@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,36 @@
1
+ import type { Server } from 'bun'
2
+
3
+ // Ports tried upward from `start` before giving up and letting the kernel assign one.
4
+ const SCAN_RANGE = 100
5
+
6
+ /*
7
+ Binds the real server, scanning upward from `start` for the first free port.
8
+ The listener that wins a port is the one that keeps it: unlike probing a
9
+ throwaway server and releasing it before the real bind, this leaves no window
10
+ for the chosen port to be stolen in between — the gap that crashed boot on
11
+ EADDRINUSE instead of stepping to the next port. `bindAt` does the actual
12
+ Bun.serve; only an in-use port is retried, any other failure propagates. After
13
+ SCAN_RANGE occupied ports it binds port 0 so the kernel assigns any free port.
14
+ */
15
+ export function listenOnOpenPort(
16
+ bindAt: (port: number) => Server<unknown>,
17
+ start: number,
18
+ ): Server<unknown> {
19
+ for (let port = start; port < start + SCAN_RANGE; port++) {
20
+ try {
21
+ return bindAt(port)
22
+ } catch (error) {
23
+ if (!isAddressInUse(error)) {
24
+ throw error
25
+ }
26
+ // port in use — try the next one up
27
+ }
28
+ }
29
+ // every candidate was taken; bind to 0 so the kernel picks a free port
30
+ return bindAt(0)
31
+ }
32
+
33
+ // Bun reports a taken port as an Error carrying code 'EADDRINUSE'.
34
+ function isAddressInUse(error: unknown): boolean {
35
+ return error instanceof Error && (error as { code?: string }).code === 'EADDRINUSE'
36
+ }
@@ -0,0 +1,156 @@
1
+ import { abideLog } from '../../shared/abideLog.ts'
2
+ import type { Pages } from '../../ui/types/Pages.ts'
3
+ import { verbRegistry } from '../rpc/verbRegistry.ts'
4
+ import { socketRegistry } from '../sockets/socketRegistry.ts'
5
+ import { ensureRegistriesLoaded } from './registryManifests.ts'
6
+
7
+ // Cell glyphs: PRESENT, ABSENT.
8
+ const PRESENT = '✓'
9
+ const ABSENT = '·'
10
+ const COLUMN_GAP = 2
11
+
12
+ const hasColor = typeof Bun !== 'undefined' && Bun.enableANSIColors
13
+ // Red foreground then `\x1b[39m` (default-foreground, not full reset) so the enclosing dim survives.
14
+ const redden = (text: string): string =>
15
+ hasColor ? `${Bun.color('red', 'ansi-256')}${text}\x1b[39m` : text
16
+
17
+ /*
18
+ A declared inputSchema is what makes mcp/cli safe to advertise (see defineVerb /
19
+ defineSocket), so a missing schema gets a red `·` to flag the declaration whose
20
+ machine surfaces are gated behind it.
21
+ */
22
+ const schemaCell = (hasSchema: boolean): string => (hasSchema ? PRESENT : redden(ABSENT))
23
+ const flag = (on: boolean): string => (on ? PRESENT : ABSENT)
24
+
25
+ // Display width ignoring ANSI color escapes, so colored glyphs don't inflate alignment.
26
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: the ESC (\x1b) is the intended match — stripping the color escape to measure visible width
27
+ const displayWidth = (cell: string): number => cell.replace(/\x1b\[[0-9;]*m/g, '').length
28
+
29
+ // A titled table: its header row plus data rows, all sharing the column layout below.
30
+ type SurfaceTable = { title: string; header: string[]; rows: string[][] }
31
+
32
+ // Per-column width: the widest cell's display width across every row given.
33
+ function columnWidths(rows: string[][]): number[] {
34
+ const columnCount = Math.max(...rows.map((row) => row.length))
35
+ return Array.from({ length: columnCount }, (_, column) =>
36
+ Math.max(...rows.map((row) => displayWidth(row[column] ?? ''))),
37
+ )
38
+ }
39
+
40
+ /*
41
+ Left-aligns one row's cells into the given fixed column widths plus a gap.
42
+ Padding is explicit spaces measured by displayWidth so embedded color escapes
43
+ don't inflate the width and break alignment. Two-space indented.
44
+ */
45
+ function renderRow(row: string[], widths: number[]): string {
46
+ return (
47
+ ' ' +
48
+ row
49
+ .map((cell, column) => {
50
+ /* widths covers every column (computed from the longest row); the fallback
51
+ exists for noUncheckedIndexedAccess in consumer tsconfigs and pads only the gap. */
52
+ const width = widths[column] ?? displayWidth(cell)
53
+ return cell + ' '.repeat(width - displayWidth(cell) + COLUMN_GAP)
54
+ })
55
+ .join('')
56
+ .trimEnd()
57
+ )
58
+ }
59
+
60
+ /*
61
+ Prints every non-empty table under one shared set of column widths, so the
62
+ identifier and glyph columns line up vertically across the page/socket/rpc
63
+ tables rather than each table aligning only within itself. Each table keeps its
64
+ own dim header row.
65
+ */
66
+ function logTables(tables: SurfaceTable[]): void {
67
+ const present = tables.filter((table) => table.rows.length > 0)
68
+ if (present.length === 0) {
69
+ return
70
+ }
71
+ const widths = columnWidths(present.flatMap((table) => [table.header, ...table.rows]))
72
+ present.forEach((table) => {
73
+ abideLog.info(`${table.title}:`)
74
+ abideLog.detail(
75
+ [table.header, ...table.rows].map((row) => renderRow(row, widths)).join('\n'),
76
+ )
77
+ })
78
+ }
79
+
80
+ /*
81
+ Boot-time surface map: every page, socket, and rpc with the surfaces it is
82
+ exposed on, so abide's routing and multimodal-by-default exposure are auditable
83
+ rather than implicit. Three aligned tables — scan a column to spot a missing
84
+ surface, a row to see one declaration's reach:
85
+
86
+ - pages: each route with the nearest layout and error boundary wrapping it.
87
+ - sockets: name + client surfaces (schema/browser/mcp/cli) and whether clients
88
+ may publish.
89
+ - rpcs: method+path (headed `http` since http/openapi are unconditional) +
90
+ per-declaration client surfaces.
91
+
92
+ All three render under one shared column grid (see logTables): the identifier
93
+ leads flush-left in every table — page route, socket name, or rpc method+path —
94
+ then the surface columns, so the glyphs line up vertically across the tables.
95
+ rpc folds its method into a left-aligned prefix of the identifier cell, so paths
96
+ still start at a shared column. For sockets and rpcs the `schema`
97
+ column leads: it's what unlocks the non-browser surfaces, so a missing schema
98
+ reddens to flag the gated declaration. Loads the full registry, so it runs once
99
+ at boot and only under `abide` debug logging (DEBUG=abide) to avoid forcing
100
+ eager imports in production. Best-effort: enumeration failures are swallowed,
101
+ this is diagnostic only.
102
+ */
103
+ export async function logExposedSurfaces(routing: { pages: Pages }): Promise<void> {
104
+ try {
105
+ await ensureRegistriesLoaded()
106
+ } catch {
107
+ return
108
+ }
109
+
110
+ const pageRows = Object.keys(routing.pages)
111
+ .map((route) => [route])
112
+ .sort()
113
+
114
+ const socketRows = Array.from(socketRegistry.values(), (entry) => [
115
+ entry.socket.name,
116
+ schemaCell(Boolean(entry.schema)),
117
+ flag(entry.clients.browser),
118
+ flag(entry.clients.mcp),
119
+ flag(entry.clients.cli),
120
+ flag(entry.allowClientPublish),
121
+ ]).sort()
122
+
123
+ /*
124
+ rpc identifier = method left-aligned to a shared width then the path, so the
125
+ methods line up and every path starts at the same column — while the cell as
126
+ a whole still leads flush-left like the page route and socket name.
127
+ */
128
+ const methodWidth = Math.max(
129
+ 'http'.length,
130
+ ...Array.from(verbRegistry.values(), (entry) => entry.remote.method.length),
131
+ )
132
+ const withMethod = (method: string, identifier: string): string =>
133
+ method.padEnd(methodWidth + COLUMN_GAP) + identifier
134
+
135
+ const rpcRows = Array.from(verbRegistry.values(), (entry) => [
136
+ withMethod(entry.remote.method, entry.remote.url),
137
+ schemaCell(Boolean(entry.inputSchema)),
138
+ flag(entry.clients.browser),
139
+ flag(entry.clients.mcp),
140
+ flag(entry.clients.cli),
141
+ ]).sort()
142
+
143
+ logTables([
144
+ { title: 'pages', header: ['page'], rows: pageRows },
145
+ {
146
+ title: 'sockets',
147
+ header: ['socket', 'schema', 'browser', 'mcp', 'cli', 'publish'],
148
+ rows: socketRows,
149
+ },
150
+ {
151
+ title: 'rpcs',
152
+ header: [withMethod('http', ''), 'schema', 'browser', 'mcp', 'cli'],
153
+ rows: rpcRows,
154
+ },
155
+ ])
156
+ }
@@ -0,0 +1,97 @@
1
+ import { abideLog } from '../../shared/abideLog.ts'
2
+ import { logTapSlot } from '../../shared/logTapSlot.ts'
3
+ import { requestScopeSlot } from '../../shared/requestScopeSlot.ts'
4
+ import { socketTapSlot } from '../../shared/socketTapSlot.ts'
5
+ import type { LogRecord } from '../../shared/types/LogRecord.ts'
6
+ import { buildCacheSnapshot } from './buildCacheSnapshot.ts'
7
+ import { buildInspectorSurface } from './buildInspectorSurface.ts'
8
+ import { ensureRegistriesLoaded } from './registryManifests.ts'
9
+ import type { InspectorContext } from './types/InspectorContext.ts'
10
+
11
+ /* The request handler `@abide/inspector` returns — serves its UI + data routes. */
12
+ type InspectorHandler = (request: Request, url: URL) => Promise<Response>
13
+
14
+ /* Shapes a published socket frame as a log record so the inspector's one feed
15
+ carries it like any other event — on the `socket` channel, tied to the active
16
+ trace when the publish happened inside a request (e.g. an RPC broadcasting). */
17
+ function socketFrameRecord(frame: { socket: string; message: unknown }): LogRecord {
18
+ const scope = requestScopeSlot.resolver?.()
19
+ return {
20
+ ts: Date.now(),
21
+ level: 'info',
22
+ channel: 'socket',
23
+ msg: frame.socket,
24
+ data: frame.message,
25
+ trace: scope?.trace.traceId,
26
+ elapsedMs: scope?.elapsedMs,
27
+ method: scope?.method,
28
+ path: scope?.path,
29
+ }
30
+ }
31
+
32
+ /*
33
+ Non-literal so Bun's bundler can't fold the optional package into a compiled
34
+ binary: the import stays external and resolves only at runtime, only when the
35
+ package is actually installed.
36
+ */
37
+ const INSPECTOR_PACKAGE = '@abide/inspector'
38
+
39
+ /*
40
+ Activates the opt-in inspector when ABIDE_ENABLE_INSPECTOR=true. The flag is the
41
+ activation switch; the package is installed explicitly (`bun add -d
42
+ @abide/inspector`) — core never installs anything. Returns the package's request
43
+ handler for createServer to route, or undefined when the flag is off or the
44
+ package isn't present (with a one-line install hint in that case).
45
+
46
+ The inspector exposes all traffic and the whole machine surface, so it's gated
47
+ behind the operator's explicit flag and announces itself loudly on mount —
48
+ enable it only in trusted/dev environments (mirrors warnUnguardedMcp).
49
+ */
50
+ export async function maybeMountInspector(app: {
51
+ name: string
52
+ version: string
53
+ }): Promise<InspectorHandler | undefined> {
54
+ if (process.env.ABIDE_ENABLE_INSPECTOR !== 'true') {
55
+ return undefined
56
+ }
57
+ const imported = (await import(INSPECTOR_PACKAGE).catch(() => undefined)) as
58
+ | { mountInspector: (context: InspectorContext) => InspectorHandler }
59
+ | undefined
60
+ if (!imported) {
61
+ abideLog.warn(
62
+ `ABIDE_ENABLE_INSPECTOR=true but ${INSPECTOR_PACKAGE} isn't installed — run \`bun add -d ${INSPECTOR_PACKAGE}\``,
63
+ )
64
+ return undefined
65
+ }
66
+ const context: InspectorContext = {
67
+ app,
68
+ loadSurface: async () => {
69
+ await ensureRegistriesLoaded()
70
+ return buildInspectorSurface()
71
+ },
72
+ cacheSnapshot: buildCacheSnapshot,
73
+ /*
74
+ One process-wide tap each for the log and socket chokepoints; the
75
+ inspector owns both and fans out to its readers. Socket frames arrive
76
+ shaped as `socket`-channel records, so the inspector sees a single
77
+ uniform event stream.
78
+ */
79
+ onRecord: (listener: (record: LogRecord) => void) => {
80
+ const onFrame = (frame: { socket: string; message: unknown }) =>
81
+ listener(socketFrameRecord(frame))
82
+ logTapSlot.tap = listener
83
+ socketTapSlot.tap = onFrame
84
+ return () => {
85
+ if (logTapSlot.tap === listener) {
86
+ logTapSlot.tap = undefined
87
+ }
88
+ if (socketTapSlot.tap === onFrame) {
89
+ socketTapSlot.tap = undefined
90
+ }
91
+ }
92
+ },
93
+ }
94
+ const handler = imported.mountInspector(context)
95
+ abideLog.warn('inspector enabled — exposes all traffic and the full surface; trusted use only')
96
+ return handler
97
+ }
@@ -0,0 +1,14 @@
1
+ /*
2
+ Derives the MIME type from a URL pathname using Bun.file().type, which
3
+ operates on the file extension synchronously without touching the disk. The
4
+ Bun.file ref here is never read from — it exists only to reuse Bun's
5
+ extension-to-MIME table. Cache by extension so repeat hits for the same
6
+ chunk type (.js / .css / .map / .svg / …) skip the BunFile allocation.
7
+ */
8
+ const mimeByExtension = new Map<string, string>()
9
+
10
+ export function mimeForExtension(pathname: string): string {
11
+ const dot = pathname.lastIndexOf('.')
12
+ const extension = dot === -1 ? '' : pathname.slice(dot)
13
+ return mimeByExtension.getOrInsertComputed(extension, () => Bun.file(pathname).type)
14
+ }
@@ -0,0 +1,15 @@
1
+ import { withBaseUrl } from '../../shared/withBaseUrl.ts'
2
+ import type { RequestStore } from './types/RequestStore.ts'
3
+
4
+ /*
5
+ The browser-space URL `page.url` publishes for a request: store.url with the
6
+ mount base re-applied, matching what window.location shows under a proxy
7
+ mount, so an active-state compare against url() output hydrates identically.
8
+ store.url itself stays app-space (base-stripped by the proxy) for routing and
9
+ error-prefix matching. Memoized on the store so repeated page-proxy reads
10
+ share one URL.
11
+ */
12
+ export function pageUrlFromStore(store: RequestStore): URL {
13
+ store.pageUrl ??= withBaseUrl(store.url)
14
+ return store.pageUrl
15
+ }
@@ -0,0 +1,10 @@
1
+ import { parseBoundedEnvInt } from '../../shared/parseBoundedEnvInt.ts'
2
+
3
+ /*
4
+ Parses ABIDE_IDLE_TIMEOUT into Bun's per-connection idle timeout in seconds.
5
+ Bun accepts 0–255 (0 disables the timeout); returns undefined for missing,
6
+ empty, or out-of-range/non-integer input so the caller keeps its default.
7
+ */
8
+ export function parseIdleTimeout(value: string | undefined): number | undefined {
9
+ return parseBoundedEnvInt(value, 0, 255)
10
+ }
@@ -0,0 +1,11 @@
1
+ import { parseBoundedEnvInt } from '../../shared/parseBoundedEnvInt.ts'
2
+
3
+ /*
4
+ Parses a PORT env value into a usable TCP port (0–65535), returning undefined
5
+ for missing, empty, or out-of-range/non-integer input so the caller can fall
6
+ back to a default. A bare Number() would turn '' into 0 (a random
7
+ kernel-assigned port) and 'abc' into NaN, both silently wrong.
8
+ */
9
+ export function parsePort(value: string | undefined): number | undefined {
10
+ return parseBoundedEnvInt(value, 0, 65535)
11
+ }
@@ -0,0 +1,66 @@
1
+ import type { PromptRoutes } from '../prompts/types/PromptRoutes.ts'
2
+ import type { RemoteRoutes } from '../rpc/types/RemoteRoutes.ts'
3
+ import type { SocketRoutes } from '../sockets/types/SocketRoutes.ts'
4
+
5
+ /*
6
+ Process-wide slot for the rpc + sockets + prompts manifests. createServer
7
+ assigns once at boot (right after the route table is built); the MCP
8
+ server, the OpenAPI emitter, and prompt enumeration read it on first
9
+ request so they can lazy-import every module and walk the
10
+ verb/socket/prompt registries.
11
+
12
+ The slot pattern (mirrors getActiveServer) lets the framework-generated
13
+ McpServer bind to the manifests at module scope while the loaders stay
14
+ lazy until the first enumeration request.
15
+ */
16
+ type RegistryManifests = {
17
+ rpc: RemoteRoutes
18
+ sockets: SocketRoutes
19
+ prompts: PromptRoutes
20
+ }
21
+
22
+ let manifests: RegistryManifests | undefined
23
+ let loading: Promise<void> | undefined
24
+
25
+ export function setRegistryManifests(value: RegistryManifests): void {
26
+ manifests = value
27
+ loading = undefined
28
+ }
29
+
30
+ /*
31
+ On first call, eagerly imports every rpc + socket + prompt module so
32
+ defineVerb / defineSocket / definePrompt fire and populate the
33
+ registries. Idempotent — repeat calls reuse the same in-flight promise,
34
+ so concurrent first requests (e.g. /openapi.json + an MCP tools/list)
35
+ trigger exactly one load instead of racing to fire the full import set
36
+ each. Eager loading is acceptable here because enumeration (MCP
37
+ tool/resource/prompt lists, the OpenAPI document) fundamentally requires
38
+ the full surface; the alternative of per-call lazy loading produces flaky
39
+ first-call latency.
40
+ */
41
+ export function ensureRegistriesLoaded(): Promise<void> {
42
+ if (!manifests) {
43
+ return Promise.resolve()
44
+ }
45
+ if (!loading) {
46
+ const { rpc, sockets, prompts } = manifests
47
+ loading = Promise.all([
48
+ ...Object.values(rpc).map((loader) => loader()),
49
+ ...Object.values(sockets).map((loader) => loader()),
50
+ ...Object.values(prompts).map((loader) => loader()),
51
+ ])
52
+ .then(() => undefined)
53
+ /*
54
+ Clear the memo on failure so a transient import error (a
55
+ module that throws at load, fixed by the next HMR pass)
56
+ doesn't poison every later enumeration request for the
57
+ process lifetime. The rejection still propagates to this
58
+ caller; the reset only affects subsequent calls.
59
+ */
60
+ .catch((error) => {
61
+ loading = undefined
62
+ throw error
63
+ })
64
+ }
65
+ return loading
66
+ }
@@ -0,0 +1,5 @@
1
+ // AsyncLocalStorage is canonical via node:async_hooks — Bun has no separate API
2
+ import { AsyncLocalStorage } from 'node:async_hooks'
3
+ import type { RequestStore } from './types/RequestStore.ts'
4
+
5
+ export const requestContext = new AsyncLocalStorage<RequestStore>()
@@ -0,0 +1,25 @@
1
+ import type { PageSnapshot } from '../../shared/types/PageSnapshot.ts'
2
+ import { pageUrlFromStore } from './pageUrlFromStore.ts'
3
+ import { requestContext } from './requestContext.ts'
4
+
5
+ /*
6
+ The server's page resolver: the `page` proxy reads route/params/url off the
7
+ ALS request store, so layout-scoped components see the live match during SSR
8
+ without a module singleton leaking across concurrent or streaming renders.
9
+ route/params land just before render; url is set at the request boundary, so
10
+ 404/error renders still get a correct page.url. Registered by serverEntry at
11
+ boot and mirrored by bootTestServer; undefined outside a request scope falls
12
+ through to activePage's empty fallback.
13
+ */
14
+ export function resolvePageSnapshot(): PageSnapshot | undefined {
15
+ const store = requestContext.getStore()
16
+ if (!store) {
17
+ return undefined
18
+ }
19
+ return {
20
+ route: store.route ?? '',
21
+ params: store.params ?? {},
22
+ url: pageUrlFromStore(store),
23
+ navigating: false,
24
+ }
25
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ Serves one compile-time-embedded asset: a gzip-capable client gets the stored
3
+ bytes as-is, anyone else gets them decompressed on the fly. Shared by the
4
+ `_app` and public/ asset servers so the decompress fallback lives once.
5
+ */
6
+ export function respondWithEmbeddedAsset(
7
+ compressed: Uint8Array<ArrayBuffer>,
8
+ wantsGzip: boolean,
9
+ headers: { base: HeadersInit; gzip: HeadersInit },
10
+ ): Response {
11
+ if (wantsGzip) {
12
+ return new Response(compressed, { headers: headers.gzip })
13
+ }
14
+ /* gunzipSync's Buffer is freshly allocated over a plain ArrayBuffer; @types/bun widens it to ArrayBufferLike, which BodyInit rejects. */
15
+ return new Response(Bun.gunzipSync(compressed) as Uint8Array<ArrayBuffer>, {
16
+ headers: headers.base,
17
+ })
18
+ }
@@ -0,0 +1,150 @@
1
+ import { abideLog } from '../../shared/abideLog.ts'
2
+ import { createCacheStore } from '../../shared/createCacheStore.ts'
3
+ import { createTraceContext } from '../../shared/createTraceContext.ts'
4
+ import { formatTraceparent } from '../../shared/formatTraceparent.ts'
5
+ import { isStreamingResponse } from '../../shared/isStreamingResponse.ts'
6
+ import { logClosingRecord } from '../../shared/logClosingRecord.ts'
7
+ import type { AppModule } from '../AppModule.ts'
8
+ import { internalErrorResponse } from './internalErrorResponse.ts'
9
+ import { requestContext } from './requestContext.ts'
10
+ import type { RequestStore } from './types/RequestStore.ts'
11
+
12
+ /*
13
+ Establishes the per-request scope and runs `body` inside it: a fresh
14
+ CacheStore, the request's trace position and start time, and request metadata
15
+ published through the AsyncLocalStorage RequestStore (so cache(), request()/
16
+ server(), trace(), and log prefixes resolve without threading args), the
17
+ app's handleError — or the framework's 500 fallback — on a thrown body, and
18
+ optional request logging. The single seam every dynamic route crosses;
19
+ extracted from createServer so the scope, error, and logging behaviour is
20
+ exercisable through this interface without booting a Bun server.
21
+ */
22
+ export function runWithRequestScope(
23
+ req: Request,
24
+ /* `url` skips the WHATWG re-parse when the caller already parsed it (the fetch fallback). */
25
+ options: { app?: AppModule; logRequests: boolean; url?: URL },
26
+ body: (store: RequestStore) => Promise<Response>,
27
+ ): Promise<Response> {
28
+ const url = options.url ?? new URL(req.url)
29
+ const store: RequestStore = {
30
+ url,
31
+ req,
32
+ cache: createCacheStore(),
33
+ trace: createTraceContext(req.headers.get('traceparent')),
34
+ start: Bun.nanoseconds(),
35
+ }
36
+ return requestContext.run(store, async () => {
37
+ let response: Response
38
+ try {
39
+ response = await body(store)
40
+ } catch (error) {
41
+ if (options.app?.handleError) {
42
+ response = await options.app.handleError(error, req)
43
+ } else {
44
+ abideLog.error(error)
45
+ response = internalErrorResponse(error)
46
+ }
47
+ }
48
+ /*
49
+ Flush any cookies the handler set onto the outgoing response. Only when
50
+ a jar was materialized (cookies() was called) and only via append, so a
51
+ Set-Cookie the handler already placed on the response init survives.
52
+ */
53
+ if (store.cookies) {
54
+ const setCookies = store.cookies.toSetCookieHeaders()
55
+ if (setCookies.length > 0) {
56
+ try {
57
+ setCookies.forEach((header) => {
58
+ response.headers.append('set-cookie', header)
59
+ })
60
+ } catch {
61
+ /* A passthrough Response (proxied fetch) carries immutable headers;
62
+ rebuild it with a mutable copy so the cookies still ship rather
63
+ than the append throwing and 500ing the successful response. */
64
+ response = new Response(response.body, response)
65
+ setCookies.forEach((header) => {
66
+ response.headers.append('set-cookie', header)
67
+ })
68
+ }
69
+ }
70
+ }
71
+ /*
72
+ Server-Timing is always-on (identical dev/build): `total` is what's
73
+ knowable at header time — for streamed responses the settled total
74
+ belongs to the closing log record — and the `traceparent` entry is the
75
+ one header browsers expose to page JS, so RUM tooling links the
76
+ frontend to this trace. Guarded: a passthrough Response (proxied
77
+ fetch) carries immutable headers.
78
+ */
79
+ const headerMs = (Bun.nanoseconds() - store.start) / 1e6
80
+ const stats = store.cache.stats
81
+ const cacheEntry =
82
+ stats.hits + stats.misses + stats.coalesced > 0
83
+ ? `, cache;desc="hits=${stats.hits} misses=${stats.misses} coalesced=${stats.coalesced}"`
84
+ : ''
85
+ try {
86
+ response.headers.set(
87
+ 'server-timing',
88
+ `total;dur=${headerMs.toFixed(1)}, traceparent;desc="${formatTraceparent(store.trace)}"${cacheEntry}`,
89
+ )
90
+ } catch {
91
+ /* Immutable headers — skip; the closing log record still reports. */
92
+ }
93
+ if (!options.logRequests) {
94
+ return response
95
+ }
96
+ /*
97
+ The closing record logs at settle so its elapsed IS the total. Buffered
98
+ responses settle here; streaming bodies (SSE/JSONL) settle when the
99
+ stream ends — re-entered into the request scope because stream
100
+ callbacks don't inherit the ALS context.
101
+ */
102
+ let settled = false
103
+ const emitClose = () => {
104
+ if (settled) {
105
+ return
106
+ }
107
+ settled = true
108
+ requestContext.run(store, () => {
109
+ const ms = (Bun.nanoseconds() - store.start) / 1e6
110
+ /* Copy freezes the tallies at settle — the live object keeps counting if late reads land. */
111
+ logClosingRecord(req.method, `${url.pathname}${url.search}`, response.status, ms, {
112
+ ...store.cache.stats,
113
+ })
114
+ })
115
+ }
116
+ if (response.body && isStreamingResponse(response)) {
117
+ /*
118
+ A hand-pumped wrap rather than a TransformStream: streams typically
119
+ end by client disconnect (an SSE tab closing), which cancels the
120
+ readable without ever flushing a transform — Bun also skips the
121
+ transformer's cancel hook — so only this readable's own close/error/
122
+ cancel paths see every termination.
123
+ */
124
+ const reader = response.body.getReader()
125
+ const monitored = new ReadableStream({
126
+ async pull(controller) {
127
+ try {
128
+ const { done, value } = await reader.read()
129
+ if (done) {
130
+ emitClose()
131
+ controller.close()
132
+ return
133
+ }
134
+ controller.enqueue(value)
135
+ } catch (error) {
136
+ emitClose()
137
+ controller.error(error)
138
+ }
139
+ },
140
+ cancel(reason) {
141
+ emitClose()
142
+ return reader.cancel(reason)
143
+ },
144
+ })
145
+ return new Response(monitored, response)
146
+ }
147
+ emitClose()
148
+ return response
149
+ })
150
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ Escapes characters that could prematurely terminate the surrounding <script>
3
+ tag or be interpreted as HTML comment delimiters when a JSON literal is
4
+ inlined into an HTML document. U+2028 (LS) and U+2029 (PS) are valid in JSON
5
+ but break a `<script>` tag's inline content because the JavaScript lexer
6
+ treats them as line terminators; encode them as Unicode escapes.
7
+ */
8
+ const LINE_SEPARATOR = String.fromCharCode(0x2028)
9
+ const PARAGRAPH_SEPARATOR = String.fromCharCode(0x2029)
10
+
11
+ export function safeJsonForScript(value: unknown): string {
12
+ return JSON.stringify(value)
13
+ .replace(/</g, '\\u003c')
14
+ .replace(/-->/g, '--\\u003e')
15
+ .replaceAll(LINE_SEPARATOR, '\\u2028')
16
+ .replaceAll(PARAGRAPH_SEPARATOR, '\\u2029')
17
+ }