@abide/abide 0.53.0 → 0.55.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 +330 -494
- package/CHANGELOG.md +106 -0
- package/README.md +166 -146
- package/package.json +3 -4
- package/src/checkAbide.ts +1 -1
- package/src/lib/server/rpc/defineRpc.ts +2 -1
- package/src/lib/server/rpc/types/RpcHelper.ts +29 -22
- package/src/lib/server/runtime/SSR_SWAP_SCRIPT.ts +3 -2
- package/src/lib/server/runtime/amendBroadcaster.ts +53 -0
- package/src/lib/server/runtime/createUiPageRenderer.ts +54 -20
- package/src/lib/server/runtime/runWithRequestScope.ts +1 -0
- package/src/lib/server/runtime/types/RequestStore.ts +9 -0
- package/src/lib/server/sockets/amendFamilyEntry.ts +39 -0
- package/src/lib/server/sockets/createSocketDispatcher.ts +9 -0
- package/src/lib/server/sockets/defineSocket.ts +11 -1
- package/src/lib/shared/AMEND_TOPIC_PREFIX.ts +9 -0
- package/src/lib/shared/SEEDS.ts +33 -0
- package/src/lib/shared/SOCKET_SEED.ts +12 -0
- package/src/lib/shared/amend.ts +48 -0
- package/src/lib/shared/amendBroadcastSlot.ts +19 -0
- package/src/lib/shared/applyAmendLocally.ts +20 -0
- package/src/lib/shared/attachRpcSelectorMethods.ts +5 -5
- package/src/lib/shared/buildSocketOverChannel.ts +9 -2
- package/src/lib/shared/cache.ts +203 -84
- package/src/lib/shared/cacheReaderSocketSlot.ts +11 -0
- package/src/lib/shared/createCacheStore.ts +8 -0
- package/src/lib/shared/createRemoteFunction.ts +4 -1
- package/src/lib/shared/encodeSeedValue.ts +24 -0
- package/src/lib/shared/jsonSchemaForType.ts +3 -16
- package/src/lib/shared/peek.ts +4 -7
- package/src/lib/shared/socketTailsSlot.ts +13 -0
- package/src/lib/shared/types/AmendApply.ts +15 -0
- package/src/lib/shared/types/CacheReaderHook.ts +11 -0
- package/src/lib/shared/types/RemoteFunction.ts +30 -19
- package/src/lib/shared/types/SocketTails.ts +13 -0
- package/src/lib/shared/types/SsrPayload.ts +6 -0
- package/src/lib/test/createTestApp.ts +6 -0
- package/src/lib/ui/amendReaderHook.ts +125 -0
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +1 -6
- package/src/lib/ui/compile/analyzeComponent.ts +0 -2
- package/src/lib/ui/compile/awaitSubjectExpr.ts +23 -0
- package/src/lib/ui/compile/cachedShadowProgram.ts +39 -0
- package/src/lib/ui/compile/compileComponent.ts +1 -3
- package/src/lib/ui/compile/componentOrdinals.ts +39 -0
- package/src/lib/ui/compile/desugarSignals.ts +65 -36
- package/src/lib/ui/compile/generateBuild.ts +25 -24
- package/src/lib/ui/compile/generateSSR.ts +37 -24
- package/src/lib/ui/compile/hoistableAwaits.ts +1 -11
- package/src/lib/ui/compile/interpolationClassifierForRoot.ts +8 -13
- package/src/lib/ui/compile/isSpuriousAsyncReadDiagnostic.ts +46 -5
- package/src/lib/ui/compile/lowerCompoundAssignment.ts +49 -0
- package/src/lib/ui/compile/lowerContext.ts +26 -6
- package/src/lib/ui/compile/lowerDocAccess.ts +19 -31
- package/src/lib/ui/compile/lowerScript.ts +1 -11
- package/src/lib/ui/compile/lowerUpdateExpression.ts +32 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +25 -45
- package/src/lib/ui/compile/seedTypeClassifierForRoot.ts +10 -15
- package/src/lib/ui/compile/shadowInterpolationClassifier.ts +1 -1
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +3 -5
- package/src/lib/ui/compile/wrapReactionCellSources.ts +10 -6
- package/src/lib/ui/compile/wrapReactiveSeeds.ts +44 -0
- package/src/lib/ui/compile/wrapSeed.ts +28 -0
- package/src/lib/ui/computed.ts +16 -0
- package/src/lib/ui/createScope.ts +4 -3
- package/src/lib/ui/dom/anchorCursor.ts +2 -1
- package/src/lib/ui/dom/anchoredBranch.ts +14 -3
- package/src/lib/ui/dom/appendStatic.ts +11 -20
- package/src/lib/ui/dom/appendText.ts +41 -43
- package/src/lib/ui/dom/appendTextAt.ts +10 -57
- package/src/lib/ui/dom/awaitBlock.ts +31 -45
- package/src/lib/ui/dom/awaitSubject.ts +118 -0
- package/src/lib/ui/dom/claimText.ts +38 -0
- package/src/lib/ui/dom/cloneStatic.ts +2 -8
- package/src/lib/ui/dom/discardAndRebuild.ts +23 -0
- package/src/lib/ui/dom/discardBoundary.ts +5 -4
- package/src/lib/ui/dom/each.ts +3 -5
- package/src/lib/ui/dom/fillBoundary.ts +2 -1
- package/src/lib/ui/dom/hydrate.ts +5 -12
- package/src/lib/ui/dom/mountChild.ts +73 -5
- package/src/lib/ui/dom/mountSwappableRange.ts +2 -1
- package/src/lib/ui/dom/openMarker.ts +2 -4
- package/src/lib/ui/dom/outlet.ts +4 -3
- package/src/lib/ui/dom/readCell.ts +26 -11
- package/src/lib/ui/dom/skeleton.ts +2 -7
- package/src/lib/ui/dom/switchBlock.ts +2 -1
- package/src/lib/ui/dom/tryBlock.ts +27 -39
- package/src/lib/ui/dom/when.ts +6 -2
- package/src/lib/ui/linked.ts +14 -0
- package/src/lib/ui/resumeSeedScript.ts +1 -1
- package/src/lib/ui/router.ts +12 -16
- package/src/lib/ui/runtime/AsyncCellError.ts +2 -1
- package/src/lib/ui/runtime/BRANCH_SEGMENT.ts +24 -0
- package/src/lib/ui/runtime/CELL_SEED.ts +4 -6
- package/src/lib/ui/runtime/DOC_SEED.ts +5 -6
- package/src/lib/ui/runtime/RENDER.ts +7 -5
- package/src/lib/ui/runtime/RESUME.ts +5 -7
- package/src/lib/ui/runtime/SEED_MARKS.ts +14 -0
- package/src/lib/ui/runtime/SuspenseSignal.ts +2 -2
- package/src/lib/ui/runtime/claimChild.ts +5 -7
- package/src/lib/ui/runtime/claimExpected.ts +2 -6
- package/src/lib/ui/runtime/claimMarker.ts +13 -0
- package/src/lib/ui/runtime/claimRun.ts +22 -0
- package/src/lib/ui/runtime/consumeSeed.ts +38 -0
- package/src/lib/ui/runtime/createAsyncCell.ts +56 -8
- package/src/lib/ui/runtime/createComputedNode.ts +1 -0
- package/src/lib/ui/runtime/createDoc.ts +5 -1
- package/src/lib/ui/runtime/createEffectNode.ts +1 -0
- package/src/lib/ui/runtime/createSignalNode.ts +1 -0
- package/src/lib/ui/runtime/parkCursor.ts +10 -0
- package/src/lib/ui/runtime/readNode.ts +21 -1
- package/src/lib/ui/runtime/renderPath.ts +2 -2
- package/src/lib/ui/runtime/routeBareSeed.ts +28 -0
- package/src/lib/ui/runtime/runHydrationPass.ts +69 -0
- package/src/lib/ui/runtime/runNode.ts +14 -0
- package/src/lib/ui/runtime/types/Cell.ts +4 -2
- package/src/lib/ui/runtime/types/Doc.ts +3 -1
- package/src/lib/ui/runtime/types/HydrationCursor.ts +8 -0
- package/src/lib/ui/runtime/types/ReactiveNode.ts +5 -0
- package/src/lib/ui/settleAsyncCells.ts +30 -3
- package/src/lib/ui/socketProxy.ts +17 -1
- package/src/lib/ui/startClient.ts +23 -0
- package/src/lib/ui/tryEncodeResume.ts +6 -15
- package/src/lib/ui/types/Scope.ts +1 -1
- package/src/lib/ui/watch.ts +21 -16
- package/src/serverEntry.ts +15 -0
- package/src/lib/shared/patch.ts +0 -41
- package/src/lib/ui/compile/COMPOUND_ASSIGNMENT_OPERATORS.ts +0 -19
- package/src/lib/ui/dom/mountStreamedChild.ts +0 -84
- package/src/lib/ui/dom/readCellBlocking.ts +0 -29
package/AGENTS.md
CHANGED
|
@@ -1,610 +1,446 @@
|
|
|
1
1
|
# AGENTS.md — abide complete surface map
|
|
2
2
|
|
|
3
|
-
> This file is the exhaustive map of abide's public surface: every `exports`
|
|
4
|
-
> grouped by namespace, with its import specifier and a one-line spec
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
> `docs/adr/`
|
|
3
|
+
> This file is the exhaustive map of abide's public surface: every `exports`
|
|
4
|
+
> key, grouped by namespace, with its import specifier and a one-line spec, plus
|
|
5
|
+
> the CLI, generated routes, env vars, and the `.abide` grammar. The README is
|
|
6
|
+
> the opposite — a curated intro to the three foundational primitives (RPCs,
|
|
7
|
+
> sockets, components). CONTEXT.md is the domain glossary; `docs/adr/` holds the
|
|
8
|
+
> rationale.
|
|
8
9
|
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
>
|
|
14
|
-
>
|
|
15
|
-
> `
|
|
16
|
-
> `invalidate`, `refresh`).
|
|
10
|
+
> **No barrels.** Every public name has its own module path — there is no
|
|
11
|
+
> umbrella `index.ts`, so importing one name never drags in side-effecting
|
|
12
|
+
> siblings. The namespace marks the side a name runs on: `abide/server/*` is
|
|
13
|
+
> server-only, `abide/ui/*` is client-only, `abide/shared/*` is isomorphic (same
|
|
14
|
+
> callable, same intent on both sides — usually identical behaviour, e.g.
|
|
15
|
+
> `HttpError`; sometimes a side-swapped runtime behind one intent, e.g.
|
|
16
|
+
> `invalidate`, `refresh`, `amend`).
|
|
17
17
|
>
|
|
18
|
-
> Package `@abide/abide
|
|
19
|
-
> (TypeScript).
|
|
20
|
-
>
|
|
21
|
-
>
|
|
22
|
-
> the on-disk file paths.
|
|
18
|
+
> Package `@abide/abide`, one runtime (Bun ≥ 1.3.0), one direct dependency
|
|
19
|
+
> (TypeScript). Below, a leading `@abide/abide/...` is the **import specifier**
|
|
20
|
+
> (an `exports` key); a `src/...` path is a **file-based convention** the bundler
|
|
21
|
+
> reads.
|
|
23
22
|
|
|
24
23
|
## The premise
|
|
25
24
|
|
|
26
|
-
One typed RPC declaration
|
|
25
|
+
One typed RPC declaration fans out to every surface:
|
|
27
26
|
|
|
28
27
|
```text
|
|
29
|
-
|
|
28
|
+
getMessages (src/server/rpc/getMessages.ts)
|
|
30
29
|
│
|
|
31
|
-
|
|
32
|
-
▼ ▼
|
|
33
|
-
SSR call
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
in-process fn(args) getMessages
|
|
30
|
+
┌──────────────┬──────────┼───────────────┬───────────────────┐
|
|
31
|
+
▼ ▼ ▼ ▼ ▼
|
|
32
|
+
SSR call browser MCP tool CLI OpenAPI op
|
|
33
|
+
(in-proc) fetch get_messages app get-messages GET /rpc/
|
|
34
|
+
smart read typed proxy (read → auto) --limit 20 getMessages
|
|
37
35
|
```
|
|
38
36
|
|
|
39
|
-
A **typed
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`schemas.input`. A declared `schemas.input`
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
A **typed input** unlocks the CLI, and for a read-only method (GET/HEAD) the MCP
|
|
38
|
+
tool: the handler's input-parameter type is projected to JSON Schema at build
|
|
39
|
+
(ADR-0030), so a plainly-typed handler auto-exposes with no hand-written
|
|
40
|
+
`schemas.input`. A declared `schemas.input` (a Standard Schema) adds runtime
|
|
41
|
+
validation on top; it is not what flips the surfaces on. A mutating method
|
|
42
|
+
(POST/PUT/PATCH/DELETE) never auto-exposes to MCP — it needs explicit
|
|
43
|
+
`clients: { mcp: true }`.
|
|
45
44
|
|
|
46
45
|
## File-based conventions
|
|
47
46
|
|
|
48
|
-
The bundler
|
|
49
|
-
tree: `$server`, `$ui`, `$shared`, `$mcp`, `$cli`.
|
|
47
|
+
The bundler reads these paths by convention (resolved by `abideResolverPlugin`):
|
|
50
48
|
|
|
51
49
|
| Path | Meaning |
|
|
52
|
-
|
|
53
|
-
| `src/server/rpc/<name>.ts` | One RPC
|
|
54
|
-
| `src/server/sockets/<name>.ts` | One `socket(...)` per file; socket name
|
|
55
|
-
| `src/
|
|
56
|
-
| `src/
|
|
57
|
-
| `src/
|
|
58
|
-
| `src/
|
|
59
|
-
| `src/
|
|
60
|
-
| `src/
|
|
61
|
-
| `src/
|
|
62
|
-
| `src/
|
|
63
|
-
| `src
|
|
64
|
-
| `
|
|
65
|
-
| `dist/` | Build output; client bundle → `dist/_app/` (dev: per-generation `dist/_app.gen-<id>`). |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `src/server/rpc/<name>.ts` | One RPC per file; the path is the URL (`/rpc/<name>`), the export name matches the file stem. |
|
|
52
|
+
| `src/server/sockets/<name>.ts` | One `socket(...)` per file; the socket name is the file stem, loaded lazily on first sub/pub frame. |
|
|
53
|
+
| `src/mcp/prompts/<name>.md` | A Markdown MCP prompt; `{{placeholder}}` args are substituted at render. |
|
|
54
|
+
| `src/mcp/resources/<name>` | A static MCP resource, gzip-embedded into the build. |
|
|
55
|
+
| `src/server/config.ts` | Boot-time `env(...)` schema, eager-imported so env validation runs at startup. |
|
|
56
|
+
| `src/app.ts` | Optional app hooks (`init`, `handle`, `handleError`, `health`, `forwardHeaders`) — the `AppModule` shape. |
|
|
57
|
+
| `src/ui/pages/**/page.abide` | A page route; `[name]` path segments become `page.params`. |
|
|
58
|
+
| `src/ui/pages/**/layout.abide` | A layout that wraps nested pages via the router outlet; persists across same-chain navigation. |
|
|
59
|
+
| `src/ui/public/` | Static assets, gzip-embedded and served from the app root. |
|
|
60
|
+
| `src/bundle/window.ts` | Optional desktop-bundle window config (default export, the `BundleWindow` shape). |
|
|
61
|
+
| `src/.abide/*.d.ts` | Generated editor/type artifacts (rpc route maps, prop shapes) written by `build`. |
|
|
62
|
+
| `dist/` | Build output; `dist/_app` is the server-loaded app dir (override with `ABIDE_APP_DIR`). |
|
|
66
63
|
|
|
67
64
|
## CLI
|
|
68
65
|
|
|
66
|
+
Every `abide <command>` (the `abide` bin):
|
|
67
|
+
|
|
69
68
|
| Command | Does |
|
|
70
|
-
|
|
71
|
-
| `abide scaffold <name
|
|
72
|
-
| `abide dev` |
|
|
73
|
-
| `abide build` |
|
|
74
|
-
| `abide
|
|
75
|
-
| `abide
|
|
76
|
-
| `abide
|
|
77
|
-
| `abide
|
|
78
|
-
| `abide
|
|
79
|
-
| `abide
|
|
80
|
-
| `abide lsp` | Run the `.abide` language server over stdio (JSON-RPC) for
|
|
81
|
-
| `abide init-agent` | Write/refresh a `CLAUDE.md` pointer to this surface map
|
|
82
|
-
|
|
83
|
-
For tests, add `preload = ["@abide/abide/preload"]` under
|
|
84
|
-
`bunfig.toml` and
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `abide scaffold <name>` | Scaffold a project from the bundled template, install deps, and (on a TTY) start dev. `--no-install` / `--no-dev` opt out. |
|
|
71
|
+
| `abide dev` | Dev orchestrator: build the client, spawn the server, watch `src/`, rebuild + restart with browser live-reload. |
|
|
72
|
+
| `abide build` | One client build into `dist/_app/`, no server (CI / static deploys). |
|
|
73
|
+
| `abide start` | Run the production server against an already-built `dist/`. |
|
|
74
|
+
| `abide run <file> [args...]` | Run a script under the abide preload (same runtime as the server); argv after the file is forwarded. |
|
|
75
|
+
| `abide compile [--target] [--out]` | Build a standalone server executable (client assets embedded) for a platform. |
|
|
76
|
+
| `abide cli [--target] [--out] [--platforms]` | Build the thin remote-client CLI binary; `--platforms` cross-compiles per platform. |
|
|
77
|
+
| `abide bundle` | Assemble a self-contained (unsigned) desktop app bundle for the host platform. |
|
|
78
|
+
| `abide check` | Type-check every `.abide` component's template + props through its shadow program. |
|
|
79
|
+
| `abide lsp` | Run the `.abide` language server over stdio (JSON-RPC) for editor diagnostics. |
|
|
80
|
+
| `abide init-agent` | Write/refresh a `CLAUDE.md` pointer to this surface map for a non-scaffolded project. |
|
|
81
|
+
|
|
82
|
+
For tests, don't use `abide run` — add `preload = ["@abide/abide/preload"]` under
|
|
83
|
+
`[test]` in `bunfig.toml` and use `bun test`, so tests run in the server runtime.
|
|
85
84
|
|
|
86
85
|
## Authoring contracts
|
|
87
86
|
|
|
88
|
-
- **RPC** (`src/server/rpc/<name>.ts`)
|
|
89
|
-
The handler receives
|
|
90
|
-
`InferOutput<schemas.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
`
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
`
|
|
118
|
-
|
|
119
|
-
(`init`/`handle`/`handleError`/`health`/`forwardHeaders`) and the boot-time
|
|
120
|
-
`env(schema)` config, respectively.
|
|
87
|
+
- **RPC** (`src/server/rpc/<name>.ts`). Declare one `export const <name> =
|
|
88
|
+
GET|POST|PUT|PATCH|DELETE|HEAD(handler, opts?)`. The handler receives the typed
|
|
89
|
+
input (`InferOutput<schemas.input>` when a schema is declared, else its own
|
|
90
|
+
parameter type), reads request context via `request()` / `cookies()` /
|
|
91
|
+
`server()`, and returns `json` / `jsonl` / `sse` / `error` / `redirect` / a raw
|
|
92
|
+
`Response`. `opts` is `{ schemas: { input?, output?, files? }, clients: {
|
|
93
|
+
browser?, mcp?, cli? }, crossOrigin?, maxBodySize?, timeout?, cache? }` — plus
|
|
94
|
+
`stream?` on the read helpers only (a write has no replayable stream). There is
|
|
95
|
+
no flat `inputSchema`/`filesSchema` and no `outbox`. Query / path / form args
|
|
96
|
+
auto-coerce from the endpoint's typed shape (ADR-0028) — no `z.coerce`.
|
|
97
|
+
- **Consuming an RPC.** The bare call `fn(args)` is the smart read — cached,
|
|
98
|
+
coalesced, reactive, in-process during SSR (its value is baked into the HTML
|
|
99
|
+
for warm hydration) and swapped to `fetch` in the browser (there is no
|
|
100
|
+
`cache()` wrapper). Also: `fn.raw(args, init?)` → the raw `Response`;
|
|
101
|
+
`fn.refresh` / `fn.invalidate` / `fn.amend` / `fn.peek` / `fn.pending` /
|
|
102
|
+
`fn.refreshing` / `fn.error` / `fn.watch`; a `jsonl`/`sse` handler makes the
|
|
103
|
+
bare call return a `Subscribable`. Typed errors come from returning an
|
|
104
|
+
`error.typed(name, status, schema?)` branch and narrow via `fn.isError`.
|
|
105
|
+
- **Socket** (`src/server/sockets/<name>.ts`). `export const <name> =
|
|
106
|
+
socket<T>(opts?)` — a `Socket<T>` (isomorphic `AsyncIterable<T>`). Opts (server
|
|
107
|
+
only): `tail` (retain the last N frames), `ttl` (evict retained frames older
|
|
108
|
+
than N ms), `clientPublish` (allow client publishes), `schema` (validate
|
|
109
|
+
payloads + type `T`), `clients` (expose to mcp/cli). HTTP face at
|
|
110
|
+
`/__abide/sockets/<name>`; all sockets multiplex onto one ws.
|
|
111
|
+
- **Page / layout** (`.abide`). A `[id]` path segment lands in `page.params.id`;
|
|
112
|
+
a layout renders its nested route at the router outlet. Read the active route
|
|
113
|
+
via `page` (`page.url`, `page.params`, `page.navigating`), move with `navigate`
|
|
114
|
+
and build hrefs with `url`.
|
|
115
|
+
- **`app.ts` / `config.ts`.** `app.ts` default-exports the `AppModule` hooks;
|
|
116
|
+
`config.ts` runs `env(schema)` at module top level so boot fails fast on bad
|
|
117
|
+
env.
|
|
121
118
|
|
|
122
119
|
## .abide template grammar
|
|
123
120
|
|
|
124
|
-
A component is
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
`
|
|
133
|
-
|
|
134
|
-
component. So a *root* `<style>` is component-scoped, a nested one is branch-scoped.
|
|
121
|
+
A `.abide` component is a leading `<script>` (module imports + setup), then
|
|
122
|
+
HTML-with-mustaches, then optional `<style>`. The reactive primitives are
|
|
123
|
+
imported by their own module paths and resolved by import binding (alias-safe):
|
|
124
|
+
`state` (`abide/ui/state`, with `.computed` / `.linked`), `watch`
|
|
125
|
+
(`abide/ui/watch`), `html` (`abide/ui/html`), `snippet` (`abide/shared/snippet`).
|
|
126
|
+
The one ambient reader is `props()` (`abide/ui/props`) — a required import, not
|
|
127
|
+
`scope()` (which is internal plumbing now, never authored). In `.abide` source a
|
|
128
|
+
`state` cell is read and reassigned as a **plain variable** (`count`,
|
|
129
|
+
`count += 1`); the compiler desugars that to the cell — `.value` is not the
|
|
130
|
+
authoring surface.
|
|
135
131
|
|
|
136
|
-
|
|
132
|
+
**Reactive state**
|
|
137
133
|
|
|
138
134
|
| Form | Meaning |
|
|
139
|
-
|
|
140
|
-
| `
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `let x = state(v, transform?)` | Writable cell; `transform` gates every write. Read/assign as a plain variable. |
|
|
141
137
|
| `state.computed(() => …)` | Read-only derived cell (lazy, never serialized). |
|
|
142
138
|
| `state.linked(() => src, transform?)` | Writable cell reseeded when the thunk's deps change. |
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
|
|
146
|
-
A writable computed is expressed at the binding: `bind:value={{ get, set }}`.
|
|
147
|
-
`scope()` is internal plumbing now, never authored; `effect` is compiler-emitted —
|
|
148
|
-
authors write `watch`, not a bare `effect(...)`.
|
|
139
|
+
| `watch(source, handler)` | The single reaction primitive (client-only) over a cell, a cell array, a socket/stream, or an rpc; bare `watch(thunk)` is an auto-tracked effect. |
|
|
140
|
+
| `const { name = fallback, ...rest } = props()` | The prop reader (ambient; required import). |
|
|
149
141
|
|
|
150
|
-
|
|
142
|
+
**Bindings / directives**
|
|
151
143
|
|
|
152
|
-
|
|
|
153
|
-
|
|
154
|
-
| `{expr}` |
|
|
155
|
-
| `{html
|
|
156
|
-
| `name={expr}` |
|
|
157
|
-
| `on<event>={fn}` | Event listener (`onclick={
|
|
144
|
+
| Form | Meaning |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `{expr}` | Reactive text interpolation (escaped). |
|
|
147
|
+
| `{html(...)}` / `{html\`…\`}` | Insert trusted raw HTML unescaped. |
|
|
148
|
+
| `name={expr}` | Reactive attribute (present/absent for booleans). |
|
|
149
|
+
| `on<event>={fn}` | Event listener (`onclick={fn}`). |
|
|
158
150
|
| `bind:value` / `bind:checked` / `bind:group` | Two-way form binds. |
|
|
159
151
|
| `bind:value={{ get, set }}` | Derived two-way bind. |
|
|
160
152
|
| `class:name={cond}` | Toggle a class. |
|
|
161
153
|
| `style:property={value}` | Set one style property. |
|
|
162
|
-
| `attach={fn}` | Run
|
|
163
|
-
| `{...
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
|
171
|
-
|
|
172
|
-
| `{#
|
|
173
|
-
| `{#
|
|
174
|
-
| `{#
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
a
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
and
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
it
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
flow were **removed** — a bare `<template>` is now an inert element, and using a
|
|
198
|
-
removed form throws a migration error.
|
|
154
|
+
| `attach={fn}` | Run `fn(node)` on mount; its return is the teardown. |
|
|
155
|
+
| `{...expr}` | Spread an object's keys as props (component) or attributes (element). |
|
|
156
|
+
|
|
157
|
+
**Control flow** — mustache blocks, not `<template>`:
|
|
158
|
+
|
|
159
|
+
| Block | Branches |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| `{#if}` … `{/if}` | `{:else if cond}`, `{:else}` |
|
|
162
|
+
| `{#for item, i of list by key}` … `{/for}` | `{#for await item of source}` over an `AsyncIterable`; `{:catch e}` on the async form |
|
|
163
|
+
| `{#await p}` … `{/await}` | `{:then v}`, `{:catch e}`, `{:finally}` |
|
|
164
|
+
| `{#switch subj}` … `{/switch}` | `{:case value}`, `{:default}` |
|
|
165
|
+
| `{#try}` … `{/try}` | `{:catch e}`, `{:finally}` |
|
|
166
|
+
| `{#snippet name(args)}` … `{/snippet}` | A reusable builder, called `{name(args)}` |
|
|
167
|
+
|
|
168
|
+
Async reads have no ceremony: the bare call `{fn(args)}` is the documented way —
|
|
169
|
+
a peek reading `undefined` while pending (auto-streams on SSR), composing with
|
|
170
|
+
`?.` / `??` / `{#if}` / attributes, paired with the `.pending()` / `.error()`
|
|
171
|
+
probes. `{await fn()}` inline blocks SSR until the value is in the HTML;
|
|
172
|
+
`{#await}` is the explicit opt-in for a distinct pending branch, a local
|
|
173
|
+
`{:catch}`, or `{:then}` narrowing.
|
|
174
|
+
|
|
175
|
+
Components are capitalised tags; the content nested in them renders where the
|
|
176
|
+
component calls `{children()}` — the single slot (the `<slot>` element was
|
|
177
|
+
removed; `{#if children}{children()}{:else}…{/if}` is the fallback form, no named
|
|
178
|
+
slots). Snippets are a `{#…}` block, not `<template>`: the `<template name>`
|
|
179
|
+
snippet form and all `<template if>`/`<template each>`/… control flow were
|
|
180
|
+
removed (a bare `<template>` is now an inert element; a removed form throws a
|
|
181
|
+
migration error).
|
|
182
|
+
|
|
183
|
+
`<script>` and `<style>` are **not** component-root-only. Either may sit inside a
|
|
184
|
+
control-flow branch, scoped to that branch's lexical scope: a nested `<script>`
|
|
185
|
+
declares branch-local `state` / `state.computed` / `state.linked` (re-seeded per
|
|
186
|
+
mount, no module imports — it reuses the leading script's imports), and a nested
|
|
187
|
+
`<style>` scopes to its sibling subtree. So a *root* `<style>` is
|
|
188
|
+
component-scoped; a nested one is branch-scoped.
|
|
199
189
|
|
|
200
190
|
## Server surface — abide/server/*
|
|
201
191
|
|
|
202
|
-
### RPC
|
|
203
|
-
|
|
204
|
-
- `abide/server/GET` — read helper; `export const x = GET(fn, opts?)`. Adds
|
|
205
|
-
`cache`/`stream` opts. Read-only, so a typed input auto-exposes it to MCP + CLI.
|
|
206
|
-
- `abide/server/HEAD` — read helper, same shape as `GET` (headers only, no body).
|
|
207
|
-
- `abide/server/POST` — mutating helper; `RpcSharedOpts` only (`cache`/`stream`
|
|
208
|
-
are a compile error). Never auto-exposes to MCP.
|
|
209
|
-
- `abide/server/PUT` — mutating helper (idempotent replace); as `POST`.
|
|
210
|
-
- `abide/server/PATCH` — mutating helper (partial update); as `POST`.
|
|
211
|
-
- `abide/server/DELETE` — mutating helper (removal); as `POST`.
|
|
212
|
-
|
|
213
|
-
### Response helpers — @documentation response
|
|
214
|
-
|
|
215
|
-
- `abide/server/json` — `json<T>(data, init?)` → `TypedResponse<T>`; default
|
|
216
|
-
`no-store`, honest-JSON encodes Set/Map/bigint/Date (ADR-0029); `undefined` body
|
|
217
|
-
→ 204.
|
|
218
|
-
- `abide/server/jsonl` — `jsonl<Frame>(iterable, init?)`; JSON Lines stream
|
|
219
|
-
(`application/jsonl`), cancellation calls `iter.return()`, a generator error
|
|
220
|
-
emits a final `{"$error":…}` line.
|
|
221
|
-
- `abide/server/sse` — `sse<Frame>(iterable, init?)`; `text/event-stream` with a
|
|
222
|
-
15 s keepalive comment; an error emits an `event: error` frame.
|
|
223
|
-
- `abide/server/error` — `error(status, message?, init?)` → `TypedResponse<never>`
|
|
224
|
-
(positional status wins). `error.typed(name, status, schema?)` returns a typed
|
|
225
|
-
error constructor driving `rpc.isError`; `schema` types `.data`, never validates.
|
|
226
|
-
- `abide/server/redirect` — `redirect(url, status = 302, init?)`; accepts relative
|
|
227
|
-
URLs, sets `Location` + `no-store`.
|
|
228
|
-
|
|
229
|
-
### Request scope — @documentation request-scope
|
|
192
|
+
### RPC — @documentation rpc
|
|
230
193
|
|
|
231
|
-
-
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
-
|
|
236
|
-
|
|
194
|
+
- `@abide/abide/server/GET` — read-only RPC helper `GET(fn, opts?)`; infers args from the handler parameter and Return/Errors from its `TypedResponse`/`error.typed` returns; opts `{ schemas, clients, crossOrigin, maxBodySize, timeout, cache, stream }`. Bundler-rewritten; throws if called unprocessed.
|
|
195
|
+
- `@abide/abide/server/HEAD` — read-only RPC helper, identical to `GET`.
|
|
196
|
+
- `@abide/abide/server/POST` — mutating RPC helper; same inference as `GET` but opts omit `stream` (writes aren't replayable), still accept `cache` (a no-ttl write coalesces only).
|
|
197
|
+
- `@abide/abide/server/PUT` — mutating RPC helper, identical to `POST`.
|
|
198
|
+
- `@abide/abide/server/PATCH` — mutating RPC helper, identical to `POST`.
|
|
199
|
+
- `@abide/abide/server/DELETE` — mutating RPC helper, identical to `POST`.
|
|
200
|
+
- `@abide/abide/shared/withJsonSchema` — attaches a `toJSONSchema()` projection to a Standard Schema lacking a native one, feeding OpenAPI / MCP / CLI / bundle-form generation; mutates and returns the same schema. (Isomorphic — lives in `shared/`.)
|
|
237
201
|
|
|
238
|
-
###
|
|
202
|
+
### Response — @documentation response
|
|
239
203
|
|
|
240
|
-
-
|
|
241
|
-
|
|
204
|
+
- `@abide/abide/server/json` — `json(data, init?)` → `TypedResponse<T>` with honest-JSON wire encoding (Set/Map/bigint) and default `Cache-Control: no-store`; caller `content-type` / `cache-control` override.
|
|
205
|
+
- `@abide/abide/server/jsonl` — `jsonl(iterable, init?)` streams an `AsyncIterable<Frame>` as `application/jsonl` (one JSON line/frame); consumer cancel flows to `iter.return()`, a throw emits a final `{"$error":…}` line.
|
|
206
|
+
- `@abide/abide/server/sse` — `sse(iterable, init?)` streams frames as `text/event-stream` (`data: <json>\n\n`) with a 15s keepalive comment; a throw emits an `event: error` frame carrying only the message.
|
|
207
|
+
- `@abide/abide/server/error` — `error(status, message?, init?)` → a `text/plain` `TypedResponse<never>` (message defaults to the status reason phrase, positional status wins); member `error.typed(name, status, schema?)` returns a constructor for a named typed error (`{$abideError,data}`) that `fn.isError(e, name)` narrows.
|
|
208
|
+
- `@abide/abide/server/redirect` — `redirect(url, status=302, init?)` → a `TypedResponse<never>` redirect accepting relative URLs, status restricted to 301/302/303/307/308, positional status wins over `init.status`.
|
|
209
|
+
- `@abide/abide/shared/HttpError` — error thrown by remote-function calls on non-2xx, carrying `status`, `statusText`, the raw `response`, and optional `kind`/`data` for typed / validation (422) errors. (Isomorphic.)
|
|
210
|
+
- `@abide/abide/shared/ValidationErrorData` — type of the `data` on a `kind: 'validation'` (422) `HttpError`: `{ issues, fields }` (raw Standard Schema issues plus a field→first-message map). (Isomorphic.)
|
|
242
211
|
|
|
243
212
|
### Sockets — @documentation sockets
|
|
244
213
|
|
|
245
|
-
-
|
|
246
|
-
under `src/server/sockets/`. Returns `Socket<T>` (isomorphic `AsyncIterable<T>`).
|
|
214
|
+
- `@abide/abide/server/socket` — declares one named `Socket<T>` per `src/server/sockets/` file (`socket<T>(opts?)` or a `{ schema }` overload inferring `T`); server-only opts `tail`/`ttl`/`clientPublish`/`schema`/`clients`. Throws if called outside a sockets module.
|
|
247
215
|
|
|
248
|
-
###
|
|
216
|
+
### Request scope — @documentation request-scope
|
|
249
217
|
|
|
250
|
-
-
|
|
251
|
-
|
|
218
|
+
- `@abide/abide/server/request` — `request()` returns the inbound `Request` for the current SSR/RPC pass (AsyncLocalStorage); throws outside a request scope.
|
|
219
|
+
- `@abide/abide/server/cookies` — `cookies()` returns the request's lazily-materialized `Bun.CookieMap` jar (reads parse inbound Cookie; `set`/`delete` flush as `Set-Cookie` on return); throws outside a request scope.
|
|
220
|
+
- `@abide/abide/server/server` — `server()` returns the active `Bun.serve` instance (or a no-op in-process server for in-scope dispatch without a booted server); throws before init outside any request scope.
|
|
252
221
|
|
|
253
|
-
###
|
|
222
|
+
### Render — @documentation render
|
|
254
223
|
|
|
255
|
-
-
|
|
256
|
-
`src/app.ts` (`init`/`handle`/`handleError`/`health`/`forwardHeaders`).
|
|
257
|
-
- `abide/server/InspectorContext` — `type InspectorContext`: the capabilities core
|
|
258
|
-
injects into `@abide/inspector` when `ABIDE_ENABLE_INSPECTOR=true`.
|
|
224
|
+
- `@abide/abide/server/render` — `render(path, params?, query?)` renders a page route to its HTML string in a fresh nested request scope; inline / blocking-await pages return complete HTML, streaming `{#await}` pages return the shell plus `<abide-resolve>` fragments. For a no-JS surface (email) use blocking awaits.
|
|
259
225
|
|
|
260
|
-
###
|
|
226
|
+
### Configuration — @documentation configuration
|
|
261
227
|
|
|
262
|
-
-
|
|
263
|
-
server-side RPC builder the bundler emits; runs validation → 422, timeout → 504,
|
|
264
|
-
and registers the registry entry.
|
|
265
|
-
- `abide/server/sockets/defineSocket` — `defineSocket<T>(name, opts?)`: the server
|
|
266
|
-
runtime `socket()` binds to; retention defaults to `tail ?? 1`, `ttl` evicts
|
|
267
|
-
lazily, schema validates synchronously on publish.
|
|
228
|
+
- `@abide/abide/server/env` — `env(schema)` validates `Bun.env` against a Standard Schema at module top level, returning the typed config and reporting all issues at once on failure; registers the schema for the launcher setup form.
|
|
268
229
|
|
|
269
|
-
|
|
230
|
+
### Beyond the browser — @documentation agent · bundle
|
|
270
231
|
|
|
271
|
-
|
|
232
|
+
- `@abide/abide/server/agent` — `agent(engine, messages)` runs an `AgentEngine` against the current request's gated MCP surface (forwarding caller auth) and returns its `AgentFrame` stream for a handler to frame via `jsonl()`/`sse()`; must run inside an RPC request scope. Exports the `NeutralMessage`/`AgentFrame`/`AgentSurface`/`AgentEngine` types.
|
|
233
|
+
- `@abide/abide/server/appDataDir` — `appDataDir()` returns the desktop bundle's per-user data dir, keyed by the injected program name; cwd-independent, filesystem-pure.
|
|
272
234
|
|
|
273
|
-
|
|
274
|
-
`toJSONSchema()` projection to a Standard Schema whose library lacks one; feeds
|
|
275
|
-
OpenAPI / MCP / CLI.
|
|
235
|
+
### Plumbing — @documentation plumbing
|
|
276
236
|
|
|
277
|
-
|
|
237
|
+
- `@abide/abide/server/rpc/defineRpc` — `defineRpc(method, url, handler, opts?)` builds the runtime `RemoteFunction` the bundler targets on the server; the bundler stamps the JSON-schema projections, `coerce`, and `streaming` flags. (Authored code uses `GET`/`POST`/…, not this.)
|
|
238
|
+
- `@abide/abide/server/sockets/defineSocket` — `defineSocket(name, opts?)` is the bundler-targeted server `Socket` implementation: per-subscriber queues, a shared retained tail (default 1, lazy `ttl` eviction), schema-validated `publish` fanning out via `server.publish`, and `tail`/`peek`.
|
|
239
|
+
- `@abide/abide/server/prompts/definePrompt` — `definePrompt(name, opts)` builds a `Prompt` (name/description/render) from a resolver-generated `src/mcp/prompts/<file>.md` module and registers it for MCP.
|
|
240
|
+
- `@abide/abide/server/prompts/renderPromptTemplate` — `renderPromptTemplate(template, args)` substitutes `{{name}}` placeholders (missing args → empty string); used by the generated `.md` prompt render closure.
|
|
241
|
+
- `@abide/abide/server/AppModule` — type of the optional `src/app.ts` hooks (`forwardHeaders`, `init` with cleanup, `handle` middleware, `handleError`, `health`), all optional with framework defaults.
|
|
242
|
+
- `@abide/abide/server/InspectorContext` — type of the capability bundle core injects into `@abide/inspector` when `ABIDE_ENABLE_INSPECTOR=true`: `app`, `loadSurface`, `cacheSnapshot`, `inFlightSnapshot`, `onRecord`.
|
|
278
243
|
|
|
279
|
-
|
|
280
|
-
calls on non-2xx. Carries `status`, `statusText`, `response`, optional `kind`
|
|
281
|
-
(declared error name or `'validation'`) and `data`.
|
|
282
|
-
- `abide/shared/ValidationErrorData` — `type ValidationErrorData`: the
|
|
283
|
-
`HttpError.data` shape when `kind === 'validation'` (422) — `{ issues, fields }`,
|
|
284
|
-
`fields` mapping top-level field → first message.
|
|
244
|
+
## Isomorphic surface — abide/shared/*
|
|
285
245
|
|
|
286
246
|
### Cache — @documentation cache
|
|
287
247
|
|
|
288
|
-
|
|
289
|
-
from the server.
|
|
290
|
-
|
|
291
|
-
- `abide/shared/invalidate` — `invalidate(selector?, args?)`: the drop verb — drop
|
|
292
|
-
matching cached reads so the next read reloads lazily. Selector grammar:
|
|
293
|
-
`(fn, args)` / `(fn)` / `({ tags })` / `()`.
|
|
294
|
-
- `abide/shared/patch` — `patch(fn, args?, updater)` / `patch({ tags }, updater)`:
|
|
295
|
-
mutate the retained value of matching reads in place, reactive, no network (the
|
|
296
|
-
optimistic-update / socket-frame primitive).
|
|
297
|
-
- `abide/shared/refresh` — `refresh(selector?, args?)`: refetch matching reads now,
|
|
298
|
-
keeping the stale value visible (`refreshing()` true) until the fresh one swaps in.
|
|
248
|
+
- `@abide/abide/shared/invalidate` — the drop verb: discards cached reads matching the selector so the next read reloads lazily (retained readers revalidate stale-in-place); `invalidate(asyncCell)` aliases `cell.refresh()`. Side-swapped (ADR-0041): local on the client, broadcast to all clients from the server.
|
|
249
|
+
- `@abide/abide/shared/refresh` — the refetch verb: refetches matching reads while keeping the stale value visible until fresh data swaps in (pair with `refreshing()`). Side-swapped (ADR-0041): local on the client, broadcast eagerly to all clients from the server.
|
|
250
|
+
- `@abide/abide/shared/amend` — mutate a retained cached value in place, reactively and without network (optimistic / real-time), via a replacement value or `(current) => Return` updater. Side-swapped (ADR-0043): local on the client; the value form broadcasts from the server, the updater form stays local.
|
|
299
251
|
|
|
300
252
|
### Probes — @documentation probes
|
|
301
253
|
|
|
302
|
-
|
|
254
|
+
- `@abide/abide/shared/pending` — reactive "no value yet" probe over cache calls and stream tails (`pending()` / `pending(fn)` / `pending(fn, args)` / `pending({ tags })` / `pending(subscribable)`); reports, never fetches.
|
|
255
|
+
- `@abide/abide/shared/refreshing` — reactive "holding an old value while a fresher one is in flight" probe over cache and streams; distinguishes revalidation from `pending()`'s "no value yet".
|
|
256
|
+
- `@abide/abide/shared/peek` — the value member: synchronously returns the retained cache value or a stream's latest frame (`T | undefined`), reactive in a tracking scope, triggering nothing; null-tolerant.
|
|
257
|
+
- `@abide/abide/shared/done` — reactive stream-only terminal-state reader: true once a subscribable's tail has closed; not-done when no prober is registered (server render).
|
|
258
|
+
- `@abide/abide/shared/online` — reactive connectivity probe: on the client re-runs on `online`/`offline` and returns `navigator.onLine`; on the server reflects the calling client's reported connectivity, defaulting true during SSR and outside any request scope.
|
|
259
|
+
|
|
260
|
+
### Templating — @documentation templating
|
|
303
261
|
|
|
304
|
-
-
|
|
305
|
-
value yet"; `()` = anything in flight.
|
|
306
|
-
- `abide/shared/peek` — `peek(fn, args?)` / `peek(socket)` / `peek(cell)`: the
|
|
307
|
-
retained value synchronously, no trigger; null-tolerant.
|
|
308
|
-
- `abide/shared/refreshing` — `refreshing(selector?, args?): boolean` — holding a
|
|
309
|
-
prior value while a fresher source is in flight (distinct from `pending`).
|
|
310
|
-
- `abide/shared/done` — `done(subscribable): boolean` — stream-only, true once the
|
|
311
|
-
source has closed.
|
|
312
|
-
- `abide/shared/online` — `online(): boolean` — reactive connectivity; browser
|
|
313
|
-
reads `navigator.onLine`, server reflects the calling client's reported state.
|
|
262
|
+
- `@abide/abide/shared/snippet` — brands a payload as a mountable snippet value (client DOM builder / server HTML string) so a `{expr}` interpolation mounts it instead of escaping; the compiler wraps snippet bodies with it.
|
|
314
263
|
|
|
315
264
|
### Observability — @documentation observability
|
|
316
265
|
|
|
317
|
-
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
-
|
|
321
|
-
speaker) with members `log.warn` / `log.error` / `log.trace(name, work)` /
|
|
322
|
-
`log.channel(name)` (DEBUG-gated); records carry request-scope context, tsv or
|
|
323
|
-
JSON under `ABIDE_LOG_FORMAT=json`. (No `log.info` — the base call is info.)
|
|
324
|
-
- `abide/shared/reachable` — `reachable(host?): Promise<boolean>`: isomorphic
|
|
325
|
-
outbound reachability, HEADs the origin, caches per TTL; no host = the app's own
|
|
326
|
-
backend (constant `true` on server).
|
|
327
|
-
- `abide/shared/trace` — `trace(): string | undefined`: the current request's W3C
|
|
328
|
-
`traceparent` (server from the ALS scope, browser from `__SSR__`).
|
|
329
|
-
|
|
330
|
-
### Page & URL — @documentation page / url
|
|
331
|
-
|
|
332
|
-
- `abide/shared/page` — `page: PageSnapshot`: reactive proxy with `route` /
|
|
333
|
-
`params` / `url` / `navigating` for the active page; reading a field in a tracked
|
|
334
|
-
scope re-runs on navigation. (`@documentation page`)
|
|
335
|
-
- `abide/shared/url` — `url(path, ...args): string`: resolve any in-app URL to its
|
|
336
|
-
base-correct form (RPC → query, page route → typed params, asset → bare path);
|
|
337
|
-
throws on a missing required param. Also exports `RpcRoutes` / `PageRoutes` /
|
|
338
|
-
`PublicAssets` / `PathParams`. (`@documentation url`)
|
|
266
|
+
- `@abide/abide/shared/health` — reactive backend-health read returning `{ reachable }` plus the app `health()` hook's fields, polled from `/__abide/health` only while a tracking scope reads it; constant `{ reachable: true }` on the server.
|
|
267
|
+
- `@abide/abide/shared/log` — the request-scope-aware logger, `Object.assign`-composed: callable `log(...)` on the always-on channel, plus `log.info` / `log.warn` / `log.error` / `log.trace` and `log.channel(name)` for a `DEBUG`-gated channel; tsv or JSON per `ABIDE_LOG_FORMAT`.
|
|
268
|
+
- `@abide/abide/shared/reachable` — isomorphic outbound reachability: `await reachable(host)` HEADs the host origin and caches the verdict for one TTL; constant true for no host (own backend) and loopback. Answers "can I connect," not "is my endpoint healthy."
|
|
269
|
+
- `@abide/abide/shared/trace` — returns the current request's W3C `traceparent` string, or undefined outside a request scope; isomorphic (server ALS / client `__SSR__`-stamped).
|
|
339
270
|
|
|
340
|
-
###
|
|
271
|
+
### Page — @documentation page
|
|
272
|
+
|
|
273
|
+
- `@abide/abide/shared/page` — reactive isomorphic page proxy exposing `route`, `params`, `url` (browser-space both sides), and `navigating`; getters resolve per-side and re-run readers on navigation.
|
|
274
|
+
|
|
275
|
+
### URL — @documentation url
|
|
341
276
|
|
|
342
|
-
-
|
|
343
|
-
payload so a `{expr}` interpolation mounts it instead of escaping (client builder
|
|
344
|
-
/ server string). Also exports `snippetPayload` and the `Snippet` / `SnippetValue`
|
|
345
|
-
types. (The `html` primitive lives under the UI surface.)
|
|
277
|
+
- `@abide/abide/shared/url` — base-correct, typed in-app URL resolver keyed off path kind (rpc args → query, page-route params, or bare asset/raw path); prefixes the mount base only for rooted internal paths, leaves external URLs untouched.
|
|
346
278
|
|
|
347
|
-
###
|
|
279
|
+
### Plumbing — @documentation plumbing
|
|
348
280
|
|
|
349
|
-
-
|
|
350
|
-
open-on-first-read / close-on-last-reader primitive over abide's signal core, for
|
|
351
|
-
building custom reactive sources.
|
|
281
|
+
- `@abide/abide/shared/createSubscriber` — abide-ui-native open-on-first-read / close-on-last-reader subscriber built on abide's signal core: `start(update)` opens the resource and returns cleanup; `subscribe()` registers a tracked reader that re-runs when `update` fires.
|
|
352
282
|
|
|
353
283
|
## UI surface — abide/ui/* (client-only)
|
|
354
284
|
|
|
355
285
|
### Reactive state — @documentation reactive-state
|
|
356
286
|
|
|
357
|
-
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
- `abide/ui/watch` — the single reaction primitive `watch(source, handler)` (and
|
|
361
|
-
bare `watch(thunk)` auto-tracked effect); unifies effect / socket.on / cache.on /
|
|
362
|
-
rpc-selector; client-only, returns a scope-tied disposer.
|
|
363
|
-
- `abide/ui/props` — `props()` prop reader; compiler-lowered inside a `.abide`
|
|
364
|
-
component, throws if called directly.
|
|
287
|
+
- `@abide/abide/ui/state` — abide's from-scratch writable reactive cell `state(initial, transform?)`, plus `.computed` (read-only derived) / `.linked` (writable, reseeded) and `.share` / `.shared` ambient-scope context. Read and reassigned as a plain variable inside `.abide`.
|
|
288
|
+
- `@abide/abide/ui/watch` — the single reaction primitive: `watch(source, handler)` names a trigger (cell / cell array / socket / rpc) and runs the handler on change; bare `watch(thunk)` is the compiler's auto-tracked binding form. Client-only, SSR-stripped.
|
|
289
|
+
- `@abide/abide/ui/props` — the prop reader `props<T>()`; compiler-lowered inside a `.abide` component, throws when called directly.
|
|
365
290
|
|
|
366
291
|
### Templating — @documentation templating
|
|
367
292
|
|
|
368
|
-
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
-
|
|
385
|
-
|
|
386
|
-
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
-
|
|
399
|
-
|
|
400
|
-
-
|
|
401
|
-
|
|
402
|
-
-
|
|
403
|
-
-
|
|
404
|
-
|
|
405
|
-
-
|
|
406
|
-
|
|
407
|
-
-
|
|
408
|
-
|
|
409
|
-
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
-
|
|
413
|
-
|
|
414
|
-
-
|
|
415
|
-
|
|
416
|
-
-
|
|
417
|
-
-
|
|
418
|
-
|
|
419
|
-
-
|
|
420
|
-
|
|
421
|
-
-
|
|
422
|
-
|
|
423
|
-
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
-
|
|
432
|
-
|
|
433
|
-
-
|
|
434
|
-
|
|
435
|
-
-
|
|
436
|
-
|
|
437
|
-
-
|
|
438
|
-
|
|
439
|
-
-
|
|
440
|
-
|
|
441
|
-
- `abide/ui/dom/restProps` — live Proxy of the unconsumed props for `{ ...rest }`,
|
|
442
|
-
excluding destructured keys and `children`.
|
|
443
|
-
- `abide/ui/dom/bindProp` — the parent half of a component `bind:prop`: annotate the
|
|
444
|
-
value thunk with a `.set` write-back channel.
|
|
445
|
-
- `abide/ui/dom/bindableProp` — the child half of a two-way prop: pass-through when the
|
|
446
|
-
parent bound it, else a local reseeding `linked` cell.
|
|
447
|
-
- `abide/ui/dom/spreadAttrs` — spread a thunk's keys onto a native element (`on*` →
|
|
448
|
-
listeners, others → reactive attributes); `exclude` skips explicit attrs.
|
|
449
|
-
- `abide/ui/dom/readCall` — guarded non-optional method call on a reactive-document
|
|
450
|
-
read, with legible authored-scope errors.
|
|
451
|
-
- `abide/ui/dom/readCell` — unified read of a `computed`/`linked`/derive reference
|
|
452
|
-
(async → throwing peek, function → call, sync → `.value`).
|
|
453
|
-
- `abide/ui/dom/readCellBlocking` — the blocking (`await`) variant of `readCell`: on a
|
|
454
|
-
pending cell it throws a suspense signal so the reading region withholds until the
|
|
455
|
-
value resolves, rather than reading `undefined` (client template lowering; ADR-0042).
|
|
456
|
-
- `abide/ui/dom/writeCell` — unified write of a `linked` reference from an author
|
|
457
|
-
assignment (async → `.set`, sync → `.value =`).
|
|
458
|
-
- `abide/ui/dom/cellPending` — whether a control-flow subject is a still-loading async
|
|
459
|
-
cell, so a block renders no branch while loading.
|
|
460
|
-
- `abide/ui/dom/mutateDocContainer` — apply an in-place container mutation
|
|
461
|
-
(`splice`/`sort`/`add`/…) on a reactive-document value by clone-mutate-`replace`.
|
|
462
|
-
- `abide/ui/dom/hydrate` — adopt existing server-rendered DOM in place with a claim
|
|
463
|
-
cursor active (no re-render); returns a disposer.
|
|
464
|
-
- `abide/ui/dom/appendText` — a reactive `{expr}` interpolation: escaped text,
|
|
465
|
-
`html`-branded raw, or a snippet call; create-appends or claims the SSR text node.
|
|
466
|
-
- `abide/ui/dom/appendTextAt` — a reactive `{expr}` mounted just after a skeleton
|
|
467
|
-
anchor comment (text interleaved with element siblings).
|
|
468
|
-
- `abide/ui/dom/appendSnippet` — mount a `{snippet(args)}` builder in a marker-bounded
|
|
469
|
-
range, reactive in its args.
|
|
470
|
-
- `abide/ui/dom/appendStatic` — a static (non-reactive) text node; create-appends or
|
|
471
|
-
claims the merged SSR text node.
|
|
472
|
-
- `abide/ui/dom/cloneStatic` — append a fully-static binding-free subtree by cloning a
|
|
473
|
-
cached template (create) / advancing the claim cursor (hydrate).
|
|
474
|
-
- `abide/ui/dom/skeleton` — realize a compiled skeleton (static subtree with located
|
|
475
|
-
holes) and return its element + anchor holes.
|
|
476
|
-
- `abide/ui/dom/anchorCursor` — position a skeleton-anchored block/slot: the create
|
|
477
|
-
insertion reference after the anchor and the hydrate claim cursor.
|
|
478
|
-
- `abide/ui/dom/outlet` — a layout outlet: insert/claim an empty `abide:outlet` comment
|
|
479
|
-
boundary; returns `{ open, close }`.
|
|
480
|
-
- `abide/ui/dom/attr` — bind an element attribute to `read()` via one effect
|
|
481
|
-
(boolean-present/absent + stringify semantics).
|
|
482
|
-
- `abide/ui/dom/on` — attach an event listener (`onclick={…}` target), scope-pinned and
|
|
483
|
-
batched, removal registered on the owner.
|
|
484
|
-
- `abide/ui/dom/attach` — run an `attach={…}` attachment against an element at build
|
|
485
|
-
time and register its teardown (the dual of `on`).
|
|
486
|
-
- `abide/ui/dom/bindSelectValue` — two-way `bind:value` for `<select>` (effect drives
|
|
487
|
-
selection re-applied via MutationObserver; `change` writes back; `multiple` → array).
|
|
488
|
-
- `abide/ui/dom/each` — keyed list runtime (`{#for … by key}`): each row a
|
|
489
|
-
marker-bounded range, reconciled by key with minimal DOM moves.
|
|
490
|
-
- `abide/ui/dom/eachAsync` — async keyed list runtime (`{#for await … of …}`):
|
|
491
|
-
append/reconcile as the iterator yields; mid-stream rejection routes to the catch.
|
|
492
|
-
- `abide/ui/dom/when` — conditional runtime (`{#if}`/`{:else}`): a swappable range
|
|
493
|
-
tracking `condition()`, with an optional pending state for a bare async subject.
|
|
494
|
-
- `abide/ui/dom/awaitBlock` — `{#await}` runtime: render pending then swap to
|
|
495
|
-
resolved/error; reactive re-runs on cache invalidation; hydration resumes or rebuilds.
|
|
496
|
-
- `abide/ui/dom/tryBlock` — `{#try}` reactive error-boundary runtime: catch build /
|
|
497
|
-
read / re-run throws, swap to the catch branch, re-arm on recovery.
|
|
498
|
-
- `abide/ui/dom/switchBlock` — `{#switch}` / `{:else if}` runtime: a swappable range
|
|
499
|
-
selecting the first matching (`===`) case (or default), with per-case async gating.
|
|
293
|
+
- `@abide/abide/ui/html` — marks a string as trusted raw HTML (plain call or tagged template) so a `{expr}` interpolation inserts its nodes verbatim instead of escaped text.
|
|
294
|
+
|
|
295
|
+
### Navigate — @documentation navigate
|
|
296
|
+
|
|
297
|
+
- `@abide/abide/ui/navigate` — navigates to a typed in-app path (interpolating `[name]` params through `url()`) via the History API, with `replace` / `keepScroll` options.
|
|
298
|
+
|
|
299
|
+
### Reaction plumbing — @documentation plumbing
|
|
300
|
+
|
|
301
|
+
- `@abide/abide/ui/effect` — abide's effect primitive (runs `fn` capturing reads, re-runs on change, teardown-returning); internal — authors use `watch`, and the compiler emits `effect`.
|
|
302
|
+
- `@abide/abide/ui/currentScope` — resolves the current lexical scope (minting a detached root outside any); the lowering host the compiler targets for `state`/`effect`/`share`.
|
|
303
|
+
- `@abide/abide/ui/enterRenderScope` — establishes a fresh nested lexical scope for an SSR render and returns the previous one to restore.
|
|
304
|
+
- `@abide/abide/ui/exitRenderScope` — restores the scope `enterRenderScope` saved, closing an SSR render's scope.
|
|
305
|
+
|
|
306
|
+
### Client entry / router plumbing — @documentation plumbing
|
|
307
|
+
|
|
308
|
+
- `@abide/abide/ui/startClient` — the abide-ui client entry: reads `window.__SSR__`, seeds the tab cache / doc / cell / socket warm partitions, then starts the router; returns a disposer.
|
|
309
|
+
- `@abide/abide/ui/router` — a minimal History-API client router that matches the path, code-splits and mounts the page + its layout chain, diffs chains across navigation, and restores scroll.
|
|
310
|
+
- `@abide/abide/ui/renderToStream` — out-of-order SSR streaming generator: yields the shell first, then one resolved fragment per streaming `await` block in completion order.
|
|
311
|
+
- `@abide/abide/ui/remoteProxy` — client-side substitute for an RPC handler: builds a `RemoteFunction` that fetches over the network (pre-flight validation, cache policy, abort/timeout).
|
|
312
|
+
- `@abide/abide/ui/socketProxy` — client-side substitute for a server `Socket`: subscribes over the multiplexed ws channel, warm-seeded from the SSR retained frame, producing the identical `Socket` surface.
|
|
313
|
+
|
|
314
|
+
### DOM binding plumbing — @documentation plumbing
|
|
315
|
+
|
|
316
|
+
Everything the compiler emits from the template; authors never call these.
|
|
317
|
+
|
|
318
|
+
- `@abide/abide/ui/dom/mount` — mounts a top-level page/layout into a host under an ownership scope and render pass, returning a disposer.
|
|
319
|
+
- `@abide/abide/ui/dom/mountChild` — the compiler's only child-component mount: a marker-bounded range adopter probing the hydration cursor for inlined vs streamed content, else create-mode.
|
|
320
|
+
- `@abide/abide/ui/dom/hydrate` — adopts existing server-rendered DOM in place by running `build` with a claim cursor active, attaching listeners/effects without re-rendering; returns a disposer.
|
|
321
|
+
- `@abide/abide/ui/dom/mergeProps` — composes a child's props from ordered explicit/spread/slot layers into one live proxy bag, last-layer-wins.
|
|
322
|
+
- `@abide/abide/ui/dom/spreadProps` — wraps a `{...source}` spread layer so every key resolves to a live value thunk.
|
|
323
|
+
- `@abide/abide/ui/dom/restProps` — exposes the unconsumed props of `const { foo, ...rest } = props()` as a live object, excluding consumed keys and `children`.
|
|
324
|
+
- `@abide/abide/ui/dom/bindProp` — the parent half of a component `bind:prop`: annotates the prop's value thunk with a `set` write-back channel.
|
|
325
|
+
- `@abide/abide/ui/dom/bindableProp` — the child half of a two-way prop: a writable pass-through to the parent's target, or a local reseeding `linked` cell when unbound.
|
|
326
|
+
- `@abide/abide/ui/dom/spreadAttrs` — spreads an object's keys onto a native element (`{...rest}`): `on*` keys attach as listeners, others bind as reactive attributes.
|
|
327
|
+
- `@abide/abide/ui/dom/attr` — binds one element attribute to `read()` via an effect, with present/absent boolean semantics, suspense handling, and a hydration divergence check.
|
|
328
|
+
- `@abide/abide/ui/dom/on` — attaches an event listener (the `onclick={…}` target) pinned to the current scope with batched writes; skips non-function handlers.
|
|
329
|
+
- `@abide/abide/ui/dom/attach` — runs an `attach={…}` against an element at build time and registers its (possibly async) teardown with the ownership scope.
|
|
330
|
+
- `@abide/abide/ui/dom/bindSelectValue` — two-way `bind:value` for a `<select>` (single or `multiple`), re-applying on value / option-set changes and writing back on `change`.
|
|
331
|
+
- `@abide/abide/ui/dom/readCall` — guarded non-optional method call on a reactive-document read, throwing a TypeError naming the authored scope path instead of the engine's opaque error.
|
|
332
|
+
- `@abide/abide/ui/dom/readCell` — the unified read for a `state`/`computed`/`linked` reference: returns the retained value, throwing a `SuspenseSignal` for a pending blocking cell or an `AsyncCellError` for a settled error.
|
|
333
|
+
- `@abide/abide/ui/dom/writeCell` — the unified write for a `linked` reference: `.value` for a sync cell or `.set(value)` for an async one.
|
|
334
|
+
- `@abide/abide/ui/dom/cellPending` — reports whether a control-flow subject is a still-loading async cell, so `{#if}`/`{#switch}` render no branch instead of flashing the falsy one.
|
|
335
|
+
- `@abide/abide/ui/dom/awaitSubject` — normalizes an `{#await}` block's bare cell subject so it awaits the async cell's resolution instead of peeking its pending `undefined`.
|
|
336
|
+
- `@abide/abide/ui/dom/mutateDocContainer` — lowers an in-place-mutating container method (splice/sort/…) on a reactive-document value to clone-mutate-`replace`, emitting a patch so readers wake.
|
|
337
|
+
- `@abide/abide/ui/dom/appendText` — a reactive `{expr}` interpolation under a parent, rendering escaped text, a snippet builder, or `html`-branded raw markup (create or hydrate-claim).
|
|
338
|
+
- `@abide/abide/ui/dom/appendTextAt` — a reactive `{expr}` interpolation mounted at a kept skeleton anchor (text interleaved with element siblings), delegating to `appendText`.
|
|
339
|
+
- `@abide/abide/ui/dom/appendSnippet` — mounts a `{snippet(args)}` builder's nodes in a marker-bounded range, reactive in its arguments.
|
|
340
|
+
- `@abide/abide/ui/dom/appendStatic` — appends a static text node under a parent (create), or claims the merged server text node (hydrate).
|
|
341
|
+
- `@abide/abide/ui/dom/cloneStatic` — appends a fully-static subtree by cloning a cached template once (create), or advances the claim cursor past the run (hydrate).
|
|
342
|
+
- `@abide/abide/ui/dom/skeleton` — realizes a compiled skeleton (a bound element subtree) under a parent and returns its element + anchor holes.
|
|
343
|
+
- `@abide/abide/ui/dom/anchorCursor` — positions a skeleton-anchored control-flow block/slot, returning the create insertion reference and parking the hydrate claim cursor.
|
|
344
|
+
- `@abide/abide/ui/dom/mountSlot` — mounts a component's `{children()}` content as a marker-bounded range positioned like a control-flow block, running once.
|
|
345
|
+
- `@abide/abide/ui/dom/outlet` — a layout's outlet as an empty `<!--abide:outlet-->` boundary the router fills; hydrate claims and skips the server child content.
|
|
346
|
+
- `@abide/abide/ui/dom/each` — keyed list binding (the compiler target for `{#for … by key}`): reconciles marker-bounded row ranges by key with minimal DOM moves and hydrate-in-place adoption.
|
|
347
|
+
- `@abide/abide/ui/dom/eachAsync` — async keyed list (the target for `{#for await … by key}`): appends/reconciles row ranges as an `AsyncIterable` yields, with generation-guarded drains and catch-branch handling.
|
|
348
|
+
- `@abide/abide/ui/dom/when` — conditional binding (the target for `{#if}`/`{:else}`): a swappable range tracking `condition()`, with an optional third pending state so a loading async subject flashes no branch.
|
|
349
|
+
- `@abide/abide/ui/dom/awaitBlock` — async binding (the target for `{#await}`): renders pending then swaps to the resolved value cell or catch branch on settle; adopts streamed-resume / warm-sync values on hydrate.
|
|
350
|
+
- `@abide/abide/ui/dom/tryBlock` — reactive error boundary (the target for `{#try}`): catches build / initial-read / re-run throws, swaps to the catch branch, and rebuilds on recovery.
|
|
351
|
+
- `@abide/abide/ui/dom/switchBlock` — multi-branch binding (the target for `{#switch}` / `{:else if}` chains): a swappable range selecting the first matching (or default) case, with per-case pending gating.
|
|
352
|
+
|
|
353
|
+
### Render runtime plumbing — @documentation plumbing
|
|
354
|
+
|
|
355
|
+
- `@abide/abide/ui/settleAsyncCells` — the SSR await-barrier: drains this render's pending async-cell list to a fixpoint so blocking `await` cells resolve before render; a client no-op.
|
|
356
|
+
- `@abide/abide/ui/flight` — server-only flight-starter that hoists an await's promise into the synchronous render prefix, normalizing sync throws and keeping pre-consumer rejections non-fatal.
|
|
357
|
+
- `@abide/abide/ui/isolateCellBarrier` — runs a hoisted child render under its own async-cell barrier list (server ALS), isolating its cell registration/drain from siblings; a client passthrough.
|
|
358
|
+
- `@abide/abide/ui/finalizeStreamedChildren` — the when-to-stream decision (ADR-0039): fills each hoisted child's reserved slot inline if its flight settled, else emits a streaming boundary.
|
|
359
|
+
- `@abide/abide/ui/runtime/renderPath` — computes the render-path (streamed-boundary id) a child mounts under by composing its ordinal onto the ambient path; server-emit-only.
|
|
360
|
+
- `@abide/abide/ui/runtime/withPath` — pushes one `escapeKey`-escaped render-path segment for the duration of a synchronous `build`, restoring after.
|
|
361
|
+
- `@abide/abide/ui/runtime/escapeKey` — escapes one object key into a JSON-Pointer token (`~`→`~0`, `/`→`~1`) so a key with `/` survives a `/`-joined render path.
|
|
362
|
+
- `@abide/abide/ui/runtime/blockId` — allocates an await/try block id namespaced by the ambient render-path (`${path}:${n}`) from a per-render-pass counter map.
|
|
363
|
+
- `@abide/abide/ui/runtime/nextBlockId` — allocates the next await/try block id in the current client render pass, over the shared `blockId`.
|
|
364
|
+
- `@abide/abide/ui/runtime/enterRenderPass` — marks entry into a render/mount, clearing per-path block-id counters at the outermost depth so each pass restarts ids at 0.
|
|
365
|
+
- `@abide/abide/ui/runtime/exitRenderPass` — marks exit from a render/mount, unwinding the depth `enterRenderPass` raised.
|
|
500
366
|
|
|
501
367
|
## Build / tooling
|
|
502
368
|
|
|
503
369
|
### Building — @documentation building
|
|
504
370
|
|
|
505
|
-
-
|
|
506
|
-
|
|
507
|
-
- `abide/compile` — `compile({ cwd, target?, outfile? })`: build the client then a
|
|
508
|
-
standalone Bun server executable; returns the binary path.
|
|
371
|
+
- `@abide/abide/build` — `build()` runs `Bun.build` to emit the client bundle into `dist` (`_app` in prod via atomic staging-swap, per-generation dirs in dev) with the `.abide` loader, virtual-module resolver, optional Tailwind and gzip; returns `{ appDir }` or `false`.
|
|
372
|
+
- `@abide/abide/compile` — `compile()` produces a standalone Bun server executable (client assets embedded), defaulting the target to the host platform; returns the emitted binary path.
|
|
509
373
|
|
|
510
374
|
### Plumbing — @documentation plumbing
|
|
511
375
|
|
|
512
|
-
-
|
|
513
|
-
|
|
514
|
-
-
|
|
515
|
-
|
|
516
|
-
- `abide/ui-plugin` — `abideUiPlugin`: the BunPlugin that loads `.abide` components
|
|
517
|
-
(compiles to an ES module; a `layout.abide` lowers its outlet to the router).
|
|
518
|
-
- `abide/tsconfig` — the consumer-extendable `tsconfig.app.json`.
|
|
376
|
+
- `@abide/abide/preload` — side-effect Bun preload registering the `.abide` UI plugin, the virtual-module resolver (mode from `ABIDE_TARGET`), and a `.css` no-op loader; add it under `[test]` `preload` in `bunfig.toml`.
|
|
377
|
+
- `@abide/abide/resolver-plugin` — `abideResolverPlugin()` is the Bun plugin supplying abide's `abide:*` virtual modules and rewriting `src/server/rpc` + `src/server/sockets` modules to server impls or client proxies.
|
|
378
|
+
- `@abide/abide/ui-plugin` — `abideUiPlugin` is the Bun plugin that loads `.abide` single-file components, compiling each (via `compileModule`) to an ES module with scoped `<style>` bundled to a virtual CSS module on the browser build.
|
|
379
|
+
- `@abide/abide/tsconfig` — shareable TS config (`tsconfig.app.json`): ESNext target/module, bundler resolution, strict + `isolatedModules` + `erasableSyntaxOnly`, `allowImportingTsExtensions`, `noEmit`, Bun types.
|
|
519
380
|
|
|
520
381
|
## Desktop bundle
|
|
521
382
|
|
|
522
|
-
###
|
|
523
|
-
|
|
524
|
-
- `abide/bundle/BundleWindow` — `type BundleWindow`: the default-export window config
|
|
525
|
-
(title/size/menu) from `src/bundle/window.ts`, baked into the launcher.
|
|
526
|
-
- `abide/bundle/BundleMenu` — `type BundleMenu`: a `{ label, items }` top-level menu
|
|
527
|
-
inserted between the Edit and Window menus.
|
|
528
|
-
- `abide/bundle/BundleMenuItem` — `type BundleMenuItem`: a divider or clickable item
|
|
529
|
-
(`emit` dispatches an `abide:menu` event, `navigate` repoints the window, `shortcut`
|
|
530
|
-
= Cmd-key).
|
|
531
|
-
- `abide/bundle/onMenu` — `onMenu(handler)` / `onMenu(name, handler)`: subscribe to
|
|
532
|
-
`abide:menu` clicks, returns unsubscribe; inert in SSR / a plain browser tab.
|
|
533
|
-
- `abide/bundle/bundled` — `bundled(): boolean`: true when running inside the abide
|
|
534
|
-
desktop bundle (isomorphic).
|
|
535
|
-
- `abide/server/appDataDir` — `appDataDir()`: the running bundle's per-user data dir
|
|
536
|
-
keyed by program name (pure, cwd-independent). (`@documentation bundle`)
|
|
537
|
-
|
|
538
|
-
## MCP
|
|
539
|
-
|
|
540
|
-
### MCP server — @documentation mcp
|
|
541
|
-
|
|
542
|
-
- `abide/mcp/createMcpServer` — `createMcpServer(opts?)`: construct the framework MCP
|
|
543
|
-
server bound to the RPC registry; `handle(request)` is what `/__abide/mcp` invokes.
|
|
544
|
-
Tools come from rpcs/sockets with `clients.mcp: true`; optional `authorize`.
|
|
383
|
+
### Bundle — @documentation bundle
|
|
545
384
|
|
|
546
|
-
|
|
385
|
+
- `@abide/abide/bundle/BundleWindow` — type for the default-exported `src/bundle/window.ts` config (title/width/height, custom `menu`, optional `config` Standard Schema overriding the setup form), baked into the launcher.
|
|
386
|
+
- `@abide/abide/bundle/BundleMenu` — type for a top-level bundle menu (`label` + `items`) inserted into the macOS menu bar between Edit and Window.
|
|
387
|
+
- `@abide/abide/bundle/BundleMenuItem` — serializable union type for a menu entry: a separator, an `emit` item dispatching an `abide:menu` event into the page, or a `navigate` item, with optional Cmd-`shortcut`.
|
|
388
|
+
- `@abide/abide/bundle/onMenu` — subscribes to bundle-menu clicks (catch-all `onMenu(handler)` or filtered `onMenu(name, handler)`), returning an unsubscribe; inert during SSR and in a plain browser tab.
|
|
389
|
+
- `@abide/abide/bundle/bundled` — `bundled()` returns true when running inside the abide desktop bundle (client: webview flag; server: `ABIDE_PARENT_PID`); isomorphic, false in a plain browser tab or remote server.
|
|
547
390
|
|
|
548
|
-
|
|
549
|
-
app's own MCP surface, returning the neutral `AgentFrame` stream (no transport — wrap
|
|
550
|
-
in `jsonl()` / `sse()`).
|
|
391
|
+
## MCP
|
|
551
392
|
|
|
552
|
-
###
|
|
393
|
+
### MCP — @documentation mcp
|
|
553
394
|
|
|
554
|
-
-
|
|
555
|
-
`Prompt`; called by the resolver-generated module for each `src/mcp/prompts/*.md`.
|
|
556
|
-
- `abide/server/prompts/renderPromptTemplate` — `renderPromptTemplate(template, args)`:
|
|
557
|
-
substitute `{{name}}` placeholders (missing → empty string).
|
|
395
|
+
- `@abide/abide/mcp/createMcpServer` — `createMcpServer(opts)` builds the framework-internal MCP server bound to the project's rpc registry, returning `{ handle(request) }` for the `/__abide/mcp` route; tools derive from rpcs/sockets with `clients.mcp`, auth inherits from the inbound request, with an optional `authorize` hook.
|
|
558
396
|
|
|
559
397
|
## Testing
|
|
560
398
|
|
|
561
399
|
### Testing — @documentation testing
|
|
562
400
|
|
|
563
|
-
-
|
|
564
|
-
`app.rpc.<rpc>` / `app.sockets.<name>` (types arrive from `src/.abide/` after a build).
|
|
401
|
+
- `@abide/abide/test/createTestApp` — `createTestApp()` boots the real app on an ephemeral port (same wiring as `serverEntry`) from the project's virtual manifests, returning a disposable `TestApp` with `origin`, `fetch`, typed `rpc`/`sockets`, `health`, and `stop`.
|
|
565
402
|
|
|
566
403
|
### Plumbing — @documentation plumbing
|
|
567
404
|
|
|
568
|
-
-
|
|
569
|
-
|
|
570
|
-
- `abide/test/assertAgentFrameConformance` — `assertAgentFrameConformance(...)`: assert
|
|
571
|
-
the neutral `AgentFrame` contract (single terminal `done`, matched
|
|
572
|
-
`tool_use`/`tool_result`, string deltas).
|
|
405
|
+
- `@abide/abide/test/createScriptedSurface` — `createScriptedSurface(tools)` returns a scripted `AgentSurface` (declarative tool stubs) that records every `call` so engine tests can assert dispatched tools and args.
|
|
406
|
+
- `@abide/abide/test/assertAgentFrameConformance` — `assertAgentFrameConformance(stream)` collects an engine's `AgentFrame` stream and asserts the neutral contract (one trailing `done`, matched `tool_use`/`tool_result` pairs, string text deltas).
|
|
573
407
|
|
|
574
408
|
## Generated machine surfaces
|
|
575
409
|
|
|
576
|
-
Runtime routes
|
|
410
|
+
Runtime routes the framework serves (`DOCUMENT` set; internal `/__abide/*`
|
|
411
|
+
routes are omitted):
|
|
577
412
|
|
|
578
413
|
| Route | Serves |
|
|
579
|
-
|
|
580
|
-
| `/openapi.json` | The generated OpenAPI document. |
|
|
581
|
-
| `/__abide/mcp` | The
|
|
582
|
-
| `/__abide/sockets` | The
|
|
583
|
-
| `/__abide/health` | Health
|
|
584
|
-
| `/__abide/identity` |
|
|
585
|
-
| `/__abide/cli` |
|
|
586
|
-
| `/__abide/inspector` |
|
|
414
|
+
| --- | --- |
|
|
415
|
+
| `/openapi.json` | The generated OpenAPI 3.1 document for the RPC surface. |
|
|
416
|
+
| `/__abide/mcp` | The MCP server endpoint (tools from mcp-exposed rpcs/sockets). |
|
|
417
|
+
| `/__abide/sockets` | The multiplexed WebSocket; `/__abide/sockets/<name>` is the per-socket HTTP face (tail over SSE/JSON, publish). |
|
|
418
|
+
| `/__abide/health` | Health probe: `{ reachable }` plus the app `health()` hook's fields, ahead of app middleware. |
|
|
419
|
+
| `/__abide/identity` | The health payload under the legacy `{ abide: true }` shape, for already-shipped probers. |
|
|
420
|
+
| `/__abide/cli` | The platform-detecting install script; `/__abide/cli/<platform>` streams the thin-CLI tarball. |
|
|
421
|
+
| `/__abide/inspector` | The operator inspector surface, gated by `ABIDE_ENABLE_INSPECTOR`. |
|
|
587
422
|
|
|
588
423
|
## Environment variables
|
|
589
424
|
|
|
590
425
|
| Var | Effect |
|
|
591
|
-
|
|
426
|
+
| --- | --- |
|
|
592
427
|
| `PORT` | Server listen port. |
|
|
593
|
-
| `APP_URL` |
|
|
594
|
-
| `ABIDE_APP_DIR` |
|
|
595
|
-
| `
|
|
596
|
-
| `
|
|
597
|
-
| `
|
|
598
|
-
| `
|
|
599
|
-
| `
|
|
600
|
-
| `
|
|
601
|
-
| `
|
|
602
|
-
| `
|
|
603
|
-
| `
|
|
604
|
-
| `
|
|
605
|
-
| `
|
|
428
|
+
| `APP_URL` | Public app URL; its path derives the mount base for all in-app URLs. |
|
|
429
|
+
| `ABIDE_APP_DIR` | Override the built app dir the server loads (default `dist/_app`). |
|
|
430
|
+
| `ABIDE_DATA_DIR` | Override the per-user app data dir (`appDataDir`). |
|
|
431
|
+
| `ABIDE_CLIENT_TIMEOUT` | Client-side RPC fetch timeout in ms (bounded 1–600000). |
|
|
432
|
+
| `ABIDE_MAX_REQUEST_BODY_SIZE` | Server-wide max request body bytes (per-RPC `maxBodySize` overrides). |
|
|
433
|
+
| `ABIDE_IDLE_TIMEOUT` | WebSocket idle timeout in seconds (default 10). |
|
|
434
|
+
| `ABIDE_LOG_FORMAT` | `json` switches `log` output to JSON lines (else tsv). |
|
|
435
|
+
| `DEBUG` | Enable diagnostic log channels (e.g. `abide:rpc`). |
|
|
436
|
+
| `ABIDE_DEV_SURFACE` | `1` logs requests even under `abide dev`. |
|
|
437
|
+
| `ABIDE_ENABLE_INSPECTOR` | `true` enables the `@abide/inspector` capability injection + `/__abide/inspector`. |
|
|
438
|
+
| `ABIDE_INSPECT` | Enable inspector debug instrumentation. |
|
|
439
|
+
| `ABIDE_APP_URL` | The app URL the remote CLI / bundle client targets. |
|
|
440
|
+
| `ABIDE_APP_TOKEN` | Bearer token the remote CLI / bundle client sends to reach its app. |
|
|
606
441
|
|
|
607
442
|
---
|
|
608
443
|
|
|
609
|
-
This map mirrors `package.json
|
|
610
|
-
export, run `bun run packages/abide/scripts/readmeSurfaces.ts` and update this
|
|
444
|
+
This map mirrors the `exports` map in `package.json`. After adding or renaming an
|
|
445
|
+
export, run `bun run packages/abide/scripts/readmeSurfaces.ts` and update this
|
|
446
|
+
file so every export, route, and env var stays accounted for.
|