every-plugin 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/build/rspack/dev-server-middleware.cjs +1 -2
  2. package/dist/build/rspack/dev-server-middleware.cjs.map +1 -1
  3. package/dist/build/rspack/dev-server-middleware.mjs +1 -2
  4. package/dist/build/rspack/dev-server-middleware.mjs.map +1 -1
  5. package/dist/build/rspack/plugin.cjs +20 -0
  6. package/dist/build/rspack/plugin.cjs.map +1 -1
  7. package/dist/build/rspack/plugin.d.cts +5 -0
  8. package/dist/build/rspack/plugin.d.cts.map +1 -1
  9. package/dist/build/rspack/plugin.d.mts +5 -0
  10. package/dist/build/rspack/plugin.d.mts.map +1 -1
  11. package/dist/build/rspack/plugin.mjs +20 -0
  12. package/dist/build/rspack/plugin.mjs.map +1 -1
  13. package/dist/index.d.cts +2 -2
  14. package/dist/index.d.mts +2 -2
  15. package/dist/plugin.cjs +2 -1
  16. package/dist/plugin.cjs.map +1 -1
  17. package/dist/plugin.d.cts.map +1 -1
  18. package/dist/plugin.d.mts.map +1 -1
  19. package/dist/plugin.mjs +2 -1
  20. package/dist/plugin.mjs.map +1 -1
  21. package/dist/runtime/index.cjs +2 -2
  22. package/dist/runtime/index.cjs.map +1 -1
  23. package/dist/runtime/index.d.cts.map +1 -1
  24. package/dist/runtime/index.d.mts.map +1 -1
  25. package/dist/runtime/index.mjs +2 -2
  26. package/dist/runtime/index.mjs.map +1 -1
  27. package/dist/runtime/mf-config.cjs +1 -1
  28. package/dist/runtime/mf-config.mjs +1 -1
  29. package/dist/runtime/services/plugin-lifecycle.service.cjs +5 -2
  30. package/dist/runtime/services/plugin-lifecycle.service.cjs.map +1 -1
  31. package/dist/runtime/services/plugin-lifecycle.service.mjs +6 -3
  32. package/dist/runtime/services/plugin-lifecycle.service.mjs.map +1 -1
  33. package/dist/runtime/services/plugin.service.cjs +1 -1
  34. package/dist/runtime/services/plugin.service.cjs.map +1 -1
  35. package/dist/runtime/services/plugin.service.d.cts.map +1 -1
  36. package/dist/runtime/services/plugin.service.d.mts.map +1 -1
  37. package/dist/runtime/services/plugin.service.mjs +1 -1
  38. package/dist/runtime/services/plugin.service.mjs.map +1 -1
  39. package/package.json +1 -1
  40. package/src/build/rspack/dev-server-middleware.ts +1 -6
  41. package/src/build/rspack/plugin.ts +38 -1
  42. package/src/index.ts +1 -0
  43. package/src/plugin.ts +8 -1
  44. package/src/runtime/index.ts +10 -2
  45. package/src/runtime/services/plugin-lifecycle.service.ts +18 -23
  46. package/src/runtime/services/plugin.service.ts +7 -4
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Hash","Effect","PluginRuntimeError","effect","Exit","Cause","Option","PluginService","ManagedRuntime"],"sources":["../../src/runtime/index.ts"],"sourcesContent":["import { createRouterClient } from \"@orpc/server\";\nimport { Cause, Effect, Exit, Hash, ManagedRuntime, Option } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InferRegistryFromEntries,\n InitializedPlugin,\n LoadedPlugin,\n PluginConfigInput,\n PluginInstance,\n PluginRegistry,\n PluginRegistryEntry,\n PluginRouterType,\n PluginRuntimeConfig,\n RegisteredPlugin,\n RegisteredPlugins,\n UsePluginResult,\n} from \"../types\";\nimport { PluginRuntimeError } from \"./errors\";\nimport { PluginService } from \"./services/plugin.service\";\n\nexport class PluginRuntime<R = RegisteredPlugins> {\n readonly __registryType?: R;\n\n private pluginCache = new Map<\n string,\n Effect.Effect<InitializedPlugin<AnyPlugin>, PluginRuntimeError>\n >();\n\n constructor(\n private runtime: ManagedRuntime.ManagedRuntime<PluginService, never>,\n private registry: PluginRegistry,\n ) {}\n\n private generateCacheKey(pluginId: string, config: unknown): string {\n const configHash = Hash.structure(config as object).toString();\n return `${pluginId}:${configHash}`;\n }\n\n private validatePluginId(pluginId: string): Effect.Effect<string, PluginRuntimeError> {\n if (!(pluginId in this.registry)) {\n return Effect.fail(\n new PluginRuntimeError({\n pluginId: String(pluginId),\n operation: \"validate-plugin-id\",\n cause: new Error(`Plugin ID '${String(pluginId)}' not found in registry.`),\n retryable: false,\n }),\n );\n }\n return Effect.succeed(String(pluginId));\n }\n\n private async runPromise<A, E>(effect: Effect.Effect<A, E, PluginService>): Promise<A> {\n const exit = await this.runtime.runPromiseExit(effect);\n\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n if (Option.isSome(error)) {\n throw error.value;\n }\n throw Cause.squash(exit.cause);\n }\n\n return exit.value;\n }\n\n async usePlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n plugins?: Record<string, unknown>,\n ): Promise<UsePluginResult<K, R>> {\n const cacheKey = this.generateCacheKey(pluginId, { ...config, __plugins: plugins ?? {} });\n\n let cachedPlugin = this.pluginCache.get(cacheKey);\n if (!cachedPlugin) {\n const operation = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const validatedId = yield* this.validatePluginId(pluginId);\n\n // Load → Instantiate → Initialize\n const ctor = yield* pluginService.loadPlugin(validatedId);\n const instance = yield* pluginService.instantiatePlugin(pluginId, ctor);\n const initialized = yield* pluginService.initializePlugin(instance, config, plugins);\n\n return initialized;\n }).pipe(Effect.provide(this.runtime));\n\n cachedPlugin = Effect.cached(operation).pipe(Effect.flatten);\n this.pluginCache.set(cacheKey, cachedPlugin);\n }\n\n const initialized = await this.runPromise(cachedPlugin);\n\n // Create client factory that accepts request context\n const createClient = (context?: any) => {\n const router = initialized.plugin.createRouter(initialized.context);\n return createRouterClient(router, { context: context ?? {} });\n };\n\n return {\n createClient: createClient as any,\n router: initialized.plugin.createRouter(initialized.context) as PluginRouterType<R[K]>,\n metadata: initialized.metadata,\n initialized: initialized as InitializedPlugin<RegisteredPlugin<K, R>>,\n } as UsePluginResult<K, R>;\n }\n\n async loadPlugin<K extends keyof R & string>(\n pluginId: K,\n ): Promise<LoadedPlugin<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.loadPlugin(pluginId);\n });\n return this.runPromise(effect) as Promise<LoadedPlugin<RegisteredPlugin<K, R>>>;\n }\n\n async instantiatePlugin<K extends keyof R & string>(\n pluginId: K,\n loadedPlugin: LoadedPlugin<RegisteredPlugin<K, R>>,\n ): Promise<PluginInstance<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.instantiatePlugin(pluginId, loadedPlugin);\n });\n return this.runPromise(effect) as Promise<PluginInstance<RegisteredPlugin<K, R>>>;\n }\n\n async initializePlugin<T extends AnyPlugin>(\n instance: PluginInstance<T>,\n config: any,\n plugins?: Record<string, unknown>,\n ): Promise<InitializedPlugin<T>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.initializePlugin(instance, config, plugins);\n });\n return this.runPromise(effect);\n }\n\n async shutdown(): Promise<void> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n yield* pluginService.cleanup();\n });\n return this.runPromise(effect);\n }\n\n async evictPlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n ): Promise<void> {\n const cacheKey = this.generateCacheKey(pluginId, config);\n\n const effect = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const cachedPlugin = this.pluginCache.get(cacheKey);\n\n if (cachedPlugin) {\n this.pluginCache.delete(cacheKey);\n\n const pluginResult = yield* cachedPlugin.pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (pluginResult) {\n yield* pluginService\n .shutdownPlugin(pluginResult)\n .pipe(Effect.catchAll(() => Effect.void));\n }\n }\n }).pipe(Effect.catchAll(() => Effect.void));\n\n return this.runPromise(effect);\n }\n}\n\n/**\n * Normalizes a remote URL to ensure it points to remoteEntry.js\n * If the URL doesn't end with a file extension, appends /remoteEntry.js\n */\nfunction normalizeRemoteUrl(url: string): string {\n if (!url) return url;\n if (url.endsWith(\".js\") || url.endsWith(\".json\")) return url;\n return `${url.endsWith(\"/\") ? url.slice(0, -1) : url}/remoteEntry.js`;\n}\n\n/**\n * Extract plugin map (module constructors) from registry entries\n */\nfunction extractPluginMap(\n registry: Record<string, PluginRegistryEntry>,\n): Record<string, AnyPluginConstructor> {\n const pluginMap: Record<string, AnyPluginConstructor> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry && entry.module) {\n pluginMap[pluginId] = entry.module;\n }\n }\n\n return pluginMap;\n}\n\n/**\n * Normalize registry entries - ensure remote URLs are properly formatted\n */\nfunction normalizeRegistry(registry: Record<string, PluginRegistryEntry>): PluginRegistry {\n const normalized: Record<string, PluginRegistryEntry> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry) {\n normalized[pluginId] = {\n ...entry,\n remote: entry.remote ? normalizeRemoteUrl(entry.remote) : undefined,\n };\n } else {\n normalized[pluginId] = {\n ...entry,\n remote: normalizeRemoteUrl(entry.remote),\n };\n }\n }\n\n return normalized as PluginRegistry;\n}\n\n/**\n * Creates a plugin runtime with support for both module and remote plugin entries.\n *\n * @example\n * ```typescript\n * // With module entries (types inferred automatically)\n * const runtime = createPluginRuntime({\n * registry: {\n * telegram: { module: TelegramPlugin },\n * gopher: { remote: \"https://cdn.example.com/gopher/remoteEntry.js\" }\n * },\n * secrets: { API_KEY: \"...\" }\n * });\n *\n * // Types are automatically inferred from module entries!\n * const { router } = await runtime.usePlugin(\"telegram\", config);\n * ```\n */\nexport function createPluginRuntime<TRegistry extends Record<string, PluginRegistryEntry>>(\n config: PluginRuntimeConfig<TRegistry>,\n): PluginRuntime<InferRegistryFromEntries<TRegistry>> {\n const secrets = config.secrets || {};\n const normalizedRegistry = normalizeRegistry(config.registry);\n const pluginMap = extractPluginMap(config.registry);\n\n const layer = PluginService.Live(normalizedRegistry, secrets, pluginMap);\n const runtime = ManagedRuntime.make(layer);\n\n return new PluginRuntime(runtime, normalizedRegistry) as PluginRuntime<\n InferRegistryFromEntries<TRegistry>\n >;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Hash","Effect","PluginRuntimeError","effect","Exit","Cause","Option","PluginService","ManagedRuntime"],"sources":["../../src/runtime/index.ts"],"sourcesContent":["import { createRouterClient } from \"@orpc/server\";\nimport { Cause, Effect, Exit, Hash, ManagedRuntime, Option } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InferRegistryFromEntries,\n InitializedPlugin,\n LoadedPlugin,\n PluginConfigInput,\n PluginInstance,\n PluginRegistry,\n PluginRegistryEntry,\n PluginRouterType,\n PluginRuntimeConfig,\n RegisteredPlugin,\n RegisteredPlugins,\n UsePluginResult,\n} from \"../types\";\nimport { PluginRuntimeError } from \"./errors\";\nimport { PluginService } from \"./services/plugin.service\";\n\nexport class PluginRuntime<R = RegisteredPlugins> {\n readonly __registryType?: R;\n\n private pluginCache = new Map<\n string,\n Effect.Effect<InitializedPlugin<AnyPlugin>, PluginRuntimeError>\n >();\n\n constructor(\n private runtime: ManagedRuntime.ManagedRuntime<PluginService, never>,\n private registry: PluginRegistry,\n ) {}\n\n private generateCacheKey(pluginId: string, config: unknown): string {\n const configHash = Hash.structure(config as object).toString();\n return `${pluginId}:${configHash}`;\n }\n\n private validatePluginId(pluginId: string): Effect.Effect<string, PluginRuntimeError> {\n if (!(pluginId in this.registry)) {\n return Effect.fail(\n new PluginRuntimeError({\n pluginId: String(pluginId),\n operation: \"validate-plugin-id\",\n cause: new Error(`Plugin ID '${String(pluginId)}' not found in registry.`),\n retryable: false,\n }),\n );\n }\n return Effect.succeed(String(pluginId));\n }\n\n private async runPromise<A, E>(effect: Effect.Effect<A, E, PluginService>): Promise<A> {\n const exit = await this.runtime.runPromiseExit(effect);\n\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n if (Option.isSome(error)) {\n throw error.value;\n }\n throw Cause.squash(exit.cause);\n }\n\n return exit.value;\n }\n\n async usePlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n plugins?: Record<string, unknown>,\n ): Promise<UsePluginResult<K, R>> {\n const cacheKey = this.generateCacheKey(pluginId, { ...config, __plugins: plugins ?? {} });\n\n let cachedPlugin = this.pluginCache.get(cacheKey);\n if (!cachedPlugin) {\n const operation = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const validatedId = yield* this.validatePluginId(pluginId);\n\n // Load → Instantiate → Initialize\n const ctor = yield* pluginService.loadPlugin(validatedId);\n const instance = yield* pluginService.instantiatePlugin(pluginId, ctor);\n const initialized = yield* pluginService.initializePlugin(instance, config, plugins);\n\n return initialized;\n }).pipe(Effect.provide(this.runtime));\n\n cachedPlugin = Effect.cached(operation).pipe(Effect.flatten);\n this.pluginCache.set(cacheKey, cachedPlugin);\n }\n\n const initialized = await this.runPromise(cachedPlugin);\n\n // Create client factory that accepts request context\n const createClient = (context?: any) => {\n const router = initialized.plugin.createRouter(initialized.context);\n return createRouterClient(router, { context: context ?? {} });\n };\n\n return {\n createClient: createClient as any,\n router: initialized.plugin.createRouter(initialized.context) as PluginRouterType<R[K]>,\n metadata: initialized.metadata,\n initialized: initialized as InitializedPlugin<RegisteredPlugin<K, R>>,\n } as UsePluginResult<K, R>;\n }\n\n async loadPlugin<K extends keyof R & string>(\n pluginId: K,\n ): Promise<LoadedPlugin<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.loadPlugin(pluginId);\n });\n return this.runPromise(effect) as Promise<LoadedPlugin<RegisteredPlugin<K, R>>>;\n }\n\n async instantiatePlugin<K extends keyof R & string>(\n pluginId: K,\n loadedPlugin: LoadedPlugin<RegisteredPlugin<K, R>>,\n ): Promise<PluginInstance<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.instantiatePlugin(pluginId, loadedPlugin);\n });\n return this.runPromise(effect) as Promise<PluginInstance<RegisteredPlugin<K, R>>>;\n }\n\n async initializePlugin<T extends AnyPlugin>(\n instance: PluginInstance<T>,\n config: any,\n plugins?: Record<string, unknown>,\n ): Promise<InitializedPlugin<T>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.initializePlugin(instance, config, plugins);\n });\n return this.runPromise(effect);\n }\n\n async shutdown(): Promise<void> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n yield* pluginService.cleanup();\n });\n return this.runPromise(effect);\n }\n\n async evictPlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n ): Promise<void> {\n const cacheKey = this.generateCacheKey(pluginId, config);\n\n const effect = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const cachedPlugin = this.pluginCache.get(cacheKey);\n\n if (cachedPlugin) {\n this.pluginCache.delete(cacheKey);\n\n const pluginResult = yield* cachedPlugin.pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (pluginResult) {\n yield* pluginService\n .shutdownPlugin(pluginResult)\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown evicted plugin ${pluginId}`, error),\n ),\n );\n }\n }\n }).pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Plugin eviction failed for ${pluginId}`, error),\n ),\n );\n\n return this.runPromise(effect);\n }\n}\n\n/**\n * Normalizes a remote URL to ensure it points to remoteEntry.js\n * If the URL doesn't end with a file extension, appends /remoteEntry.js\n */\nfunction normalizeRemoteUrl(url: string): string {\n if (!url) return url;\n if (url.endsWith(\".js\") || url.endsWith(\".json\")) return url;\n return `${url.endsWith(\"/\") ? url.slice(0, -1) : url}/remoteEntry.js`;\n}\n\n/**\n * Extract plugin map (module constructors) from registry entries\n */\nfunction extractPluginMap(\n registry: Record<string, PluginRegistryEntry>,\n): Record<string, AnyPluginConstructor> {\n const pluginMap: Record<string, AnyPluginConstructor> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry && entry.module) {\n pluginMap[pluginId] = entry.module;\n }\n }\n\n return pluginMap;\n}\n\n/**\n * Normalize registry entries - ensure remote URLs are properly formatted\n */\nfunction normalizeRegistry(registry: Record<string, PluginRegistryEntry>): PluginRegistry {\n const normalized: Record<string, PluginRegistryEntry> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry) {\n normalized[pluginId] = {\n ...entry,\n remote: entry.remote ? normalizeRemoteUrl(entry.remote) : undefined,\n };\n } else {\n normalized[pluginId] = {\n ...entry,\n remote: normalizeRemoteUrl(entry.remote),\n };\n }\n }\n\n return normalized as PluginRegistry;\n}\n\n/**\n * Creates a plugin runtime with support for both module and remote plugin entries.\n *\n * @example\n * ```typescript\n * // With module entries (types inferred automatically)\n * const runtime = createPluginRuntime({\n * registry: {\n * telegram: { module: TelegramPlugin },\n * gopher: { remote: \"https://cdn.example.com/gopher/remoteEntry.js\" }\n * },\n * secrets: { API_KEY: \"...\" }\n * });\n *\n * // Types are automatically inferred from module entries!\n * const { router } = await runtime.usePlugin(\"telegram\", config);\n * ```\n */\nexport function createPluginRuntime<TRegistry extends Record<string, PluginRegistryEntry>>(\n config: PluginRuntimeConfig<TRegistry>,\n): PluginRuntime<InferRegistryFromEntries<TRegistry>> {\n const secrets = config.secrets || {};\n const normalizedRegistry = normalizeRegistry(config.registry);\n const pluginMap = extractPluginMap(config.registry);\n\n const layer = PluginService.Live(normalizedRegistry, secrets, pluginMap);\n const runtime = ManagedRuntime.make(layer);\n\n return new PluginRuntime(runtime, normalizedRegistry) as PluginRuntime<\n InferRegistryFromEntries<TRegistry>\n >;\n}\n"],"mappings":";;;;;;;;AAqBA,IAAa,gBAAb,MAAkD;CAChD,AAAS;CAET,AAAQ,8BAAc,IAAI,KAGvB;CAEH,YACE,AAAQ,SACR,AAAQ,UACR;EAFQ;EACA;;CAGV,AAAQ,iBAAiB,UAAkB,QAAyB;AAElE,SAAO,GAAG,SAAS,GADAA,YAAK,UAAU,OAAiB,CAAC,UAAU;;CAIhE,AAAQ,iBAAiB,UAA6D;AACpF,MAAI,EAAE,YAAY,KAAK,UACrB,QAAOC,cAAO,KACZ,IAAIC,kCAAmB;GACrB,UAAU,OAAO,SAAS;GAC1B,WAAW;GACX,uBAAO,IAAI,MAAM,cAAc,OAAO,SAAS,CAAC,0BAA0B;GAC1E,WAAW;GACZ,CAAC,CACH;AAEH,SAAOD,cAAO,QAAQ,OAAO,SAAS,CAAC;;CAGzC,MAAc,WAAiB,UAAwD;EACrF,MAAM,OAAO,MAAM,KAAK,QAAQ,eAAeE,SAAO;AAEtD,MAAIC,YAAK,UAAU,KAAK,EAAE;GACxB,MAAM,QAAQC,aAAM,cAAc,KAAK,MAAM;AAC7C,OAAIC,cAAO,OAAO,MAAM,CACtB,OAAM,MAAM;AAEd,SAAMD,aAAM,OAAO,KAAK,MAAM;;AAGhC,SAAO,KAAK;;CAGd,MAAM,UACJ,UACA,QACA,SACgC;EAChC,MAAM,WAAW,KAAK,iBAAiB,UAAU;GAAE,GAAG;GAAQ,WAAW,WAAW,EAAE;GAAE,CAAC;EAEzF,IAAI,eAAe,KAAK,YAAY,IAAI,SAAS;AACjD,MAAI,CAAC,cAAc;GACjB,MAAM,YAAYJ,cAAO,IAAI,MAAM,aAAa;IAC9C,MAAM,gBAAgB,OAAOM;IAC7B,MAAM,cAAc,OAAO,KAAK,iBAAiB,SAAS;IAG1D,MAAM,OAAO,OAAO,cAAc,WAAW,YAAY;IACzD,MAAM,WAAW,OAAO,cAAc,kBAAkB,UAAU,KAAK;AAGvE,WAFoB,OAAO,cAAc,iBAAiB,UAAU,QAAQ,QAAQ;KAGpF,CAAC,KAAKN,cAAO,QAAQ,KAAK,QAAQ,CAAC;AAErC,kBAAeA,cAAO,OAAO,UAAU,CAAC,KAAKA,cAAO,QAAQ;AAC5D,QAAK,YAAY,IAAI,UAAU,aAAa;;EAG9C,MAAM,cAAc,MAAM,KAAK,WAAW,aAAa;EAGvD,MAAM,gBAAgB,YAAkB;AAEtC,+CADe,YAAY,OAAO,aAAa,YAAY,QAAQ,EACjC,EAAE,SAAS,WAAW,EAAE,EAAE,CAAC;;AAG/D,SAAO;GACS;GACd,QAAQ,YAAY,OAAO,aAAa,YAAY,QAAQ;GAC5D,UAAU,YAAY;GACT;GACd;;CAGH,MAAM,WACJ,UAC+C;EAC/C,MAAME,WAASF,cAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAOM,sCACD,WAAW,SAAS;IAChD;AACF,SAAO,KAAK,WAAWJ,SAAO;;CAGhC,MAAM,kBACJ,UACA,cACiD;EACjD,MAAMA,WAASF,cAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAOM,sCACD,kBAAkB,UAAU,aAAa;IACrE;AACF,SAAO,KAAK,WAAWJ,SAAO;;CAGhC,MAAM,iBACJ,UACA,QACA,SAC+B;EAC/B,MAAMA,WAASF,cAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAOM,sCACD,iBAAiB,UAAU,QAAQ,QAAQ;IACvE;AACF,SAAO,KAAK,WAAWJ,SAAO;;CAGhC,MAAM,WAA0B;EAC9B,MAAMA,WAASF,cAAO,IAAI,aAAa;AAErC,WADsB,OAAOM,sCACR,SAAS;IAC9B;AACF,SAAO,KAAK,WAAWJ,SAAO;;CAGhC,MAAM,YACJ,UACA,QACe;EACf,MAAM,WAAW,KAAK,iBAAiB,UAAU,OAAO;EAExD,MAAMA,WAASF,cAAO,IAAI,MAAM,aAAa;GAC3C,MAAM,gBAAgB,OAAOM;GAC7B,MAAM,eAAe,KAAK,YAAY,IAAI,SAAS;AAEnD,OAAI,cAAc;AAChB,SAAK,YAAY,OAAO,SAAS;IAEjC,MAAM,eAAe,OAAO,aAAa,KAAKN,cAAO,eAAeA,cAAO,QAAQ,KAAK,CAAC,CAAC;AAE1F,QAAI,aACF,QAAO,cACJ,eAAe,aAAa,CAC5B,KACCA,cAAO,UAAU,UACfA,cAAO,WAAW,qCAAqC,YAAY,MAAM,CAC1E,CACF;;IAGP,CAAC,KACDA,cAAO,UAAU,UACfA,cAAO,WAAW,8BAA8B,YAAY,MAAM,CACnE,CACF;AAED,SAAO,KAAK,WAAWE,SAAO;;;;;;;AAQlC,SAAS,mBAAmB,KAAqB;AAC/C,KAAI,CAAC,IAAK,QAAO;AACjB,KAAI,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,QAAQ,CAAE,QAAO;AACzD,QAAO,GAAG,IAAI,SAAS,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI;;;;;AAMvD,SAAS,iBACP,UACsC;CACtC,MAAM,YAAkD,EAAE;AAE1D,MAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,SAAS,CACtD,KAAI,YAAY,SAAS,MAAM,OAC7B,WAAU,YAAY,MAAM;AAIhC,QAAO;;;;;AAMT,SAAS,kBAAkB,UAA+D;CACxF,MAAM,aAAkD,EAAE;AAE1D,MAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,SAAS,CACtD,KAAI,YAAY,MACd,YAAW,YAAY;EACrB,GAAG;EACH,QAAQ,MAAM,SAAS,mBAAmB,MAAM,OAAO,GAAG;EAC3D;KAED,YAAW,YAAY;EACrB,GAAG;EACH,QAAQ,mBAAmB,MAAM,OAAO;EACzC;AAIL,QAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,oBACd,QACoD;CACpD,MAAM,UAAU,OAAO,WAAW,EAAE;CACpC,MAAM,qBAAqB,kBAAkB,OAAO,SAAS;CAC7D,MAAM,YAAY,iBAAiB,OAAO,SAAS;CAEnD,MAAM,QAAQI,qCAAc,KAAK,oBAAoB,SAAS,UAAU;AAGxE,QAAO,IAAI,cAFKC,sBAAe,KAAK,MAAM,EAER,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;;;;cAqBa,aAAA,KAAkB,iBAAA;EAAA,QASnB,OAAA;EAAA,QACA,QAAA;EAAA,SATD,cAAA,GAAiB,CAAA;EAAA,QAElB,WAAA;cAME,OAAA,EAAS,cAAA,CAAe,cAAA,CAAe,aAAA,UACvC,QAAA,EAAU,cAAA;EAAA,QAGZ,gBAAA;EAAA,QAKA,gBAAA;EAAA,QAcM,UAAA;EAcR,SAAA,iBAA0B,CAAA,UAAA,CAC9B,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,IAC5B,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,eAAA,CAAgB,CAAA,EAAG,CAAA;EAqCxB,UAAA,iBAA2B,CAAA,UAAA,CAC/B,QAAA,EAAU,CAAA,GACT,OAAA,CAAQ,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQtC,iBAAA,iBAAkC,CAAA,UAAA,CACtC,QAAA,EAAU,CAAA,EACV,YAAA,EAAc,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA,KAC9C,OAAA,CAAQ,cAAA,CAAe,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQxC,gBAAA,WAA2B,SAAA,CAAA,CAC/B,QAAA,EAAU,cAAA,CAAe,CAAA,GACzB,MAAA,OACA,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EAQvB,QAAA,CAAA,GAAY,OAAA;EAQZ,WAAA,iBAA4B,CAAA,UAAA,CAChC,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,KAC3B,OAAA;AAAA;;;;;;;;;;;;;;;;;;;iBA4FW,mBAAA,mBAAsC,MAAA,SAAe,mBAAA,EAAA,CACnE,MAAA,EAAQ,mBAAA,CAAoB,SAAA,IAC3B,aAAA,CAAc,wBAAA,CAAyB,SAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;;;;cAqBa,aAAA,KAAkB,iBAAA;EAAA,QASnB,OAAA;EAAA,QACA,QAAA;EAAA,SATD,cAAA,GAAiB,CAAA;EAAA,QAElB,WAAA;cAME,OAAA,EAAS,cAAA,CAAe,cAAA,CAAe,aAAA,UACvC,QAAA,EAAU,cAAA;EAAA,QAGZ,gBAAA;EAAA,QAKA,gBAAA;EAAA,QAcM,UAAA;EAcR,SAAA,iBAA0B,CAAA,UAAA,CAC9B,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,IAC5B,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,eAAA,CAAgB,CAAA,EAAG,CAAA;EAqCxB,UAAA,iBAA2B,CAAA,UAAA,CAC/B,QAAA,EAAU,CAAA,GACT,OAAA,CAAQ,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQtC,iBAAA,iBAAkC,CAAA,UAAA,CACtC,QAAA,EAAU,CAAA,EACV,YAAA,EAAc,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA,KAC9C,OAAA,CAAQ,cAAA,CAAe,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQxC,gBAAA,WAA2B,SAAA,CAAA,CAC/B,QAAA,EAAU,cAAA,CAAe,CAAA,GACzB,MAAA,OACA,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EAQvB,QAAA,CAAA,GAAY,OAAA;EAQZ,WAAA,iBAA4B,CAAA,UAAA,CAChC,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,KAC3B,OAAA;AAAA;;;;;;;;;;;;;;;;;;;iBAoGW,mBAAA,mBAAsC,MAAA,SAAe,mBAAA,EAAA,CACnE,MAAA,EAAQ,mBAAA,CAAoB,SAAA,IAC3B,aAAA,CAAc,wBAAA,CAAyB,SAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;;;;cAqBa,aAAA,KAAkB,iBAAA;EAAA,QASnB,OAAA;EAAA,QACA,QAAA;EAAA,SATD,cAAA,GAAiB,CAAA;EAAA,QAElB,WAAA;cAME,OAAA,EAAS,cAAA,CAAe,cAAA,CAAe,aAAA,UACvC,QAAA,EAAU,cAAA;EAAA,QAGZ,gBAAA;EAAA,QAKA,gBAAA;EAAA,QAcM,UAAA;EAcR,SAAA,iBAA0B,CAAA,UAAA,CAC9B,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,IAC5B,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,eAAA,CAAgB,CAAA,EAAG,CAAA;EAqCxB,UAAA,iBAA2B,CAAA,UAAA,CAC/B,QAAA,EAAU,CAAA,GACT,OAAA,CAAQ,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQtC,iBAAA,iBAAkC,CAAA,UAAA,CACtC,QAAA,EAAU,CAAA,EACV,YAAA,EAAc,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA,KAC9C,OAAA,CAAQ,cAAA,CAAe,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQxC,gBAAA,WAA2B,SAAA,CAAA,CAC/B,QAAA,EAAU,cAAA,CAAe,CAAA,GACzB,MAAA,OACA,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EAQvB,QAAA,CAAA,GAAY,OAAA;EAQZ,WAAA,iBAA4B,CAAA,UAAA,CAChC,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,KAC3B,OAAA;AAAA;;;;;;;;;;;;;;;;;;;iBA4FW,mBAAA,mBAAsC,MAAA,SAAe,mBAAA,EAAA,CACnE,MAAA,EAAQ,mBAAA,CAAoB,SAAA,IAC3B,aAAA,CAAc,wBAAA,CAAyB,SAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;;;;cAqBa,aAAA,KAAkB,iBAAA;EAAA,QASnB,OAAA;EAAA,QACA,QAAA;EAAA,SATD,cAAA,GAAiB,CAAA;EAAA,QAElB,WAAA;cAME,OAAA,EAAS,cAAA,CAAe,cAAA,CAAe,aAAA,UACvC,QAAA,EAAU,cAAA;EAAA,QAGZ,gBAAA;EAAA,QAKA,gBAAA;EAAA,QAcM,UAAA;EAcR,SAAA,iBAA0B,CAAA,UAAA,CAC9B,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,IAC5B,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,eAAA,CAAgB,CAAA,EAAG,CAAA;EAqCxB,UAAA,iBAA2B,CAAA,UAAA,CAC/B,QAAA,EAAU,CAAA,GACT,OAAA,CAAQ,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQtC,iBAAA,iBAAkC,CAAA,UAAA,CACtC,QAAA,EAAU,CAAA,EACV,YAAA,EAAc,YAAA,CAAa,gBAAA,CAAiB,CAAA,EAAG,CAAA,KAC9C,OAAA,CAAQ,cAAA,CAAe,gBAAA,CAAiB,CAAA,EAAG,CAAA;EAQxC,gBAAA,WAA2B,SAAA,CAAA,CAC/B,QAAA,EAAU,cAAA,CAAe,CAAA,GACzB,MAAA,OACA,OAAA,GAAU,MAAA,oBACT,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EAQvB,QAAA,CAAA,GAAY,OAAA;EAQZ,WAAA,iBAA4B,CAAA,UAAA,CAChC,QAAA,EAAU,CAAA,EACV,MAAA,EAAQ,iBAAA,CAAkB,CAAA,CAAE,CAAA,KAC3B,OAAA;AAAA;;;;;;;;;;;;;;;;;;;iBAoGW,mBAAA,mBAAsC,MAAA,SAAe,mBAAA,EAAA,CACnE,MAAA,EAAQ,mBAAA,CAAoB,SAAA,IAC3B,aAAA,CAAc,wBAAA,CAAyB,SAAA"}
@@ -92,9 +92,9 @@ var PluginRuntime = class {
92
92
  if (cachedPlugin) {
93
93
  this.pluginCache.delete(cacheKey);
94
94
  const pluginResult = yield* cachedPlugin.pipe(Effect.catchAll(() => Effect.succeed(null)));
95
- if (pluginResult) yield* pluginService.shutdownPlugin(pluginResult).pipe(Effect.catchAll(() => Effect.void));
95
+ if (pluginResult) yield* pluginService.shutdownPlugin(pluginResult).pipe(Effect.catchAll((error) => Effect.logWarning(`Failed to shutdown evicted plugin ${pluginId}`, error)));
96
96
  }
97
- }).pipe(Effect.catchAll(() => Effect.void));
97
+ }).pipe(Effect.catchAll((error) => Effect.logWarning(`Plugin eviction failed for ${pluginId}`, error)));
98
98
  return this.runPromise(effect);
