@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,37 @@
1
+ /*
2
+ Inspects the raw request URL (not the parsed pathname) for path-traversal
3
+ patterns. The WHATWG URL parser decodes `%2E%2E` to `..` and then collapses
4
+ dot-segments out of the pathname during normalization, so by the time
5
+ `url.pathname` is observable any encoded traversal has been masked. The
6
+ remaining literal `..` check guards against any future URL-parser quirk
7
+ that lets a normalised path through.
8
+
9
+ Hot path early-out: if none of the suspect substrings appear in the raw
10
+ URL we never lowercase the whole string nor walk segments.
11
+ */
12
+ export function containsTraversal(rawUrl: string): boolean {
13
+ if (rawUrl.includes('\\')) {
14
+ return true
15
+ }
16
+ if (rawUrl.includes('..') && segmentContainsDotDot(rawUrl)) {
17
+ return true
18
+ }
19
+ if (rawUrl.indexOf('%') === -1) {
20
+ return false
21
+ }
22
+ const lower = rawUrl.toLowerCase()
23
+ return lower.includes('%2e%2e') || lower.includes('%2f') || lower.includes('%5c')
24
+ }
25
+
26
+ function segmentContainsDotDot(rawUrl: string): boolean {
27
+ const queryStart = rawUrl.indexOf('?')
28
+ const pathEnd = queryStart === -1 ? rawUrl.length : queryStart
29
+ const pathStart = rawUrl.indexOf('/', rawUrl.indexOf('://') + 3)
30
+ if (pathStart === -1 || pathStart >= pathEnd) {
31
+ return false
32
+ }
33
+ return rawUrl
34
+ .slice(pathStart, pathEnd)
35
+ .split('/')
36
+ .some((segment) => segment === '..')
37
+ }
@@ -0,0 +1,76 @@
1
+ import { NO_STORE } from '../../shared/CACHE_CONTROL_VALUES.ts'
2
+ import { TEXT_PLAIN } from '../../shared/TEXT_PLAIN.ts'
3
+ import { acceptsGzip } from './acceptsGzip.ts'
4
+ import { cacheControlForAsset } from './cacheControlForAsset.ts'
5
+ import { containsTraversal } from './containsTraversal.ts'
6
+ import { createAssetHeaderCache } from './createAssetHeaderCache.ts'
7
+ import { globToPathSet } from './globToPathSet.ts'
8
+ import { respondWithEmbeddedAsset } from './respondWithEmbeddedAsset.ts'
9
+ import type { Assets } from './types/Assets.ts'
10
+
11
+ /*
12
+ Serves the build's `_app` assets (hashed chunks, css, sourcemaps). Two
13
+ sources, picked at construction — the sibling of createPublicAssetServer for
14
+ the framework-owned tree:
15
+
16
+ - `assets` (standalone compile): a map of request path → gzip bytes
17
+ embedded into the binary.
18
+ - `distDir` on disk (dev + `abide start`): files served straight from
19
+ `dist`, with the precompressed `.gz` sibling set snapshotted once at
20
+ boot so a gzip-capable client gets those bytes without on-the-fly
21
+ compression.
22
+
23
+ Unlike the public server this answers every `/_app/` request itself (404 on
24
+ a miss — nothing falls through past the build tree). The path-traversal
25
+ guard inspects the raw request URL because the WHATWG parser normalizes
26
+ encoded `..` segments away before `url.pathname` is visible.
27
+ */
28
+ export async function createAppAssetServer({
29
+ distDir,
30
+ assets,
31
+ }: {
32
+ distDir: string
33
+ assets?: Assets
34
+ }): Promise<(req: Request, url: URL) => Promise<Response>> {
35
+ // Per-pathname asset header bundles, hashed-chunk-aware Cache-Control.
36
+ const headersForAsset = createAssetHeaderCache(cacheControlForAsset)
37
+ const diskGzipPaths = assets
38
+ ? new Set<string>()
39
+ : await globToPathSet(
40
+ `${distDir}/_app`,
41
+ '**/*.gz',
42
+ (file) => `/_app/${file.replace(/\.gz$/, '')}`,
43
+ )
44
+
45
+ return async function serveAppAsset(req, url) {
46
+ if (containsTraversal(req.url)) {
47
+ return new Response('Not Found', {
48
+ status: 404,
49
+ headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
50
+ })
51
+ }
52
+ if (assets) {
53
+ const compressed = assets[url.pathname]
54
+ /* Miss-check before header work: the header cache keys on
55
+ (request-controlled) pathnames, so building bundles for junk
56
+ `/_app/*` probes would grow it without bound. */
57
+ if (!compressed) {
58
+ return new Response('Not Found', {
59
+ status: 404,
60
+ headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
61
+ })
62
+ }
63
+ return respondWithEmbeddedAsset(
64
+ compressed,
65
+ acceptsGzip(req),
66
+ headersForAsset(url.pathname),
67
+ )
68
+ }
69
+ const { base: baseHeaders, gzip: gzipHeaders } = headersForAsset(url.pathname)
70
+ const diskPath = distDir + url.pathname
71
+ if (acceptsGzip(req) && diskGzipPaths.has(url.pathname)) {
72
+ return new Response(Bun.file(`${diskPath}.gz`), { headers: gzipHeaders })
73
+ }
74
+ return new Response(Bun.file(diskPath), { headers: baseHeaders })
75
+ }
76
+ }
@@ -0,0 +1,31 @@
1
+ import { mimeForExtension } from './mimeForExtension.ts'
2
+
3
+ /*
4
+ A static-asset response's headers depend only on its pathname (extension →
5
+ Content-Type, path → Cache-Control), so each distinct pathname's header bundle
6
+ is built once and reused across every hit on that chunk — avoiding a per-request
7
+ allocation on a cold page load that pulls dozens of files. Each bundle carries
8
+ the plain `base` headers plus a `gzip` variant with `Content-Encoding: gzip`.
9
+ `cacheControlFor` lets callers vary the policy: hashed-aware for `/_app/`,
10
+ fixed for public/.
11
+ */
12
+ type AssetHeaderBundle = {
13
+ base: HeadersInit
14
+ gzip: HeadersInit
15
+ }
16
+
17
+ export function createAssetHeaderCache(
18
+ cacheControlFor: (pathname: string) => string,
19
+ ): (pathname: string) => AssetHeaderBundle {
20
+ const cache = new Map<string, AssetHeaderBundle>()
21
+ return function headersFor(pathname) {
22
+ return cache.getOrInsertComputed(pathname, () => {
23
+ const base: HeadersInit = {
24
+ 'Content-Type': mimeForExtension(pathname),
25
+ Vary: 'Accept-Encoding',
26
+ 'Cache-Control': cacheControlFor(pathname),
27
+ }
28
+ return { base, gzip: { ...base, 'Content-Encoding': 'gzip' } }
29
+ })
30
+ }
31
+ }
@@ -0,0 +1,67 @@
1
+ import { PUBLIC_ASSET_CACHE_CONTROL } from '../../shared/CACHE_CONTROL_VALUES.ts'
2
+ import { acceptsGzip } from './acceptsGzip.ts'
3
+ import { containsTraversal } from './containsTraversal.ts'
4
+ import { createAssetHeaderCache } from './createAssetHeaderCache.ts'
5
+ import { globToPathSet } from './globToPathSet.ts'
6
+ import { respondWithEmbeddedAsset } from './respondWithEmbeddedAsset.ts'
7
+ import type { Assets } from './types/Assets.ts'
8
+
9
+ /*
10
+ Serves files from the project's `public/` folder at the site root. Two
11
+ sources, picked at construction:
12
+
13
+ - `publicAssets` (standalone compile): a map of root path → gzip bytes
14
+ embedded into the binary, mirroring the `_app` asset embed.
15
+ - `publicDir` on disk (dev + `abide start`): files read straight from
16
+ `${cwd}/src/ui/public`, with the set of paths snapshotted once at
17
+ boot (see below).
18
+
19
+ Returns a server fn that resolves to `undefined` when no public file
20
+ matches the request path, so the caller falls through to its own 404 /
21
+ middleware path. The path-traversal guard mirrors serveStaticAsset's
22
+ defence against encoded `..` segments in the raw URL.
23
+
24
+ Async because disk mode globs `publicDir` once at construction to build a
25
+ Set of the available paths: every page nav and RPC falls through here, so
26
+ a Set lookup beats a filesystem stat per miss. A file added to public/
27
+ after boot needs a server restart to be seen — the same restart a code
28
+ change already triggers under `bun --watch`.
29
+ */
30
+ export async function createPublicAssetServer({
31
+ publicDir,
32
+ publicAssets,
33
+ }: {
34
+ publicDir: string
35
+ publicAssets?: Assets
36
+ }): Promise<(req: Request, url: URL) => Promise<Response | undefined>> {
37
+ const headersFor = createAssetHeaderCache(() => PUBLIC_ASSET_CACHE_CONTROL)
38
+ // `dot: true` keeps dotfiles (e.g. `.well-known/…`) servable, matching a raw disk stat.
39
+ const diskPaths = publicAssets
40
+ ? new Set<string>()
41
+ : await globToPathSet(publicDir, '**/*', (file) => `/${file}`, { dot: true })
42
+
43
+ /*
44
+ Existence is checked before any header work: every page nav and RPC
45
+ falls through here on its way to the 404/middleware path, and the
46
+ header cache keys on (request-controlled) pathnames — building bundles
47
+ for misses would grow it without bound.
48
+ */
49
+ return async function servePublicAsset(req, url) {
50
+ if (containsTraversal(req.url)) {
51
+ return undefined
52
+ }
53
+ if (publicAssets) {
54
+ const compressed = publicAssets[url.pathname]
55
+ if (!compressed) {
56
+ return undefined
57
+ }
58
+ return respondWithEmbeddedAsset(compressed, acceptsGzip(req), headersFor(url.pathname))
59
+ }
60
+ if (!diskPaths.has(url.pathname)) {
61
+ return undefined
62
+ }
63
+ return new Response(Bun.file(publicDir + url.pathname), {
64
+ headers: headersFor(url.pathname).base,
65
+ })
66
+ }
67
+ }
@@ -0,0 +1,109 @@
1
+ import { createLivenessWatch } from '../../shared/createLivenessWatch.ts'
2
+
3
+ /*
4
+ The reachability registry behind `abide/server/reachable`. A probe transport
5
+ and the timings are injected so the public name wires them from env + a real
6
+ HEAD while tests drive scripted outcomes on tiny intervals.
7
+
8
+ Per origin, the first read awaits one real probe (the FAITHFUL first answer —
9
+ its latency, including a full timeout when the host is down, is the price of
10
+ not guessing) and then hands the origin to a createLivenessWatch that re-probes
11
+ every `intervalMs` to keep the value warm. Every later read resolves instantly
12
+ off that warm value, fresh within one interval — the faithful cost is paid once.
13
+
14
+ The inaugural probe runs DIRECTLY, not through the watch: the watch's
15
+ failureLimit (anti-flap) is right for the ongoing poll but would make a down
16
+ host take failureLimit× the timeout to answer on the first call. The watch's
17
+ injected probe doubles as the idle reaper — a host nobody has read in `idleMs`
18
+ stops polling (stop() during the probe changes the watched url, so the watch
19
+ discards the result and never reschedules); the next read restarts it cold.
20
+ */
21
+ export function createReachable(options: {
22
+ probe: (origin: string) => Promise<boolean>
23
+ intervalMs: number
24
+ idleMs: number
25
+ }): {
26
+ reachable: (host: string | URL) => Promise<boolean>
27
+ /* Stop every origin's poll — graceful shutdown, and test isolation. */
28
+ stop: () => void
29
+ /* `using registry = createReachable(...)` — disposal stops every poll. */
30
+ [Symbol.dispose]: () => void
31
+ } {
32
+ type Entry = {
33
+ alive: boolean
34
+ /* The inaugural probe while it is still in flight; concurrent cold reads await the same one. */
35
+ inflight: Promise<boolean> | undefined
36
+ watch: ReturnType<typeof createLivenessWatch> | undefined
37
+ lastReadAt: number
38
+ }
39
+ const registry = new Map<string, Entry>()
40
+
41
+ /* The ongoing poll's probe: reap an idle origin, else run the real probe. */
42
+ function watchProbe(origin: string): Promise<boolean> {
43
+ const entry = registry.get(origin)
44
+ if (entry && Date.now() - entry.lastReadAt > options.idleMs) {
45
+ entry.watch?.stop()
46
+ registry.delete(origin)
47
+ /* Discarded — stop() moved the watched url, so the watch won't reschedule. */
48
+ return Promise.resolve(false)
49
+ }
50
+ return options.probe(origin)
51
+ }
52
+
53
+ function startWatch(entry: Entry, origin: string): void {
54
+ entry.watch = createLivenessWatch({
55
+ probe: watchProbe,
56
+ onChange: (alive) => {
57
+ entry.alive = alive
58
+ },
59
+ intervalMs: options.intervalMs,
60
+ })
61
+ entry.watch.watch(origin)
62
+ }
63
+
64
+ async function reachable(host: string | URL): Promise<boolean> {
65
+ /*
66
+ HEAD the origin root: this answers host connectivity, not endpoint
67
+ health. A bare host string defaults to https (the external-dependency
68
+ norm); an explicit http://… is honored.
69
+ */
70
+ const url =
71
+ typeof host === 'string' && !/^https?:\/\//i.test(host) ? `https://${host}` : host
72
+ const origin = new URL(url).origin
73
+ const existing = registry.get(origin)
74
+ if (existing) {
75
+ existing.lastReadAt = Date.now()
76
+ return existing.inflight ?? existing.alive
77
+ }
78
+ /* Cold: optimistic seed, but the first read awaits a real probe before returning. */
79
+ const entry: Entry = {
80
+ alive: true,
81
+ inflight: undefined,
82
+ watch: undefined,
83
+ lastReadAt: Date.now(),
84
+ }
85
+ registry.set(origin, entry)
86
+ /* A rejecting probe reads as unreachable, not a permanent wedge: without
87
+ the catch a thrown probe leaves inflight set forever (every later read
88
+ returns the rejected promise) and never starts the watch. */
89
+ entry.inflight = options
90
+ .probe(origin)
91
+ .catch(() => false)
92
+ .then((alive) => {
93
+ entry.alive = alive
94
+ entry.inflight = undefined
95
+ startWatch(entry, origin)
96
+ return alive
97
+ })
98
+ return entry.inflight
99
+ }
100
+
101
+ function stop(): void {
102
+ for (const entry of registry.values()) {
103
+ entry.watch?.stop()
104
+ }
105
+ registry.clear()
106
+ }
107
+
108
+ return { reachable, stop, [Symbol.dispose]: stop }
109
+ }
@@ -0,0 +1,127 @@
1
+ import { NO_STORE } from '../../shared/CACHE_CONTROL_VALUES.ts'
2
+ import { memoizeByKey } from '../../shared/memoizeByKey.ts'
3
+ import { NAV_HEADER } from '../../shared/NAV_HEADER.ts'
4
+ import { REMOTE_FUNCTION } from '../../shared/REMOTE_FUNCTION.ts'
5
+ import { TEXT_PLAIN } from '../../shared/TEXT_PLAIN.ts'
6
+ import type { HttpVerb } from '../../shared/types/HttpVerb.ts'
7
+ import type { RemoteFunction } from '../../shared/types/RemoteFunction.ts'
8
+ import type { Pages } from '../../ui/types/Pages.ts'
9
+ import type { RemoteRoutes } from '../rpc/types/RemoteRoutes.ts'
10
+ import { crossOriginGate } from './crossOriginGate.ts'
11
+ import type { RequestStore } from './types/RequestStore.ts'
12
+
13
+ type AnyRemoteFunction = RemoteFunction<unknown, unknown>
14
+
15
+ /* Resolves a matched route to a Response, given the request and its scope. */
16
+ type RouteHandler = (
17
+ req: Request,
18
+ pathParams: Record<string, string>,
19
+ store: RequestStore,
20
+ ) => Promise<Response>
21
+
22
+ /* Renders the page at `routeUrl` — injected so dispatch is testable without SSR. */
23
+ type RenderPage = (
24
+ routeUrl: string,
25
+ params: Record<string, string>,
26
+ store: RequestStore,
27
+ ) => Promise<Response>
28
+
29
+ /* The framework's 405 — `Allow` names the permitted verb(s), body and NO_STORE shared so the rpc and page branches can't drift. */
30
+ function methodNotAllowed(allow: string): Response {
31
+ return new Response('Method Not Allowed', {
32
+ status: 405,
33
+ headers: { Allow: allow, 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
34
+ })
35
+ }
36
+
37
+ /*
38
+ Owns route dispatch: deciding, per registered URL, whether a request hits an
39
+ rpc verb, a page render, or nothing — and the method-matching that picks the
40
+ status. Page URLs (under src/ui/pages/) serve GET/HEAD by rendering; rpc
41
+ URLs (under src/server/rpc/, `/rpc/...`) dispatch to the single declared verb,
42
+ 405 on method mismatch; an unregistered URL is 404. Page and rpc URLs are
43
+ disjoint by construction, so each route lands in exactly one branch.
44
+
45
+ `renderPage` is injected rather than built here: dispatch decisions (the
46
+ 405/404 branches and the rpc method match) are the behaviour worth testing,
47
+ and keeping the page render behind the seam lets a test exercise them with a
48
+ stub instead of booting a server. The rpc-module loader is memoised internally
49
+ so each module loads once.
50
+ */
51
+ export function createRouteDispatcher({
52
+ pages,
53
+ rpc,
54
+ renderPage,
55
+ }: {
56
+ pages: Pages
57
+ rpc: RemoteRoutes
58
+ renderPage: RenderPage
59
+ }): (routeUrl: string) => RouteHandler {
60
+ const loadRpc = memoizeByKey((url): Promise<AnyRemoteFunction | undefined> | undefined => {
61
+ const loader = rpc[url]
62
+ if (!loader) {
63
+ return undefined
64
+ }
65
+ /*
66
+ Each $rpc module has exactly one named export, validated at build
67
+ time. Pick the first REMOTE_FUNCTION-branded export — exact, so an
68
+ incidental re-export carrying method/url props can't be mistaken
69
+ for the verb.
70
+ */
71
+ return loader().then((mod) => {
72
+ for (const value of Object.values(mod)) {
73
+ if (typeof value === 'function' && REMOTE_FUNCTION in value) {
74
+ return value as AnyRemoteFunction
75
+ }
76
+ }
77
+ return undefined
78
+ })
79
+ })
80
+
81
+ return function buildRouteHandler(routeUrl: string): RouteHandler {
82
+ const hasPage = pages[routeUrl] !== undefined
83
+ const hasRpc = rpc[routeUrl] !== undefined
84
+ return async function routeHandler(req, pathParams, store) {
85
+ const method = req.method as HttpVerb
86
+ if (hasRpc) {
87
+ const fn = await loadRpc(routeUrl)
88
+ if (fn && fn.method === method) {
89
+ const forbidden = crossOriginGate(req, store.url, {
90
+ allowReadOnly: true,
91
+ optOut: fn.crossOrigin === true,
92
+ hint: 'Declare `crossOrigin: true` on the verb to accept cross-site calls.',
93
+ })
94
+ if (forbidden) {
95
+ return forbidden
96
+ }
97
+ return fn.fetch(req)
98
+ }
99
+ return methodNotAllowed(fn ? fn.method : '')
100
+ }
101
+ if (hasPage) {
102
+ if (method !== 'GET' && method !== 'HEAD') {
103
+ return methodNotAllowed('GET, HEAD')
104
+ }
105
+ /*
106
+ SPA navigation probe: the client router fetches the destination
107
+ with NAV_HEADER purely so app.handle runs (auth/redirect gating)
108
+ before it mounts the page itself. Reaching here means handle()
109
+ already passed — it called next — so a bare 204 says "cleared,
110
+ mount it client-side" without paying for a render. A redirect or
111
+ block from handle() short-circuits before next and never arrives.
112
+ */
113
+ if (req.headers.has(NAV_HEADER)) {
114
+ return new Response(null, {
115
+ status: 204,
116
+ headers: { 'Cache-Control': NO_STORE },
117
+ })
118
+ }
119
+ return renderPage(routeUrl, pathParams, store)
120
+ }
121
+ return new Response('Not Found', {
122
+ status: 404,
123
+ headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
124
+ })
125
+ }
126
+ }
127
+ }