@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.
Files changed (325) hide show
  1. package/AGENTS.md +564 -437
  2. package/CHANGELOG.md +183 -0
  3. package/README.md +165 -202
  4. package/package.json +14 -5
  5. package/src/abideLsp.ts +5 -6
  6. package/src/abideResolverPlugin.ts +197 -169
  7. package/src/build.ts +79 -56
  8. package/src/buildDisconnected.ts +0 -2
  9. package/src/checkAbide.ts +12 -2
  10. package/src/devEntry.ts +113 -28
  11. package/src/discoveryEntry.ts +3 -2
  12. package/src/lib/bundle/disconnected.abide +69 -73
  13. package/src/lib/bundle/infoPlist.ts +13 -7
  14. package/src/lib/bundle/spawnEmbeddedServer.ts +13 -4
  15. package/src/lib/bundle/waitForServer.ts +6 -1
  16. package/src/lib/mcp/mcpTools.ts +15 -6
  17. package/src/lib/server/error.ts +6 -6
  18. package/src/lib/server/json.ts +17 -3
  19. package/src/lib/server/rpc/defineRpc.ts +58 -24
  20. package/src/lib/server/rpc/parseArgs.ts +98 -13
  21. package/src/lib/server/rpc/resolveRpcJsonSchema.ts +28 -0
  22. package/src/lib/server/rpc/types/RpcHelper.ts +75 -105
  23. package/src/lib/server/rpc/types/RpcRegistryEntry.ts +24 -9
  24. package/src/lib/server/rpc/validationError.ts +1 -1
  25. package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +0 -15
  26. package/src/lib/server/runtime/buildCacheSnapshot.ts +10 -9
  27. package/src/lib/server/runtime/buildInspectorSurface.ts +6 -4
  28. package/src/lib/server/runtime/buildOpenApiSpec.ts +55 -11
  29. package/src/lib/server/runtime/buildPreloadManifest.ts +12 -10
  30. package/src/lib/server/runtime/createAppAssetServer.ts +18 -15
  31. package/src/lib/server/runtime/createAppRouteResolver.ts +145 -0
  32. package/src/lib/server/runtime/createPlumbingRouter.ts +212 -0
  33. package/src/lib/server/runtime/createRouteDispatcher.ts +4 -10
  34. package/src/lib/server/runtime/createServer.ts +120 -324
  35. package/src/lib/server/runtime/createUiPageRenderer.ts +137 -26
  36. package/src/lib/server/runtime/devClientFingerprint.ts +19 -34
  37. package/src/lib/server/runtime/installAmbientScopeStore.ts +30 -9
  38. package/src/lib/server/runtime/logExposedSurfaces.ts +8 -7
  39. package/src/lib/server/runtime/pathStore.ts +15 -0
  40. package/src/lib/server/runtime/registryManifests.ts +1 -1
  41. package/src/lib/server/runtime/renderCellBarrierStore.ts +15 -0
  42. package/src/lib/server/runtime/runWithRequestScope.ts +3 -0
  43. package/src/lib/server/runtime/serializeCacheSnapshot.ts +6 -4
  44. package/src/lib/server/runtime/snapshotEntryFromCache.ts +14 -14
  45. package/src/lib/server/runtime/streamCacheResolutions.ts +14 -7
  46. package/src/lib/server/runtime/streamFromIterator.ts +30 -2
  47. package/src/lib/server/runtime/textResponse.ts +23 -0
  48. package/src/lib/server/runtime/types/DevReloadStamp.ts +6 -10
  49. package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
  50. package/src/lib/server/runtime/types/RequestStore.ts +27 -0
  51. package/src/lib/server/runtime/warnUnguardedMcp.ts +15 -5
  52. package/src/lib/server/sockets/createSocketDispatcher.ts +9 -11
  53. package/src/lib/server/sockets/defineSocket.ts +5 -4
  54. package/src/lib/server/sse.ts +5 -1
  55. package/src/lib/shared/ASYNC_CELL.ts +5 -0
  56. package/src/lib/shared/DEV_REBUILD_PATH.ts +6 -0
  57. package/src/lib/shared/HTTP_METHODS.ts +6 -0
  58. package/src/lib/shared/HttpError.ts +1 -5
  59. package/src/lib/shared/MCP_PATH.ts +6 -0
  60. package/src/lib/shared/PROXIED_SERVER_SUBDIRS.ts +15 -0
  61. package/src/lib/shared/REF_JSON_TAGS.ts +13 -1
  62. package/src/lib/shared/RPC_SHIM_GLOBALS.ts +9 -0
  63. package/src/lib/shared/activeCacheStore.ts +1 -0
  64. package/src/lib/shared/activePage.ts +1 -0
  65. package/src/lib/shared/buildArtifact.ts +4 -1
  66. package/src/lib/shared/buildSocketOverChannel.ts +4 -3
  67. package/src/lib/shared/bundleGraphFromMetafile.ts +68 -0
  68. package/src/lib/shared/cache.ts +156 -131
  69. package/src/lib/shared/changeAffectsClient.ts +12 -7
  70. package/src/lib/shared/createCacheStore.ts +31 -8
  71. package/src/lib/shared/createLifecycleChannel.ts +7 -1
  72. package/src/lib/shared/createReachable.ts +47 -78
  73. package/src/lib/shared/createRemoteFunction.ts +52 -30
  74. package/src/lib/shared/createRpcServerProgram.ts +820 -0
  75. package/src/lib/shared/decodeRefJson.ts +4 -4
  76. package/src/lib/shared/decodeResponse.ts +2 -2
  77. package/src/lib/shared/decodeWireBody.ts +35 -0
  78. package/src/lib/shared/detectRpcMethod.ts +8 -1
  79. package/src/lib/shared/done.ts +8 -2
  80. package/src/lib/shared/encodeRefJson.ts +4 -4
  81. package/src/lib/shared/encodeWireBody.ts +18 -0
  82. package/src/lib/{server/rpc → shared}/fieldErrorsFromIssues.ts +5 -1
  83. package/src/lib/shared/generateDeclarations.ts +72 -0
  84. package/src/lib/shared/hasSeedableRequest.ts +25 -0
  85. package/src/lib/shared/hydrationWindow.ts +53 -0
  86. package/src/lib/shared/isAsyncCell.ts +11 -0
  87. package/src/lib/shared/isAsyncIterable.ts +8 -0
  88. package/src/lib/shared/isSubscribable.ts +3 -3
  89. package/src/lib/shared/isThenable.ts +9 -0
  90. package/src/lib/shared/jsonSchemaForType.ts +258 -0
  91. package/src/lib/shared/lenientDecode.ts +15 -0
  92. package/src/lib/shared/loadProjectTsConfig.ts +28 -0
  93. package/src/lib/shared/markFrameworkSourcesIgnored.ts +1 -1
  94. package/src/lib/shared/matchRoute.ts +4 -14
  95. package/src/lib/shared/peek.ts +14 -0
  96. package/src/lib/shared/pending.ts +9 -6
  97. package/src/lib/shared/pendingAsyncCellsSlot.ts +13 -0
  98. package/src/lib/shared/prepareRpcModule.ts +91 -93
  99. package/src/lib/shared/prepareSocketModule.ts +3 -2
  100. package/src/lib/shared/probeRegistries.ts +5 -18
  101. package/src/lib/shared/reachable.ts +7 -10
  102. package/src/lib/shared/refresh.ts +12 -2
  103. package/src/lib/shared/refreshing.ts +8 -2
  104. package/src/lib/shared/resolvedCellsSlot.ts +13 -0
  105. package/src/lib/shared/reviveWireField.ts +49 -0
  106. package/src/lib/shared/reviveWireOutput.ts +36 -0
  107. package/src/lib/shared/rpcServerForRoot.ts +25 -0
  108. package/src/lib/shared/scanPages.ts +25 -0
  109. package/src/lib/shared/snapshotShippable.ts +8 -7
  110. package/src/lib/shared/streamedCellsSlot.ts +14 -0
  111. package/src/lib/shared/subscribableFromResponse.ts +4 -4
  112. package/src/lib/shared/subscribableProbes.ts +1 -1
  113. package/src/lib/shared/tailProbeSlot.ts +1 -1
  114. package/src/lib/shared/types/AsyncComputed.ts +20 -0
  115. package/src/lib/shared/types/AsyncState.ts +13 -0
  116. package/src/lib/shared/types/CacheEntry.ts +7 -7
  117. package/src/lib/shared/types/CacheOptions.ts +23 -37
  118. package/src/lib/shared/types/CachePolicy.ts +25 -0
  119. package/src/lib/shared/types/CacheSnapshotEntry.ts +6 -5
  120. package/src/lib/shared/types/ErrorJsonSchemas.ts +8 -0
  121. package/src/lib/shared/types/HttpMethod.ts +3 -1
  122. package/src/lib/shared/types/InputCoercion.ts +17 -0
  123. package/src/lib/shared/types/{Subscribable.ts → NamedAsyncIterable.ts} +1 -1
  124. package/src/lib/shared/types/OutputWirePlan.ts +17 -0
  125. package/src/lib/shared/types/PagesScan.ts +7 -0
  126. package/src/lib/shared/types/PendingAsyncCells.ts +10 -0
  127. package/src/lib/shared/types/RawRemoteFunction.ts +6 -0
  128. package/src/lib/shared/types/RemoteCallable.ts +8 -7
  129. package/src/lib/shared/types/RemoteFunction.ts +16 -15
  130. package/src/lib/shared/types/ResolvedCells.ts +11 -0
  131. package/src/lib/shared/types/ReturnBody.ts +15 -0
  132. package/src/lib/shared/types/RpcBuildStamps.ts +23 -0
  133. package/src/lib/shared/types/RpcErrorGuard.ts +3 -8
  134. package/src/lib/shared/types/Socket.ts +4 -4
  135. package/src/lib/shared/types/SsrPayload.ts +5 -1
  136. package/src/lib/shared/types/StreamPolicy.ts +11 -0
  137. package/src/lib/shared/types/StreamedCells.ts +19 -0
  138. package/src/lib/shared/types/StreamedResolution.ts +24 -6
  139. package/src/lib/shared/types/TailHooks.ts +1 -1
  140. package/src/lib/shared/types/WireKind.ts +11 -0
  141. package/src/lib/shared/validationHttpError.ts +33 -0
  142. package/src/lib/shared/warmSeedKey.ts +16 -0
  143. package/src/lib/shared/wireJsonReplacer.ts +30 -0
  144. package/src/lib/shared/writeRpcDts.ts +11 -1
  145. package/src/lib/shared/writeTestSocketsDts.ts +1 -1
  146. package/src/lib/test/createTestApp.ts +19 -1
  147. package/src/lib/ui/README.md +1 -1
  148. package/src/lib/ui/activePendingCells.ts +14 -0
  149. package/src/lib/ui/compile/BLOCK_KEYWORDS.ts +21 -0
  150. package/src/lib/ui/compile/SSR_ESCAPE.ts +4 -1
  151. package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +35 -8
  152. package/src/lib/ui/compile/abideUiPlugin.ts +19 -2
  153. package/src/lib/ui/compile/analyzeComponent.ts +89 -6
  154. package/src/lib/ui/compile/assignmentTargetNames.ts +54 -0
  155. package/src/lib/ui/compile/asyncInterpolationFields.ts +152 -0
  156. package/src/lib/ui/compile/asyncValuePositionError.ts +21 -0
  157. package/src/lib/ui/compile/asyncValuePositionInterpolations.ts +64 -0
  158. package/src/lib/ui/compile/attrLiftPosition.ts +18 -0
  159. package/src/lib/ui/compile/cachedSourceFile.ts +40 -0
  160. package/src/lib/ui/compile/catchBinding.ts +7 -5
  161. package/src/lib/ui/compile/classifyInterpolationType.ts +46 -0
  162. package/src/lib/ui/compile/collectAbideDiagnostics.ts +96 -0
  163. package/src/lib/ui/compile/compileComponent.ts +19 -3
  164. package/src/lib/ui/compile/compileModule.ts +27 -58
  165. package/src/lib/ui/compile/compileSSR.ts +51 -12
  166. package/src/lib/ui/compile/compileShadow.ts +145 -18
  167. package/src/lib/ui/compile/composeProps.ts +12 -2
  168. package/src/lib/ui/compile/createShadowLanguageService.ts +116 -68
  169. package/src/lib/ui/compile/createShadowProgram.ts +35 -6
  170. package/src/lib/ui/compile/declaredNames.ts +36 -0
  171. package/src/lib/ui/compile/desugarSignals.ts +418 -36
  172. package/src/lib/ui/compile/expressionIsPrefixEvaluable.ts +19 -0
  173. package/src/lib/ui/compile/generateBuild.ts +52 -9
  174. package/src/lib/ui/compile/generateSSR.ts +242 -43
  175. package/src/lib/ui/compile/hoistableAwaits.ts +193 -0
  176. package/src/lib/ui/compile/hoistableChildRenders.ts +112 -0
  177. package/src/lib/ui/compile/interpolatedTemplateLiteral.ts +3 -1
  178. package/src/lib/ui/compile/interpolationClassifierForRoot.ts +37 -0
  179. package/src/lib/ui/compile/isSpuriousAsyncReadDiagnostic.ts +174 -0
  180. package/src/lib/ui/compile/liftAsyncSubExpressions.ts +166 -0
  181. package/src/lib/ui/compile/lowerAsyncInterpolations.ts +92 -0
  182. package/src/lib/ui/compile/lowerContext.ts +10 -0
  183. package/src/lib/ui/compile/lowerDocAccess.ts +26 -23
  184. package/src/lib/ui/compile/lowerScript.ts +40 -4
  185. package/src/lib/ui/compile/nodeAtShadowOffset.ts +28 -0
  186. package/src/lib/ui/compile/parseTemplate.ts +18 -1092
  187. package/src/lib/ui/compile/parseTemplateRecovering.ts +1385 -0
  188. package/src/lib/ui/compile/referencedIdentifiers.ts +35 -0
  189. package/src/lib/ui/compile/renameSignalRefs.ts +21 -22
  190. package/src/lib/ui/compile/seedTypeClassifierForRoot.ts +65 -0
  191. package/src/lib/ui/compile/shadowInterpolationClassifier.ts +47 -0
  192. package/src/lib/ui/compile/sourceFileOptionsSignature.ts +20 -0
  193. package/src/lib/ui/compile/structuralHeadTokens.ts +107 -0
  194. package/src/lib/ui/compile/templateSemanticTokens.ts +21 -0
  195. package/src/lib/ui/compile/templateStartOffset.ts +15 -0
  196. package/src/lib/ui/compile/tryPlan.ts +4 -3
  197. package/src/lib/ui/compile/types/AnalyzedComponent.ts +4 -0
  198. package/src/lib/ui/compile/types/AsyncInterpolationField.ts +19 -0
  199. package/src/lib/ui/compile/types/InterpolationClassifier.ts +12 -0
  200. package/src/lib/ui/compile/types/InterpolationKind.ts +7 -0
  201. package/src/lib/ui/compile/types/ParseDiagnostic.ts +8 -0
  202. package/src/lib/ui/compile/types/SeedTypeClassifier.ts +15 -0
  203. package/src/lib/ui/compile/types/TemplateNode.ts +36 -4
  204. package/src/lib/ui/compile/types/ValuePositionInterpolation.ts +13 -0
  205. package/src/lib/ui/compile/writtenTemplateNames.ts +84 -0
  206. package/src/lib/ui/computed.ts +28 -1
  207. package/src/lib/ui/createScope.ts +35 -68
  208. package/src/lib/ui/dom/anchoredBranch.ts +142 -0
  209. package/src/lib/ui/dom/appendText.ts +8 -3
  210. package/src/lib/ui/dom/awaitBlock.ts +43 -94
  211. package/src/lib/ui/dom/bindProp.ts +22 -0
  212. package/src/lib/ui/dom/bindableProp.ts +47 -0
  213. package/src/lib/ui/dom/cellPending.ts +24 -0
  214. package/src/lib/ui/dom/disposeRange.ts +2 -1
  215. package/src/lib/ui/dom/each.ts +26 -4
  216. package/src/lib/ui/dom/eachAsync.ts +39 -3
  217. package/src/lib/ui/dom/fillBoundary.ts +2 -3
  218. package/src/lib/ui/dom/fillRange.ts +4 -4
  219. package/src/lib/ui/dom/hydrate.ts +6 -12
  220. package/src/lib/ui/dom/isComment.ts +1 -1
  221. package/src/lib/ui/dom/matchingRangeClose.ts +29 -0
  222. package/src/lib/ui/dom/mount.ts +1 -2
  223. package/src/lib/ui/dom/mountChild.ts +9 -40
  224. package/src/lib/ui/dom/mountRange.ts +2 -3
  225. package/src/lib/ui/dom/mountStreamedChild.ts +84 -0
  226. package/src/lib/ui/dom/mountSwappableRange.ts +46 -4
  227. package/src/lib/ui/dom/mutateDocContainer.ts +65 -0
  228. package/src/lib/ui/dom/on.ts +2 -2
  229. package/src/lib/ui/dom/readCell.ts +40 -0
  230. package/src/lib/ui/dom/switchBlock.ts +30 -7
  231. package/src/lib/ui/dom/tryBlock.ts +230 -66
  232. package/src/lib/ui/dom/types/SwitchCase.ts +5 -1
  233. package/src/lib/ui/dom/when.ts +12 -2
  234. package/src/lib/ui/dom/withScope.ts +2 -2
  235. package/src/lib/ui/finalizeStreamedChildren.ts +89 -0
  236. package/src/lib/ui/flight.ts +56 -0
  237. package/src/lib/ui/html.ts +12 -1
  238. package/src/lib/ui/isolateCellBarrier.ts +17 -0
  239. package/src/lib/ui/linked.ts +48 -2
  240. package/src/lib/ui/remoteProxy.ts +84 -159
  241. package/src/lib/ui/renderChain.ts +49 -13
  242. package/src/lib/ui/renderToStream.ts +22 -18
  243. package/src/lib/ui/resumeSeedScript.ts +1 -1
  244. package/src/lib/ui/router.ts +63 -36
  245. package/src/lib/ui/runtime/AsyncCellError.ts +20 -0
  246. package/src/lib/ui/runtime/CELL_SEED.ts +14 -0
  247. package/src/lib/ui/runtime/CURRENT_BOUNDARY.ts +11 -0
  248. package/src/lib/ui/runtime/CURRENT_PATH.ts +29 -0
  249. package/src/lib/ui/runtime/RENDER.ts +10 -7
  250. package/src/lib/ui/runtime/RESUME.ts +4 -4
  251. package/src/lib/ui/runtime/STREAMED_CELLS.ts +57 -0
  252. package/src/lib/ui/runtime/ambientPathBacking.ts +32 -0
  253. package/src/lib/ui/runtime/applyPatchToTree.ts +1 -1
  254. package/src/lib/ui/runtime/blockId.ts +31 -0
  255. package/src/lib/ui/runtime/boundaryFor.ts +11 -0
  256. package/src/lib/ui/runtime/cellBarrierBacking.ts +30 -0
  257. package/src/lib/ui/runtime/createAsyncCell.ts +300 -0
  258. package/src/lib/ui/runtime/createDoc.ts +3 -42
  259. package/src/lib/ui/runtime/createEffectNode.ts +9 -0
  260. package/src/lib/ui/runtime/enterRenderPass.ts +5 -4
  261. package/src/lib/ui/runtime/flushEffects.ts +16 -6
  262. package/src/lib/ui/runtime/isAsyncFunction.ts +14 -0
  263. package/src/lib/ui/runtime/nextBlockId.ts +8 -7
  264. package/src/lib/ui/runtime/renderPath.ts +16 -0
  265. package/src/lib/ui/runtime/types/Boundary.ts +9 -0
  266. package/src/lib/ui/runtime/types/RenderContext.ts +9 -7
  267. package/src/lib/ui/runtime/types/SsrRender.ts +9 -2
  268. package/src/lib/ui/runtime/types/UiComponent.ts +1 -5
  269. package/src/lib/ui/runtime/withOptionalPath.ts +8 -0
  270. package/src/lib/ui/runtime/withPath.ts +16 -0
  271. package/src/lib/ui/runtime/withPathFrom.ts +20 -0
  272. package/src/lib/ui/seedStreamedResolution.ts +31 -6
  273. package/src/lib/ui/settleAsyncCells.ts +24 -0
  274. package/src/lib/ui/socketProxy.ts +1 -1
  275. package/src/lib/ui/startClient.ts +16 -31
  276. package/src/lib/ui/trackedComputed.ts +68 -0
  277. package/src/lib/ui/types/Scope.ts +8 -24
  278. package/src/lib/ui/watch.ts +3 -3
  279. package/src/serverEntry.ts +14 -0
  280. package/template/src/server/rpc/getHello.ts +15 -13
  281. package/template/test/app.test.ts +1 -1
  282. package/src/lib/server/runtime/devHotModuleResponse.ts +0 -41
  283. package/src/lib/shared/DEV_HOT_PREFIX.ts +0 -7
  284. package/src/lib/shared/UNREACHABLE_STATUSES.ts +0 -13
  285. package/src/lib/shared/hasReplayableRequest.ts +0 -17
  286. package/src/lib/shared/hydratingSlot.ts +0 -12
  287. package/src/lib/shared/outboxProbeSlot.ts +0 -20
  288. package/src/lib/shared/types/Outbox.ts +0 -9
  289. package/src/lib/shared/types/OutboxEntry.ts +0 -27
  290. package/src/lib/shared/types/SmartReadOptions.ts +0 -36
  291. package/src/lib/shared/wakeHydrationPeeks.ts +0 -20
  292. package/src/lib/ui/COMPONENT_WRAPPER_PREFIX.ts +0 -5
  293. package/src/lib/ui/compile/REACTIVE_CALLEES.ts +0 -11
  294. package/src/lib/ui/compile/assertRuntimeHelpersBound.ts +0 -80
  295. package/src/lib/ui/compile/markupTokens.ts +0 -313
  296. package/src/lib/ui/compile/structuralBlockTokens.ts +0 -100
  297. package/src/lib/ui/dom/applyResolved.ts +0 -87
  298. package/src/lib/ui/dom/mutateDocArray.ts +0 -38
  299. package/src/lib/ui/dom/scopeLabel.ts +0 -21
  300. package/src/lib/ui/dom/text.ts +0 -20
  301. package/src/lib/ui/history.ts +0 -108
  302. package/src/lib/ui/installHotBridge.ts +0 -95
  303. package/src/lib/ui/installInspectorBridge.ts +0 -140
  304. package/src/lib/ui/outbox.ts +0 -35
  305. package/src/lib/ui/persist.ts +0 -115
  306. package/src/lib/ui/rpcOutbox/createOutboxQueue.ts +0 -281
  307. package/src/lib/ui/rpcOutbox/outboxRegistry.ts +0 -69
  308. package/src/lib/ui/runtime/PATCH_BUS.ts +0 -28
  309. package/src/lib/ui/runtime/captureModelDoc.ts +0 -43
  310. package/src/lib/ui/runtime/hotInstances.ts +0 -10
  311. package/src/lib/ui/runtime/hotReloadEnabled.ts +0 -8
  312. package/src/lib/ui/runtime/hotReplace.ts +0 -38
  313. package/src/lib/ui/runtime/liveScopes.ts +0 -15
  314. package/src/lib/ui/runtime/localStoragePersistence.ts +0 -47
  315. package/src/lib/ui/runtime/registerHotInstance.ts +0 -23
  316. package/src/lib/ui/runtime/seedModelDoc.ts +0 -26
  317. package/src/lib/ui/runtime/types/HotInstance.ts +0 -22
  318. package/src/lib/ui/runtime/types/PatchEvent.ts +0 -16
  319. package/src/lib/ui/seedResolved.ts +0 -28
  320. package/src/lib/ui/sync.ts +0 -48
  321. package/src/lib/ui/types/History.ts +0 -14
  322. package/src/lib/ui/types/PersistHandle.ts +0 -11
  323. package/src/lib/ui/types/PersistenceStore.ts +0 -12
  324. package/src/lib/ui/types/ResolvedFrame.ts +0 -15
  325. 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: 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.**
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 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.
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). One runtime (Bun ≥ 1.3).
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
- bunx abide scaffold my-app # scaffolds, installs, and starts the dev server
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 run the kitchen-sink example, which demos the full surface:
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 && bun install
26
- cd examples/kitchen-sink && bun run dev
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 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.
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 { listMessages } from '$server/store'
35
+ import { load } from '$server/db.ts'
43
36
 
