@abide/abide 0.33.1 → 0.34.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 +39 -34
- package/CHANGELOG.md +24 -0
- package/README.md +21 -21
- package/package.json +5 -5
- package/src/abideResolverPlugin.ts +1 -1
- package/src/build.ts +1 -1
- package/src/compile.ts +1 -1
- package/src/lib/bundle/BundleMenu.ts +1 -1
- package/src/lib/bundle/BundleMenuItem.ts +1 -1
- package/src/lib/bundle/BundleWindow.ts +1 -1
- package/src/lib/bundle/bundled.ts +1 -1
- package/src/lib/bundle/disconnected.abide +105 -75
- package/src/lib/bundle/onMenu.ts +1 -1
- package/src/lib/mcp/createMcpServer.ts +1 -1
- package/src/lib/server/AppModule.ts +1 -1
- package/src/lib/server/DELETE.ts +1 -1
- package/src/lib/server/GET.ts +1 -1
- package/src/lib/server/HEAD.ts +1 -1
- package/src/lib/server/PATCH.ts +1 -1
- package/src/lib/server/POST.ts +1 -1
- package/src/lib/server/PUT.ts +1 -1
- package/src/lib/server/agent.ts +1 -1
- package/src/lib/server/appDataDir.ts +1 -1
- package/src/lib/server/cookies.ts +1 -1
- package/src/lib/server/env.ts +1 -1
- package/src/lib/server/error.ts +1 -1
- package/src/lib/server/json.ts +1 -1
- package/src/lib/server/jsonl.ts +1 -1
- package/src/lib/server/prompts/definePrompt.ts +1 -1
- package/src/lib/server/prompts/renderPromptTemplate.ts +1 -1
- package/src/lib/server/reachable.ts +1 -1
- package/src/lib/server/redirect.ts +1 -1
- package/src/lib/server/request.ts +1 -1
- package/src/lib/server/rpc/defineVerb.ts +1 -1
- package/src/lib/server/runtime/buildCacheSnapshot.ts +1 -1
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +2 -2
- package/src/lib/server/runtime/types/InspectorContext.ts +2 -2
- package/src/lib/server/server.ts +1 -1
- package/src/lib/server/socket.ts +1 -1
- package/src/lib/server/sockets/defineSocket.ts +1 -1
- package/src/lib/server/sse.ts +1 -1
- package/src/lib/shared/HttpError.ts +1 -1
- package/src/lib/shared/cache.ts +18 -18
- package/src/lib/shared/createSubscriber.ts +1 -1
- package/src/lib/shared/health.ts +1 -1
- package/src/lib/shared/html.ts +1 -1
- package/src/lib/shared/isSubscribable.ts +1 -1
- package/src/lib/shared/log.ts +1 -1
- package/src/lib/shared/online.ts +1 -1
- package/src/lib/shared/page.ts +1 -1
- package/src/lib/shared/pending.ts +2 -2
- package/src/lib/shared/probeRegistries.ts +2 -2
- package/src/lib/shared/refreshing.ts +2 -2
- package/src/lib/shared/selectorMatcher.ts +8 -8
- package/src/lib/shared/selectorPrefix.ts +1 -1
- package/src/lib/shared/snippet.ts +1 -1
- package/src/lib/shared/toTagSet.ts +4 -0
- package/src/lib/shared/trace.ts +1 -1
- package/src/lib/shared/types/CacheEntry.ts +3 -3
- package/src/lib/shared/types/CacheOptions.ts +3 -3
- package/src/lib/shared/types/CacheSelector.ts +2 -2
- package/src/lib/shared/url.ts +1 -1
- package/src/lib/shared/withJsonSchema.ts +1 -1
- package/src/lib/test/assertAgentFrameConformance.ts +1 -1
- package/src/lib/test/createScriptedSurface.ts +1 -1
- package/src/lib/test/createTestApp.ts +1 -1
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +7 -2
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +3 -4
- package/src/lib/ui/compile/abideUiPlugin.ts +1 -1
- package/src/lib/ui/compile/analyzeComponent.ts +2 -1
- package/src/lib/ui/compile/compileComponent.ts +3 -3
- package/src/lib/ui/compile/compileModule.ts +30 -2
- package/src/lib/ui/compile/compileSSR.ts +5 -5
- package/src/lib/ui/compile/compileShadow.ts +54 -36
- package/src/lib/ui/compile/desugarSignals.ts +147 -18
- package/src/lib/ui/compile/generateBuild.ts +15 -28
- package/src/lib/ui/compile/generateSSR.ts +20 -13
- package/src/lib/ui/compile/isControlFlow.ts +18 -0
- package/src/lib/ui/compile/isTextLeaf.ts +15 -0
- package/src/lib/ui/compile/lowerContext.ts +45 -5
- package/src/lib/ui/compile/prepareNestedScript.ts +12 -8
- package/src/lib/ui/compile/renameSignalRefs.ts +21 -4
- package/src/lib/ui/compile/skeletonable.ts +1 -14
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +1 -0
- package/src/lib/ui/computed.ts +32 -0
- package/src/lib/ui/createScope.ts +91 -0
- package/src/lib/ui/dom/anchorCursor.ts +1 -1
- package/src/lib/ui/dom/appendSnippet.ts +1 -1
- package/src/lib/ui/dom/appendStatic.ts +1 -1
- package/src/lib/ui/dom/appendText.ts +1 -1
- package/src/lib/ui/dom/appendTextAt.ts +1 -1
- package/src/lib/ui/dom/applyResolved.ts +1 -1
- package/src/lib/ui/dom/attach.ts +7 -2
- package/src/lib/ui/dom/attr.ts +1 -1
- package/src/lib/ui/dom/awaitBlock.ts +1 -1
- package/src/lib/ui/dom/cloneStatic.ts +1 -1
- package/src/lib/ui/dom/each.ts +4 -3
- package/src/lib/ui/dom/eachAsync.ts +1 -1
- package/src/lib/ui/dom/hydrate.ts +20 -6
- package/src/lib/ui/dom/mount.ts +12 -1
- package/src/lib/ui/dom/mountChild.ts +6 -2
- package/src/lib/ui/dom/mountSlot.ts +1 -1
- package/src/lib/ui/dom/on.ts +10 -4
- package/src/lib/ui/dom/openMarker.ts +3 -3
- package/src/lib/ui/dom/skeleton.ts +13 -5
- package/src/lib/ui/dom/switchBlock.ts +1 -1
- package/src/lib/ui/dom/text.ts +1 -1
- package/src/lib/ui/dom/tryBlock.ts +1 -1
- package/src/lib/ui/dom/when.ts +1 -1
- package/src/lib/ui/effect.ts +7 -2
- package/src/lib/ui/enterScope.ts +18 -0
- package/src/lib/ui/exitScope.ts +8 -0
- package/src/lib/ui/history.ts +102 -0
- package/src/lib/ui/installHotBridge.ts +6 -8
- package/src/lib/ui/linked.ts +0 -1
- package/src/lib/ui/navigate.ts +1 -1
- package/src/lib/ui/outbox.ts +115 -0
- package/src/lib/ui/persist.ts +112 -0
- package/src/lib/ui/probeNavigation.ts +1 -1
- package/src/lib/ui/remoteProxy.ts +1 -1
- package/src/lib/ui/renderToStream.ts +1 -1
- package/src/lib/ui/router.ts +1 -1
- package/src/lib/ui/runtime/CURRENT_SCOPE.ts +10 -0
- package/src/lib/ui/runtime/OUTLET_TAG.ts +1 -1
- package/src/lib/ui/runtime/PATCH_BUS.ts +28 -0
- package/src/lib/ui/runtime/RESUME.ts +1 -1
- package/src/lib/ui/runtime/captureModelDoc.ts +29 -0
- package/src/lib/ui/runtime/claimExpected.ts +26 -0
- package/src/lib/ui/runtime/createComputedNode.ts +1 -1
- package/src/lib/ui/runtime/createDoc.ts +73 -3
- package/src/lib/ui/runtime/enterRenderPass.ts +1 -1
- package/src/lib/ui/runtime/escapeKey.ts +13 -0
- package/src/lib/ui/runtime/exitRenderPass.ts +1 -1
- package/src/lib/ui/runtime/hotReplace.ts +17 -8
- package/src/lib/ui/runtime/inScope.ts +19 -0
- package/src/lib/ui/runtime/localStoragePersistence.ts +34 -0
- package/src/lib/ui/runtime/nextBlockId.ts +1 -1
- package/src/lib/ui/runtime/seedModelDoc.ts +26 -0
- package/src/lib/ui/runtime/types/{Derived.ts → Computed.ts} +1 -1
- package/src/lib/ui/runtime/types/Doc.ts +3 -0
- package/src/lib/ui/runtime/types/HotInstance.ts +6 -2
- package/src/lib/ui/runtime/types/PatchEvent.ts +16 -0
- package/src/lib/ui/runtime/unescapeKey.ts +12 -0
- package/src/lib/ui/runtime/walkPath.ts +3 -1
- package/src/lib/ui/scope.ts +19 -0
- package/src/lib/ui/socketProxy.ts +1 -1
- package/src/lib/ui/startClient.ts +1 -1
- package/src/lib/ui/state.ts +1 -2
- package/src/lib/ui/sync.ts +42 -0
- package/src/lib/ui/tail.ts +1 -1
- package/src/lib/ui/types/History.ts +14 -0
- package/src/lib/ui/types/Outbox.ts +14 -0
- package/src/lib/ui/types/PersistHandle.ts +11 -0
- package/src/lib/ui/types/PersistenceStore.ts +12 -0
- package/src/lib/ui/types/Scope.ts +57 -0
- package/src/lib/ui/types/SyncTransport.ts +13 -0
- package/src/preload.ts +1 -1
- package/src/lib/shared/toScopeSet.ts +0 -4
- package/src/lib/ui/derived.ts +0 -49
- package/src/lib/ui/doc.ts +0 -15
package/AGENTS.md
CHANGED
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
|
|
26
26
|
One declared verb fans out to every surface, with no extra work:
|
|
27
27
|
|
|
28
|
-
```
|
|
28
|
+
```text
|
|
29
29
|
export const getMessages = GET(fn, { inputSchema })
|
|
30
30
|
│
|
|
31
31
|
┌───────────────┬────────────┼──────────────┬────────────────┐
|
|
32
32
|
SSR call browser fetch MCP tool CLI subcommand OpenAPI op
|
|
33
|
-
cache(fn)() fetch /rpc/...
|
|
34
|
-
(in-process) (typed proxy)
|
|
33
|
+
cache(fn)() fetch /rpc/... getMessages app get-messages /openapi.json
|
|
34
|
+
(in-process) (typed proxy) (read-only+schema) (schema→flags) (described)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
A Standard Schema (zod / valibot / arktype, unadapted) is the contract: it
|
|
@@ -76,7 +76,7 @@ For `bun test`, add `preload = ["@abide/abide/preload"]` under `[test]` in `bunf
|
|
|
76
76
|
|
|
77
77
|
## Server surface — `abide/server/*` (and authored helpers)
|
|
78
78
|
|
|
79
|
-
### RPC verbs — `@
|
|
79
|
+
### RPC verbs — `@documentation rpc`
|
|
80
80
|
Each is `Verb(fn, opts?)` with three overloads (see `src/lib/server/rpc/types/VerbHelper.ts`):
|
|
81
81
|
`Verb(fn, { inputSchema, outputSchema?, filesSchema?, clients?, timeout?, maxBodySize?, crossOrigin? })`,
|
|
82
82
|
`Verb(fn, { clients })`, and bare `Verb(fn)`. Return type usually infers from the
|
|
@@ -94,7 +94,7 @@ plain call decodes the body + throws `HttpError` on non-2xx; `.raw` resolves to
|
|
|
94
94
|
`Response` undecoded; `.stream(args)` returns a `Subscribable` (SSE/JSONL frames, or
|
|
95
95
|
the decoded body once) for `tail()`; `.fetch(req)` is framework-internal dispatch.
|
|
96
96
|
|
|
97
|
-
### Responses — `@
|
|
97
|
+
### Responses — `@documentation response`
|
|
98
98
|
- `abide/server/json(data, init?)` — JSON with `Cache-Control: no-store`; `json(undefined)` → 204 that round-trips to `undefined`.
|
|
99
99
|
- `abide/server/error(status, message?, init?)` — text/plain error; message defaults to the status reason phrase.
|
|
100
100
|
- `abide/server/redirect(url, status=302, init?)` — accepts relative URLs (platform `Response.redirect` doesn't); 301/302/303/307/308.
|
|
@@ -102,29 +102,29 @@ the decoded body once) for `tail()`; `.fetch(req)` is framework-internal dispatc
|
|
|
102
102
|
- `abide/server/sse(iterable, init?)` — wrap an `AsyncIterable` as Server-Sent Events; 15s keepalive; errors → `event: error`.
|
|
103
103
|
- `abide/shared/HttpError` — thrown by remote calls on non-2xx; carries `status`, `statusText`, raw `response`.
|
|
104
104
|
|
|
105
|
-
### Sockets — `@
|
|
105
|
+
### Sockets — `@documentation sockets`
|
|
106
106
|
- `abide/server/socket(opts?)` — declare a `Socket<T>` (an isomorphic `AsyncIterable<T>`) inside `src/server/sockets/<name>.ts`. Opts: `{ schema?, tail?, ttl?, clientPublish?, clients? }`. `tail: n` retains last n frames; `ttl` evicts older. HTTP face at `/__abide/sockets/<name>`: GET = retained tail, POST = publish (gated by `clientPublish`).
|
|
107
107
|
|
|
108
|
-
### Agents — `@
|
|
108
|
+
### Agents — `@documentation agent`
|
|
109
109
|
- `abide/server/agent(engine, messages)` — run a model engine against the app's own (already-gated) MCP surface; returns the engine's `AgentFrame` stream. Wrap in `jsonl()`/`sse()` to pick the transport. Types exported: `NeutralMessage`, `AgentFrame` (`text`/`tool_use`/`tool_result`/`done`), `AgentSurface`, `AgentEngine`. Engines live in `@abide/<provider>` packages, never in core.
|
|
110
110
|
|
|
111
|
-
### Request scope — `@
|
|
111
|
+
### Request scope — `@documentation request-scope`
|
|
112
112
|
Resolve only during an in-flight SSR render or RPC handler (throw outside one):
|
|
113
113
|
- `abide/server/request()` → the inbound `Request`.
|
|
114
114
|
- `abide/server/cookies()` → Bun `CookieMap`; writes flush as `Set-Cookie` on return.
|
|
115
115
|
- `abide/server/server()` → active `Bun.serve` (or a no-op in-process server under CLI/MCP/test).
|
|
116
116
|
|
|
117
|
-
### Config / data — `@
|
|
117
|
+
### Config / data — `@documentation configuration` / `reference`
|
|
118
118
|
- `abide/server/env(schema, opts?)` — validate `Bun.env` against a Standard Schema at module top level; fails boot loudly. Registered so the bundle launcher derives its setup form.
|
|
119
119
|
- `abide/server/appDataDir()` → the running bundle's per-user data dir (cwd-independent, pure).
|
|
120
120
|
|
|
121
|
-
### Observability — `@
|
|
121
|
+
### Observability — `@documentation observability`
|
|
122
122
|
- `abide/server/reachable(host)` — server-only outbound reachability; first call probes (HEAD), then warm-polls every TTL. Tuned by `ABIDE_REACHABLE_TTL` / `ABIDE_REACHABLE_TIMEOUT`.
|
|
123
123
|
- `abide/shared/health()` → `HealthState` (framework + app `health()` hook payload, typed via generated `health.d.ts`); also at `/__abide/health`.
|
|
124
124
|
- `abide/shared/log` — unified logger carrying request-scope context; `log()/warn/error/trace` on the app channel, `log.channel(name)` on a `DEBUG`-gated channel. `ABIDE_LOG_FORMAT=json` for JSON lines.
|
|
125
125
|
- `abide/shared/trace()` → current W3C `traceparent` (isomorphic; client reads the SSR-stamped trace).
|
|
126
126
|
|
|
127
|
-
### App / inspector types — `@
|
|
127
|
+
### App / inspector types — `@documentation plumbing`
|
|
128
128
|
- `abide/server/AppModule` — shape of `src/app.ts` (error handler, health hook, lifecycle).
|
|
129
129
|
- `abide/server/InspectorContext` — inspector wiring type.
|
|
130
130
|
- `abide/server/rpc/defineVerb`, `abide/server/sockets/defineSocket`, `abide/server/prompts/definePrompt`, `abide/server/prompts/renderPromptTemplate` — bundler-emitted runtime bindings; you don't call these by hand (the `GET`/`socket`/`.md` files compile down to them).
|
|
@@ -133,24 +133,24 @@ Resolve only during an in-flight SSR render or RPC handler (throw outside one):
|
|
|
133
133
|
|
|
134
134
|
## Isomorphic surface — `abide/shared/*`
|
|
135
135
|
|
|
136
|
-
### Cache — `@
|
|
137
|
-
- `abide/shared/cache(fnOrProducer)` → a memoised callable. Key auto-derives (method+url+args for a remote fn; producer-reference+args for a producer). Options `{ ttl?,
|
|
138
|
-
- `cache.invalidate(selector?, args?)` — end retention early (by fn, fn+args, `{
|
|
136
|
+
### Cache — `@documentation cache`
|
|
137
|
+
- `abide/shared/cache(fnOrProducer)` → a memoised callable. Key auto-derives (method+url+args for a remote fn; producer-reference+args for a producer). Options `{ ttl?, tags?, global?, swr? }`: `ttl` ms-past-resolve (omit = forever, `0` = dedupe-only / the **mutation idiom**); `tags` for group invalidation; `global` = process-level store (server); `swr` = stale-while-revalidate — on invalidate, keep the stale value (reader sees `refreshing()`, not `pending()`) and refetch in the background. `swr: true` refetches immediately; `swr: { throttle | debounce }` adds a coalescing window. GET-only, throws on a write.
|
|
138
|
+
- `cache.invalidate(selector?, args?)` — end retention early (by fn, fn+args, `{ tags }`, or all).
|
|
139
139
|
- `cache.patch(selector, updater, args?)` — optimistic local fold over matching entries.
|
|
140
140
|
- `cache.on(subscribable, (frame, ctx) => …)` — event-driven cache maintenance: run a handler per socket/stream frame; `ctx.invalidate` / `ctx.patch` are coverage-tracked and resync on reconnect. Client-only (no-op on server).
|
|
141
141
|
|
|
142
|
-
### Probes — `@
|
|
142
|
+
### Probes — `@documentation probes` (read-only; reading never triggers work)
|
|
143
143
|
- `abide/shared/pending(selector?, args?)` — "no value yet" (in-flight call, or stream awaiting first frame).
|
|
144
144
|
- `abide/shared/refreshing(selector?, args?)` — "holding a value while a fresher source is in flight".
|
|
145
145
|
- `abide/shared/online()` — reactive connectivity probe (server: the calling client's reported state via offline header).
|
|
146
146
|
|
|
147
147
|
Same selector grammar as `cache.invalidate`; also accept a `Subscribable`. See CONTEXT.md → Probe.
|
|
148
148
|
|
|
149
|
-
### Routing / page — `@
|
|
149
|
+
### Routing / page — `@documentation page` / `url`
|
|
150
150
|
- `abide/shared/page` — reactive proxy: `route`, `params`, `url` (browser-space), `navigating`. Isomorphic; re-runs reactive readers on navigation.
|
|
151
151
|
- `abide/shared/url(path, query?)` — type-safe URL builder; augmented by generated `RpcRoutes`/`PageRoutes`/`PublicAssets` for autocomplete. Applies mount base.
|
|
152
152
|
|
|
153
|
-
### Templating values — `@
|
|
153
|
+
### Templating values — `@documentation plumbing`
|
|
154
154
|
- `abide/shared/html` — `html\`...\`` tagged template → `RawHtml` (trusted markup); `rawHtmlString(v)`.
|
|
155
155
|
- `abide/shared/snippet(payload)` → `Snippet` — a reusable template builder (the `<template name=…>` form).
|
|
156
156
|
- `abide/shared/createSubscriber(start)` — the subscription primitive behind sockets/streams/probes.
|
|
@@ -159,53 +159,58 @@ Same selector grammar as `cache.invalidate`; also accept a `Subscribable`. See C
|
|
|
159
159
|
|
|
160
160
|
## UI surface — `abide/ui/*` (client-only)
|
|
161
161
|
|
|
162
|
-
### Reactive primitives — `@
|
|
163
|
-
|
|
164
|
-
- `
|
|
165
|
-
- `
|
|
166
|
-
- `
|
|
167
|
-
- `
|
|
162
|
+
### Reactive primitives — `@documentation plumbing` (declared through `scope()` in a `.abide` `<script>`; the runtime forms are NOT public exports)
|
|
163
|
+
Reactive state is owned by a scope and declared explicitly through it: `const count = scope().state(0)` (or a captured handle: `const s = scope(); const count = s.state(0)`). A **bare** `state(...)` / `linked(...)` / `computed(...)` call is a compile error — the surface always shows the scope interaction. The declared binding is then read/written by its bare name (`{count}`, `count = count + 1`); the compiler lowers that to the doc API.
|
|
164
|
+
- `scope().state(initial, transform?)` — local truth. Plain `state(x)` lowers to a serializable `model` (= `scope()`) doc slot. `state(x, transform)` is a write-coercion gate (`.value` cell).
|
|
165
|
+
- `scope().linked(seed, transform?)` — a `.value` cell seeded reactively from upstream (Angular's `linkedSignal`): owns a local value, reseeds when the `seed` thunk's deps change, edits stay local. Non-serializing — reseeds on resume.
|
|
166
|
+
- `scope().computed(compute)` → a read-only computed **doc slot** (`scope().derive("name", compute)`), referenced as `name()` (string-free reader): re-computed on resume, never serialized/journalled. Always read-only (no `set` overload) — a writable computed is expressed at the binding site (`bind:value={{ get, set }}`), where the write actually originates.
|
|
167
|
+
- `prop('name')` → a read-only computed doc slot over the parent thunk (`scope().derive`), referenced as `name()`.
|
|
168
|
+
- `abide/ui/effect(fn)` → run now, re-run on dependency change; `fn` may return teardown / be async; returns dispose. (`effect` IS still a public export.)
|
|
169
|
+
- `abide/ui/scope(address?)` → `Scope` — **the data + capability seam; the only public way to reach reactive state.** The reactive document (immutable path-addressed tree, every change a patch — JSON Pointer keys via `escapeKey`, so a key may contain `/`) is now *internal* (`doc`/`createDoc`): a scope wraps one and mirrors its interface — `read`/`replace`/`add`/`remove`/`cell`/`derive`/`snapshot` (data; `derive(path, compute)` is a computed slot, never stored/serialized/journalled), `child`/`root`/`parent` (tree), `dispose`. Every applied patch is announced on an internal process-global patch bus (`PATCH_BUS`) carrying `{ doc, patch, inverse }` — the single tap undo / persistence / sync consume; computed recomputes never reach it. Capabilities route where the scope's changes go — `record({ limit? })` to an undo journal (then `undo`/`redo`/`canUndo`/`canRedo`), `persist(key?)` to durable storage (key defaults to the scope `id`), `broadcast(transport)` to peers. A passable value (`<Child parentScope={scope}/>`). `scope()` = the ambient current scope — `mount`/`hydrate` (client) and `enterScope`/`exitScope` (SSR, per render) establish one per component; the lowering emits `const model = scope()`, so `scope()`'s data IS the component's `state`; `scope('/')` = the root. Resolves correctly inside event handlers, effects, and attach teardowns (they pin the scope they were registered under).
|
|
170
|
+
|
|
171
|
+
### Local-first queue — `@documentation ui`
|
|
172
|
+
- `abide/ui/outbox({ key, send, store?, online?, onDrop? })` → `Outbox<T>` — durable FIFO queue for local-first writes; distinct from `scope().broadcast()` (which replicates *state*, not outbound mutations). `enqueue(payload)` records a serializable mutation (persisted via `persist`, so it survives a reload) and drains FIFO while `online()`; success dequeues, offline-mid-send keeps the head and retries on reconnect (auto-drains on the online edge), an online rejection drops the entry and reports via `onDrop` (roll back the optimistic change there). At-least-once → `send` should be idempotent. `pending()` is a reactive read for a sync indicator. Built on `doc` + `persist` + `online` (the queue is itself a persisted doc).
|
|
168
173
|
|
|
169
174
|
### Streams
|
|
170
175
|
- `abide/ui/tail(subscribable)` → latest frame (`T | undefined`); `tail(x, { last: n })` → window `T[]`. Reactive latest-wins read of a socket/stream. `tail.status` / `tail.error` expose richer stream state. See CONTEXT.md → Tail.
|
|
171
176
|
|
|
172
|
-
### Navigation / lifecycle — `@
|
|
177
|
+
### Navigation / lifecycle — `@documentation plumbing`
|
|
173
178
|
- `abide/ui/navigate(path, replace?)` — client navigation.
|
|
174
179
|
- `abide/ui/router(...)`, `abide/ui/startClient(...)`, `abide/ui/renderToStream(render)` — bootstrap/render runtime (compiler/launcher uses these).
|
|
175
180
|
|
|
176
|
-
### DOM + render runtime — `@
|
|
181
|
+
### DOM + render runtime — `@documentation plumbing` (compiler-emitted; you don't hand-write these)
|
|
177
182
|
`abide/ui/dom/{mount,mountChild,hydrate,text,appendText,appendTextAt,appendSnippet,appendStatic,cloneStatic,skeleton,anchorCursor,mountSlot,attr,on,attach,each,eachAsync,when,awaitBlock,tryBlock,switchBlock,applyResolved}` and `abide/ui/runtime/{nextBlockId,enterRenderPass,exitRenderPass}`. These are what `analyzeComponent → generateBuild/generateSSR` lower a `.abide` file into — every bound element builds through the parser-backed `skeleton` (one clone + located holes / `<!--a-->` anchors); there is no imperative element builder. Read them only to understand compiler output.
|
|
178
183
|
- `abide/ui/remoteProxy`, `abide/ui/socketProxy` — the browser-side implementations the bundler swaps in for `GET(...)` / `socket(...)`.
|
|
179
184
|
|
|
180
185
|
### `.abide` component format (see `src/lib/ui/README.md`)
|
|
181
186
|
Valid HTML with `<script>` + native `<template>` control flow + scoped `<style>`.
|
|
182
|
-
- **Bindings:** `{expr}` text, `name={expr}` attr, `onclick={fn}`, `bind:value={…}` / `bind:checked` / `bind:group`, `attach={fn}` (node-lifetime attachment — the dual of `on`; the `use:`-action / `{@attach}` equivalent, lowered to `ui/dom/attach`).
|
|
187
|
+
- **Bindings:** `{expr}` text, `name={expr}` attr, `onclick={fn}`, `bind:value={…}` / `bind:checked` / `bind:group`, `attach={fn}` (node-lifetime attachment — the dual of `on`; the `use:`-action / `{@attach}` equivalent, lowered to `ui/dom/attach`). A two-way `bind:` target is an **lvalue** (`count`, `model.lines[i]`) or an **accessor object** `bind:value={{ get, set }}` (reads via `get()`, writes via `set(v)`) — the only way to two-way-bind derived state; binding a read-only `computed` is a compile error.
|
|
183
188
|
- **Control flow (native `<template>`):** `if` with a nested `else` (the `<template else>` is a CHILD of its `<template if>`, not a sibling), `each={list} as="x" key="x.id"`, `await={p}`/`then`/`catch`, `switch`/`case`/`default`.
|
|
184
|
-
- **A branch is a lexical scope:** any control-flow branch may host its own nested `<script>` and `<style>`. The nested `<script>` declares branch-local **plain** signals (`state`/`
|
|
189
|
+
- **A branch is a lexical scope:** any control-flow branch may host its own nested `<script>` and `<style>`. The nested `<script>` declares branch-local **plain** signals (`state`/`computed`/`linked`/`prop`) — owned by the branch's render scope, re-seeded each mount (not the serializable top-level `doc`) — with the branch's binding in scope (`then`/`catch`'s `as` value, the `each` `as`/`key` row), so it can derive from the awaited/iterated value; its bindings cover the branch subtree and later siblings auto-deref them. The nested `<style>` is scoped to that branch alone (its own `data-a-<hash>`), not the whole component.
|
|
185
190
|
- **Components:** capitalised tags (`<Layout title=…>`); children fill `<slot/>`; props are reactive (passed as thunks). A component has no directives — every attribute is a prop under its written name (so `onclick=`/`bind:open=`/`attach=` pass through as props, e.g. callbacks, not the DOM-element directives those are on a lowercase tag) and is type-checked against the child's declared props. `prop('name')` reads a typed component prop (the parent-supplied thunk, reactive + read-only); route params come from the `page` proxy (`page.params.name`), not `prop()`.
|
|
186
191
|
- **Snippets / named slots:** `<template name="x" args={…}>` declares a reusable named builder (the `snippet()` form), rendered like a function — covers named slots / `{@render}`.
|
|
187
192
|
- **Reactivity:** write plain assignment (`count += 1`, `items.push(x)`); the compiler lowers it to patches. Deep-field edits wake only that field.
|
|
188
|
-
- **SSR:** byte-identical HTML string; `renderToStream` ships the shell then streams `<template await>` fragments out of order; `hydrate` adopts
|
|
193
|
+
- **SSR:** byte-identical HTML string; `renderToStream` ships the shell then streams `<template await>` fragments out of order; `hydrate` adopts the server DOM in place — static structure, `if`/`else`, keyed `each`, `switch`, `try`, and child components/slots all claim existing nodes (no re-render; focus/scroll/input preserved). The one cold-rebuild case left is a genuinely-pending `await` that is neither resumable (`RESUME[id]`) nor cache-warm — it discards the boundary and builds the pending branch fresh; an `await` over a `cache`d read is warm on resume and adopts without a flash.
|
|
189
194
|
|
|
190
195
|
---
|
|
191
196
|
|
|
192
|
-
## Build / tooling — `@
|
|
197
|
+
## Build / tooling — `@documentation plumbing`
|
|
193
198
|
- `abide/ui-plugin` — Bun loader plugin for `.abide` files.
|
|
194
199
|
- `abide/resolver-plugin` — resolves the `$server`/`$ui`/virtual modules and swaps server↔client runtime per target.
|
|
195
200
|
- `abide/preload` — Bun preload registering both plugins (use in `bunfig.toml` `[test]`).
|
|
196
201
|
- `abide/build`, `abide/compile` — programmatic build / standalone-executable compile.
|
|
197
202
|
- `abide/tsconfig` — base tsconfig for consumer apps.
|
|
198
203
|
|
|
199
|
-
## Desktop bundle — `@
|
|
204
|
+
## Desktop bundle — `@documentation bundle`
|
|
200
205
|
- `abide/bundle/BundleWindow` — `src/bundle/window.ts` default-export shape (`title`, `width`, `height`, `menu`, `config` schema for the first-run setup form).
|
|
201
206
|
- `abide/bundle/BundleMenu`, `abide/bundle/BundleMenuItem` — custom menu types.
|
|
202
207
|
- `abide/bundle/onMenu(handler)` / `onMenu(name, handler)` — subscribe to native menu clicks (returns unsubscribe; drop into an `effect`). Inert outside the bundle.
|
|
203
208
|
- `abide/bundle/bundled()` — true inside the desktop webview (isomorphic detection).
|
|
204
209
|
|
|
205
|
-
## MCP — `@
|
|
210
|
+
## MCP — `@documentation plumbing`
|
|
206
211
|
- `abide/mcp/createMcpServer(opts)` — framework-internal; the `abide:mcp` virtual constructs it. Tools derive from verbs/sockets flagged `clients.mcp: true`; auth inherits from the inbound request; optional `authorize` hook. Served at `/__abide/mcp`.
|
|
207
212
|
|
|
208
|
-
## Testing — `@
|
|
213
|
+
## Testing — `@documentation testing`
|
|
209
214
|
- `abide/test/createTestApp()` → `TestApp` with typed `RpcClient` / `SocketClient` — in-process dispatch, no network.
|
|
210
215
|
- `abide/test/createScriptedSurface(...)` — records tool dispatches for engine tests.
|
|
211
216
|
- `abide/test/assertAgentFrameConformance(...)` — the frame contract every engine must satisfy (exactly one `done`, last; every `tool_use` answered by a same-id/name `tool_result`).
|
|
@@ -240,5 +245,5 @@ Valid HTML with `<script>` + native `<template>` control flow + scoped `<style>`
|
|
|
240
245
|
|
|
241
246
|
*Maintenance (abide repo only): this file mirrors `package.json` `exports`. After
|
|
242
247
|
adding/renaming an export, run `bun run scripts/readmeSurfaces.ts` from
|
|
243
|
-
`packages/abide/` (it lists every export by `@
|
|
244
|
-
one) and reflect the change here.*
|
|
248
|
+
`packages/abide/` (it lists every export by `@documentation` slug and fails on any
|
|
249
|
+
untagged one) and reflect the change here.*
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
+
## 0.34.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - make scope() the sole reactive surface ([`7484b44`](https://github.com/briancray/abide/commit/7484b44034542a9bdbdaeedd6c8b9bb08c71f2cf))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [`1593504`](https://github.com/briancray/abide/commit/159350461d6b1070bd0981c7a8ae049655eb1c7d) - drop unused Doc import from Scope type ([`383669b`](https://github.com/briancray/abide/commit/383669b957648e4393e4df341dc9e1b01303fab5))
|
|
12
|
+
|
|
13
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - rename selector "scope" to "tags" ([`38c41c8`](https://github.com/briancray/abide/commit/38c41c838091448c1477f588e6fafc4e566f9830))
|
|
14
|
+
|
|
15
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - rename @readme export tag to @documentation ([`7045cfb`](https://github.com/briancray/abide/commit/7045cfbe5a9d3f69d165cb91fd01355f76162495))
|
|
16
|
+
|
|
17
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - preserve template-literal whitespace when indenting module bodies ([`89d975a`](https://github.com/briancray/abide/commit/89d975ae58dc4459c85909f414e0e46431924103))
|
|
18
|
+
|
|
19
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - resolve scope() in the shadow program and map binding names ([`a06c38a`](https://github.com/briancray/abide/commit/a06c38a08d417bd45509c58d661caa5f45b34ae3))
|
|
20
|
+
|
|
21
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - migrate to the scope() authoring surface ([`b0691fc`](https://github.com/briancray/abide/commit/b0691fc56746e516b7196eec008c063c0dda5e6d))
|
|
22
|
+
|
|
23
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - rewrite scope() to avoid assignment-in-expression ([`c6e021b`](https://github.com/briancray/abide/commit/c6e021b68401bb30e55f11cf587a4b1bdf6f41c9))
|
|
24
|
+
|
|
25
|
+
- [`3697394`](https://github.com/briancray/abide/commit/3697394b693f82266dadd227033d08cacd9df0bf) - regenerate README/AGENTS and refocus the write-readme skill ([`d40a3fe`](https://github.com/briancray/abide/commit/d40a3fec152c339f267327a95348af51c1f62027))
|
|
26
|
+
|
|
3
27
|
## 0.33.1
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Write one function. Get a typed HTTP endpoint, a CLI, an MCP tool, and an OpenAPI operation — from the same line of code.**
|
|
4
4
|
|
|
5
|
-
abide is
|
|
5
|
+
abide is a type-safe isomorphic framework built on web standards and Bun. You declare a verb once; the bundler swaps the runtime per side and projects that one declaration onto every surface — humans hit it over HTTP or the CLI, machines hit it over MCP, and you control which surfaces each verb exposes. It's a framework built for humans *and* machines.
|
|
6
|
+
|
|
7
|
+
- Zero runtime dependencies
|
|
8
|
+
- A single runtime (Bun) in every mode — dev, build, and compiled binary
|
|
6
9
|
|
|
7
10
|
## Quick start
|
|
8
11
|
|
|
@@ -10,7 +13,7 @@ abide is not just a web framework. Strongly-typed RPCs surface through HTTP, a C
|
|
|
10
13
|
bunx abide scaffold my-app # scaffolds, installs, and starts the dev server
|
|
11
14
|
```
|
|
12
15
|
|
|
13
|
-
To see
|
|
16
|
+
To see every surface live, clone the repo and run the kitchen-sink example — each page is runnable and documented:
|
|
14
17
|
|
|
15
18
|
```sh
|
|
16
19
|
git clone https://github.com/briancray/abide
|
|
@@ -18,9 +21,7 @@ cd abide && bun install
|
|
|
18
21
|
cd examples/kitchen-sink && bun run dev
|
|
19
22
|
```
|
|
20
23
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
### RPCs
|
|
24
|
+
## RPCs
|
|
24
25
|
|
|
25
26
|
An RPC is a handler wrapped by its HTTP method — one export per file under `src/server/rpc/`. The file path is the URL; the schema validates args and projects the MCP tool, CLI flags, and OpenAPI operation. Standard Schema is the contract: zod, valibot, and arktype work unadapted.
|
|
26
27
|
|
|
@@ -50,13 +51,13 @@ cache(fn)() fetch /rpc/... getMessages app get-messages /openapi.json
|
|
|
50
51
|
(in-process) (typed proxy) (read-only+schema) (schema→flags) (described)
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
The same callable is consumed differently per side — `cache(getMessages)({ room })` in-process, the swapped `fetch` in the browser, `.raw(args)` for a `Response`, `.stream(args)` for `tail()`. A schema gates the machine surfaces: it unlocks CLI and (for read-only verbs) MCP; a mutating verb never auto-exposes to MCP — it needs an explicit `clients: { mcp: true }`. Per-verb `timeout` (504, on every surface) is distinct from the client-side `ABIDE_CLIENT_TIMEOUT`.
|
|
54
|
+
The same callable is consumed differently per side — `cache(getMessages)({ room })` in-process, the swapped `fetch` in the browser, `.raw(args)` for a `Response`, `.stream(args)` for `tail()`. A schema gates the machine surfaces: it unlocks the CLI and (for read-only verbs) MCP; a mutating verb never auto-exposes to MCP — it needs an explicit `clients: { mcp: true }`. Per-verb `timeout` (504, on every surface) is distinct from the client-side `ABIDE_CLIENT_TIMEOUT`.
|
|
54
55
|
|
|
55
56
|
> Query args travel as strings — use `z.coerce.*` so numbers and booleans validate.
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
## Sockets
|
|
58
59
|
|
|
59
|
-
One broadcast topic per file under `src/server/sockets/`. A `Socket<T>` is an isomorphic `AsyncIterable<T>` — every socket multiplexes onto one ws at `/__abide/sockets`.
|
|
60
|
+
One broadcast topic per file under `src/server/sockets/`. A `Socket<T>` is an isomorphic `AsyncIterable<T>` — every socket multiplexes onto one ws at `/__abide/sockets`. A `schema` validates publishes, infers the frame type, and flips on the MCP/CLI read faces.
|
|
60
61
|
|
|
61
62
|
```ts
|
|
62
63
|
// src/server/sockets/chat.ts
|
|
@@ -70,11 +71,11 @@ export const chat = socket({ schema, tail: 100, ttl: 3_600_000 })
|
|
|
70
71
|
export type ChatMessage = z.infer<typeof schema>
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
For clients that can't speak the ws multiplex, each socket has an HTTP face at `/__abide/sockets/<name>` — `GET` returns the retained tail, `POST` publishes (gated by `clientPublish
|
|
74
|
+
For clients that can't speak the ws multiplex, each socket has an HTTP face at `/__abide/sockets/<name>` — `GET` returns the retained tail, `POST` publishes (gated by `clientPublish`, off by default).
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
## Components
|
|
76
77
|
|
|
77
|
-
Components are `.abide` files — valid HTML with `<script>`, native `<template>` control flow, `{expr}` bindings, and a component-scoped `<style>`.
|
|
78
|
+
Components are `.abide` files — valid HTML with `<script>`, native `<template>` control flow, `{expr}` bindings, and a component-scoped `<style>`. Reactive state is reached through `scope()` (`scope().state(v)`, `scope().computed(fn)`); `prop` and `effect` are in scope without import. This page reads the verb above through `cache()`, tails the socket live, and exercises most of the template grammar:
|
|
78
79
|
|
|
79
80
|
```html
|
|
80
81
|
<script>
|
|
@@ -85,19 +86,19 @@ import { publishChat } from '$server/rpc/publishChat.ts'
|
|
|
85
86
|
import { chat } from '$server/sockets/chat.ts'
|
|
86
87
|
import Avatar from '$ui/Avatar.abide'
|
|
87
88
|
|
|
88
|
-
let room = prop('room')
|
|
89
|
-
const history =
|
|
90
|
-
const latest =
|
|
89
|
+
let room = prop('room') // typed via src/.abide/routes.d.ts
|
|
90
|
+
const history = scope().computed(() => cache(getMessages)({ room })) // SSR snapshot + reactive refetch
|
|
91
|
+
const latest = scope().computed(() => tail(chat)) // re-renders on every new frame
|
|
91
92
|
|
|
92
|
-
let from = state('alice')
|
|
93
|
-
let text = state('')
|
|
94
|
-
let filter = state('all') // all | mine | others
|
|
95
|
-
let onlyUnread = state(false)
|
|
93
|
+
let from = scope().state('alice')
|
|
94
|
+
let text = scope().state('')
|
|
95
|
+
let filter = scope().state('all') // all | mine | others
|
|
96
|
+
let onlyUnread = scope().state(false)
|
|
96
97
|
|
|
97
98
|
async function send(event: SubmitEvent) {
|
|
98
99
|
event.preventDefault()
|
|
99
100
|
if (text.trim() === '') return
|
|
100
|
-
await publishChat({
|
|
101
|
+
await publishChat({ from, text }) // server validates, then broadcasts
|
|
101
102
|
text = ''
|
|
102
103
|
}
|
|
103
104
|
</script>
|
|
@@ -150,5 +151,4 @@ async function send(event: SubmitEvent) {
|
|
|
150
151
|
</style>
|
|
151
152
|
```
|
|
152
153
|
|
|
153
|
-
|
|
154
154
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abide/abide",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Isomorphic multimodal HTTP framework built for humans and machines in a single Bun runtime",
|
|
@@ -72,11 +72,11 @@
|
|
|
72
72
|
"./shared/trace": "./src/lib/shared/trace.ts",
|
|
73
73
|
"./shared/url": "./src/lib/shared/url.ts",
|
|
74
74
|
"./shared/createSubscriber": "./src/lib/shared/createSubscriber.ts",
|
|
75
|
-
"./ui/state": "./src/lib/ui/state.ts",
|
|
76
|
-
"./ui/linked": "./src/lib/ui/linked.ts",
|
|
77
|
-
"./ui/derived": "./src/lib/ui/derived.ts",
|
|
78
75
|
"./ui/effect": "./src/lib/ui/effect.ts",
|
|
79
|
-
"./ui/
|
|
76
|
+
"./ui/scope": "./src/lib/ui/scope.ts",
|
|
77
|
+
"./ui/enterScope": "./src/lib/ui/enterScope.ts",
|
|
78
|
+
"./ui/exitScope": "./src/lib/ui/exitScope.ts",
|
|
79
|
+
"./ui/outbox": "./src/lib/ui/outbox.ts",
|
|
80
80
|
"./ui/dom/mount": "./src/lib/ui/dom/mount.ts",
|
|
81
81
|
"./ui/dom/mountChild": "./src/lib/ui/dom/mountChild.ts",
|
|
82
82
|
"./ui/dom/hydrate": "./src/lib/ui/dom/hydrate.ts",
|
|
@@ -99,7 +99,7 @@ Also rewrites modules under src/server/rpc and src/server/sockets:
|
|
|
99
99
|
defineSocket on the server (with the socket name + opts) or
|
|
100
100
|
socketProxy on the client (name only — opts are server-side).
|
|
101
101
|
*/
|
|
102
|
-
// @
|
|
102
|
+
// @documentation plumbing
|
|
103
103
|
export function abideResolverPlugin({
|
|
104
104
|
cwd = process.cwd(),
|
|
105
105
|
embedAssets = false,
|
package/src/build.ts
CHANGED
|
@@ -32,7 +32,7 @@ last-good server) survives instead of crashing and orphaning the child. By
|
|
|
32
32
|
default a failure exits the process (one-shot `abide build` / `compile`);
|
|
33
33
|
the dev orchestrator passes `exitOnFailure: false`.
|
|
34
34
|
*/
|
|
35
|
-
// @
|
|
35
|
+
// @documentation building
|
|
36
36
|
export async function build({
|
|
37
37
|
cwd = process.cwd(),
|
|
38
38
|
minify = true,
|
package/src/compile.ts
CHANGED
|
@@ -16,7 +16,7 @@ entry. Defaults
|
|
|
16
16
|
the target to the host platform and appends `.exe` for windows targets.
|
|
17
17
|
Returns the path of the emitted binary; exits the process on build failure.
|
|
18
18
|
*/
|
|
19
|
-
// @
|
|
19
|
+
// @documentation building
|
|
20
20
|
export async function compile({
|
|
21
21
|
cwd = process.cwd(),
|
|
22
22
|
target = detectTarget(),
|
|
@@ -5,7 +5,7 @@ A top-level bundle menu, inserted into the macOS menu bar between the standard
|
|
|
5
5
|
Edit and Window menus. `label` titles the menu; `items` are its entries top to
|
|
6
6
|
bottom.
|
|
7
7
|
*/
|
|
8
|
-
// @
|
|
8
|
+
// @documentation bundle
|
|
9
9
|
export type BundleMenu = {
|
|
10
10
|
label: string
|
|
11
11
|
items: BundleMenuItem[]
|
|
@@ -18,7 +18,7 @@ calls `webview_navigate` with the given URL (the native side, on the UI thread).
|
|
|
18
18
|
That's how the built-in Server menu drives the connect screen — `emit` reaches
|
|
19
19
|
the loaded page, `navigate` repoints the window itself.
|
|
20
20
|
*/
|
|
21
|
-
// @
|
|
21
|
+
// @documentation bundle
|
|
22
22
|
export type BundleMenuItem =
|
|
23
23
|
| { separator: true }
|
|
24
24
|
| { label: string; shortcut?: string; emit: string }
|
|
@@ -13,7 +13,7 @@ built-in File menu (Start server / Connect / Disconnect) are always installed.
|
|
|
13
13
|
`menu` adds custom top-level menus between the Edit and Window menus; their items
|
|
14
14
|
emit `abide:menu` events the app handles. See BundleMenuItem.
|
|
15
15
|
*/
|
|
16
|
-
// @
|
|
16
|
+
// @documentation bundle
|
|
17
17
|
export type BundleWindow = {
|
|
18
18
|
title?: string
|
|
19
19
|
width?: number
|
|
@@ -26,7 +26,7 @@ its *rendering context* (the webview) is inside it.
|
|
|
26
26
|
Distinct from runningAsStandaloneBinary(), which is also true for a plain compiled
|
|
27
27
|
(install-tarball) server binary — still a web app, not a bundle.
|
|
28
28
|
*/
|
|
29
|
-
// @
|
|
29
|
+
// @documentation bundle
|
|
30
30
|
export function bundled(): boolean {
|
|
31
31
|
if (typeof window === 'undefined') {
|
|
32
32
|
return Boolean(Bun.env.ABIDE_PARENT_PID)
|