@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,73 @@
1
+ import { pageUrlForFile } from './pageUrlForFile.ts'
2
+ import { parseRouteSegments } from './parseRouteSegments.ts'
3
+ import { writeDts } from './writeDts.ts'
4
+
5
+ /*
6
+ Walks a `[name]` / `[...rest]` route URL and returns the param shape it
7
+ declares. Catch-all segments map to `string` under their declared name —
8
+ the server's toBunRoutePattern renames Bun's `*` key back to that name
9
+ when dispatching, so the page component sees `params.rest`, not
10
+ `params['*']`.
11
+ */
12
+ function paramsForRoute(routeUrl: string): Record<string, 'string'> {
13
+ return Object.fromEntries(
14
+ parseRouteSegments(routeUrl)
15
+ .filter((segment) => segment.kind === 'param')
16
+ .map((segment) => [segment.name, 'string'] as const),
17
+ )
18
+ }
19
+
20
+ function renderParamsShape(shape: Record<string, 'string'>): string {
21
+ const keys = Object.keys(shape)
22
+ if (keys.length === 0) {
23
+ return 'Record<string, never>'
24
+ }
25
+ return `{ ${keys.map((key) => `${JSON.stringify(key)}: string`).join('; ')} }`
26
+ }
27
+
28
+ /*
29
+ Emits a `.d.ts` that augments abide's `Routes` interface with one entry per
30
+ page file in the project. Page picks this up as a discriminated union keyed
31
+ on `route`, so `if (page.route === '/media/[id]') page.params.id` is typed
32
+ automatically without consumers writing route types by hand.
33
+ The file is written to `src/.abide/routes.d.ts` so the consumer's existing
34
+ src tsconfig include picks it up with no extra configuration. The augmented
35
+ module is keyed on the name the project imports abide under (`importName`),
36
+ so the augmentation matches the consumer's `page` import whether abide is
37
+ installed directly (`abide`) or behind an alias.
38
+ */
39
+ export async function writeRoutesDts({
40
+ cwd,
41
+ pageFiles,
42
+ importName,
43
+ }: {
44
+ cwd: string
45
+ pageFiles: string[]
46
+ importName: string
47
+ }): Promise<void> {
48
+ const routes = pageFiles
49
+ .map((file) => ({
50
+ route: pageUrlForFile(file),
51
+ params: paramsForRoute(pageUrlForFile(file)),
52
+ }))
53
+ .toSorted((a, b) => a.route.localeCompare(b.route))
54
+ const entries = routes
55
+ .map(
56
+ ({ route, params }) => ` ${JSON.stringify(route)}: ${renderParamsShape(params)}`,
57
+ )
58
+ .join('\n')
59
+ /* Keys-only mirror for url()'s autocomplete (values unused — PathParams derives the shape). */
60
+ const urlKeys = routes.map(({ route }) => ` ${JSON.stringify(route)}: true`).join('\n')
61
+ const body = `declare module '${importName}/shared/page' {
62
+ interface Routes {
63
+ ${entries}
64
+ }
65
+ }
66
+
67
+ declare module '${importName}/shared/url' {
68
+ interface PageRoutes {
69
+ ${urlKeys}
70
+ }
71
+ }`
72
+ await writeDts(cwd, 'routes', body)
73
+ }
@@ -0,0 +1,49 @@
1
+ import { carriesBodyArgs } from './carriesBodyArgs.ts'
2
+ import { detectVerbMethod } from './detectVerbMethod.ts'
3
+ import { fileStem } from './fileStem.ts'
4
+ import { rpcUrlForFile } from './rpcUrlForFile.ts'
5
+ import { writeDts } from './writeDts.ts'
6
+
7
+ /*
8
+ Emits a `.d.ts` that augments abide's `RpcRoutes` interface with one entry per
9
+ query-carrying $rpc verb, so `url('/rpc/search', { q })` types its args against
10
+ the verb's own signature. Only GET/DELETE/HEAD (non-body) verbs are included —
11
+ a url() can carry a query string but not a request body, so a POST verb has no
12
+ URL form. `RpcArgs` lifts the args type out of the verb's RemoteFunction
13
+ (dropping the FormData upload variant); the file path resolves the export by
14
+ its filename, the abide one-export-per-file convention. Written to
15
+ `src/.abide/rpc.d.ts` so the consumer's src tsconfig include picks it up, keyed
16
+ on the project's abide import name like writeRoutesDts.
17
+ */
18
+ export async function writeRpcDts({
19
+ cwd,
20
+ rpcDir,
21
+ rpcFiles,
22
+ importName,
23
+ }: {
24
+ cwd: string
25
+ rpcDir: string
26
+ rpcFiles: string[]
27
+ importName: string
28
+ }): Promise<void> {
29
+ const lines = await Promise.all(
30
+ rpcFiles.map(async (file) => {
31
+ const method = detectVerbMethod(await Bun.file(`${rpcDir}/${file}`).text())
32
+ // A body verb's args can't ride a URL — leave it out of the url() rpc map.
33
+ if (!method || carriesBodyArgs(method)) {
34
+ return undefined
35
+ }
36
+ const importPath = `../server/rpc/${file}`
37
+ return ` ${JSON.stringify(rpcUrlForFile(file))}: RpcArgs<typeof import(${JSON.stringify(importPath)}).${fileStem(file)}>`
38
+ }),
39
+ )
40
+ const entries = lines.filter((line) => line !== undefined).toSorted()
41
+ const body = `type RpcArgs<Fn> = Fn extends (args: infer Args) => unknown ? Exclude<Args, FormData> : never
42
+
43
+ declare module '${importName}/shared/url' {
44
+ interface RpcRoutes {
45
+ ${entries.join('\n')}
46
+ }
47
+ }`
48
+ await writeDts(cwd, 'rpc', body)
49
+ }
@@ -0,0 +1,45 @@
1
+ import { commandNameForUrl } from './commandNameForUrl.ts'
2
+ import { fileStem } from './fileStem.ts'
3
+ import { rpcUrlForFile } from './rpcUrlForFile.ts'
4
+ import { writeDts } from './writeDts.ts'
5
+
6
+ /*
7
+ Emits a `.d.ts` that augments createTestApp's `RpcClient` interface with one
8
+ entry per $rpc verb, keyed by command name (the same key `app.rpc.<name>`
9
+ resolves at runtime). Each entry lifts the verb's args + resolved return out of
10
+ its RemoteFunction so `app.rpc.getProduct({ id })` types against the verb's own
11
+ signature — args in, decoded body out, plus `.raw` for the Response. `RpcArgs`
12
+ drops the FormData upload variant exactly as writeRpcDts does; `RpcReturn`
13
+ reads the resolved body type. Written to `src/.abide/testRpc.d.ts` so the
14
+ consumer's src tsconfig include picks it up, keyed on the project's abide
15
+ import name.
16
+ */
17
+ export async function writeTestRpcDts({
18
+ cwd,
19
+ rpcFiles,
20
+ importName,
21
+ }: {
22
+ cwd: string
23
+ rpcFiles: string[]
24
+ importName: string
25
+ }): Promise<void> {
26
+ const entries = rpcFiles
27
+ .map((file) => {
28
+ const name = commandNameForUrl(rpcUrlForFile(file))
29
+ const importPath = `../server/rpc/${file}`
30
+ return ` ${JSON.stringify(name)}: RpcInvoker<typeof import(${JSON.stringify(importPath)}).${fileStem(file)}>`
31
+ })
32
+ .toSorted()
33
+ const body = `type RpcArgs<Fn> = Fn extends (args: infer Args) => unknown ? Exclude<Args, FormData> : never
34
+ type RpcReturn<Fn> = Fn extends (...args: never[]) => Promise<infer Return> ? Return : never
35
+ type RpcInvoker<Fn> = ((args?: RpcArgs<Fn>) => Promise<RpcReturn<Fn>>) & {
36
+ raw: (args?: RpcArgs<Fn>) => Promise<Response>
37
+ }
38
+
39
+ declare module '${importName}/test/createTestApp' {
40
+ interface RpcClient {
41
+ ${entries.join('\n')}
42
+ }
43
+ }`
44
+ await writeDts(cwd, 'testRpc', body)
45
+ }
@@ -0,0 +1,34 @@
1
+ import { fileStem } from './fileStem.ts'
2
+ import { socketNameForFile } from './socketNameForFile.ts'
3
+ import { writeDts } from './writeDts.ts'
4
+
5
+ /*
6
+ Emits a `.d.ts` that augments createTestApp's `SocketClient` interface with one
7
+ entry per $socket, keyed by socket name (the same key `app.sockets.<name>`
8
+ resolves at runtime). The `socket(...)` helper statically returns `Socket<T>`,
9
+ so each entry is the export's own type directly — `app.sockets.chat` types as
10
+ `Socket<ChatMessage>`, iterable for the live stream with `.tail`/`.publish`.
11
+ Written to `src/.abide/testSockets.d.ts` like its rpc sibling.
12
+ */
13
+ export async function writeTestSocketsDts({
14
+ cwd,
15
+ socketFiles,
16
+ importName,
17
+ }: {
18
+ cwd: string
19
+ socketFiles: string[]
20
+ importName: string
21
+ }): Promise<void> {
22
+ const entries = socketFiles
23
+ .map((file) => {
24
+ const importPath = `../server/sockets/${file}`
25
+ return ` ${JSON.stringify(socketNameForFile(file))}: typeof import(${JSON.stringify(importPath)}).${fileStem(file)}`
26
+ })
27
+ .toSorted()
28
+ const body = `declare module '${importName}/test/createTestApp' {
29
+ interface SocketClient {
30
+ ${entries.join('\n')}
31
+ }
32
+ }`
33
+ await writeDts(cwd, 'testSockets', body)
34
+ }
@@ -0,0 +1,73 @@
1
+ import type { AgentFrame } from '../server/agent.ts'
2
+
3
+ /*
4
+ Collects an engine's frame stream and asserts the neutral AgentFrame contract
5
+ every provider engine must satisfy, throwing a plain Error (test-framework
6
+ agnostic) on the first violation:
7
+
8
+ - the stream ends with exactly one `done` frame and yields nothing after it
9
+ - every `tool_use` is answered by exactly one `tool_result` carrying the
10
+ same id and name, in use-then-result order
11
+ - no `tool_result` arrives for an unannounced id
12
+ - text deltas are strings
13
+
14
+ Returns the collected frames plus the `done` frame so a scenario can layer
15
+ its provider-specific assertions on top. This is the conformance seam: one
16
+ suite of invariants, N engine adapters run against it.
17
+ */
18
+ // @readme plumbing
19
+ export async function assertAgentFrameConformance(
20
+ stream: AsyncIterable<AgentFrame>,
21
+ ): Promise<{ frames: AgentFrame[]; done: Extract<AgentFrame, { type: 'done' }> }> {
22
+ const frames: AgentFrame[] = []
23
+ for await (const frame of stream) {
24
+ frames.push(frame)
25
+ }
26
+ if (frames.length === 0) {
27
+ throw new Error('conformance: engine yielded no frames — expected at least a done frame')
28
+ }
29
+
30
+ const doneIndexes = frames.flatMap((frame, index) => (frame.type === 'done' ? [index] : []))
31
+ if (doneIndexes.length !== 1) {
32
+ throw new Error(`conformance: expected exactly one done frame, saw ${doneIndexes.length}`)
33
+ }
34
+ if (doneIndexes[0] !== frames.length - 1) {
35
+ throw new Error(
36
+ `conformance: frames continued after done (done at ${doneIndexes[0]} of ${frames.length - 1})`,
37
+ )
38
+ }
39
+
40
+ const openToolUses = new Map<string, string>()
41
+ for (const [index, frame] of frames.entries()) {
42
+ if (frame.type === 'text' && typeof frame.delta !== 'string') {
43
+ throw new Error(`conformance: text frame at ${index} has a non-string delta`)
44
+ }
45
+ if (frame.type === 'tool_use') {
46
+ if (openToolUses.has(frame.id)) {
47
+ throw new Error(`conformance: duplicate tool_use id ${frame.id} at ${index}`)
48
+ }
49
+ openToolUses.set(frame.id, frame.name)
50
+ }
51
+ if (frame.type === 'tool_result') {
52
+ const expectedName = openToolUses.get(frame.id)
53
+ if (expectedName === undefined) {
54
+ throw new Error(
55
+ `conformance: tool_result at ${index} answers unannounced id ${frame.id}`,
56
+ )
57
+ }
58
+ if (frame.name !== expectedName) {
59
+ throw new Error(
60
+ `conformance: tool_result at ${index} names ${frame.name}, tool_use said ${expectedName}`,
61
+ )
62
+ }
63
+ openToolUses.delete(frame.id)
64
+ }
65
+ }
66
+ if (openToolUses.size > 0) {
67
+ const unanswered = Array.from(openToolUses.keys()).join(', ')
68
+ throw new Error(`conformance: tool_use without a tool_result: ${unanswered}`)
69
+ }
70
+
71
+ const done = frames[frames.length - 1] as Extract<AgentFrame, { type: 'done' }>
72
+ return { frames, done }
73
+ }
@@ -0,0 +1,45 @@
1
+ import type { ToolResult } from '../mcp/mcpSurface.ts'
2
+ import type { AgentSurface } from '../server/agent.ts'
3
+
4
+ type ScriptedTool = {
5
+ name: string
6
+ description?: string
7
+ inputSchema?: Record<string, unknown>
8
+ /* Result handed back to the engine; throw to simulate a failed dispatch. */
9
+ result: (args: Record<string, unknown> | undefined) => ToolResult
10
+ }
11
+
12
+ type RecordedCall = { name: string; args: Record<string, unknown> | undefined }
13
+
14
+ /*
15
+ A scripted AgentSurface for engine tests: declarative tool stubs in, an MCP
16
+ surface out, with every `call` recorded so a test can assert exactly which
17
+ tools an engine dispatched and with what arguments. Prompts and resources are
18
+ empty — engines must tolerate an app exposing none.
19
+ */
20
+ // @readme plumbing
21
+ export function createScriptedSurface(
22
+ tools: ScriptedTool[] = [],
23
+ ): AgentSurface & { calls: RecordedCall[] } {
24
+ const calls: RecordedCall[] = []
25
+ return {
26
+ calls,
27
+ tools: tools.map((tool) => ({
28
+ name: tool.name,
29
+ description: tool.description ?? tool.name,
30
+ inputSchema: tool.inputSchema ?? { type: 'object' },
31
+ })),
32
+ async call(name, args) {
33
+ calls.push({ name, args })
34
+ const tool = tools.find((candidate) => candidate.name === name)
35
+ if (!tool) {
36
+ return { content: [{ type: 'text', text: `unknown tool: ${name}` }], isError: true }
37
+ }
38
+ return tool.result(args)
39
+ },
40
+ prompts: [],
41
+ getPrompt: () => [],
42
+ listResources: async () => [],
43
+ readResource: async () => undefined,
44
+ }
45
+ }
@@ -0,0 +1,203 @@
1
+ import type { Server } from 'bun'
2
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
3
+ import * as appMod from '../../_virtual/app.ts'
4
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
5
+ import { appInfo } from '../../_virtual/app-info.ts'
6
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
7
+ import { assets } from '../../_virtual/assets.ts'
8
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
9
+ import cliProgramName from '../../_virtual/cli-name.ts'
10
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
11
+ import { layouts } from '../../_virtual/layouts.ts'
12
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
13
+ import mcp from '../../_virtual/mcp.ts'
14
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
15
+ import { mcpResources } from '../../_virtual/mcp-resources.ts'
16
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
17
+ import { pages } from '../../_virtual/pages.ts'
18
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
19
+ import { prompts } from '../../_virtual/prompts.ts'
20
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
21
+ import { publicAssets } from '../../_virtual/public-assets.ts'
22
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
23
+ import { rpc } from '../../_virtual/rpc.ts'
24
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
25
+ import { shell } from '../../_virtual/shell.ts'
26
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
27
+ import { sockets } from '../../_virtual/sockets.ts'
28
+ import { verbRegistry } from '../server/rpc/verbRegistry.ts'
29
+ import { createServer } from '../server/runtime/createServer.ts'
30
+ import { ensureRegistriesLoaded } from '../server/runtime/registryManifests.ts'
31
+ import { requestContext } from '../server/runtime/requestContext.ts'
32
+ import { resolvePageSnapshot } from '../server/runtime/resolvePageSnapshot.ts'
33
+ import { serverSlot } from '../server/runtime/serverSlot.ts'
34
+ import type { Socket } from '../server/sockets/types/Socket.ts'
35
+ import { baseSlot } from '../shared/baseSlot.ts'
36
+ import { buildRpcProxy } from '../shared/buildRpcProxy.ts'
37
+ import { buildRpcRequest } from '../shared/buildRpcRequest.ts'
38
+ import { cacheStoreSlot } from '../shared/cacheStoreSlot.ts'
39
+ import { commandNameForUrl } from '../shared/commandNameForUrl.ts'
40
+ import { createCacheStore } from '../shared/createCacheStore.ts'
41
+ import { globalCacheStoreSlot } from '../shared/globalCacheStoreSlot.ts'
42
+ import { HEALTH_PATH } from '../shared/HEALTH_PATH.ts'
43
+ import { pageSlot } from '../shared/pageSlot.ts'
44
+ import { SOCKETS_PATH } from '../shared/SOCKETS_PATH.ts'
45
+ import type { RemoteFunction } from '../shared/types/RemoteFunction.ts'
46
+ import { createTestSocketChannel } from './createTestSocketChannel.ts'
47
+
48
+ /*
49
+ Augmentable verb/socket maps for `app.rpc.<verb>` / `app.sockets.<name>`. The
50
+ build's writeTestRpcDts / writeTestSocketsDts emit one entry per verb/socket
51
+ (into src/.abide/), so the keys + signatures are the project's real surface
52
+ with no imports. Empty here; types arrive once the app has been built. Mirrors
53
+ url's RpcRoutes / health's AppHealthMap.
54
+ */
55
+ // @readme testing
56
+ // biome-ignore lint/suspicious/noEmptyInterface: augmented by the generated testRpc.d.ts
57
+ export interface RpcClient {}
58
+ // biome-ignore lint/suspicious/noEmptyInterface: augmented by the generated testSockets.d.ts
59
+ export interface SocketClient {}
60
+
61
+ /* The booted app under test. Every named subsystem is reachable as the verb
62
+ you call, the socket you iterate, or a path you fetch — over the real
63
+ server, so the full pipeline (CSRF, cookies, base path) runs. */
64
+ export type TestApp = {
65
+ /* The kernel-assigned origin, e.g. http://localhost:51234. */
66
+ origin: string
67
+ /* fetch against the app: prefixes the kernel-assigned origin, so you pass a
68
+ route-space path (`/products/1`), not the wire URL. The booted server
69
+ matches routes at raw paths — the APP_URL mount base is stripped by an
70
+ external proxy in production, absent here — so paths carry no base. */
71
+ fetch: (path: string, init?: RequestInit) => Promise<Response>
72
+ /* Verb calls over HTTP, keyed by command name: `app.rpc.getProduct({ id })`. */
73
+ rpc: RpcClient
74
+ /* Sockets keyed by name: `app.sockets.ticker` is the Socket — iterate it for
75
+ the live stream, `.tail(n)` to seed, `.publish(m)` to send. */
76
+ sockets: SocketClient
77
+ /* The /__abide/health payload, decoded. */
78
+ health: () => Promise<unknown>
79
+ /* Stops the server, releases the port, restores every touched slot. */
80
+ stop: () => Promise<void>
81
+ /* `await using app = await createTestApp()` — disposal runs stop(), so a
82
+ thrown assertion still releases the port and restores the slots rather
83
+ than leaking the request-scope/cache/page resolvers into the next file. */
84
+ [Symbol.asyncDispose]: () => Promise<void>
85
+ }
86
+
87
+ /*
88
+ Boots the real app on an ephemeral port — the same wiring serverEntry performs,
89
+ minus the standalone-binary env layers. Imports the framework's virtual
90
+ manifests (resolved by abideResolverPlugin, registered via `abide/preload`
91
+ in the consumer's bunfig), so the routes, verbs, and sockets are the project's
92
+ real surface, not a fixture. Pass nothing: `await createTestApp()` is the app
93
+ exactly as `bun start` would serve it.
94
+
95
+ Slots are saved and restored around the boot so a suite tears down without
96
+ leaking the request-scope/cache/page resolvers into the next test file.
97
+ */
98
+ export async function createTestApp(): Promise<TestApp> {
99
+ const previous = {
100
+ cacheResolver: cacheStoreSlot.resolver,
101
+ globalResolver: globalCacheStoreSlot.resolver,
102
+ pageResolver: pageSlot.resolver,
103
+ baseResolver: baseSlot.resolver,
104
+ activeServer: serverSlot.active,
105
+ }
106
+
107
+ cacheStoreSlot.resolver = () => requestContext.getStore()?.cache
108
+ const globalStore = createCacheStore()
109
+ globalCacheStoreSlot.resolver = () => globalStore
110
+ pageSlot.resolver = resolvePageSnapshot
111
+
112
+ /* Eager env validation, exactly as serverEntry: a top-level env(schema) in
113
+ src/server/config.ts fails the boot loudly here rather than lazily. No-op
114
+ when the file is absent. */
115
+ // @ts-expect-error virtual module resolved by abideResolverPlugin
116
+ await import('../../_virtual/config.ts')
117
+
118
+ const server: Server<unknown> = await createServer({
119
+ pages,
120
+ layouts,
121
+ rpc,
122
+ sockets,
123
+ prompts,
124
+ shell,
125
+ app: appMod,
126
+ assets,
127
+ publicAssets,
128
+ mcpResources,
129
+ mcp,
130
+ cliProgramName,
131
+ appInfo,
132
+ port: 0,
133
+ })
134
+
135
+ const origin = `http://localhost:${server.port}`
136
+
137
+ function appFetch(path: string, init?: RequestInit): Promise<Response> {
138
+ return fetch(`${origin}${path}`, init)
139
+ }
140
+
141
+ /* Verb modules loaded once so the registry holds every RemoteFunction; the
142
+ proxy maps command name → an HTTP call against the booted server. */
143
+ await ensureRegistriesLoaded()
144
+ const remotes = new Map<string, RemoteFunction<unknown, unknown>>(
145
+ Array.from(verbRegistry.values()).map((entry) => [
146
+ commandNameForUrl(entry.remote.url),
147
+ entry.remote,
148
+ ]),
149
+ )
150
+
151
+ function send(remote: RemoteFunction<unknown, unknown>, args: unknown): Promise<Response> {
152
+ /* Same-origin Origin header so the CSRF gate admits mutating verbs; the
153
+ server serves verbs at their raw url (no mount base applied here). */
154
+ const request = buildRpcRequest({
155
+ method: remote.method,
156
+ url: remote.url,
157
+ args,
158
+ baseUrl: `${origin}/`,
159
+ headers: new Headers({ origin }),
160
+ })
161
+ return fetch(request)
162
+ }
163
+
164
+ const rpcClient = buildRpcProxy<RpcClient>((name) => {
165
+ const remote = remotes.get(name)
166
+ return remote ? (args) => send(remote, args) : undefined
167
+ })
168
+
169
+ /* One ws to the booted multiplex, dialed lazily on first socket access so a
170
+ suite touching no socket holds no connection. http→ws, raw path. */
171
+ const wsUrl = `${origin.replace(/^http/, 'ws')}${SOCKETS_PATH}`
172
+ let channel: ReturnType<typeof createTestSocketChannel> | undefined
173
+ const socketNames = new Set(Object.keys(sockets as Record<string, unknown>))
174
+ const socketClient = new Proxy({} as Record<string, Socket<unknown>>, {
175
+ get(_target, prop): Socket<unknown> | undefined {
176
+ if (typeof prop !== 'string' || !socketNames.has(prop)) {
177
+ return undefined
178
+ }
179
+ channel ??= createTestSocketChannel(wsUrl)
180
+ return channel.socket(prop)
181
+ },
182
+ })
183
+
184
+ async function stop(): Promise<void> {
185
+ channel?.close()
186
+ server.stop(true)
187
+ cacheStoreSlot.resolver = previous.cacheResolver
188
+ globalCacheStoreSlot.resolver = previous.globalResolver
189
+ pageSlot.resolver = previous.pageResolver
190
+ baseSlot.resolver = previous.baseResolver
191
+ serverSlot.active = previous.activeServer
192
+ }
193
+
194
+ return {
195
+ origin,
196
+ fetch: appFetch,
197
+ rpc: rpcClient,
198
+ sockets: socketClient as unknown as SocketClient,
199
+ health: () => appFetch(HEALTH_PATH).then((response) => response.json()),
200
+ stop,
201
+ [Symbol.asyncDispose]: stop,
202
+ }
203
+ }
@@ -0,0 +1,142 @@
1
+ import type { Socket } from '../server/sockets/types/Socket.ts'
2
+ import type { SocketClientFrame } from '../server/sockets/types/SocketClientFrame.ts'
3
+ import type { SocketServerFrame } from '../server/sockets/types/SocketServerFrame.ts'
4
+ import { buildSocketOverChannel } from '../shared/buildSocketOverChannel.ts'
5
+ import type { SocketChannel } from '../shared/types/SocketChannel.ts'
6
+ import type { SocketSubCallbacks } from '../shared/types/SocketSubCallbacks.ts'
7
+
8
+ /*
9
+ Test-side substitute for the browser socketChannel: one ws to the booted
10
+ server's multiplex, speaking the same SocketClientFrame/SocketServerFrame
11
+ protocol. Stripped of the browser channel's reconnect/backoff/visibility
12
+ machinery — a test owns the connection lifecycle through `close()`, so a drop
13
+ is teardown, not something to recover from. Frames sent before the ws opens
14
+ queue and flush on open, the one piece of timing a test can't sidestep.
15
+
16
+ Implements SocketChannel (subscribe/unsubscribe/publish), so `socket(name)`
17
+ hands its sockets to the same buildSocketOverChannel the browser socketProxy
18
+ uses — the Socket<T> surface can't drift between the test path and production.
19
+ */
20
+ export function createTestSocketChannel(wsUrl: string): {
21
+ socket: <T>(name: string) => Socket<T>
22
+ close: () => void
23
+ /* `using channel = createTestSocketChannel(url)` — disposal closes the ws. */
24
+ [Symbol.dispose]: () => void
25
+ } {
26
+ const subs = new Map<string, { socket: string; callbacks: SocketSubCallbacks }>()
27
+ const subsBySocket = new Map<string, Set<string>>()
28
+ let pendingSends: string[] = []
29
+
30
+ const ws = new WebSocket(wsUrl)
31
+
32
+ function flushPending(): void {
33
+ if (ws.readyState !== WebSocket.OPEN) {
34
+ return
35
+ }
36
+ for (const message of pendingSends) {
37
+ ws.send(message)
38
+ }
39
+ pendingSends = []
40
+ }
41
+
42
+ function send(frame: SocketClientFrame): void {
43
+ const message = JSON.stringify(frame)
44
+ if (ws.readyState === WebSocket.OPEN) {
45
+ ws.send(message)
46
+ return
47
+ }
48
+ pendingSends.push(message)
49
+ }
50
+
51
+ function dropSub(id: string): void {
52
+ const entry = subs.get(id)
53
+ if (!entry) {
54
+ return
55
+ }
56
+ subs.delete(id)
57
+ const set = subsBySocket.get(entry.socket)
58
+ if (set) {
59
+ set.delete(id)
60
+ if (set.size === 0) {
61
+ subsBySocket.delete(entry.socket)
62
+ }
63
+ }
64
+ }
65
+
66
+ ws.addEventListener('open', flushPending)
67
+ ws.addEventListener('message', (event) => {
68
+ let frame: SocketServerFrame
69
+ try {
70
+ frame = JSON.parse(event.data as string) as SocketServerFrame
71
+ } catch {
72
+ return
73
+ }
74
+ if (frame.type === 'msg') {
75
+ const targets = subsBySocket.get(frame.socket)
76
+ if (!targets) {
77
+ return
78
+ }
79
+ for (const subId of targets) {
80
+ subs.get(subId)?.callbacks.onMessage(frame.message)
81
+ }
82
+ return
83
+ }
84
+ if (frame.type === 'replay') {
85
+ subs.get(frame.sub)?.callbacks.onReplay(frame.messages)
86
+ return
87
+ }
88
+ const sub = subs.get(frame.sub)
89
+ if (!sub) {
90
+ return
91
+ }
92
+ dropSub(frame.sub)
93
+ if (frame.type === 'end') {
94
+ sub.callbacks.onEnd()
95
+ } else {
96
+ sub.callbacks.onError(frame.message)
97
+ }
98
+ })
99
+ /* A drop after subs are live is unexpected; surface it so iterators unblock
100
+ instead of awaiting a frame that never comes. Idempotent — the first of
101
+ error/close clears subs, the second finds none. error covers a failed
102
+ handshake (no open, no clean close) that close alone would miss. */
103
+ function disconnectAll(): void {
104
+ const active = [...subs.values()]
105
+ subs.clear()
106
+ subsBySocket.clear()
107
+ for (const sub of active) {
108
+ sub.callbacks.onDisconnect()
109
+ }
110
+ }
111
+ ws.addEventListener('close', disconnectAll)
112
+ ws.addEventListener('error', disconnectAll)
113
+
114
+ const channel: SocketChannel = {
115
+ subscribe(id, socket, replay, callbacks) {
116
+ subs.set(id, { socket, callbacks })
117
+ let set = subsBySocket.get(socket)
118
+ if (!set) {
119
+ set = new Set()
120
+ subsBySocket.set(socket, set)
121
+ }
122
+ set.add(id)
123
+ send({ type: 'sub', sub: id, socket, replay })
124
+ },
125
+ unsubscribe(id) {
126
+ if (!subs.has(id)) {
127
+ return
128
+ }
129
+ dropSub(id)
130
+ send({ type: 'unsub', sub: id })
131
+ },
132
+ publish: (socket, message) => send({ type: 'pub', socket, message }),
133
+ }
134
+
135
+ /* Same Socket<T> builder the browser proxy uses, over this test channel. */
136
+ function socket<T>(name: string): Socket<T> {
137
+ return buildSocketOverChannel<T>(name, () => channel)
138
+ }
139
+
140
+ const close = () => ws.close()
141
+ return { socket, close, [Symbol.dispose]: close }
142
+ }