44
37
  export const getMessages = GET(
45
- async ({ room, limit }) => json(await listMessages(room, limit)),
38
+ (args) => json(load(args.channel, args.limit)),
46
39
  {
47
- inputSchema: z.object({
48
- room: z.string(),
49
- limit: z.coerce.number().default(50),
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
- That one file fans out:
50
+ One declaration, five surfaces:
56
51
 
57
52
  ```text
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
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 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 stringsuse `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.
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/` — 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`.
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(), 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)
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.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`.
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
- 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.
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
- import { props } from '@abide/abide/ui/props'
140
- import type { Snippet } from '@abide/abide/shared/snippet'
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
- const { title, children } = props<{ title: string; children?: Snippet }>()
143
- </script>
116
+ const { title = 'Chat', ...rest } = props()
144
117
 
145
- <section>
146
- <h2>{title}</h2>
147
- {#if children}{children()}{:else}<p>Nothing here yet.</p>{/if}
148
- </section>
118
+ let channel = state('general')
119
+ let draft = state('')
120
+ let pinned = state(false)
121
+ let limit = state(20)
149
122
 
150
- <style>
151
- section {
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
- And one page tying together the RPC from above, the socket, and the whole
158
- template grammar:
126
+ const badge = html`<sup class="ml-1 text-xs text-emerald-600">live</sup>`
159
127
 
160
- ```html
161
- <script>
162
- import { getMessages } from '$server/rpc/getMessages'
163
- import { sendMessage } from '$server/rpc/sendMessage' // POST, declared like getMessages
164
- import { chat } from '$server/sockets/chat'
165
- import { state } from '@abide/abide/ui/state'
166
- import { watch } from '@abide/abide/ui/watch'
167
- import { html } from '@abide/abide/ui/html'
168
- import { props } from '@abide/abide/ui/props'
169
- import Panel from '$ui/components/Panel.abide'
170
-
171
- const { room = 'lobby' } = props<{ room?: string }>()
172
-
173
- let draft = state('')
174
- let author = state('anon')
175
- let tone = state('friendly')
176
- let notify = state(true)
177
- let volume = state(5, (next, previous) => (Number.isFinite(next) ? next : previous))
178
- let shout = state.computed(() => draft.toUpperCase())
179
- let roomDraft = state.linked(() => room)
180
-
181
- // watch is the one reaction primitive: a socket, an rpc, or a tracked thunk.
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
- {#snippet line(message)}
200
- <li>{message.author}: {message.text}</li>
201
- {/snippet}
152
+ <section {...rest} class:pinned={pinned.value} style:opacity={pinned.value ? '1' : '0.85'}>
153
+ <h1>{title} {badge}</h1>
202
154
 
203
- <Panel {...panelProps}>
204
- <h1 class:muted={!notify} style:opacity={notify ? '1' : '0.6'}>
205
- {room} {shout}
206
- </h1>
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
- {#await getMessages({ room })}
209
- <p>loading…</p>
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
- {#if messages.length === 0}
212
- <p>No messages yet.</p>
213
- {:else if messages.length < 100}
214
- <ul>
215
- {#for message, i of messages by message.id}
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
- <p>checked just now</p>
194
+ <hr />
236
195
  {/await}
237
196
 
238
- <ol>
239
- {#for await message of chat}
240
- {line(message)}
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 tone}
245
- {:case 'friendly'}
246
- <p>{html`<em>be&nbsp;kind</em>`}</p>
201
+ {#switch channel.value}
202
+ {:case 'general'}
203
+ <span>General channel</span>
204
+ {:case 'random'}
205
+ <span>Random channel</span>
247
206
  {:default}
248
- <p>say anything</p>
207
+ <span>Unknown channel</span>
249
208
  {/switch}
250
209
 
251
210
  {#try}
252
- <p>{JSON.parse(draft).summary}</p>
211
+ <MessageCard name="system">
212
+ <p>System notice</p>
213
+ </MessageCard>
253
214
  {:catch}
254
- <p>draft isn't JSON yet</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
- form {
274
- display: flex;
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.49.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/mutateDocArray": "./src/lib/ui/dom/mutateDocArray.ts",
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 { structuralBlockTokens } from './lib/ui/compile/structuralBlockTokens.ts'
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 merged with the shadow's type-aware expression
29
- tokens, encoded to the LSP wire format. The markup tokens make the LSP own the
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
- ...markupTokens(text),
42
- ...structuralBlockTokens(text),
41
+ ...templateSemanticTokens(text),
43
42
  ...service.semanticClassifications(abidePath),
44
43
  ]
45
44
  return encodeSemanticTokens(text, tokens)