diff --git a/examples/methods/a-simple.js b/examples/methods/a-simple.js new file mode 100644 index 0000000..27839b7 --- /dev/null +++ b/examples/methods/a-simple.js @@ -0,0 +1,9 @@ +({ + field: 'value', + + add(a, b) { + return a + b; + }, + + sub: (a, b) => a - b, +}); diff --git a/examples/methods/b-simple.js b/examples/methods/b-simple.js new file mode 100644 index 0000000..27839b7 --- /dev/null +++ b/examples/methods/b-simple.js @@ -0,0 +1,9 @@ +({ + field: 'value', + + add(a, b) { + return a + b; + }, + + sub: (a, b) => a - b, +}); diff --git a/metavm.d.ts b/metavm.d.ts index f73a7ec..7cd6952 100644 --- a/metavm.d.ts +++ b/metavm.d.ts @@ -42,3 +42,8 @@ export function readScript( filePath: string, options?: BaseOptions, ): Promise; + +export function readScripts( + dir: string, + options?: BaseOptions, +): Promise>; diff --git a/metavm.js b/metavm.js index 5ccbc12..edf56f6 100644 --- a/metavm.js +++ b/metavm.js @@ -167,16 +167,33 @@ class MetaScript { const createScript = (name, src, options) => new MetaScript(name, src, options); -const readScript = async (filePath, options) => { +const readScript = async (filePath, options = {}) => { const src = await fsp.readFile(filePath, 'utf8'); if (src === '') throw new SyntaxError(`File ${filePath} is empty`); - const name = options?.filename - ? options.filename - : path.basename(filePath, '.js'); - const script = new MetaScript(name, src, options); + const name = options.filename ?? path.basename(filePath, '.js'); + const script = createScript(name, src, options); return script; }; +const readDirectory = async (dir, options) => { + const files = await fsp.readdir(dir, { withFileTypes: true }); + const container = {}; + const tasks = []; + for (const file of files) { + const { name } = file; + if (file.isFile() && !name.endsWith('.js')) continue; + const location = path.join(dir, name); + const key = path.basename(name, '.js'); + const loader = file.isFile() ? readScript : readDirectory; + const task = loader(location, options).then((script) => { + container[key] = script; + }); + tasks.push(task); + } + await Promise.all(tasks); + return container; +}; + module.exports = { createContext, MetaScript, @@ -186,4 +203,5 @@ module.exports = { NODE_CONTEXT, MODULE_TYPE, readScript, + readDirectory, }; diff --git a/test/unit.js b/test/unit.js index fb1377f..b53e5f3 100644 --- a/test/unit.js +++ b/test/unit.js @@ -65,6 +65,33 @@ test('Load script', async () => { assert.strictEqual(ms.exports.add(2, 3), 5); }); +test('Load directory', async () => { + const dir = path.join(examples, 'methods'); + const metaScripts = await metavm.readDirectory(dir); + + assert.strictEqual(typeof metaScripts, 'object'); + assert.ok('a-simple' in metaScripts); + assert.ok('b-simple' in metaScripts); + + const scripts = Object.values(metaScripts); + + assert.strictEqual(scripts.length, 2); + + for (const ms of scripts) { + assert.strictEqual(typeof ms.exports, 'object'); + + const fields = Object.keys(ms); + assert.deepEqual(fields, SCRIPT_FIELDS); + + const keys = Object.keys(ms.exports); + assert.deepEqual(keys, ['field', 'add', 'sub']); + + assert.strictEqual(ms.exports.field, 'value'); + assert.strictEqual(ms.exports.sub(2, 3), -1); + assert.strictEqual(ms.exports.add(2, 3), 5); + } +}); + test('Load empty script', async () => { try { const filePath = path.join(examples, 'simple');