From 2a400f8c7e59a1f062b90354aacb889a039b66c3 Mon Sep 17 00:00:00 2001 From: Tom Wilson Date: Sat, 24 Jul 2021 11:11:33 +0000 Subject: [PATCH 1/5] feat: enabled plugin load method to support promises (#242) --- packages/core/mod.js | 9 ++++---- packages/core/mod_test.js | 28 +++++++++++++++++++++++ packages/core/scripts/test.sh | 2 +- packages/core/utils/plugin-schema.js | 2 +- packages/core/utils/plugins.js | 34 ++++++++++++++++------------ packages/core/utils/plugins_test.js | 28 ++++++++++++----------- 6 files changed, 69 insertions(+), 34 deletions(-) create mode 100644 packages/core/mod_test.js diff --git a/packages/core/mod.js b/packages/core/mod.js index f0e2528d..9701c827 100644 --- a/packages/core/mod.js +++ b/packages/core/mod.js @@ -17,16 +17,17 @@ export default async function main(config) { config = validateConfig(config); + //load methods can return promises so entire plugin svc returns a promise -tnw + const adapters = await initAdapters(prop('adapters', config)) + // TODO: validate config const services = compose( // add eventMgr to services wrapCore, assoc("middleware", propOr([], "middleware", config)), assoc("events", eventMgr()), - loadPorts, - initAdapters, - prop("adapters"), - )(config); + loadPorts + )(adapters); const app = config.app(services); diff --git a/packages/core/mod_test.js b/packages/core/mod_test.js new file mode 100644 index 00000000..e7b2faf0 --- /dev/null +++ b/packages/core/mod_test.js @@ -0,0 +1,28 @@ +import opine from 'https://x.nest.land/hyper-app-opine@1.1.2/mod.js' +import dndb from 'https://x.nest.land/hyper-adapter-dndb@0.0.3/mod.js' +import memory from 'https://x.nest.land/hyper-adapter-memory@1.2.6/mod.js' +import { superdeno } from "https://deno.land/x/superdeno@4.4.0/mod.ts"; +import { assertEquals } from 'https://deno.land/std/testing/asserts.ts' + +import core from './mod.js' + +const test = Deno.test +Deno.env.set("DENO_ENV", "test"); + +const config = { + app: opine, + adapters: [ + { port: 'data', plugins: [dndb('./data/foo.db')] }, + { port: 'cache', plugins: [memory()] } + ], + middleware: [] +} + +test('build hyper core', async () => { + const app = await core(config) + const res = await superdeno(app) + .get('/') + //console.log(res.body) + + assertEquals(res.body.name, 'hyper63') +}) \ No newline at end of file diff --git a/packages/core/scripts/test.sh b/packages/core/scripts/test.sh index 6aadb0a0..becfdf55 100755 --- a/packages/core/scripts/test.sh +++ b/packages/core/scripts/test.sh @@ -2,5 +2,5 @@ deno lint deno fmt --check -deno test --unstable --allow-env lib/storage/*_test.js utils/*_test.js lib/cache/*_test.js lib/data/*_test.js lib/crawler/*_test.js +deno test --unstable --allow-env --allow-read --allow-net lib/storage/*_test.js utils/*_test.js lib/cache/*_test.js lib/data/*_test.js lib/crawler/*_test.js mod_test.js diff --git a/packages/core/utils/plugin-schema.js b/packages/core/utils/plugin-schema.js index e95ea856..f6bf5238 100644 --- a/packages/core/utils/plugin-schema.js +++ b/packages/core/utils/plugin-schema.js @@ -21,7 +21,7 @@ export default function (plugin) { }); const instance = schema.parse(plugin); - instance.load = schema.shape.load.validate(plugin.load); + //instance.load = schema.shape.load.validate(plugin.load); instance.link = schema.shape.link.validate(plugin.link); return instance; diff --git a/packages/core/utils/plugins.js b/packages/core/utils/plugins.js index f9744a92..69e96e09 100644 --- a/packages/core/utils/plugins.js +++ b/packages/core/utils/plugins.js @@ -1,15 +1,22 @@ import { R } from "../deps.js"; const { + andThen, applyTo, filter, compose, + composeP, map, + mergeAll, is, + identity, reduce, defaultTo, fromPairs, + pluck, + pipe, reverse, + tap, } = R; /** @@ -18,11 +25,8 @@ const { * * @param {[]} plugins - a list of plugins */ -function loadAdapterConfig(plugins = []) { - return compose( - reduce((acc, plugin) => defaultTo(acc, plugin.load(acc)), {}), - filter((plugin) => is(Function, plugin.load)), - )(plugins); +async function loadAdapterConfig(plugins = []) { + return await pipe(...pluck('load', plugins))({}) } /** @@ -57,12 +61,10 @@ function linkPlugins(plugins, adapterConfig) { )(plugins); } -function initAdapter(portAdapter) { +async function initAdapter(portAdapter) { const { plugins } = portAdapter; - return compose( - (adapterConfig) => linkPlugins(plugins, adapterConfig), - loadAdapterConfig, - )(plugins || []); + const env = await loadAdapterConfig(plugins || []) + return linkPlugins(plugins, env) } /** @@ -71,9 +73,11 @@ function initAdapter(portAdapter) { * * @param {[]} adapters - a list of port nodes from a hyper63 config */ -export default function initAdapters(adapters) { - return compose( - fromPairs, - map((adapterNode) => [adapterNode.port, initAdapter(adapterNode)]), - )(adapters); +export default async function initAdapters(adapters) { + const svcs = await Promise.all( + map(async (adapterNode) => ({ + [adapterNode.port]: await initAdapter(adapterNode) + }), adapters), + ); + return mergeAll(svcs) } diff --git a/packages/core/utils/plugins_test.js b/packages/core/utils/plugins_test.js index e63cad3d..61ee8e14 100644 --- a/packages/core/utils/plugins_test.js +++ b/packages/core/utils/plugins_test.js @@ -4,28 +4,30 @@ import { assertEquals, assertObjectMatch } from "../dev_deps.js"; const test = Deno.test; -test("sucessfully compose plugins", () => { - const plugin1 = validate({ - id: "plugin1", - port: "default", - load: (env) => ({ ...env, hello: "world" }), - link: (env) => () => ({ hello: () => env.hello }), - }); - - const plugin2 = (config) => +test("sucessfully compose plugins", async () => { + const plugin1 = validate({ - id: "plugin2", + id: "plugin1", port: "default", - load: (env) => ({ ...env, ...config }), - link: (env) => (plugin) => ({ ...plugin, beep: () => env }), + load: (env) => ({ ...env, hello: "world" }), + link: (env) => () => ({ hello: () => env.hello }), }); + const plugin2 = (config) => + validate({ + id: "plugin2", + port: "default", + load: (env) => ({ ...env, ...config }), + link: (env) => (plugin) => ({ ...plugin, beep: () => env }), + }); + const config = { adapters: [ { port: "default", plugins: [plugin2({ foo: "bar" }), plugin1] }, ], }; - const adapters = initAdapters(config.adapters); + const adapters = await initAdapters(config.adapters); + //console.log(adapters) assertEquals(adapters.default.hello(), "world"); assertObjectMatch(adapters.default.beep(), { foo: "bar", hello: "world" }); From 4559614f81740f93d46a3a5f8d54e52f0db5f2f2 Mon Sep 17 00:00:00 2001 From: Tom Wilson Date: Sat, 24 Jul 2021 15:52:33 +0000 Subject: [PATCH 2/5] feat (core): allow load method on adapters to be a promise --- .github/workflows/tests-core.yml | 2 +- packages/core/mod.js | 4 ++-- packages/core/mod_test.js | 30 ++++++++++++++--------------- packages/core/utils/plugins.js | 17 +++++----------- packages/core/utils/plugins_test.js | 23 +++++++++++----------- 5 files changed, 34 insertions(+), 42 deletions(-) diff --git a/.github/workflows/tests-core.yml b/.github/workflows/tests-core.yml index 0e4143fd..938b4a2c 100644 --- a/.github/workflows/tests-core.yml +++ b/.github/workflows/tests-core.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - deno: [1.11.x] + deno: [1.12.x] steps: - uses: actions/checkout@v2 - name: Use Deno ${{ matrix.deno-version }} diff --git a/packages/core/mod.js b/packages/core/mod.js index 9701c827..b1b6494d 100644 --- a/packages/core/mod.js +++ b/packages/core/mod.js @@ -18,7 +18,7 @@ export default async function main(config) { config = validateConfig(config); //load methods can return promises so entire plugin svc returns a promise -tnw - const adapters = await initAdapters(prop('adapters', config)) + const adapters = await initAdapters(prop("adapters", config)); // TODO: validate config const services = compose( @@ -26,7 +26,7 @@ export default async function main(config) { wrapCore, assoc("middleware", propOr([], "middleware", config)), assoc("events", eventMgr()), - loadPorts + loadPorts, )(adapters); const app = config.app(services); diff --git a/packages/core/mod_test.js b/packages/core/mod_test.js index e7b2faf0..080817dc 100644 --- a/packages/core/mod_test.js +++ b/packages/core/mod_test.js @@ -1,28 +1,28 @@ -import opine from 'https://x.nest.land/hyper-app-opine@1.1.2/mod.js' -import dndb from 'https://x.nest.land/hyper-adapter-dndb@0.0.3/mod.js' -import memory from 'https://x.nest.land/hyper-adapter-memory@1.2.6/mod.js' +import opine from "https://x.nest.land/hyper-app-opine@1.1.2/mod.js"; +import dndb from "https://x.nest.land/hyper-adapter-dndb@0.0.3/mod.js"; +import memory from "https://x.nest.land/hyper-adapter-memory@1.2.6/mod.js"; import { superdeno } from "https://deno.land/x/superdeno@4.4.0/mod.ts"; -import { assertEquals } from 'https://deno.land/std/testing/asserts.ts' +import { assertEquals } from "https://deno.land/std/testing/asserts.ts"; -import core from './mod.js' +import core from "./mod.js"; -const test = Deno.test +const test = Deno.test; Deno.env.set("DENO_ENV", "test"); const config = { app: opine, adapters: [ - { port: 'data', plugins: [dndb('./data/foo.db')] }, - { port: 'cache', plugins: [memory()] } + { port: "data", plugins: [dndb("./data/foo.db")] }, + { port: "cache", plugins: [memory()] }, ], - middleware: [] -} + middleware: [], +}; -test('build hyper core', async () => { - const app = await core(config) +test("build hyper core", async () => { + const app = await core(config); const res = await superdeno(app) - .get('/') + .get("/"); //console.log(res.body) - assertEquals(res.body.name, 'hyper63') -}) \ No newline at end of file + assertEquals(res.body.name, "hyper63"); +}); diff --git a/packages/core/utils/plugins.js b/packages/core/utils/plugins.js index 69e96e09..cd1cf92b 100644 --- a/packages/core/utils/plugins.js +++ b/packages/core/utils/plugins.js @@ -1,22 +1,15 @@ import { R } from "../deps.js"; const { - andThen, applyTo, filter, compose, - composeP, map, mergeAll, is, - identity, - reduce, - defaultTo, - fromPairs, pluck, pipe, reverse, - tap, } = R; /** @@ -26,7 +19,7 @@ const { * @param {[]} plugins - a list of plugins */ async function loadAdapterConfig(plugins = []) { - return await pipe(...pluck('load', plugins))({}) + return await pipe(...filter(is(Function), pluck("load", plugins)))({}); } /** @@ -63,8 +56,8 @@ function linkPlugins(plugins, adapterConfig) { async function initAdapter(portAdapter) { const { plugins } = portAdapter; - const env = await loadAdapterConfig(plugins || []) - return linkPlugins(plugins, env) + const env = await loadAdapterConfig(plugins || []); + return linkPlugins(plugins, env); } /** @@ -76,8 +69,8 @@ async function initAdapter(portAdapter) { export default async function initAdapters(adapters) { const svcs = await Promise.all( map(async (adapterNode) => ({ - [adapterNode.port]: await initAdapter(adapterNode) + [adapterNode.port]: await initAdapter(adapterNode), }), adapters), ); - return mergeAll(svcs) + return mergeAll(svcs); } diff --git a/packages/core/utils/plugins_test.js b/packages/core/utils/plugins_test.js index 61ee8e14..91d32d31 100644 --- a/packages/core/utils/plugins_test.js +++ b/packages/core/utils/plugins_test.js @@ -5,22 +5,21 @@ import { assertEquals, assertObjectMatch } from "../dev_deps.js"; const test = Deno.test; test("sucessfully compose plugins", async () => { - const plugin1 = + const plugin1 = validate({ + id: "plugin1", + port: "default", + load: (env) => ({ ...env, hello: "world" }), + link: (env) => () => ({ hello: () => env.hello }), + }); + + const plugin2 = (config) => validate({ - id: "plugin1", + id: "plugin2", port: "default", - load: (env) => ({ ...env, hello: "world" }), - link: (env) => () => ({ hello: () => env.hello }), + load: (env) => ({ ...env, ...config }), + link: (env) => (plugin) => ({ ...plugin, beep: () => env }), }); - const plugin2 = (config) => - validate({ - id: "plugin2", - port: "default", - load: (env) => ({ ...env, ...config }), - link: (env) => (plugin) => ({ ...plugin, beep: () => env }), - }); - const config = { adapters: [ { port: "default", plugins: [plugin2({ foo: "bar" }), plugin1] }, From 4f4686bfd149dcc8fa6ca83ae538791766cc10d6 Mon Sep 17 00:00:00 2001 From: Tom Wilson Date: Sat, 24 Jul 2021 15:54:24 +0000 Subject: [PATCH 3/5] feat (core): allow load method on adapters to be a promise --- packages/core/utils/plugins_test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/utils/plugins_test.js b/packages/core/utils/plugins_test.js index 91d32d31..5cf528a0 100644 --- a/packages/core/utils/plugins_test.js +++ b/packages/core/utils/plugins_test.js @@ -26,7 +26,6 @@ test("sucessfully compose plugins", async () => { ], }; const adapters = await initAdapters(config.adapters); - //console.log(adapters) assertEquals(adapters.default.hello(), "world"); assertObjectMatch(adapters.default.beep(), { foo: "bar", hello: "world" }); From 0ee397ef5e045974eb4918eaed3b012cc720d94c Mon Sep 17 00:00:00 2001 From: Tom Wilson Date: Sat, 24 Jul 2021 15:56:15 +0000 Subject: [PATCH 4/5] feat (core): allow load method on adapters to be a promise --- .github/workflows/tests-core.yml | 3 +++ packages/core/README.md | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/tests-core.yml b/.github/workflows/tests-core.yml index 938b4a2c..98aa032a 100644 --- a/.github/workflows/tests-core.yml +++ b/.github/workflows/tests-core.yml @@ -2,6 +2,9 @@ name: test core on: push: tags-ignore: '*' + branches: + - main + - '**' paths: - "packages/core/**" jobs: diff --git a/packages/core/README.md b/packages/core/README.md index 1e281a20..a03e881f 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -10,3 +10,7 @@ The core package validates the config schema and plugin schemas ``` ./scripts/test.sh ``` + +## License + +Apache 2.0 \ No newline at end of file From d1ec247716c4bde523d0eaa58fd962fa803acdf8 Mon Sep 17 00:00:00 2001 From: Tom Wilson Date: Sat, 24 Jul 2021 16:31:39 +0000 Subject: [PATCH 5/5] feat: allow load to be a promise (#242) --- packages/core/README.md | 2 +- packages/core/utils/plugins.js | 4 ++-- packages/core/utils/plugins_test.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/README.md b/packages/core/README.md index a03e881f..e70622cb 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -13,4 +13,4 @@ The core package validates the config schema and plugin schemas ## License -Apache 2.0 \ No newline at end of file +Apache 2.0 diff --git a/packages/core/utils/plugins.js b/packages/core/utils/plugins.js index cd1cf92b..6b02ce52 100644 --- a/packages/core/utils/plugins.js +++ b/packages/core/utils/plugins.js @@ -8,7 +8,7 @@ const { mergeAll, is, pluck, - pipe, + pipeP, reverse, } = R; @@ -19,7 +19,7 @@ const { * @param {[]} plugins - a list of plugins */ async function loadAdapterConfig(plugins = []) { - return await pipe(...filter(is(Function), pluck("load", plugins)))({}); + return await pipeP(...filter(is(Function), pluck("load", plugins)))({}); } /** diff --git a/packages/core/utils/plugins_test.js b/packages/core/utils/plugins_test.js index 5cf528a0..c48d815f 100644 --- a/packages/core/utils/plugins_test.js +++ b/packages/core/utils/plugins_test.js @@ -8,7 +8,7 @@ test("sucessfully compose plugins", async () => { const plugin1 = validate({ id: "plugin1", port: "default", - load: (env) => ({ ...env, hello: "world" }), + load: (env) => Promise.resolve({ ...env, hello: "world" }), link: (env) => () => ({ hello: () => env.hello }), }); @@ -16,7 +16,7 @@ test("sucessfully compose plugins", async () => { validate({ id: "plugin2", port: "default", - load: (env) => ({ ...env, ...config }), + load: (env) => Promise.resolve({ ...env, ...config }), link: (env) => (plugin) => ({ ...plugin, beep: () => env }), });