@abide/abide 0.41.1 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +234 -294
- package/CHANGELOG.md +82 -0
- package/README.md +51 -95
- package/package.json +3 -2
- package/src/abideLsp.ts +46 -8
- package/src/abideResolverPlugin.ts +107 -19
- package/src/buildCli.ts +1 -1
- package/src/discoveryEntry.ts +3 -3
- package/src/lib/bundle/BundleMenuItem.ts +1 -1
- package/src/lib/cli/createClient.ts +12 -12
- package/src/lib/cli/dispatchCommand.ts +1 -1
- package/src/lib/cli/printSessionStatus.ts +1 -1
- package/src/lib/cli/resolveCliTarget.ts +1 -1
- package/src/lib/cli/runCli.ts +1 -1
- package/src/lib/cli/types/CliManifest.ts +1 -1
- package/src/lib/cli/types/CliManifestEntry.ts +2 -2
- package/src/lib/mcp/annotationsForMethod.ts +5 -5
- package/src/lib/mcp/createMcpServer.ts +3 -3
- package/src/lib/mcp/mcpSurface.ts +14 -14
- package/src/lib/mcp/types/McpServerOptions.ts +1 -1
- package/src/lib/server/DELETE.ts +4 -4
- package/src/lib/server/GET.ts +4 -4
- package/src/lib/server/HEAD.ts +4 -4
- package/src/lib/server/PATCH.ts +4 -4
- package/src/lib/server/POST.ts +4 -4
- package/src/lib/server/PUT.ts +4 -4
- package/src/lib/server/agent.ts +4 -4
- package/src/lib/server/env.ts +1 -1
- package/src/lib/server/error.ts +49 -7
- package/src/lib/server/json.ts +1 -1
- package/src/lib/server/rpc/buildErrorConstructors.ts +19 -0
- package/src/lib/server/rpc/{defineVerb.ts → defineRpc.ts} +52 -34
- package/src/lib/server/rpc/{dispatchVerbInProcess.ts → dispatchRpcInProcess.ts} +3 -3
- package/src/lib/server/rpc/fieldErrorsFromIssues.ts +23 -0
- package/src/lib/server/rpc/{findVerbByCommandName.ts → findRpcByCommandName.ts} +5 -5
- package/src/lib/server/rpc/parseArgs.ts +6 -6
- package/src/lib/server/rpc/readBodyWithinLimit.ts +2 -2
- package/src/lib/server/rpc/registerRpc.ts +6 -0
- package/src/lib/server/rpc/{verbRegistry.ts → rpcRegistry.ts} +4 -4
- package/src/lib/server/rpc/{runWithVerbTimeout.ts → runWithRpcTimeout.ts} +4 -4
- package/src/lib/server/rpc/types/RemoteHandler.ts +9 -3
- package/src/lib/server/rpc/types/{VerbHelper.ts → RpcHelper.ts} +57 -23
- package/src/lib/server/rpc/types/{VerbRegistryEntry.ts → RpcRegistryEntry.ts} +3 -3
- package/src/lib/server/rpc/types/TypedResponse.ts +2 -2
- package/src/lib/server/rpc/unprocessed.ts +6 -7
- package/src/lib/server/rpc/validationError.ts +17 -0
- package/src/lib/server/runtime/buildInspectorSurface.ts +7 -7
- package/src/lib/server/runtime/buildOpenApiSpec.ts +6 -6
- package/src/lib/server/runtime/createRouteDispatcher.ts +7 -7
- package/src/lib/server/runtime/createServer.ts +4 -4
- package/src/lib/server/runtime/crossOriginForbidden.ts +1 -1
- package/src/lib/server/runtime/crossOriginGate.ts +4 -4
- package/src/lib/server/runtime/devClientFingerprint.ts +2 -1
- package/src/lib/server/runtime/logExposedSurfaces.ts +4 -4
- package/src/lib/server/runtime/registryManifests.ts +2 -2
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
- package/src/lib/server/runtime/types/InspectorRpc.ts +27 -0
- package/src/lib/server/runtime/types/InspectorSurface.ts +4 -4
- package/src/lib/server/runtime/types/RequestStore.ts +1 -1
- package/src/lib/server/runtime/warnUnguardedMcp.ts +2 -2
- package/src/lib/server/sockets/createSocketDispatcher.ts +15 -14
- package/src/lib/server/sockets/types/SocketOperation.ts +2 -2
- package/src/lib/shared/HttpError.ts +15 -1
- package/src/lib/shared/UNREACHABLE_STATUSES.ts +13 -0
- package/src/lib/shared/buildRpcRequest.ts +5 -5
- package/src/lib/shared/cache.ts +50 -168
- package/src/lib/shared/carriesBodyArgs.ts +4 -4
- package/src/lib/shared/createCacheStore.ts +12 -0
- package/src/lib/shared/createRemoteFunction.ts +11 -6
- package/src/lib/shared/decodeResponse.ts +2 -2
- package/src/lib/shared/detectRpcMethod.ts +17 -0
- package/src/lib/shared/emitLogRecord.ts +3 -3
- package/src/lib/shared/escapeRegex.ts +9 -0
- package/src/lib/shared/extraForwardHeaders.ts +1 -1
- package/src/lib/shared/fileName.ts +9 -0
- package/src/lib/shared/fileStem.ts +3 -1
- package/src/lib/shared/findExportCallSite.ts +30 -273
- package/src/lib/shared/forwardHeaders.ts +2 -2
- package/src/lib/shared/httpErrorFor.ts +26 -0
- package/src/lib/shared/isAsciiWhitespace.ts +5 -0
- package/src/lib/shared/isIdentPart.ts +9 -0
- package/src/lib/shared/isIdentStart.ts +8 -0
- package/src/lib/shared/isReadOnlyMethod.ts +4 -4
- package/src/lib/shared/keyForRemoteCall.ts +4 -4
- package/src/lib/shared/log.ts +1 -1
- package/src/lib/shared/outboxProbeSlot.ts +20 -0
- package/src/lib/shared/pending.ts +4 -1
- package/src/lib/shared/prepareRpcModule.ts +96 -14
- package/src/lib/shared/probeRegistries.ts +17 -4
- package/src/lib/shared/programNameForPackage.ts +3 -1
- package/src/lib/shared/queryStringFromArgs.ts +1 -1
- package/src/lib/shared/remoteMetaStore.ts +2 -2
- package/src/lib/shared/resolveClientFlags.ts +1 -1
- package/src/lib/shared/skipNonCode.ts +230 -0
- package/src/lib/shared/streamResponse.ts +9 -6
- package/src/lib/shared/stripImport.ts +6 -4
- package/src/lib/shared/types/CacheEntry.ts +2 -4
- package/src/lib/shared/types/CacheOnContext.ts +1 -11
- package/src/lib/shared/types/CacheStore.ts +13 -7
- package/src/lib/shared/types/ClientFlags.ts +1 -1
- package/src/lib/shared/types/ErrorConstructors.ts +17 -0
- package/src/lib/shared/types/ErrorDescriptor.ts +10 -0
- package/src/lib/shared/types/ErrorSpec.ts +11 -0
- package/src/lib/shared/types/HttpMethod.ts +1 -0
- package/src/lib/shared/types/Outbox.ts +9 -0
- package/src/lib/shared/types/OutboxEntry.ts +27 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +2 -2
- package/src/lib/shared/types/RemoteCallable.ts +2 -2
- package/src/lib/shared/types/RemoteFunction.ts +21 -6
- package/src/lib/shared/types/RequestScopeInfo.ts +1 -1
- package/src/lib/shared/types/RpcErrorGuard.ts +40 -0
- package/src/lib/shared/types/RpcInvoker.ts +1 -1
- package/src/lib/shared/types/StandardSchemaV1.ts +1 -1
- package/src/lib/shared/types/ValidationErrorData.ts +20 -0
- package/src/lib/shared/url.ts +3 -3
- package/src/lib/shared/writeRpcDts.ts +7 -7
- package/src/lib/shared/writeTestRpcDts.ts +3 -3
- package/src/lib/test/createTestApp.ts +10 -10
- package/src/lib/ui/compile/ABIDE_SEMANTIC_TOKENS_LEGEND.ts +45 -0
- package/src/lib/ui/compile/abideUiPlugin.ts +2 -1
- package/src/lib/ui/compile/awaitPlan.ts +48 -0
- package/src/lib/ui/compile/compileShadow.ts +117 -31
- package/src/lib/ui/compile/createShadowLanguageService.ts +48 -0
- package/src/lib/ui/compile/desugarSignals.ts +42 -6
- package/src/lib/ui/compile/encodeSemanticTokens.ts +37 -0
- package/src/lib/ui/compile/generateBuild.ts +45 -62
- package/src/lib/ui/compile/generateSSR.ts +90 -60
- package/src/lib/ui/compile/ifPlan.ts +30 -0
- package/src/lib/ui/compile/makeVarNamer.ts +10 -0
- package/src/lib/ui/compile/offsetToPosition.ts +9 -0
- package/src/lib/ui/compile/parseTemplate.ts +565 -115
- package/src/lib/ui/compile/stripEffects.ts +17 -9
- package/src/lib/ui/compile/structuralBlockTokens.ts +101 -0
- package/src/lib/ui/compile/switchPlan.ts +22 -0
- package/src/lib/ui/compile/tryPlan.ts +29 -0
- package/src/lib/ui/compile/types/SemanticToken.ts +11 -0
- package/src/lib/ui/compile/types/TemplateAttr.ts +8 -2
- package/src/lib/ui/compile/types/TemplateNode.ts +15 -2
- package/src/lib/ui/createScope.ts +20 -2
- package/src/lib/ui/dom/appendText.ts +1 -5
- package/src/lib/ui/dom/applyResolved.ts +1 -5
- package/src/lib/ui/dom/disposeRange.ts +6 -10
- package/src/lib/ui/dom/hydrate.ts +2 -5
- package/src/lib/ui/dom/isComment.ts +6 -0
- package/src/lib/ui/dom/mount.ts +1 -2
- package/src/lib/ui/dom/withScope.ts +6 -9
- package/src/lib/ui/effect.ts +4 -2
- package/src/lib/ui/navigate.ts +40 -13
- package/src/lib/ui/outbox.ts +30 -110
- package/src/lib/ui/remoteProxy.ts +160 -10
- package/src/lib/ui/router.ts +3 -3
- package/src/lib/ui/rpcOutbox/createOutboxQueue.ts +281 -0
- package/src/lib/ui/rpcOutbox/outboxRegistry.ts +69 -0
- package/src/lib/ui/runtime/createDoc.ts +3 -3
- package/src/lib/ui/runtime/pathSegments.ts +10 -0
- package/src/lib/ui/socketChannel.ts +7 -1
- package/src/lib/ui/types/Scope.ts +20 -5
- package/template/.zed/settings.json +4 -0
- package/template/CLAUDE.md +1 -1
- package/template/src/server/rpc/getHello.ts +3 -3
- package/template/src/ui/pages/page.abide +4 -4
- package/template/test/app.test.ts +2 -2
- package/src/lib/server/rpc/registerVerb.ts +0 -6
- package/src/lib/server/runtime/types/InspectorVerb.ts +0 -27
- package/src/lib/shared/detectVerbMethod.ts +0 -17
- package/src/lib/shared/types/HttpVerb.ts +0 -1
- package/src/lib/ui/types/Outbox.ts +0 -14
package/AGENTS.md
CHANGED
|
@@ -1,404 +1,344 @@
|
|
|
1
1
|
# AGENTS.md — abide complete surface map
|
|
2
2
|
|
|
3
|
-
> The exhaustive index of abide's public surface: every `exports` key appears
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
>
|
|
9
|
-
> **No barrels.** Every public name has its own module path —
|
|
10
|
-
> `@abide/abide/server/GET`, `@abide/abide/shared/cache`, `@abide/abide/ui/scope`. The namespace
|
|
11
|
-
> marks the side a name runs on: `@abide/abide/server/*` is server-only,
|
|
12
|
-
> `@abide/abide/ui/*` is client-only, `@abide/abide/shared/*` is isomorphic (same callable,
|
|
13
|
-
> same behaviour on both sides — the bundler swaps the runtime). There is no
|
|
14
|
-
> umbrella `index.ts`, so importing one name never drags in side-effecting
|
|
15
|
-
> siblings.
|
|
16
|
-
>
|
|
17
|
-
> Package `@abide/abide`, runtime Bun ≥ 1.3.0, one direct dependency
|
|
18
|
-
> (`typescript`); `tailwindcss` + `bun-plugin-tailwind` are optional peers.
|
|
19
|
-
> Import specifiers below are `package.json` `exports` keys, not file paths —
|
|
20
|
-
> `@abide/abide/server/GET` resolves to `src/lib/server/GET.ts`.
|
|
3
|
+
> The exhaustive index of abide's public surface: every `exports` key appears once, grouped by namespace, with its import specifier and a one-line spec. This is the whole-API read; the README is the curated 3-primitive intro. CONTEXT.md is the glossary, `docs/adr/` the rationale.
|
|
4
|
+
|
|
5
|
+
**No barrels.** Every public name has its own module path (`abide/server/GET`, `abide/shared/cache`, `abide/ui/scope`) — there is no umbrella `index.ts`, so importing one name never drags side-effecting siblings into the bundle. The namespace marks the side a name runs on: `abide/server/*` is server-only, `abide/ui/*` is client-only, `abide/shared/*` is isomorphic (same callable, same behaviour on both sides; the bundler swaps the runtime). The bullets below name each export by its import specifier in the `abide/…` shorthand (the published package is `@abide/abide`, so `abide/server/GET` imports from `@abide/abide/server/GET`) — these are import specifiers, not source file paths.
|
|
6
|
+
|
|
7
|
+
Package `@abide/abide`. Runtime: Bun ≥ 1.3.0. One direct dependency (TypeScript); `tailwindcss` + `bun-plugin-tailwind` are optional peers for styling.
|
|
21
8
|
|
|
22
9
|
## The premise
|
|
23
10
|
|
|
24
|
-
One typed
|
|
11
|
+
One typed RPC declaration fans out to every surface:
|
|
25
12
|
|
|
26
13
|
```text
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
SSR call
|
|
32
|
-
cache(fn)()
|
|
33
|
-
proxy
|
|
14
|
+
export const getMessages = GET(fn, { inputSchema })
|
|
15
|
+
│
|
|
16
|
+
┌────────────┬────────────┬────────────┬────────────┐
|
|
17
|
+
▼ ▼ ▼ ▼ ▼
|
|
18
|
+
SSR call browser MCP tool CLI cmd OpenAPI
|
|
19
|
+
cache(fn)() fetch proxy (read-only) abide cli /openapi.json
|
|
34
20
|
```
|
|
35
21
|
|
|
36
|
-
|
|
37
|
-
(`GET` / `HEAD`); a mutating verb never auto-exposes to MCP — it opts in with
|
|
38
|
-
`clients: { mcp: true }`. The same gating applies to sockets: a schema flips
|
|
39
|
-
the MCP/CLI read faces on.
|
|
22
|
+
The Standard Schema is the gate: an `inputSchema` unlocks the CLI subcommand and, for read-only methods (GET/HEAD), the MCP tool automatically. A mutating method (POST/PUT/PATCH/DELETE) never auto-exposes to MCP — it opts in with `clients: { mcp: true }`.
|
|
40
23
|
|
|
41
24
|
## File-based conventions
|
|
42
25
|
|
|
43
|
-
The bundler reads these paths
|
|
44
|
-
|
|
45
|
-
| Path
|
|
46
|
-
|
|
|
47
|
-
| `src/server/rpc/<name>.ts`
|
|
48
|
-
| `src/server/sockets/<name>.ts`
|
|
49
|
-
| `src/
|
|
50
|
-
| `src/
|
|
51
|
-
| `src/
|
|
52
|
-
| `src/
|
|
53
|
-
| `src/
|
|
54
|
-
| `src/
|
|
55
|
-
| `src
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `src/.abide/*.d.ts` | Generated types written each build — `routes`, `rpc`, `sockets`, `health`, `publicAssets`, and test surfaces. |
|
|
59
|
-
| `dist/_app/` | Client bundle output (hashed chunks; prod adds precompressed `.gz` siblings). |
|
|
26
|
+
The bundler reads these paths; the path is the identity.
|
|
27
|
+
|
|
28
|
+
| Path | Meaning |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `src/server/rpc/<name>.ts` | one RPC export; URL is `/rpc/<name>` |
|
|
31
|
+
| `src/server/sockets/<name>.ts` | one socket export; socket identity is `<name>` |
|
|
32
|
+
| `src/mcp/prompts/<name>.md` | one MCP prompt; identity is `<name>` (front-matter + `{{arg}}` body) |
|
|
33
|
+
| `src/server/config.ts` | the `env(schema)` config, read at boot |
|
|
34
|
+
| `src/app.ts` | optional `AppModule` hooks (`init`, `handle`, `handleError`) |
|
|
35
|
+
| `src/bundle/window.ts` | optional `BundleWindow` default export (desktop bundle) |
|
|
36
|
+
| `src/ui/pages/**/page.abide` | a page; the directory is the route, `[id]` a dynamic segment, `[...rest]` a catch-all |
|
|
37
|
+
| `src/ui/pages/**/layout.abide` | a layout wrapping every page below it via its `<slot/>` outlet |
|
|
38
|
+
| `src/.abide/*.d.ts` | generated type surfaces (RPC routes, health fields, test client) |
|
|
39
|
+
| `public/` | static assets served as-is |
|
|
40
|
+
| `dist/_app/` | the built client bundle (`abide build`) |
|
|
60
41
|
|
|
61
42
|
## CLI
|
|
62
43
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
abide dev
|
|
66
|
-
abide
|
|
67
|
-
abide
|
|
68
|
-
abide
|
|
69
|
-
abide
|
|
70
|
-
abide
|
|
71
|
-
abide
|
|
72
|
-
abide
|
|
73
|
-
abide
|
|
74
|
-
abide
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(`[test] preload = ["@abide/abide/preload"]`) so `.abide` modules resolve.
|
|
44
|
+
| Command | Does |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `abide scaffold <name>` | scaffold a project, install it, start dev (`--no-install` / `--no-dev` to skip) |
|
|
47
|
+
| `abide dev` | build + run with hot reload |
|
|
48
|
+
| `abide build` | build the client into `dist/_app/` |
|
|
49
|
+
| `abide check` | type-check `.abide` templates + props |
|
|
50
|
+
| `abide start` | run the production server against `dist/` |
|
|
51
|
+
| `abide run <file> [args…]` | run a script under the abide preload (same runtime as the server) |
|
|
52
|
+
| `abide compile [--target] [--out]` | build a standalone server executable |
|
|
53
|
+
| `abide cli [--target] [--out] [--platforms]` | build the CLI binary (a thin remote client that ships the server beside it) |
|
|
54
|
+
| `abide bundle` | build a movable, self-contained desktop app bundle for this platform |
|
|
55
|
+
| `abide lsp` | the `.abide` language server (editor integration) |
|
|
56
|
+
| `abide init-agent` | write/refresh a CLAUDE.md pointer to this surface map (non-scaffolded projects) |
|
|
57
|
+
|
|
58
|
+
For tests, add `preload = ["@abide/abide/preload"]` under `[test]` in `bunfig.toml` and use `bun test`.
|
|
79
59
|
|
|
80
60
|
## Authoring contracts
|
|
81
61
|
|
|
82
|
-
**RPC
|
|
83
|
-
`
|
|
84
|
-
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
raw `Response`. `opts`: `inputSchema` (validates args, infers the type, gates
|
|
88
|
-
CLI + read-MCP), `outputSchema` (documents the 200 body for OpenAPI/MCP),
|
|
89
|
-
`filesSchema` (multipart File parts), `clients: { browser, mcp, cli }` (explicit
|
|
90
|
-
surface targeting; explicit wins over schema auto-flip), `crossOrigin` (exempt
|
|
91
|
-
a mutating verb from the same-origin gate), `maxBodySize` (per-verb 413
|
|
92
|
-
ceiling), `timeout` (handler deadline in ms; 504 on every surface). Query args
|
|
93
|
-
arrive as strings — use `z.coerce.*`. Consume four ways: `cache(verb)(args)`
|
|
94
|
-
in-process, the swapped browser `fetch`, `verb.raw(args)` for the `Response`,
|
|
95
|
-
`verb.stream(args)` to iterate a streaming body.
|
|
96
|
-
|
|
97
|
-
**Socket** — `export const <name> = socket({ schema?, tail?, ttl?,
|
|
98
|
-
clientPublish?, clients? })`. `tail` retains the last N frames for late joiners
|
|
99
|
-
and the read faces; `ttl` lazily evicts frames older than N ms; `clientPublish`
|
|
100
|
-
(default off) gates browser publishes; `schema` validates publishes
|
|
101
|
-
synchronously and flips MCP/CLI on. Isomorphic `AsyncIterable<T>`: bare
|
|
102
|
-
iteration is the live stream, `.tail(count?)` seeds from retention,
|
|
103
|
-
`.publish(msg)` fans out in-process + over the multiplexed ws.
|
|
104
|
-
|
|
105
|
-
**Page / layout** — a `[id]` folder segment becomes `page.params.id`. A layout's
|
|
106
|
-
`<slot/>` is the outlet the next layer fills. Read `page` (route, params, url,
|
|
107
|
-
navigating) and call `navigate(path)` for SPA transitions.
|
|
108
|
-
|
|
109
|
-
**App / config** — `src/app.ts` default-exports an `AppModule`; `src/server/config.ts`
|
|
110
|
-
runs `env(schema)` at boot.
|
|
111
|
-
|
|
112
|
-
**Isomorphism move** — wrap an SSR read in `cache(fn)()` so the value serializes
|
|
113
|
-
into the document and the client hydrates warm instead of refetching.
|
|
62
|
+
- **RPC** — `export const <name> = METHOD(handler, opts?)` in `src/server/rpc/<name>.ts`. The handler receives the parsed args (`InferOutput<inputSchema>`, or the raw `Args` when schemaless), reads request state via `request()` / `cookies()`, and returns `json` / `jsonl` / `sse` / `error` / `redirect` / a raw `Response`. `opts`: `inputSchema`, `outputSchema`, `filesSchema` (multipart upload), `errors`, `clients: { browser, mcp, cli }`, `crossOrigin` (CSRF exemption), `maxBodySize` (413 past it), `timeout` (504, every surface), `outbox` (durable mutating delivery). Query args (GET/DELETE/HEAD) arrive as strings — use `z.coerce.*`. Consume four ways: `cache(fn)()` in-process, the swapped `fetch` proxy in the browser, `fn.raw(args)` (untouched `Response`), `fn.stream(args)` (frame stream). A non-2xx throws `HttpError`; `fn.isError(err, name)` type-guards it against the rpc's own `errors` (plus `'validation'` / `'queued'`), narrowing `.kind` and the matching `.data`.
|
|
63
|
+
- **Socket** — `export const <name> = socket(opts)` in `src/server/sockets/<name>.ts`. A `Socket<T>` is an `AsyncIterable<T>`: bare iteration is the live stream; `<name>.tail(count?)` seeds from the retained tail; `<name>.publish(m)` is isomorphic. `opts`: `schema` (validates publishes, infers `T`, flips MCP/CLI faces on), `tail` (retained frame count), `ttl` (lazy age eviction), `clientPublish` (allow browser publishes), `clients`.
|
|
64
|
+
- **Page / layout** — `.abide` files under `src/ui/pages/`. A `[id]` segment lands on `page.params.id`; a layout's `<slot/>` is the outlet the child fills; read the route via `page`, navigate via `url` / `navigate`.
|
|
65
|
+
- **app.ts / config.ts** — `app.ts` exports optional `AppModule` hooks (`init` → cleanup, `handle` middleware, `handleError`); `config.ts` exports `env(schema)`, validated synchronously at boot.
|
|
66
|
+
- **Isomorphism move** — read through `cache()` during SSR so the value bakes into the HTML and the matching `{#await}` adopts the server DOM warm on hydration (no refetch).
|
|
114
67
|
|
|
115
68
|
## .abide template grammar
|
|
116
69
|
|
|
117
|
-
A component file
|
|
118
|
-
reactive declarations) + optional `<template name="…">` snippet definitions +
|
|
119
|
-
markup + an optional component-scoped `<style>`. Ambient in-scope names need no
|
|
120
|
-
import: `scope`, `props` / `prop`, `effect`, `html`, `snippet`.
|
|
70
|
+
A component is one `.abide` file: valid HTML with an optional `<script lang="ts">`, `{expr}` bindings, `{#…}` control-flow blocks, `<template name>` snippets, capitalised component tags, and a component-scoped `<style>`. The browser's parser is the tree-builder, so SVG/MathML and foreign content work. Ambient in every component (no import): `scope`, `props`, `effect`; `html` and `snippet` are the templating brands.
|
|
121
71
|
|
|
122
|
-
**Reactive state**
|
|
72
|
+
**Reactive state** — reached through `scope()` (destructure `const { state, computed, linked } = scope()` once, or call `scope().state(…)` directly). A bare `state` / `computed` / `linked` with no `scope()` in view is a compile error.
|
|
123
73
|
|
|
124
|
-
| Form
|
|
125
|
-
|
|
|
126
|
-
| `scope().state(
|
|
127
|
-
| `scope().
|
|
128
|
-
| `scope().
|
|
129
|
-
| `effect(fn)`
|
|
130
|
-
| `props()`
|
|
74
|
+
| Form | Is |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `scope().state(value, transform?)` | a writable cell — read/reassigned as a plain variable; optional `transform(next, prev)` coerces every write |
|
|
77
|
+
| `scope().linked(fn, transform?)` | a writable local draft seeded from upstream — reseeds when the source changes, edits stay local |
|
|
78
|
+
| `scope().computed(fn)` | a read-only derived value — re-runs when a cell it reads changes |
|
|
79
|
+
| `scope().effect(fn)` | a client-only side effect (stripped from SSR); return a function to clean up |
|
|
80
|
+
| `props()` | destructure component props (`const { name = fallback, ...rest } = props()`), each a reactive read |
|
|
81
|
+
|
|
82
|
+
A two-way binding over derived state is an accessor at the bind site (`bind:value={{ get, set }}`), not a writable primitive.
|
|
131
83
|
|
|
132
84
|
**Bindings**
|
|
133
85
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
| `{expr}`
|
|
137
|
-
| `name={expr}`
|
|
138
|
-
| `on<event>={fn}`
|
|
139
|
-
| `bind:value={x}`
|
|
140
|
-
| `bind:
|
|
141
|
-
| `
|
|
142
|
-
| `bind:value={{ get, set }}` | Writable computed at the binding site. |
|
|
143
|
-
| `{...expr}` | Spread keys as attributes (elements) or props (components). |
|
|
144
|
-
| `attach={fn}` | Build-time element attachment with optional teardown. |
|
|
145
|
-
|
|
146
|
-
**Control flow** — native `<template>` tags:
|
|
147
|
-
|
|
148
|
-
| Form | Meaning |
|
|
149
|
-
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
150
|
-
| `<template if={c}>` / `<template elseif={c}>` / `<template else>` | Conditional, source-order, re-evaluated reactively. |
|
|
151
|
-
| `<template each={list} as="x" key="x.id" index="i">` | Keyed list; reorder/re-key updates rows in place; `index` is reactive. |
|
|
152
|
-
| `<template each await={asyncIter} as="x" key="…">` | Async keyed list; rows append as the iterator yields. |
|
|
153
|
-
| `<template await={p}>` / `<template then="v">` / `<template catch="e">` / `<template finally>` | Promise branches; `await={p} then="v"` on one tag renders inline (blocking) on the server. |
|
|
154
|
-
| `<template switch={s}>` / `<template case="v">` / `<template default>` | First strict (`===`) match wins. |
|
|
155
|
-
| `<template try>` / `<template catch="e">` / `<template finally>` | Synchronous render error boundary. |
|
|
156
|
-
| `<template name="row" args={item}>` … `{row(item)}` | Snippet definition + call. |
|
|
157
|
-
|
|
158
|
-
**Components & slots** — a capitalised tag (`<Card title={x}>`) mounts a child;
|
|
159
|
-
attributes become props, children fill the child's `<slot>` (with fallback when
|
|
160
|
-
empty). `<style>` is scoped to the component and its children. Component files
|
|
161
|
-
end in `.abide`. `then`/`each` value names lexically shadow same-named
|
|
162
|
-
component state inside the block.
|
|
163
|
-
|
|
164
|
-
## Server surface — abide/server/\* (server-only)
|
|
165
|
-
|
|
166
|
-
### RPC — @documentation rpc
|
|
167
|
-
|
|
168
|
-
- `@abide/abide/server/GET` — declare a `GET` verb; args from the query string. Schema auto-exposes CLI + read-MCP.
|
|
169
|
-
- `@abide/abide/server/POST` — declare a `POST` verb; args from JSON/form/multipart body (body wins on collision).
|
|
170
|
-
- `@abide/abide/server/PUT` — declare a `PUT` verb (body args; mutating).
|
|
171
|
-
- `@abide/abide/server/PATCH` — declare a `PATCH` verb (body args; mutating).
|
|
172
|
-
- `@abide/abide/server/DELETE` — declare a `DELETE` verb (query args; mutating).
|
|
173
|
-
- `@abide/abide/server/HEAD` — declare a `HEAD` verb (query args; read-only, headers-only response).
|
|
174
|
-
|
|
175
|
-
### Response — @documentation response
|
|
176
|
-
|
|
177
|
-
- `@abide/abide/server/json` — `json(data, init?)`: JSON `TypedResponse` (`Cache-Control: no-store`); `undefined` → 204.
|
|
178
|
-
- `@abide/abide/server/jsonl` — `jsonl(asyncIterable, init?)`: JSONL stream, one value per line; errors emit a `{"$error"}` final line.
|
|
179
|
-
- `@abide/abide/server/sse` — `sse(asyncIterable, init?)`: Server-Sent Events with 15s keepalive comments; errors as an `error` event.
|
|
180
|
-
- `@abide/abide/server/error` — `error(status, message?, init?)`: plain-text error `TypedResponse<never>` (narrows out of the success union).
|
|
181
|
-
- `@abide/abide/server/redirect` — `redirect(url, status=302, init?)`: redirect accepting relative URLs; `TypedResponse<never>`.
|
|
86
|
+
| Syntax | Binds |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `{expr}` | reactive text / snippet / `html` interpolation (escaped unless `html`-branded) |
|
|
89
|
+
| `name={expr}` | reactive attribute (`false`/`null`/`undefined` removes it) |
|
|
90
|
+
| `on<event>={fn}` | event listener (`onclick`, `onsubmit`, …) |
|
|
91
|
+
| `bind:value={x}` / `bind:checked={x}` / `bind:group={x}` | two-way form binding |
|
|
92
|
+
| `bind:value={{ get, set }}` | two-way binding over derived state |
|
|
93
|
+
| `{...expr}` | spread props (component) or attributes (element) |
|
|
182
94
|
|
|
183
|
-
|
|
95
|
+
**Control flow** — mustache blocks (`{#…}` open, `{:…}` branch, `{/…}` close):
|
|
184
96
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
97
|
+
| Block | Form |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| if | `{#if cond}` … `{:elseif cond}` … `{:else}` … `{/if}` |
|
|
100
|
+
| for | `{#for item of list by key}` … `{/for}` (`item, i of list`; `{#for await x of source …}` over an AsyncIterable) |
|
|
101
|
+
| await | `{#await promise}` pending `{:then value}` … `{:catch error}` … `{/await}` (inline `{#await p then v}`) |
|
|
102
|
+
| switch | `{#switch subject}` `{:case value}` … `{:default}` … `{/switch}` |
|
|
103
|
+
| try | `{#try}` … `{:catch error}` … `{:finally}` … `{/try}` |
|
|
104
|
+
| snippet | `<template name="row" args={{ msg }}>…</template>`, called as `{row({ msg })}` |
|
|
188
105
|
|
|
189
|
-
|
|
106
|
+
**Components & slots** — a capitalised tag (`<Avatar name={…} />`) mounts a child `.abide` component as a marker-bounded range (no wrapper element); its children fill the child's `<slot>`. `<style>` is component-scoped.
|
|
107
|
+
|
|
108
|
+
## Server surface — abide/server/*
|
|
190
109
|
|
|
191
|
-
|
|
110
|
+
### RPC helpers — @documentation rpc
|
|
111
|
+
|
|
112
|
+
- `abide/server/GET` — declare a read RPC; the bundler rewrites it to a server `defineRpc` or a client `remoteProxy`. Calling it directly throws.
|
|
113
|
+
- `abide/server/POST` — declare a creating mutating RPC (carries the durable `outbox` overloads).
|
|
114
|
+
- `abide/server/PUT` — declare a replacing mutating RPC.
|
|
115
|
+
- `abide/server/PATCH` — declare a partial-update mutating RPC.
|
|
116
|
+
- `abide/server/DELETE` — declare a deleting mutating RPC.
|
|
117
|
+
- `abide/server/HEAD` — declare a metadata-only read RPC.
|
|
192
118
|
|
|
193
119
|
### Sockets — @documentation sockets
|
|
194
120
|
|
|
195
|
-
-
|
|
121
|
+
- `abide/server/socket` — declare a broadcast `Socket<T>` in `src/server/sockets/<name>.ts`; opts (`schema`, `tail`, `ttl`, `clientPublish`, `clients`) live on the server, the client proxy discards them.
|
|
196
122
|
|
|
197
|
-
###
|
|
123
|
+
### Responses — @documentation response
|
|
124
|
+
|
|
125
|
+
- `abide/server/json` — JSON `Response` with `Cache-Control: no-store` default; `json(undefined)` emits a 204 that round-trips back to `undefined`. Brands `T` so the RPC infers `Return`.
|
|
126
|
+
- `abide/server/jsonl` — wrap an `AsyncIterable<Frame>` as a JSON Lines (`application/jsonl`) streaming response; cancellation flows into the generator's `return()`, errors become a final `{"$error":…}` line.
|
|
127
|
+
- `abide/server/sse` — wrap an `AsyncIterable<Frame>` as Server-Sent Events (`text/event-stream`) with a 15s keepalive; errors become an `event: error` frame.
|
|
128
|
+
- `abide/server/error` — return a non-2xx wire error (`TypedResponse<never>`); the caller's `await fn(args)` throws `HttpError`, so it never pollutes the inferred success `Return`.
|
|
129
|
+
- `abide/server/redirect` — return a 3xx redirect (`TypedResponse<never>`), same inference-neutral shape as `error`.
|
|
130
|
+
|
|
131
|
+
### Request scope — @documentation request-scope
|
|
132
|
+
|
|
133
|
+
- `abide/server/request` — the inbound `Request` for the current SSR/RPC pass (AsyncLocalStorage); throws outside a request scope.
|
|
134
|
+
- `abide/server/cookies` — the request's `Bun.CookieMap`; reads parse the inbound header, writes flush as `Set-Cookie` on return. Lazy; throws outside a scope.
|
|
135
|
+
- `abide/server/server` — the active `Bun.serve` instance; returns a no-op in-process server under a scope without a booted server (CLI/MCP/test), throws before init outside any scope.
|
|
136
|
+
|
|
137
|
+
### Configuration — @documentation configuration
|
|
198
138
|
|
|
199
|
-
-
|
|
139
|
+
- `abide/server/env` — validate `Bun.env` against a Standard Schema at boot and return the typed config; reports every issue at once on failure, registers the schema for the bundle setup form.
|
|
200
140
|
|
|
201
141
|
### Observability — @documentation observability
|
|
202
142
|
|
|
203
|
-
-
|
|
143
|
+
- `abide/server/reachable` — server-only outbound reachability: `await reachable(host)` HEADs the origin, caches the verdict, and background-polls every TTL so later calls resolve instantly.
|
|
144
|
+
|
|
145
|
+
### Bundle data — @documentation bundle
|
|
146
|
+
|
|
147
|
+
- `abide/server/appDataDir` — the running desktop bundle's per-user data dir, keyed by the program name; cwd-independent, pure.
|
|
148
|
+
|
|
149
|
+
### Agent — @documentation agent
|
|
150
|
+
|
|
151
|
+
- `abide/server/agent` — run a provider engine against the app's own MCP surface (`agent(engine, messages)`) and yield a neutral `AgentFrame` stream; the handler frames it with `jsonl()`/`sse()`. Exports `NeutralMessage` / `AgentFrame` / `AgentEngine`.
|
|
204
152
|
|
|
205
153
|
### Plumbing — @documentation plumbing
|
|
206
154
|
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
155
|
+
- `abide/server/AppModule` — the optional `src/app.ts` hook shape (`init` → cleanup, single-middleware `handle`, `handleError`).
|
|
156
|
+
- `abide/server/InspectorContext` — the capability bundle core injects into `@abide/inspector` when `ABIDE_ENABLE_INSPECTOR=true`, so the inspector stays a pure consumer.
|
|
157
|
+
- `abide/server/rpc/defineRpc` — server-side RPC construction from method + URL + handler; the bundler's server-target rewrite emits it. Records the synthesized Request for `cache()`.
|
|
158
|
+
- `abide/server/sockets/defineSocket` — server-side socket construction; the bundler's server-target rewrite binds the file-path name into real fan-out over `server.publish`.
|
|
159
|
+
- `abide/server/prompts/definePrompt` — register an MCP prompt from a name + options; the resolver plugin emits it per `src/mcp/prompts/<name>.md`.
|
|
160
|
+
- `abide/server/prompts/renderPromptTemplate` — substitute `{{name}}` placeholders in a prompt body (missing args collapse to empty).
|
|
211
161
|
|
|
212
|
-
## Isomorphic surface — abide/shared
|
|
162
|
+
## Isomorphic surface — abide/shared/*
|
|
213
163
|
|
|
214
|
-
###
|
|
164
|
+
### Responses — @documentation response
|
|
215
165
|
|
|
216
|
-
-
|
|
166
|
+
- `abide/shared/HttpError` — thrown by remote-function calls on a non-2xx response; carries the raw `Response` (status/`statusText`/headers/body) plus the typed-error layer parsed off a `{ $abideError, data }` body: `.kind` (the declared error name, `'validation'`, or the framework-reserved `'queued'`) and `.data` (`unknown` — narrow yourself; `ValidationErrorData` for `'validation'`). Both undefined for a plain `error(status, text)`.
|
|
167
|
+
- `abide/shared/ValidationErrorData` — the `data` a `kind: 'validation'` HttpError (422) carries: `{ issues, fields }` — the raw Standard Schema issue list plus the form-friendly field → first-message map.
|
|
217
168
|
|
|
218
|
-
###
|
|
169
|
+
### Schema projection — @documentation rpc
|
|
219
170
|
|
|
220
|
-
-
|
|
221
|
-
- `@abide/abide/shared/snippet` — `snippet(payload)`: brand a snippet payload (client DOM builder / server HTML string) so `{expr}` mounts it.
|
|
171
|
+
- `abide/shared/withJsonSchema` — attach a `toJSONSchema()` projection to a Standard Schema whose library lacks one, feeding OpenAPI / MCP / CLI / the setup form.
|
|
222
172
|
|
|
223
|
-
###
|
|
173
|
+
### Templating — @documentation templating
|
|
224
174
|
|
|
225
|
-
-
|
|
175
|
+
- `abide/shared/html` — a `` html`…` `` tag marking trusted raw markup that a `{expr}` inserts verbatim (registered-Symbol brand, survives bundle copies).
|
|
176
|
+
- `abide/shared/snippet` — the `Snippet<Payload>` brand a `<template name>` carries: a DOM builder on the client, pre-rendered HTML on the server.
|
|
226
177
|
|
|
227
|
-
###
|
|
178
|
+
### Cache — @documentation cache
|
|
228
179
|
|
|
229
|
-
-
|
|
180
|
+
- `abide/shared/cache` — curry a call against a store: `cache(fn, options?)` returns an invoker that coalesces in-flight calls and retains by `ttl` (undefined = forever, 0 = dedupe-only). Reactive (subscribes the reading scope), isomorphic, `options.global` for the process store. `cache.invalidate` / `cache.on` address entries by selector.
|
|
230
181
|
|
|
231
182
|
### Page — @documentation page
|
|
232
183
|
|
|
233
|
-
-
|
|
184
|
+
- `abide/shared/page` — the reactive page proxy (matched route, decoded `params`, browser-space `url`, `navigating`); isomorphic, re-runs readers on navigation.
|
|
234
185
|
|
|
235
|
-
###
|
|
186
|
+
### Probes — @documentation probes
|
|
236
187
|
|
|
237
|
-
-
|
|
188
|
+
- `abide/shared/pending` — reactive "no value yet" probe over the cache + tail registries; selector grammar `pending(fn)` / `pending(fn, args)` / `pending({ tags })` / `pending(subscribable)`. Counts undelivered durable-outbox entries.
|
|
189
|
+
- `abide/shared/refreshing` — reactive "holding a value while a fresher source is in flight" probe; same selector grammar.
|
|
190
|
+
- `abide/shared/online` — the client/server-reported connectivity boolean (the inbound counterpart to `reachable`).
|
|
238
191
|
|
|
239
|
-
###
|
|
192
|
+
### URL — @documentation url
|
|
240
193
|
|
|
241
|
-
-
|
|
242
|
-
- `@abide/abide/shared/refreshing` — `refreshing(selector?, args?)`: reactive — a value held while fresh data is in flight (SWR refetch / reconnect with retained value).
|
|
243
|
-
- `@abide/abide/shared/online` — `online()`: reactive connectivity (client `navigator.onLine`; server reads the caller's reported state); reports, never acts.
|
|
194
|
+
- `abide/shared/url` — typed URL builder: `url('/rpc/search', { q })` types args against the generated `RpcRoutes`, falling through to page/asset paths; base-correct.
|
|
244
195
|
|
|
245
196
|
### Observability — @documentation observability
|
|
246
197
|
|
|
247
|
-
-
|
|
248
|
-
-
|
|
249
|
-
-
|
|
198
|
+
- `abide/shared/health` — reactive backend health (`reachable` + the app `health()` hook's fields), polled from `/__abide/health` only while a tracking scope reads it; constant `{ reachable: true }` on the server.
|
|
199
|
+
- `abide/shared/log` — the unified logger: `log`/`warn`/`error`/`trace` on the app's always-on channel, `log.channel(name)` on a DEBUG-gated channel; tsv default or JSON per line (`ABIDE_LOG_FORMAT=json`). Carries request-scope context.
|
|
200
|
+
- `abide/shared/trace` — the current request's W3C `traceparent`, isomorphic (ALS on the server, `__SSR__` stamp in the browser); undefined outside a scope.
|
|
250
201
|
|
|
251
202
|
### Plumbing — @documentation plumbing
|
|
252
203
|
|
|
253
|
-
-
|
|
204
|
+
- `abide/shared/createSubscriber` — abide-ui-native open-on-first-read / close-on-last-reader subscriber over abide's own signal core (the lifecycle `cache`/`tail`/`health` reuse).
|
|
254
205
|
|
|
255
|
-
## UI surface — abide/ui
|
|
206
|
+
## UI surface — abide/ui/* (client-only)
|
|
256
207
|
|
|
257
208
|
### Reactive state — @documentation reactive-state
|
|
258
209
|
|
|
259
|
-
-
|
|
210
|
+
- `abide/ui/scope` — resolve a lexical scope: `scope()` is the current one (compiler-established per level), `scope('/')` the tree root; the returned value is passable to children/helpers.
|
|
260
211
|
|
|
261
|
-
###
|
|
212
|
+
### Streaming — @documentation tail
|
|
262
213
|
|
|
263
|
-
-
|
|
214
|
+
- `abide/ui/tail` — reactive consumer for a `Subscribable<T>` (a `Socket<T>` or `fn.stream(args)`): bare form is latest-wins (`T | undefined`), `{ last: n }` is a live window (`T[]`); reconnect keeps the value and flags `refreshing`. No-op on the server. `tail.error` / `tail.status` address the same entry.
|
|
264
215
|
|
|
265
|
-
###
|
|
216
|
+
### Navigation — @documentation navigate
|
|
266
217
|
|
|
267
|
-
-
|
|
218
|
+
- `abide/ui/navigate` — programmatic SPA navigation typed off the page routes; `NavigateOptions` carries `replace` / `keepScroll`. Delegates path-building to `url`.
|
|
268
219
|
|
|
269
|
-
###
|
|
220
|
+
### Outbox — @documentation ui
|
|
270
221
|
|
|
271
|
-
-
|
|
272
|
-
|
|
273
|
-
### UI — @documentation ui
|
|
274
|
-
|
|
275
|
-
- `@abide/abide/ui/outbox` — `outbox({ key, send, store, online, onDrop })`: durable FIFO mutation queue for local-first writes; drains while online, retries on reconnect, at-least-once.
|
|
222
|
+
- `abide/ui/outbox` — the global reactive view of every durable-RPC outbox: a flat list of undelivered entries tagged with their `rpc`, `outbox.retry()` to drain all queues. A single RPC's slice is `rpc.outbox`. Empty on the server. Exports `GlobalOutboxEntry`.
|
|
276
223
|
|
|
277
224
|
### Plumbing — @documentation plumbing
|
|
278
225
|
|
|
279
|
-
-
|
|
280
|
-
-
|
|
281
|
-
-
|
|
282
|
-
-
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
-
|
|
287
|
-
-
|
|
288
|
-
-
|
|
289
|
-
-
|
|
290
|
-
-
|
|
291
|
-
-
|
|
292
|
-
-
|
|
293
|
-
-
|
|
294
|
-
-
|
|
295
|
-
-
|
|
296
|
-
-
|
|
297
|
-
-
|
|
298
|
-
-
|
|
299
|
-
-
|
|
300
|
-
-
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
304
|
-
-
|
|
305
|
-
-
|
|
306
|
-
-
|
|
307
|
-
-
|
|
308
|
-
-
|
|
309
|
-
-
|
|
310
|
-
-
|
|
311
|
-
-
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
-
|
|
315
|
-
-
|
|
316
|
-
-
|
|
317
|
-
-
|
|
226
|
+
- `abide/ui/effect` — abide's reaction primitive: run `fn` now, re-run on dep change, optional (async) teardown; returns a dispose. The runtime target the compiler emits for `scope().effect`.
|
|
227
|
+
- `abide/ui/enterScope` — open a fresh lexical scope for an SSR render, returning the previous to restore.
|
|
228
|
+
- `abide/ui/exitScope` — restore the scope `enterScope` saved.
|
|
229
|
+
- `abide/ui/remoteProxy` — the client-side RPC substitute the bundler emits per export: fetches, decodes by Content-Type, throws `HttpError`; a durable (`outbox`) RPC parks an unreachable request for replay as a side-effect. Exports `DurableOptions`.
|
|
230
|
+
- `abide/ui/socketProxy` — the client-side socket substitute: subscribe/publish over the multiplexed ws channel, same `Socket` shape as the server.
|
|
231
|
+
- `abide/ui/startClient` — the official client entry: read `__SSR__`, seed the warm cache store, install the mount base, start the router.
|
|
232
|
+
- `abide/ui/router` — the History-API client router: match the path, import the page chunk + its layout chain, mount the chain into nested `<slot/>` outlets.
|
|
233
|
+
- `abide/ui/renderToStream` — out-of-order SSR streaming: shell first, then one `<abide-resolve>` fragment per streaming `{#await}` as it settles.
|
|
234
|
+
- `abide/ui/runtime/escapeKey` — escape one object key into a JSON-Pointer token (`~0`/`~1`) so a key with `/` or `~` survives a `/`-joined path.
|
|
235
|
+
- `abide/ui/runtime/nextBlockId` — the next block id in the current render pass (document order), so page and child ids don't collide.
|
|
236
|
+
- `abide/ui/runtime/enterRenderPass` — mark entry into a render/mount; the outermost resets the block-id counter.
|
|
237
|
+
- `abide/ui/runtime/exitRenderPass` — mark exit from a render/mount, unwinding the depth.
|
|
238
|
+
- `abide/ui/dom/mount` — mount a top-level page/layout into a host element under an ownership scope; returns a disposer.
|
|
239
|
+
- `abide/ui/dom/mountChild` — mount a child component as a marker-bounded range (no wrapper); hot path keeps the range for in-place HMR re-fill.
|
|
240
|
+
- `abide/ui/dom/mountSlot` — mount a component's `<slot>` content as a marker range (parent `$children` or fallback); renders once.
|
|
241
|
+
- `abide/ui/dom/outlet` — a layout's `<slot/>` outlet as an empty comment boundary the router fills with the next chain layer.
|
|
242
|
+
- `abide/ui/dom/mergeProps` — compose a child's props from ordered layers (explicit thunks, spreads, the `$children` slot), last layer wins per key.
|
|
243
|
+
- `abide/ui/dom/spreadProps` — wrap a `{...source}` props layer so each key resolves to a live value thunk; the source thunk re-reads reactively.
|
|
244
|
+
- `abide/ui/dom/restProps` — the unconsumed props of a `const { a, ...rest } = props()` as a live object (thunks unwrapped; plain page params returned as-is).
|
|
245
|
+
- `abide/ui/dom/spreadAttrs` — spread an object's keys onto a native element (`<div {...rest}>`): keys enumerated once, each value live; `on*` keys attach as listeners.
|
|
246
|
+
- `abide/ui/dom/attr` — bind one element attribute to `read()` (boolean present/absent, else stringified); one effect per attribute.
|
|
247
|
+
- `abide/ui/dom/on` — attach an event listener scoped to the owning component (the `onclick={…}` runtime target), pinned to its `scope()`.
|
|
248
|
+
- `abide/ui/dom/attach` — run a node-lifetime attachment at build time with optional teardown (the dual of `on`); may be async.
|
|
249
|
+
- `abide/ui/dom/text` — a text node tracking `read()` via one effect (plain text, `String()`-coerced).
|
|
250
|
+
- `abide/ui/dom/appendText` — a reactive `{expr}` interpolation (escaped text, snippet, or `html`); claims and splits merged SSR text on hydrate.
|
|
251
|
+
- `abide/ui/dom/appendTextAt` — a reactive `{expr}` mounted at a skeleton anchor, for text interleaved with element siblings.
|
|
252
|
+
- `abide/ui/dom/appendStatic` — a static (non-reactive) text node, claimed/split from SSR text on hydrate.
|
|
253
|
+
- `abide/ui/dom/appendSnippet` — a `{snippet(args)}` interpolation mounted in a marker-bounded range; reactive in its args.
|
|
254
|
+
- `abide/ui/dom/cloneStatic` — append a fully-static subtree from a compiler skeleton string (byte-identical to SSR markup).
|
|
255
|
+
- `abide/ui/dom/skeleton` — realize a compiled skeleton under a parent and return its element holes (pre-order) + anchor holes (document order); the parser is the tree-builder, so foreign content lands namespaced.
|
|
256
|
+
- `abide/ui/dom/anchorCursor` — position a skeleton-anchored control-flow block or slot relative to its `<!--a-->` marker.
|
|
257
|
+
- `abide/ui/dom/readCall` — a guarded method call on a reactive-doc read, so a nullish throw names the authored scope path instead of the desugared call.
|
|
258
|
+
- `abide/ui/dom/hydrate` — adopt server-rendered DOM: run `build` with a claim cursor so dom helpers take existing nodes; returns a disposer.
|
|
259
|
+
- `abide/ui/dom/each` — the keyed `{#for … by key}` runtime: each row a marker-bounded range reconciled by key.
|
|
260
|
+
- `abide/ui/dom/eachAsync` — the async `{#for await … by key}` runtime over an `AsyncIterable`; SSR renders no rows.
|
|
261
|
+
- `abide/ui/dom/when` — the `{#if}` (+ `{:else}`) runtime: a branch range swapped on a truthy↔falsy flip.
|
|
262
|
+
- `abide/ui/dom/awaitBlock` — the `{#await}` runtime: pending → resolved/error branch on settle, each a range.
|
|
263
|
+
- `abide/ui/dom/tryBlock` — the `{#try}` runtime: a synchronous error boundary; build throw → `{:catch}` branch, no catch re-throws.
|
|
264
|
+
- `abide/ui/dom/switchBlock` — the `{#switch}` runtime: first `===`-matching case (or default), each a range.
|
|
265
|
+
- `abide/ui/dom/applyResolved` — bundle-side consumer of an SSR stream chunk (streaming SPA nav, socket-delivered SSR): seed cache partitions and swap await boundaries.
|
|
318
266
|
|
|
319
267
|
## Build / tooling
|
|
320
268
|
|
|
321
269
|
### Building — @documentation building
|
|
322
270
|
|
|
323
|
-
-
|
|
324
|
-
-
|
|
271
|
+
- `abide/build` — build the client bundle into `dist/_app` (Bun.build + the `.abide` loader, virtual-module resolver, optional Tailwind; `compress` writes `.gz` siblings).
|
|
272
|
+
- `abide/compile` — produce a standalone Bun server executable (runs `build` first to embed assets); returns the binary path.
|
|
325
273
|
|
|
326
274
|
### Plumbing — @documentation plumbing
|
|
327
275
|
|
|
328
|
-
-
|
|
329
|
-
-
|
|
330
|
-
-
|
|
331
|
-
-
|
|
276
|
+
- `abide/preload` — the Bun preload entry that installs the `.abide` loader + resolver for `abide run` and `bun test`.
|
|
277
|
+
- `abide/resolver-plugin` — the Bun plugin wiring every build-time virtual import (`abide:rpc` / `abide:sockets` / `abide:pages` / `abide:prompts` / `abide:app` …).
|
|
278
|
+
- `abide/ui-plugin` — the Bun plugin that compiles each `.abide` single-file component (and `layout.abide`) to its ES module.
|
|
279
|
+
- `abide/tsconfig` — the shareable base `tsconfig` (`tsconfig.app.json`) projects extend.
|
|
332
280
|
|
|
333
|
-
## Desktop bundle
|
|
281
|
+
## Desktop bundle — abide/bundle/*
|
|
334
282
|
|
|
335
283
|
### Bundle — @documentation bundle
|
|
336
284
|
|
|
337
|
-
-
|
|
338
|
-
-
|
|
339
|
-
-
|
|
340
|
-
-
|
|
341
|
-
-
|
|
342
|
-
- `@abide/abide/bundle/bundled` — `bundled()`: true when running inside the abide desktop bundle.
|
|
285
|
+
- `abide/bundle/BundleWindow` — the optional `src/bundle/window.ts` default-export shape (title, size, menus); baked into the launcher.
|
|
286
|
+
- `abide/bundle/BundleMenu` — a top-level menu inserted into the macOS menu bar (`label` + `items`).
|
|
287
|
+
- `abide/bundle/BundleMenuItem` — one menu entry: a divider or a clickable item that dispatches an `abide:menu` CustomEvent into the page.
|
|
288
|
+
- `abide/bundle/onMenu` — subscribe to bundle menu clicks (catch-all or per-name), returning an unsubscribe.
|
|
289
|
+
- `abide/bundle/bundled` — `true` when the code runs inside the abide desktop bundle; isomorphic, detected per side.
|
|
343
290
|
|
|
344
|
-
## MCP
|
|
291
|
+
## MCP — abide/mcp/*
|
|
345
292
|
|
|
346
293
|
### MCP — @documentation mcp
|
|
347
294
|
|
|
348
|
-
-
|
|
349
|
-
|
|
350
|
-
### Prompts — @documentation plumbing
|
|
351
|
-
|
|
352
|
-
- `@abide/abide/server/prompts/definePrompt` — `definePrompt(name, opts)`: build a `Prompt` from an `src/mcp/prompts/*.md` file (the bundler emits the call).
|
|
353
|
-
- `@abide/abide/server/prompts/renderPromptTemplate` — `renderPromptTemplate(template, args)`: substitute `{{name}}` placeholders (missing → empty string).
|
|
295
|
+
- `abide/mcp/createMcpServer` — construct the MCP server bound to the project's RPC registry; its `handle(request)` backs `/__abide/mcp`. Framework-internal (the `abide:mcp` virtual default-constructs it).
|
|
354
296
|
|
|
355
|
-
## Testing
|
|
297
|
+
## Testing — abide/test/*
|
|
356
298
|
|
|
357
299
|
### Testing — @documentation testing
|
|
358
300
|
|
|
359
|
-
-
|
|
301
|
+
- `abide/test/createTestApp` — an in-process test app exposing `app.rpc.<rpc>` / `app.sockets.<name>` typed against the project's generated surface (no network, no imports).
|
|
360
302
|
|
|
361
303
|
### Plumbing — @documentation plumbing
|
|
362
304
|
|
|
363
|
-
-
|
|
364
|
-
-
|
|
305
|
+
- `abide/test/createScriptedSurface` — a scripted `AgentSurface` for engine tests: declarative tool stubs in, an MCP surface out, every `call` recorded.
|
|
306
|
+
- `abide/test/assertAgentFrameConformance` — collect an engine's frame stream and assert the neutral `AgentFrame` contract (one terminal `done`, every `tool_use` answered, …).
|
|
365
307
|
|
|
366
308
|
## Generated machine surfaces
|
|
367
309
|
|
|
368
310
|
Runtime routes the framework serves:
|
|
369
311
|
|
|
370
|
-
| Route
|
|
371
|
-
|
|
|
372
|
-
| `/openapi.json`
|
|
373
|
-
| `/__abide/mcp`
|
|
374
|
-
| `/__abide/health`
|
|
375
|
-
| `/__abide/sockets`
|
|
376
|
-
| `/__abide/cli`
|
|
377
|
-
| `/__abide/
|
|
378
|
-
| `/__abide/
|
|
379
|
-
| `/__abide/
|
|
312
|
+
| Route | Serves |
|
|
313
|
+
| --- | --- |
|
|
314
|
+
| `/openapi.json` | the OpenAPI document projected from every RPC schema |
|
|
315
|
+
| `/__abide/mcp` | the MCP endpoint (tools/prompts from the RPC + prompt registries) |
|
|
316
|
+
| `/__abide/health` | the health payload (`reachable` + the app `health()` hook's fields) |
|
|
317
|
+
| `/__abide/sockets` | the multiplexed WebSocket hub (and `/__abide/sockets/<name>` HTTP face) |
|
|
318
|
+
| `/__abide/cli` | the CLI manifest the `abide cli` binary reads |
|
|
319
|
+
| `/__abide/identity` | the server identity the bundle/CLI client probes |
|
|
320
|
+
| `/__abide/inspector` | the inspector surface (when `ABIDE_ENABLE_INSPECTOR=true`) |
|
|
321
|
+
| `/__abide/hot` | the dev hot-reload channel |
|
|
380
322
|
|
|
381
323
|
## Environment variables
|
|
382
324
|
|
|
383
|
-
| Variable
|
|
384
|
-
|
|
|
385
|
-
| `PORT`
|
|
386
|
-
| `APP_URL`
|
|
387
|
-
| `ABIDE_APP_URL`
|
|
388
|
-
| `ABIDE_APP_TOKEN`
|
|
389
|
-
| `ABIDE_CLIENT_TIMEOUT`
|
|
390
|
-
| `ABIDE_MAX_REQUEST_BODY_SIZE` |
|
|
391
|
-
| `ABIDE_IDLE_TIMEOUT`
|
|
392
|
-
| `
|
|
393
|
-
| `ABIDE_REACHABLE_TTL`
|
|
394
|
-
| `
|
|
395
|
-
| `ABIDE_LOG_FORMAT`
|
|
396
|
-
| `DEBUG`
|
|
397
|
-
| `ABIDE_ENABLE_INSPECTOR`
|
|
398
|
-
| `ABIDE_INSPECT`
|
|
325
|
+
| Variable | Effect |
|
|
326
|
+
| --- | --- |
|
|
327
|
+
| `PORT` | server listen port (unset → abide scans from a default) |
|
|
328
|
+
| `APP_URL` | public origin; its pathname becomes the app's mount base (sub-path hosting) |
|
|
329
|
+
| `ABIDE_APP_URL` | runtime URL of the server the bundle/CLI client connects to |
|
|
330
|
+
| `ABIDE_APP_TOKEN` | bearer token the bundle/CLI client sends to an authenticated remote server |
|
|
331
|
+
| `ABIDE_CLIENT_TIMEOUT` | client-side per-call fetch timeout (ms); a breach surfaces as a 504 `HttpError` |
|
|
332
|
+
| `ABIDE_MAX_REQUEST_BODY_SIZE` | default inbound request-body byte cap (a per-RPC `maxBodySize` overrides) |
|
|
333
|
+
| `ABIDE_IDLE_TIMEOUT` | Bun per-connection idle timeout (seconds) |
|
|
334
|
+
| `ABIDE_DATA_DIR` | override the per-user app data dir on every platform (used as-is) |
|
|
335
|
+
| `ABIDE_REACHABLE_TTL` | `reachable()` poll cadence / freshness window (ms) |
|
|
336
|
+
| `ABIDE_REACHABLE_TIMEOUT` | `reachable()` per-HEAD probe bound (ms) |
|
|
337
|
+
| `ABIDE_LOG_FORMAT` | `json` switches the logger from tsv to one JSON object per line |
|
|
338
|
+
| `DEBUG` | enable DEBUG-gated diagnostic log channels (npm-debug conventions, e.g. `abide`, `abide:*`) |
|
|
339
|
+
| `ABIDE_ENABLE_INSPECTOR` | inject the `InspectorContext` into `@abide/inspector` (exposes all traffic; trusted use only) |
|
|
340
|
+
| `ABIDE_INSPECT` | enable the desktop bundle's right-click → Inspect web-inspector (off in release bundles) |
|
|
399
341
|
|
|
400
342
|
---
|
|
401
343
|
|
|
402
|
-
This map mirrors `package.json
|
|
403
|
-
run `bun run packages/abide/scripts/readmeSurfaces.ts` and update the matching
|
|
404
|
-
bullet here.
|
|
344
|
+
This map mirrors the `exports` map in `package.json`. After adding or renaming an export, run `bun run packages/abide/scripts/readmeSurfaces.ts` and update the matching section here.
|