From 179fa1abb3592209282ee4edb2eacbe36f9e3c02 Mon Sep 17 00:00:00 2001 From: Jakob Rosenberg Date: Sat, 17 Oct 2020 17:38:44 +0200 Subject: [PATCH] feat: added $map suffix for object arrays --- examples/basic/_roxi/roxi.config.yaml | 2 +- lib/app.js | 12 ++-- lib/plugins/mdsvex/index.js | 27 ++++----- lib/plugins/postcss/index.js | 49 +++++++-------- lib/plugins/preprocess/index.js | 17 ++---- lib/plugins/rollup/index.js | 9 --- lib/plugins/rollup/rollup.compile.js | 11 ---- lib/plugins/rollup/rollup.template.js | 2 +- lib/plugins/svelte/index.js | 12 +++- lib/utils/index.js | 47 ++++++++++++++- .../tests/keysAsFunctionsRecursive.spec.js | 60 +++++++++++++++++++ 11 files changed, 160 insertions(+), 88 deletions(-) delete mode 100644 lib/plugins/rollup/rollup.compile.js create mode 100644 lib/utils/tests/keysAsFunctionsRecursive.spec.js diff --git a/examples/basic/_roxi/roxi.config.yaml b/examples/basic/_roxi/roxi.config.yaml index d75809a..a66e213 100644 --- a/examples/basic/_roxi/roxi.config.yaml +++ b/examples/basic/_roxi/roxi.config.yaml @@ -26,7 +26,7 @@ plugins: - spassr: port: 3400 ssr: true - - postcss: - mdsvex: + - postcss: - vite: - debugger: diff --git a/lib/app.js b/lib/app.js index 485e6be..0c4578e 100644 --- a/lib/app.js +++ b/lib/app.js @@ -1,9 +1,6 @@ /// - -/** @ts-ignore */ -const esmRequire = require("esm")(module, {}/*, options*/) -const { deepAssign, log } = require('./utils') +const { deepAssign, log, keysAsFunctionsRecursive } = require('./utils') /** @type {AppEvent[]} */ @@ -42,6 +39,7 @@ const App = class { async run(events = this.events) { try { for (const event of events) { + console.log('event', event) this.state.event = event await runPlugins(event, this) } @@ -49,13 +47,17 @@ const App = class { } } +//todo move this somewhere else? +const objToArray = { + hooks: [{ event: 'bundle', action: app => keysAsFunctionsRecursive(app) }] +} /** * @param {AppEvent} event * @param {RoxiApp} app */ async function runPlugins(event, app) { - const plugins = [...app.config.roxi.plugins] + const plugins = [objToArray, ...app.config.roxi.plugins] for (const plugin of plugins) { const hooks = plugin.hooks.filter(hookCondition(app, plugin.params, { event })) for (const hook of hooks) diff --git a/lib/plugins/mdsvex/index.js b/lib/plugins/mdsvex/index.js index 68b5a7b..0d78cfd 100644 --- a/lib/plugins/mdsvex/index.js +++ b/lib/plugins/mdsvex/index.js @@ -1,7 +1,6 @@ /// import { mdsvex } from 'mdsvex' -const extension = ['.md', '.svx', '.svelte'] /** @type {RoxiPlugin} */ module.exports.default = { @@ -9,28 +8,24 @@ module.exports.default = { hooks: [ { event: 'start', - action: app => app.config.mdsvex = {}, //provide an mdsvex object for developers to modify - }, - { - event: 'before:bundle', action: (app, params) => { + const extension = params.extension || .md + + //provide an mdsvex object for developers to modify + const conf = { extension, ...params } + + app.merge({ config: { + mdsvex: conf, svelte: { - preprocess: [ - mdsvex({ - extension: '.md', - ...app.config.mdsvex, - ...params - }) - ], - extensions: params.extension - || app.config.mdsvex.extension - || extension + preprocess: { mdsvex: conf }, + preprocess$map: { mdsvex }, + extensions: [extension] } } }) } - } + }, ] } diff --git a/lib/plugins/postcss/index.js b/lib/plugins/postcss/index.js index e9770c3..6192e7f 100644 --- a/lib/plugins/postcss/index.js +++ b/lib/plugins/postcss/index.js @@ -8,43 +8,34 @@ export default { event: 'start', action: async (app, params) => { const postcssImport = (await import('postcss-import')).default - app.merge({ - config: { - postcss: { - pluginsMap: { postcssImport }, - plugins: { - postcssImport: {} - } - } - } - }) - } - }, - { - event: 'before:bundle', - action: async (app, params) => { - const { keysAsFunctions } = (await import('../../utils')) - const { plugins, pluginsMap } = app.config.postcss const postcss = (await import('rollup-plugin-postcss')).default - const autoPreprocess = (await import('svelte-preprocess')).default - app.config.postcss.plugins = await keysAsFunctions(plugins, pluginsMap) - delete app.config.postcss.pluginsMap + + const postcssConfig = { + plugins$map: { postcssImport }, + plugins: { + postcssImport: {}, + } + } app.merge({ config: { + // add postcss to the config + postcss: postcssConfig, + + // rollup needs access rollup: { - pluginsMap: { postcss }, - plugins: { - postcss: app.config.postcss - } + plugins: { postcss: postcssConfig }, + plugins$map: { postcss } }, + + // and so does svelte preprocess svelte: { - preprocess: [ - autoPreprocess({ - postcss: app.config.postcss, + preprocess: { + autoPreprocess: { + _postcss: postcssConfig, defaults: { style: 'postcss' } - }) - ] + } + } } } }) diff --git a/lib/plugins/preprocess/index.js b/lib/plugins/preprocess/index.js index 70be2cc..8ca7caf 100644 --- a/lib/plugins/preprocess/index.js +++ b/lib/plugins/preprocess/index.js @@ -1,20 +1,15 @@ +import autoPreprocess from 'svelte-preprocess' + export default { hooks: [ { - condition: 'start', - action: app => app.config.autoPreprocess = {} - }, - { - condition: 'before:bundle', - action: async (app, params) => { - const autoPreprocess = (await import('svelte-preprocess')).default - + event: 'start', + action: app => { app.merge({ config: { svelte: { - preprocess: [ - autoPreprocess(app.config.autoPreprocess) - ] + preprocess: { autoPreprocess: {} }, + preprocess$map: { autoPreprocess } } } }) diff --git a/lib/plugins/rollup/index.js b/lib/plugins/rollup/index.js index 4d235e0..f87ce61 100644 --- a/lib/plugins/rollup/index.js +++ b/lib/plugins/rollup/index.js @@ -1,6 +1,5 @@ const rollup = require('rollup') import rollupTemplate from './rollup.template' -import rollupCompile from './rollup.compile' export default { name: 'rollup', @@ -9,14 +8,6 @@ export default { event: 'start', action: rollupTemplate }, - { - event: 'bundle', - condition: app => - app.state.production - || app.config.rollup.compileConfig - || app.config.rollup.writeConfig, - action: rollupCompile - }, { event: 'bundle', condition: app => app.state.production || app.config.rollup.writeConfig, diff --git a/lib/plugins/rollup/rollup.compile.js b/lib/plugins/rollup/rollup.compile.js deleted file mode 100644 index 6348509..0000000 --- a/lib/plugins/rollup/rollup.compile.js +++ /dev/null @@ -1,11 +0,0 @@ -/// - -const { keysAsFunctions } = require('../../utils') - -/**@param {RoxiApp} app */ -export default async function rollupConfig(app, params, ctx) { - const { plugins, pluginsMap } = app.config.rollup - delete app.config.rollup.pluginsMap - app.config.rollup.plugins.svelte = app.config.svelte - app.config.rollup.plugins = await keysAsFunctions(plugins, pluginsMap) -} diff --git a/lib/plugins/rollup/rollup.template.js b/lib/plugins/rollup/rollup.template.js index 3e7c32f..08b485c 100644 --- a/lib/plugins/rollup/rollup.template.js +++ b/lib/plugins/rollup/rollup.template.js @@ -24,7 +24,7 @@ module.exports = function rollup(app, params) { sourcemap: true, format: 'esm', dir: buildDir }, - pluginsMap: { svelte, resolve, commonjs, terser, hmr, livereload }, + plugins$map: { svelte, resolve, commonjs, terser, hmr, livereload }, plugins: { terser: production && {}, svelte: app.config.svelte, diff --git a/lib/plugins/svelte/index.js b/lib/plugins/svelte/index.js index 316cdf3..6c4ef25 100644 --- a/lib/plugins/svelte/index.js +++ b/lib/plugins/svelte/index.js @@ -3,9 +3,15 @@ export default { { event: 'start', action: async (app, params, ctx) => { - app.config.svelte = { - extensions: [] - } + app.merge({ + config: { + svelte: { + extensions: ['.svelte'], + preprocess: {}, + preprocess$map: {} + } + } + }) } } ] diff --git a/lib/utils/index.js b/lib/utils/index.js index b272760..419c215 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -42,7 +42,47 @@ function deepAssign(target, ...sources) { return target } -async function keysAsFunctions(obj, map) { +async function keysAsFunctionsRecursive(obj, suffix = '$map') { + const maps = [] + + // process all descendants' maps first + const children = Object.entries(obj).map(([key, value]) => { + if (isObject(value)) { + if (key.endsWith(suffix)) + maps.push({ key, value }) + else + return keysAsFunctionsRecursive(value, suffix) + } + }) + await Promise.all(children) + + // process own maps + const ownMaps = await Promise.all(maps.map(async ({ key, value }) => { + delete obj[key] + key = key.substr(0, key.length - suffix.length) + const result = await keysAsFunctions(obj[key], value, key) + return { + key, + result + } + })) + ownMaps.forEach(thing => obj[thing.key] = thing.result) + + return obj +} + +/** + * converts objects to arrays + * each field value is parsed through a function from the map which corresponds to the field's key + * map = { aPlugin: val => val + 'bar' } + * obj = { aPlugin: 'foo', _n: 123 } + * keysAsFunctions(obj, map) // ['foobar', 123] + * @param {object} obj + * @param {Object.} map + */ +async function keysAsFunctions(obj, map, name) { + if (!isObject(obj)) + throw new Error(`expected an object for "${name}", but got ${JSON.stringify(obj, null, 2)}`) const { log } = require('./log') const promises = Object.entries(obj).map(([key, value]) => { const isFn = !key.startsWith('_') @@ -51,7 +91,9 @@ async function keysAsFunctions(obj, map) { if (!fn && isFn) log.info( `there's no map method named ${key}. Available methods: ${Object.keys(map)}.` + - `\nRenaming to "_${key}" will hide this message.` + `\nRenaming to "_${key}" will hide this message.` + + `\nvalue: ${JSON.stringify(value, null, 2)}` + + `\nobj: ${JSON.stringify(obj, null, 2)}` ) return fn && value ? fn(value) : value }) @@ -63,5 +105,6 @@ module.exports = { isObject, deepAssign, keysAsFunctions, + keysAsFunctionsRecursive, ...require('./log') } diff --git a/lib/utils/tests/keysAsFunctionsRecursive.spec.js b/lib/utils/tests/keysAsFunctionsRecursive.spec.js new file mode 100644 index 0000000..580ceb7 --- /dev/null +++ b/lib/utils/tests/keysAsFunctionsRecursive.spec.js @@ -0,0 +1,60 @@ +const { keysAsFunctionsRecursive } = require(".."); + +const fn = async val => ({ ...val, touched: true }) +const getBaseObj = () => ({ + aPlugin: { + string: 'abc', + number: 123, + obj: { foo: 'bar' }, + target$map: { fn }, + target: { + fn: { isTarget: true, touched: false } + } + } +}) + +it('converts objects to arrays', async () => { + const config = getBaseObj() + const result = await keysAsFunctionsRecursive(config) + + expect(result).toEqual({ + aPlugin: { + string: 'abc', + number: 123, + obj: { foo: 'bar' }, + target: [ + { + "isTarget": true, + "touched": true, + }, + ] + } + }) +}) + +it('processes children first', async () => { + const config = getBaseObj() + config.aPlugin.target.fn.child = { fn: { isTarget: true, touched: false } } + config.aPlugin.target.fn.child$map = { fn } + + + const result = await keysAsFunctionsRecursive(config) + + expect(result).toEqual({ + aPlugin: { + string: 'abc', + number: 123, + obj: { foo: 'bar' }, + target: [ + { + isTarget: true, + touched: true, + child: [{ + isTarget: true, + touched: true, + }] + }, + ] + } + }) +})