99
99
  }
100
100
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/runtime/index.ts"],"sourcesContent":["import { createRouterClient } from \"@orpc/server\";\nimport { Cause, Effect, Exit, Hash, ManagedRuntime, Option } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InferRegistryFromEntries,\n InitializedPlugin,\n LoadedPlugin,\n PluginConfigInput,\n PluginInstance,\n PluginRegistry,\n PluginRegistryEntry,\n PluginRouterType,\n PluginRuntimeConfig,\n RegisteredPlugin,\n RegisteredPlugins,\n UsePluginResult,\n} from \"../types\";\nimport { PluginRuntimeError } from \"./errors\";\nimport { PluginService } from \"./services/plugin.service\";\n\nexport class PluginRuntime<R = RegisteredPlugins> {\n readonly __registryType?: R;\n\n private pluginCache = new Map<\n string,\n Effect.Effect<InitializedPlugin<AnyPlugin>, PluginRuntimeError>\n >();\n\n constructor(\n private runtime: ManagedRuntime.ManagedRuntime<PluginService, never>,\n private registry: PluginRegistry,\n ) {}\n\n private generateCacheKey(pluginId: string, config: unknown): string {\n const configHash = Hash.structure(config as object).toString();\n return `${pluginId}:${configHash}`;\n }\n\n private validatePluginId(pluginId: string): Effect.Effect<string, PluginRuntimeError> {\n if (!(pluginId in this.registry)) {\n return Effect.fail(\n new PluginRuntimeError({\n pluginId: String(pluginId),\n operation: \"validate-plugin-id\",\n cause: new Error(`Plugin ID '${String(pluginId)}' not found in registry.`),\n retryable: false,\n }),\n );\n }\n return Effect.succeed(String(pluginId));\n }\n\n private async runPromise<A, E>(effect: Effect.Effect<A, E, PluginService>): Promise<A> {\n const exit = await this.runtime.runPromiseExit(effect);\n\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n if (Option.isSome(error)) {\n throw error.value;\n }\n throw Cause.squash(exit.cause);\n }\n\n return exit.value;\n }\n\n async usePlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n plugins?: Record<string, unknown>,\n ): Promise<UsePluginResult<K, R>> {\n const cacheKey = this.generateCacheKey(pluginId, { ...config, __plugins: plugins ?? {} });\n\n let cachedPlugin = this.pluginCache.get(cacheKey);\n if (!cachedPlugin) {\n const operation = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const validatedId = yield* this.validatePluginId(pluginId);\n\n // Load → Instantiate → Initialize\n const ctor = yield* pluginService.loadPlugin(validatedId);\n const instance = yield* pluginService.instantiatePlugin(pluginId, ctor);\n const initialized = yield* pluginService.initializePlugin(instance, config, plugins);\n\n return initialized;\n }).pipe(Effect.provide(this.runtime));\n\n cachedPlugin = Effect.cached(operation).pipe(Effect.flatten);\n this.pluginCache.set(cacheKey, cachedPlugin);\n }\n\n const initialized = await this.runPromise(cachedPlugin);\n\n // Create client factory that accepts request context\n const createClient = (context?: any) => {\n const router = initialized.plugin.createRouter(initialized.context);\n return createRouterClient(router, { context: context ?? {} });\n };\n\n return {\n createClient: createClient as any,\n router: initialized.plugin.createRouter(initialized.context) as PluginRouterType<R[K]>,\n metadata: initialized.metadata,\n initialized: initialized as InitializedPlugin<RegisteredPlugin<K, R>>,\n } as UsePluginResult<K, R>;\n }\n\n async loadPlugin<K extends keyof R & string>(\n pluginId: K,\n ): Promise<LoadedPlugin<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.loadPlugin(pluginId);\n });\n return this.runPromise(effect) as Promise<LoadedPlugin<RegisteredPlugin<K, R>>>;\n }\n\n async instantiatePlugin<K extends keyof R & string>(\n pluginId: K,\n loadedPlugin: LoadedPlugin<RegisteredPlugin<K, R>>,\n ): Promise<PluginInstance<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.instantiatePlugin(pluginId, loadedPlugin);\n });\n return this.runPromise(effect) as Promise<PluginInstance<RegisteredPlugin<K, R>>>;\n }\n\n async initializePlugin<T extends AnyPlugin>(\n instance: PluginInstance<T>,\n config: any,\n plugins?: Record<string, unknown>,\n ): Promise<InitializedPlugin<T>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.initializePlugin(instance, config, plugins);\n });\n return this.runPromise(effect);\n }\n\n async shutdown(): Promise<void> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n yield* pluginService.cleanup();\n });\n return this.runPromise(effect);\n }\n\n async evictPlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n ): Promise<void> {\n const cacheKey = this.generateCacheKey(pluginId, config);\n\n const effect = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const cachedPlugin = this.pluginCache.get(cacheKey);\n\n if (cachedPlugin) {\n this.pluginCache.delete(cacheKey);\n\n const pluginResult = yield* cachedPlugin.pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (pluginResult) {\n yield* pluginService\n .shutdownPlugin(pluginResult)\n .pipe(Effect.catchAll(() => Effect.void));\n }\n }\n }).pipe(Effect.catchAll(() => Effect.void));\n\n return this.runPromise(effect);\n }\n}\n\n/**\n * Normalizes a remote URL to ensure it points to remoteEntry.js\n * If the URL doesn't end with a file extension, appends /remoteEntry.js\n */\nfunction normalizeRemoteUrl(url: string): string {\n if (!url) return url;\n if (url.endsWith(\".js\") || url.endsWith(\".json\")) return url;\n return `${url.endsWith(\"/\") ? url.slice(0, -1) : url}/remoteEntry.js`;\n}\n\n/**\n * Extract plugin map (module constructors) from registry entries\n */\nfunction extractPluginMap(\n registry: Record<string, PluginRegistryEntry>,\n): Record<string, AnyPluginConstructor> {\n const pluginMap: Record<string, AnyPluginConstructor> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry && entry.module) {\n pluginMap[pluginId] = entry.module;\n }\n }\n\n return pluginMap;\n}\n\n/**\n * Normalize registry entries - ensure remote URLs are properly formatted\n */\nfunction normalizeRegistry(registry: Record<string, PluginRegistryEntry>): PluginRegistry {\n const normalized: Record<string, PluginRegistryEntry> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry) {\n normalized[pluginId] = {\n ...entry,\n remote: entry.remote ? normalizeRemoteUrl(entry.remote) : undefined,\n };\n } else {\n normalized[pluginId] = {\n ...entry,\n remote: normalizeRemoteUrl(entry.remote),\n };\n }\n }\n\n return normalized as PluginRegistry;\n}\n\n/**\n * Creates a plugin runtime with support for both module and remote plugin entries.\n *\n * @example\n * ```typescript\n * // With module entries (types inferred automatically)\n * const runtime = createPluginRuntime({\n * registry: {\n * telegram: { module: TelegramPlugin },\n * gopher: { remote: \"https://cdn.example.com/gopher/remoteEntry.js\" }\n * },\n * secrets: { API_KEY: \"...\" }\n * });\n *\n * // Types are automatically inferred from module entries!\n * const { router } = await runtime.usePlugin(\"telegram\", config);\n * ```\n */\nexport function createPluginRuntime<TRegistry extends Record<string, PluginRegistryEntry>>(\n config: PluginRuntimeConfig<TRegistry>,\n): PluginRuntime<InferRegistryFromEntries<TRegistry>> {\n const secrets = config.secrets || {};\n const normalizedRegistry = normalizeRegistry(config.registry);\n const pluginMap = extractPluginMap(config.registry);\n\n const layer = PluginService.Live(normalizedRegistry, secrets, pluginMap);\n const runtime = ManagedRuntime.make(layer);\n\n return new PluginRuntime(runtime, normalizedRegistry) as PluginRuntime<\n InferRegistryFromEntries<TRegistry>\n >;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/runtime/index.ts"],"sourcesContent":["import { createRouterClient } from \"@orpc/server\";\nimport { Cause, Effect, Exit, Hash, ManagedRuntime, Option } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InferRegistryFromEntries,\n InitializedPlugin,\n LoadedPlugin,\n PluginConfigInput,\n PluginInstance,\n PluginRegistry,\n PluginRegistryEntry,\n PluginRouterType,\n PluginRuntimeConfig,\n RegisteredPlugin,\n RegisteredPlugins,\n UsePluginResult,\n} from \"../types\";\nimport { PluginRuntimeError } from \"./errors\";\nimport { PluginService } from \"./services/plugin.service\";\n\nexport class PluginRuntime<R = RegisteredPlugins> {\n readonly __registryType?: R;\n\n private pluginCache = new Map<\n string,\n Effect.Effect<InitializedPlugin<AnyPlugin>, PluginRuntimeError>\n >();\n\n constructor(\n private runtime: ManagedRuntime.ManagedRuntime<PluginService, never>,\n private registry: PluginRegistry,\n ) {}\n\n private generateCacheKey(pluginId: string, config: unknown): string {\n const configHash = Hash.structure(config as object).toString();\n return `${pluginId}:${configHash}`;\n }\n\n private validatePluginId(pluginId: string): Effect.Effect<string, PluginRuntimeError> {\n if (!(pluginId in this.registry)) {\n return Effect.fail(\n new PluginRuntimeError({\n pluginId: String(pluginId),\n operation: \"validate-plugin-id\",\n cause: new Error(`Plugin ID '${String(pluginId)}' not found in registry.`),\n retryable: false,\n }),\n );\n }\n return Effect.succeed(String(pluginId));\n }\n\n private async runPromise<A, E>(effect: Effect.Effect<A, E, PluginService>): Promise<A> {\n const exit = await this.runtime.runPromiseExit(effect);\n\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n if (Option.isSome(error)) {\n throw error.value;\n }\n throw Cause.squash(exit.cause);\n }\n\n return exit.value;\n }\n\n async usePlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n plugins?: Record<string, unknown>,\n ): Promise<UsePluginResult<K, R>> {\n const cacheKey = this.generateCacheKey(pluginId, { ...config, __plugins: plugins ?? {} });\n\n let cachedPlugin = this.pluginCache.get(cacheKey);\n if (!cachedPlugin) {\n const operation = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const validatedId = yield* this.validatePluginId(pluginId);\n\n // Load → Instantiate → Initialize\n const ctor = yield* pluginService.loadPlugin(validatedId);\n const instance = yield* pluginService.instantiatePlugin(pluginId, ctor);\n const initialized = yield* pluginService.initializePlugin(instance, config, plugins);\n\n return initialized;\n }).pipe(Effect.provide(this.runtime));\n\n cachedPlugin = Effect.cached(operation).pipe(Effect.flatten);\n this.pluginCache.set(cacheKey, cachedPlugin);\n }\n\n const initialized = await this.runPromise(cachedPlugin);\n\n // Create client factory that accepts request context\n const createClient = (context?: any) => {\n const router = initialized.plugin.createRouter(initialized.context);\n return createRouterClient(router, { context: context ?? {} });\n };\n\n return {\n createClient: createClient as any,\n router: initialized.plugin.createRouter(initialized.context) as PluginRouterType<R[K]>,\n metadata: initialized.metadata,\n initialized: initialized as InitializedPlugin<RegisteredPlugin<K, R>>,\n } as UsePluginResult<K, R>;\n }\n\n async loadPlugin<K extends keyof R & string>(\n pluginId: K,\n ): Promise<LoadedPlugin<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.loadPlugin(pluginId);\n });\n return this.runPromise(effect) as Promise<LoadedPlugin<RegisteredPlugin<K, R>>>;\n }\n\n async instantiatePlugin<K extends keyof R & string>(\n pluginId: K,\n loadedPlugin: LoadedPlugin<RegisteredPlugin<K, R>>,\n ): Promise<PluginInstance<RegisteredPlugin<K, R>>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.instantiatePlugin(pluginId, loadedPlugin);\n });\n return this.runPromise(effect) as Promise<PluginInstance<RegisteredPlugin<K, R>>>;\n }\n\n async initializePlugin<T extends AnyPlugin>(\n instance: PluginInstance<T>,\n config: any,\n plugins?: Record<string, unknown>,\n ): Promise<InitializedPlugin<T>> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n return yield* pluginService.initializePlugin(instance, config, plugins);\n });\n return this.runPromise(effect);\n }\n\n async shutdown(): Promise<void> {\n const effect = Effect.gen(function* () {\n const pluginService = yield* PluginService;\n yield* pluginService.cleanup();\n });\n return this.runPromise(effect);\n }\n\n async evictPlugin<K extends keyof R & string>(\n pluginId: K,\n config: PluginConfigInput<R[K]>,\n ): Promise<void> {\n const cacheKey = this.generateCacheKey(pluginId, config);\n\n const effect = Effect.gen(this, function* () {\n const pluginService = yield* PluginService;\n const cachedPlugin = this.pluginCache.get(cacheKey);\n\n if (cachedPlugin) {\n this.pluginCache.delete(cacheKey);\n\n const pluginResult = yield* cachedPlugin.pipe(Effect.catchAll(() => Effect.succeed(null)));\n\n if (pluginResult) {\n yield* pluginService\n .shutdownPlugin(pluginResult)\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown evicted plugin ${pluginId}`, error),\n ),\n );\n }\n }\n }).pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Plugin eviction failed for ${pluginId}`, error),\n ),\n );\n\n return this.runPromise(effect);\n }\n}\n\n/**\n * Normalizes a remote URL to ensure it points to remoteEntry.js\n * If the URL doesn't end with a file extension, appends /remoteEntry.js\n */\nfunction normalizeRemoteUrl(url: string): string {\n if (!url) return url;\n if (url.endsWith(\".js\") || url.endsWith(\".json\")) return url;\n return `${url.endsWith(\"/\") ? url.slice(0, -1) : url}/remoteEntry.js`;\n}\n\n/**\n * Extract plugin map (module constructors) from registry entries\n */\nfunction extractPluginMap(\n registry: Record<string, PluginRegistryEntry>,\n): Record<string, AnyPluginConstructor> {\n const pluginMap: Record<string, AnyPluginConstructor> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry && entry.module) {\n pluginMap[pluginId] = entry.module;\n }\n }\n\n return pluginMap;\n}\n\n/**\n * Normalize registry entries - ensure remote URLs are properly formatted\n */\nfunction normalizeRegistry(registry: Record<string, PluginRegistryEntry>): PluginRegistry {\n const normalized: Record<string, PluginRegistryEntry> = {};\n\n for (const [pluginId, entry] of Object.entries(registry)) {\n if (\"module\" in entry) {\n normalized[pluginId] = {\n ...entry,\n remote: entry.remote ? normalizeRemoteUrl(entry.remote) : undefined,\n };\n } else {\n normalized[pluginId] = {\n ...entry,\n remote: normalizeRemoteUrl(entry.remote),\n };\n }\n }\n\n return normalized as PluginRegistry;\n}\n\n/**\n * Creates a plugin runtime with support for both module and remote plugin entries.\n *\n * @example\n * ```typescript\n * // With module entries (types inferred automatically)\n * const runtime = createPluginRuntime({\n * registry: {\n * telegram: { module: TelegramPlugin },\n * gopher: { remote: \"https://cdn.example.com/gopher/remoteEntry.js\" }\n * },\n * secrets: { API_KEY: \"...\" }\n * });\n *\n * // Types are automatically inferred from module entries!\n * const { router } = await runtime.usePlugin(\"telegram\", config);\n * ```\n */\nexport function createPluginRuntime<TRegistry extends Record<string, PluginRegistryEntry>>(\n config: PluginRuntimeConfig<TRegistry>,\n): PluginRuntime<InferRegistryFromEntries<TRegistry>> {\n const secrets = config.secrets || {};\n const normalizedRegistry = normalizeRegistry(config.registry);\n const pluginMap = extractPluginMap(config.registry);\n\n const layer = PluginService.Live(normalizedRegistry, secrets, pluginMap);\n const runtime = ManagedRuntime.make(layer);\n\n return new PluginRuntime(runtime, normalizedRegistry) as PluginRuntime<\n InferRegistryFromEntries<TRegistry>\n >;\n}\n"],"mappings":";;;;;;AAqBA,IAAa,gBAAb,MAAkD;CAChD,AAAS;CAET,AAAQ,8BAAc,IAAI,KAGvB;CAEH,YACE,AAAQ,SACR,AAAQ,UACR;EAFQ;EACA;;CAGV,AAAQ,iBAAiB,UAAkB,QAAyB;AAElE,SAAO,GAAG,SAAS,GADA,KAAK,UAAU,OAAiB,CAAC,UAAU;;CAIhE,AAAQ,iBAAiB,UAA6D;AACpF,MAAI,EAAE,YAAY,KAAK,UACrB,QAAO,OAAO,KACZ,IAAI,mBAAmB;GACrB,UAAU,OAAO,SAAS;GAC1B,WAAW;GACX,uBAAO,IAAI,MAAM,cAAc,OAAO,SAAS,CAAC,0BAA0B;GAC1E,WAAW;GACZ,CAAC,CACH;AAEH,SAAO,OAAO,QAAQ,OAAO,SAAS,CAAC;;CAGzC,MAAc,WAAiB,QAAwD;EACrF,MAAM,OAAO,MAAM,KAAK,QAAQ,eAAe,OAAO;AAEtD,MAAI,KAAK,UAAU,KAAK,EAAE;GACxB,MAAM,QAAQ,MAAM,cAAc,KAAK,MAAM;AAC7C,OAAI,OAAO,OAAO,MAAM,CACtB,OAAM,MAAM;AAEd,SAAM,MAAM,OAAO,KAAK,MAAM;;AAGhC,SAAO,KAAK;;CAGd,MAAM,UACJ,UACA,QACA,SACgC;EAChC,MAAM,WAAW,KAAK,iBAAiB,UAAU;GAAE,GAAG;GAAQ,WAAW,WAAW,EAAE;GAAE,CAAC;EAEzF,IAAI,eAAe,KAAK,YAAY,IAAI,SAAS;AACjD,MAAI,CAAC,cAAc;GACjB,MAAM,YAAY,OAAO,IAAI,MAAM,aAAa;IAC9C,MAAM,gBAAgB,OAAO;IAC7B,MAAM,cAAc,OAAO,KAAK,iBAAiB,SAAS;IAG1D,MAAM,OAAO,OAAO,cAAc,WAAW,YAAY;IACzD,MAAM,WAAW,OAAO,cAAc,kBAAkB,UAAU,KAAK;AAGvE,WAFoB,OAAO,cAAc,iBAAiB,UAAU,QAAQ,QAAQ;KAGpF,CAAC,KAAK,OAAO,QAAQ,KAAK,QAAQ,CAAC;AAErC,kBAAe,OAAO,OAAO,UAAU,CAAC,KAAK,OAAO,QAAQ;AAC5D,QAAK,YAAY,IAAI,UAAU,aAAa;;EAG9C,MAAM,cAAc,MAAM,KAAK,WAAW,aAAa;EAGvD,MAAM,gBAAgB,YAAkB;AAEtC,UAAO,mBADQ,YAAY,OAAO,aAAa,YAAY,QAAQ,EACjC,EAAE,SAAS,WAAW,EAAE,EAAE,CAAC;;AAG/D,SAAO;GACS;GACd,QAAQ,YAAY,OAAO,aAAa,YAAY,QAAQ;GAC5D,UAAU,YAAY;GACT;GACd;;CAGH,MAAM,WACJ,UAC+C;EAC/C,MAAM,SAAS,OAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAO,eACD,WAAW,SAAS;IAChD;AACF,SAAO,KAAK,WAAW,OAAO;;CAGhC,MAAM,kBACJ,UACA,cACiD;EACjD,MAAM,SAAS,OAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAO,eACD,kBAAkB,UAAU,aAAa;IACrE;AACF,SAAO,KAAK,WAAW,OAAO;;CAGhC,MAAM,iBACJ,UACA,QACA,SAC+B;EAC/B,MAAM,SAAS,OAAO,IAAI,aAAa;AAErC,UAAO,QADe,OAAO,eACD,iBAAiB,UAAU,QAAQ,QAAQ;IACvE;AACF,SAAO,KAAK,WAAW,OAAO;;CAGhC,MAAM,WAA0B;EAC9B,MAAM,SAAS,OAAO,IAAI,aAAa;AAErC,WADsB,OAAO,eACR,SAAS;IAC9B;AACF,SAAO,KAAK,WAAW,OAAO;;CAGhC,MAAM,YACJ,UACA,QACe;EACf,MAAM,WAAW,KAAK,iBAAiB,UAAU,OAAO;EAExD,MAAM,SAAS,OAAO,IAAI,MAAM,aAAa;GAC3C,MAAM,gBAAgB,OAAO;GAC7B,MAAM,eAAe,KAAK,YAAY,IAAI,SAAS;AAEnD,OAAI,cAAc;AAChB,SAAK,YAAY,OAAO,SAAS;IAEjC,MAAM,eAAe,OAAO,aAAa,KAAK,OAAO,eAAe,OAAO,QAAQ,KAAK,CAAC,CAAC;AAE1F,QAAI,aACF,QAAO,cACJ,eAAe,aAAa,CAC5B,KACC,OAAO,UAAU,UACf,OAAO,WAAW,qCAAqC,YAAY,MAAM,CAC1E,CACF;;IAGP,CAAC,KACD,OAAO,UAAU,UACf,OAAO,WAAW,8BAA8B,YAAY,MAAM,CACnE,CACF;AAED,SAAO,KAAK,WAAW,OAAO;;;;;;;AAQlC,SAAS,mBAAmB,KAAqB;AAC/C,KAAI,CAAC,IAAK,QAAO;AACjB,KAAI,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,QAAQ,CAAE,QAAO;AACzD,QAAO,GAAG,IAAI,SAAS,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI;;;;;AAMvD,SAAS,iBACP,UACsC;CACtC,MAAM,YAAkD,EAAE;AAE1D,MAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,SAAS,CACtD,KAAI,YAAY,SAAS,MAAM,OAC7B,WAAU,YAAY,MAAM;AAIhC,QAAO;;;;;AAMT,SAAS,kBAAkB,UAA+D;CACxF,MAAM,aAAkD,EAAE;AAE1D,MAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,SAAS,CACtD,KAAI,YAAY,MACd,YAAW,YAAY;EACrB,GAAG;EACH,QAAQ,MAAM,SAAS,mBAAmB,MAAM,OAAO,GAAG;EAC3D;KAED,YAAW,YAAY;EACrB,GAAG;EACH,QAAQ,mBAAmB,MAAM,OAAO;EACzC;AAIL,QAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,oBACd,QACoD;CACpD,MAAM,UAAU,OAAO,WAAW,EAAE;CACpC,MAAM,qBAAqB,kBAAkB,OAAO,SAAS;CAC7D,MAAM,YAAY,iBAAiB,OAAO,SAAS;CAEnD,MAAM,QAAQ,cAAc,KAAK,oBAAoB,SAAS,UAAU;AAGxE,QAAO,IAAI,cAFK,eAAe,KAAK,MAAM,EAER,mBAAmB"}
@@ -12,7 +12,7 @@ function getInstalledPackageVersion(packageName, fallbackRange) {
12
12
  return match ? match[0] : fallbackRange.replace(/^[\^~>=<\s]+/, "");
13
13
  }
