# `plugin.ts` _(no submodules)_ ## Purpose The plugin factory for `@suaveplan/api-plugin-export`. Construction-time it validates options through `ExportPluginOptionsSchema` (rejecting with `ExportError(EXPORT.INVALID_CONFIG)` on failure) and returns a `PluginDescriptor` with three lifecycle hooks. `onInit` registers the in-memory `providers` + `jobs` maps on the augmented `ServiceRegistry`. `onReady` resolves the host `app` (`OpenAPIHono`) and mounts the export routes at the configured `basePath`. `onClose` clears both maps so a re-registration of the plugin starts clean. ## Features - Caller-supplied options are honoured end-to-end — the upstream `_config`-discard bug is fixed at migration time. - Side-effect import of `registry-augmentation` makes `ctx.getService("exportProviders")` / `ctx.getService("exportJobs")` type-narrow correctly at every call site that imports this module. - `registerDataProvider(providers, provider)` is a convenience the upstream package shipped — re-exposed here so downstream code does not need to construct the providers map by hand. - `onReady` mounts routes via `ctx.getService("app")` (the suaveplanent of upstream's `ctx.app.route(...)` call) so the plugin participates in the rest of the plugin ecosystem cleanly. ## Usage: Basic ```ts import { createExportPlugin } from "@suaveplan/api-plugin-export"; const registry = createPluginRegistry(); registry.register(createExportPlugin({ basePath: "/v1/exports", maxRows: 10_000 })); await registry.init(); await registry.ready(); ``` ## Usage: Advanced ```ts import { createExportPlugin, registerDataProvider, type DataProvider, } from "@suaveplan/api-plugin-export"; const plugin = createExportPlugin({ defaultFormat: "json" }); // later, after onInit completes: const providers = ctx.getService("exportProviders"); if (providers) { const userProvider: DataProvider = { resource: "users", fetch: async () => db.select("user").get(), }; registerDataProvider(providers, userProvider); } ``` ## API Reference | Symbol | Kind | Notes | |---|---|---| | `createExportPlugin(options?)` | function | Returns `PluginDescriptor`. Throws `EXPORT.INVALID_CONFIG` on bad input. | | `registerDataProvider(providers, provider)` | function | `providers.set(provider.resource, provider)` helper. | ## Implementation Notes The descriptor uses `defaults: config` so the `PluginContext`-level `getOwnConfig()` returns the merged, fully-defaulted options shape — downstream plugins that read the plugin config (or that the host orchestrator inspects) see the same values the route handler uses. The `app` lookup in `onReady` returns `OpenAPIHono | undefined` (per the `ServiceRegistry` augmentation in `@suaveplan/api`), so the missing case is checked explicitly with an `ExportError(INVALID_CONFIG)` — this is a misconfiguration of the host, not of the plugin options, but the same code is correct because the host failed to seed the `app` slot before plugin registration. `runOnInit` is async even though it does no `await` because the lifecycle hook signature requires it; making it async eliminates a subtle TypeScript variance gotcha when the registry awaits the return value. The runtime maps are held on a `PluginRuntime` interface so the three hook helpers can pass state without resorting to module-scope `let` (which would conflict with multiple plugin instances co-existing in one process).