Skip to content

Commit 179fa1a

Browse files
feat: added $map suffix for object arrays
1 parent 72cc945 commit 179fa1a

File tree

11 files changed

+160
-88
lines changed

11 files changed

+160
-88
lines changed

examples/basic/_roxi/roxi.config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ plugins:
2626
- spassr:
2727
port: 3400
2828
ssr: true
29-
- postcss:
3029
- mdsvex:
30+
- postcss:
3131
- vite:
3232
- debugger:

lib/app.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
/// <reference path="../typedef.js" />
22

3-
4-
/** @ts-ignore */
5-
const esmRequire = require("esm")(module, {}/*, options*/)
6-
const { deepAssign, log } = require('./utils')
3+
const { deepAssign, log, keysAsFunctionsRecursive } = require('./utils')
74

85

96
/** @type {AppEvent[]} */
@@ -42,20 +39,25 @@ const App = class {
4239
async run(events = this.events) {
4340
try {
4441
for (const event of events) {
42+
console.log('event', event)
4543
this.state.event = event
4644
await runPlugins(event, this)
4745
}
4846
} catch (err) { this.errorHandler(err) }
4947
}
5048
}
5149

50+
//todo move this somewhere else?
51+
const objToArray = {
52+
hooks: [{ event: 'bundle', action: app => keysAsFunctionsRecursive(app) }]
53+
}
5254

