@abide/abide 0.46.0 → 0.47.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 +365 -320
- package/CHANGELOG.md +80 -0
- package/README.md +203 -168
- package/package.json +12 -8
- package/src/abideLsp.ts +11 -12
- package/src/abideResolverPlugin.ts +9 -4
- package/src/lib/bundle/disconnected.abide +3 -0
- package/src/lib/cli/printCommandHelp.ts +43 -0
- package/src/lib/cli/printSessionHelp.ts +2 -1
- package/src/lib/cli/{printHelp.ts → printTopLevelHelp.ts} +3 -40
- package/src/lib/cli/runCli.ts +2 -1
- package/src/lib/mcp/buildPrompts.ts +25 -0
- package/src/lib/mcp/dispatchMcpRequest.ts +8 -6
- package/src/lib/mcp/mcpResourceServerSlot.ts +5 -10
- package/src/lib/mcp/mcpSurface.ts +13 -252
- package/src/lib/mcp/mcpTools.ts +187 -0
- package/src/lib/mcp/renderPrompt.ts +25 -0
- package/src/lib/mcp/types/McpSurface.ts +15 -0
- package/src/lib/mcp/types/PromptDescriptor.ts +5 -0
- package/src/lib/mcp/types/PromptMessage.ts +2 -0
- package/src/lib/mcp/types/ToolDescriptor.ts +7 -0
- package/src/lib/mcp/types/ToolResult.ts +2 -0
- package/src/lib/server/agent.ts +1 -1
- package/src/lib/server/jsonl.ts +2 -2
- package/src/lib/server/rpc/defineRpc.ts +5 -0
- package/src/lib/server/runtime/containsTraversal.ts +21 -17
- package/src/lib/server/runtime/createAppAssetServer.ts +11 -16
- package/src/lib/server/runtime/createServer.ts +101 -71
- package/src/lib/server/runtime/createUiPageRenderer.ts +23 -4
- package/src/lib/server/runtime/devClientFingerprint.ts +3 -3
- package/src/lib/server/runtime/devHotModuleResponse.ts +2 -1
- package/src/lib/server/runtime/finalizeResponse.ts +32 -0
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +8 -17
- package/src/lib/server/socket.ts +1 -1
- package/src/lib/server/sockets/createSocketDispatcher.ts +28 -5
- package/src/lib/server/sockets/defineSocket.ts +26 -7
- package/src/lib/server/sockets/types/SocketRegistryEntry.ts +1 -1
- package/src/lib/server/sockets/types/SocketRoutes.ts +1 -1
- package/src/lib/server/sse.ts +2 -2
- package/src/lib/shared/DEFER.ts +8 -0
- package/src/lib/shared/activeCacheStore.ts +2 -2
- package/src/lib/shared/activePage.ts +2 -2
- package/src/lib/shared/attachRpcSelectorMethods.ts +42 -0
- package/src/lib/shared/attachSocketSelectorMethods.ts +34 -0
- package/src/lib/shared/basePath.ts +2 -2
- package/src/lib/shared/baseSlot.ts +6 -5
- package/src/lib/shared/bodyValueForKind.ts +1 -2
- package/src/lib/shared/buildSocketOverChannel.ts +40 -4
- package/src/lib/shared/cache.ts +477 -110
- package/src/lib/shared/cacheEntryFromSnapshot.ts +3 -22
- package/src/lib/shared/cacheStoreSlot.ts +9 -5
- package/src/lib/{server/runtime → shared}/createReachable.ts +2 -2
- package/src/lib/shared/createRemoteFunction.ts +58 -9
- package/src/lib/shared/createResolverSlot.ts +24 -31
- package/src/lib/shared/createSocketSubRegistry.ts +2 -2
- package/src/lib/shared/decodeRefJson.ts +4 -2
- package/src/lib/shared/decodeResponse.ts +8 -6
- package/src/lib/shared/done.ts +14 -0
- package/src/lib/shared/encodeRefJson.ts +4 -2
- package/src/lib/shared/globalCacheStoreSlot.ts +9 -6
- package/src/lib/shared/hydratingSlot.ts +12 -0
- package/src/lib/shared/isLayoutFile.ts +12 -0
- package/src/lib/shared/keyForRemoteCall.ts +2 -1
- package/src/lib/shared/keyPrefixForRemote.ts +12 -0
- package/src/lib/shared/matchRoute.ts +175 -0
- package/src/lib/shared/normalizePathname.ts +11 -0
- package/src/lib/shared/pageSlot.ts +14 -5
- package/src/lib/shared/pageUrlForFile.ts +3 -3
- package/src/lib/shared/parseRouteSegments.ts +16 -7
- package/src/lib/shared/patch.ts +41 -0
- package/src/lib/shared/peek.ts +35 -0
- package/src/lib/shared/prepareRemoteExport.ts +40 -0
- package/src/lib/shared/prepareRpcModule.ts +98 -16
- package/src/lib/shared/prepareSocketModule.ts +11 -15
- package/src/lib/shared/queryStringFromArgs.ts +11 -0
- package/src/lib/shared/reachable.ts +102 -0
- package/src/lib/shared/refresh.ts +22 -0
- package/src/lib/shared/requestScopeSlot.ts +10 -7
- package/src/lib/shared/routeParamsShape.ts +9 -9
- package/src/lib/shared/rpcErrorRegistry.ts +69 -0
- package/src/lib/shared/selectorPrefix.ts +3 -10
- package/src/lib/shared/setOwnProperty.ts +19 -0
- package/src/lib/shared/snippet.ts +1 -1
- package/src/lib/shared/subscribableProbes.ts +111 -0
- package/src/lib/shared/tailProbeSlot.ts +8 -1
- package/src/lib/shared/types/CacheEntry.ts +9 -15
- package/src/lib/shared/types/CacheOptions.ts +8 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +0 -5
- package/src/lib/shared/types/RemoteCallable.ts +25 -7
- package/src/lib/shared/types/RemoteFunction.ts +48 -13
- package/src/lib/shared/types/ResolverSlot.ts +7 -4
- package/src/lib/shared/types/RpcError.ts +26 -0
- package/src/lib/shared/types/SmartReadOptions.ts +32 -0
- package/src/lib/shared/types/Socket.ts +54 -0
- package/src/lib/shared/types/SsrBootState.ts +27 -0
- package/src/lib/shared/types/SsrPayload.ts +21 -0
- package/src/lib/shared/types/Subscribable.ts +13 -13
- package/src/lib/shared/types/TailHooks.ts +2 -1
- package/src/lib/shared/url.ts +29 -14
- package/src/lib/shared/wakeHydrationPeeks.ts +20 -0
- package/src/lib/shared/writeTestSocketsDts.ts +1 -1
- package/src/lib/test/createScriptedSurface.ts +1 -1
- package/src/lib/test/createTestApp.ts +2 -2
- package/src/lib/test/createTestSocketChannel.ts +3 -3
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +5 -6
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +10 -7
- package/src/lib/ui/compile/abideUiPlugin.ts +2 -2
- package/src/lib/ui/compile/analyzeComponent.ts +28 -6
- package/src/lib/ui/compile/compileModule.ts +137 -11
- package/src/lib/ui/compile/compileShadow.ts +101 -84
- package/src/lib/ui/compile/desugarSignals.ts +120 -107
- package/src/lib/ui/compile/generateBuild.ts +48 -16
- package/src/lib/ui/compile/generateSSR.ts +117 -14
- package/src/lib/ui/compile/identifierReferencePattern.ts +13 -0
- package/src/lib/ui/compile/lowerContext.ts +10 -4
- package/src/lib/ui/compile/lowerScript.ts +72 -5
- package/src/lib/ui/compile/parseTemplate.ts +1 -14
- package/src/lib/ui/compile/prepareNestedScript.ts +31 -17
- package/src/lib/ui/compile/resolveReactiveExport.ts +95 -0
- package/src/lib/ui/compile/signalCallee.ts +24 -0
- package/src/lib/ui/compile/stripEffects.ts +14 -11
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +5 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +0 -5
- package/src/lib/ui/dom/appendStatic.ts +9 -1
- package/src/lib/ui/dom/appendText.ts +15 -3
- package/src/lib/ui/dom/assertClaimedText.ts +20 -0
- package/src/lib/ui/dom/awaitBlock.ts +19 -83
- package/src/lib/ui/dom/bindSelectValue.ts +48 -0
- package/src/lib/ui/dom/each.ts +12 -1
- package/src/lib/ui/dom/hydrate.ts +10 -0
- package/src/lib/ui/dom/mountChild.ts +2 -5
- package/src/lib/ui/dom/mountRange.ts +0 -75
- package/src/lib/ui/effect.ts +4 -3
- package/src/lib/ui/installHotBridge.ts +4 -2
- package/src/lib/ui/remoteProxy.ts +18 -2
- package/src/lib/ui/renderToStream.ts +9 -13
- package/src/lib/ui/resumeSeedScript.ts +2 -2
- package/src/lib/ui/router.ts +21 -2
- package/src/lib/ui/runtime/RESUME.ts +0 -6
- package/src/lib/ui/runtime/ambientScopeBacking.ts +1 -1
- package/src/lib/ui/runtime/types/SsrRender.ts +3 -4
- package/src/lib/ui/scope.ts +6 -3
- package/src/lib/ui/seedBootState.ts +53 -0
- package/src/lib/ui/socketChannel.ts +2 -2
- package/src/lib/ui/socketProxy.ts +9 -3
- package/src/lib/ui/startClient.ts +16 -30
- package/src/lib/ui/state.ts +44 -13
- package/src/lib/ui/sync.ts +11 -5
- package/src/lib/ui/tryEncodeResume.ts +2 -5
- package/src/lib/ui/types/Scope.ts +14 -10
- package/src/lib/ui/watch.ts +140 -0
- package/src/serverEntry.ts +6 -6
- package/template/CLAUDE.md +1 -1
- package/template/package.json +1 -1
- package/template/src/server/rpc/getHello.ts +3 -3
- package/template/src/ui/pages/page.abide +2 -2
- package/template/test/app.test.ts +1 -1
- package/src/lib/server/reachable.ts +0 -45
- package/src/lib/server/sockets/types/Socket.ts +0 -23
- package/src/lib/shared/CACHE_WRAPPED.ts +0 -9
- package/src/lib/shared/DEFER_MIN_ARRAY_LENGTH.ts +0 -14
- package/src/lib/shared/baseResolver.ts +0 -10
- package/src/lib/shared/cacheKeyOf.ts +0 -7
- package/src/lib/shared/cacheKeyStore.ts +0 -8
- package/src/lib/shared/cacheStoreResolver.ts +0 -12
- package/src/lib/shared/globalCacheStoreResolver.ts +0 -12
- package/src/lib/shared/pageResolver.ts +0 -16
- package/src/lib/shared/recordCacheKey.ts +0 -6
- package/src/lib/shared/requestScopeResolver.ts +0 -12
- package/src/lib/shared/setBaseResolver.ts +0 -4
- package/src/lib/shared/setCacheStoreResolver.ts +0 -4
- package/src/lib/shared/setGlobalCacheStoreResolver.ts +0 -4
- package/src/lib/shared/setPageResolver.ts +0 -4
- package/src/lib/shared/setRequestScopeResolver.ts +0 -4
- package/src/lib/shared/toBunRoutePattern.ts +0 -28
- package/src/lib/shared/types/TailOptions.ts +0 -10
- package/src/lib/ui/deferResume.ts +0 -36
- package/src/lib/ui/dom/firstElementBetween.ts +0 -14
- package/src/lib/ui/matchRoute.ts +0 -106
- package/src/lib/ui/runtime/scheduleWake.ts +0 -28
- package/src/lib/ui/runtime/whenIdle.ts +0 -21
- package/src/lib/ui/runtime/whenVisible.ts +0 -105
- package/src/lib/ui/tail.ts +0 -324
- /package/src/lib/{server/sockets → shared}/types/SocketClientFrame.ts +0 -0
- /package/src/lib/{server/sockets → shared}/types/SocketServerFrame.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,85 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
+
## 0.47.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 981c53f: server-side streaming — defineRpc opts.streaming + rewriteForServer injects it ([`00f6fa8`](https://github.com/briancray/abide/commit/00f6fa8fdedc412808108c959c8ad9cced2b643b))
|
|
8
|
+
- 981c53f: socket/rpc instance methods + reactive-surface follow-through ([`0d3d686`](https://github.com/briancray/abide/commit/0d3d686125d7906e1360af4f040f40f39892caa6))
|
|
9
|
+
- 981c53f: on(source, handler) reaction primitive ([`1cfa4f9`](https://github.com/briancray/abide/commit/1cfa4f94bf2e6cd5b612ae26a449007d2b1e1769))
|
|
10
|
+
- 981c53f: syntactic import-resolved reactive recognition (alias-safe, checker-free) ([`1e3e041`](https://github.com/briancray/abide/commit/1e3e041865541058d36c0f5d759d6b09f1256bb4))
|
|
11
|
+
- 981c53f: capture call errors at the boundary, clear on success/invalidate ([`32f3ee7`](https://github.com/briancray/abide/commit/32f3ee7ae495149a7873b5102b215b1d8c07ca04))
|
|
12
|
+
- 981c53f: bare call reads through the cache store (coalesced, reactive) ([`410e552`](https://github.com/briancray/abide/commit/410e552f5b233a814640737954cb01bf5825e816))
|
|
13
|
+
- 981c53f: typed fn.error(args?) probe over the rpc error registry ([`41f4d4a`](https://github.com/briancray/abide/commit/41f4d4a2127a35327bbc573f3656eda9dcf9307a))
|
|
14
|
+
- 981c53f: parked durable writes are pending, not errored ([`41fefbc`](https://github.com/briancray/abide/commit/41fefbc2d4f25c9364bd3e866edb90e1eb82df4e))
|
|
15
|
+
- 981c53f: .refresh/.patch/.peek instance methods ([`55d4051`](https://github.com/briancray/abide/commit/55d40512d6113a20960d128c3d47b5a54d4d6f98))
|
|
16
|
+
- 981c53f: patch() — optimistic/real-time local value mutation ([`67a2df7`](https://github.com/briancray/abide/commit/67a2df733d4e3948e68d253671daf322816737b0))
|
|
17
|
+
- 981c53f: rpc error registry (last error per call identity, reactive) ([`7138e23`](https://github.com/briancray/abide/commit/7138e23bf0285da2f90fdc08e918a4abe3b749ad))
|
|
18
|
+
- 981c53f: export ./ui/state; withdraw scope()/effect from author doc surface ([`77b5221`](https://github.com/briancray/abide/commit/77b52217d5baa9fa22b26d8aba8b0111237434eb))
|
|
19
|
+
- 981c53f: peek() — synchronous non-triggering value probe ([`78469a8`](https://github.com/briancray/abide/commit/78469a89dac0cc014b8958f8e1ffa85e4fb189ba))
|
|
20
|
+
- 981c53f: pre-bound selector methods on rpc instances (pending/refreshing/invalidate/cache) ([`8154dd0`](https://github.com/briancray/abide/commit/8154dd03ca4a1ac1b8c26292a43f72a85f3a9dab))
|
|
21
|
+
- 981c53f: SWR retention always-on for smart reads; type the smart call ([`844a8b7`](https://github.com/briancray/abide/commit/844a8b79a9b526d5d82e5e7febe57f61f23aa98d))
|
|
22
|
+
- 981c53f: done(sub) terminal reader + tail prober reports done/error ([`8a11ab3`](https://github.com/briancray/abide/commit/8a11ab31417edc59f062042b8181e5eaaa6bc140))
|
|
23
|
+
- 981c53f: state() gains .linked/.computed/.share/.shared ([`b02aead`](https://github.com/briancray/abide/commit/b02aeade95173ddea2ea363f6de2f9e1cc23fc90))
|
|
24
|
+
- 981c53f: refresh() — always-refetch over the selector grammar ([`b7bddb2`](https://github.com/briancray/abide/commit/b7bddb2dba94c269449ba2f52193f8c5ace6d5c1))
|
|
25
|
+
- 981c53f: wire client streaming — detectStreaming codegen + proxy flag ([`bac63fe`](https://github.com/briancray/abide/commit/bac63fe94d08a94cbf887600bf2f61764170dbc0))
|
|
26
|
+
- 981c53f: refresh() + peek() ([`d2f8f1a`](https://github.com/briancray/abide/commit/d2f8f1a5f541707a627a9e196ee0b53a060b721a))
|
|
27
|
+
- 981c53f: broadcast() + tail defaults to 1 ([`dc280e9`](https://github.com/briancray/abide/commit/dc280e9e76a781994ee92af8c98967220e4f793e))
|
|
28
|
+
- 981c53f: type-driven streaming — bare call returns Subscribable, drop .stream() ([`f457a2c`](https://github.com/briancray/abide/commit/f457a2c9c716a35ac398217196af92cf5751d650))
|
|
29
|
+
- 981c53f: emit $$watch for bindings; watch recognized + SSR-stripped (renames on) ([`f4f7812`](https://github.com/briancray/abide/commit/f4f781201c82fdfe28d50e5535d93766b0e130c8))
|
|
30
|
+
- c0db71d: Rebuild the data & reactivity surface around one smart call plus thin modifiers/probes/reactions.
|
|
31
|
+
|
|
32
|
+
**Breaking changes:**
|
|
33
|
+
|
|
34
|
+
- The **bare rpc call is now the smart read** — cached, coalesced, reactive, and stale-while-revalidate by default for replayable (GET/HEAD) reads; writes are coalesce-only. `cache(getFoo, args)` → `getFoo(args)`. The `cache()` function and the `./shared/cache` export are removed (the store remains the internal substrate). Per-call transport options (`signal`/`headers`/`keepalive`/`priority`/`cache`) move to `getFoo.raw(args, init)`; the smart call's second arg is cache/stream options (`ttl`/`tags`/`throttle`/`debounce`/`n`).
|
|
35
|
+
- **`.refresh` / `.patch` / `.peek`** — new global functions (`./shared/refresh`, `./shared/patch`, `./shared/peek`) and rpc instance methods. `.refresh` replaces `.invalidate` (refetch keeping the stale value visible, never blanking); `.patch` mutates the retained value locally with no network; `.peek` reads the retained value synchronously. `fn.invalidate`/`fn.cache` instance methods are removed (`fn.refresh` / the bare call replace them).
|
|
36
|
+
- **`watch(source, handler)`** (`./ui/watch`) is the single reaction primitive, replacing `effect`, `socket.on`, and `cache.on` for authors and the compiler (bindings emit `$$watch`). `effect` is off the taught surface (internal plumbing). Instance sugar mirrors the global for the two subscribable/rpc sources — `socket.watch(handler)` and `fn.watch(handler)` / `fn.watch(args, handler)` (client-only; SSR-inert no-op).
|
|
37
|
+
- **Sockets:** `socket.broadcast(msg)` replaces `.publish`; retention (`tail`) defaults to `1`; `socket.peek()` / `socket.refresh()` added. The `tail()` reactive-consumer function (`./ui/tail`) and `socket.tail()` are off the taught surface — consume the socket directly (`for await` / `watch`) and window via `watch` + `state`; `pending`/`refreshing`/`done`(socket) now register on consumption.
|
|
38
|
+
|
|
39
|
+
- 2a42d90: Remove all later-hydration: the inferred deferred `{#await cache()}` inert path and the explicit `client:idle` / `client:visible` component islands. Both traded eager hydration for a wake-later heuristic, and the inference was the source of the "control renders dead until the wake fires" bug class. A blocking `{#await cache()}` now renders on the server, seeds warm, and hydrates eagerly — live on the first frame. `client:idle` / `client:visible` are no longer recognized directives. Very large grids that relied on island deferral should adopt their own virtualization.
|
|
40
|
+
- f0f8d77: Close the `<select>` and boolean/numeric binding gaps.
|
|
41
|
+
|
|
42
|
+
- **`<select bind:value>` now handles late-mounting options.** Options produced by a `{#for}` block or async data mount _after_ the binding runs, and the browser drops a `value` set that names a not-yet-present option — so the initial value silently failed to apply. The bind now routes through a new `bindSelectValue` runtime helper (`./ui/dom/bindSelectValue`) that re-applies the selection whenever the option set changes (via a `MutationObserver`), covering static, `{#for}`, and async options uniformly.
|
|
43
|
+
- **`<select multiple bind:value>`** binds an array of the selected option values (two-way): the bound array drives which options are `selected`, and a user's picks are collected back into it.
|
|
44
|
+
- **SSR selects the matching option.** A server-rendered `<select bind:value>` now emits `selected` on the matching `<option>` (single) or every member (multiple) — the browser ignores a `value="…"` on the select, so the pre-hydration/no-JS state was wrong before. Option value is taken from its `value` attribute, else its static text.
|
|
45
|
+
- **`<details bind:open>` SSR fix.** `open` is a boolean attribute, so the old generic path emitted `open="false"` and rendered the element _open_ when closed. It now emits the bare attribute only when truthy, like `checked`.
|
|
46
|
+
- **Numeric input coercion.** `bind:value` on `<input type="number">` / `type="range"` now writes back a number (via `valueAsNumber`, empty field → `undefined`) instead of a string, so number-typed state stays a number.
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- 981c53f: rpc error registry is client-only — no cross-request SSR leak ([`00c6efb`](https://github.com/briancray/abide/commit/00c6efb0053c0bcd0e44748ebcb85826ec382b27))
|
|
51
|
+
- 981c53f: decide the tool namespace once — mcpTools replaces buildTools/callTool ([`05b31f1`](https://github.com/briancray/abide/commit/05b31f18a02c2ec344f8d17bcbda50d534aad104))
|
|
52
|
+
- 981c53f: migrate .abide fixtures off scope() onto the imported reactive surface ([`0d487db`](https://github.com/briancray/abide/commit/0d487dbf02c6368bd1f889c6679951fc49c364ca))
|
|
53
|
+
- 981c53f: Breaking: re-home subscribable probes onto consume; remove tail() ([`1e0ae9f`](https://github.com/briancray/abide/commit/1e0ae9ff75f2c48921c807c6c4445930933533c6))
|
|
54
|
+
- 981c53f: desugar via import-resolution; bare imported primitives are the surface ([`21a52a5`](https://github.com/briancray/abide/commit/21a52a5b733da810a155eab6863d35b9e9ddd459))
|
|
55
|
+
- 981c53f: keep SSR/client text claims congruent ([`383f7ab`](https://github.com/briancray/abide/commit/383f7ab5582533f7ecaad7c76b01c6ce7c114818))
|
|
56
|
+
- 981c53f: shadow + nested-script recognize imported reactives; effect author-imported ([`415a232`](https://github.com/briancray/abide/commit/415a23223b44ff60776f5f68226d93dc9c2c5c7c))
|
|
57
|
+
- 981c53f: regenerate README + AGENTS.md for the imported-reactive / flat-cache / bare-streaming surface ([`42a7404`](https://github.com/briancray/abide/commit/42a7404c00fa90334d14d715d2a17095f5b5456d))
|
|
58
|
+
- 981c53f: extract finalizeResponse — the dynamic route's wire-handling step ([`4369119`](https://github.com/briancray/abide/commit/4369119ae41e3338af2769790ccd4a2b3cad68de))
|
|
59
|
+
- 981c53f: regenerate README + AGENTS.md for the new data/reactivity surface ([`4c6d6eb`](https://github.com/briancray/abide/commit/4c6d6eb1033f64770c8e2154e856f00f6a5a834f))
|
|
60
|
+
- 981c53f: hoist value consts above __Props so keyof typeof prop annotations resolve ([`581eebe`](https://github.com/briancray/abide/commit/581eebefd41f05d2875f96a3965d90c2c7a1da63))
|
|
61
|
+
- 981c53f: import-resolution is the sole reactive recognition path ([`5b13721`](https://github.com/briancray/abide/commit/5b13721741e5c7bd85844b21f23372b588f05d24))
|
|
62
|
+
- 981c53f: bump scaffold @abide/abide floor to ^0.46.0 ([`5d10cb5`](https://github.com/briancray/abide/commit/5d10cb5b2388fd45e0403b798ca8908b08f0a0e4))
|
|
63
|
+
- 981c53f: reject streaming rpcs at compile time (@deprecated overload → never) ([`7277533`](https://github.com/briancray/abide/commit/7277533c74eec1103c4021844bbb5547f8b452de))
|
|
64
|
+
- 981c53f: narrow the select-bind indexed access so tsgo passes under noUncheckedIndexedAccess ([`796340c`](https://github.com/briancray/abide/commit/796340c5aed2e21a1a46411fda30a4cb9450a95d))
|
|
65
|
+
- 981c53f: resolve full-codebase review findings (22 bugs + cleanups) ([`8523d25`](https://github.com/briancray/abide/commit/8523d25d596d435ffea989ce93da75b4210bb655))
|
|
66
|
+
- 981c53f: server streaming rewrite handles trailing comma / empty opts ([`89eb801`](https://github.com/briancray/abide/commit/89eb80142cae47fc53b3654e0c81f1bd9a394ecc))
|
|
67
|
+
- 981c53f: unify **SSR** payload behind a shared contract + exhaustive boot seed ([`8b242f1`](https://github.com/briancray/abide/commit/8b242f1d0dab035a3bd439370b6a5066d5254d86))
|
|
68
|
+
- 981c53f: sync examples, README, and AGENTS.md to {#snippet} block syntax ([`8fa8e72`](https://github.com/briancray/abide/commit/8fa8e7256eb2ddb1df48ab19c39ebfa1a86ac7c8))
|
|
69
|
+
- 981c53f: repoint scope host to plumbing exports; drop dead reactive imports ([`a58aee6`](https://github.com/briancray/abide/commit/a58aee6418136de675a56190e4b7ee7dc84d54cc))
|
|
70
|
+
- 981c53f: type {#snippet} as Snippet-returning in the check shadow ([`b2bca21`](https://github.com/briancray/abide/commit/b2bca217dfc12a6fe5870bdecf0bca2ef4e4b628))
|
|
71
|
+
- 981c53f: Breaking: flatten cache(fn, args, options) — direct read-through, drop the wrapper ([`b8d356f`](https://github.com/briancray/abide/commit/b8d356fb078a548433311dd19a2bec930c30e29a))
|
|
72
|
+
- 981c53f: migrate template + scaffold to the new surface ([`bc1ccfd`](https://github.com/briancray/abide/commit/bc1ccfdc7699cc0de034bdadcf79b7cc5e3695bd))
|
|
73
|
+
- 981c53f: guard detectStreaming indexed access under noUncheckedIndexedAccess ([`bc5cecb`](https://github.com/briancray/abide/commit/bc5cecbf5b6669297a90e16cf8762110b928b641))
|
|
74
|
+
- 981c53f: one module per resolved runtime value — the slot is the seam ([`c2dcde4`](https://github.com/briancray/abide/commit/c2dcde496e43868aeb94c23773e9f6630820b3c9))
|
|
75
|
+
- 981c53f: declare pending/refreshing/invalidate/cache instance methods ([`c743df8`](https://github.com/briancray/abide/commit/c743df80777f6dcf1c7d326713c6124254a4bca4))
|
|
76
|
+
- 981c53f: record why the type-check shadow stays off the Plan model (ADR-0014) ([`c9f77dd`](https://github.com/briancray/abide/commit/c9f77ddb44832354e71d711d035be497fa258ef6))
|
|
77
|
+
- 981c53f: flatten cache() and update .stream() doc to bare streaming-rpc call ([`cfdf715`](https://github.com/briancray/abide/commit/cfdf71546bf14c2e29714d057307b14081e048a9))
|
|
78
|
+
- 981c53f: Breaking: remove .invalidate/.cache instance methods ([`e809b22`](https://github.com/briancray/abide/commit/e809b22280ff851e51dbbbc3e65c6e8e6fb86a81))
|
|
79
|
+
- 981c53f: Breaking: remove ./shared/cache export; retag ./ui/effect as plumbing ([`e9b5e94`](https://github.com/briancray/abide/commit/e9b5e9463f6f201bbf7e7b9455e5090e4c4c6ba6))
|
|
80
|
+
- 981c53f: fold route matching into shared matchRoute ([`f00630b`](https://github.com/briancray/abide/commit/f00630bd2366f968e412d61b7b791e679d985414))
|
|
81
|
+
- 981c53f: Breaking: remove .publish, migrate all call sites to .broadcast ([`fa0fd00`](https://github.com/briancray/abide/commit/fa0fd00f5f891d9f804155aaf496f6cf0eb9c535))
|
|
82
|
+
|
|
3
83
|
## 0.46.0
|
|
4
84
|
|
|
5
85
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,242 +1,277 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
-
**One typed declaration
|
|
4
|
-
|
|
3
|
+
**One typed declaration, every surface: an RPC you write once fans out to HTTP,
|
|
4
|
+
a CLI, an MCP tool, and an OpenAPI operation — and the same callable runs
|
|
5
|
+
in-process on the server and over fetch in the browser.**
|
|
5
6
|
|
|
6
|
-
abide is
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
OpenAPI operation.
|
|
7
|
+
abide is an isomorphic multimodal HTTP framework built for humans and machines
|
|
8
|
+
in a single Bun runtime: file-path routing, Standard Schema validation, and a
|
|
9
|
+
compiled `.abide` UI layer that server-renders, streams, and hydrates the same
|
|
10
|
+
components. The bundler swaps each callable's runtime per side — same name,
|
|
11
|
+
same behavior, no client/server forks in app code.
|
|
12
12
|
|
|
13
|
-
One direct dependency (TypeScript). One runtime (Bun ≥ 1.3
|
|
13
|
+
- One direct dependency (TypeScript). One runtime (Bun ≥ 1.3).
|
|
14
14
|
|
|
15
15
|
## Quick start
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
bunx abide scaffold my-app # scaffolds, installs, and starts the dev server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or run the kitchen-sink example, which demos the full surface:
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
```sh
|
|
22
24
|
git clone https://github.com/briancray/abide
|
|
23
|
-
cd abide
|
|
24
|
-
bun
|
|
25
|
-
bun run dev
|
|
25
|
+
cd abide && bun install
|
|
26
|
+
cd examples/kitchen-sink && bun run dev
|
|
26
27
|
```
|
|
27
28
|
|
|
28
29
|
## RPCs
|
|
29
30
|
|
|
30
|
-
An RPC is one
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
valibot, arktype
|
|
34
|
-
|
|
31
|
+
An RPC is one exported handler per file under `src/server/rpc/` — the file path
|
|
32
|
+
is the URL. The export wraps the handler in an HTTP-method helper (`GET`,
|
|
33
|
+
`POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`); a Standard Schema `inputSchema`
|
|
34
|
+
(zod, valibot, arktype — no adapter) validates the args and projects the CLI
|
|
35
|
+
flags, the MCP tool, and the OpenAPI operation from the one declaration.
|
|
35
36
|
|
|
36
37
|
```ts
|
|
37
38
|
// src/server/rpc/getMessages.ts
|
|
38
39
|
import { GET } from '@abide/abide/server/GET'
|
|
39
40
|
import { json } from '@abide/abide/server/json'
|
|
40
41
|
import { z } from 'zod'
|
|
42
|
+
import { listMessages } from '$server/store'
|
|
41
43
|
|
|
42
|
-
const rooms: Record<string, { id: string; text: string }[]> = {}
|
|
43
|
-
|
|
44
|
-
// GET /rpc/getMessages?room=lobby
|
|
45
44
|
export const getMessages = GET(
|
|
46
|
-
(
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// src/server/rpc/postMessage.ts
|
|
53
|
-
import { POST } from '@abide/abide/server/POST'
|
|
54
|
-
import { json } from '@abide/abide/server/json'
|
|
55
|
-
import { error } from '@abide/abide/server/error'
|
|
56
|
-
import { z } from 'zod'
|
|
57
|
-
|
|
58
|
-
const rateLimited = error.typed('rateLimited', 429)
|
|
59
|
-
|
|
60
|
-
// A mutating method never auto-exposes to MCP — opt in explicitly.
|
|
61
|
-
export const postMessage = POST(
|
|
62
|
-
(args: { room: string; text: string }) => {
|
|
63
|
-
if (args.text.length > 500) return rateLimited()
|
|
64
|
-
return json({ ok: true })
|
|
45
|
+
async ({ room, limit }) => json(await listMessages(room, limit)),
|
|
46
|
+
{
|
|
47
|
+
inputSchema: z.object({
|
|
48
|
+
room: z.string(),
|
|
49
|
+
limit: z.coerce.number().default(50),
|
|
50
|
+
}),
|
|
65
51
|
},
|
|
66
|
-
{ inputSchema: z.object({ room: z.string(), text: z.string() }), clients: { mcp: true } },
|
|
67
52
|
)
|
|
68
53
|
```
|
|
69
54
|
|
|
70
|
-
|
|
55
|
+
That one file fans out:
|
|
71
56
|
|
|
72
57
|
```text
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
58
|
+
src/server/rpc/getMessages.ts
|
|
59
|
+
│
|
|
60
|
+
├─ SSR / server await getMessages({ room }) in-process, no HTTP
|
|
61
|
+
├─ browser await getMessages({ room }) typed fetch proxy
|
|
62
|
+
├─ HTTP GET /rpc/getMessages?room=…
|
|
63
|
+
├─ CLI my-app get-messages --room …
|
|
64
|
+
├─ MCP tool: get-messages
|
|
65
|
+
└─ OpenAPI operation in /openapi.json
|
|
80
66
|
```
|
|
81
67
|
|
|
82
|
-
A schema
|
|
83
|
-
|
|
84
|
-
explicit `clients: { mcp: true }`.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
68
|
+
A schema is the gate: it unlocks the CLI, and — for read-only methods
|
|
69
|
+
(GET/HEAD) — the MCP tool. A mutating method (POST/PUT/PATCH/DELETE) never
|
|
70
|
+
auto-exposes to MCP; it needs an explicit `clients: { mcp: true }`.
|
|
71
|
+
|
|
72
|
+
The bare call **is** the smart read — cached, coalesced, reactive,
|
|
73
|
+
stale-while-revalidate — and it is isomorphic: the same callable resolves
|
|
74
|
+
in-process during SSR (its value baked into the HTML for warm hydration) and
|
|
75
|
+
over `fetch` in the browser. Around it:
|
|
76
|
+
|
|
77
|
+
- `getMessages.raw(args, init?)` — the raw `Response`; per-call transport
|
|
78
|
+
options (`signal`, `headers`, …) live here
|
|
79
|
+
- `getMessages.refresh(args?)` — refetch, keeping the stale value visible
|
|
80
|
+
- `getMessages.patch(args?, updater)` — mutate the retained value locally,
|
|
81
|
+
no network
|
|
82
|
+
- `getMessages.peek(args?)` — read the retained value synchronously
|
|
83
|
+
- `getMessages.pending(args?)` / `.refreshing(args?)` / `.error(args?)` —
|
|
84
|
+
reactive probes
|
|
85
|
+
- a handler that returns `jsonl()`/`sse()` makes the bare call return a
|
|
86
|
+
`Subscribable` you `for await` — detected at build time, nothing to declare
|
|
87
|
+
|
|
88
|
+
> Query args travel as strings — use `z.coerce.*` for numbers and booleans on
|
|
89
|
+
> GET/HEAD. The per-RPC `timeout` option is a server-side handler deadline
|
|
90
|
+
> (504, enforced on every surface); `ABIDE_CLIENT_TIMEOUT` bounds browser calls
|
|
91
|
+
> and is separate.
|
|
92
92
|
|
|
93
93
|
## Sockets
|
|
94
94
|
|
|
95
|
-
A socket is one broadcast topic per file under `src/server/sockets
|
|
96
|
-
`Socket<T>` is an isomorphic `AsyncIterable<T
|
|
97
|
-
|
|
98
|
-
WebSocket at `/__abide/sockets
|
|
99
|
-
the browser proxy sends a `pub` frame.
|
|
95
|
+
A socket is one broadcast topic per file under `src/server/sockets/` — the
|
|
96
|
+
export name is the topic. A `Socket<T>` is an isomorphic `AsyncIterable<T>`:
|
|
97
|
+
server code iterates and broadcasts in-process; browser code gets the same
|
|
98
|
+
shape over one multiplexed WebSocket at `/__abide/sockets`.
|
|
100
99
|
|
|
101
100
|
```ts
|
|
102
|
-
// src/server/sockets/
|
|
101
|
+
// src/server/sockets/chat.ts
|
|
103
102
|
import { socket } from '@abide/abide/server/socket'
|
|
104
103
|
import { z } from 'zod'
|
|
105
104
|
|
|
106
|
-
export const
|
|
107
|
-
schema: z.object({
|
|
108
|
-
tail: 50, // retain the last 50 frames for late joiners
|
|
109
|
-
ttl: 60_000, //
|
|
105
|
+
export const chat = socket({
|
|
106
|
+
schema: z.object({ author: z.string(), text: z.string() }),
|
|
107
|
+
tail: 50, // retain the last 50 frames for late joiners (default 1)
|
|
108
|
+
ttl: 60_000, // retained frames expire after a minute
|
|
109
|
+
clientPublish: true, // allow browser publishes (off by default)
|
|
110
110
|
})
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
`chat.broadcast(msg)` publishes from either side — schema-validated on the
|
|
114
|
+
server, and client publishes are gated by `clientPublish`. `for await (const
|
|
115
|
+
msg of chat)` is the live stream; `chat.peek()` reads the latest retained
|
|
116
|
+
frame; `chat.refresh()` re-pulls the server tail after a reconnect. A schema
|
|
117
|
+
also advertises the topic to MCP and the CLI.
|
|
118
|
+
|
|
119
|
+
Every exposed socket has an HTTP face at `/__abide/sockets/<name>`: `GET`
|
|
120
|
+
returns the retained tail as JSON (or a live SSE stream under
|
|
121
|
+
`Accept: text/event-stream`), `POST` publishes — gated by `clientPublish`.
|
|
115
122
|
|
|
116
123
|
## Components
|
|
117
124
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
Pages are `.abide` single-file components under `src/ui/pages/` (`page.abide` /
|
|
126
|
+
`layout.abide`; a `[id]` folder becomes a route param read via `props()`). A
|
|
127
|
+
component is HTML plus `{expr}` bindings and `{#…}` control-flow blocks.
|
|
128
|
+
Reactive state comes from imported primitives the compiler lowers, so inside a
|
|
129
|
+
component you read and write state as plain variables. The same file renders on
|
|
130
|
+
the server — blocking awaits inline, streaming awaits out of order, cached
|
|
131
|
+
reads seeded warm — and hydrates in the browser.
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
destructure-once idiom — pull the primitives off `scope()` at the top of the
|
|
125
|
-
`<script>`, then call them bare. `computed` is read-only; `effect` is client-only
|
|
126
|
-
(stripped from SSR). A bare `state`/`computed`/`linked`/`effect` with no
|
|
127
|
-
`scope()` destructure is a compile error.
|
|
133
|
+
A child component renders whatever you nest in it at `{children()}`:
|
|
128
134
|
|
|
129
135
|
```html
|
|
130
136
|
<script>
|
|
131
|
-
|
|
132
|
-
import { tail } from '@abide/abide/ui/tail'
|
|
133
|
-
import { html } from '@abide/abide/ui/html'
|
|
134
|
-
import { getMessages } from '$server/rpc/getMessages.ts'
|
|
135
|
-
import { postMessage } from '$server/rpc/postMessage.ts'
|
|
136
|
-
import { messages } from '$server/sockets/messages.ts'
|
|
137
|
-
import MessageCard from '$ui/MessageCard.abide'
|
|
138
|
-
|
|
139
|
-
const { state, computed, linked, effect } = scope()
|
|
140
|
-
const { room = 'lobby' } = props()
|
|
141
|
-
|
|
142
|
-
let draft = state('')
|
|
143
|
-
let showRaw = state(false)
|
|
144
|
-
let filter = state('all')
|
|
145
|
-
const trimmed = computed(() => draft.trim())
|
|
146
|
-
const outgoing = linked(() => room + ': ' + trimmed)
|
|
147
|
-
const banner = html`<strong>#${room}</strong>`
|
|
148
|
-
|
|
149
|
-
// client-only reaction — never runs during SSR
|
|
150
|
-
effect(() => console.log('draft is now', draft))
|
|
151
|
-
|
|
152
|
-
// the derived two-way binding target, read down / written up
|
|
153
|
-
const get = () => outgoing
|
|
154
|
-
const set = (value) => (draft = value)
|
|
155
|
-
// mutating RPC from an event handler
|
|
156
|
-
const send = () => {
|
|
157
|
-
postMessage({ room, text: trimmed })
|
|
158
|
-
draft = ''
|
|
159
|
-
}
|
|
137
|
+
const { title } = props()
|
|
160
138
|
</script>
|
|
161
139
|
|
|
162
|
-
|
|
163
|
-
<
|
|
140
|
+
<section>
|
|
141
|
+
<h2>{title}</h2>
|
|
142
|
+
{#if children}{children()}{:else}<p>Nothing here yet.</p>{/if}
|
|
143
|
+
</section>
|
|
144
|
+
|
|
145
|
+
<style>
|
|
146
|
+
section {
|
|
147
|
+
border: 1px solid gray;
|
|
148
|
+
}
|
|
149
|
+
</style>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
And one page tying together the RPC from above, the socket, and the whole
|
|
153
|
+
template grammar:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<script>
|
|
157
|
+
import { getMessages } from '$server/rpc/getMessages'
|
|
158
|
+
import { sendMessage } from '$server/rpc/sendMessage' // POST, declared like getMessages
|
|
159
|
+
import { chat } from '$server/sockets/chat'
|
|
160
|
+
import { state } from '@abide/abide/ui/state'
|
|
161
|
+
import { watch } from '@abide/abide/ui/watch'
|
|
162
|
+
import { html } from '@abide/abide/ui/html'
|
|
163
|
+
import Panel from '$ui/components/Panel.abide'
|
|
164
|
+
|
|
165
|
+
const { room = 'lobby' } = props()
|
|
166
|
+
|
|
167
|
+
let draft = state('')
|
|
168
|
+
let author = state('anon')
|
|
169
|
+
let tone = state('friendly')
|
|
170
|
+
let notify = state(true)
|
|
171
|
+
let volume = state(5, (next, previous) => (Number.isFinite(next) ? next : previous))
|
|
172
|
+
let shout = state.computed(() => draft.toUpperCase())
|
|
173
|
+
let roomDraft = state.linked(() => room)
|
|
174
|
+
|
|
175
|
+
// watch is the one reaction primitive: a socket, an rpc, or a tracked thunk.
|
|
176
|
+
watch(chat, () => getMessages.refresh({ room }))
|
|
177
|
+
watch(() => console.log(author, tone))
|
|
178
|
+
|
|
179
|
+
// a writable computed lives at the binding: bind:value={{ get, set }}
|
|
180
|
+
const get = () => draft.trim()
|
|
181
|
+
const set = (next) => (draft = next)
|
|
182
|
+
|
|
183
|
+
const focus = (element) => element.focus()
|
|
184
|
+
const panelProps = { title: 'Live feed' }
|
|
185
|
+
const draftAttrs = { placeholder: 'say something', autocomplete: 'off' }
|
|
186
|
+
|
|
187
|
+
async function send() {
|
|
188
|
+
await sendMessage({ room: roomDraft, author, text: draft })
|
|
189
|
+
draft = ''
|
|
190
|
+
}
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
{#snippet line(message)}
|
|
194
|
+
<li>{message.author}: {message.text}</li>
|
|
164
195
|
{/snippet}
|
|
165
196
|
|
|
166
|
-
<
|
|
167
|
-
<h1 class:
|
|
197
|
+
<Panel {...panelProps}>
|
|
198
|
+
<h1 class:muted={!notify} style:opacity={notify ? '1' : '0.6'}>
|
|
199
|
+
{room} — {shout}
|
|
200
|
+
</h1>
|
|
168
201
|
|
|
169
|
-
{#await
|
|
202
|
+
{#await getMessages({ room })}
|
|
170
203
|
<p>loading…</p>
|
|
171
|
-
{:then
|
|
172
|
-
{#if
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<p>no history yet</p>
|
|
204
|
+
{:then messages}
|
|
205
|
+
{#if messages.length === 0}
|
|
206
|
+
<p>No messages yet.</p>
|
|
207
|
+
{:else if messages.length < 100}
|
|
208
|
+
<ul>
|
|
209
|
+
{#for message, i of messages by message.id}
|
|
210
|
+
{line(message)}
|
|
211
|
+
{/for}
|
|
212
|
+
</ul>
|
|
181
213
|
{:else}
|
|
182
|
-
<
|
|
214
|
+
<script>
|
|
215
|
+
// branch-local state, re-seeded each time this branch mounts
|
|
216
|
+
let offset = state(0)
|
|
217
|
+
</script>
|
|
218
|
+
<p>huge room — showing from {offset}</p>
|
|
219
|
+
<button onclick={() => (offset = offset + 100)}>next</button>
|
|
220
|
+
<style>
|
|
221
|
+
p {
|
|
222
|
+
font-variant-numeric: tabular-nums;
|
|
223
|
+
}
|
|
224
|
+
</style>
|
|
183
225
|
{/if}
|
|
184
226
|
{:catch error}
|
|
185
227
|
<p>failed to load: {error.message}</p>
|
|
186
228
|
{:finally}
|
|
187
|
-
<
|
|
229
|
+
<p>checked just now</p>
|
|
188
230
|
{/await}
|
|
189
231
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
{:
|
|
232
|
+
<ol>
|
|
233
|
+
{#for await message of chat}
|
|
234
|
+
{line(message)}
|
|
235
|
+
{/for}
|
|
236
|
+
</ol>
|
|
237
|
+
|
|
238
|
+
{#switch tone}
|
|
239
|
+
{:case 'friendly'}
|
|
240
|
+
<p>{html`<em>be kind</em>`}</p>
|
|
241
|
+
{:default}
|
|
242
|
+
<p>say anything</p>
|
|
198
243
|
{/switch}
|
|
199
244
|
|
|
200
245
|
{#try}
|
|
201
|
-
{
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<pre>{label}</pre>
|
|
205
|
-
{/if}
|
|
206
|
-
{:catch error}
|
|
207
|
-
<p>render error: {error.message}</p>
|
|
208
|
-
{:finally}
|
|
209
|
-
<small>rendered</small>
|
|
246
|
+
<p>{JSON.parse(draft).summary}</p>
|
|
247
|
+
{:catch}
|
|
248
|
+
<p>draft isn't JSON yet</p>
|
|
210
249
|
{/try}
|
|
211
250
|
|
|
212
|
-
<form onsubmit={send}>
|
|
213
|
-
<input bind:value={draft}
|
|
214
|
-
<label><input type="checkbox" bind:checked={showRaw} /> raw</label>
|
|
215
|
-
<label><input type="radio" bind:group={filter} value="all" /> all</label>
|
|
216
|
-
<label><input type="radio" bind:group={filter} value="mine" /> mine</label>
|
|
251
|
+
<form onsubmit={(event) => { event.preventDefault(); send() }}>
|
|
252
|
+
<input attach={focus} bind:value={draft} {...draftAttrs} />
|
|
217
253
|
<input bind:value={{ get, set }} />
|
|
218
|
-
<
|
|
254
|
+
<label><input type="checkbox" bind:checked={notify} /> notify</label>
|
|
255
|
+
<label><input type="radio" bind:group={tone} value="friendly" /> friendly</label>
|
|
256
|
+
<label><input type="radio" bind:group={tone} value="blunt" /> blunt</label>
|
|
257
|
+
<input type="range" bind:value={volume} min="0" max="10" />
|
|
258
|
+
<select bind:value={author}>
|
|
259
|
+
<option>anon</option>
|
|
260
|
+
<option>me</option>
|
|
261
|
+
</select>
|
|
262
|
+
<button disabled={draft === ''}>send</button>
|
|
219
263
|
</form>
|
|
220
|
-
</
|
|
264
|
+
</Panel>
|
|
221
265
|
|
|
222
266
|
<style>
|
|
223
|
-
|
|
267
|
+
form {
|
|
268
|
+
display: flex;
|
|
269
|
+
gap: 0.5rem;
|
|
270
|
+
}
|
|
271
|
+
.muted {
|
|
272
|
+
color: gray;
|
|
273
|
+
}
|
|
224
274
|
</style>
|
|
225
275
|
```
|
|
226
276
|
|
|
227
|
-
Content nested inside a capitalised child component renders where the child
|
|
228
|
-
calls `{children()}` — the single slot, with `{#if children}…{:else}…{/if}` as
|
|
229
|
-
its fallback (there is no `<slot>` element and no named slots):
|
|
230
|
-
|
|
231
|
-
```html
|
|
232
|
-
<script>
|
|
233
|
-
const { text = '' } = props()
|
|
234
|
-
</script>
|
|
235
|
-
|
|
236
|
-
<article class="card rounded border p-2">
|
|
237
|
-
<p class="font-medium">{text}</p>
|
|
238
|
-
{#if children}{children()}{:else}<em>no body</em>{/if}
|
|
239
|
-
</article>
|
|
240
|
-
```
|
|
241
|
-
|
|
242
277
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abide/abide",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.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",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"./server/error": "./src/lib/server/error.ts",
|
|
47
47
|
"./server/redirect": "./src/lib/server/redirect.ts",
|
|
48
48
|
"./server/request": "./src/lib/server/request.ts",
|
|
49
|
-
"./server/reachable": "./src/lib/server/reachable.ts",
|
|
50
49
|
"./server/cookies": "./src/lib/server/cookies.ts",
|
|
51
50
|
"./server/env": "./src/lib/server/env.ts",
|
|
52
51
|
"./server/appDataDir": "./src/lib/server/appDataDir.ts",
|
|
@@ -57,10 +56,13 @@
|
|
|
57
56
|
"./server/rpc/defineRpc": "./src/lib/server/rpc/defineRpc.ts",
|
|
58
57
|
"./server/sockets/defineSocket": "./src/lib/server/sockets/defineSocket.ts",
|
|
59
58
|
"./server/prompts/definePrompt": "./src/lib/server/prompts/definePrompt.ts",
|
|
60
|
-
"./ui/
|
|
61
|
-
"./shared/cache": "./src/lib/shared/cache.ts",
|
|
59
|
+
"./ui/watch": "./src/lib/ui/watch.ts",
|
|
62
60
|
"./shared/pending": "./src/lib/shared/pending.ts",
|
|
61
|
+
"./shared/patch": "./src/lib/shared/patch.ts",
|
|
62
|
+
"./shared/peek": "./src/lib/shared/peek.ts",
|
|
63
|
+
"./shared/refresh": "./src/lib/shared/refresh.ts",
|
|
63
64
|
"./shared/refreshing": "./src/lib/shared/refreshing.ts",
|
|
65
|
+
"./shared/done": "./src/lib/shared/done.ts",
|
|
64
66
|
"./shared/HttpError": "./src/lib/shared/HttpError.ts",
|
|
65
67
|
"./shared/ValidationErrorData": "./src/lib/shared/types/ValidationErrorData.ts",
|
|
66
68
|
"./shared/snippet": "./src/lib/shared/snippet.ts",
|
|
@@ -68,16 +70,17 @@
|
|
|
68
70
|
"./shared/health": "./src/lib/shared/health.ts",
|
|
69
71
|
"./shared/log": "./src/lib/shared/log.ts",
|
|
70
72
|
"./shared/online": "./src/lib/shared/online.ts",
|
|
73
|
+
"./shared/reachable": "./src/lib/shared/reachable.ts",
|
|
71
74
|
"./shared/page": "./src/lib/shared/page.ts",
|
|
72
75
|
"./shared/trace": "./src/lib/shared/trace.ts",
|
|
73
76
|
"./shared/url": "./src/lib/shared/url.ts",
|
|
74
77
|
"./shared/createSubscriber": "./src/lib/shared/createSubscriber.ts",
|
|
75
78
|
"./ui/html": "./src/lib/ui/html.ts",
|
|
79
|
+
"./ui/state": "./src/lib/ui/state.ts",
|
|
76
80
|
"./ui/effect": "./src/lib/ui/effect.ts",
|
|
77
|
-
"./ui/
|
|
78
|
-
"./ui/
|
|
79
|
-
"./ui/
|
|
80
|
-
"./ui/exitScope": "./src/lib/ui/exitScope.ts",
|
|
81
|
+
"./ui/currentScope": "./src/lib/ui/scope.ts",
|
|
82
|
+
"./ui/enterRenderScope": "./src/lib/ui/enterScope.ts",
|
|
83
|
+
"./ui/exitRenderScope": "./src/lib/ui/exitScope.ts",
|
|
81
84
|
"./ui/outbox": "./src/lib/ui/outbox.ts",
|
|
82
85
|
"./ui/dom/mount": "./src/lib/ui/dom/mount.ts",
|
|
83
86
|
"./ui/dom/mountChild": "./src/lib/ui/dom/mountChild.ts",
|
|
@@ -100,6 +103,7 @@
|
|
|
100
103
|
"./ui/dom/attr": "./src/lib/ui/dom/attr.ts",
|
|
101
104
|
"./ui/dom/on": "./src/lib/ui/dom/on.ts",
|
|
102
105
|
"./ui/dom/attach": "./src/lib/ui/dom/attach.ts",
|
|
106
|
+
"./ui/dom/bindSelectValue": "./src/lib/ui/dom/bindSelectValue.ts",
|
|
103
107
|
"./ui/dom/each": "./src/lib/ui/dom/each.ts",
|
|
104
108
|
"./ui/dom/eachAsync": "./src/lib/ui/dom/eachAsync.ts",
|
|
105
109
|
"./ui/dom/when": "./src/lib/ui/dom/when.ts",
|