Skip to main content

kickjs-add-plugin

Use when scaffolding a feature that bundles modules + DI + middleware + adapters together (auth, monitoring suite, multi-tenant scaffolding).

来源信息

仓库
forinda/kick-fullstack-netlify
最近来源活动
2026年9月18日 11:52
检测到的 SKILL.md 语言
英语
星标
0
Forks
0

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
kickjs-add-plugin
description
Use when scaffolding a feature that bundles modules + DI + middleware + adapters together (auth, monitoring suite, multi-tenant scaffolding).
<!-- Generated by `kick g agents` for kick-fullstack-server. Edits are overwritten on the next refresh; keep customisation in a SKILL.local.md alongside. --> **When plugin > adapter**: a plugin is the right answer when the integration ships **more than one** of: a module, a DI binding, middleware, or another adapter. If you have a single hook (`beforeStart`) and no other contributions, use `defineAdapter` instead. **Canonical shape**: ```ts import { definePlugin } from '@forinda/kickjs' export const AuthPlugin = definePlugin({ name: 'AuthPlugin', defaults: { tokenTtl: '1h' }, build: (config, { name }) => ({ modules: () => [AuthModule()], adapters: () => [JwtAdapter({ ttl: config.tokenTtl })], middleware: () => [requestIdMiddleware()], register(container) { container.registerFactory(TOKEN_SIGNER, () => createSigner(config)) }, contributors() { return [LoadCurrentUser.registration] }, onReady({ server }) { log.info(`AuthPlugin listening on port ${server.address().port}`) }, }), }) // In bootstrap: bootstrap({ plugins: [AuthPlugin({ tokenTtl: env.TOKEN_TTL })] }) // <-- parens ``` **Inline plugin literal** — the canonical answer for one-off DI bindings. There's no top-level `register:` on `bootstrap` itself: ```ts bootstrap({ plugins: [{ name: 'vector-store', register(c) { c.registerInstance(VECTOR_STORE, store) } }], }) ``` **Execution order** (memorize): plugin `register()` → plugin `middleware()` → plugin `modules()` + user modules → plugin `adapters()` + user adapters → server listens → plugin `onReady()`. **Static vs dynamic modules**: `modules()` returning an array is introspectable (Swagger, DevTools see it). `setup(registry)` is imperative — pick the latter when the module set depends on resolved config. **Multi-instance** — `.scoped('users', { url })`; derive unique DI tokens from `ctx.name` inside `build`: ```ts build: (config, { name }) => ({ register(c) { c.registerInstance(createToken(`cache/${name}`), client) }, }) ``` **Precedence**: plugin contributors land at `'adapter'` precedence — beat global, lose to module/class/method same-key. **Red flags**: - `bootstrap({ plugins: [AuthPlugin] })` — passed factory. Call it: `AuthPlugin()`. - Reaching for a plugin when an adapter would do (no modules, no DI bindings, no contributors) — overkill; use `defineAdapter()`. - `.async()` plugin that depends on `modules()` / `middleware()` / `adapters()` / `contributors()` — those are dropped. `.async()` only resolves `register()` + `onReady()`. - Confusing CLI plugins (`defineCliPlugin` from `@forinda/kickjs-cli`) with runtime plugins (`definePlugin` from `@forinda/kickjs`) — different surfaces, different registration sites. - `dependsOn: ['SomePlugin']` referring to a plugin not in the boot list — throws `MissingMountDepError` at boot. **Nuances**: - `definition` is `Object.freeze`'d metadata; useful for version checks (`compare(AuthPlugin.definition.version, '1.2.0')`) — not mountable.
在 GitHub 查看