14
14
  }
15
- const PLUGIN_VERSION = "2.3.0";
15
+ const PLUGIN_VERSION = "2.4.0";
16
16
  const SHARE_CONFIG = {
17
17
  singleton: true,
18
18
  requiredVersion: false,
@@ -10,7 +10,7 @@ function getInstalledPackageVersion(packageName, fallbackRange) {
10
10
  return match ? match[0] : fallbackRange.replace(/^[\^~>=<\s]+/, "");
11
11
  }
12
12
  }
13
- const PLUGIN_VERSION = "2.3.0";
13
+ const PLUGIN_VERSION = "2.4.0";
14
14
  const SHARE_CONFIG = {
15
15
  singleton: true,
16
16
  requiredVersion: false,
@@ -22,9 +22,12 @@ var PluginLifecycleService = class extends effect.Effect.Service()("PluginLifecy
22
22
  }),
23
23
  cleanup: () => effect.Effect.gen(function* () {
24
24
  const plugins = yield* effect.Ref.get(activePlugins);
25
- yield* effect.Effect.forEach(plugins, (plugin) => plugin.plugin.shutdown().pipe(effect.Effect.mapError((error) => require_errors.toPluginRuntimeError(error, plugin.plugin.id, void 0, "cleanup-shutdown", false)), effect.Effect.catchAll((error) => effect.Effect.logError(`Failed to shutdown plugin ${plugin.plugin.id} during cleanup`, error, { pluginId: plugin.plugin.id }))), { concurrency: "unbounded" });
25
+ yield* effect.Effect.forEach(plugins, (plugin) => effect.Effect.gen(function* () {
26
+ yield* plugin.plugin.shutdown().pipe(effect.Effect.catchAll((error) => effect.Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error)));
27
+ yield* effect.Scope.close(plugin.scope, effect.Exit.succeed(void 0)).pipe(effect.Effect.catchAll((error) => effect.Effect.logWarning(`Failed to close scope for plugin ${plugin.plugin.id}`, error)));
28
+ }), { concurrency: "unbounded" });
26
29
  yield* effect.Ref.set(activePlugins, /* @__PURE__ */ new Set());
27
- }).pipe(effect.Effect.catchAll(() => effect.Effect.void))
30
+ }).pipe(effect.Effect.catchAll((error) => effect.Effect.logWarning("Plugin cleanup failed", error)))
28
31
  };
