CI / Lint (push) Canceled after 0s
CI / Build Test (stage-web) (push) Canceled after 0s
CI / Build Test (ui-loading-screens) (push) Canceled after 0s
CI / Build Test (ui-transitions) (push) Canceled after 0s
CI / Unit Test (push) Canceled after 0s
CI / Type Check (push) Canceled after 0s
CI / Check Provenance (push) Canceled after 0s
Sync Labels / sync-labels (push) Successful in 1m43s
- Remove stage-tamagotchi, stage-pocket, server, and engine workspaces with their workflows, addons, and docs - Switch the toolchain from pnpm to bun, replace lockfiles with bun.lock - Rewrite remaining product references to Moeka
67 lines
2.8 KiB
Markdown
67 lines
2.8 KiB
Markdown
# @proj-airi/plugin-sdk
|
|
|
|
Runtime-agnostic SDK for Moeka extensions.
|
|
|
|
## Kit API Naming
|
|
|
|
Kits should hide transport details from extension authors. A normal extension should use a kit as a normal API object directly from setup:
|
|
|
|
```ts
|
|
const gamelets = await ctx.kits.use(gameletKit)
|
|
await gamelets.mount(input)
|
|
```
|
|
|
|
Explicit module scopes are an advanced lifecycle and attribution API. Use `module.kits.use(...)` only when the host needs a contribution to be associated with a sub-scope that may later be inspected, disposed, or restarted independently.
|
|
|
|
When a kit needs to work across process or network boundaries, expose shared Eventa invoke contracts from the kit package and build the client from those contracts. Do not introduce kit-specific transport method names such as `invokeGamelet`, `gameletRpc`, or `gameletRuntime`.
|
|
|
|
Use these names consistently:
|
|
|
|
| Name | Meaning |
|
|
| --- | --- |
|
|
| `gameletKitApis` | Shared Eventa API contract exported by the kit package. This is usually a map of `defineInvokeEventa(...)` entries. |
|
|
| `gameletKitService` | Host-side implementation of the kit behavior. It owns real side effects such as mounting, updating, and cleaning up UI. |
|
|
| `gameletKit` | The kit definition consumed by `ctx.kits.use(...)` or an optional module scope. It owns identity, version, availability policy, and client creation. |
|
|
| `gamelets` | The client instance returned to extension authors. Prefer a plural namespace when the client exposes multiple operations. |
|
|
| `createGameletKit(...)` | Factory that wires dependencies into `gameletKit`, including local client creation and remote Eventa-backed client creation. |
|
|
|
|
Example shape:
|
|
|
|
```ts
|
|
export const gameletKitApis = {
|
|
mount: defineInvokeEventa<GameletMountResult, GameletMountInput>(
|
|
'airi:kit:gamelet:mount',
|
|
),
|
|
}
|
|
|
|
export interface GameletKitService {
|
|
mount: (input: GameletMountInput, scope: KitCallScope) => Promise<GameletMountResult>
|
|
}
|
|
|
|
export function createGameletKit(options: { service: GameletKitService }) {
|
|
return defineKit<GameletClient>({
|
|
id: 'kit.gamelet',
|
|
version: '1.0.0',
|
|
createClient(runtime) {
|
|
return {
|
|
mount: input => options.service.mount(input, runtime),
|
|
}
|
|
},
|
|
})
|
|
}
|
|
```
|
|
|
|
Remote clients should reuse Eventa invoke instead of defining a parallel RPC protocol. Use a lazy context callback when the underlying transport can reconnect or be created after the client object:
|
|
|
|
```ts
|
|
const mount = defineInvoke(getContext, gameletKitApis.mount)
|
|
|
|
const gamelets = {
|
|
mount(input: GameletMountInput) {
|
|
return mount(input, scope)
|
|
},
|
|
}
|
|
```
|
|
|
|
The shared artifact is the Eventa API contract, not the implementation function. Local clients may call `gameletKitService` directly; remote clients call the same API through Eventa. Both should expose the same authoring shape.
|