@abide/abide 0.28.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.
Files changed (562) hide show
  1. package/CHANGELOG.md +607 -0
  2. package/LICENSE +21 -0
  3. package/README.md +154 -0
  4. package/bin/abide.ts +212 -0
  5. package/package.json +155 -0
  6. package/src/abideLsp.ts +211 -0
  7. package/src/abideModules.d.ts +8 -0
  8. package/src/abideResolverPlugin.ts +923 -0
  9. package/src/appEntry.ts +151 -0
  10. package/src/assets/app.html +12 -0
  11. package/src/build.ts +143 -0
  12. package/src/buildCli.ts +127 -0
  13. package/src/buildDisconnected.ts +118 -0
  14. package/src/bundleApp.ts +147 -0
  15. package/src/bundleDisconnectedEntry.ts +14 -0
  16. package/src/checkAbide.ts +77 -0
  17. package/src/cliEntry.ts +25 -0
  18. package/src/clientBuildPlugins.ts +33 -0
  19. package/src/clientEntry.ts +17 -0
  20. package/src/compile.ts +63 -0
  21. package/src/controlServerWorker.ts +426 -0
  22. package/src/devEntry.ts +250 -0
  23. package/src/discoveryEntry.ts +81 -0
  24. package/src/lib/bundle/BundleMenu.ts +12 -0
  25. package/src/lib/bundle/BundleMenuItem.ts +25 -0
  26. package/src/lib/bundle/BundleWindow.ts +37 -0
  27. package/src/lib/bundle/WEBVIEW_BUILD_REVISION.ts +9 -0
  28. package/src/lib/bundle/WEBVIEW_VERSION.ts +7 -0
  29. package/src/lib/bundle/bindConnectedFlag.ts +29 -0
  30. package/src/lib/bundle/bindRequestNavigate.ts +34 -0
  31. package/src/lib/bundle/buildWebviewLib.ts +111 -0
  32. package/src/lib/bundle/bundled.ts +35 -0
  33. package/src/lib/bundle/disconnected.abide +236 -0
  34. package/src/lib/bundle/disconnected.css +9 -0
  35. package/src/lib/bundle/ensureWebviewLib.ts +20 -0
  36. package/src/lib/bundle/exitWithParent.ts +28 -0
  37. package/src/lib/bundle/infoPlist.ts +46 -0
  38. package/src/lib/bundle/installDownloads.ts +24 -0
  39. package/src/lib/bundle/installMacMenu.ts +39 -0
  40. package/src/lib/bundle/listenLocalControlServer.ts +19 -0
  41. package/src/lib/bundle/native/abideMenu.mm +422 -0
  42. package/src/lib/bundle/native/webview.h +4557 -0
  43. package/src/lib/bundle/onMenu.ts +42 -0
  44. package/src/lib/bundle/openWebview.ts +104 -0
  45. package/src/lib/bundle/pngToIcns.ts +47 -0
  46. package/src/lib/bundle/probeAbideServer.ts +57 -0
  47. package/src/lib/bundle/resolveServerBinary.ts +12 -0
  48. package/src/lib/bundle/resolveWebviewLib.ts +53 -0
  49. package/src/lib/bundle/serverBinaryFilename.ts +8 -0
  50. package/src/lib/bundle/signMacApp.ts +37 -0
  51. package/src/lib/bundle/spawnEmbeddedServer.ts +64 -0
  52. package/src/lib/bundle/stableLocalPort.ts +19 -0
  53. package/src/lib/bundle/waitForServer.ts +23 -0
  54. package/src/lib/bundle/webviewCachePath.ts +23 -0
  55. package/src/lib/bundle/webviewLibName.ts +11 -0
  56. package/src/lib/cli/connectToServer.ts +23 -0
  57. package/src/lib/cli/createClient.ts +108 -0
  58. package/src/lib/cli/dispatchCommand.ts +71 -0
  59. package/src/lib/cli/loadEnvFromBinaryDir.ts +15 -0
  60. package/src/lib/cli/parseArgvForRpc.ts +100 -0
  61. package/src/lib/cli/printHelp.ts +119 -0
  62. package/src/lib/cli/printSessionHelp.ts +27 -0
  63. package/src/lib/cli/printSessionStatus.ts +21 -0
  64. package/src/lib/cli/printTrimmed.ts +8 -0
  65. package/src/lib/cli/printValue.ts +10 -0
  66. package/src/lib/cli/resolveCliTarget.ts +48 -0
  67. package/src/lib/cli/runCli.ts +176 -0
  68. package/src/lib/cli/runSession.ts +108 -0
  69. package/src/lib/cli/startLocalInstance.ts +14 -0
  70. package/src/lib/cli/tokenizeLine.ts +51 -0
  71. package/src/lib/cli/types/CliManifest.ts +9 -0
  72. package/src/lib/cli/types/CliManifestEntry.ts +17 -0
  73. package/src/lib/cli/types/CliTarget.ts +13 -0
  74. package/src/lib/mcp/annotationsForMethod.ts +29 -0
  75. package/src/lib/mcp/createMcpResourceServer.ts +102 -0
  76. package/src/lib/mcp/createMcpServer.ts +48 -0
  77. package/src/lib/mcp/dispatchMcpRequest.ts +138 -0
  78. package/src/lib/mcp/mcpResourceServerSlot.ts +18 -0
  79. package/src/lib/mcp/mcpSurface.ts +295 -0
  80. package/src/lib/mcp/toolResultFromResponse.ts +66 -0
  81. package/src/lib/mcp/types/JsonRpcRequest.ts +12 -0
  82. package/src/lib/mcp/types/JsonRpcResponse.ts +20 -0
  83. package/src/lib/mcp/types/McpResourceContents.ts +10 -0
  84. package/src/lib/mcp/types/McpResourceDescriptor.ts +6 -0
  85. package/src/lib/mcp/types/McpResourceServer.ts +12 -0
  86. package/src/lib/mcp/types/McpServer.ts +9 -0
  87. package/src/lib/mcp/types/McpServerOptions.ts +16 -0
  88. package/src/lib/server/AppModule.ts +47 -0
  89. package/src/lib/server/DELETE.ts +10 -0
  90. package/src/lib/server/GET.ts +10 -0
  91. package/src/lib/server/HEAD.ts +10 -0
  92. package/src/lib/server/PATCH.ts +10 -0
  93. package/src/lib/server/POST.ts +10 -0
  94. package/src/lib/server/PUT.ts +10 -0
  95. package/src/lib/server/agent.ts +86 -0
  96. package/src/lib/server/appDataDir.ts +16 -0
  97. package/src/lib/server/cli/buildEnvContent.ts +19 -0
  98. package/src/lib/server/cli/createTarGz.ts +77 -0
  99. package/src/lib/server/cli/handleCliDownload.ts +150 -0
  100. package/src/lib/server/cli/handleCliInstall.ts +37 -0
  101. package/src/lib/server/cli/installScript.ts +31 -0
  102. package/src/lib/server/cli/maxSourceMtime.ts +26 -0
  103. package/src/lib/server/cookies.ts +30 -0
  104. package/src/lib/server/env.ts +51 -0
  105. package/src/lib/server/error.ts +73 -0
  106. package/src/lib/server/json.ts +42 -0
  107. package/src/lib/server/jsonl.ts +47 -0
  108. package/src/lib/server/prompts/definePrompt.ts +21 -0
  109. package/src/lib/server/prompts/promptRegistry.ts +9 -0
  110. package/src/lib/server/prompts/registerPrompt.ts +6 -0
  111. package/src/lib/server/prompts/renderPromptTemplate.ts +17 -0
  112. package/src/lib/server/prompts/types/Prompt.ts +13 -0
  113. package/src/lib/server/prompts/types/PromptOptions.ts +12 -0
  114. package/src/lib/server/prompts/types/PromptRegistryEntry.ts +13 -0
  115. package/src/lib/server/prompts/types/PromptRoutes.ts +10 -0
  116. package/src/lib/server/reachable.ts +45 -0
  117. package/src/lib/server/redirect.ts +43 -0
  118. package/src/lib/server/request.ts +19 -0
  119. package/src/lib/server/rpc/defineVerb.ts +210 -0
  120. package/src/lib/server/rpc/dispatchVerbInProcess.ts +46 -0
  121. package/src/lib/server/rpc/findVerbByCommandName.ts +18 -0
  122. package/src/lib/server/rpc/parseArgs.ts +127 -0
  123. package/src/lib/server/rpc/readBodyWithinLimit.ts +44 -0
  124. package/src/lib/server/rpc/registerVerb.ts +6 -0
  125. package/src/lib/server/rpc/runWithVerbTimeout.ts +49 -0
  126. package/src/lib/server/rpc/types/RemoteHandler.ts +27 -0
  127. package/src/lib/server/rpc/types/RemoteRoutes.ts +13 -0
  128. package/src/lib/server/rpc/types/TypedResponse.ts +18 -0
  129. package/src/lib/server/rpc/types/VerbHelper.ts +87 -0
  130. package/src/lib/server/rpc/types/VerbRegistryEntry.ts +35 -0
  131. package/src/lib/server/rpc/unprocessed.ts +14 -0
  132. package/src/lib/server/rpc/verbRegistry.ts +11 -0
  133. package/src/lib/server/runtime/DEFAULT_PORT.ts +6 -0
  134. package/src/lib/server/runtime/DEV_READY_MESSAGE.ts +6 -0
  135. package/src/lib/server/runtime/DEV_REBUILD_MESSAGE.ts +4 -0
  136. package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +107 -0
  137. package/src/lib/server/runtime/SSR_SWAP_SCRIPT.ts +16 -0
  138. package/src/lib/server/runtime/acceptsGzip.ts +24 -0
  139. package/src/lib/server/runtime/buildCacheSnapshot.ts +61 -0
  140. package/src/lib/server/runtime/buildHealthPayload.ts +34 -0
  141. package/src/lib/server/runtime/buildInspectorSurface.ts +37 -0
  142. package/src/lib/server/runtime/buildOpenApiSpec.ts +106 -0
  143. package/src/lib/server/runtime/cacheControlForAsset.ts +22 -0
  144. package/src/lib/server/runtime/containsTraversal.ts +37 -0
  145. package/src/lib/server/runtime/createAppAssetServer.ts +76 -0
  146. package/src/lib/server/runtime/createAssetHeaderCache.ts +31 -0
  147. package/src/lib/server/runtime/createPublicAssetServer.ts +67 -0
  148. package/src/lib/server/runtime/createReachable.ts +109 -0
  149. package/src/lib/server/runtime/createRouteDispatcher.ts +127 -0
  150. package/src/lib/server/runtime/createServer.ts +674 -0
  151. package/src/lib/server/runtime/createUiPageRenderer.ts +181 -0
  152. package/src/lib/server/runtime/crossOriginForbidden.ts +17 -0
  153. package/src/lib/server/runtime/crossOriginGate.ts +29 -0
  154. package/src/lib/server/runtime/devClientFingerprint.ts +117 -0
  155. package/src/lib/server/runtime/devHotModuleResponse.ts +40 -0
  156. package/src/lib/server/runtime/devReloadResponse.ts +41 -0
  157. package/src/lib/server/runtime/disableIdleTimeoutForStream.ts +27 -0
  158. package/src/lib/server/runtime/envSchemaStore.ts +15 -0
  159. package/src/lib/server/runtime/findOpenPort.ts +21 -0
  160. package/src/lib/server/runtime/getActiveServer.ts +6 -0
  161. package/src/lib/server/runtime/globToPathSet.ts +29 -0
  162. package/src/lib/server/runtime/gzipResponse.ts +46 -0
  163. package/src/lib/server/runtime/inProcessServer.ts +20 -0
  164. package/src/lib/server/runtime/internalErrorResponse.ts +25 -0
  165. package/src/lib/server/runtime/isCrossOriginRequest.ts +23 -0
  166. package/src/lib/server/runtime/listenOnOpenPort.ts +36 -0
  167. package/src/lib/server/runtime/logExposedSurfaces.ts +156 -0
  168. package/src/lib/server/runtime/maybeMountInspector.ts +97 -0
  169. package/src/lib/server/runtime/mimeForExtension.ts +14 -0
  170. package/src/lib/server/runtime/pageUrlFromStore.ts +15 -0
  171. package/src/lib/server/runtime/parseIdleTimeout.ts +10 -0
  172. package/src/lib/server/runtime/parsePort.ts +11 -0
  173. package/src/lib/server/runtime/registryManifests.ts +66 -0
  174. package/src/lib/server/runtime/requestContext.ts +5 -0
  175. package/src/lib/server/runtime/resolvePageSnapshot.ts +25 -0
  176. package/src/lib/server/runtime/respondWithEmbeddedAsset.ts +18 -0
  177. package/src/lib/server/runtime/runWithRequestScope.ts +150 -0
  178. package/src/lib/server/runtime/safeJsonForScript.ts +17 -0
  179. package/src/lib/server/runtime/serializeCacheSnapshot.ts +45 -0
  180. package/src/lib/server/runtime/serverSlot.ts +13 -0
  181. package/src/lib/server/runtime/setActiveServer.ts +6 -0
  182. package/src/lib/server/runtime/snapshotEntryFromCache.ts +83 -0
  183. package/src/lib/server/runtime/streamCacheResolutions.ts +37 -0
  184. package/src/lib/server/runtime/streamFromIterator.ts +86 -0
  185. package/src/lib/server/runtime/types/Assets.ts +6 -0
  186. package/src/lib/server/runtime/types/DevReloadStamp.ts +18 -0
  187. package/src/lib/server/runtime/types/InspectorCacheEntry.ts +24 -0
  188. package/src/lib/server/runtime/types/InspectorCacheSnapshot.ts +11 -0
  189. package/src/lib/server/runtime/types/InspectorContext.ts +30 -0
  190. package/src/lib/server/runtime/types/InspectorSocket.ts +17 -0
  191. package/src/lib/server/runtime/types/InspectorSurface.ts +13 -0
  192. package/src/lib/server/runtime/types/InspectorVerb.ts +27 -0
  193. package/src/lib/server/runtime/types/RequestStore.ts +55 -0
  194. package/src/lib/server/runtime/warnUnguardedMcp.ts +32 -0
  195. package/src/lib/server/runtime/withResponseDefaults.ts +24 -0
  196. package/src/lib/server/server.ts +33 -0
  197. package/src/lib/server/socket.ts +32 -0
  198. package/src/lib/server/sockets/createSocketDispatcher.ts +337 -0
  199. package/src/lib/server/sockets/defineSocket.ts +179 -0
  200. package/src/lib/server/sockets/lookupSocket.ts +6 -0
  201. package/src/lib/server/sockets/registerSocket.ts +6 -0
  202. package/src/lib/server/sockets/socketOperations.ts +36 -0
  203. package/src/lib/server/sockets/socketRegistry.ts +9 -0
  204. package/src/lib/server/sockets/types/Socket.ts +23 -0
  205. package/src/lib/server/sockets/types/SocketClientFrame.ts +19 -0
  206. package/src/lib/server/sockets/types/SocketOperation.ts +22 -0
  207. package/src/lib/server/sockets/types/SocketOptions.ts +26 -0
  208. package/src/lib/server/sockets/types/SocketRegistryEntry.ts +19 -0
  209. package/src/lib/server/sockets/types/SocketRoutes.ts +10 -0
  210. package/src/lib/server/sockets/types/SocketServerFrame.ts +24 -0
  211. package/src/lib/server/sse.ts +54 -0
  212. package/src/lib/shared/ABIDE_PACKAGE_NAME.ts +7 -0
  213. package/src/lib/shared/ABIDE_VERSION.ts +9 -0
  214. package/src/lib/shared/CACHE_CONTROL_VALUES.ts +16 -0
  215. package/src/lib/shared/CACHE_WRAPPED.ts +8 -0
  216. package/src/lib/shared/CLI_PATH.ts +7 -0
  217. package/src/lib/shared/DEV_HOT_PREFIX.ts +7 -0
  218. package/src/lib/shared/DEV_RELOAD_PATH.ts +6 -0
  219. package/src/lib/shared/HEALTH_PATH.ts +7 -0
  220. package/src/lib/shared/HttpError.ts +20 -0
  221. package/src/lib/shared/IDENTITY_PATH.ts +6 -0
  222. package/src/lib/shared/INSPECTOR_PATH.ts +7 -0
  223. package/src/lib/shared/NAV_HEADER.ts +8 -0
  224. package/src/lib/shared/OFFLINE_HEADER.ts +8 -0
  225. package/src/lib/shared/REMOTE_FUNCTION.ts +8 -0
  226. package/src/lib/shared/REPLAYABLE_METHODS.ts +12 -0
  227. package/src/lib/shared/SOCKETS_PATH.ts +7 -0
  228. package/src/lib/shared/STREAMING_CONTENT_TYPES.ts +11 -0
  229. package/src/lib/shared/SocketDisconnectedError.ts +13 -0
  230. package/src/lib/shared/TEXT_PLAIN.ts +7 -0
  231. package/src/lib/shared/abideImportName.ts +44 -0
  232. package/src/lib/shared/abideLog.ts +38 -0
  233. package/src/lib/shared/activeCacheStore.ts +20 -0
  234. package/src/lib/shared/activePage.ts +25 -0
  235. package/src/lib/shared/appDataDir.ts +34 -0
  236. package/src/lib/shared/appNameSlot.ts +10 -0
  237. package/src/lib/shared/basePath.ts +10 -0
  238. package/src/lib/shared/basePathFromAppUrl.ts +20 -0
  239. package/src/lib/shared/baseSlot.ts +14 -0
  240. package/src/lib/shared/binaryDirEnvPath.ts +12 -0
  241. package/src/lib/shared/browserClientFlags.ts +10 -0
  242. package/src/lib/shared/buildRpcProxy.ts +39 -0
  243. package/src/lib/shared/buildRpcRequest.ts +70 -0
  244. package/src/lib/shared/buildSocketOverChannel.ts +58 -0
  245. package/src/lib/shared/bundleLayout.ts +36 -0
  246. package/src/lib/shared/cache.ts +951 -0
  247. package/src/lib/shared/cacheEntryFromSnapshot.ts +59 -0
  248. package/src/lib/shared/cacheStoreSlot.ts +16 -0
  249. package/src/lib/shared/cacheStores.ts +10 -0
  250. package/src/lib/shared/canonicalJson.ts +63 -0
  251. package/src/lib/shared/carriesBodyArgs.ts +13 -0
  252. package/src/lib/shared/clearLastConnection.ts +7 -0
  253. package/src/lib/shared/commandNameForUrl.ts +17 -0
  254. package/src/lib/shared/createCacheStore.ts +104 -0
  255. package/src/lib/shared/createChannelLog.ts +122 -0
  256. package/src/lib/shared/createLifecycleChannel.ts +56 -0
  257. package/src/lib/shared/createLivenessWatch.ts +118 -0
  258. package/src/lib/shared/createPushIterator.ts +127 -0
  259. package/src/lib/shared/createRemoteFunction.ts +122 -0
  260. package/src/lib/shared/createSubscriber.ts +55 -0
  261. package/src/lib/shared/createTraceContext.ts +21 -0
  262. package/src/lib/shared/dataDirEnvPath.ts +12 -0
  263. package/src/lib/shared/decodeResponse.ts +47 -0
  264. package/src/lib/shared/detectTarget.ts +27 -0
  265. package/src/lib/shared/detectVerbMethod.ts +17 -0
  266. package/src/lib/shared/emitLogRecord.ts +190 -0
  267. package/src/lib/shared/exeSuffix.ts +9 -0
  268. package/src/lib/shared/exitOnBuildFailure.ts +17 -0
  269. package/src/lib/shared/extraForwardHeaders.ts +16 -0
  270. package/src/lib/shared/fileStem.ts +9 -0
  271. package/src/lib/shared/findExportCallSite.ts +476 -0
  272. package/src/lib/shared/formatTraceparent.ts +6 -0
  273. package/src/lib/shared/forwardHeaders.ts +44 -0
  274. package/src/lib/shared/getRemoteMeta.ts +5 -0
  275. package/src/lib/shared/globalCacheStore.ts +15 -0
  276. package/src/lib/shared/globalCacheStoreSlot.ts +14 -0
  277. package/src/lib/shared/health.ts +179 -0
  278. package/src/lib/shared/healthReadSlot.ts +11 -0
  279. package/src/lib/shared/healthSeedSlot.ts +12 -0
  280. package/src/lib/shared/html.ts +38 -0
  281. package/src/lib/shared/importNamesToStrip.ts +13 -0
  282. package/src/lib/shared/invalidateEvent.ts +11 -0
  283. package/src/lib/shared/invalidateTripwire.ts +40 -0
  284. package/src/lib/shared/isAbideHealthPayload.ts +11 -0
  285. package/src/lib/shared/isCompileTarget.ts +15 -0
  286. package/src/lib/shared/isDebugEnabled.ts +26 -0
  287. package/src/lib/shared/isDebugNegated.ts +19 -0
  288. package/src/lib/shared/isModuleNotFound.ts +16 -0
  289. package/src/lib/shared/isReadOnlyMethod.ts +14 -0
  290. package/src/lib/shared/isReplayableMethod.ts +7 -0
  291. package/src/lib/shared/isStreamingResponse.ts +11 -0
  292. package/src/lib/shared/isSubscribable.ts +15 -0
  293. package/src/lib/shared/jsonSchemaForPromptArguments.ts +29 -0
  294. package/src/lib/shared/jsonSchemaForSchema.ts +39 -0
  295. package/src/lib/shared/jsonlErrorFrame.ts +24 -0
  296. package/src/lib/shared/keyForRemoteCall.ts +29 -0
  297. package/src/lib/shared/keyMatchesPrefix.ts +9 -0
  298. package/src/lib/shared/lastConnectionPath.ts +7 -0
  299. package/src/lib/shared/layoutChainForRoute.ts +22 -0
  300. package/src/lib/shared/loadEnvFile.ts +17 -0
  301. package/src/lib/shared/loadEnvFromDataDir.ts +14 -0
  302. package/src/lib/shared/log.ts +24 -0
  303. package/src/lib/shared/logClosingRecord.ts +28 -0
  304. package/src/lib/shared/logTapSlot.ts +13 -0
  305. package/src/lib/shared/manifestModule.ts +39 -0
  306. package/src/lib/shared/matchesDebugPattern.ts +16 -0
  307. package/src/lib/shared/memoizeByKey.ts +32 -0
  308. package/src/lib/shared/normalizeTarget.ts +10 -0
  309. package/src/lib/shared/online.ts +51 -0
  310. package/src/lib/shared/page.ts +30 -0
  311. package/src/lib/shared/pageSlot.ts +17 -0
  312. package/src/lib/shared/pageUrlForFile.ts +14 -0
  313. package/src/lib/shared/parseBoundedEnvInt.ts +20 -0
  314. package/src/lib/shared/parseDebugPatterns.ts +21 -0
  315. package/src/lib/shared/parseEnv.ts +30 -0
  316. package/src/lib/shared/parsePromptMarkdown.ts +35 -0
  317. package/src/lib/shared/parseRouteSegments.ts +22 -0
  318. package/src/lib/shared/parseTraceparent.ts +26 -0
  319. package/src/lib/shared/pending.ts +30 -0
  320. package/src/lib/shared/prepareRpcModule.ts +59 -0
  321. package/src/lib/shared/prepareSocketModule.ts +49 -0
  322. package/src/lib/shared/probeRegistries.ts +68 -0
  323. package/src/lib/shared/producerKey.ts +32 -0
  324. package/src/lib/shared/programNameForPackage.ts +14 -0
  325. package/src/lib/shared/promptNameForFile.ts +10 -0
  326. package/src/lib/shared/queryStringFromArgs.ts +27 -0
  327. package/src/lib/shared/randomHexId.ts +14 -0
  328. package/src/lib/shared/readEnvFile.ts +15 -0
  329. package/src/lib/shared/readLastConnection.ts +18 -0
  330. package/src/lib/shared/readPackageJson.ts +9 -0
  331. package/src/lib/shared/recordRemoteMeta.ts +5 -0
  332. package/src/lib/shared/refreshing.ts +31 -0
  333. package/src/lib/shared/remoteMetaStore.ts +16 -0
  334. package/src/lib/shared/requestScopeSlot.ts +15 -0
  335. package/src/lib/shared/resolveClientFlags.ts +20 -0
  336. package/src/lib/shared/responseErrorText.ts +9 -0
  337. package/src/lib/shared/rpcTimeoutSlot.ts +9 -0
  338. package/src/lib/shared/rpcUrlForFile.ts +19 -0
  339. package/src/lib/shared/runningAsStandaloneBinary.ts +13 -0
  340. package/src/lib/shared/selectorMatcher.ts +68 -0
  341. package/src/lib/shared/selectorPrefix.ts +39 -0
  342. package/src/lib/shared/serializeEnv.ts +18 -0
  343. package/src/lib/shared/setAppName.ts +5 -0
  344. package/src/lib/shared/setBaseResolver.ts +6 -0
  345. package/src/lib/shared/setCacheStoreResolver.ts +6 -0
  346. package/src/lib/shared/setGlobalCacheStoreResolver.ts +6 -0
  347. package/src/lib/shared/setPageResolver.ts +7 -0
  348. package/src/lib/shared/setRequestScopeResolver.ts +6 -0
  349. package/src/lib/shared/snippet.ts +25 -0
  350. package/src/lib/shared/socketNameForFile.ts +11 -0
  351. package/src/lib/shared/socketTapSlot.ts +12 -0
  352. package/src/lib/shared/sseErrorFrame.ts +29 -0
  353. package/src/lib/shared/streamResponse.ts +169 -0
  354. package/src/lib/shared/stripImport.ts +27 -0
  355. package/src/lib/shared/subscribableFromResponse.ts +51 -0
  356. package/src/lib/shared/tailProbeSlot.ts +16 -0
  357. package/src/lib/shared/toBunRoutePattern.ts +28 -0
  358. package/src/lib/shared/toScopeSet.ts +4 -0
  359. package/src/lib/shared/trace.ts +16 -0
  360. package/src/lib/shared/types/CacheEntry.ts +84 -0
  361. package/src/lib/shared/types/CacheInvalidation.ts +9 -0
  362. package/src/lib/shared/types/CacheOnContext.ts +25 -0
  363. package/src/lib/shared/types/CacheOptions.ts +39 -0
  364. package/src/lib/shared/types/CacheSelector.ts +17 -0
  365. package/src/lib/shared/types/CacheSnapshot.ts +16 -0
  366. package/src/lib/shared/types/CacheSnapshotEntry.ts +17 -0
  367. package/src/lib/shared/types/CacheStats.ts +13 -0
  368. package/src/lib/shared/types/CacheStore.ts +39 -0
  369. package/src/lib/shared/types/ChannelLog.ts +13 -0
  370. package/src/lib/shared/types/ClientFlags.ts +11 -0
  371. package/src/lib/shared/types/CompileTarget.ts +6 -0
  372. package/src/lib/shared/types/FrameworkLog.ts +13 -0
  373. package/src/lib/shared/types/HttpVerb.ts +1 -0
  374. package/src/lib/shared/types/LastConnection.ts +9 -0
  375. package/src/lib/shared/types/Log.ts +13 -0
  376. package/src/lib/shared/types/LogRecord.ts +42 -0
  377. package/src/lib/shared/types/LogVoice.ts +7 -0
  378. package/src/lib/shared/types/PageSnapshot.ts +14 -0
  379. package/src/lib/shared/types/PromptArgument.ts +12 -0
  380. package/src/lib/shared/types/RawRemoteFunction.ts +14 -0
  381. package/src/lib/shared/types/RemoteCallable.ts +12 -0
  382. package/src/lib/shared/types/RemoteFunction.ts +47 -0
  383. package/src/lib/shared/types/ReplayableMethod.ts +7 -0
  384. package/src/lib/shared/types/RequestScopeInfo.ts +16 -0
  385. package/src/lib/shared/types/RpcInvoker.ts +6 -0
  386. package/src/lib/shared/types/SocketChannel.ts +17 -0
  387. package/src/lib/shared/types/SocketSubCallbacks.ts +13 -0
  388. package/src/lib/shared/types/StandardSchemaV1.ts +56 -0
  389. package/src/lib/shared/types/StreamedResolution.ts +10 -0
  390. package/src/lib/shared/types/Subscribable.ts +26 -0
  391. package/src/lib/shared/types/TailHooks.ts +12 -0
  392. package/src/lib/shared/types/TailOptions.ts +10 -0
  393. package/src/lib/shared/types/TraceContext.ts +17 -0
  394. package/src/lib/shared/url.ts +118 -0
  395. package/src/lib/shared/withBase.ts +11 -0
  396. package/src/lib/shared/withBaseUrl.ts +17 -0
  397. package/src/lib/shared/withJsonSchema.ts +21 -0
  398. package/src/lib/shared/writeDts.ts +12 -0
  399. package/src/lib/shared/writeHealthDts.ts +36 -0
  400. package/src/lib/shared/writeLastConnection.ts +13 -0
  401. package/src/lib/shared/writePublicAssetsDts.ts +31 -0
  402. package/src/lib/shared/writeRoutesDts.ts +73 -0
  403. package/src/lib/shared/writeRpcDts.ts +49 -0
  404. package/src/lib/shared/writeTestRpcDts.ts +45 -0
  405. package/src/lib/shared/writeTestSocketsDts.ts +34 -0
  406. package/src/lib/test/assertAgentFrameConformance.ts +73 -0
  407. package/src/lib/test/createScriptedSurface.ts +45 -0
  408. package/src/lib/test/createTestApp.ts +203 -0
  409. package/src/lib/test/createTestSocketChannel.ts +142 -0
  410. package/src/lib/ui/README.md +86 -0
  411. package/src/lib/ui/compile/SSR_ESCAPE.ts +25 -0
  412. package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +36 -0
  413. package/src/lib/ui/compile/VOID_TAGS.ts +21 -0
  414. package/src/lib/ui/compile/abideUiPlugin.ts +65 -0
  415. package/src/lib/ui/compile/analyzeComponent.ts +117 -0
  416. package/src/lib/ui/compile/assetModulesFile.ts +32 -0
  417. package/src/lib/ui/compile/branchElements.ts +50 -0
  418. package/src/lib/ui/compile/collectAbideDiagnostics.ts +59 -0
  419. package/src/lib/ui/compile/compileComponent.ts +20 -0
  420. package/src/lib/ui/compile/compileModule.ts +116 -0
  421. package/src/lib/ui/compile/compileSSR.ts +36 -0
  422. package/src/lib/ui/compile/compileShadow.ts +352 -0
  423. package/src/lib/ui/compile/createShadowLanguageService.ts +197 -0
  424. package/src/lib/ui/compile/createShadowProgram.ts +96 -0
  425. package/src/lib/ui/compile/decodeHtmlEntities.ts +49 -0
  426. package/src/lib/ui/compile/desugarSignals.ts +133 -0
  427. package/src/lib/ui/compile/escapeHtml.ts +15 -0
  428. package/src/lib/ui/compile/generateBuild.ts +638 -0
  429. package/src/lib/ui/compile/generateSSR.ts +380 -0
  430. package/src/lib/ui/compile/groupBindParts.ts +28 -0
  431. package/src/lib/ui/compile/hoistCells.ts +120 -0
  432. package/src/lib/ui/compile/loadShadowTsConfig.ts +31 -0
  433. package/src/lib/ui/compile/lowerDocAccess.ts +202 -0
  434. package/src/lib/ui/compile/nearestProjectRoot.ts +16 -0
  435. package/src/lib/ui/compile/parseTemplate.ts +396 -0
  436. package/src/lib/ui/compile/partitionSlots.ts +36 -0
  437. package/src/lib/ui/compile/prepareNestedScript.ts +42 -0
  438. package/src/lib/ui/compile/remapShadowDiagnostic.ts +30 -0
  439. package/src/lib/ui/compile/renameSignalRefs.ts +85 -0
  440. package/src/lib/ui/compile/resolveAbideImports.ts +29 -0
  441. package/src/lib/ui/compile/scopeCss.ts +115 -0
  442. package/src/lib/ui/compile/shadowNaming.ts +11 -0
  443. package/src/lib/ui/compile/sourceToShadowOffset.ts +24 -0
  444. package/src/lib/ui/compile/staticAttrValue.ts +13 -0
  445. package/src/lib/ui/compile/stripEffects.ts +32 -0
  446. package/src/lib/ui/compile/types/AbideDiagnostic.ts +14 -0
  447. package/src/lib/ui/compile/types/AnalyzedComponent.ts +25 -0
  448. package/src/lib/ui/compile/types/CompiledShadow.ts +15 -0
  449. package/src/lib/ui/compile/types/TemplateAttr.ts +16 -0
  450. package/src/lib/ui/compile/types/TemplateNode.ts +78 -0
  451. package/src/lib/ui/compile/types/TextPart.ts +8 -0
  452. package/src/lib/ui/derived.ts +28 -0
  453. package/src/lib/ui/doc.ts +15 -0
  454. package/src/lib/ui/dom/appendSnippet.ts +34 -0
  455. package/src/lib/ui/dom/appendStatic.ts +27 -0
  456. package/src/lib/ui/dom/appendText.ts +114 -0
  457. package/src/lib/ui/dom/applyResolved.ts +72 -0
  458. package/src/lib/ui/dom/attach.ts +20 -0
  459. package/src/lib/ui/dom/attr.ts +19 -0
  460. package/src/lib/ui/dom/awaitBlock.ts +224 -0
  461. package/src/lib/ui/dom/cloneStatic.ts +52 -0
  462. package/src/lib/ui/dom/each.ts +115 -0
  463. package/src/lib/ui/dom/eachAsync.ts +153 -0
  464. package/src/lib/ui/dom/hydrate.ts +35 -0
  465. package/src/lib/ui/dom/mount.ts +29 -0
  466. package/src/lib/ui/dom/mountChild.ts +33 -0
  467. package/src/lib/ui/dom/on.ts +15 -0
  468. package/src/lib/ui/dom/openChild.ts +22 -0
  469. package/src/lib/ui/dom/openRoot.ts +20 -0
  470. package/src/lib/ui/dom/switchBlock.ts +75 -0
  471. package/src/lib/ui/dom/text.ts +20 -0
  472. package/src/lib/ui/dom/tryBlock.ts +112 -0
  473. package/src/lib/ui/dom/types/EachRow.ts +3 -0
  474. package/src/lib/ui/dom/types/SwitchCase.ts +6 -0
  475. package/src/lib/ui/dom/when.ts +73 -0
  476. package/src/lib/ui/effect.ts +16 -0
  477. package/src/lib/ui/installHotBridge.ts +73 -0
  478. package/src/lib/ui/matchRoute.ts +89 -0
  479. package/src/lib/ui/navigate.ts +17 -0
  480. package/src/lib/ui/probeNavigation.ts +33 -0
  481. package/src/lib/ui/remoteProxy.ts +97 -0
  482. package/src/lib/ui/renderChain.ts +50 -0
  483. package/src/lib/ui/renderToStream.ts +104 -0
  484. package/src/lib/ui/router.ts +286 -0
  485. package/src/lib/ui/runtime/OUTLET_TAG.ts +8 -0
  486. package/src/lib/ui/runtime/OWNER.ts +8 -0
  487. package/src/lib/ui/runtime/REACTIVE_CONTEXT.ts +14 -0
  488. package/src/lib/ui/runtime/RENDER.ts +23 -0
  489. package/src/lib/ui/runtime/RESUME.ts +16 -0
  490. package/src/lib/ui/runtime/applyPatchToTree.ts +41 -0
  491. package/src/lib/ui/runtime/claimChild.ts +10 -0
  492. package/src/lib/ui/runtime/clientPage.ts +16 -0
  493. package/src/lib/ui/runtime/createComputedNode.ts +16 -0
  494. package/src/lib/ui/runtime/createDoc.ts +177 -0
  495. package/src/lib/ui/runtime/createEffectNode.ts +58 -0
  496. package/src/lib/ui/runtime/createSignalNode.ts +16 -0
  497. package/src/lib/ui/runtime/detachLink.ts +21 -0
  498. package/src/lib/ui/runtime/endTracking.ts +24 -0
  499. package/src/lib/ui/runtime/enterRenderPass.ts +12 -0
  500. package/src/lib/ui/runtime/exitRenderPass.ts +7 -0
  501. package/src/lib/ui/runtime/firstOutlet.ts +22 -0
  502. package/src/lib/ui/runtime/flushEffects.ts +17 -0
  503. package/src/lib/ui/runtime/hotInstances.ts +10 -0
  504. package/src/lib/ui/runtime/hotReloadEnabled.ts +8 -0
  505. package/src/lib/ui/runtime/hotReplace.ts +25 -0
  506. package/src/lib/ui/runtime/nextBlockId.ts +11 -0
  507. package/src/lib/ui/runtime/pathExists.ts +23 -0
  508. package/src/lib/ui/runtime/readNode.ts +17 -0
  509. package/src/lib/ui/runtime/registerHotInstance.ts +23 -0
  510. package/src/lib/ui/runtime/runNode.ts +28 -0
  511. package/src/lib/ui/runtime/runtimePath.ts +9 -0
  512. package/src/lib/ui/runtime/scope.ts +24 -0
  513. package/src/lib/ui/runtime/toTeardown.ts +26 -0
  514. package/src/lib/ui/runtime/track.ts +58 -0
  515. package/src/lib/ui/runtime/trigger.ts +44 -0
  516. package/src/lib/ui/runtime/types/Cell.ts +5 -0
  517. package/src/lib/ui/runtime/types/Derived.ts +3 -0
  518. package/src/lib/ui/runtime/types/Doc.ts +19 -0
  519. package/src/lib/ui/runtime/types/EffectResult.ts +10 -0
  520. package/src/lib/ui/runtime/types/HotInstance.ts +14 -0
  521. package/src/lib/ui/runtime/types/NavVerdict.ts +9 -0
  522. package/src/lib/ui/runtime/types/Patch.ts +11 -0
  523. package/src/lib/ui/runtime/types/ReactiveLink.ts +21 -0
  524. package/src/lib/ui/runtime/types/ReactiveNode.ts +25 -0
  525. package/src/lib/ui/runtime/types/Route.ts +8 -0
  526. package/src/lib/ui/runtime/types/RouteLoader.ts +7 -0
  527. package/src/lib/ui/runtime/types/SsrRender.ts +22 -0
  528. package/src/lib/ui/runtime/types/State.ts +3 -0
  529. package/src/lib/ui/runtime/types/Teardown.ts +5 -0
  530. package/src/lib/ui/runtime/types/UiComponent.ts +16 -0
  531. package/src/lib/ui/runtime/types/UiProps.ts +15 -0
  532. package/src/lib/ui/runtime/unlinkDeps.ts +20 -0
  533. package/src/lib/ui/runtime/untrack.ts +20 -0
  534. package/src/lib/ui/runtime/valueAtPath.ts +18 -0
  535. package/src/lib/ui/runtime/writeNode.ts +16 -0
  536. package/src/lib/ui/socketChannel.ts +227 -0
  537. package/src/lib/ui/socketProxy.ts +25 -0
  538. package/src/lib/ui/startClient.ts +58 -0
  539. package/src/lib/ui/state.ts +25 -0
  540. package/src/lib/ui/tail.ts +324 -0
  541. package/src/lib/ui/types/Layouts.ts +9 -0
  542. package/src/lib/ui/types/Pages.ts +8 -0
  543. package/src/preload.ts +19 -0
  544. package/src/scaffold.ts +153 -0
  545. package/src/serverBuildPlugins.ts +19 -0
  546. package/src/serverEntry.ts +95 -0
  547. package/template/bunfig.toml +4 -0
  548. package/template/package.json +18 -0
  549. package/template/src/app.ts +28 -0
  550. package/template/src/bundle/icon.png +0 -0
  551. package/template/src/cli/banner.txt +3 -0
  552. package/template/src/cli/footer.txt +1 -0
  553. package/template/src/server/config.ts +17 -0
  554. package/template/src/server/rpc/getHello.ts +36 -0
  555. package/template/src/ui/Layout.abide +19 -0
  556. package/template/src/ui/app.css +21 -0
  557. package/template/src/ui/app.html +24 -0
  558. package/template/src/ui/pages/about/page.abide +9 -0
  559. package/template/src/ui/pages/page.abide +22 -0
  560. package/template/test/app.test.ts +30 -0
  561. package/template/tsconfig.json +18 -0
  562. package/tsconfig.app.json +17 -0