29
32
  }) }) {};
30
33
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-lifecycle.service.cjs","names":["Effect","Ref","toPluginRuntimeError"],"sources":["../../../src/runtime/services/plugin-lifecycle.service.ts"],"sourcesContent":["import { Effect, Ref } from \"effect\";\nimport type { AnyPlugin, InitializedPlugin } from \"../../types\";\nimport { toPluginRuntimeError } from \"../errors\";\n\nexport class PluginLifecycleService extends Effect.Service<PluginLifecycleService>()(\n \"PluginLifecycleService\",\n {\n effect: Effect.gen(function* () {\n const activePlugins = yield* Ref.make(new Set<InitializedPlugin<AnyPlugin>>());\n\n return {\n register: <T extends AnyPlugin>(plugin: InitializedPlugin<T>) =>\n Ref.update(activePlugins, (plugins) =>\n new Set(plugins).add(plugin as InitializedPlugin<AnyPlugin>),\n ),\n\n unregister: (plugin: InitializedPlugin<AnyPlugin>) =>\n Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n }),\n\n shutdown: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Remove from active plugins\n yield* Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n });\n\n // Shutdown the plugin\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"shutdown-plugin\",\n false,\n ),\n ),\n );\n }),\n\n cleanup: () =>\n Effect.gen(function* () {\n const plugins = yield* Ref.get(activePlugins);\n\n // Shutdown all active plugins concurrently\n yield* Effect.forEach(\n plugins,\n (plugin) =>\n plugin.plugin.shutdown().pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"cleanup-shutdown\",\n false,\n ),\n ),\n Effect.catchAll((error) =>\n Effect.logError(\n `Failed to shutdown plugin ${plugin.plugin.id} during cleanup`,\n error,\n { pluginId: plugin.plugin.id },\n ),\n ),\n ),\n { concurrency: \"unbounded\" },\n );\n\n // Clear the active plugins set\n yield* Ref.set(activePlugins, new Set());\n }).pipe(\n Effect.catchAll(() => Effect.void), // Convert errors to void for cleanup\n ),\n };\n }),\n },\n) {}\n"],"mappings":";;;;;AAIA,IAAa,yBAAb,cAA4CA,cAAO,SAAiC,CAClF,0BACA,EACE,QAAQA,cAAO,IAAI,aAAa;CAC9B,MAAM,gBAAgB,OAAOC,WAAI,qBAAK,IAAI,KAAmC,CAAC;AAE9E,QAAO;EACL,WAAgC,WAC9BA,WAAI,OAAO,gBAAgB,YACzB,IAAI,IAAI,QAAQ,CAAC,IAAI,OAAuC,CAC7D;EAEH,aAAa,WACXA,WAAI,OAAO,gBAAgB,YAAY;GACrC,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,UAAO,OAAO,OAAO;AACrB,UAAO;IACP;EAEJ,WAAW,WACTD,cAAO,IAAI,aAAa;AAEtB,UAAOC,WAAI,OAAO,gBAAgB,YAAY;IAC5C,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,WAAO,OAAO,OAAO;AACrB,WAAO;KACP;AAGF,UAAO,OAAO,OACX,UAAU,CACV,KACCD,cAAO,UAAU,UACfE,oCACE,OACA,OAAO,OAAO,IACd,QACA,mBACA,MACD,CACF,CACF;IACH;EAEJ,eACEF,cAAO,IAAI,aAAa;GACtB,MAAM,UAAU,OAAOC,WAAI,IAAI,cAAc;AAG7C,UAAOD,cAAO,QACZ,UACC,WACC,OAAO,OAAO,UAAU,CAAC,KACvBA,cAAO,UAAU,UACfE,oCACE,OACA,OAAO,OAAO,IACd,QACA,oBACA,MACD,CACF,EACDF,cAAO,UAAU,UACfA,cAAO,SACL,6BAA6B,OAAO,OAAO,GAAG,kBAC9C,OACA,EAAE,UAAU,OAAO,OAAO,IAAI,CAC/B,CACF,CACF,EACH,EAAE,aAAa,aAAa,CAC7B;AAGD,UAAOC,WAAI,IAAI,+BAAe,IAAI,KAAK,CAAC;IACxC,CAAC,KACDD,cAAO,eAAeA,cAAO,KAAK,CACnC;EACJ;EACD,EACH,CACF,CAAC"}
1
+ {"version":3,"file":"plugin-lifecycle.service.cjs","names":["Effect","Ref","toPluginRuntimeError","Scope","Exit"],"sources":["../../../src/runtime/services/plugin-lifecycle.service.ts"],"sourcesContent":["import { Effect, Exit, Ref, Scope } from \"effect\";\nimport type { AnyPlugin, InitializedPlugin } from \"../../types\";\nimport { toPluginRuntimeError } from \"../errors\";\n\nexport class PluginLifecycleService extends Effect.Service<PluginLifecycleService>()(\n \"PluginLifecycleService\",\n {\n effect: Effect.gen(function* () {\n const activePlugins = yield* Ref.make(new Set<InitializedPlugin<AnyPlugin>>());\n\n return {\n register: <T extends AnyPlugin>(plugin: InitializedPlugin<T>) =>\n Ref.update(activePlugins, (plugins) =>\n new Set(plugins).add(plugin as InitializedPlugin<AnyPlugin>),\n ),\n\n unregister: (plugin: InitializedPlugin<AnyPlugin>) =>\n Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n }),\n\n shutdown: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Remove from active plugins\n yield* Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n });\n\n // Shutdown the plugin\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"shutdown-plugin\",\n false,\n ),\n ),\n );\n }),\n\n cleanup: () =>\n Effect.gen(function* () {\n const plugins = yield* Ref.get(activePlugins);\n\n yield* Effect.forEach(\n plugins,\n (plugin) =>\n Effect.gen(function* () {\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),\n ),\n );\n yield* Scope.close(plugin.scope, Exit.succeed(undefined)).pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(\n `Failed to close scope for plugin ${plugin.plugin.id}`,\n error,\n ),\n ),\n );\n }),\n { concurrency: \"unbounded\" },\n );\n\n yield* Ref.set(activePlugins, new Set());\n }).pipe(Effect.catchAll((error) => Effect.logWarning(\"Plugin cleanup failed\", error))),\n };\n }),\n },\n) {}\n"],"mappings":";;;;;AAIA,IAAa,yBAAb,cAA4CA,cAAO,SAAiC,CAClF,0BACA,EACE,QAAQA,cAAO,IAAI,aAAa;CAC9B,MAAM,gBAAgB,OAAOC,WAAI,qBAAK,IAAI,KAAmC,CAAC;AAE9E,QAAO;EACL,WAAgC,WAC9BA,WAAI,OAAO,gBAAgB,YACzB,IAAI,IAAI,QAAQ,CAAC,IAAI,OAAuC,CAC7D;EAEH,aAAa,WACXA,WAAI,OAAO,gBAAgB,YAAY;GACrC,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,UAAO,OAAO,OAAO;AACrB,UAAO;IACP;EAEJ,WAAW,WACTD,cAAO,IAAI,aAAa;AAEtB,UAAOC,WAAI,OAAO,gBAAgB,YAAY;IAC5C,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,WAAO,OAAO,OAAO;AACrB,WAAO;KACP;AAGF,UAAO,OAAO,OACX,UAAU,CACV,KACCD,cAAO,UAAU,UACfE,oCACE,OACA,OAAO,OAAO,IACd,QACA,mBACA,MACD,CACF,CACF;IACH;EAEJ,eACEF,cAAO,IAAI,aAAa;GACtB,MAAM,UAAU,OAAOC,WAAI,IAAI,cAAc;AAE7C,UAAOD,cAAO,QACZ,UACC,WACCA,cAAO,IAAI,aAAa;AACtB,WAAO,OAAO,OACX,UAAU,CACV,KACCA,cAAO,UAAU,UACfA,cAAO,WAAW,6BAA6B,OAAO,OAAO,MAAM,MAAM,CAC1E,CACF;AACH,WAAOG,aAAM,MAAM,OAAO,OAAOC,YAAK,QAAQ,OAAU,CAAC,CAAC,KACxDJ,cAAO,UAAU,UACfA,cAAO,WACL,oCAAoC,OAAO,OAAO,MAClD,MACD,CACF,CACF;KACD,EACJ,EAAE,aAAa,aAAa,CAC7B;AAED,UAAOC,WAAI,IAAI,+BAAe,IAAI,KAAK,CAAC;IACxC,CAAC,KAAKD,cAAO,UAAU,UAAUA,cAAO,WAAW,yBAAyB,MAAM,CAAC,CAAC;EACzF;EACD,EACH,CACF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { toPluginRuntimeError } from "../errors.mjs";
2
- import { Effect, Ref } from "effect";
2
+ import { Effect, Exit, Ref, Scope } from "effect";
3
3
 
4
4
  //#region src/runtime/services/plugin-lifecycle.service.ts
5
5
  var PluginLifecycleService = class extends Effect.Service()("PluginLifecycleService", { effect: Effect.gen(function* () {
@@ -21,9 +21,12 @@ var PluginLifecycleService = class extends Effect.Service()("PluginLifecycleServ
21
21
  }),
22
22
  cleanup: () => Effect.gen(function* () {
23
23
  const plugins = yield* Ref.get(activePlugins);
24
- yield* Effect.forEach(plugins, (plugin) => plugin.plugin.shutdown().pipe(Effect.mapError((error) => toPluginRuntimeError(error, plugin.plugin.id, void 0, "cleanup-shutdown", false)), Effect.catchAll((error) => Effect.logError(`Failed to shutdown plugin ${plugin.plugin.id} during cleanup`, error, { pluginId: plugin.plugin.id }))), { concurrency: "unbounded" });
24
+ yield* Effect.forEach(plugins, (plugin) => Effect.gen(function* () {
25
+ yield* plugin.plugin.shutdown().pipe(Effect.catchAll((error) => Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error)));
26
+ yield* Scope.close(plugin.scope, Exit.succeed(void 0)).pipe(Effect.catchAll((error) => Effect.logWarning(`Failed to close scope for plugin ${plugin.plugin.id}`, error)));
27
+ }), { concurrency: "unbounded" });
25
28
  yield* Ref.set(activePlugins, /* @__PURE__ */ new Set());
26
- }).pipe(Effect.catchAll(() => Effect.void))
29
+ }).pipe(Effect.catchAll((error) => Effect.logWarning("Plugin cleanup failed", error)))
27
30
  };
