@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,59 @@
1
+ import type { CacheEntry } from './types/CacheEntry.ts'
2
+ import type { CacheSnapshotEntry } from './types/CacheSnapshotEntry.ts'
3
+
4
+ /*
5
+ Rebuilds a warm cache entry from a wire snapshot: an already-resolved Response
6
+ plus the synchronously-decoded warm value, so cache() reads it without a network
7
+ round-trip or a microtask hop. Shared by the initial inline snapshot hydration
8
+ and the streamed resolution path. `settled` is true — the body shipped fully
9
+ resolved either way. `hydrated` marks that the wrap options didn't travel:
10
+ the first cache() read adopts its call site's ttl (see CacheEntry).
11
+ */
12
+ export function cacheEntryFromSnapshot(entry: CacheSnapshotEntry): CacheEntry {
13
+ const headers = new Headers(entry.headers)
14
+ const response = new Response(entry.body, {
15
+ status: entry.status,
16
+ statusText: entry.statusText,
17
+ headers,
18
+ })
19
+ return {
20
+ key: entry.key,
21
+ promise: Promise.resolve(response),
22
+ request: new Request(entry.url, { method: entry.method }),
23
+ ttl: undefined,
24
+ expiresAt: undefined,
25
+ value: warmValueFromSnapshot(entry.status, headers, entry.body),
26
+ settled: true,
27
+ hydrated: true,
28
+ }
29
+ }
30
+
31
+ /*
32
+ Synchronously decodes a snapshot body so the warm entry reads without a
33
+ microtask hop on first render. Mirrors decodeResponse for the textual cases the
34
+ snapshot ships; non-2xx and 204 yield no warm value and fall back to the async
35
+ path, which throws HttpError / returns undefined exactly as a live call would.
36
+ Binary/xml bodies also skip the warm path and decode asynchronously.
37
+ */
38
+ function warmValueFromSnapshot(status: number, headers: Headers, body: string): unknown {
39
+ if (status === 204 || status < 200 || status >= 300) {
40
+ return undefined
41
+ }
42
+ const contentType = (headers.get('content-type') ?? '').toLowerCase()
43
+ if (contentType.includes('json')) {
44
+ /*
45
+ `.includes('json')` also matches streaming/non-JSON types like
46
+ application/x-ndjson; fall back to the async path (return undefined)
47
+ rather than throwing a SyntaxError synchronously during hydration.
48
+ */
49
+ try {
50
+ return JSON.parse(body)
51
+ } catch {
52
+ return undefined
53
+ }
54
+ }
55
+ if (contentType.startsWith('text/')) {
56
+ return body
57
+ }
58
+ return undefined
59
+ }
@@ -0,0 +1,16 @@
1
+ import type { CacheStore } from './types/CacheStore.ts'
2
+
3
+ /*
4
+ Internal slot the runtime entries register their resolver into. The
5
+ server entry installs an ALS-backed resolver (request-scoped); the
6
+ client entry installs a module-singleton resolver. `fallback` is a
7
+ single lazy store used only when no resolver is registered — keeps
8
+ isolated tests working without forcing them to spin up the runtime.
9
+ */
10
+ export const cacheStoreSlot: {
11
+ resolver: (() => CacheStore | undefined) | undefined
12
+ fallback: CacheStore | undefined
13
+ } = {
14
+ resolver: undefined,
15
+ fallback: undefined,
16
+ }
@@ -0,0 +1,10 @@
1
+ import { activeCacheStore } from './activeCacheStore.ts'
2
+ import { globalCacheStore } from './globalCacheStore.ts'
3
+ import type { CacheStore } from './types/CacheStore.ts'
4
+
5
+ /* Active + process-level stores, deduped (one tab store on the client). */
6
+ export function cacheStores(): CacheStore[] {
7
+ const active = activeCacheStore()
8
+ const global = globalCacheStore()
9
+ return active === global ? [active] : [active, global]
10
+ }
@@ -0,0 +1,63 @@
1
+ /*
2
+ Deterministic key string for a value. Object keys (and Map keys, Set members)
3
+ are sorted so values differing only in insertion order produce identical
4
+ strings, and every recognised type carries a tag so distinct types never
5
+ collide — a Date never equals the string of its ISO form, a Map never equals a
6
+ plain object. Used to derive cache keys from producer args and from auto-keyed
7
+ POST/PUT/PATCH bodies; the output is a key, not a request body, so it is free to
8
+ encode types JSON.stringify would silently flatten (Map/Set → {}), coerce
9
+ (Date → its ISO string, via toJSON before any replacer sees it) or drop
10
+ (undefined). Covers the value types commonly passed as rpc args: primitives,
11
+ arrays, plain objects, Date, Map, Set, and bigint. Functions and symbols can't
12
+ key anything meaningful but are tagged rather than dropped so a stray one can't
13
+ silently collapse two distinct argument sets onto the same key.
14
+ */
15
+ export function canonicalJson(value: unknown): string {
16
+ if (value === null) {
17
+ return 'null'
18
+ }
19
+ if (value === undefined) {
20
+ return 'undefined'
21
+ }
22
+ const type = typeof value
23
+ if (type === 'string') {
24
+ return JSON.stringify(value)
25
+ }
26
+ if (type === 'bigint') {
27
+ return `${value}n`
28
+ }
29
+ if (type === 'number') {
30
+ // -0 and 0 stringify alike but are distinct keys; NaN/Infinity stay stable (JSON drops them to null).
31
+ return Object.is(value, -0) ? '-0' : String(value)
32
+ }
33
+ if (type === 'boolean') {
34
+ return String(value)
35
+ }
36
+ if (type !== 'object') {
37
+ // function | symbol — not serialisable; tag by type so the key can't crash or alias a real value.
38
+ return `${type}()`
39
+ }
40
+ if (value instanceof Date) {
41
+ return `Date(${value.getTime()})`
42
+ }
43
+ if (Array.isArray(value)) {
44
+ return `[${value.map(canonicalJson).join(',')}]`
45
+ }
46
+ if (value instanceof Map) {
47
+ // Sort by encoded entry so key order doesn't change the result.
48
+ const entries = Array.from(
49
+ value,
50
+ ([key, val]) => `${canonicalJson(key)}=>${canonicalJson(val)}`,
51
+ ).sort()
52
+ return `Map{${entries.join(',')}}`
53
+ }
54
+ if (value instanceof Set) {
55
+ const members = Array.from(value, canonicalJson).sort()
56
+ return `Set{${members.join(',')}}`
57
+ }
58
+ const record = value as Record<string, unknown>
59
+ const entries = Object.keys(record)
60
+ .sort()
61
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`)
62
+ return `{${entries.join(',')}}`
63
+ }
@@ -0,0 +1,13 @@
1
+ import type { HttpVerb } from './types/HttpVerb.ts'
2
+
3
+ /*
4
+ Whether a verb carries its args in the request body (POST/PUT/PATCH) vs
5
+ on the query string (GET/DELETE/HEAD). Single source for the split so the
6
+ synthesized Request (buildRpcRequest), the handler-side parse (parseArgs),
7
+ the cache key (keyForRemoteCall), and the OpenAPI doc can't disagree.
8
+ */
9
+ const BODY_METHODS = new Set<HttpVerb>(['POST', 'PUT', 'PATCH'])
10
+
11
+ export function carriesBodyArgs(method: HttpVerb): boolean {
12
+ return BODY_METHODS.has(method)
13
+ }
@@ -0,0 +1,7 @@
1
+ import { rm } from 'node:fs/promises'
2
+ import { lastConnectionPath } from './lastConnectionPath.ts'
3
+
4
+ // Forgets the saved connection (the `/disconnect` reset). Missing file is a no-op.
5
+ export async function clearLastConnection(programName: string): Promise<void> {
6
+ await rm(lastConnectionPath(programName), { force: true })
7
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ Derives the MCP tool name / CLI subcommand name from an rpc URL. Strips
3
+ the framework's `/rpc/` mount and joins nested folder segments with `-`
4
+ so `users/list.ts` (mounted at `/rpc/users/list`) becomes `users-list`
5
+ across both surfaces. Folder prefixing prevents collisions when two
6
+ files in different folders share the same stem (e.g. `users/list.ts`
7
+ and `posts/list.ts`); `/` is not a valid character in MCP tool names or
8
+ typical CLI subcommands, so the join uses `-`.
9
+ */
10
+ const RPC_PREFIX = '/rpc/'
11
+
12
+ export function commandNameForUrl(url: string): string {
13
+ const trimmed = url.startsWith(RPC_PREFIX)
14
+ ? url.slice(RPC_PREFIX.length)
15
+ : url.replace(/^\//, '')
16
+ return trimmed.replaceAll('/', '-')
17
+ }
@@ -0,0 +1,104 @@
1
+ import { createLifecycleChannel } from './createLifecycleChannel.ts'
2
+ import { createSubscriber } from './createSubscriber.ts'
3
+ import { keyMatchesPrefix } from './keyMatchesPrefix.ts'
4
+ import type { CacheEntry } from './types/CacheEntry.ts'
5
+ import type { CacheInvalidation } from './types/CacheInvalidation.ts'
6
+ import type { CacheStore } from './types/CacheStore.ts'
7
+
8
+ /*
9
+ Returns a fresh cache store. On the server, every request gets its own
10
+ store via the AsyncLocalStorage RequestStore. On the client, a single
11
+ module-level store is created at startup and shared across the tab.
12
+
13
+ Each key gets a lazily-created subscriber. Reading a key from a
14
+ tracking scope (derived / effect) subscribes that scope; invalidating
15
+ the key dispatches an 'invalidate' event whose detail is a Set of affected
16
+ keys so each listener's lookup is O(1). The subscriber outlives entry
17
+ eviction — invalidating/refetching a key reuses the same subscriber, so
18
+ there's no listener churn or duplicate registration as cache values come
19
+ and go. It's evicted only when its last reactive reader tears down (the
20
+ client store is module-level/tab-scoped, so retaining a thunk per distinct
21
+ key would otherwise grow unbounded across a session), identity-guarded so
22
+ a concurrent re-subscribe isn't clobbered — mirroring tail.ts.
23
+ */
24
+ export function createCacheStore(): CacheStore {
25
+ const entries = new Map<string, CacheEntry>()
26
+ const events = new EventTarget()
27
+ const subscribers = new Map<string, () => void>()
28
+ const pendingRefresh = new Set<string>()
29
+
30
+ function subscribe(key: string): void {
31
+ const existing = subscribers.get(key)
32
+ if (existing) {
33
+ existing()
34
+ return
35
+ }
36
+ const registered = createSubscriber((update) => {
37
+ const onInvalidate = (event: Event) => {
38
+ if ((event as CustomEvent<CacheInvalidation>).detail.has(key)) {
39
+ update()
40
+ }
41
+ }
42
+ events.addEventListener('invalidate', onInvalidate)
43
+ return () => {
44
+ events.removeEventListener('invalidate', onInvalidate)
45
+ if (subscribers.get(key) === registered) {
46
+ subscribers.delete(key)
47
+ }
48
+ }
49
+ })
50
+ subscribers.set(key, registered)
51
+ registered()
52
+ }
53
+
54
+ /* Store-wide in-flight tap for the probes; semantics live in createLifecycleChannel. */
55
+ const lifecycle = createLifecycleChannel()
56
+ /*
57
+ Per-prefix channels arm fn-selector probes (pending(fn) / refreshing(fn))
58
+ without waking them on unrelated cache events. Keyed by selector prefix
59
+ (method+url / producer reference id — see selectorPrefix), so the
60
+ population is bounded by probe call sites in code, not by data; a channel
61
+ whose last reader tore down is an inert closure, not a leak.
62
+ */
63
+ const prefixLifecycles = new Map<string, ReturnType<typeof createLifecycleChannel>>()
64
+
65
+ function trackLifecycle(keyPrefix?: string): void {
66
+ if (keyPrefix === undefined) {
67
+ lifecycle.track()
68
+ return
69
+ }
70
+ let channel = prefixLifecycles.get(keyPrefix)
71
+ if (channel === undefined) {
72
+ channel = createLifecycleChannel()
73
+ prefixLifecycles.set(keyPrefix, channel)
74
+ }
75
+ channel.track()
76
+ }
77
+
78
+ /*
79
+ Marks the store-wide channel always (bare/scope probes scan everything)
80
+ plus any probed prefix channel owning the changed key — a new entry's key
81
+ starts with its fn's prefix, so prefix probes see membership too.
82
+ */
83
+ function markLifecycle(key?: string): void {
84
+ lifecycle.mark()
85
+ if (key === undefined) {
86
+ return
87
+ }
88
+ prefixLifecycles.forEach((channel, prefix) => {
89
+ if (keyMatchesPrefix(key, prefix)) {
90
+ channel.mark()
91
+ }
92
+ })
93
+ }
94
+
95
+ return {
96
+ entries,
97
+ events,
98
+ subscribe,
99
+ trackLifecycle,
100
+ markLifecycle,
101
+ pendingRefresh,
102
+ stats: { hits: 0, misses: 0, coalesced: 0 },
103
+ }
104
+ }
@@ -0,0 +1,122 @@
1
+ import { emitLogRecord } from './emitLogRecord.ts'
2
+ import { isDebugEnabled } from './isDebugEnabled.ts'
3
+ import { isDebugNegated } from './isDebugNegated.ts'
4
+ import { randomHexId } from './randomHexId.ts'
5
+ import type { ChannelLog } from './types/ChannelLog.ts'
6
+
7
+ /*
8
+ Channel gating source. Server: the DEBUG env var, npm-debug conventions via
9
+ isDebugEnabled. Browser: the `abide-debug` localStorage key with the same
10
+ pattern syntax, read per call so toggling it in devtools takes effect without
11
+ a reload. localStorage access is guarded — privacy modes throw on read.
12
+ */
13
+ function channelPatterns(): string | undefined {
14
+ if (typeof process !== 'undefined' && process.env.DEBUG) {
15
+ return process.env.DEBUG
16
+ }
17
+ if (typeof localStorage !== 'undefined') {
18
+ try {
19
+ return localStorage.getItem('abide-debug') ?? undefined
20
+ } catch {
21
+ return undefined
22
+ }
23
+ }
24
+ return undefined
25
+ }
26
+
27
+ // Prefers a full stack trace when the value is an Error so logs include the call site.
28
+ function errorParts(value: unknown): { msg: string; stack?: string } {
29
+ if (value instanceof Error) {
30
+ return { msg: value.message, stack: value.stack }
31
+ }
32
+ return { msg: String(value) }
33
+ }
34
+
35
+ /* Times `work` under an operation name, minting the record's span id so a future exporter can materialise it as a span. */
36
+ async function traceWork<Return>(
37
+ name: string,
38
+ work: () => Return | Promise<Return>,
39
+ channel: string,
40
+ ): Promise<Return> {
41
+ const spanId = randomHexId(8)
42
+ const startMs = performance.now()
43
+ try {
44
+ const result = await work()
45
+ emitLogRecord({
46
+ level: 'info',
47
+ msg: '',
48
+ name,
49
+ spanId,
50
+ durationMs: performance.now() - startMs,
51
+ channel,
52
+ })
53
+ return result
54
+ } catch (error) {
55
+ const { msg, stack } = errorParts(error)
56
+ emitLogRecord({
57
+ level: 'error',
58
+ msg,
59
+ stack,
60
+ name,
61
+ spanId,
62
+ durationMs: performance.now() - startMs,
63
+ channel,
64
+ })
65
+ throw error
66
+ }
67
+ }
68
+
69
+ /*
70
+ Builds the callable-with-levels log shape bound to a channel. Every record
71
+ carries the channel; `getChannel` is a thunk because the default (app-name)
72
+ channel resolves after module init. `always` channels — the app's own and
73
+ abide's framework voice — emit unless a `-name` DEBUG pattern explicitly
74
+ shuts them off; everything else is a diagnostic channel gated by DEBUG
75
+ (browser: the abide-debug localStorage key). Levels never gate: a silenced
76
+ channel is silent at every level, an enabled one shows them all.
77
+ */
78
+ export function createChannelLog(
79
+ getChannel: () => string,
80
+ always: boolean,
81
+ ): ChannelLog & { enabled(): boolean } {
82
+ const enabled = () =>
83
+ always
84
+ ? !isDebugNegated(getChannel(), channelPatterns())
85
+ : isDebugEnabled(getChannel(), channelPatterns())
86
+ const call = (message: string, data?: unknown): void => {
87
+ if (enabled()) {
88
+ emitLogRecord({ level: 'info', msg: message, data, channel: getChannel() })
89
+ }
90
+ }
91
+ return Object.assign(call, {
92
+ /* Exposed so wrappers (abideLog's styling voices) emit through the same gate. */
93
+ enabled,
94
+ warn(message: string, data?: unknown): void {
95
+ if (enabled()) {
96
+ emitLogRecord({ level: 'warn', msg: message, data, channel: getChannel() })
97
+ }
98
+ },
99
+ error(value: unknown, data?: unknown): void {
100
+ if (enabled()) {
101
+ emitLogRecord({ level: 'error', ...errorParts(value), data, channel: getChannel() })
102
+ }
103
+ },
104
+ trace<Return>(name: string, work: () => Return | Promise<Return>): Promise<Return> {
105
+ if (enabled()) {
106
+ return traceWork(name, work, getChannel())
107
+ }
108
+ /*
109
+ No span: skip the async-wrapper allocation that every other method
110
+ already gates away, and hand back work()'s own promise untouched so
111
+ a coalesced cache join keeps the shared promise's identity. A
112
+ synchronous throw still surfaces as a rejection, matching traceWork.
113
+ */
114
+ try {
115
+ const result = work()
116
+ return result instanceof Promise ? result : Promise.resolve(result)
117
+ } catch (error) {
118
+ return Promise.reject(error)
119
+ }
120
+ },
121
+ })
122
+ }
@@ -0,0 +1,56 @@
1
+ import { createSubscriber } from './createSubscriber.ts'
2
+
3
+ /*
4
+ Lifecycle tap shared by the cache store and the tail registry: one
5
+ "membership or state changed" signal for the pending()/refreshing() probes,
6
+ which match a group of entries and re-derive by scanning. The owning
7
+ registry decides the granularity — the cache store keeps a store-wide
8
+ channel plus one per probed selector prefix; this module only owns the
9
+ subscribe/notify semantics. track() inside a
10
+ tracking scope ($derived / $effect) re-runs that scope on every mark();
11
+ outside one it is a no-op. The subscriber is created lazily on the first
12
+ tracked read and self-evicts when its last reader tears down,
13
+ identity-guarded so a concurrent re-track isn't clobbered. mark() is a plain
14
+ callback — the channel only ever has the one memoized listener, so no
15
+ EventTarget dispatch is needed.
16
+
17
+ mark() defers its notify to a microtask: registry mutations happen inside
18
+ consumer read paths, and the documented read idiom is `$derived(await
19
+ cache(fn)())` — a cold read there registers an entry mid-derived, where
20
+ writing the subscriber's version source throws state_unsafe_mutation. The
21
+ probes scan the registry at re-derive time, so a deferred ping reads state
22
+ that is already current; marks within one tick coalesce into one notify.
23
+ */
24
+ export function createLifecycleChannel(): { track: () => void; mark: () => void } {
25
+ let notify: (() => void) | undefined
26
+ let tracker: (() => void) | undefined
27
+ let marked = false
28
+ return {
29
+ track() {
30
+ if (!tracker) {
31
+ const created = createSubscriber((update) => {
32
+ notify = update
33
+ return () => {
34
+ notify = undefined
35
+ if (tracker === created) {
36
+ tracker = undefined
37
+ }
38
+ }
39
+ })
40
+ tracker = created
41
+ }
42
+ tracker()
43
+ },
44
+ mark() {
45
+ if (notify === undefined || marked) {
46
+ return
47
+ }
48
+ marked = true
49
+ queueMicrotask(() => {
50
+ marked = false
51
+ /* Re-read: the last reader may have torn down during the deferral. */
52
+ notify?.()
53
+ })
54
+ },
55
+ }
56
+ }
@@ -0,0 +1,118 @@
1
+ /*
2
+ The liveness state machine shared by every "is that server still there?"
3
+ consumer: a recursive timer (never setInterval, so a slow probe can't overlap
4
+ the next) runs `probe(url)`; a success resets the miss count, `failureLimit`
5
+ consecutive misses declare the target down. Two modes by which hook is given:
6
+
7
+ - `onLost` (terminal): the bundle launcher's mode — down fires onLost once
8
+ and the watch stops; the user reconnects deliberately.
9
+ - `onChange` (continuous): the client health() mode — down fires
10
+ onChange(false), polling continues, and the first subsequent success fires
11
+ onChange(true). Transitions only, never per-poll — except the first success
12
+ after watch(), which always reports so a consumer that kept state across a
13
+ stop()/watch() cycle (health's backendAlive) resyncs with the machine.
14
+
15
+ watch(url) (re)starts against a new target (first probe after one interval —
16
+ probeNow() forces an immediate one); a probe resolving after the target
17
+ changed is discarded (the url capture is the staleness guard). Probe
18
+ transport is injected — the launcher passes the identity-endpoint check, the
19
+ client health() a browser fetch — so the machine is side-neutral.
20
+ */
21
+ export function createLivenessWatch(options: {
22
+ probe: (url: string) => Promise<boolean>
23
+ onLost?: (url: string) => void
24
+ onChange?: (alive: boolean) => void
25
+ intervalMs?: number
26
+ failureLimit?: number
27
+ }): {
28
+ watch: (url: string) => void
29
+ stop: () => void
30
+ probeNow: () => void
31
+ } {
32
+ const intervalMs = options.intervalMs ?? 4000
33
+ const failureLimit = options.failureLimit ?? 2
34
+ let watchedUrl: string | undefined
35
+ let timer: ReturnType<typeof setTimeout> | undefined
36
+ let inFlight = false
37
+ let failures = 0
38
+ let alive = true
39
+ /* No verdict reported since watch() — makes the first success always report. */
40
+ let fresh = true
41
+
42
+ async function runProbe(): Promise<void> {
43
+ const url = watchedUrl
44
+ if (!url) {
45
+ return
46
+ }
47
+ if (inFlight) {
48
+ /*
49
+ A stale probe from a previous target is still awaiting. Keep this
50
+ watch's timer armed — the stale resolution discards itself without
51
+ rescheduling, so returning bare here would leave no timer and the
52
+ new target silently unwatched.
53
+ */
54
+ timer = setTimeout(runProbe, intervalMs)
55
+ return
56
+ }
57
+ inFlight = true
58
+ const up = await options.probe(url)
59
+ inFlight = false
60
+ // A stop or re-watch during the await moved the target — discard.
61
+ if (watchedUrl !== url) {
62
+ return
63
+ }
64
+ if (up) {
65
+ failures = 0
66
+ if (!alive || fresh) {
67
+ alive = true
68
+ fresh = false
69
+ options.onChange?.(true)
70
+ }
71
+ } else {
72
+ failures += 1
73
+ if (failures >= failureLimit && alive) {
74
+ alive = false
75
+ fresh = false
76
+ if (options.onChange) {
77
+ options.onChange(false)
78
+ } else {
79
+ stop()
80
+ options.onLost?.(url)
81
+ return
82
+ }
83
+ }
84
+ }
85
+ timer = setTimeout(runProbe, intervalMs)
86
+ }
87
+
88
+ function watch(url: string): void {
89
+ stop()
90
+ watchedUrl = url
91
+ fresh = true
92
+ timer = setTimeout(runProbe, intervalMs)
93
+ }
94
+
95
+ function stop(): void {
96
+ if (timer) {
97
+ clearTimeout(timer)
98
+ timer = undefined
99
+ }
100
+ watchedUrl = undefined
101
+ failures = 0
102
+ alive = true
103
+ }
104
+
105
+ /* Event-accelerated check (visibility return, online event): probe immediately instead of waiting out the interval. */
106
+ function probeNow(): void {
107
+ if (!watchedUrl || inFlight) {
108
+ return
109
+ }
110
+ if (timer) {
111
+ clearTimeout(timer)
112
+ timer = undefined
113
+ }
114
+ void runProbe()
115
+ }
116
+
117
+ return { watch, stop, probeNow }
118
+ }