@@ -0,0 +1,153 @@
1
+ import { effect } from '../effect.ts'
2
+ import { claimChild } from '../runtime/claimChild.ts'
3
+ import { OWNER } from '../runtime/OWNER.ts'
4
+ import { RENDER } from '../runtime/RENDER.ts'
5
+ import { scope } from '../runtime/scope.ts'
6
+ import type { EachRow } from './types/EachRow.ts'
7
+
8
+ /*
9
+ Async keyed list — the runtime for `<template each await key=>`. Like `each`, but
10
+ over an AsyncIterable: rows append and reconcile by key as the iterator yields, so
11
+ a live stream (an `async function*` rpc, a socket feed) lands row by row. Keying by
12
+ identity lets a re-yielded key reuse its node and inner effects rather than append a
13
+ duplicate.
14
+
15
+ SSR renders no rows — async sources are client-time (an infinite stream would hang
16
+ SSR) — so hydration just parks the anchor before the next sibling (like an empty
17
+ sync each) and the client drains the iterable. A reactive re-run (a cache
18
+ invalidate, or the iterable expression changing) bumps the generation so a prior
19
+ in-flight drain stops appending; departed keys are pruned once a drain completes
20
+ (an infinite stream never prunes — rows accumulate / update in place).
21
+
22
+ On a mid-stream rejection the already-streamed rows stay and the `<template catch>`
23
+ branch (`renderCatch`) renders after them; absent a catch branch the rejection
24
+ surfaces (re-throws) instead of being swallowed (mirrors `<template await>`).
25
+ */
26
+ // @readme plumbing
27
+ export function eachAsync<T>(
28
+ parent: Node,
29
+ items: () => AsyncIterable<T>,
30
+ keyOf: (item: T) => string,
31
+ render: (parent: Node, item: T) => Node,
32
+ /* Absent → an iterator rejection surfaces instead of rendering a catch branch. */
33
+ renderCatch: ((parent: Node, error: unknown) => Node[]) | undefined,
34
+ ): void {
35
+ const rows = new Map<string, EachRow>()
36
+
37
+ /* Build one row in its own scope so its bindings dispose when it leaves. Rows are
38
+ always created (never on the server), so this runs after hydration has ended. */
39
+ const buildRow = (item: T): EachRow => {
40
+ let node: Node | undefined
41
+ const dispose = scope(() => {
42
+ node = render(parent, item)
43
+ })
44
+ return { node: node as Node, dispose }
45
+ }
46
+
47
+ const hydration = RENDER.hydration
48
+ const anchor = document.createTextNode('')
49
+ if (hydration !== undefined) {
50
+ parent.insertBefore(anchor, claimChild(hydration, parent)) // no server rows to claim
51
+ } else {
52
+ parent.appendChild(anchor)
53
+ }
54
+
55
+ /* The mounted `<template catch>` range, disposed when a fresh run re-streams. */
56
+ let errorRange: { nodes: Node[]; dispose: () => void } | undefined
57
+ const clearError = (): void => {
58
+ if (errorRange !== undefined) {
59
+ errorRange.dispose()
60
+ for (const node of errorRange.nodes) {
61
+ parent.removeChild(node)
62
+ }
63
+ errorRange = undefined
64
+ }
65
+ }
66
+
67
+ /* Bumped each run so a superseded drain stops appending and pruning. */
68
+ let generation = 0
69
+ /* The live iterator, held so a re-run or teardown can `return()` it — closing
70
+ the source (a generator's `finally`, a socket) and resolving any pending
71
+ `next()`. Bumping `generation` alone can't reach a drain parked on `await
72
+ iterator.next()`: an idle infinite stream never yields again, so the loop
73
+ never re-checks `generation` — it dangles on the microtask queue forever. */
74
+ let iterator: AsyncIterator<T> | undefined
75
+ effect(() => {
76
+ generation += 1
77
+ const generationAtStart = generation
78
+ iterator?.return?.() // close the superseded run's iterator before re-streaming
79
+ iterator = undefined
80
+ clearError() // a fresh run drops a prior error branch
81
+ const iterable = items() // read (subscribe) synchronously
82
+ const present = new Set<string>()
83
+ const drain = async (): Promise<void> => {
84
+ const active = iterable[Symbol.asyncIterator]()
85
+ iterator = active
86
+ while (true) {
87
+ const result = await active.next()
88
+ /* A re-run or teardown bumped the generation while we awaited. */
89
+ if (generationAtStart !== generation) {
90
+ return
91
+ }
92
+ if (result.done === true) {
93
+ break
94
+ }
95
+ const key = keyOf(result.value)
96
+ present.add(key)
97
+ /* A re-yielded key rebuilds the row from the new value, swapping the old
98
+ node out (v1 has no in-place field patch — rows bind plain snapshots). */
99
+ const stale = rows.get(key)
100
+ const row = buildRow(result.value)
101
+ rows.set(key, row)
102
+ if (stale !== undefined) {
103
+ stale.dispose()
104
+ parent.removeChild(stale.node)
105
+ }
106
+ parent.insertBefore(row.node, anchor) // arrival order, before the anchor
107
+ }
108
+ for (const [key, row] of rows) {
109
+ if (!present.has(key)) {
110
+ row.dispose()
111
+ parent.removeChild(row.node)
112
+ rows.delete(key)
113
+ }
114
+ }
115
+ }
116
+ drain().catch((error: unknown) => {
117
+ if (generationAtStart !== generation) {
118
+ return
119
+ }
120
+ /* No catch branch → surface the rejection (mirrors `<template await>`). */
121
+ if (renderCatch === undefined) {
122
+ throw error
123
+ }
124
+ /* Keep the streamed rows; render the catch branch after them, at the anchor. */
125
+ let nodes: Node[] = []
126
+ const dispose = scope(() => {
127
+ nodes = renderCatch(parent, error)
128
+ })
129
+ for (const node of nodes) {
130
+ parent.insertBefore(node, anchor)
131
+ }
132
+ errorRange = { nodes, dispose }
133
+ })
134
+ })
135
+
136
+ /* Stop the live stream when the enclosing scope tears down. The effect's own
137
+ disposer only unsubscribes from `items()` — it leaves the running `drain()`
138
+ pulling rows into a now-detached parent forever. Bump the generation so the
139
+ drain abandons its loop, `return()` the iterator to release the source and any
140
+ pending `next()`, drop the error branch, and dispose every surviving row. */
141
+ if (OWNER.current !== undefined) {
142
+ OWNER.current.push(() => {
143
+ generation += 1
144
+ iterator?.return?.()
145
+ iterator = undefined
146
+ clearError()
147
+ for (const row of rows.values()) {
148
+ row.dispose()
149
+ }
150
+ rows.clear()
151
+ })
152
+ }
153
+ }
@@ -0,0 +1,35 @@
1
+ import { enterRenderPass } from '../runtime/enterRenderPass.ts'
2
+ import { exitRenderPass } from '../runtime/exitRenderPass.ts'
3
+ import { RENDER } from '../runtime/RENDER.ts'
4
+ import { scope } from '../runtime/scope.ts'
5
+
6
+ /*
7
+ Adopts existing server-rendered DOM instead of rebuilding it. Runs `build(host)`
8
+ with a claim cursor active, so the dom helpers (openChild/appendText/appendStatic)
9
+ take the existing nodes rather than creating new ones — attaching event listeners
10
+ and reactive effects to the server's markup in place (no re-render, preserved
11
+ focus/scroll). Returns a disposer.
12
+
13
+ Adopts the server DOM in place across the framework: static structure (elements
14
+ + text + bindings), `if`/`else`, keyed `each`, `switch`, and child components
15
+ (with slots) — they hydrate automatically because the wrapper is claimed while
16
+ hydration is still active. The only block not yet adopted is `await` (it
17
+ interacts with the streamed stream-swap); a component using `await` should `mount`.
18
+ */
19
+ // @readme plumbing
20
+ export function hydrate(host: Element, build: (host: Element) => void): () => void {
21
+ const previous = RENDER.hydration
22
+ RENDER.hydration = { next: new Map() }
23
+ enterRenderPass()
24
+ try {
25
+ return scope(() => {
26
+ try {
27
+ build(host)
28
+ } finally {
29
+ exitRenderPass()
30
+ }
31
+ })
32
+ } finally {
33
+ RENDER.hydration = previous
34
+ }
35
+ }
@@ -0,0 +1,29 @@
1
+ import { enterRenderPass } from '../runtime/enterRenderPass.ts'
2
+ import { exitRenderPass } from '../runtime/exitRenderPass.ts'
3
+ import { scope } from '../runtime/scope.ts'
4
+
5
+ /*
6
+ Mounts a component into `host`: runs `build(host)` under an ownership scope so
7
+ every binding it creates is collected, and returns a disposer that stops all
8
+ reactivity and clears the host. `build` appends its nodes to `host` (via the dom
9
+ bindings below). This is the runtime entry the compiler's component output calls.
10
+
11
+ Brackets a render pass so the outermost mount resets the block-id counter and an
12
+ inlined child component's mount continues it — keeping await/try ids aligned with
13
+ the SSR stream (see `enterRenderPass`).
14
+ */
15
+ // @readme plumbing
16
+ export function mount(host: Element, build: (host: Element) => void): () => void {
17
+ enterRenderPass()
18
+ const stop = scope(() => {
19
+ try {
20
+ build(host)
21
+ } finally {
22
+ exitRenderPass()
23
+ }
24
+ })
25
+ return () => {
26
+ stop()
27
+ host.textContent = ''
28
+ }
29
+ }
@@ -0,0 +1,33 @@
1
+ import { hotReloadEnabled } from '../runtime/hotReloadEnabled.ts'
2
+ import { OWNER } from '../runtime/OWNER.ts'
3
+ import { registerHotInstance } from '../runtime/registerHotInstance.ts'
4
+ import type { UiComponent } from '../runtime/types/UiComponent.ts'
5
+
6
+ /*
7
+ Mounts a child component into its wrapper host. Plain path (production, and dev
8
+ without the hot bridge): run the factory — exactly the bare call the compiler used
9
+ to emit. Hot path (hotReloadEnabled and the factory carries a module id): keep the
10
+ mount disposer and record the instance so an edit can dispose + re-run it in place,
11
+ and file a cleanup with the mounting owner so the record and its scope leave
12
+ together when the parent (or branch/row) tears down. The factory already mounts
13
+ under its own scope (see `mount`), so the recorded disposer tears down just this
14
+ instance.
15
+ */
16
+ // @readme plumbing
17
+ export function mountChild(
18
+ host: Element,
19
+ factory: UiComponent,
20
+ props: Parameters<UiComponent>[1],
21
+ ): void {
22
+ const moduleId = factory.__abideId
23
+ if (!hotReloadEnabled.current || moduleId === undefined) {
24
+ factory(host, props)
25
+ return
26
+ }
27
+ const instance = { host, factory, props, dispose: factory(host, props) }
28
+ const remove = registerHotInstance(moduleId, instance)
29
+ OWNER.current?.push(() => {
30
+ instance.dispose()
31
+ remove()
32
+ })
33
+ }
@@ -0,0 +1,15 @@
1
+ import { OWNER } from '../runtime/OWNER.ts'
2
+
3
+ /*
4
+ Attaches an event listener and registers its removal with the current ownership
5
+ scope, so a component's listeners detach when it disposes. This is the runtime
6
+ target for an `onclick={…}` binding; the handler body is where the compiler's
7
+ lowered patches (`model.replace(...)`) run.
8
+ */
9
+ // @readme plumbing
10
+ export function on(element: Element, type: string, handler: EventListener): void {
11
+ element.addEventListener(type, handler)
12
+ if (OWNER.current !== undefined) {
13
+ OWNER.current.push(() => element.removeEventListener(type, handler))
14
+ }
15
+ }
@@ -0,0 +1,22 @@
1
+ import { claimChild } from '../runtime/claimChild.ts'
2
+ import { RENDER } from '../runtime/RENDER.ts'
3
+
4
+ /*
5
+ Opens a child element of `parent`: creates and appends it (create mode), or claims
6
+ the existing server-rendered node at the parent's current build position (hydrate
7
+ mode), advancing the claim pointer. Returns the element so bindings and children
8
+ attach to it. The compiler emits this for every element so the same build code
9
+ serves both modes.
10
+ */
11
+ // @readme plumbing
12
+ export function openChild(parent: Node, tag: string): Element {
13
+ const hydration = RENDER.hydration
14
+ if (hydration !== undefined) {
15
+ const current = claimChild(hydration, parent)
16
+ hydration.next.set(parent, current === null ? null : current.nextSibling)
17
+ return current as unknown as Element
18
+ }
19
+ const element = document.createElement(tag)
20
+ parent.appendChild(element)
21
+ return element
22
+ }
@@ -0,0 +1,20 @@
1
+ import { claimChild } from '../runtime/claimChild.ts'
2
+ import { RENDER } from '../runtime/RENDER.ts'
3
+
4
+ /*
5
+ Opens the root element of a control-flow branch/row, which the block inserts
6
+ itself. In create mode it returns a detached element (the block does the
7
+ insert); in hydrate mode it claims the existing server-rendered root from the
8
+ parent's claim pointer (in place — the block adopts it). The compiler emits this
9
+ for `each`/`if`/`switch`/`await` branch roots so adoption and creation share code.
10
+ */
11
+ // @readme plumbing
12
+ export function openRoot(parent: Node, tag: string): Element {
13
+ const hydration = RENDER.hydration
14
+ if (hydration !== undefined) {
15
+ const current = claimChild(hydration, parent)
16
+ hydration.next.set(parent, current === null ? null : current.nextSibling)
17
+ return current as unknown as Element
18
+ }
19
+ return document.createElement(tag)
20
+ }
@@ -0,0 +1,75 @@
1
+ import { effect } from '../effect.ts'
2
+ import { claimChild } from '../runtime/claimChild.ts'
3
+ import { RENDER } from '../runtime/RENDER.ts'
4
+ import { scope } from '../runtime/scope.ts'
5
+ import type { SwitchCase } from './types/SwitchCase.ts'
6
+
7
+ /*
8
+ Multi-branch binding — the runtime for `<template switch>`. An effect evaluates
9
+ the subject, picks the first case whose `match` equals it (strict `===`), falling
10
+ back to the default (`match` undefined); the chosen branch renders in its own
11
+ scope, anchored for placement. A branch is a RANGE of element roots, tracked as a
12
+ node array so a multi-root case inserts/removes as a unit. Staying on the same
13
+ branch across a subject change leaves it mounted; switching disposes the old.
14
+
15
+ On hydrate it adopts the case the server rendered (in place) and anchors after it;
16
+ the effect's first run picks the same case and is a no-op, later changes swap fresh.
17
+ */
18
+ // @readme plumbing
19
+ export function switchBlock(parent: Node, subject: () => unknown, cases: SwitchCase[]): void {
20
+ const hydration = RENDER.hydration
21
+ let active: { nodes: Node[]; dispose: () => void } | undefined
22
+ let activeIndex = -1
23
+ let anchor: Node
24
+
25
+ const build = (chosen: SwitchCase): { nodes: Node[]; dispose: () => void } => {
26
+ let nodes: Node[] = []
27
+ const dispose = scope(() => {
28
+ nodes = chosen.render(parent)
29
+ })
30
+ return { nodes, dispose }
31
+ }
32
+
33
+ const select = (value: unknown): number => {
34
+ const matched = cases.findIndex(
35
+ (entry) => entry.match !== undefined && entry.match() === value,
36
+ )
37
+ return matched === -1 ? cases.findIndex((entry) => entry.match === undefined) : matched
38
+ }
39
+
40
+ if (hydration !== undefined) {
41
+ activeIndex = select(subject())
42
+ const chosen = activeIndex === -1 ? undefined : cases[activeIndex]
43
+ if (chosen !== undefined) {
44
+ active = build(chosen)
45
+ }
46
+ anchor = document.createTextNode('')
47
+ parent.insertBefore(anchor, claimChild(hydration, parent))
48
+ } else {
49
+ anchor = document.createTextNode('')
50
+ parent.appendChild(anchor)
51
+ }
52
+
53
+ effect(() => {
54
+ const index = select(subject())
55
+ if (index === activeIndex) {
56
+ return
57
+ }
58
+ if (active !== undefined) {
59
+ active.dispose()
60
+ for (const node of active.nodes) {
61
+ parent.removeChild(node)
62
+ }
63
+ active = undefined
64
+ }
65
+ activeIndex = index
66
+ const chosen = index === -1 ? undefined : cases[index]
67
+ if (chosen === undefined) {
68
+ return
69
+ }
70
+ active = build(chosen)
71
+ for (const node of active.nodes) {
72
+ parent.insertBefore(node, anchor)
73
+ }
74
+ })
75
+ }
@@ -0,0 +1,20 @@
1
+ import { effect } from '../effect.ts'
2
+
3
+ /*
4
+ A text node whose content tracks `read()`. The effect captures whatever reactive
5
+ cells `read` touches, so the node — and only this node — re-renders when they
6
+ change: one text node, one effect — fine-grained granularity.
7
+
8
+ Plain-text only — `read()` is coerced with String(). For a `{expr}` interpolation
9
+ that may yield an `html\`…\`` or snippet value the compiler emits `appendText`,
10
+ which branches on the branded value and inserts raw markup; `text` cannot host
11
+ multiple nodes and would stringify such a value to `[object Object]`.
12
+ */
13
+ // @readme plumbing
14
+ export function text(read: () => unknown): Text {
15
+ const node = document.createTextNode('')
16
+ effect(() => {
17
+ node.data = String(read())
18
+ })
19
+ return node
20
+ }
@@ -0,0 +1,112 @@
1
+ import { claimChild } from '../runtime/claimChild.ts'
2
+ import { OWNER } from '../runtime/OWNER.ts'
3
+ import { RENDER } from '../runtime/RENDER.ts'
4
+
5
+ /*
6
+ Synchronous error boundary — the runtime for `<template try>`. Builds the guarded
7
+ subtree (`renderTry`); if building it throws — including a throw from an initial
8
+ reactive read, since effects run during build — it tears down the partial scope
9
+ and builds `renderCatch(error)` instead. Both branches are a range of element
10
+ roots tracked together. No `renderCatch` (no `<template catch>`) re-throws, so the
11
+ error propagates to the nearest enclosing boundary (or the server 500 / stream).
12
+
13
+ Catches throws during the BUILD of the subtree (mount, hydrate adoption, and the
14
+ initial reactive reads). A throw in a later effect re-run is outside this lexical
15
+ build and is not caught here.
16
+
17
+ On hydrate it claims the SSR boundary (`<!--abide:try:N-->…<!--/abide:try:N-->`):
18
+ the happy path adopts the guarded nodes in place; a throw discards the boundary's
19
+ server nodes and builds the catch fresh.
20
+ */
21
+ // @readme plumbing
22
+ export function tryBlock(
23
+ parent: Node,
24
+ id: number,
25
+ renderTry: (parent: Node) => Node[],
26
+ renderCatch?: (parent: Node, error: unknown) => Node[],
27
+ ): void {
28
+ /* Run a build under a fresh ownership scope; on throw, tear down the partial
29
+ effects/listeners it registered and rethrow so the caller can fall back. */
30
+ const buildScoped = (build: () => Node[]): Node[] => {
31
+ const previous = OWNER.current
32
+ const disposers: Array<() => void> = []
33
+ OWNER.current = disposers
34
+ try {
35
+ const nodes = build()
36
+ OWNER.current = previous
37
+ return nodes
38
+ } catch (error) {
39
+ OWNER.current = previous
40
+ for (let index = disposers.length - 1; index >= 0; index -= 1) {
41
+ disposers[index]?.()
42
+ }
43
+ throw error
44
+ }
45
+ }
46
+
47
+ const hydration = RENDER.hydration
48
+ if (hydration !== undefined) {
49
+ const open = claimChild(hydration, parent)
50
+ hydration.next.set(parent, open?.nextSibling ?? null) // advance past the open marker
51
+ try {
52
+ buildScoped(() => renderTry(parent)) // claims the guarded nodes in place
53
+ const close = claimChild(hydration, parent) // claim the close marker
54
+ hydration.next.set(parent, close?.nextSibling ?? null)
55
+ } catch (error) {
56
+ /* The server rendered (or partially built) something that didn't adopt —
57
+ drop the whole boundary and build the catch fresh in its place. */
58
+ const after = discardBoundary(parent, open, `/abide:try:${id}`, hydration)
59
+ if (renderCatch === undefined) {
60
+ throw error
61
+ }
62
+ const previous = RENDER.hydration
63
+ RENDER.hydration = undefined
64
+ try {
65
+ for (const node of buildScoped(() => renderCatch(parent, error))) {
66
+ parent.insertBefore(node, after)
67
+ }
68
+ } finally {
69
+ RENDER.hydration = previous
70
+ }
71
+ }
72
+ return
73
+ }
74
+
75
+ let nodes: Node[]
76
+ try {
77
+ nodes = buildScoped(() => renderTry(parent))
78
+ } catch (error) {
79
+ if (renderCatch === undefined) {
80
+ throw error
81
+ }
82
+ nodes = buildScoped(() => renderCatch(parent, error))
83
+ }
84
+ for (const node of nodes) {
85
+ parent.appendChild(node)
86
+ }
87
+ }
88
+
89
+ /* Remove the SSR boundary — open marker through close marker (inclusive) — and
90
+ park the hydration cursor on the node after it, returning that node so a fresh
91
+ catch can be inserted in the boundary's place. */
92
+ function discardBoundary(
93
+ parent: Node,
94
+ open: Node | null,
95
+ closeData: string,
96
+ hydration: NonNullable<(typeof RENDER)['hydration']>,
97
+ ): Node | null {
98
+ let node = open
99
+ let after: Node | null = null
100
+ while (node !== null) {
101
+ const next = node.nextSibling
102
+ const isClose = (node as { data?: string }).data === closeData
103
+ parent.removeChild(node)
104
+ if (isClose) {
105
+ after = next
106
+ break
107
+ }
108
+ node = next
109
+ }
110
+ hydration.next.set(parent, after)
111
+ return after
112
+ }
@@ -0,0 +1,3 @@
1
+ /* A live row in a keyed list: its top node (for placement/removal) and the
2
+ disposer for the bindings created in its ownership scope. */
3
+ export type EachRow = { node: Node; dispose: () => void }
@@ -0,0 +1,6 @@
1
+ /* One branch of a `switch`: `match` returns the value this case selects on
2
+ (undefined = the default branch); `render` builds the branch's element roots. */
3
+ export type SwitchCase = {
4
+ match: (() => unknown) | undefined
5
+ render: (parent: Node) => Node[]
6
+ }
@@ -0,0 +1,73 @@
1
+ import { effect } from '../effect.ts'
2
+ import { claimChild } from '../runtime/claimChild.ts'
3
+ import { RENDER } from '../runtime/RENDER.ts'
4
+ import { scope } from '../runtime/scope.ts'
5
+
6
+ /*
7
+ Conditional binding — the runtime for `<template if>` (with optional `else`). An
8
+ effect tracks `condition()` and mounts the matching branch (`render` truthy,
9
+ `renderElse` falsy), anchored for placement; only a truthy↔falsy flip swaps. A
10
+ branch is a RANGE of element roots (one or more), tracked as a node array so a
11
+ multi-root branch inserts/removes as a unit.
12
+
13
+ On hydrate it adopts the branch the server rendered: it runs the matching render
14
+ in place (its roots claim the existing nodes), then inserts an anchor after them
15
+ for future toggles. The effect's first run sees the same branch and is a no-op;
16
+ later toggles (after hydration ends) build fresh.
17
+ */
18
+ // @readme plumbing
19
+ export function when(
20
+ parent: Node,
21
+ condition: () => unknown,
22
+ render: (parent: Node) => Node[],
23
+ renderElse?: (parent: Node) => Node[],
24
+ ): void {
25
+ const hydration = RENDER.hydration
26
+ let active: { nodes: Node[]; dispose: () => void } | undefined
27
+ let activeBranch: 'then' | 'else' | undefined
28
+ let anchor: Node
29
+
30
+ const build = (chosen: (parent: Node) => Node[]): { nodes: Node[]; dispose: () => void } => {
31
+ let nodes: Node[] = []
32
+ const dispose = scope(() => {
33
+ nodes = chosen(parent)
34
+ })
35
+ return { nodes, dispose }
36
+ }
37
+
38
+ if (hydration !== undefined) {
39
+ activeBranch = condition() ? 'then' : 'else'
40
+ const chosen = activeBranch === 'then' ? render : renderElse
41
+ if (chosen !== undefined) {
42
+ active = build(chosen) // roots claim the SSR nodes in place
43
+ }
44
+ anchor = document.createTextNode('')
45
+ parent.insertBefore(anchor, claimChild(hydration, parent))
46
+ } else {
47
+ anchor = document.createTextNode('')
48
+ parent.appendChild(anchor)
49
+ }
50
+
51
+ effect(() => {
52
+ const branch = condition() ? 'then' : 'else'
53
+ if (branch === activeBranch) {
54
+ return
55
+ }
56
+ if (active !== undefined) {
57
+ active.dispose()
58
+ for (const node of active.nodes) {
59
+ parent.removeChild(node)
60
+ }
61
+ active = undefined
62
+ }
63
+ activeBranch = branch
64
+ const chosen = branch === 'then' ? render : renderElse
65
+ if (chosen === undefined) {
66
+ return
67
+ }
68
+ active = build(chosen)
69
+ for (const node of active.nodes) {
70
+ parent.insertBefore(node, anchor)
71
+ }
72
+ })
73
+ }
@@ -0,0 +1,16 @@
1
+ import { createEffectNode } from './runtime/createEffectNode.ts'
2
+ import type { EffectResult } from './runtime/types/EffectResult.ts'
3
+
4
+ /*
5
+ Runs `fn` now, capturing every reactive cell it reads, then re-runs it whenever
6
+ any of those change. `fn` may return a teardown — run before each re-run and on
7
+ dispose — and may be async (its teardown then runs once the promise settles, but
8
+ only the reads before its first `await` are tracked). Returns a dispose that runs
9
+ the final teardown and detaches it from the graph. This is abide's from-scratch
10
+ effect primitive: the open-on-first-read / close-on-last-reader lifecycle,
11
+ grounded in abide's own reactive core.
12
+ */
13
+ // @readme plumbing
14
+ export function effect(fn: () => EffectResult): () => void {
15
+ return createEffectNode(fn)
16
+ }