28
31
  }) }) {};
29
32
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-lifecycle.service.mjs","names":[],"sources":["../../../src/runtime/services/plugin-lifecycle.service.ts"],"sourcesContent":["import { Effect, Ref } from \"effect\";\nimport type { AnyPlugin, InitializedPlugin } from \"../../types\";\nimport { toPluginRuntimeError } from \"../errors\";\n\nexport class PluginLifecycleService extends Effect.Service<PluginLifecycleService>()(\n \"PluginLifecycleService\",\n {\n effect: Effect.gen(function* () {\n const activePlugins = yield* Ref.make(new Set<InitializedPlugin<AnyPlugin>>());\n\n return {\n register: <T extends AnyPlugin>(plugin: InitializedPlugin<T>) =>\n Ref.update(activePlugins, (plugins) =>\n new Set(plugins).add(plugin as InitializedPlugin<AnyPlugin>),\n ),\n\n unregister: (plugin: InitializedPlugin<AnyPlugin>) =>\n Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n }),\n\n shutdown: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Remove from active plugins\n yield* Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n });\n\n // Shutdown the plugin\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"shutdown-plugin\",\n false,\n ),\n ),\n );\n }),\n\n cleanup: () =>\n Effect.gen(function* () {\n const plugins = yield* Ref.get(activePlugins);\n\n // Shutdown all active plugins concurrently\n yield* Effect.forEach(\n plugins,\n (plugin) =>\n plugin.plugin.shutdown().pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"cleanup-shutdown\",\n false,\n ),\n ),\n Effect.catchAll((error) =>\n Effect.logError(\n `Failed to shutdown plugin ${plugin.plugin.id} during cleanup`,\n error,\n { pluginId: plugin.plugin.id },\n ),\n ),\n ),\n { concurrency: \"unbounded\" },\n );\n\n // Clear the active plugins set\n yield* Ref.set(activePlugins, new Set());\n }).pipe(\n Effect.catchAll(() => Effect.void), // Convert errors to void for cleanup\n ),\n };\n }),\n },\n) {}\n"],"mappings":";;;;AAIA,IAAa,yBAAb,cAA4C,OAAO,SAAiC,CAClF,0BACA,EACE,QAAQ,OAAO,IAAI,aAAa;CAC9B,MAAM,gBAAgB,OAAO,IAAI,qBAAK,IAAI,KAAmC,CAAC;AAE9E,QAAO;EACL,WAAgC,WAC9B,IAAI,OAAO,gBAAgB,YACzB,IAAI,IAAI,QAAQ,CAAC,IAAI,OAAuC,CAC7D;EAEH,aAAa,WACX,IAAI,OAAO,gBAAgB,YAAY;GACrC,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,UAAO,OAAO,OAAO;AACrB,UAAO;IACP;EAEJ,WAAW,WACT,OAAO,IAAI,aAAa;AAEtB,UAAO,IAAI,OAAO,gBAAgB,YAAY;IAC5C,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,WAAO,OAAO,OAAO;AACrB,WAAO;KACP;AAGF,UAAO,OAAO,OACX,UAAU,CACV,KACC,OAAO,UAAU,UACf,qBACE,OACA,OAAO,OAAO,IACd,QACA,mBACA,MACD,CACF,CACF;IACH;EAEJ,eACE,OAAO,IAAI,aAAa;GACtB,MAAM,UAAU,OAAO,IAAI,IAAI,cAAc;AAG7C,UAAO,OAAO,QACZ,UACC,WACC,OAAO,OAAO,UAAU,CAAC,KACvB,OAAO,UAAU,UACf,qBACE,OACA,OAAO,OAAO,IACd,QACA,oBACA,MACD,CACF,EACD,OAAO,UAAU,UACf,OAAO,SACL,6BAA6B,OAAO,OAAO,GAAG,kBAC9C,OACA,EAAE,UAAU,OAAO,OAAO,IAAI,CAC/B,CACF,CACF,EACH,EAAE,aAAa,aAAa,CAC7B;AAGD,UAAO,IAAI,IAAI,+BAAe,IAAI,KAAK,CAAC;IACxC,CAAC,KACD,OAAO,eAAe,OAAO,KAAK,CACnC;EACJ;EACD,EACH,CACF,CAAC"}
1
+ {"version":3,"file":"plugin-lifecycle.service.mjs","names":[],"sources":["../../../src/runtime/services/plugin-lifecycle.service.ts"],"sourcesContent":["import { Effect, Exit, Ref, Scope } from \"effect\";\nimport type { AnyPlugin, InitializedPlugin } from \"../../types\";\nimport { toPluginRuntimeError } from \"../errors\";\n\nexport class PluginLifecycleService extends Effect.Service<PluginLifecycleService>()(\n \"PluginLifecycleService\",\n {\n effect: Effect.gen(function* () {\n const activePlugins = yield* Ref.make(new Set<InitializedPlugin<AnyPlugin>>());\n\n return {\n register: <T extends AnyPlugin>(plugin: InitializedPlugin<T>) =>\n Ref.update(activePlugins, (plugins) =>\n new Set(plugins).add(plugin as InitializedPlugin<AnyPlugin>),\n ),\n\n unregister: (plugin: InitializedPlugin<AnyPlugin>) =>\n Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n }),\n\n shutdown: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Remove from active plugins\n yield* Ref.update(activePlugins, (plugins) => {\n const newSet = new Set(plugins);\n newSet.delete(plugin);\n return newSet;\n });\n\n // Shutdown the plugin\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.mapError((error) =>\n toPluginRuntimeError(\n error,\n plugin.plugin.id,\n undefined,\n \"shutdown-plugin\",\n false,\n ),\n ),\n );\n }),\n\n cleanup: () =>\n Effect.gen(function* () {\n const plugins = yield* Ref.get(activePlugins);\n\n yield* Effect.forEach(\n plugins,\n (plugin) =>\n Effect.gen(function* () {\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),\n ),\n );\n yield* Scope.close(plugin.scope, Exit.succeed(undefined)).pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(\n `Failed to close scope for plugin ${plugin.plugin.id}`,\n error,\n ),\n ),\n );\n }),\n { concurrency: \"unbounded\" },\n );\n\n yield* Ref.set(activePlugins, new Set());\n }).pipe(Effect.catchAll((error) => Effect.logWarning(\"Plugin cleanup failed\", error))),\n };\n }),\n },\n) {}\n"],"mappings":";;;;AAIA,IAAa,yBAAb,cAA4C,OAAO,SAAiC,CAClF,0BACA,EACE,QAAQ,OAAO,IAAI,aAAa;CAC9B,MAAM,gBAAgB,OAAO,IAAI,qBAAK,IAAI,KAAmC,CAAC;AAE9E,QAAO;EACL,WAAgC,WAC9B,IAAI,OAAO,gBAAgB,YACzB,IAAI,IAAI,QAAQ,CAAC,IAAI,OAAuC,CAC7D;EAEH,aAAa,WACX,IAAI,OAAO,gBAAgB,YAAY;GACrC,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,UAAO,OAAO,OAAO;AACrB,UAAO;IACP;EAEJ,WAAW,WACT,OAAO,IAAI,aAAa;AAEtB,UAAO,IAAI,OAAO,gBAAgB,YAAY;IAC5C,MAAM,SAAS,IAAI,IAAI,QAAQ;AAC/B,WAAO,OAAO,OAAO;AACrB,WAAO;KACP;AAGF,UAAO,OAAO,OACX,UAAU,CACV,KACC,OAAO,UAAU,UACf,qBACE,OACA,OAAO,OAAO,IACd,QACA,mBACA,MACD,CACF,CACF;IACH;EAEJ,eACE,OAAO,IAAI,aAAa;GACtB,MAAM,UAAU,OAAO,IAAI,IAAI,cAAc;AAE7C,UAAO,OAAO,QACZ,UACC,WACC,OAAO,IAAI,aAAa;AACtB,WAAO,OAAO,OACX,UAAU,CACV,KACC,OAAO,UAAU,UACf,OAAO,WAAW,6BAA6B,OAAO,OAAO,MAAM,MAAM,CAC1E,CACF;AACH,WAAO,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,OAAU,CAAC,CAAC,KACxD,OAAO,UAAU,UACf,OAAO,WACL,oCAAoC,OAAO,OAAO,MAClD,MACD,CACF,CACF;KACD,EACJ,EAAE,aAAa,aAAa,CAC7B;AAED,UAAO,IAAI,IAAI,+BAAe,IAAI,KAAK,CAAC;IACxC,CAAC,KAAK,OAAO,UAAU,UAAU,OAAO,WAAW,yBAAyB,MAAM,CAAC,CAAC;EACzF;EACD,EACH,CACF,CAAC"}
@@ -14,7 +14,7 @@ var PluginService = class PluginService extends effect.Effect.Service()("PluginS
14
14
  instantiatePlugin: loader.instantiatePlugin,
15
15
  initializePlugin: loader.initializePlugin,
16
16
  shutdownPlugin: (plugin) => effect.Effect.gen(function* () {
17
- yield* plugin.plugin.shutdown().pipe(effect.Effect.catchAll(() => effect.Effect.void));
17
+ yield* plugin.plugin.shutdown().pipe(effect.Effect.catchAll((error) => effect.Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error)));
18
18
  yield* effect.Scope.close(plugin.scope, effect.Exit.succeed(void 0));
19
19
  yield* lifecycle.unregister(plugin);
20
20
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.service.cjs","names":["Effect","PluginLoaderService","PluginLifecycleService","Scope","Exit","Layer","PluginRegistryTag","SecretsConfigTag","PluginMapTag","ModuleFederationService","SecretsService","RegistryService"],"sources":["../../../src/runtime/services/plugin.service.ts"],"sourcesContent":["import { Effect, Exit, Layer, Scope } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InitializedPlugin,\n PluginRegistry,\n SecretsConfig,\n} from \"../../types\";\nimport { ModuleFederationService } from \"./module-federation.service\";\nimport { PluginLifecycleService } from \"./plugin-lifecycle.service\";\nimport {\n PluginLoaderService,\n PluginMapTag,\n PluginRegistryTag,\n RegistryService,\n} from \"./plugin-loader.service\";\nimport { SecretsConfigTag, SecretsService } from \"./secrets.service\";\n\nexport class PluginService extends Effect.Service<PluginService>()(\"PluginService\", {\n scoped: Effect.gen(function* () {\n const loader = yield* PluginLoaderService;\n const lifecycle = yield* PluginLifecycleService;\n\n return {\n loadPlugin: loader.loadPlugin,\n instantiatePlugin: loader.instantiatePlugin,\n initializePlugin: loader.initializePlugin,\n shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Shutdown the plugin first (graceful cleanup)\n yield* plugin.plugin.shutdown().pipe(Effect.catchAll(() => Effect.void));\n\n // Close the plugin scope to interrupt fibers and release resources\n yield* Scope.close(plugin.scope, Exit.succeed(undefined));\n\n // Unregister from lifecycle tracking\n yield* lifecycle.unregister(plugin);\n }),\n cleanup: lifecycle.cleanup,\n };\n }),\n}) {\n static Live = (\n registry: PluginRegistry,\n secrets: SecretsConfig,\n pluginMap: Record<string, AnyPluginConstructor> = {},\n ) => {\n const contextLayer = Layer.mergeAll(\n Layer.succeed(PluginRegistryTag, registry),\n Layer.succeed(SecretsConfigTag, secrets),\n Layer.succeed(PluginMapTag, pluginMap),\n );\n\n const servicesLayer = Layer.mergeAll(\n ModuleFederationService.Default,\n SecretsService.Default,\n RegistryService.Default,\n PluginLifecycleService.Default,\n ).pipe(Layer.provide(contextLayer));\n\n return PluginService.Default.pipe(\n Layer.provide(PluginLoaderService.Default),\n Layer.provide(servicesLayer),\n );\n };\n}\n"],"mappings":";;;;;;;;AAkBA,IAAa,gBAAb,MAAa,sBAAsBA,cAAO,SAAwB,CAAC,iBAAiB,EAClF,QAAQA,cAAO,IAAI,aAAa;CAC9B,MAAM,SAAS,OAAOC;CACtB,MAAM,YAAY,OAAOC;AAEzB,QAAO;EACL,YAAY,OAAO;EACnB,mBAAmB,OAAO;EAC1B,kBAAkB,OAAO;EACzB,iBAAiB,WACfF,cAAO,IAAI,aAAa;AAEtB,UAAO,OAAO,OAAO,UAAU,CAAC,KAAKA,cAAO,eAAeA,cAAO,KAAK,CAAC;AAGxE,UAAOG,aAAM,MAAM,OAAO,OAAOC,YAAK,QAAQ,OAAU,CAAC;AAGzD,UAAO,UAAU,WAAW,OAAO;IACnC;EACJ,SAAS,UAAU;EACpB;EACD,EACH,CAAC,CAAC;CACD,OAAO,QACL,UACA,SACA,YAAkD,EAAE,KACjD;EACH,MAAM,eAAeC,aAAM,SACzBA,aAAM,QAAQC,iDAAmB,SAAS,EAC1CD,aAAM,QAAQE,0CAAkB,QAAQ,EACxCF,aAAM,QAAQG,4CAAc,UAAU,CACvC;EAED,MAAM,gBAAgBH,aAAM,SAC1BI,0DAAwB,SACxBC,uCAAe,SACfC,8CAAgB,SAChBT,wDAAuB,QACxB,CAAC,KAAKG,aAAM,QAAQ,aAAa,CAAC;AAEnC,SAAO,cAAc,QAAQ,KAC3BA,aAAM,QAAQJ,kDAAoB,QAAQ,EAC1CI,aAAM,QAAQ,cAAc,CAC7B"}
1
+ {"version":3,"file":"plugin.service.cjs","names":["Effect","PluginLoaderService","PluginLifecycleService","Scope","Exit","Layer","PluginRegistryTag","SecretsConfigTag","PluginMapTag","ModuleFederationService","SecretsService","RegistryService"],"sources":["../../../src/runtime/services/plugin.service.ts"],"sourcesContent":["import { Effect, Exit, Layer, Scope } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InitializedPlugin,\n PluginRegistry,\n SecretsConfig,\n} from \"../../types\";\nimport { ModuleFederationService } from \"./module-federation.service\";\nimport { PluginLifecycleService } from \"./plugin-lifecycle.service\";\nimport {\n PluginLoaderService,\n PluginMapTag,\n PluginRegistryTag,\n RegistryService,\n} from \"./plugin-loader.service\";\nimport { SecretsConfigTag, SecretsService } from \"./secrets.service\";\n\nexport class PluginService extends Effect.Service<PluginService>()(\"PluginService\", {\n scoped: Effect.gen(function* () {\n const loader = yield* PluginLoaderService;\n const lifecycle = yield* PluginLifecycleService;\n\n return {\n loadPlugin: loader.loadPlugin,\n instantiatePlugin: loader.instantiatePlugin,\n initializePlugin: loader.initializePlugin,\n shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),\n ),\n );\n\n yield* Scope.close(plugin.scope, Exit.succeed(undefined));\n\n yield* lifecycle.unregister(plugin);\n }),\n cleanup: lifecycle.cleanup,\n };\n }),\n}) {\n static Live = (\n registry: PluginRegistry,\n secrets: SecretsConfig,\n pluginMap: Record<string, AnyPluginConstructor> = {},\n ) => {\n const contextLayer = Layer.mergeAll(\n Layer.succeed(PluginRegistryTag, registry),\n Layer.succeed(SecretsConfigTag, secrets),\n Layer.succeed(PluginMapTag, pluginMap),\n );\n\n const servicesLayer = Layer.mergeAll(\n ModuleFederationService.Default,\n SecretsService.Default,\n RegistryService.Default,\n PluginLifecycleService.Default,\n ).pipe(Layer.provide(contextLayer));\n\n return PluginService.Default.pipe(\n Layer.provide(PluginLoaderService.Default),\n Layer.provide(servicesLayer),\n );\n };\n}\n"],"mappings":";;;;;;;;AAkBA,IAAa,gBAAb,MAAa,sBAAsBA,cAAO,SAAwB,CAAC,iBAAiB,EAClF,QAAQA,cAAO,IAAI,aAAa;CAC9B,MAAM,SAAS,OAAOC;CACtB,MAAM,YAAY,OAAOC;AAEzB,QAAO;EACL,YAAY,OAAO;EACnB,mBAAmB,OAAO;EAC1B,kBAAkB,OAAO;EACzB,iBAAiB,WACfF,cAAO,IAAI,aAAa;AACtB,UAAO,OAAO,OACX,UAAU,CACV,KACCA,cAAO,UAAU,UACfA,cAAO,WAAW,6BAA6B,OAAO,OAAO,MAAM,MAAM,CAC1E,CACF;AAEH,UAAOG,aAAM,MAAM,OAAO,OAAOC,YAAK,QAAQ,OAAU,CAAC;AAEzD,UAAO,UAAU,WAAW,OAAO;IACnC;EACJ,SAAS,UAAU;EACpB;EACD,EACH,CAAC,CAAC;CACD,OAAO,QACL,UACA,SACA,YAAkD,EAAE,KACjD;EACH,MAAM,eAAeC,aAAM,SACzBA,aAAM,QAAQC,iDAAmB,SAAS,EAC1CD,aAAM,QAAQE,0CAAkB,QAAQ,EACxCF,aAAM,QAAQG,4CAAc,UAAU,CACvC;EAED,MAAM,gBAAgBH,aAAM,SAC1BI,0DAAwB,SACxBC,uCAAe,SACfC,8CAAgB,SAChBT,wDAAuB,QACxB,CAAC,KAAKG,aAAM,QAAQ,aAAa,CAAC;AAEnC,SAAO,cAAc,QAAQ,KAC3BA,aAAM,QAAQJ,kDAAoB,QAAQ,EAC1CI,aAAM,QAAQ,cAAc,CAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.service.d.cts","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"mappings":";;;;;;;;cAeiC,kBAAA;;;;;;;;;;;;;;;;;;;;;;;6BAYF,iBAAA,CAAkB,SAAA,MAAU,MAAA,CAAA,MAAA;;;;cAT9C,aAAA,SAAsB,kBAAA;EAAA,OAwB1B,IAAA,GACL,QAAA,EAAU,cAAA,EACV,OAAA,EAAS,aAAA,EACT,SAAA,GAAW,MAAA,SAAe,oBAAA,MAA0B,KAAA,CAAA,KAAA,CAAA,aAAA;AAAA"}
1
+ {"version":3,"file":"plugin.service.d.cts","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"mappings":";;;;;;;;cAeiC,kBAAA;;;;;;;;;;;;;;;;;;;;;;;6BAYF,iBAAA,CAAkB,SAAA,MAAU,MAAA,CAAA,MAAA;;;;cAT9C,aAAA,SAAsB,kBAAA;EAAA,OA2B1B,IAAA,GACL,QAAA,EAAU,cAAA,EACV,OAAA,EAAS,aAAA,EACT,SAAA,GAAW,MAAA,SAAe,oBAAA,MAA0B,KAAA,CAAA,KAAA,CAAA,aAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.service.d.mts","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"mappings":";;;;;;;;cAeiC,kBAAA;;;;;;;;;;;;;;;;;;;;;;;6BAYF,iBAAA,CAAkB,SAAA,MAAU,MAAA,CAAA,MAAA;;;;cAT9C,aAAA,SAAsB,kBAAA;EAAA,OAwB1B,IAAA,GACL,QAAA,EAAU,cAAA,EACV,OAAA,EAAS,aAAA,EACT,SAAA,GAAW,MAAA,SAAe,oBAAA,MAA0B,KAAA,CAAA,KAAA,CAAA,aAAA;AAAA"}
1
+ {"version":3,"file":"plugin.service.d.mts","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"mappings":";;;;;;;;cAeiC,kBAAA;;;;;;;;;;;;;;;;;;;;;;;6BAYF,iBAAA,CAAkB,SAAA,MAAU,MAAA,CAAA,MAAA;;;;cAT9C,aAAA,SAAsB,kBAAA;EAAA,OA2B1B,IAAA,GACL,QAAA,EAAU,cAAA,EACV,OAAA,EAAS,aAAA,EACT,SAAA,GAAW,MAAA,SAAe,oBAAA,MAA0B,KAAA,CAAA,KAAA,CAAA,aAAA;AAAA"}
@@ -13,7 +13,7 @@ var PluginService = class PluginService extends Effect.Service()("PluginService"
13
13
  instantiatePlugin: loader.instantiatePlugin,
14
14
  initializePlugin: loader.initializePlugin,
15
15
  shutdownPlugin: (plugin) => Effect.gen(function* () {
16
- yield* plugin.plugin.shutdown().pipe(Effect.catchAll(() => Effect.void));
16
+ yield* plugin.plugin.shutdown().pipe(Effect.catchAll((error) => Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error)));
17
17
  yield* Scope.close(plugin.scope, Exit.succeed(void 0));
18
18
  yield* lifecycle.unregister(plugin);
19
19
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.service.mjs","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"sourcesContent":["import { Effect, Exit, Layer, Scope } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InitializedPlugin,\n PluginRegistry,\n SecretsConfig,\n} from \"../../types\";\nimport { ModuleFederationService } from \"./module-federation.service\";\nimport { PluginLifecycleService } from \"./plugin-lifecycle.service\";\nimport {\n PluginLoaderService,\n PluginMapTag,\n PluginRegistryTag,\n RegistryService,\n} from \"./plugin-loader.service\";\nimport { SecretsConfigTag, SecretsService } from \"./secrets.service\";\n\nexport class PluginService extends Effect.Service<PluginService>()(\"PluginService\", {\n scoped: Effect.gen(function* () {\n const loader = yield* PluginLoaderService;\n const lifecycle = yield* PluginLifecycleService;\n\n return {\n loadPlugin: loader.loadPlugin,\n instantiatePlugin: loader.instantiatePlugin,\n initializePlugin: loader.initializePlugin,\n shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n // Shutdown the plugin first (graceful cleanup)\n yield* plugin.plugin.shutdown().pipe(Effect.catchAll(() => Effect.void));\n\n // Close the plugin scope to interrupt fibers and release resources\n yield* Scope.close(plugin.scope, Exit.succeed(undefined));\n\n // Unregister from lifecycle tracking\n yield* lifecycle.unregister(plugin);\n }),\n cleanup: lifecycle.cleanup,\n };\n }),\n}) {\n static Live = (\n registry: PluginRegistry,\n secrets: SecretsConfig,\n pluginMap: Record<string, AnyPluginConstructor> = {},\n ) => {\n const contextLayer = Layer.mergeAll(\n Layer.succeed(PluginRegistryTag, registry),\n Layer.succeed(SecretsConfigTag, secrets),\n Layer.succeed(PluginMapTag, pluginMap),\n );\n\n const servicesLayer = Layer.mergeAll(\n ModuleFederationService.Default,\n SecretsService.Default,\n RegistryService.Default,\n PluginLifecycleService.Default,\n ).pipe(Layer.provide(contextLayer));\n\n return PluginService.Default.pipe(\n Layer.provide(PluginLoaderService.Default),\n Layer.provide(servicesLayer),\n );\n };\n}\n"],"mappings":";;;;;;;AAkBA,IAAa,gBAAb,MAAa,sBAAsB,OAAO,SAAwB,CAAC,iBAAiB,EAClF,QAAQ,OAAO,IAAI,aAAa;CAC9B,MAAM,SAAS,OAAO;CACtB,MAAM,YAAY,OAAO;AAEzB,QAAO;EACL,YAAY,OAAO;EACnB,mBAAmB,OAAO;EAC1B,kBAAkB,OAAO;EACzB,iBAAiB,WACf,OAAO,IAAI,aAAa;AAEtB,UAAO,OAAO,OAAO,UAAU,CAAC,KAAK,OAAO,eAAe,OAAO,KAAK,CAAC;AAGxE,UAAO,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,OAAU,CAAC;AAGzD,UAAO,UAAU,WAAW,OAAO;IACnC;EACJ,SAAS,UAAU;EACpB;EACD,EACH,CAAC,CAAC;CACD,OAAO,QACL,UACA,SACA,YAAkD,EAAE,KACjD;EACH,MAAM,eAAe,MAAM,SACzB,MAAM,QAAQ,mBAAmB,SAAS,EAC1C,MAAM,QAAQ,kBAAkB,QAAQ,EACxC,MAAM,QAAQ,cAAc,UAAU,CACvC;EAED,MAAM,gBAAgB,MAAM,SAC1B,wBAAwB,SACxB,eAAe,SACf,gBAAgB,SAChB,uBAAuB,QACxB,CAAC,KAAK,MAAM,QAAQ,aAAa,CAAC;AAEnC,SAAO,cAAc,QAAQ,KAC3B,MAAM,QAAQ,oBAAoB,QAAQ,EAC1C,MAAM,QAAQ,cAAc,CAC7B"}
1
+ {"version":3,"file":"plugin.service.mjs","names":[],"sources":["../../../src/runtime/services/plugin.service.ts"],"sourcesContent":["import { Effect, Exit, Layer, Scope } from \"effect\";\nimport type {\n AnyPlugin,\n AnyPluginConstructor,\n InitializedPlugin,\n PluginRegistry,\n SecretsConfig,\n} from \"../../types\";\nimport { ModuleFederationService } from \"./module-federation.service\";\nimport { PluginLifecycleService } from \"./plugin-lifecycle.service\";\nimport {\n PluginLoaderService,\n PluginMapTag,\n PluginRegistryTag,\n RegistryService,\n} from \"./plugin-loader.service\";\nimport { SecretsConfigTag, SecretsService } from \"./secrets.service\";\n\nexport class PluginService extends Effect.Service<PluginService>()(\"PluginService\", {\n scoped: Effect.gen(function* () {\n const loader = yield* PluginLoaderService;\n const lifecycle = yield* PluginLifecycleService;\n\n return {\n loadPlugin: loader.loadPlugin,\n instantiatePlugin: loader.instantiatePlugin,\n initializePlugin: loader.initializePlugin,\n shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>\n Effect.gen(function* () {\n yield* plugin.plugin\n .shutdown()\n .pipe(\n Effect.catchAll((error) =>\n Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),\n ),\n );\n\n yield* Scope.close(plugin.scope, Exit.succeed(undefined));\n\n yield* lifecycle.unregister(plugin);\n }),\n cleanup: lifecycle.cleanup,\n };\n }),\n}) {\n static Live = (\n registry: PluginRegistry,\n secrets: SecretsConfig,\n pluginMap: Record<string, AnyPluginConstructor> = {},\n ) => {\n const contextLayer = Layer.mergeAll(\n Layer.succeed(PluginRegistryTag, registry),\n Layer.succeed(SecretsConfigTag, secrets),\n Layer.succeed(PluginMapTag, pluginMap),\n );\n\n const servicesLayer = Layer.mergeAll(\n ModuleFederationService.Default,\n SecretsService.Default,\n RegistryService.Default,\n PluginLifecycleService.Default,\n ).pipe(Layer.provide(contextLayer));\n\n return PluginService.Default.pipe(\n Layer.provide(PluginLoaderService.Default),\n Layer.provide(servicesLayer),\n );\n };\n}\n"],"mappings":";;;;;;;AAkBA,IAAa,gBAAb,MAAa,sBAAsB,OAAO,SAAwB,CAAC,iBAAiB,EAClF,QAAQ,OAAO,IAAI,aAAa;CAC9B,MAAM,SAAS,OAAO;CACtB,MAAM,YAAY,OAAO;AAEzB,QAAO;EACL,YAAY,OAAO;EACnB,mBAAmB,OAAO;EAC1B,kBAAkB,OAAO;EACzB,iBAAiB,WACf,OAAO,IAAI,aAAa;AACtB,UAAO,OAAO,OACX,UAAU,CACV,KACC,OAAO,UAAU,UACf,OAAO,WAAW,6BAA6B,OAAO,OAAO,MAAM,MAAM,CAC1E,CACF;AAEH,UAAO,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,OAAU,CAAC;AAEzD,UAAO,UAAU,WAAW,OAAO;IACnC;EACJ,SAAS,UAAU;EACpB;EACD,EACH,CAAC,CAAC;CACD,OAAO,QACL,UACA,SACA,YAAkD,EAAE,KACjD;EACH,MAAM,eAAe,MAAM,SACzB,MAAM,QAAQ,mBAAmB,SAAS,EAC1C,MAAM,QAAQ,kBAAkB,QAAQ,EACxC,MAAM,QAAQ,cAAc,UAAU,CACvC;EAED,MAAM,gBAAgB,MAAM,SAC1B,wBAAwB,SACxB,eAAe,SACf,gBAAgB,SAChB,uBAAuB,QACxB,CAAC,KAAK,MAAM,QAAQ,aAAa,CAAC;AAEnC,SAAO,cAAc,QAAQ,KAC3B,MAAM,QAAQ,oBAAoB,QAAQ,EAC1C,MAAM,QAAQ,cAAc,CAC7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "every-plugin",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -63,12 +63,7 @@ export function setupPluginMiddleware(
63
63
  const loaded = await runtime.usePlugin(pluginId, (devConfig?.config ?? defaultConfig) as any);
64
64
 
65
65
  cleanup = async () => {
66
- if (loaded && typeof (loaded as any).dispose === "function") {
67
- await (loaded as any).dispose();
68
- }
69
- if (runtime && typeof (runtime as any).cleanup === "function") {
70
- await (runtime as any).cleanup();
71
- }
66
+ if (runtime) await runtime.shutdown();
72
67
  handlers.rpc = null;
73
68
  handlers.api = null;
74
69
  if (devServer.app.locals.handlers) {
@@ -14,9 +14,15 @@ export interface EveryPluginOptions {
14
14
  dts?: boolean;
15
15
  }
16
16
 
17
+ export interface AdditionalExport {
18
+ srcPath: string;
19
+ exportNames: string[];
20
+ }
21
+
17
22
  export interface PluginManifestEmitterOptions {
18
23
  manifestFileName?: string;
19
24
  contractFileName?: string;
25
+ additionalExports?: AdditionalExport[];
20
26
  }
21
27
 
22
28
  export class EmitPluginManifest implements RspackPluginInstance {
@@ -73,7 +79,7 @@ export class EmitPluginManifest implements RspackPluginInstance {
73
79
  }
74
80
 
75
81
  const contractSha256 = crypto.createHash("sha256").update(contractTypes).digest("hex");
76
- const manifest = {
82
+ const manifest: Record<string, unknown> = {
77
83
  schemaVersion: 1,
78
84
  kind: "every-plugin/manifest",
79
85
  plugin: {
@@ -94,6 +100,37 @@ export class EmitPluginManifest implements RspackPluginInstance {
94
100
  },
95
101
  };
96
102
 
103
+ const additionalExportsEntries: Array<{ path: string; exports: string[]; sha256: string }> =
104
+ [];
105
+
106
+ if (this.options.additionalExports?.length) {
107
+ for (const additional of this.options.additionalExports) {
108
+ const sourcePath = path.join(context, "types", additional.srcPath);
109
+ const content = await tryReadFile(sourcePath);
110
+ if (!content) {
111
+ console.warn(
112
+ `[EmitPluginManifest] Additional export file not found at ${sourcePath}. Skipping.`,
113
+ );
114
+ continue;
115
+ }
116
+ const sha256 = crypto.createHash("sha256").update(content).digest("hex");
117
+ const distPath = `./types/${additional.srcPath}`;
118
+ additionalExportsEntries.push({
119
+ path: distPath,
120
+ exports: additional.exportNames,
121
+ sha256,
122
+ });
123
+
124
+ if (rawSource) {
125
+ compilation.emitAsset(`types/${additional.srcPath}`, new rawSource(content));
126
+ }
127
+ }
128
+
129
+ if (additionalExportsEntries.length > 0) {
130
+ manifest.additionalExports = additionalExportsEntries;
131
+ }
132
+ }
133
+
97
134
  if (rawSource) {
98
135
  compilation.emitAsset(
99
136
  manifestFileName,
package/src/index.ts CHANGED
@@ -23,4 +23,5 @@ export type {
23
23
  PluginVariables,
24
24
  RegisteredPlugins,
25
25
  SecretsConfig,
26
+ UsePluginResult,
26
27
  } from "./types";
package/src/plugin.ts CHANGED
@@ -152,8 +152,15 @@ export const createPlugin: CreatePluginFn = function createPlugin<
152
152
  const self = this;
153
153
  return Effect.gen(function* () {
154
154
  if (config.shutdown && self._deps) {
155
- yield* config.shutdown(self._deps).pipe(Effect.catchAll(() => Effect.void));
155
+ yield* config
156
+ .shutdown(self._deps)
157
+ .pipe(
158
+ Effect.catchAll((error) =>
159
+ Effect.logWarning(`Plugin shutdown hook failed for ${self.id}`, error),
160
+ ),
161
+ );
156
162
  }
163
+ self._deps = null;
157
164
  });
158
165
  }
159
166
 
@@ -165,10 +165,18 @@ export class PluginRuntime<R = RegisteredPlugins> {
165
165
  if (pluginResult) {
166
166
  yield* pluginService
167
167
  .shutdownPlugin(pluginResult)
168
- .pipe(Effect.catchAll(() => Effect.void));
168
+ .pipe(
169
+ Effect.catchAll((error) =>
170
+ Effect.logWarning(`Failed to shutdown evicted plugin ${pluginId}`, error),
171
+ ),
172
+ );
169
173
  }
170
174
  }
171
- }).pipe(Effect.catchAll(() => Effect.void));
175
+ }).pipe(
176
+ Effect.catchAll((error) =>
177
+ Effect.logWarning(`Plugin eviction failed for ${pluginId}`, error),
178
+ ),
179
+ );
172
180
 
173
181
  return this.runPromise(effect);
174
182
  }
@@ -1,4 +1,4 @@
1
- import { Effect, Ref } from "effect";
1
+ import { Effect, Exit, Ref, Scope } from "effect";
2
2
  import type { AnyPlugin, InitializedPlugin } from "../../types";
3
3
  import { toPluginRuntimeError } from "../errors";
4
4
 
@@ -50,36 +50,31 @@ export class PluginLifecycleService extends Effect.Service<PluginLifecycleServic
50
50
  Effect.gen(function* () {
51
51
  const plugins = yield* Ref.get(activePlugins);
52
52
 
53
- // Shutdown all active plugins concurrently
54
53
  yield* Effect.forEach(
55
54
  plugins,
56
55
  (plugin) =>
57
- plugin.plugin.shutdown().pipe(
58
- Effect.mapError((error) =>
59
- toPluginRuntimeError(
60
- error,
61
- plugin.plugin.id,
62
- undefined,
63
- "cleanup-shutdown",
64
- false,
56
+ Effect.gen(function* () {
57
+ yield* plugin.plugin
58
+ .shutdown()
59
+ .pipe(
60
+ Effect.catchAll((error) =>
61
+ Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),
62
+ ),
63
+ );
64
+ yield* Scope.close(plugin.scope, Exit.succeed(undefined)).pipe(
65
+ Effect.catchAll((error) =>
66
+ Effect.logWarning(
67
+ `Failed to close scope for plugin ${plugin.plugin.id}`,
68
+ error,
69
+ ),
65
70
  ),
66
- ),
67
- Effect.catchAll((error) =>
68
- Effect.logError(
69
- `Failed to shutdown plugin ${plugin.plugin.id} during cleanup`,
70
- error,
71
- { pluginId: plugin.plugin.id },
72
- ),
73
- ),
74
- ),
71
+ );
72
+ }),
75
73
  { concurrency: "unbounded" },
76
74
  );
77
75
 
78
- // Clear the active plugins set
79
76
  yield* Ref.set(activePlugins, new Set());
80
- }).pipe(
81
- Effect.catchAll(() => Effect.void), // Convert errors to void for cleanup
82
- ),
77
+ }).pipe(Effect.catchAll((error) => Effect.logWarning("Plugin cleanup failed", error))),
83
78
  };
84
79
  }),
85
80
  },
@@ -27,13 +27,16 @@ export class PluginService extends Effect.Service<PluginService>()("PluginServic
27
27
  initializePlugin: loader.initializePlugin,
28
28
  shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>
29
29
  Effect.gen(function* () {
30
- // Shutdown the plugin first (graceful cleanup)
31
- yield* plugin.plugin.shutdown().pipe(Effect.catchAll(() => Effect.void));
30
+ yield* plugin.plugin
31
+ .shutdown()
32
+ .pipe(
33
+ Effect.catchAll((error) =>
34
+ Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),
35
+ ),
36
+ );
32
37
 
33
- // Close the plugin scope to interrupt fibers and release resources
34
38
  yield* Scope.close(plugin.scope, Exit.succeed(undefined));
35
39
 
36
- // Unregister from lifecycle tracking
37
40
  yield* lifecycle.unregister(plugin);
38
41
  }),
39
42
  cleanup: lifecycle.cleanup,