first commit
This commit is contained in:
96
docs/api-stack/api/api-plugin/src/define/define.md
Normal file
96
docs/api-stack/api/api-plugin/src/define/define.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# define
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The `define` module exports a single function — `definePlugin<TConfig>(descriptor)`
|
||||
— that is the canonical entry point for authoring a plugin. The function
|
||||
returns its input unchanged at runtime; the value is entirely in its
|
||||
type signature, which threads the `TConfig` generic through every place
|
||||
the descriptor references it: `configSchema?: ZodType<TConfig>`,
|
||||
`defaults?: Partial<TConfig>`, and the four lifecycle hooks
|
||||
(`onRegister/onInit/onReady/onClose`). Inside each hook,
|
||||
`ctx.getOwnConfig()` returns `TConfig` with no cast required.
|
||||
|
||||
Using `definePlugin` is preferred over building a raw `PluginDescriptor`
|
||||
literal because it pins the generic at the call site. TypeScript will
|
||||
then flag mismatches at the source of the error (the hook body), not at
|
||||
the registration site one or two files away.
|
||||
|
||||
## Features
|
||||
|
||||
- Zero runtime overhead — the function body is `return descriptor`.
|
||||
- Full `TConfig` inference flows into hooks via `PluginContext<TConfig>`.
|
||||
- Compatible with descriptor field defaults (`description`, `dependencies`,
|
||||
`optionalDependencies`, `priority`, `enabledByDefault`, `tags`).
|
||||
- Plays nicely with `as const` literals — readers preserve `readonly`
|
||||
arrays for `dependencies` etc.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { definePlugin } from "@suaveplan/api-plugin/define";
|
||||
import z from "zod";
|
||||
|
||||
export const auth = definePlugin({
|
||||
name: "auth",
|
||||
version: "0.1.0",
|
||||
configSchema: z.object({ sessionTtlSeconds: z.number().int().positive() }),
|
||||
defaults: { sessionTtlSeconds: 3600 },
|
||||
onInit(ctx) {
|
||||
const { sessionTtlSeconds } = ctx.getOwnConfig();
|
||||
ctx.logger.info("auth ready", { sessionTtlSeconds });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Multiple hooks with `await` and the abort signal:
|
||||
|
||||
```ts
|
||||
export const queue = definePlugin<{ concurrency: number }>({
|
||||
name: "queue",
|
||||
version: "0.1.0",
|
||||
dependencies: ["db"],
|
||||
defaults: { concurrency: 4 },
|
||||
async onInit(ctx) {
|
||||
const { concurrency } = ctx.getOwnConfig();
|
||||
ctx.logger.info("starting queue", { concurrency });
|
||||
},
|
||||
async onReady(ctx) {
|
||||
if (ctx.signal.aborted) return;
|
||||
ctx.logger.info("queue ready");
|
||||
},
|
||||
async onClose(ctx) {
|
||||
ctx.logger.info("queue draining");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Export | Signature |
|
||||
|---|---|
|
||||
| `definePlugin<TConfig>(descriptor)` | `(PluginDescriptor<TConfig>) => PluginDescriptor<TConfig>` |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The function is intentionally an identity at runtime so it can be
|
||||
constant-folded by bundlers — the dependency graph rewards leaf
|
||||
helpers that the optimiser can drop. Because the `descriptor` parameter
|
||||
is typed as `PluginDescriptor<TConfig>`, TypeScript will not narrow
|
||||
`TConfig` away if the call site supplies an explicit generic
|
||||
(`definePlugin<MyConfig>({...})`). Implicit inference also works
|
||||
when `configSchema` is provided as a Zod schema, because the
|
||||
descriptor field is typed `ZodType<TConfig>` and Zod's schema generic
|
||||
is contravariant in this position.
|
||||
|
||||
Calling `definePlugin` is preferred over a bare object literal even
|
||||
though both are runtime-equivalent: the call site is the right place
|
||||
for an editor to surface "Quick Info" on the generic, and it keeps the
|
||||
public author surface consistent across the 40+ in-flight
|
||||
`@suaveplan/api-plugin-*` packages.
|
||||
Reference in New Issue
Block a user