From 7617fd4ed3ff92937c87d11b8b2acebf8affaaad Mon Sep 17 00:00:00 2001 From: Shigma Date: Wed, 21 Feb 2024 21:27:37 +0800 Subject: [PATCH] feat(loader): handle plugin update --- packages/cordis/src/worker/index.ts | 3 +- packages/hmr/src/index.ts | 2 +- packages/loader/src/shared.ts | 8 ++++-- packages/loader/tests/index.spec.ts | 44 ++++++++++++++++++++++++----- packages/loader/tests/utils.ts | 6 +++- 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/packages/cordis/src/worker/index.ts b/packages/cordis/src/worker/index.ts index 9c1d345..fdb7cb5 100644 --- a/packages/cordis/src/worker/index.ts +++ b/packages/cordis/src/worker/index.ts @@ -20,13 +20,12 @@ export interface Options extends Loader.Options { export async function start(options: Options) { const ctx = new Context() ctx.plugin(Loader, options) + await ctx.loader.init(process.env.CORDIS_LOADER_ENTRY) if (process.execArgv.includes('--expose-internals')) { const { internal } = await import('./internal.js') ctx.loader.internal = internal } - await ctx.loader.init(process.env.CORDIS_LOADER_ENTRY) if (options.logger) ctx.plugin(logger, options.logger) if (options.daemon) ctx.plugin(daemon, options.daemon) - await ctx.loader.readConfig() await ctx.start() } diff --git a/packages/hmr/src/index.ts b/packages/hmr/src/index.ts index 24eca1c..a8ef749 100644 --- a/packages/hmr/src/index.ts +++ b/packages/hmr/src/index.ts @@ -109,7 +109,7 @@ class Watcher extends Service { this.ctx.loader.exit() } else { const config = await loader.readConfig() - this.ctx.root.state.update(config) + loader.entry.update(config) this.ctx.emit('config') } } else { diff --git a/packages/loader/src/shared.ts b/packages/loader/src/shared.ts index b51796c..63654d4 100644 --- a/packages/loader/src/shared.ts +++ b/packages/loader/src/shared.ts @@ -74,6 +74,7 @@ export abstract class Loader extends env: process.env, } + public entry!: ForkScope public suspend = false public writable = false public mimeType!: string @@ -247,7 +248,8 @@ export abstract class Loader extends } async start() { - this.app.plugin(group, this.config) + await this.readConfig() + this.entry = this.app.plugin(group, this.config) this.app.on('dispose', () => { this.exit() @@ -263,7 +265,9 @@ export abstract class Loader extends if (fork[kUpdate]) return delete fork[kUpdate] if (!fork.id) return const { schema } = fork.runtime - fork.parent.scope.config = schema ? schema.simplify(config) : config + const entry = fork.parent.scope.config?.find((entry: Entry) => entry.id === fork.id) + if (!entry) return + entry.config = schema ? schema.simplify(config) : config this.writeConfig() }) diff --git a/packages/loader/tests/index.spec.ts b/packages/loader/tests/index.spec.ts index 5a35cc9..321b1a5 100644 --- a/packages/loader/tests/index.spec.ts +++ b/packages/loader/tests/index.spec.ts @@ -8,7 +8,16 @@ describe('@cordisjs/loader', () => { root.plugin(MockLoader) root.loader.writable = true - test('loader.createApp()', async () => { + const foo = mock.fn((ctx: Context) => { + ctx.accept() + }) + const bar = mock.fn((ctx: Context) => { + ctx.accept() + }) + root.loader.register('foo', foo) + root.loader.register('bar', bar) + + test('basic support', async () => { root.loader.config = [{ id: '1', name: 'foo', @@ -24,16 +33,37 @@ describe('@cordisjs/loader', () => { }], }] - const foo = mock.fn() - const bar = mock.fn() - root.loader.register('foo', foo) - root.loader.register('bar', bar) - await root.start() - expect(root.registry.get(foo)).to.be.ok expect(root.registry.get(foo)?.config).to.deep.equal({}) + expect(foo.mock.calls).to.have.length(1) expect(root.registry.get(bar)).to.be.ok expect(root.registry.get(bar)?.config).to.deep.equal({ a: 1 }) + expect(bar.mock.calls).to.have.length(1) + }) + + test('entry update', async () => { + root.loader.config = [{ + id: '1', + name: 'foo', + }] + + root.loader.entry.update(root.loader.config) + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(root.registry.get(foo)).to.be.ok + expect(root.registry.get(bar)).to.be.not.ok + expect(foo.mock.calls).to.have.length(1) + expect(bar.mock.calls).to.have.length(1) + }) + + test('plugin update', async () => { + const runtime = root.registry.get(foo) + runtime?.update({ a: 3 }) + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(root.loader.config).to.deep.equal([{ + id: '1', + name: 'foo', + config: { a: 3 }, + }]) }) }) diff --git a/packages/loader/tests/utils.ts b/packages/loader/tests/utils.ts index 631764a..6baed0f 100644 --- a/packages/loader/tests/utils.ts +++ b/packages/loader/tests/utils.ts @@ -1,6 +1,6 @@ import { Dict } from 'cosmokit' import { Context, Plugin } from '@cordisjs/core' -import { group, Loader } from '../src/shared' +import { Entry, group, Loader } from '../src/shared' declare module '../src/shared' { interface Loader { @@ -23,4 +23,8 @@ export default class MockLoader extends Loader { async import(name: string) { return this.data[name] } + + async readConfig() { + return this.config + } }