every-plugin
Version:
70 lines (63 loc) • 2.1 kB
text/typescript
import { Effect, Exit, Layer, Scope } from "effect";
import type {
AnyPlugin,
AnyPluginConstructor,
InitializedPlugin,
PluginRegistry,
SecretsConfig,
} from "../../types";
import { ModuleFederationService } from "./module-federation.service";
import { PluginLifecycleService } from "./plugin-lifecycle.service";
import {
PluginLoaderService,
PluginMapTag,
PluginRegistryTag,
RegistryService,
} from "./plugin-loader.service";
import { SecretsConfigTag, SecretsService } from "./secrets.service";
export class PluginService extends Effect.Service<PluginService>()("PluginService", {
scoped: Effect.gen(function* () {
const loader = yield* PluginLoaderService;
const lifecycle = yield* PluginLifecycleService;
return {
loadPlugin: loader.loadPlugin,
instantiatePlugin: loader.instantiatePlugin,
initializePlugin: loader.initializePlugin,
shutdownPlugin: (plugin: InitializedPlugin<AnyPlugin>) =>
Effect.gen(function* () {
yield* plugin.plugin
.shutdown()
.pipe(
Effect.catchAll((error) =>
Effect.logWarning(`Failed to shutdown plugin ${plugin.plugin.id}`, error),
),
);
yield* Scope.close(plugin.scope, Exit.succeed(undefined));
yield* lifecycle.unregister(plugin);
}),
cleanup: lifecycle.cleanup,
};
}),
}) {
static Live = (
registry: PluginRegistry,
secrets: SecretsConfig,
pluginMap: Record<string, AnyPluginConstructor> = {},
) => {
const contextLayer = Layer.mergeAll(
Layer.succeed(PluginRegistryTag, registry),
Layer.succeed(SecretsConfigTag, secrets),
Layer.succeed(PluginMapTag, pluginMap),
);
const servicesLayer = Layer.mergeAll(
ModuleFederationService.Default,
SecretsService.Default,
RegistryService.Default,
PluginLifecycleService.Default,
).pipe(Layer.provide(contextLayer));
return PluginService.Default.pipe(
Layer.provide(PluginLoaderService.Default),
Layer.provide(servicesLayer),
);
};
}