5355
/**
5456
* @param {AppEvent} event
5557
* @param {RoxiApp} app
5658
*/
5759
async function runPlugins(event, app) {
58-
const plugins = [...app.config.roxi.plugins]
60+
const plugins = [objToArray, ...app.config.roxi.plugins]
5961
for (const plugin of plugins) {
6062
const hooks = plugin.hooks.filter(hookCondition(app, plugin.params, { event }))
6163
for (const hook of hooks)

lib/plugins/mdsvex/index.js

+11-16
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,31 @@
11
/// <reference path="../../../typedef.js" />
22

33
import { mdsvex } from 'mdsvex'
4-
const extension = ['.md', '.svx', '.svelte']
54

65
/** @type {RoxiPlugin} */
76
module.exports.default = {
87
name: 'mdsvex',
98
hooks: [
109
{
1110
event: 'start',
12-
action: app => app.config.mdsvex = {}, //provide an mdsvex object for developers to modify
13-
},
14-
{
15-
event: 'before:bundle',
1611
action: (app, params) => {
12+
const extension = params.extension || .md
13+
14+
//provide an mdsvex object for developers to modify
15+
const conf = { extension, ...params }
16+
17+
1718
app.merge({
1819
config: {
20+
mdsvex: conf,
1921
svelte: {
20-
preprocess: [
21-
mdsvex({
22-
extension: '.md',
23-
...app.config.mdsvex,
24-
...params
25-
})
26-
],
27-
extensions: params.extension
28-
|| app.config.mdsvex.extension
29-
|| extension
22+
preprocess: { mdsvex: conf },
23+
preprocess$map: { mdsvex },
24+
extensions: [extension]
3025
}
3126
}
3227
})
3328
}
34-
}
29+
},
3530
]
3631
}

lib/plugins/postcss/index.js

+20-29
Original file line numberDiff line numberDiff line change
@@ -8,43 +8,34 @@ export default {
88
event: 'start',
99
action: async (app, params) => {
1010
const postcssImport = (await import('postcss-import')).default
11-
app.merge({
12-
config: {
13-
postcss: {
14-
pluginsMap: { postcssImport },
15-
plugins: {
16-
postcssImport: {}
17-
}
18-
}
19-
}
20-
})
21-
}
22-
},
23-
{
24-
event: 'before:bundle',
25-
action: async (app, params) => {
26-
const { keysAsFunctions } = (await import('../../utils'))
27-
const { plugins, pluginsMap } = app.config.postcss
2811
const postcss = (await import('rollup-plugin-postcss')).default
29-
const autoPreprocess = (await import('svelte-preprocess')).default
30-
app.config.postcss.plugins = await keysAsFunctions(plugins, pluginsMap)
31-
delete app.config.postcss.pluginsMap
12+
13+
const postcssConfig = {
14+
plugins$map: { postcssImport },
15+
plugins: {
16+
postcssImport: {},
17+
}
18+
}
3219

3320
app.merge({
3421
config: {
22+
// add postcss to the config
23+
postcss: postcssConfig,
24+
25+
// rollup needs access
3526
rollup: {
36-
pluginsMap: { postcss },
37-
plugins: {
38-
postcss: app.config.postcss
39-
}
27+
plugins: { postcss: postcssConfig },
28+
plugins$map: { postcss }
4029
},
30+
31+
// and so does svelte preprocess
4132
svelte: {
42-
preprocess: [
43-
autoPreprocess({
44-
postcss: app.config.postcss,
33+
preprocess: {
34+
autoPreprocess: {
35+
_postcss: postcssConfig,
4536
defaults: { style: 'postcss' }
46-
})
47-
]
37+
}
38+
}
4839
}
4940
}
5041
})

lib/plugins/preprocess/index.js

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1+
import autoPreprocess from 'svelte-preprocess'
2+
13
export default {
24
hooks: [
35
{
4-
condition: 'start',
5-
action: app => app.config.autoPreprocess = {}
6-
},
7-
{
8-
condition: 'before:bundle',
9-
action: async (app, params) => {
10-
const autoPreprocess = (await import('svelte-preprocess')).default
11-
6+
event: 'start',
7+
action: app => {
128
app.merge({
139
config: {
1410
svelte: {
15-
preprocess: [
16-
autoPreprocess(app.config.autoPreprocess)
17-
]
11+
preprocess: { autoPreprocess: {} },
12+
preprocess$map: { autoPreprocess }
1813
}
1914
}
2015
})

lib/plugins/rollup/index.js

-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const rollup = require('rollup')
22
import rollupTemplate from './rollup.template'
3-
import rollupCompile from './rollup.compile'
43

54
export default {
65
name: 'rollup',
@@ -9,14 +8,6 @@ export default {
98
event: 'start',
109
action: rollupTemplate
1110
},
12-
{
13-
event: 'bundle',
14-
condition: app =>
15-
app.state.production
16-
|| app.config.rollup.compileConfig
17-
|| app.config.rollup.writeConfig,
18-
action: rollupCompile
19-
},
2011
{
2112
event: 'bundle',
2213
condition: app => app.state.production || app.config.rollup.writeConfig,

lib/plugins/rollup/rollup.compile.js

-11
This file was deleted.

lib/plugins/rollup/rollup.template.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = function rollup(app, params) {
2424
sourcemap: true,
2525
format: 'esm', dir: buildDir
2626
},
27-
pluginsMap: { svelte, resolve, commonjs, terser, hmr, livereload },
27+
plugins$map: { svelte, resolve, commonjs, terser, hmr, livereload },
2828
plugins: {
2929
terser: production && {},
3030
svelte: app.config.svelte,

lib/plugins/svelte/index.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ export default {
33
{
44
event: 'start',
55
action: async (app, params, ctx) => {
6-
app.config.svelte = {
7-
extensions: []
8-
}
6+
app.merge({
7+
config: {
8+
svelte: {
9+
extensions: ['.svelte'],
10+
preprocess: {},
11+
preprocess$map: {}
12+
}
13+
}
14+
})
915
}
1016
}
1117
]

lib/utils/index.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,47 @@ function deepAssign(target, ...sources) {
4242
return target
4343
}
4444

45-
async function keysAsFunctions(obj, map) {
45+
async function keysAsFunctionsRecursive(obj, suffix = '$map') {
46+
const maps = []
47+
48+
// process all descendants' maps first
49+
const children = Object.entries(obj).map(([key, value]) => {
50+
if (isObject(value)) {
51+
if (key.endsWith(suffix))
52+
maps.push({ key, value })
53+
else
54+
return keysAsFunctionsRecursive(value, suffix)
55+
}
56+
})
57+
await Promise.all(children)
58+
59+
// process own maps
60+
const ownMaps = await Promise.all(maps.map(async ({ key, value }) => {
61+
delete obj[key]
62+
key = key.substr(0, key.length - suffix.length)
63+
const result = await keysAsFunctions(obj[key], value, key)
64+
return {
65+
key,
66+
result
67+
}
68+
}))
69+
ownMaps.forEach(thing => obj[thing.key] = thing.result)
70+
71+
return obj
72+
}
73+
74+
/**
75+
* converts objects to arrays
76+
* each field value is parsed through a function from the map which corresponds to the field's key
77+
* map = { aPlugin: val => val + 'bar' }
78+
* obj = { aPlugin: 'foo', _n: 123 }
79+
* keysAsFunctions(obj, map) // ['foobar', 123]
80+
* @param {object} obj
81+
* @param {Object.<string, function>} map
82+
*/
83+
async function keysAsFunctions(obj, map, name) {
84+
if (!isObject(obj))
85+
throw new Error(`expected an object for "${name}", but got ${JSON.stringify(obj, null, 2)}`)
4686
const { log } = require('./log')
4787
const promises = Object.entries(obj).map(([key, value]) => {
4888
const isFn = !key.startsWith('_')
@@ -51,7 +91,9 @@ async function keysAsFunctions(obj, map) {
5191

5292
if (!fn && isFn) log.info(
5393
`there's no map method named ${key}. Available methods: ${Object.keys(map)}.` +
54-
`\nRenaming to "_${key}" will hide this message.`
94+
`\nRenaming to "_${key}" will hide this message.` +
95+
`\nvalue: ${JSON.stringify(value, null, 2)}` +
96+
`\nobj: ${JSON.stringify(obj, null, 2)}`
5597
)
5698
return fn && value ? fn(value) : value
5799
})
@@ -63,5 +105,6 @@ module.exports = {
63105
isObject,
64106
deepAssign,
65107
keysAsFunctions,
108+
keysAsFunctionsRecursive,
66109
...require('./log')
67110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
const { keysAsFunctionsRecursive } = require("..");
2+
3+
const fn = async val => ({ ...val, touched: true })
4+
const getBaseObj = () => ({
5+
aPlugin: {
6+
string: 'abc',
7+
number: 123,
8+
obj: { foo: 'bar' },
9+
target$map: { fn },
10+
target: {
11+
fn: { isTarget: true, touched: false }
12+
}
13+
}
14+
})
15+
16+
it('converts objects to arrays', async () => {
17+
const config = getBaseObj()
18+
const result = await keysAsFunctionsRecursive(config)
19+
20+
expect(result).toEqual({
21+
aPlugin: {
22+
string: 'abc',
23+
number: 123,
24+
obj: { foo: 'bar' },
25+
target: [
26+
{
27+
"isTarget": true,
28+
"touched": true,
29+
},
30+
]
31+
}
32+
})
33+
})
34+
35+
it('processes children first', async () => {
36+
const config = getBaseObj()
37+
config.aPlugin.target.fn.child = { fn: { isTarget: true, touched: false } }
38+
config.aPlugin.target.fn.child$map = { fn }
39+
40+
41+
const result = await keysAsFunctionsRecursive(config)
42+
43+
expect(result).toEqual({
44+
aPlugin: {
45+
string: 'abc',
46+
number: 123,
47+
obj: { foo: 'bar' },
48+
target: [
49+
{
50+
isTarget: true,
51+
touched: true,
52+
child: [{
53+
isTarget: true,
54+
touched: true,
55+
}]
56+
},
57+
]
58+
}
59+
})
60+
})

0 commit comments

Comments
 (0)