From 92df648927761879e0f33e5b384640d71c0fe93d Mon Sep 17 00:00:00 2001 From: Shigma Date: Fri, 24 May 2024 00:48:19 +0800 Subject: [PATCH] feat(loader): extract entry group --- packages/loader/.npmignore | 2 -- packages/loader/src/entry.ts | 1 + packages/loader/src/group.ts | 31 ++++++++++++++++++++++ packages/loader/src/shared.ts | 49 ++++++++++++++--------------------- 4 files changed, 51 insertions(+), 32 deletions(-) delete mode 100644 packages/loader/.npmignore create mode 100644 packages/loader/src/group.ts diff --git a/packages/loader/.npmignore b/packages/loader/.npmignore deleted file mode 100644 index 7e5fcbc..0000000 --- a/packages/loader/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.DS_Store -tsconfig.tsbuildinfo diff --git a/packages/loader/src/entry.ts b/packages/loader/src/entry.ts index 8a4c988..8e74651 100644 --- a/packages/loader/src/entry.ts +++ b/packages/loader/src/entry.ts @@ -46,6 +46,7 @@ export class Entry { public isUpdate = false public parent!: Context public options!: Entry.Options + public group: Entry.Options[] | null = null constructor(public loader: Loader) {} diff --git a/packages/loader/src/group.ts b/packages/loader/src/group.ts new file mode 100644 index 0000000..fc5f263 --- /dev/null +++ b/packages/loader/src/group.ts @@ -0,0 +1,31 @@ +import { Context } from '@cordisjs/core' +import { Entry } from './entry.ts' +import Loader from './shared.ts' + +export class EntryGroup { + public config: Entry.Options[] = [] + + constructor(public loader: Loader, public ctx: Context) { + ctx.on('dispose', () => { + for (const options of this.config) { + this.loader._remove(options.id) + } + }) + } + + update(config: Entry.Options[]) { + const oldConfig = this.config as Entry.Options[] + this.config = config + const oldMap = Object.fromEntries(oldConfig.map(options => [options.id, options])) + const newMap = Object.fromEntries(config.map(options => [options.id ?? Symbol('anonymous'), options])) + + // update inner plugins + for (const id of Reflect.ownKeys({ ...oldMap, ...newMap }) as string[]) { + if (!newMap[id]) { + this.loader._remove(id) + } else { + this.loader._ensure(this.ctx, newMap[id]) + } + } + } +} diff --git a/packages/loader/src/shared.ts b/packages/loader/src/shared.ts index dba9a47..6aeeeeb 100644 --- a/packages/loader/src/shared.ts +++ b/packages/loader/src/shared.ts @@ -7,6 +7,7 @@ import { interpolate } from './utils.ts' import { Entry } from './entry.ts' import * as yaml from 'js-yaml' import * as path from 'path' +import { EntryGroup } from './group.ts' declare module '@cordisjs/core' { interface Events { @@ -313,17 +314,27 @@ export abstract class Loader extends entry.patch(entry.fork.parent, ctx) } - paths(scope: EffectScope): string[] { + locate(ctx = this[Context.current]) { + return this._locate(ctx.scope).map(entry => entry.options.id) + } + + _locate(scope: EffectScope): Entry[] { // root scope if (scope === scope.parent.scope) return [] // runtime scope if (scope.runtime === scope) { - return ([] as string[]).concat(...scope.runtime.children.map(child => this.paths(child))) + return ([] as Entry[]).concat(...scope.runtime.children.map(child => this._locate(child))) } - if (scope.entry) return [scope.entry.options.id] - return this.paths(scope.parent.scope) + if (scope.entry) return [scope.entry] + return this._locate(scope.parent.scope) + } + + createGroup() { + const ctx = this[Context.current] + // if (!ctx.scope.entry) throw new Error(`expected entry scope`) + return new EntryGroup(this, ctx) } async start() { @@ -377,32 +388,10 @@ export function createGroup(config?: Entry.Options[], options: GroupOptions = {} options.initial = config function group(ctx: Context, config: Entry.Options[]) { - const loader = ctx.get('loader')! - for (const options of config) { - loader._ensure(ctx, options) - } - - ctx.accept((neo: Entry.Options[]) => { - // update config reference - const old = ctx.scope.config as Entry.Options[] - const oldMap: any = Object.fromEntries(old.map(entry => [entry.id, entry])) - const neoMap: any = Object.fromEntries(neo.map(entry => [entry.id, entry])) - - // update inner plugins - for (const id in { ...oldMap, ...neoMap }) { - if (!neoMap[id]) { - loader._remove(id) - } else { - loader._ensure(ctx, neoMap[id]) - } - } - }, { passive: true }) - - ctx.on('dispose', () => { - for (const entry of ctx.scope.config as Entry.Options[]) { - loader._remove(entry.id) - } - }) + const group = ctx.get('loader')!.createGroup() + ctx.accept((config: Entry.Options[]) => { + group.update(config) + }, { passive: true, immediate: true }) } defineProperty(group, 'reusable', true)