@abide/abide 0.49.0 → 0.50.1
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 +564 -437
- package/CHANGELOG.md +183 -0
- package/README.md +165 -202
- package/package.json +14 -5
- package/src/abideLsp.ts +5 -6
- package/src/abideResolverPlugin.ts +197 -169
- package/src/build.ts +79 -56
- package/src/buildDisconnected.ts +0 -2
- package/src/checkAbide.ts +12 -2
- package/src/devEntry.ts +113 -28
- package/src/discoveryEntry.ts +3 -2
- package/src/lib/bundle/disconnected.abide +69 -73
- package/src/lib/bundle/infoPlist.ts +13 -7
- package/src/lib/bundle/spawnEmbeddedServer.ts +13 -4
- package/src/lib/bundle/waitForServer.ts +6 -1
- package/src/lib/mcp/mcpTools.ts +15 -6
- package/src/lib/server/error.ts +6 -6
- package/src/lib/server/json.ts +17 -3
- package/src/lib/server/rpc/defineRpc.ts +58 -24
- package/src/lib/server/rpc/parseArgs.ts +98 -13
- package/src/lib/server/rpc/resolveRpcJsonSchema.ts +28 -0
- package/src/lib/server/rpc/types/RpcHelper.ts +75 -105
- package/src/lib/server/rpc/types/RpcRegistryEntry.ts +24 -9
- package/src/lib/server/rpc/validationError.ts +1 -1
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +0 -15
- package/src/lib/server/runtime/buildCacheSnapshot.ts +10 -9
- package/src/lib/server/runtime/buildInspectorSurface.ts +6 -4
- package/src/lib/server/runtime/buildOpenApiSpec.ts +55 -11
- package/src/lib/server/runtime/buildPreloadManifest.ts +12 -10
- package/src/lib/server/runtime/createAppAssetServer.ts +18 -15
- package/src/lib/server/runtime/createAppRouteResolver.ts +145 -0
- package/src/lib/server/runtime/createPlumbingRouter.ts +212 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +4 -10
- package/src/lib/server/runtime/createServer.ts +120 -324
- package/src/lib/server/runtime/createUiPageRenderer.ts +137 -26
- package/src/lib/server/runtime/devClientFingerprint.ts +19 -34
- package/src/lib/server/runtime/installAmbientScopeStore.ts +30 -9
- package/src/lib/server/runtime/logExposedSurfaces.ts +8 -7
- package/src/lib/server/runtime/pathStore.ts +15 -0
- package/src/lib/server/runtime/registryManifests.ts +1 -1
- package/src/lib/server/runtime/renderCellBarrierStore.ts +15 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +3 -0
- package/src/lib/server/runtime/serializeCacheSnapshot.ts +6 -4
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +14 -14
- package/src/lib/server/runtime/streamCacheResolutions.ts +14 -7
- package/src/lib/server/runtime/streamFromIterator.ts +30 -2
- package/src/lib/server/runtime/textResponse.ts +23 -0
- package/src/lib/server/runtime/types/DevReloadStamp.ts +6 -10
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
- package/src/lib/server/runtime/types/RequestStore.ts +27 -0
- package/src/lib/server/runtime/warnUnguardedMcp.ts +15 -5
- package/src/lib/server/sockets/createSocketDispatcher.ts +9 -11
- package/src/lib/server/sockets/defineSocket.ts +5 -4
- package/src/lib/server/sse.ts +5 -1
- package/src/lib/shared/ASYNC_CELL.ts +5 -0
- package/src/lib/shared/DEV_REBUILD_PATH.ts +6 -0
- package/src/lib/shared/HTTP_METHODS.ts +6 -0
- package/src/lib/shared/HttpError.ts +1 -5
- package/src/lib/shared/MCP_PATH.ts +6 -0
- package/src/lib/shared/PROXIED_SERVER_SUBDIRS.ts +15 -0
- package/src/lib/shared/REF_JSON_TAGS.ts +13 -1
- package/src/lib/shared/RPC_SHIM_GLOBALS.ts +9 -0
- package/src/lib/shared/activeCacheStore.ts +1 -0
- package/src/lib/shared/activePage.ts +1 -0
- package/src/lib/shared/buildArtifact.ts +4 -1
- package/src/lib/shared/buildSocketOverChannel.ts +4 -3
- package/src/lib/shared/bundleGraphFromMetafile.ts +68 -0
- package/src/lib/shared/cache.ts +156 -131
- package/src/lib/shared/changeAffectsClient.ts +12 -7
- package/src/lib/shared/createCacheStore.ts +31 -8
- package/src/lib/shared/createLifecycleChannel.ts +7 -1
- package/src/lib/shared/createReachable.ts +47 -78
- package/src/lib/shared/createRemoteFunction.ts +52 -30
- package/src/lib/shared/createRpcServerProgram.ts +820 -0
- package/src/lib/shared/decodeRefJson.ts +4 -4
- package/src/lib/shared/decodeResponse.ts +2 -2
- package/src/lib/shared/decodeWireBody.ts +35 -0
- package/src/lib/shared/detectRpcMethod.ts +8 -1
- package/src/lib/shared/done.ts +8 -2
- package/src/lib/shared/encodeRefJson.ts +4 -4
- package/src/lib/shared/encodeWireBody.ts +18 -0
- package/src/lib/{server/rpc → shared}/fieldErrorsFromIssues.ts +5 -1
- package/src/lib/shared/generateDeclarations.ts +72 -0
- package/src/lib/shared/hasSeedableRequest.ts +25 -0
- package/src/lib/shared/hydrationWindow.ts +53 -0
- package/src/lib/shared/isAsyncCell.ts +11 -0
- package/src/lib/shared/isAsyncIterable.ts +8 -0
- package/src/lib/shared/isSubscribable.ts +3 -3
- package/src/lib/shared/isThenable.ts +9 -0
- package/src/lib/shared/jsonSchemaForType.ts +258 -0
- package/src/lib/shared/lenientDecode.ts +15 -0
- package/src/lib/shared/loadProjectTsConfig.ts +28 -0
- package/src/lib/shared/markFrameworkSourcesIgnored.ts +1 -1
- package/src/lib/shared/matchRoute.ts +4 -14
- package/src/lib/shared/peek.ts +14 -0
- package/src/lib/shared/pending.ts +9 -6
- package/src/lib/shared/pendingAsyncCellsSlot.ts +13 -0
- package/src/lib/shared/prepareRpcModule.ts +91 -93
- package/src/lib/shared/prepareSocketModule.ts +3 -2
- package/src/lib/shared/probeRegistries.ts +5 -18
- package/src/lib/shared/reachable.ts +7 -10
- package/src/lib/shared/refresh.ts +12 -2
- package/src/lib/shared/refreshing.ts +8 -2
- package/src/lib/shared/resolvedCellsSlot.ts +13 -0
- package/src/lib/shared/reviveWireField.ts +49 -0
- package/src/lib/shared/reviveWireOutput.ts +36 -0
- package/src/lib/shared/rpcServerForRoot.ts +25 -0
- package/src/lib/shared/scanPages.ts +25 -0
- package/src/lib/shared/snapshotShippable.ts +8 -7
- package/src/lib/shared/streamedCellsSlot.ts +14 -0
- package/src/lib/shared/subscribableFromResponse.ts +4 -4
- package/src/lib/shared/subscribableProbes.ts +1 -1
- package/src/lib/shared/tailProbeSlot.ts +1 -1
- package/src/lib/shared/types/AsyncComputed.ts +20 -0
- package/src/lib/shared/types/AsyncState.ts +13 -0
- package/src/lib/shared/types/CacheEntry.ts +7 -7
- package/src/lib/shared/types/CacheOptions.ts +23 -37
- package/src/lib/shared/types/CachePolicy.ts +25 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +6 -5
- package/src/lib/shared/types/ErrorJsonSchemas.ts +8 -0
- package/src/lib/shared/types/HttpMethod.ts +3 -1
- package/src/lib/shared/types/InputCoercion.ts +17 -0
- package/src/lib/shared/types/{Subscribable.ts → NamedAsyncIterable.ts} +1 -1
- package/src/lib/shared/types/OutputWirePlan.ts +17 -0
- package/src/lib/shared/types/PagesScan.ts +7 -0
- package/src/lib/shared/types/PendingAsyncCells.ts +10 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +6 -0
- package/src/lib/shared/types/RemoteCallable.ts +8 -7
- package/src/lib/shared/types/RemoteFunction.ts +16 -15
- package/src/lib/shared/types/ResolvedCells.ts +11 -0
- package/src/lib/shared/types/ReturnBody.ts +15 -0
- package/src/lib/shared/types/RpcBuildStamps.ts +23 -0
- package/src/lib/shared/types/RpcErrorGuard.ts +3 -8
- package/src/lib/shared/types/Socket.ts +4 -4
- package/src/lib/shared/types/SsrPayload.ts +5 -1
- package/src/lib/shared/types/StreamPolicy.ts +11 -0
- package/src/lib/shared/types/StreamedCells.ts +19 -0
- package/src/lib/shared/types/StreamedResolution.ts +24 -6
- package/src/lib/shared/types/TailHooks.ts +1 -1
- package/src/lib/shared/types/WireKind.ts +11 -0
- package/src/lib/shared/validationHttpError.ts +33 -0
- package/src/lib/shared/warmSeedKey.ts +16 -0
- package/src/lib/shared/wireJsonReplacer.ts +30 -0
- package/src/lib/shared/writeRpcDts.ts +11 -1
- package/src/lib/shared/writeTestSocketsDts.ts +1 -1
- package/src/lib/test/createTestApp.ts +19 -1
- package/src/lib/ui/README.md +1 -1
- package/src/lib/ui/activePendingCells.ts +14 -0
- package/src/lib/ui/compile/BLOCK_KEYWORDS.ts +21 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +4 -1
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +35 -8
- package/src/lib/ui/compile/abideUiPlugin.ts +19 -2
- package/src/lib/ui/compile/analyzeComponent.ts +89 -6
- package/src/lib/ui/compile/assignmentTargetNames.ts +54 -0
- package/src/lib/ui/compile/asyncInterpolationFields.ts +152 -0
- package/src/lib/ui/compile/asyncValuePositionError.ts +21 -0
- package/src/lib/ui/compile/asyncValuePositionInterpolations.ts +64 -0
- package/src/lib/ui/compile/attrLiftPosition.ts +18 -0
- package/src/lib/ui/compile/cachedSourceFile.ts +40 -0
- package/src/lib/ui/compile/catchBinding.ts +7 -5
- package/src/lib/ui/compile/classifyInterpolationType.ts +46 -0
- package/src/lib/ui/compile/collectAbideDiagnostics.ts +96 -0
- package/src/lib/ui/compile/compileComponent.ts +19 -3
- package/src/lib/ui/compile/compileModule.ts +27 -58
- package/src/lib/ui/compile/compileSSR.ts +51 -12
- package/src/lib/ui/compile/compileShadow.ts +145 -18
- package/src/lib/ui/compile/composeProps.ts +12 -2
- package/src/lib/ui/compile/createShadowLanguageService.ts +116 -68
- package/src/lib/ui/compile/createShadowProgram.ts +35 -6
- package/src/lib/ui/compile/declaredNames.ts +36 -0
- package/src/lib/ui/compile/desugarSignals.ts +418 -36
- package/src/lib/ui/compile/expressionIsPrefixEvaluable.ts +19 -0
- package/src/lib/ui/compile/generateBuild.ts +52 -9
- package/src/lib/ui/compile/generateSSR.ts +242 -43
- package/src/lib/ui/compile/hoistableAwaits.ts +193 -0
- package/src/lib/ui/compile/hoistableChildRenders.ts +112 -0
- package/src/lib/ui/compile/interpolatedTemplateLiteral.ts +3 -1
- package/src/lib/ui/compile/interpolationClassifierForRoot.ts +37 -0
- package/src/lib/ui/compile/isSpuriousAsyncReadDiagnostic.ts +174 -0
- package/src/lib/ui/compile/liftAsyncSubExpressions.ts +166 -0
- package/src/lib/ui/compile/lowerAsyncInterpolations.ts +92 -0
- package/src/lib/ui/compile/lowerContext.ts +10 -0
- package/src/lib/ui/compile/lowerDocAccess.ts +26 -23
- package/src/lib/ui/compile/lowerScript.ts +40 -4
- package/src/lib/ui/compile/nodeAtShadowOffset.ts +28 -0
- package/src/lib/ui/compile/parseTemplate.ts +18 -1092
- package/src/lib/ui/compile/parseTemplateRecovering.ts +1385 -0
- package/src/lib/ui/compile/referencedIdentifiers.ts +35 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +21 -22
- package/src/lib/ui/compile/seedTypeClassifierForRoot.ts +65 -0
- package/src/lib/ui/compile/shadowInterpolationClassifier.ts +47 -0
- package/src/lib/ui/compile/sourceFileOptionsSignature.ts +20 -0
- package/src/lib/ui/compile/structuralHeadTokens.ts +107 -0
- package/src/lib/ui/compile/templateSemanticTokens.ts +21 -0
- package/src/lib/ui/compile/templateStartOffset.ts +15 -0
- package/src/lib/ui/compile/tryPlan.ts +4 -3
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +4 -0
- package/src/lib/ui/compile/types/AsyncInterpolationField.ts +19 -0
- package/src/lib/ui/compile/types/InterpolationClassifier.ts +12 -0
- package/src/lib/ui/compile/types/InterpolationKind.ts +7 -0
- package/src/lib/ui/compile/types/ParseDiagnostic.ts +8 -0
- package/src/lib/ui/compile/types/SeedTypeClassifier.ts +15 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +36 -4
- package/src/lib/ui/compile/types/ValuePositionInterpolation.ts +13 -0
- package/src/lib/ui/compile/writtenTemplateNames.ts +84 -0
- package/src/lib/ui/computed.ts +28 -1
- package/src/lib/ui/createScope.ts +35 -68
- package/src/lib/ui/dom/anchoredBranch.ts +142 -0
- package/src/lib/ui/dom/appendText.ts +8 -3
- package/src/lib/ui/dom/awaitBlock.ts +43 -94
- package/src/lib/ui/dom/bindProp.ts +22 -0
- package/src/lib/ui/dom/bindableProp.ts +47 -0
- package/src/lib/ui/dom/cellPending.ts +24 -0
- package/src/lib/ui/dom/disposeRange.ts +2 -1
- package/src/lib/ui/dom/each.ts +26 -4
- package/src/lib/ui/dom/eachAsync.ts +39 -3
- package/src/lib/ui/dom/fillBoundary.ts +2 -3
- package/src/lib/ui/dom/fillRange.ts +4 -4
- package/src/lib/ui/dom/hydrate.ts +6 -12
- package/src/lib/ui/dom/isComment.ts +1 -1
- package/src/lib/ui/dom/matchingRangeClose.ts +29 -0
- package/src/lib/ui/dom/mount.ts +1 -2
- package/src/lib/ui/dom/mountChild.ts +9 -40
- package/src/lib/ui/dom/mountRange.ts +2 -3
- package/src/lib/ui/dom/mountStreamedChild.ts +84 -0
- package/src/lib/ui/dom/mountSwappableRange.ts +46 -4
- package/src/lib/ui/dom/mutateDocContainer.ts +65 -0
- package/src/lib/ui/dom/on.ts +2 -2
- package/src/lib/ui/dom/readCell.ts +40 -0
- package/src/lib/ui/dom/switchBlock.ts +30 -7
- package/src/lib/ui/dom/tryBlock.ts +230 -66
- package/src/lib/ui/dom/types/SwitchCase.ts +5 -1
- package/src/lib/ui/dom/when.ts +12 -2
- package/src/lib/ui/dom/withScope.ts +2 -2
- package/src/lib/ui/finalizeStreamedChildren.ts +89 -0
- package/src/lib/ui/flight.ts +56 -0
- package/src/lib/ui/html.ts +12 -1
- package/src/lib/ui/isolateCellBarrier.ts +17 -0
- package/src/lib/ui/linked.ts +48 -2
- package/src/lib/ui/remoteProxy.ts +84 -159
- package/src/lib/ui/renderChain.ts +49 -13
- package/src/lib/ui/renderToStream.ts +22 -18
- package/src/lib/ui/resumeSeedScript.ts +1 -1
- package/src/lib/ui/router.ts +63 -36
- package/src/lib/ui/runtime/AsyncCellError.ts +20 -0
- package/src/lib/ui/runtime/CELL_SEED.ts +14 -0
- package/src/lib/ui/runtime/CURRENT_BOUNDARY.ts +11 -0
- package/src/lib/ui/runtime/CURRENT_PATH.ts +29 -0
- package/src/lib/ui/runtime/RENDER.ts +10 -7
- package/src/lib/ui/runtime/RESUME.ts +4 -4
- package/src/lib/ui/runtime/STREAMED_CELLS.ts +57 -0
- package/src/lib/ui/runtime/ambientPathBacking.ts +32 -0
- package/src/lib/ui/runtime/applyPatchToTree.ts +1 -1
- package/src/lib/ui/runtime/blockId.ts +31 -0
- package/src/lib/ui/runtime/boundaryFor.ts +11 -0
- package/src/lib/ui/runtime/cellBarrierBacking.ts +30 -0
- package/src/lib/ui/runtime/createAsyncCell.ts +300 -0
- package/src/lib/ui/runtime/createDoc.ts +3 -42
- package/src/lib/ui/runtime/createEffectNode.ts +9 -0
- package/src/lib/ui/runtime/enterRenderPass.ts +5 -4
- package/src/lib/ui/runtime/flushEffects.ts +16 -6
- package/src/lib/ui/runtime/isAsyncFunction.ts +14 -0
- package/src/lib/ui/runtime/nextBlockId.ts +8 -7
- package/src/lib/ui/runtime/renderPath.ts +16 -0
- package/src/lib/ui/runtime/types/Boundary.ts +9 -0
- package/src/lib/ui/runtime/types/RenderContext.ts +9 -7
- package/src/lib/ui/runtime/types/SsrRender.ts +9 -2
- package/src/lib/ui/runtime/types/UiComponent.ts +1 -5
- package/src/lib/ui/runtime/withOptionalPath.ts +8 -0
- package/src/lib/ui/runtime/withPath.ts +16 -0
- package/src/lib/ui/runtime/withPathFrom.ts +20 -0
- package/src/lib/ui/seedStreamedResolution.ts +31 -6
- package/src/lib/ui/settleAsyncCells.ts +24 -0
- package/src/lib/ui/socketProxy.ts +1 -1
- package/src/lib/ui/startClient.ts +16 -31
- package/src/lib/ui/trackedComputed.ts +68 -0
- package/src/lib/ui/types/Scope.ts +8 -24
- package/src/lib/ui/watch.ts +3 -3
- package/src/serverEntry.ts +14 -0
- package/template/src/server/rpc/getHello.ts +15 -13
- package/template/test/app.test.ts +1 -1
- package/src/lib/server/runtime/devHotModuleResponse.ts +0 -41
- package/src/lib/shared/DEV_HOT_PREFIX.ts +0 -7
- package/src/lib/shared/UNREACHABLE_STATUSES.ts +0 -13
- package/src/lib/shared/hasReplayableRequest.ts +0 -17
- package/src/lib/shared/hydratingSlot.ts +0 -12
- package/src/lib/shared/outboxProbeSlot.ts +0 -20
- package/src/lib/shared/types/Outbox.ts +0 -9
- package/src/lib/shared/types/OutboxEntry.ts +0 -27
- package/src/lib/shared/types/SmartReadOptions.ts +0 -36
- package/src/lib/shared/wakeHydrationPeeks.ts +0 -20
- package/src/lib/ui/COMPONENT_WRAPPER_PREFIX.ts +0 -5
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +0 -11
- package/src/lib/ui/compile/assertRuntimeHelpersBound.ts +0 -80
- package/src/lib/ui/compile/markupTokens.ts +0 -313
- package/src/lib/ui/compile/structuralBlockTokens.ts +0 -100
- package/src/lib/ui/dom/applyResolved.ts +0 -87
- package/src/lib/ui/dom/mutateDocArray.ts +0 -38
- package/src/lib/ui/dom/scopeLabel.ts +0 -21
- package/src/lib/ui/dom/text.ts +0 -20
- package/src/lib/ui/history.ts +0 -108
- package/src/lib/ui/installHotBridge.ts +0 -95
- package/src/lib/ui/installInspectorBridge.ts +0 -140
- package/src/lib/ui/outbox.ts +0 -35
- package/src/lib/ui/persist.ts +0 -115
- package/src/lib/ui/rpcOutbox/createOutboxQueue.ts +0 -281
- package/src/lib/ui/rpcOutbox/outboxRegistry.ts +0 -69
- package/src/lib/ui/runtime/PATCH_BUS.ts +0 -28
- package/src/lib/ui/runtime/captureModelDoc.ts +0 -43
- package/src/lib/ui/runtime/hotInstances.ts +0 -10
- package/src/lib/ui/runtime/hotReloadEnabled.ts +0 -8
- package/src/lib/ui/runtime/hotReplace.ts +0 -38
- package/src/lib/ui/runtime/liveScopes.ts +0 -15
- package/src/lib/ui/runtime/localStoragePersistence.ts +0 -47
- package/src/lib/ui/runtime/registerHotInstance.ts +0 -23
- package/src/lib/ui/runtime/seedModelDoc.ts +0 -26
- package/src/lib/ui/runtime/types/HotInstance.ts +0 -22
- package/src/lib/ui/runtime/types/PatchEvent.ts +0 -16
- package/src/lib/ui/seedResolved.ts +0 -28
- package/src/lib/ui/sync.ts +0 -48
- package/src/lib/ui/types/History.ts +0 -14
- package/src/lib/ui/types/PersistHandle.ts +0 -11
- package/src/lib/ui/types/PersistenceStore.ts +0 -12
- package/src/lib/ui/types/ResolvedFrame.ts +0 -15
- package/src/lib/ui/types/SyncTransport.ts +0 -13
package/README.md
CHANGED
|
@@ -1,101 +1,89 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
-
**One typed declaration, every surface:
|
|
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.**
|
|
3
|
+
**One typed declaration, every surface: SSR, browser fetch, MCP, CLI, and OpenAPI from a single Bun runtime.**
|
|
6
4
|
|
|
7
|
-
abide is an isomorphic
|
|
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.
|
|
5
|
+
abide is an isomorphic HTTP framework where a typed RPC you declare once fans out to an in-process SSR call, a browser fetch, an MCP tool, a CLI subcommand, and an OpenAPI operation — the bundler swaps the runtime per side, so the same callable behaves the same in-process on the server and over `fetch` in the browser. It is built for humans and machines: the same schema that types your code projects the tool, the flag, and the spec.
|
|
12
6
|
|
|
13
|
-
- One direct dependency (TypeScript)
|
|
7
|
+
- One direct dependency (TypeScript), one runtime (Bun ≥ 1.3.0).
|
|
8
|
+
- No barrels — every public name is its own module path (`@abide/abide/server/GET`, `@abide/abide/ui/state`, …). The namespace marks the side: `server/*` runs server-side, `ui/*` client-side, `shared/*` isomorphic.
|
|
14
9
|
|
|
15
10
|
## Quick start
|
|
16
11
|
|
|
17
12
|
```sh
|
|
18
|
-
|
|
13
|
+
# Scaffold a project from the bundled template, install it, and start dev.
|
|
14
|
+
bunx abide scaffold my-app
|
|
19
15
|
```
|
|
20
16
|
|
|
21
|
-
Or
|
|
17
|
+
Or clone the kitchen-sink example, which exercises the whole surface:
|
|
22
18
|
|
|
23
19
|
```sh
|
|
24
20
|
git clone https://github.com/briancray/abide
|
|
25
|
-
cd abide
|
|
26
|
-
|
|
21
|
+
cd abide/examples/kitchen-sink
|
|
22
|
+
bun install
|
|
23
|
+
bun run dev
|
|
27
24
|
```
|
|
28
25
|
|
|
29
26
|
## RPCs
|
|
30
27
|
|
|
31
|
-
An RPC is one
|
|
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.
|
|
28
|
+
An RPC is one export per file under `src/server/rpc/`. The file path is the URL; the declared method helper (`GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`HEAD`) picks the verb. Attach a `schemas.input` (any Standard Schema — zod, valibot, or arktype, unadapted) and the same schema validates the args and projects the MCP tool, the CLI flags, and the OpenAPI operation.
|
|
36
29
|
|
|
37
30
|
```ts
|
|
38
31
|
// src/server/rpc/getMessages.ts
|
|
39
32
|
import { GET } from '@abide/abide/server/GET'
|
|
40
33
|
import { json } from '@abide/abide/server/json'
|
|
41
34
|
import { z } from 'zod'
|
|
42
|
-
import {
|
|
35
|
+
import { load } from '$server/db.ts'
|
|
43
36
|
|
|
44
37
|
export const getMessages = GET(
|
|
45
|
-
|
|
38
|
+
(args) => json(load(args.channel, args.limit)),
|
|
46
39
|
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
schemas: {
|
|
41
|
+
input: z.object({
|
|
42
|
+
channel: z.string().default('general'),
|
|
43
|
+
limit: z.number().max(100).default(20),
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
51
46
|
},
|
|
52
47
|
)
|
|
53
48
|
```
|
|
54
49
|
|
|
55
|
-
|
|
50
|
+
One declaration, five surfaces:
|
|
56
51
|
|
|
57
52
|
```text
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
└─ OpenAPI operation in /openapi.json
|
|
53
|
+
export const getMessages = GET(fn, { schemas })
|
|
54
|
+
│
|
|
55
|
+
┌───────────┬──────────────┼──────────────┬─────────────┐
|
|
56
|
+
▼ ▼ ▼ ▼ ▼
|
|
57
|
+
SSR call browser fetch MCP tool CLI subcmd OpenAPI op
|
|
58
|
+
(bare, (same call, (read-only abide-cli /openapi.json
|
|
59
|
+
in-proc) swap to fetch) from schema) getMessages
|
|
66
60
|
```
|
|
67
61
|
|
|
68
|
-
A schema
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
> Query args
|
|
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.
|
|
62
|
+
A schema unlocks the CLI on any RPC, and MCP for read-only methods (`GET`/`HEAD`). A mutating method never auto-exposes to MCP — it opts in explicitly:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// src/server/rpc/sendMessage.ts
|
|
66
|
+
import { POST } from '@abide/abide/server/POST'
|
|
67
|
+
import { json } from '@abide/abide/server/json'
|
|
68
|
+
import { z } from 'zod'
|
|
69
|
+
import { append } from '$server/db.ts'
|
|
70
|
+
|
|
71
|
+
export const sendMessage = POST(
|
|
72
|
+
(args) => json(append(args.channel, args.body)),
|
|
73
|
+
{
|
|
74
|
+
schemas: { input: z.object({ channel: z.string(), body: z.string() }) },
|
|
75
|
+
clients: { mcp: true }, // a mutating RPC must opt into MCP by hand
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Consume forms are isomorphic. The **bare call `fn(args)` is the smart read** — cached, coalesced, reactive, resolved in-process during SSR and over `fetch` in the browser (there is no `cache()` wrapper; the bare call carries the caching). Alongside it: `fn.raw(args, init?)` for the raw `Response`, and the mutators/probes `fn.refresh()`, `fn.patch(...)`, `fn.peek()`, `fn.pending()`, `fn.refreshing()`, and `fn.error()`. A streaming handler (`jsonl`/`sse`) makes the bare call return a `Subscribable` you iterate.
|
|
81
|
+
|
|
82
|
+
> Query and path args auto-coerce from the endpoint's typed shape — a numeric field arrives as a number, no `z.coerce` needed. The per-RPC `timeout` (a 504 on every surface) is distinct from the client-wide `ABIDE_CLIENT_TIMEOUT`.
|
|
92
83
|
|
|
93
84
|
## Sockets
|
|
94
85
|
|
|
95
|
-
A socket is one broadcast topic per file under `src/server/sockets
|
|
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`.
|
|
86
|
+
A socket is one broadcast topic per file under `src/server/sockets/`. A `Socket<T>` is an isomorphic `AsyncIterable<T>` — the same value you `for await` on both sides — and every socket multiplexes onto one WebSocket at `/__abide/sockets`.
|
|
99
87
|
|
|
100
88
|
```ts
|
|
101
89
|
// src/server/sockets/chat.ts
|
|
@@ -103,181 +91,156 @@ import { socket } from '@abide/abide/server/socket'
|
|
|
103
91
|
import { z } from 'zod'
|
|
104
92
|
|
|
105
93
|
export const chat = socket({
|
|
106
|
-
schema: z.object({ author: z.string(),
|
|
107
|
-
tail:
|
|
108
|
-
ttl: 60_000, // retained frames
|
|
109
|
-
clientPublish: true, // allow browser publishes (off by default)
|
|
94
|
+
schema: z.object({ author: z.string(), body: z.string() }),
|
|
95
|
+
tail: 20, // retain the last 20 frames for late joiners and reconnects
|
|
96
|
+
ttl: 60_000, // evict retained frames older than 60s
|
|
110
97
|
})
|
|
111
98
|
```
|
|
112
99
|
|
|
113
|
-
`chat.
|
|
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`.
|
|
100
|
+
Publish with `chat.publish(frame)`; seed a late reader with `chat.tail(count)`. Each socket also has an HTTP face at `/__abide/sockets/<name>`: `GET` returns the retained tail, and `POST` publishes when `clientPublish` is set.
|
|
122
101
|
|
|
123
102
|
## Components
|
|
124
103
|
|
|
125
|
-
|
|
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.
|
|
132
|
-
|
|
133
|
-
Nested content becomes the component's `children` prop — an ordinary declared
|
|
134
|
-
prop of type `Snippet` — and renders wherever the component calls
|
|
135
|
-
`{children()}`:
|
|
104
|
+
A `.abide` component is HTML with a leading `<script>`. The example below is one page that imports the RPC and socket above and exercises the whole template grammar. Reactive primitives are imported by their own module paths and called bare: `state(0)` is a writable cell (read/write via `.value`), `state.computed(fn)` is read-only derived, `state.linked(fn)` is writable and reseeded from a thunk. `watch(source, handler)` is the single reaction primitive — over a cell, a socket, or an RPC. `props()` is the ambient prop reader (no import).
|
|
136
105
|
|
|
137
106
|
```html
|
|
138
107
|
<script>
|
|
139
|
-
|
|
140
|
-
|
|
108
|
+
import { getMessages } from '$server/rpc/getMessages.ts'
|
|
109
|
+
import { sendMessage } from '$server/rpc/sendMessage.ts'
|
|
110
|
+
import { chat } from '$server/sockets/chat.ts'
|
|
111
|
+
import MessageCard from '$ui/components/MessageCard.abide'
|
|
112
|
+
import { state } from '@abide/abide/ui/state'
|
|
113
|
+
import { watch } from '@abide/abide/ui/watch'
|
|
114
|
+
import { html } from '@abide/abide/ui/html'
|
|
141
115
|
|
|
142
|
-
|
|
143
|
-
</script>
|
|
116
|
+
const { title = 'Chat', ...rest } = props()
|
|
144
117
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
118
|
+
let channel = state('general')
|
|
119
|
+
let draft = state('')
|
|
120
|
+
let pinned = state(false)
|
|
121
|
+
let limit = state(20)
|
|
149
122
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
border: 1px solid gray;
|
|
153
|
-
}
|
|
154
|
-
</style>
|
|
155
|
-
```
|
|
123
|
+
let trimmed = state.computed(() => draft.value.trim())
|
|
124
|
+
let live = state.linked(() => limit.value)
|
|
156
125
|
|
|
157
|
-
|
|
158
|
-
template grammar:
|
|
126
|
+
const badge = html`<sup class="ml-1 text-xs text-emerald-600">live</sup>`
|
|
159
127
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
watch(chat, () => getMessages.refresh({ room }))
|
|
183
|
-
watch(() => console.log(author, tone))
|
|
184
|
-
|
|
185
|
-
// a writable computed lives at the binding: bind:value={{ get, set }}
|
|
186
|
-
const get = () => draft.trim()
|
|
187
|
-
const set = (next) => (draft = next)
|
|
188
|
-
|
|
189
|
-
const focus = (element) => element.focus()
|
|
190
|
-
const panelProps = { title: 'Live feed' }
|
|
191
|
-
const draftAttrs = { placeholder: 'say something', autocomplete: 'off' }
|
|
192
|
-
|
|
193
|
-
async function send() {
|
|
194
|
-
await sendMessage({ room: roomDraft, author, text: draft })
|
|
195
|
-
draft = ''
|
|
196
|
-
}
|
|
128
|
+
watch(trimmed, (value) => console.log('draft is now', value))
|
|
129
|
+
watch(chat, (frame) => {
|
|
130
|
+
live.value = live.value + 1
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
async function submit(event) {
|
|
134
|
+
event.preventDefault()
|
|
135
|
+
if (trimmed.value === '') return
|
|
136
|
+
await sendMessage({ channel: channel.value, body: trimmed.value })
|
|
137
|
+
draft.value = ''
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function autofocus(node) {
|
|
141
|
+
node.focus()
|
|
142
|
+
return () => {}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const rowProps = { class: 'flex gap-2' }
|
|
146
|
+
|
|
147
|
+
// Derived two-way binding: read a string, coerce writes back into the numeric cell.
|
|
148
|
+
const get = () => String(limit.value)
|
|
149
|
+
const set = (next) => (limit.value = Number(next))
|
|
197
150
|
</script>
|
|
198
151
|
|
|
199
|
-
{
|
|
200
|
-
<
|
|
201
|
-
{/snippet}
|
|
152
|
+
<section {...rest} class:pinned={pinned.value} style:opacity={pinned.value ? '1' : '0.85'}>
|
|
153
|
+
<h1>{title} {badge}</h1>
|
|
202
154
|
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
{
|
|
206
|
-
|
|
155
|
+
<form onsubmit={submit}>
|
|
156
|
+
<input bind:value={draft} attach={autofocus} placeholder="Say something" />
|
|
157
|
+
<label><input type="checkbox" bind:checked={pinned} /> pin</label>
|
|
158
|
+
<label><input type="radio" bind:group={channel} value="general" /> general</label>
|
|
159
|
+
<label><input type="radio" bind:group={channel} value="random" /> random</label>
|
|
160
|
+
<input bind:value={{ get, set }} />
|
|
161
|
+
<button type="submit">Send</button>
|
|
162
|
+
</form>
|
|
207
163
|
|
|
208
|
-
{#
|
|
209
|
-
<
|
|
164
|
+
{#snippet row(message, index)}
|
|
165
|
+
<MessageCard {...rowProps} name={message.author} onclick={() => console.log(index)}>
|
|
166
|
+
<p>{message.body}</p>
|
|
167
|
+
</MessageCard>
|
|
168
|
+
{/snippet}
|
|
169
|
+
|
|
170
|
+
{#if live.value > 100}
|
|
171
|
+
<p>Busy channel</p>
|
|
172
|
+
{:else if live.value > 0}
|
|
173
|
+
<p>{live.value} updates</p>
|
|
174
|
+
{:else}
|
|
175
|
+
<script>
|
|
176
|
+
let seenAt = state(Date.now())
|
|
177
|
+
let ageLabel = state.computed(() => `waiting since ${seenAt.value}`)
|
|
178
|
+
</script>
|
|
179
|
+
<style>
|
|
180
|
+
p { color: gray; }
|
|
181
|
+
</style>
|
|
182
|
+
<p>{ageLabel.value}</p>
|
|
183
|
+
{/if}
|
|
184
|
+
|
|
185
|
+
{#await getMessages({ limit: limit.value })}
|
|
186
|
+
<p>Loading…</p>
|
|
210
187
|
{:then messages}
|
|
211
|
-
{#
|
|
212
|
-
|
|
213
|
-
{
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
{line(message)}
|
|
217
|
-
{/for}
|
|
218
|
-
</ul>
|
|
219
|
-
{:else}
|
|
220
|
-
<script>
|
|
221
|
-
// branch-local state, re-seeded each time this branch mounts
|
|
222
|
-
let offset = state(0)
|
|
223
|
-
</script>
|
|
224
|
-
<p>huge room — showing from {offset}</p>
|
|
225
|
-
<button onclick={() => (offset = offset + 100)}>next</button>
|
|
226
|
-
<style>
|
|
227
|
-
p {
|
|
228
|
-
font-variant-numeric: tabular-nums;
|
|
229
|
-
}
|
|
230
|
-
</style>
|
|
231
|
-
{/if}
|
|
232
|
-
{:catch error}
|
|
233
|
-
<p>failed to load: {error.message}</p>
|
|
188
|
+
{#for message, i of messages by message.id}
|
|
189
|
+
{row(message, i)}
|
|
190
|
+
{/for}
|
|
191
|
+
{:catch problem}
|
|
192
|
+
<p>Failed: {problem.message}</p>
|
|
234
193
|
{:finally}
|
|
235
|
-
<
|
|
194
|
+
<hr />
|
|
236
195
|
{/await}
|
|
237
196
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
{/for}
|
|
242
|
-
</ol>
|
|
197
|
+
{#for await frame of chat}
|
|
198
|
+
<p class="text-sm opacity-70">{frame.author}: {frame.body}</p>
|
|
199
|
+
{/for}
|
|
243
200
|
|
|
244
|
-
{#switch
|
|
245
|
-
{:case '
|
|
246
|
-
<
|
|
201
|
+
{#switch channel.value}
|
|
202
|
+
{:case 'general'}
|
|
203
|
+
<span>General channel</span>
|
|
204
|
+
{:case 'random'}
|
|
205
|
+
<span>Random channel</span>
|
|
247
206
|
{:default}
|
|
248
|
-
<
|
|
207
|
+
<span>Unknown channel</span>
|
|
249
208
|
{/switch}
|
|
250
209
|
|
|
251
210
|
{#try}
|
|
252
|
-
<
|
|
211
|
+
<MessageCard name="system">
|
|
212
|
+
<p>System notice</p>
|
|
213
|
+
</MessageCard>
|
|
253
214
|
{:catch}
|
|
254
|
-
<p>
|
|
215
|
+
<p>Card crashed</p>
|
|
216
|
+
{:finally}
|
|
217
|
+
<span class="sr-only">done</span>
|
|
255
218
|
{/try}
|
|
256
|
-
|
|
257
|
-
<form onsubmit={(event) => { event.preventDefault(); send() }}>
|
|
258
|
-
<input attach={focus} bind:value={draft} {...draftAttrs} />
|
|
259
|
-
<input bind:value={{ get, set }} />
|
|
260
|
-
<label><input type="checkbox" bind:checked={notify} /> notify</label>
|
|
261
|
-
<label><input type="radio" bind:group={tone} value="friendly" /> friendly</label>
|
|
262
|
-
<label><input type="radio" bind:group={tone} value="blunt" /> blunt</label>
|
|
263
|
-
<input type="range" bind:value={volume} min="0" max="10" />
|
|
264
|
-
<select bind:value={author}>
|
|
265
|
-
<option>anon</option>
|
|
266
|
-
<option>me</option>
|
|
267
|
-
</select>
|
|
268
|
-
<button disabled={draft === ''}>send</button>
|
|
269
|
-
</form>
|
|
270
|
-
</Panel>
|
|
219
|
+
</section>
|
|
271
220
|
|
|
272
221
|
<style>
|
|
273
|
-
|
|
274
|
-
display:
|
|
222
|
+
section {
|
|
223
|
+
display: grid;
|
|
275
224
|
gap: 0.5rem;
|
|
276
225
|
}
|
|
277
|
-
.muted {
|
|
278
|
-
color: gray;
|
|
279
|
-
}
|
|
280
226
|
</style>
|
|
281
227
|
```
|
|
282
228
|
|
|
229
|
+
The capitalised `MessageCard` renders its passed content where it calls `{children()}`. The `<slot>` element was removed — `{children()}` is the single fill point, and `{#if children}{children()}{:else}…{/if}` is the fallback form.
|
|
230
|
+
|
|
231
|
+
```html
|
|
232
|
+
<script>
|
|
233
|
+
const { name, ...rest } = props()
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<article {...rest}>
|
|
237
|
+
<strong>{name}</strong>
|
|
238
|
+
{#if children}
|
|
239
|
+
{children()}
|
|
240
|
+
{:else}
|
|
241
|
+
<em>No content</em>
|
|
242
|
+
{/if}
|
|
243
|
+
</article>
|
|
244
|
+
```
|
|
245
|
+
|
|
283
246
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abide/abide",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.1",
|
|
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",
|
|
@@ -82,17 +82,26 @@
|
|
|
82
82
|
"./ui/currentScope": "./src/lib/ui/scope.ts",
|
|
83
83
|
"./ui/enterRenderScope": "./src/lib/ui/enterScope.ts",
|
|
84
84
|
"./ui/exitRenderScope": "./src/lib/ui/exitScope.ts",
|
|
85
|
-
"./ui/outbox": "./src/lib/ui/outbox.ts",
|
|
86
85
|
"./ui/dom/mount": "./src/lib/ui/dom/mount.ts",
|
|
87
86
|
"./ui/dom/mountChild": "./src/lib/ui/dom/mountChild.ts",
|
|
87
|
+
"./ui/dom/mountStreamedChild": "./src/lib/ui/dom/mountStreamedChild.ts",
|
|
88
88
|
"./ui/dom/mergeProps": "./src/lib/ui/dom/mergeProps.ts",
|
|
89
89
|
"./ui/dom/spreadProps": "./src/lib/ui/dom/spreadProps.ts",
|
|
90
90
|
"./ui/dom/restProps": "./src/lib/ui/dom/restProps.ts",
|
|
91
|
+
"./ui/dom/bindProp": "./src/lib/ui/dom/bindProp.ts",
|
|
92
|
+
"./ui/dom/bindableProp": "./src/lib/ui/dom/bindableProp.ts",
|
|
91
93
|
"./ui/dom/spreadAttrs": "./src/lib/ui/dom/spreadAttrs.ts",
|
|
92
94
|
"./ui/dom/readCall": "./src/lib/ui/dom/readCall.ts",
|
|
93
|
-
"./ui/dom/
|
|
95
|
+
"./ui/dom/readCell": "./src/lib/ui/dom/readCell.ts",
|
|
96
|
+
"./ui/dom/cellPending": "./src/lib/ui/dom/cellPending.ts",
|
|
97
|
+
"./ui/runtime/withPath": "./src/lib/ui/runtime/withPath.ts",
|
|
98
|
+
"./ui/settleAsyncCells": "./src/lib/ui/settleAsyncCells.ts",
|
|
99
|
+
"./ui/flight": "./src/lib/ui/flight.ts",
|
|
100
|
+
"./ui/isolateCellBarrier": "./src/lib/ui/isolateCellBarrier.ts",
|
|
101
|
+
"./ui/finalizeStreamedChildren": "./src/lib/ui/finalizeStreamedChildren.ts",
|
|
102
|
+
"./ui/runtime/renderPath": "./src/lib/ui/runtime/renderPath.ts",
|
|
103
|
+
"./ui/dom/mutateDocContainer": "./src/lib/ui/dom/mutateDocContainer.ts",
|
|
94
104
|
"./ui/dom/hydrate": "./src/lib/ui/dom/hydrate.ts",
|
|
95
|
-
"./ui/dom/text": "./src/lib/ui/dom/text.ts",
|
|
96
105
|
"./ui/dom/appendText": "./src/lib/ui/dom/appendText.ts",
|
|
97
106
|
"./ui/dom/appendTextAt": "./src/lib/ui/dom/appendTextAt.ts",
|
|
98
107
|
"./ui/dom/appendSnippet": "./src/lib/ui/dom/appendSnippet.ts",
|
|
@@ -112,9 +121,9 @@
|
|
|
112
121
|
"./ui/dom/awaitBlock": "./src/lib/ui/dom/awaitBlock.ts",
|
|
113
122
|
"./ui/dom/tryBlock": "./src/lib/ui/dom/tryBlock.ts",
|
|
114
123
|
"./ui/dom/switchBlock": "./src/lib/ui/dom/switchBlock.ts",
|
|
115
|
-
"./ui/dom/applyResolved": "./src/lib/ui/dom/applyResolved.ts",
|
|
116
124
|
"./ui/runtime/escapeKey": "./src/lib/ui/runtime/escapeKey.ts",
|
|
117
125
|
"./ui/runtime/nextBlockId": "./src/lib/ui/runtime/nextBlockId.ts",
|
|
126
|
+
"./ui/runtime/blockId": "./src/lib/ui/runtime/blockId.ts",
|
|
118
127
|
"./ui/runtime/enterRenderPass": "./src/lib/ui/runtime/enterRenderPass.ts",
|
|
119
128
|
"./ui/runtime/exitRenderPass": "./src/lib/ui/runtime/exitRenderPass.ts",
|
|
120
129
|
"./ui/router": "./src/lib/ui/router.ts",
|
package/src/abideLsp.ts
CHANGED
|
@@ -6,10 +6,9 @@ import type {
|
|
|
6
6
|
} from './lib/ui/compile/createShadowLanguageService.ts'
|
|
7
7
|
import { createShadowLanguageService } from './lib/ui/compile/createShadowLanguageService.ts'
|
|
8
8
|
import { encodeSemanticTokens } from './lib/ui/compile/encodeSemanticTokens.ts'
|
|
9
|
-
import { markupTokens } from './lib/ui/compile/markupTokens.ts'
|
|
10
9
|
import { nearestProjectRoot } from './lib/ui/compile/nearestProjectRoot.ts'
|
|
11
10
|
import { offsetToPosition } from './lib/ui/compile/offsetToPosition.ts'
|
|
12
|
-
import {
|
|
11
|
+
import { templateSemanticTokens } from './lib/ui/compile/templateSemanticTokens.ts'
|
|
13
12
|
import type { AbideDiagnostic } from './lib/ui/compile/types/AbideDiagnostic.ts'
|
|
14
13
|
|
|
15
14
|
/*
|
|
@@ -25,8 +24,9 @@ their own project — matching `abide check` run from that package.
|
|
|
25
24
|
*/
|
|
26
25
|
/*
|
|
27
26
|
The semantic-tokens `data` array for one component: the HTML markup structure and
|
|
28
|
-
the structural `{#…}` framing
|
|
29
|
-
|
|
27
|
+
the structural `{#…}` framing — both driven by the ONE parse walk
|
|
28
|
+
(`templateSemanticTokens`) — merged with the shadow's type-aware expression tokens,
|
|
29
|
+
encoded to the LSP wire format. The markup tokens make the LSP own the
|
|
30
30
|
element/attribute coloring too, so a tree-sitter parse desynced by an `attr={expr}`
|
|
31
31
|
value can't bleed miscoloring below it. Never throws — on any internal failure it
|
|
32
32
|
yields an empty stream so the editor falls back to tree-sitter highlighting.
|
|
@@ -38,8 +38,7 @@ export function componentSemanticTokens(
|
|
|
38
38
|
): number[] {
|
|
39
39
|
try {
|
|
40
40
|
const tokens = [
|
|
41
|
-
...
|
|
42
|
-
...structuralBlockTokens(text),
|
|
41
|
+
...templateSemanticTokens(text),
|
|
43
42
|
...service.semanticClassifications(abidePath),
|
|
44
43
|
]
|
|
45
44
|
return encodeSemanticTokens(text, tokens)
|