@abide/abide 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/CHANGELOG.md +607 -0
  2. package/LICENSE +21 -0
  3. package/README.md +154 -0
  4. package/bin/abide.ts +212 -0
  5. package/package.json +155 -0
  6. package/src/abideLsp.ts +211 -0
  7. package/src/abideModules.d.ts +8 -0
  8. package/src/abideResolverPlugin.ts +923 -0
  9. package/src/appEntry.ts +151 -0
  10. package/src/assets/app.html +12 -0
  11. package/src/build.ts +143 -0
  12. package/src/buildCli.ts +127 -0
  13. package/src/buildDisconnected.ts +118 -0
  14. package/src/bundleApp.ts +147 -0
  15. package/src/bundleDisconnectedEntry.ts +14 -0
  16. package/src/checkAbide.ts +77 -0
  17. package/src/cliEntry.ts +25 -0
  18. package/src/clientBuildPlugins.ts +33 -0
  19. package/src/clientEntry.ts +17 -0
  20. package/src/compile.ts +63 -0
  21. package/src/controlServerWorker.ts +426 -0
  22. package/src/devEntry.ts +250 -0
  23. package/src/discoveryEntry.ts +81 -0
  24. package/src/lib/bundle/BundleMenu.ts +12 -0
  25. package/src/lib/bundle/BundleMenuItem.ts +25 -0
  26. package/src/lib/bundle/BundleWindow.ts +37 -0
  27. package/src/lib/bundle/WEBVIEW_BUILD_REVISION.ts +9 -0
  28. package/src/lib/bundle/WEBVIEW_VERSION.ts +7 -0
  29. package/src/lib/bundle/bindConnectedFlag.ts +29 -0
  30. package/src/lib/bundle/bindRequestNavigate.ts +34 -0
  31. package/src/lib/bundle/buildWebviewLib.ts +111 -0
  32. package/src/lib/bundle/bundled.ts +35 -0
  33. package/src/lib/bundle/disconnected.abide +236 -0
  34. package/src/lib/bundle/disconnected.css +9 -0
  35. package/src/lib/bundle/ensureWebviewLib.ts +20 -0
  36. package/src/lib/bundle/exitWithParent.ts +28 -0
  37. package/src/lib/bundle/infoPlist.ts +46 -0
  38. package/src/lib/bundle/installDownloads.ts +24 -0
  39. package/src/lib/bundle/installMacMenu.ts +39 -0
  40. package/src/lib/bundle/listenLocalControlServer.ts +19 -0
  41. package/src/lib/bundle/native/abideMenu.mm +422 -0
  42. package/src/lib/bundle/native/webview.h +4557 -0
  43. package/src/lib/bundle/onMenu.ts +42 -0
  44. package/src/lib/bundle/openWebview.ts +104 -0
  45. package/src/lib/bundle/pngToIcns.ts +47 -0
  46. package/src/lib/bundle/probeAbideServer.ts +57 -0
  47. package/src/lib/bundle/resolveServerBinary.ts +12 -0
  48. package/src/lib/bundle/resolveWebviewLib.ts +53 -0
  49. package/src/lib/bundle/serverBinaryFilename.ts +8 -0
  50. package/src/lib/bundle/signMacApp.ts +37 -0
  51. package/src/lib/bundle/spawnEmbeddedServer.ts +64 -0
  52. package/src/lib/bundle/stableLocalPort.ts +19 -0
  53. package/src/lib/bundle/waitForServer.ts +23 -0
  54. package/src/lib/bundle/webviewCachePath.ts +23 -0
  55. package/src/lib/bundle/webviewLibName.ts +11 -0
  56. package/src/lib/cli/connectToServer.ts +23 -0
  57. package/src/lib/cli/createClient.ts +108 -0
  58. package/src/lib/cli/dispatchCommand.ts +71 -0
  59. package/src/lib/cli/loadEnvFromBinaryDir.ts +15 -0
  60. package/src/lib/cli/parseArgvForRpc.ts +100 -0
  61. package/src/lib/cli/printHelp.ts +119 -0
  62. package/src/lib/cli/printSessionHelp.ts +27 -0
  63. package/src/lib/cli/printSessionStatus.ts +21 -0
  64. package/src/lib/cli/printTrimmed.ts +8 -0
  65. package/src/lib/cli/printValue.ts +10 -0
  66. package/src/lib/cli/resolveCliTarget.ts +48 -0
  67. package/src/lib/cli/runCli.ts +176 -0
  68. package/src/lib/cli/runSession.ts +108 -0
  69. package/src/lib/cli/startLocalInstance.ts +14 -0
  70. package/src/lib/cli/tokenizeLine.ts +51 -0
  71. package/src/lib/cli/types/CliManifest.ts +9 -0
  72. package/src/lib/cli/types/CliManifestEntry.ts +17 -0
  73. package/src/lib/cli/types/CliTarget.ts +13 -0
  74. package/src/lib/mcp/annotationsForMethod.ts +29 -0
  75. package/src/lib/mcp/createMcpResourceServer.ts +102 -0
  76. package/src/lib/mcp/createMcpServer.ts +48 -0
  77. package/src/lib/mcp/dispatchMcpRequest.ts +138 -0
  78. package/src/lib/mcp/mcpResourceServerSlot.ts +18 -0
  79. package/src/lib/mcp/mcpSurface.ts +295 -0
  80. package/src/lib/mcp/toolResultFromResponse.ts +66 -0
  81. package/src/lib/mcp/types/JsonRpcRequest.ts +12 -0
  82. package/src/lib/mcp/types/JsonRpcResponse.ts +20 -0
  83. package/src/lib/mcp/types/McpResourceContents.ts +10 -0
  84. package/src/lib/mcp/types/McpResourceDescriptor.ts +6 -0
  85. package/src/lib/mcp/types/McpResourceServer.ts +12 -0
  86. package/src/lib/mcp/types/McpServer.ts +9 -0
  87. package/src/lib/mcp/types/McpServerOptions.ts +16 -0
  88. package/src/lib/server/AppModule.ts +47 -0
  89. package/src/lib/server/DELETE.ts +10 -0
  90. package/src/lib/server/GET.ts +10 -0
  91. package/src/lib/server/HEAD.ts +10 -0
  92. package/src/lib/server/PATCH.ts +10 -0
  93. package/src/lib/server/POST.ts +10 -0
  94. package/src/lib/server/PUT.ts +10 -0
  95. package/src/lib/server/agent.ts +86 -0
  96. package/src/lib/server/appDataDir.ts +16 -0
  97. package/src/lib/server/cli/buildEnvContent.ts +19 -0
  98. package/src/lib/server/cli/createTarGz.ts +77 -0
  99. package/src/lib/server/cli/handleCliDownload.ts +150 -0
  100. package/src/lib/server/cli/handleCliInstall.ts +37 -0
  101. package/src/lib/server/cli/installScript.ts +31 -0
  102. package/src/lib/server/cli/maxSourceMtime.ts +26 -0
  103. package/src/lib/server/cookies.ts +30 -0
  104. package/src/lib/server/env.ts +51 -0
  105. package/src/lib/server/error.ts +73 -0
  106. package/src/lib/server/json.ts +42 -0
  107. package/src/lib/server/jsonl.ts +47 -0
  108. package/src/lib/server/prompts/definePrompt.ts +21 -0
  109. package/src/lib/server/prompts/promptRegistry.ts +9 -0
  110. package/src/lib/server/prompts/registerPrompt.ts +6 -0
  111. package/src/lib/server/prompts/renderPromptTemplate.ts +17 -0
  112. package/src/lib/server/prompts/types/Prompt.ts +13 -0
  113. package/src/lib/server/prompts/types/PromptOptions.ts +12 -0
  114. package/src/lib/server/prompts/types/PromptRegistryEntry.ts +13 -0
  115. package/src/lib/server/prompts/types/PromptRoutes.ts +10 -0
  116. package/src/lib/server/reachable.ts +45 -0
  117. package/src/lib/server/redirect.ts +43 -0
  118. package/src/lib/server/request.ts +19 -0
  119. package/src/lib/server/rpc/defineVerb.ts +210 -0
  120. package/src/lib/server/rpc/dispatchVerbInProcess.ts +46 -0
  121. package/src/lib/server/rpc/findVerbByCommandName.ts +18 -0
  122. package/src/lib/server/rpc/parseArgs.ts +127 -0
  123. package/src/lib/server/rpc/readBodyWithinLimit.ts +44 -0
  124. package/src/lib/server/rpc/registerVerb.ts +6 -0
  125. package/src/lib/server/rpc/runWithVerbTimeout.ts +49 -0
  126. package/src/lib/server/rpc/types/RemoteHandler.ts +27 -0
  127. package/src/lib/server/rpc/types/RemoteRoutes.ts +13 -0
  128. package/src/lib/server/rpc/types/TypedResponse.ts +18 -0
  129. package/src/lib/server/rpc/types/VerbHelper.ts +87 -0
  130. package/src/lib/server/rpc/types/VerbRegistryEntry.ts +35 -0
  131. package/src/lib/server/rpc/unprocessed.ts +14 -0
  132. package/src/lib/server/rpc/verbRegistry.ts +11 -0
  133. package/src/lib/server/runtime/DEFAULT_PORT.ts +6 -0
  134. package/src/lib/server/runtime/DEV_READY_MESSAGE.ts +6 -0
  135. package/src/lib/server/runtime/DEV_REBUILD_MESSAGE.ts +4 -0
  136. package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +107 -0
  137. package/src/lib/server/runtime/SSR_SWAP_SCRIPT.ts +16 -0
  138. package/src/lib/server/runtime/acceptsGzip.ts +24 -0
  139. package/src/lib/server/runtime/buildCacheSnapshot.ts +61 -0
  140. package/src/lib/server/runtime/buildHealthPayload.ts +34 -0
  141. package/src/lib/server/runtime/buildInspectorSurface.ts +37 -0
  142. package/src/lib/server/runtime/buildOpenApiSpec.ts +106 -0
  143. package/src/lib/server/runtime/cacheControlForAsset.ts +22 -0
  144. package/src/lib/server/runtime/containsTraversal.ts +37 -0
  145. package/src/lib/server/runtime/createAppAssetServer.ts +76 -0
  146. package/src/lib/server/runtime/createAssetHeaderCache.ts +31 -0
  147. package/src/lib/server/runtime/createPublicAssetServer.ts +67 -0
  148. package/src/lib/server/runtime/createReachable.ts +109 -0
  149. package/src/lib/server/runtime/createRouteDispatcher.ts +127 -0
  150. package/src/lib/server/runtime/createServer.ts +674 -0
  151. package/src/lib/server/runtime/createUiPageRenderer.ts +181 -0
  152. package/src/lib/server/runtime/crossOriginForbidden.ts +17 -0
  153. package/src/lib/server/runtime/crossOriginGate.ts +29 -0
  154. package/src/lib/server/runtime/devClientFingerprint.ts +117 -0
  155. package/src/lib/server/runtime/devHotModuleResponse.ts +40 -0
  156. package/src/lib/server/runtime/devReloadResponse.ts +41 -0
  157. package/src/lib/server/runtime/disableIdleTimeoutForStream.ts +27 -0
  158. package/src/lib/server/runtime/envSchemaStore.ts +15 -0
  159. package/src/lib/server/runtime/findOpenPort.ts +21 -0
  160. package/src/lib/server/runtime/getActiveServer.ts +6 -0
  161. package/src/lib/server/runtime/globToPathSet.ts +29 -0
  162. package/src/lib/server/runtime/gzipResponse.ts +46 -0
  163. package/src/lib/server/runtime/inProcessServer.ts +20 -0
  164. package/src/lib/server/runtime/internalErrorResponse.ts +25 -0
  165. package/src/lib/server/runtime/isCrossOriginRequest.ts +23 -0
  166. package/src/lib/server/runtime/listenOnOpenPort.ts +36 -0
  167. package/src/lib/server/runtime/logExposedSurfaces.ts +156 -0
  168. package/src/lib/server/runtime/maybeMountInspector.ts +97 -0
  169. package/src/lib/server/runtime/mimeForExtension.ts +14 -0
  170. package/src/lib/server/runtime/pageUrlFromStore.ts +15 -0
  171. package/src/lib/server/runtime/parseIdleTimeout.ts +10 -0
  172. package/src/lib/server/runtime/parsePort.ts +11 -0
  173. package/src/lib/server/runtime/registryManifests.ts +66 -0
  174. package/src/lib/server/runtime/requestContext.ts +5 -0
  175. package/src/lib/server/runtime/resolvePageSnapshot.ts +25 -0
  176. package/src/lib/server/runtime/respondWithEmbeddedAsset.ts +18 -0
  177. package/src/lib/server/runtime/runWithRequestScope.ts +150 -0
  178. package/src/lib/server/runtime/safeJsonForScript.ts +17 -0
  179. package/src/lib/server/runtime/serializeCacheSnapshot.ts +45 -0
  180. package/src/lib/server/runtime/serverSlot.ts +13 -0
  181. package/src/lib/server/runtime/setActiveServer.ts +6 -0
  182. package/src/lib/server/runtime/snapshotEntryFromCache.ts +83 -0
  183. package/src/lib/server/runtime/streamCacheResolutions.ts +37 -0
  184. package/src/lib/server/runtime/streamFromIterator.ts +86 -0
  185. package/src/lib/server/runtime/types/Assets.ts +6 -0
  186. package/src/lib/server/runtime/types/DevReloadStamp.ts +18 -0
  187. package/src/lib/server/runtime/types/InspectorCacheEntry.ts +24 -0
  188. package/src/lib/server/runtime/types/InspectorCacheSnapshot.ts +11 -0
  189. package/src/lib/server/runtime/types/InspectorContext.ts +30 -0
  190. package/src/lib/server/runtime/types/InspectorSocket.ts +17 -0
  191. package/src/lib/server/runtime/types/InspectorSurface.ts +13 -0
  192. package/src/lib/server/runtime/types/InspectorVerb.ts +27 -0
  193. package/src/lib/server/runtime/types/RequestStore.ts +55 -0
  194. package/src/lib/server/runtime/warnUnguardedMcp.ts +32 -0
  195. package/src/lib/server/runtime/withResponseDefaults.ts +24 -0
  196. package/src/lib/server/server.ts +33 -0
  197. package/src/lib/server/socket.ts +32 -0
  198. package/src/lib/server/sockets/createSocketDispatcher.ts +337 -0
  199. package/src/lib/server/sockets/defineSocket.ts +179 -0
  200. package/src/lib/server/sockets/lookupSocket.ts +6 -0
  201. package/src/lib/server/sockets/registerSocket.ts +6 -0
  202. package/src/lib/server/sockets/socketOperations.ts +36 -0
  203. package/src/lib/server/sockets/socketRegistry.ts +9 -0
  204. package/src/lib/server/sockets/types/Socket.ts +23 -0
  205. package/src/lib/server/sockets/types/SocketClientFrame.ts +19 -0
  206. package/src/lib/server/sockets/types/SocketOperation.ts +22 -0
  207. package/src/lib/server/sockets/types/SocketOptions.ts +26 -0
  208. package/src/lib/server/sockets/types/SocketRegistryEntry.ts +19 -0
  209. package/src/lib/server/sockets/types/SocketRoutes.ts +10 -0
  210. package/src/lib/server/sockets/types/SocketServerFrame.ts +24 -0
  211. package/src/lib/server/sse.ts +54 -0
  212. package/src/lib/shared/ABIDE_PACKAGE_NAME.ts +7 -0
  213. package/src/lib/shared/ABIDE_VERSION.ts +9 -0
  214. package/src/lib/shared/CACHE_CONTROL_VALUES.ts +16 -0
  215. package/src/lib/shared/CACHE_WRAPPED.ts +8 -0
  216. package/src/lib/shared/CLI_PATH.ts +7 -0
  217. package/src/lib/shared/DEV_HOT_PREFIX.ts +7 -0
  218. package/src/lib/shared/DEV_RELOAD_PATH.ts +6 -0
  219. package/src/lib/shared/HEALTH_PATH.ts +7 -0
  220. package/src/lib/shared/HttpError.ts +20 -0
  221. package/src/lib/shared/IDENTITY_PATH.ts +6 -0
  222. package/src/lib/shared/INSPECTOR_PATH.ts +7 -0
  223. package/src/lib/shared/NAV_HEADER.ts +8 -0
  224. package/src/lib/shared/OFFLINE_HEADER.ts +8 -0
  225. package/src/lib/shared/REMOTE_FUNCTION.ts +8 -0
  226. package/src/lib/shared/REPLAYABLE_METHODS.ts +12 -0
  227. package/src/lib/shared/SOCKETS_PATH.ts +7 -0
  228. package/src/lib/shared/STREAMING_CONTENT_TYPES.ts +11 -0
  229. package/src/lib/shared/SocketDisconnectedError.ts +13 -0
  230. package/src/lib/shared/TEXT_PLAIN.ts +7 -0
  231. package/src/lib/shared/abideImportName.ts +44 -0
  232. package/src/lib/shared/abideLog.ts +38 -0
  233. package/src/lib/shared/activeCacheStore.ts +20 -0
  234. package/src/lib/shared/activePage.ts +25 -0
  235. package/src/lib/shared/appDataDir.ts +34 -0
  236. package/src/lib/shared/appNameSlot.ts +10 -0
  237. package/src/lib/shared/basePath.ts +10 -0
  238. package/src/lib/shared/basePathFromAppUrl.ts +20 -0
  239. package/src/lib/shared/baseSlot.ts +14 -0
  240. package/src/lib/shared/binaryDirEnvPath.ts +12 -0
  241. package/src/lib/shared/browserClientFlags.ts +10 -0
  242. package/src/lib/shared/buildRpcProxy.ts +39 -0
  243. package/src/lib/shared/buildRpcRequest.ts +70 -0
  244. package/src/lib/shared/buildSocketOverChannel.ts +58 -0
  245. package/src/lib/shared/bundleLayout.ts +36 -0
  246. package/src/lib/shared/cache.ts +951 -0
  247. package/src/lib/shared/cacheEntryFromSnapshot.ts +59 -0
  248. package/src/lib/shared/cacheStoreSlot.ts +16 -0
  249. package/src/lib/shared/cacheStores.ts +10 -0
  250. package/src/lib/shared/canonicalJson.ts +63 -0
  251. package/src/lib/shared/carriesBodyArgs.ts +13 -0
  252. package/src/lib/shared/clearLastConnection.ts +7 -0
  253. package/src/lib/shared/commandNameForUrl.ts +17 -0
  254. package/src/lib/shared/createCacheStore.ts +104 -0
  255. package/src/lib/shared/createChannelLog.ts +122 -0
  256. package/src/lib/shared/createLifecycleChannel.ts +56 -0
  257. package/src/lib/shared/createLivenessWatch.ts +118 -0
  258. package/src/lib/shared/createPushIterator.ts +127 -0
  259. package/src/lib/shared/createRemoteFunction.ts +122 -0
  260. package/src/lib/shared/createSubscriber.ts +55 -0
  261. package/src/lib/shared/createTraceContext.ts +21 -0
  262. package/src/lib/shared/dataDirEnvPath.ts +12 -0
  263. package/src/lib/shared/decodeResponse.ts +47 -0
  264. package/src/lib/shared/detectTarget.ts +27 -0
  265. package/src/lib/shared/detectVerbMethod.ts +17 -0
  266. package/src/lib/shared/emitLogRecord.ts +190 -0
  267. package/src/lib/shared/exeSuffix.ts +9 -0
  268. package/src/lib/shared/exitOnBuildFailure.ts +17 -0
  269. package/src/lib/shared/extraForwardHeaders.ts +16 -0
  270. package/src/lib/shared/fileStem.ts +9 -0
  271. package/src/lib/shared/findExportCallSite.ts +476 -0
  272. package/src/lib/shared/formatTraceparent.ts +6 -0
  273. package/src/lib/shared/forwardHeaders.ts +44 -0
  274. package/src/lib/shared/getRemoteMeta.ts +5 -0
  275. package/src/lib/shared/globalCacheStore.ts +15 -0
  276. package/src/lib/shared/globalCacheStoreSlot.ts +14 -0
  277. package/src/lib/shared/health.ts +179 -0
  278. package/src/lib/shared/healthReadSlot.ts +11 -0
  279. package/src/lib/shared/healthSeedSlot.ts +12 -0
  280. package/src/lib/shared/html.ts +38 -0
  281. package/src/lib/shared/importNamesToStrip.ts +13 -0
  282. package/src/lib/shared/invalidateEvent.ts +11 -0
  283. package/src/lib/shared/invalidateTripwire.ts +40 -0
  284. package/src/lib/shared/isAbideHealthPayload.ts +11 -0
  285. package/src/lib/shared/isCompileTarget.ts +15 -0
  286. package/src/lib/shared/isDebugEnabled.ts +26 -0
  287. package/src/lib/shared/isDebugNegated.ts +19 -0
  288. package/src/lib/shared/isModuleNotFound.ts +16 -0
  289. package/src/lib/shared/isReadOnlyMethod.ts +14 -0
  290. package/src/lib/shared/isReplayableMethod.ts +7 -0
  291. package/src/lib/shared/isStreamingResponse.ts +11 -0
  292. package/src/lib/shared/isSubscribable.ts +15 -0
  293. package/src/lib/shared/jsonSchemaForPromptArguments.ts +29 -0
  294. package/src/lib/shared/jsonSchemaForSchema.ts +39 -0
  295. package/src/lib/shared/jsonlErrorFrame.ts +24 -0
  296. package/src/lib/shared/keyForRemoteCall.ts +29 -0
  297. package/src/lib/shared/keyMatchesPrefix.ts +9 -0
  298. package/src/lib/shared/lastConnectionPath.ts +7 -0
  299. package/src/lib/shared/layoutChainForRoute.ts +22 -0
  300. package/src/lib/shared/loadEnvFile.ts +17 -0
  301. package/src/lib/shared/loadEnvFromDataDir.ts +14 -0
  302. package/src/lib/shared/log.ts +24 -0
  303. package/src/lib/shared/logClosingRecord.ts +28 -0
  304. package/src/lib/shared/logTapSlot.ts +13 -0
  305. package/src/lib/shared/manifestModule.ts +39 -0
  306. package/src/lib/shared/matchesDebugPattern.ts +16 -0
  307. package/src/lib/shared/memoizeByKey.ts +32 -0
  308. package/src/lib/shared/normalizeTarget.ts +10 -0
  309. package/src/lib/shared/online.ts +51 -0
  310. package/src/lib/shared/page.ts +30 -0
  311. package/src/lib/shared/pageSlot.ts +17 -0
  312. package/src/lib/shared/pageUrlForFile.ts +14 -0
  313. package/src/lib/shared/parseBoundedEnvInt.ts +20 -0
  314. package/src/lib/shared/parseDebugPatterns.ts +21 -0
  315. package/src/lib/shared/parseEnv.ts +30 -0
  316. package/src/lib/shared/parsePromptMarkdown.ts +35 -0
  317. package/src/lib/shared/parseRouteSegments.ts +22 -0
  318. package/src/lib/shared/parseTraceparent.ts +26 -0
  319. package/src/lib/shared/pending.ts +30 -0
  320. package/src/lib/shared/prepareRpcModule.ts +59 -0
  321. package/src/lib/shared/prepareSocketModule.ts +49 -0
  322. package/src/lib/shared/probeRegistries.ts +68 -0
  323. package/src/lib/shared/producerKey.ts +32 -0
  324. package/src/lib/shared/programNameForPackage.ts +14 -0
  325. package/src/lib/shared/promptNameForFile.ts +10 -0
  326. package/src/lib/shared/queryStringFromArgs.ts +27 -0
  327. package/src/lib/shared/randomHexId.ts +14 -0
  328. package/src/lib/shared/readEnvFile.ts +15 -0
  329. package/src/lib/shared/readLastConnection.ts +18 -0
  330. package/src/lib/shared/readPackageJson.ts +9 -0
  331. package/src/lib/shared/recordRemoteMeta.ts +5 -0
  332. package/src/lib/shared/refreshing.ts +31 -0
  333. package/src/lib/shared/remoteMetaStore.ts +16 -0
  334. package/src/lib/shared/requestScopeSlot.ts +15 -0
  335. package/src/lib/shared/resolveClientFlags.ts +20 -0
  336. package/src/lib/shared/responseErrorText.ts +9 -0
  337. package/src/lib/shared/rpcTimeoutSlot.ts +9 -0
  338. package/src/lib/shared/rpcUrlForFile.ts +19 -0
  339. package/src/lib/shared/runningAsStandaloneBinary.ts +13 -0
  340. package/src/lib/shared/selectorMatcher.ts +68 -0
  341. package/src/lib/shared/selectorPrefix.ts +39 -0
  342. package/src/lib/shared/serializeEnv.ts +18 -0
  343. package/src/lib/shared/setAppName.ts +5 -0
  344. package/src/lib/shared/setBaseResolver.ts +6 -0
  345. package/src/lib/shared/setCacheStoreResolver.ts +6 -0
  346. package/src/lib/shared/setGlobalCacheStoreResolver.ts +6 -0
  347. package/src/lib/shared/setPageResolver.ts +7 -0
  348. package/src/lib/shared/setRequestScopeResolver.ts +6 -0
  349. package/src/lib/shared/snippet.ts +25 -0
  350. package/src/lib/shared/socketNameForFile.ts +11 -0
  351. package/src/lib/shared/socketTapSlot.ts +12 -0
  352. package/src/lib/shared/sseErrorFrame.ts +29 -0
  353. package/src/lib/shared/streamResponse.ts +169 -0
  354. package/src/lib/shared/stripImport.ts +27 -0
  355. package/src/lib/shared/subscribableFromResponse.ts +51 -0
  356. package/src/lib/shared/tailProbeSlot.ts +16 -0
  357. package/src/lib/shared/toBunRoutePattern.ts +28 -0
  358. package/src/lib/shared/toScopeSet.ts +4 -0
  359. package/src/lib/shared/trace.ts +16 -0
  360. package/src/lib/shared/types/CacheEntry.ts +84 -0
  361. package/src/lib/shared/types/CacheInvalidation.ts +9 -0
  362. package/src/lib/shared/types/CacheOnContext.ts +25 -0
  363. package/src/lib/shared/types/CacheOptions.ts +39 -0
  364. package/src/lib/shared/types/CacheSelector.ts +17 -0
  365. package/src/lib/shared/types/CacheSnapshot.ts +16 -0
  366. package/src/lib/shared/types/CacheSnapshotEntry.ts +17 -0
  367. package/src/lib/shared/types/CacheStats.ts +13 -0
  368. package/src/lib/shared/types/CacheStore.ts +39 -0
  369. package/src/lib/shared/types/ChannelLog.ts +13 -0
  370. package/src/lib/shared/types/ClientFlags.ts +11 -0
  371. package/src/lib/shared/types/CompileTarget.ts +6 -0
  372. package/src/lib/shared/types/FrameworkLog.ts +13 -0
  373. package/src/lib/shared/types/HttpVerb.ts +1 -0
  374. package/src/lib/shared/types/LastConnection.ts +9 -0
  375. package/src/lib/shared/types/Log.ts +13 -0
  376. package/src/lib/shared/types/LogRecord.ts +42 -0
  377. package/src/lib/shared/types/LogVoice.ts +7 -0
  378. package/src/lib/shared/types/PageSnapshot.ts +14 -0
  379. package/src/lib/shared/types/PromptArgument.ts +12 -0
  380. package/src/lib/shared/types/RawRemoteFunction.ts +14 -0
  381. package/src/lib/shared/types/RemoteCallable.ts +12 -0
  382. package/src/lib/shared/types/RemoteFunction.ts +47 -0
  383. package/src/lib/shared/types/ReplayableMethod.ts +7 -0
  384. package/src/lib/shared/types/RequestScopeInfo.ts +16 -0
  385. package/src/lib/shared/types/RpcInvoker.ts +6 -0
  386. package/src/lib/shared/types/SocketChannel.ts +17 -0
  387. package/src/lib/shared/types/SocketSubCallbacks.ts +13 -0
  388. package/src/lib/shared/types/StandardSchemaV1.ts +56 -0
  389. package/src/lib/shared/types/StreamedResolution.ts +10 -0
  390. package/src/lib/shared/types/Subscribable.ts +26 -0
  391. package/src/lib/shared/types/TailHooks.ts +12 -0
  392. package/src/lib/shared/types/TailOptions.ts +10 -0
  393. package/src/lib/shared/types/TraceContext.ts +17 -0
  394. package/src/lib/shared/url.ts +118 -0
  395. package/src/lib/shared/withBase.ts +11 -0
  396. package/src/lib/shared/withBaseUrl.ts +17 -0
  397. package/src/lib/shared/withJsonSchema.ts +21 -0
  398. package/src/lib/shared/writeDts.ts +12 -0
  399. package/src/lib/shared/writeHealthDts.ts +36 -0
  400. package/src/lib/shared/writeLastConnection.ts +13 -0
  401. package/src/lib/shared/writePublicAssetsDts.ts +31 -0
  402. package/src/lib/shared/writeRoutesDts.ts +73 -0
  403. package/src/lib/shared/writeRpcDts.ts +49 -0
  404. package/src/lib/shared/writeTestRpcDts.ts +45 -0
  405. package/src/lib/shared/writeTestSocketsDts.ts +34 -0
  406. package/src/lib/test/assertAgentFrameConformance.ts +73 -0
  407. package/src/lib/test/createScriptedSurface.ts +45 -0
  408. package/src/lib/test/createTestApp.ts +203 -0
  409. package/src/lib/test/createTestSocketChannel.ts +142 -0
  410. package/src/lib/ui/README.md +86 -0
  411. package/src/lib/ui/compile/SSR_ESCAPE.ts +25 -0
  412. package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +36 -0
  413. package/src/lib/ui/compile/VOID_TAGS.ts +21 -0
  414. package/src/lib/ui/compile/abideUiPlugin.ts +65 -0
  415. package/src/lib/ui/compile/analyzeComponent.ts +117 -0
  416. package/src/lib/ui/compile/assetModulesFile.ts +32 -0
  417. package/src/lib/ui/compile/branchElements.ts +50 -0
  418. package/src/lib/ui/compile/collectAbideDiagnostics.ts +59 -0
  419. package/src/lib/ui/compile/compileComponent.ts +20 -0
  420. package/src/lib/ui/compile/compileModule.ts +116 -0
  421. package/src/lib/ui/compile/compileSSR.ts +36 -0
  422. package/src/lib/ui/compile/compileShadow.ts +352 -0
  423. package/src/lib/ui/compile/createShadowLanguageService.ts +197 -0
  424. package/src/lib/ui/compile/createShadowProgram.ts +96 -0
  425. package/src/lib/ui/compile/decodeHtmlEntities.ts +49 -0
  426. package/src/lib/ui/compile/desugarSignals.ts +133 -0
  427. package/src/lib/ui/compile/escapeHtml.ts +15 -0
  428. package/src/lib/ui/compile/generateBuild.ts +638 -0
  429. package/src/lib/ui/compile/generateSSR.ts +380 -0
  430. package/src/lib/ui/compile/groupBindParts.ts +28 -0
  431. package/src/lib/ui/compile/hoistCells.ts +120 -0
  432. package/src/lib/ui/compile/loadShadowTsConfig.ts +31 -0
  433. package/src/lib/ui/compile/lowerDocAccess.ts +202 -0
  434. package/src/lib/ui/compile/nearestProjectRoot.ts +16 -0
  435. package/src/lib/ui/compile/parseTemplate.ts +396 -0
  436. package/src/lib/ui/compile/partitionSlots.ts +36 -0
  437. package/src/lib/ui/compile/prepareNestedScript.ts +42 -0
  438. package/src/lib/ui/compile/remapShadowDiagnostic.ts +30 -0
  439. package/src/lib/ui/compile/renameSignalRefs.ts +85 -0
  440. package/src/lib/ui/compile/resolveAbideImports.ts +29 -0
  441. package/src/lib/ui/compile/scopeCss.ts +115 -0
  442. package/src/lib/ui/compile/shadowNaming.ts +11 -0
  443. package/src/lib/ui/compile/sourceToShadowOffset.ts +24 -0
  444. package/src/lib/ui/compile/staticAttrValue.ts +13 -0
  445. package/src/lib/ui/compile/stripEffects.ts +32 -0
  446. package/src/lib/ui/compile/types/AbideDiagnostic.ts +14 -0
  447. package/src/lib/ui/compile/types/AnalyzedComponent.ts +25 -0
  448. package/src/lib/ui/compile/types/CompiledShadow.ts +15 -0
  449. package/src/lib/ui/compile/types/TemplateAttr.ts +16 -0
  450. package/src/lib/ui/compile/types/TemplateNode.ts +78 -0
  451. package/src/lib/ui/compile/types/TextPart.ts +8 -0
  452. package/src/lib/ui/derived.ts +28 -0
  453. package/src/lib/ui/doc.ts +15 -0
  454. package/src/lib/ui/dom/appendSnippet.ts +34 -0
  455. package/src/lib/ui/dom/appendStatic.ts +27 -0
  456. package/src/lib/ui/dom/appendText.ts +114 -0
  457. package/src/lib/ui/dom/applyResolved.ts +72 -0
  458. package/src/lib/ui/dom/attach.ts +20 -0
  459. package/src/lib/ui/dom/attr.ts +19 -0
  460. package/src/lib/ui/dom/awaitBlock.ts +224 -0
  461. package/src/lib/ui/dom/cloneStatic.ts +52 -0
  462. package/src/lib/ui/dom/each.ts +115 -0
  463. package/src/lib/ui/dom/eachAsync.ts +153 -0
  464. package/src/lib/ui/dom/hydrate.ts +35 -0
  465. package/src/lib/ui/dom/mount.ts +29 -0
  466. package/src/lib/ui/dom/mountChild.ts +33 -0
  467. package/src/lib/ui/dom/on.ts +15 -0
  468. package/src/lib/ui/dom/openChild.ts +22 -0
  469. package/src/lib/ui/dom/openRoot.ts +20 -0
  470. package/src/lib/ui/dom/switchBlock.ts +75 -0
  471. package/src/lib/ui/dom/text.ts +20 -0
  472. package/src/lib/ui/dom/tryBlock.ts +112 -0
  473. package/src/lib/ui/dom/types/EachRow.ts +3 -0
  474. package/src/lib/ui/dom/types/SwitchCase.ts +6 -0
  475. package/src/lib/ui/dom/when.ts +73 -0
  476. package/src/lib/ui/effect.ts +16 -0
  477. package/src/lib/ui/installHotBridge.ts +73 -0
  478. package/src/lib/ui/matchRoute.ts +89 -0
  479. package/src/lib/ui/navigate.ts +17 -0
  480. package/src/lib/ui/probeNavigation.ts +33 -0
  481. package/src/lib/ui/remoteProxy.ts +97 -0
  482. package/src/lib/ui/renderChain.ts +50 -0
  483. package/src/lib/ui/renderToStream.ts +104 -0
  484. package/src/lib/ui/router.ts +286 -0
  485. package/src/lib/ui/runtime/OUTLET_TAG.ts +8 -0
  486. package/src/lib/ui/runtime/OWNER.ts +8 -0
  487. package/src/lib/ui/runtime/REACTIVE_CONTEXT.ts +14 -0
  488. package/src/lib/ui/runtime/RENDER.ts +23 -0
  489. package/src/lib/ui/runtime/RESUME.ts +16 -0
  490. package/src/lib/ui/runtime/applyPatchToTree.ts +41 -0
  491. package/src/lib/ui/runtime/claimChild.ts +10 -0
  492. package/src/lib/ui/runtime/clientPage.ts +16 -0
  493. package/src/lib/ui/runtime/createComputedNode.ts +16 -0
  494. package/src/lib/ui/runtime/createDoc.ts +177 -0
  495. package/src/lib/ui/runtime/createEffectNode.ts +58 -0
  496. package/src/lib/ui/runtime/createSignalNode.ts +16 -0
  497. package/src/lib/ui/runtime/detachLink.ts +21 -0
  498. package/src/lib/ui/runtime/endTracking.ts +24 -0
  499. package/src/lib/ui/runtime/enterRenderPass.ts +12 -0
  500. package/src/lib/ui/runtime/exitRenderPass.ts +7 -0
  501. package/src/lib/ui/runtime/firstOutlet.ts +22 -0
  502. package/src/lib/ui/runtime/flushEffects.ts +17 -0
  503. package/src/lib/ui/runtime/hotInstances.ts +10 -0
  504. package/src/lib/ui/runtime/hotReloadEnabled.ts +8 -0
  505. package/src/lib/ui/runtime/hotReplace.ts +25 -0
  506. package/src/lib/ui/runtime/nextBlockId.ts +11 -0
  507. package/src/lib/ui/runtime/pathExists.ts +23 -0
  508. package/src/lib/ui/runtime/readNode.ts +17 -0
  509. package/src/lib/ui/runtime/registerHotInstance.ts +23 -0
  510. package/src/lib/ui/runtime/runNode.ts +28 -0
  511. package/src/lib/ui/runtime/runtimePath.ts +9 -0
  512. package/src/lib/ui/runtime/scope.ts +24 -0
  513. package/src/lib/ui/runtime/toTeardown.ts +26 -0
  514. package/src/lib/ui/runtime/track.ts +58 -0
  515. package/src/lib/ui/runtime/trigger.ts +44 -0
  516. package/src/lib/ui/runtime/types/Cell.ts +5 -0
  517. package/src/lib/ui/runtime/types/Derived.ts +3 -0
  518. package/src/lib/ui/runtime/types/Doc.ts +19 -0
  519. package/src/lib/ui/runtime/types/EffectResult.ts +10 -0
  520. package/src/lib/ui/runtime/types/HotInstance.ts +14 -0
  521. package/src/lib/ui/runtime/types/NavVerdict.ts +9 -0
  522. package/src/lib/ui/runtime/types/Patch.ts +11 -0
  523. package/src/lib/ui/runtime/types/ReactiveLink.ts +21 -0
  524. package/src/lib/ui/runtime/types/ReactiveNode.ts +25 -0
  525. package/src/lib/ui/runtime/types/Route.ts +8 -0
  526. package/src/lib/ui/runtime/types/RouteLoader.ts +7 -0
  527. package/src/lib/ui/runtime/types/SsrRender.ts +22 -0
  528. package/src/lib/ui/runtime/types/State.ts +3 -0
  529. package/src/lib/ui/runtime/types/Teardown.ts +5 -0
  530. package/src/lib/ui/runtime/types/UiComponent.ts +16 -0
  531. package/src/lib/ui/runtime/types/UiProps.ts +15 -0
  532. package/src/lib/ui/runtime/unlinkDeps.ts +20 -0
  533. package/src/lib/ui/runtime/untrack.ts +20 -0
  534. package/src/lib/ui/runtime/valueAtPath.ts +18 -0
  535. package/src/lib/ui/runtime/writeNode.ts +16 -0
  536. package/src/lib/ui/socketChannel.ts +227 -0
  537. package/src/lib/ui/socketProxy.ts +25 -0
  538. package/src/lib/ui/startClient.ts +58 -0
  539. package/src/lib/ui/state.ts +25 -0
  540. package/src/lib/ui/tail.ts +324 -0
  541. package/src/lib/ui/types/Layouts.ts +9 -0
  542. package/src/lib/ui/types/Pages.ts +8 -0
  543. package/src/preload.ts +19 -0
  544. package/src/scaffold.ts +153 -0
  545. package/src/serverBuildPlugins.ts +19 -0
  546. package/src/serverEntry.ts +95 -0
  547. package/template/bunfig.toml +4 -0
  548. package/template/package.json +18 -0
  549. package/template/src/app.ts +28 -0
  550. package/template/src/bundle/icon.png +0 -0
  551. package/template/src/cli/banner.txt +3 -0
  552. package/template/src/cli/footer.txt +1 -0
  553. package/template/src/server/config.ts +17 -0
  554. package/template/src/server/rpc/getHello.ts +36 -0
  555. package/template/src/ui/Layout.abide +19 -0
  556. package/template/src/ui/app.css +21 -0
  557. package/template/src/ui/app.html +24 -0
  558. package/template/src/ui/pages/about/page.abide +9 -0
  559. package/template/src/ui/pages/page.abide +22 -0
  560. package/template/test/app.test.ts +30 -0
  561. package/template/tsconfig.json +18 -0
  562. package/tsconfig.app.json +17 -0
@@ -0,0 +1,36 @@
1
+ import { analyzeComponent } from './analyzeComponent.ts'
2
+ import { generateSSR } from './generateSSR.ts'
3
+ import { SSR_ESCAPE } from './SSR_ESCAPE.ts'
4
+ import { stripEffects } from './stripEffects.ts'
5
+
6
+ /*
7
+ Compiles a component into the body of a server render function. Runs the shared
8
+ front-end, then the SSR back-end, and returns `{ html, state, awaits }`:
9
+
10
+ - `html` — server-rendered markup (await blocks render their pending shell);
11
+ - `state` — the document snapshot the client adopts on resume;
12
+ - `awaits` — pending await blocks (id + promise + resolved/error renderers) that
13
+ `renderToStream` flushes out of order; empty for a fully synchronous component.
14
+
15
+ Effects are stripped — they are client lifecycle and emit no HTML, so the server
16
+ render is a snapshot of the markup before any effect runs.
17
+
18
+ Runs with `doc`/`state`/`derived`/`effect`/`nextBlockId`/`enterRenderPass`/
19
+ `exitRenderPass` in scope and defines `model`. The body is bracketed by a render
20
+ pass so the outermost render resets the block-id counter and an inlined child
21
+ render continues it — keeping await/try ids unique and aligned with the client.
22
+ */
23
+ export function compileSSR(source: string, isLayout = false, scopeSeed?: string): string {
24
+ const { script, stateNames, derivedNames, nodes } = analyzeComponent(source, scopeSeed)
25
+ const ssr = generateSSR(nodes, stateNames, derivedNames, isLayout)
26
+ /* No `<style>` in the markup — the scoped CSS is bundled into the entry stylesheet
27
+ the shell links (see `abideUiPlugin`), so SSR output is styled by that sheet. The
28
+ elements still carry their `data-a-…` scopes via `generateSSR`. */
29
+ /* `typeof model` guards a component with no reactive state (a pure-async or
30
+ static component declares no `model`); its snapshot is then empty. */
31
+ return (
32
+ `enterRenderPass();\ntry {\n${stripEffects(script)}\n${SSR_ESCAPE}\nconst $out = [];\nconst $awaits = [];\n${ssr}` +
33
+ `return { html: $out.join(''), state: (typeof model !== 'undefined' ? model.snapshot() : {}), awaits: $awaits };\n` +
34
+ `} finally { exitRenderPass(); }`
35
+ )
36
+ }
@@ -0,0 +1,352 @@
1
+ import ts from 'typescript'
2
+ import { ABIDE_PACKAGE_NAME } from '../../shared/ABIDE_PACKAGE_NAME.ts'
3
+ import { parseTemplate } from './parseTemplate.ts'
4
+ import type { CompiledShadow, ShadowMapping } from './types/CompiledShadow.ts'
5
+ import type { TemplateNode } from './types/TemplateNode.ts'
6
+
7
+ /*
8
+ Framework callables the `.abide` loader injects into a component's scope, imported
9
+ into the shadow with their real types so author calls (`effect`, `html`, …)
10
+ type-check. `state`/`derived` are imported too as a fallback for stray uses; their
11
+ declarations are rewritten to value types so the import is normally unused (fine —
12
+ the shadow program disables noUnusedLocals). `prop` has no runtime export, so it
13
+ never appears here — every `prop()` declaration is rewritten away. `$props` is the
14
+ legacy untyped prop bag (pre-`prop()` sugar) made available raw.
15
+ */
16
+ const SHADOW_PREAMBLE = `import { state } from '${ABIDE_PACKAGE_NAME}/ui/state'
17
+ import { derived } from '${ABIDE_PACKAGE_NAME}/ui/derived'
18
+ import { effect } from '${ABIDE_PACKAGE_NAME}/ui/effect'
19
+ import { doc } from '${ABIDE_PACKAGE_NAME}/ui/doc'
20
+ import { html } from '${ABIDE_PACKAGE_NAME}/shared/html'
21
+ import { snippet } from '${ABIDE_PACKAGE_NAME}/shared/snippet'
22
+ declare const $props: Record<string, (() => unknown) | undefined>
23
+ void [state, derived, effect, doc, html, snippet]
24
+ `
25
+
26
+ /*
27
+ Compiles a `.abide` component into its type-checking shadow — a synthetic TS
28
+ module that reconstructs the author scope with value types and references every
29
+ template expression in a checkable position (see ADR-0010). The shadow is never
30
+ executed; it exists only so `tsc`/the language service can type-check template
31
+ expressions and child-component props, with diagnostics mapped back through the
32
+ returned segments.
33
+
34
+ The script's signal surface is rewritten to value types:
35
+ let count = state(0) → let count = (0)
36
+ const total = derived(() => …) → const total = (() => …)()
37
+ let title = prop<string>('t') → Props field + `let title = props['t']`
38
+ Everything else (functions, plain consts, imports) is emitted verbatim, so
39
+ expressions inside it (e.g. a derived's compute body) are checked and mapped too.
40
+ */
41
+ export function compileShadow(source: string): CompiledShadow {
42
+ const builder = createBuilder()
43
+ const leadingScript = source.match(/^\s*<script[^>]*>([\s\S]*?)<\/script>/)
44
+ const scriptBody = leadingScript?.[1] ?? ''
45
+ /* Body starts just past the opening `<script …>`; template just past `</script>`. */
46
+ const scriptStart = leadingScript ? source.indexOf('>', leadingScript.index) + 1 : 0
47
+ const templateStart = leadingScript ? (leadingScript.index ?? 0) + leadingScript[0].length : 0
48
+
49
+ const { imports, scope, props } = analyzeScript(scriptBody, scriptStart)
50
+ builder.raw(SHADOW_PREAMBLE)
51
+ for (const line of imports) {
52
+ builder.flush(line)
53
+ }
54
+ builder.raw(`interface __Props {\n${props.join('\n')}\n}\n`)
55
+ /* async so `await` blocks are legal; never executed, so the return is void. */
56
+ builder.raw('export default async function (props: __Props): Promise<void> {\n')
57
+ /* Reference props so an all-optional bag with no reads doesn't read as unused. */
58
+ builder.raw('void props;\n')
59
+ for (const line of scope) {
60
+ builder.flush(line)
61
+ }
62
+ for (const node of parseTemplate(source.slice(templateStart), templateStart).nodes) {
63
+ emitNode(node, builder)
64
+ }
65
+ builder.raw('}\n')
66
+ return builder.result()
67
+ }
68
+
69
+ /* The shadow text builder: `raw` appends synthesised scaffolding (no mapping),
70
+ `expr` appends an inline parenthesised source span `(code)` and records its
71
+ segment, `stmt` wraps one as a standalone statement, `flush` appends a
72
+ pre-assembled scope line carrying its own embedded segments. */
73
+ type Builder = {
74
+ raw: (text: string) => void
75
+ expr: (code: string, sourceLoc: number | undefined) => void
76
+ stmt: (code: string, sourceLoc: number | undefined) => void
77
+ flush: (line: ScopeLine) => void
78
+ result: () => CompiledShadow
79
+ }
80
+
81
+ /* A reconstructed scope statement plus the segments embedded inside it (the parts
82
+ emitted verbatim from the original script), offset-relative to the line start. */
83
+ type ScopeLine = { text: string; segments: ShadowMapping[] }
84
+
85
+ function createBuilder(): Builder {
86
+ let code = ''
87
+ const mappings: ShadowMapping[] = []
88
+ const builder: Builder = {
89
+ raw(text) {
90
+ code += text
91
+ },
92
+ expr(exprCode, sourceLoc) {
93
+ code += '('
94
+ if (sourceLoc !== undefined) {
95
+ mappings.push({
96
+ shadowStart: code.length,
97
+ sourceStart: sourceLoc,
98
+ length: exprCode.length,
99
+ })
100
+ }
101
+ code += `${exprCode})`
102
+ },
103
+ stmt(exprCode, sourceLoc) {
104
+ code += ';'
105
+ builder.expr(exprCode, sourceLoc)
106
+ code += ';\n'
107
+ },
108
+ flush(line) {
109
+ const base = code.length
110
+ for (const segment of line.segments) {
111
+ mappings.push({ ...segment, shadowStart: base + segment.shadowStart })
112
+ }
113
+ code += `${line.text}\n`
114
+ },
115
+ result: () => ({ code, mappings }),
116
+ }
117
+ return builder
118
+ }
119
+
120
+ type ScriptAnalysis = { imports: ScopeLine[]; scope: ScopeLine[]; props: string[] }
121
+
122
+ /* Walks the leading `<script>` and produces the shadow's module imports, the
123
+ value-typed scope lines, and the Props interface fields. `scriptStart` is the
124
+ body's absolute offset in the source, so verbatim spans map back exactly. */
125
+ function analyzeScript(scriptBody: string, scriptStart: number): ScriptAnalysis {
126
+ const imports: ScopeLine[] = []
127
+ const scope: ScopeLine[] = []
128
+ const props: string[] = []
129
+ if (scriptBody.trim() === '') {
130
+ return { imports, scope, props }
131
+ }
132
+ const file = ts.createSourceFile('script.ts', scriptBody, ts.ScriptTarget.Latest, true)
133
+ /* A verbatim span: original text + the segment mapping it back, relative to the
134
+ line start (the caller rebases shadowStart onto the running shadow length). */
135
+ const span = (node: ts.Node, prefixLength: number): ScopeLine['segments'][number] => ({
136
+ shadowStart: prefixLength,
137
+ sourceStart: scriptStart + node.getStart(file),
138
+ length: node.getEnd() - node.getStart(file),
139
+ })
140
+ const verbatim = (node: ts.Node): string => scriptBody.slice(node.getStart(file), node.getEnd())
141
+
142
+ for (const statement of file.statements) {
143
+ if (ts.isImportDeclaration(statement)) {
144
+ /* Emit verbatim with a span so hover/go-to resolve on the imported names. */
145
+ imports.push({ text: verbatim(statement), segments: [span(statement, 0)] })
146
+ continue
147
+ }
148
+ const reactive = reactiveDeclarations(statement)
149
+ if (reactive === undefined) {
150
+ /* Plain statement (function, const, expression) — emit verbatim, mapped. */
151
+ scope.push({ text: verbatim(statement), segments: [span(statement, 0)] })
152
+ continue
153
+ }
154
+ for (const declaration of reactive) {
155
+ scope.push(scopeLineFor(declaration, props, verbatim, span))
156
+ }
157
+ }
158
+ return { imports, scope, props }
159
+ }
160
+
161
+ /* The `state`/`derived`/`prop` declarations in a variable statement, or undefined
162
+ if it isn't one declaring them (so the caller emits it verbatim). A statement
163
+ mixing reactive and plain declarations is rare; treated as all-verbatim. */
164
+ function reactiveDeclarations(statement: ts.Statement): ts.VariableDeclaration[] | undefined {
165
+ if (!ts.isVariableStatement(statement)) {
166
+ return undefined
167
+ }
168
+ const declarations = statement.declarationList.declarations
169
+ const reactive = declarations.filter((declaration) => signalCallee(declaration) !== undefined)
170
+ return reactive.length === declarations.length && reactive.length > 0 ? reactive : undefined
171
+ }
172
+
173
+ /* The callee name of a `NAME = state(...)` / `derived(...)` / `prop(...)` decl. */
174
+ function signalCallee(declaration: ts.VariableDeclaration): string | undefined {
175
+ const initializer = declaration.initializer
176
+ if (
177
+ initializer !== undefined &&
178
+ ts.isCallExpression(initializer) &&
179
+ ts.isIdentifier(initializer.expression) &&
180
+ ['state', 'derived', 'prop'].includes(initializer.expression.text)
181
+ ) {
182
+ return initializer.expression.text
183
+ }
184
+ return undefined
185
+ }
186
+
187
+ /* Builds one scope line for a reactive declaration, projecting it to its value
188
+ type. `prop` also contributes a Props field (pushed into `props`). */
189
+ function scopeLineFor(
190
+ declaration: ts.VariableDeclaration,
191
+ props: string[],
192
+ verbatim: (node: ts.Node) => string,
193
+ span: (node: ts.Node, prefixLength: number) => ShadowMapping,
194
+ ): ScopeLine {
195
+ const name = ts.isIdentifier(declaration.name) ? declaration.name.text : '_'
196
+ const call = declaration.initializer as ts.CallExpression
197
+ const callee = (call.expression as ts.Identifier).text
198
+ if (callee === 'state') {
199
+ /* state<T>(initial): T is the value type — carry it onto the `let` so an
200
+ explicit annotation isn't lost to `any`/`any[]` inference of the initial. */
201
+ const typeNode = call.typeArguments?.[0]
202
+ const annotation = typeNode === undefined ? '' : `: ${verbatim(typeNode)}`
203
+ const init = call.arguments[0]
204
+ if (init === undefined) {
205
+ return { text: `let ${name}${annotation};`, segments: [] }
206
+ }
207
+ const prefix = `let ${name}${annotation} = (`
208
+ return { text: `${prefix}${verbatim(init)});`, segments: [span(init, prefix.length)] }
209
+ }
210
+ if (callee === 'derived') {
211
+ /* derived<T>(compute): T is the value type — annotate so an explicit
212
+ argument isn't lost to inference of the compute's return. */
213
+ const typeNode = call.typeArguments?.[0]
214
+ const annotation = typeNode === undefined ? '' : `: ${verbatim(typeNode)}`
215
+ const fn = call.arguments[0]
216
+ if (fn === undefined) {
217
+ return { text: `const ${name} = undefined;`, segments: [] }
218
+ }
219
+ const prefix = `const ${name}${annotation} = (`
220
+ return { text: `${prefix}${verbatim(fn)})();`, segments: [span(fn, prefix.length)] }
221
+ }
222
+ /* prop<T>('key'): Props field `key[?]: T`, scope binding read from props. */
223
+ const key = call.arguments[0]
224
+ const keyText = key !== undefined && ts.isStringLiteralLike(key) ? key.text : name
225
+ const typeNode = call.typeArguments?.[0]
226
+ const typeText = typeNode === undefined ? 'unknown' : verbatim(typeNode)
227
+ const optional = typeNode === undefined || /\bundefined\b/.test(typeText)
228
+ props.push(` ${JSON.stringify(keyText)}${optional ? '?' : ''}: ${typeText}`)
229
+ return { text: `let ${name} = props[${JSON.stringify(keyText)}];`, segments: [] }
230
+ }
231
+
232
+ /* Emits a template node's expressions into the shadow's `if (false) {…}` render
233
+ body. Control flow introduces its binding so children type-check against it;
234
+ every expression is referenced in a statement so a type error surfaces and maps. */
235
+ function emitNode(node: TemplateNode, builder: Builder): void {
236
+ switch (node.kind) {
237
+ case 'text':
238
+ for (const part of node.parts) {
239
+ if (part.kind === 'expression') {
240
+ builder.stmt(part.code, part.loc)
241
+ }
242
+ }
243
+ return
244
+ case 'element':
245
+ for (const attr of node.attrs) {
246
+ if (attr.kind !== 'static') {
247
+ builder.stmt(attr.code, attr.loc)
248
+ }
249
+ }
250
+ node.children.forEach((child) => {
251
+ emitNode(child, builder)
252
+ })
253
+ return
254
+ case 'component': {
255
+ /* Check each prop against the child's declared type. The imported tag
256
+ resolves (via the shadow host) to the child's `(props: Props) => …`
257
+ default, so `Parameters<typeof Child>[0]["name"]` is that prop's type;
258
+ assigning the mapped value to it lands a mismatch diagnostic on the
259
+ offending expression (an annotated target reports the error on the RHS,
260
+ unlike an object literal which reports it on the key). */
261
+ for (const prop of node.props) {
262
+ builder.raw(
263
+ `((__prop: Parameters<typeof ${node.name}>[0][${JSON.stringify(prop.name)}]) => {})(`,
264
+ )
265
+ builder.expr(prop.code, prop.loc)
266
+ builder.raw(');\n')
267
+ }
268
+ node.children.forEach((child) => {
269
+ emitNode(child, builder)
270
+ })
271
+ return
272
+ }
273
+ case 'if':
274
+ builder.raw('if ')
275
+ builder.expr(node.condition, node.loc)
276
+ builder.raw(' {\n')
277
+ node.children.forEach((child) => {
278
+ emitNode(child, builder)
279
+ })
280
+ builder.raw('}\n')
281
+ return
282
+ case 'each':
283
+ builder.raw(`for (const ${node.as} of `)
284
+ builder.expr(node.items, node.loc)
285
+ builder.raw(') {\n')
286
+ if (node.key !== undefined) {
287
+ builder.raw(`void (${node.key});\n`)
288
+ }
289
+ node.children.forEach((child) => {
290
+ emitNode(child, builder)
291
+ })
292
+ builder.raw('}\n')
293
+ return
294
+ case 'await':
295
+ builder.raw('{\n')
296
+ builder.raw(node.as !== undefined ? `const ${node.as} = await ` : 'await ')
297
+ builder.expr(node.promise, node.loc)
298
+ builder.raw(';\n')
299
+ node.children.forEach((child) => {
300
+ emitNode(child, builder)
301
+ })
302
+ builder.raw('}\n')
303
+ return
304
+ case 'switch':
305
+ builder.stmt(node.subject, node.loc)
306
+ node.children.forEach((child) => {
307
+ emitNode(child, builder)
308
+ })
309
+ return
310
+ case 'case':
311
+ if (node.match !== undefined) {
312
+ builder.stmt(node.match, node.loc)
313
+ }
314
+ node.children.forEach((child) => {
315
+ emitNode(child, builder)
316
+ })
317
+ return
318
+ case 'branch':
319
+ /* then/catch bind the resolved value / error as `any` so children check. */
320
+ builder.raw('{\n')
321
+ if (node.as !== undefined) {
322
+ builder.raw(`const ${node.as} = undefined as any;\n`)
323
+ }
324
+ node.children.forEach((child) => {
325
+ emitNode(child, builder)
326
+ })
327
+ builder.raw('}\n')
328
+ return
329
+ case 'try':
330
+ builder.raw('{\n')
331
+ node.children.forEach((child) => {
332
+ emitNode(child, builder)
333
+ })
334
+ builder.raw('}\n')
335
+ return
336
+ case 'snippet':
337
+ builder.raw(`const ${node.name} = (${node.params ?? ''}) => {\n`)
338
+ node.children.forEach((child) => {
339
+ emitNode(child, builder)
340
+ })
341
+ builder.raw('};\n')
342
+ return
343
+ case 'script':
344
+ /* A scoped reactive `<script>` block — its body is author TS; emit it so
345
+ its references check. Not yet position-mapped (rare). */
346
+ builder.raw(`{\n${node.code}\n}\n`)
347
+ return
348
+ case 'style':
349
+ /* CSS, not TypeScript — nothing for the shadow to type-check. */
350
+ return
351
+ }
352
+ }
@@ -0,0 +1,197 @@
1
+ import { resolve } from 'node:path'
2
+ import ts from 'typescript'
3
+ import { assetModulesFile } from './assetModulesFile.ts'
4
+ import { compileShadow } from './compileShadow.ts'
5
+ import { loadShadowTsConfig } from './loadShadowTsConfig.ts'
6
+ import { remapShadowDiagnostic } from './remapShadowDiagnostic.ts'
7
+ import { resolveAbideImports } from './resolveAbideImports.ts'
8
+ import { shadowNaming } from './shadowNaming.ts'
9
+ import { sourceToShadowOffset } from './sourceToShadowOffset.ts'
10
+ import type { AbideDiagnostic } from './types/AbideDiagnostic.ts'
11
+ import type { CompiledShadow } from './types/CompiledShadow.ts'
12
+
13
+ const { suffixed, isShadow, sourceOf } = shadowNaming
14
+
15
+ /* Hover quick-info for a source position: TypeScript's signature line and doc
16
+ comment, with the covered span mapped back onto the `.abide` source. */
17
+ export type ShadowQuickInfo = { text: string; documentation: string; start: number; length: number }
18
+
19
+ export type ShadowLanguageService = {
20
+ /* Record/replace an open document's in-memory text (overrides disk). */
21
+ update: (abidePath: string, text: string) => void
22
+ /* Forget an open document; subsequent reads fall back to disk. */
23
+ close: (abidePath: string) => void
24
+ /* Current diagnostics for one component, mapped onto its source. */
25
+ diagnostics: (abidePath: string) => AbideDiagnostic[]
26
+ /* Hover info at a source offset, or undefined if the offset isn't a checked
27
+ expression (markup, whitespace) or TypeScript has nothing to report. */
28
+ quickInfo: (abidePath: string, sourceOffset: number) => ShadowQuickInfo | undefined
29
+ }
30
+
31
+ /*
32
+ An incremental `ts.LanguageService` over the shadow world, for the LSP. Open
33
+ documents are held as in-memory overlays that override disk, so diagnostics
34
+ reflect unsaved edits; every other file (real `.ts`, unopened `.abide`) reads from
35
+ disk. Shares the shadow compiler, module resolver, and tsconfig with the one-shot
36
+ check Program — the editor and CLI report identically.
37
+ */
38
+ export function createShadowLanguageService(cwd: string): ShadowLanguageService {
39
+ const { options, fileNames } = loadShadowTsConfig(cwd)
40
+ const overlays = new Map<string, string>()
41
+ const versions = new Map<string, number>()
42
+ const shadows = new Map<string, CompiledShadow>()
43
+ const parseErrors = new Map<string, string>()
44
+
45
+ /* Ambient declarations for bundler-handled asset imports (`*.css`, …). */
46
+ const assets = assetModulesFile(cwd)
47
+
48
+ const exists = (abidePath: string): boolean =>
49
+ overlays.has(abidePath) || ts.sys.fileExists(abidePath)
50
+
51
+ /* Compiles (and caches) a component's shadow from its overlay or disk text; a
52
+ template parse error yields a minimal valid module + a recorded message. */
53
+ const shadowText = (abidePath: string): string => {
54
+ const source = overlays.get(abidePath) ?? ts.sys.readFile(abidePath) ?? ''
55
+ try {
56
+ const compiled = compileShadow(source)
57
+ shadows.set(abidePath, compiled)
58
+ parseErrors.delete(abidePath)
59
+ return compiled.code
60
+ } catch (error) {
61
+ shadows.set(abidePath, { code: '', mappings: [] })
62
+ parseErrors.set(abidePath, error instanceof Error ? error.message : String(error))
63
+ return 'export default function (): void {}\n'
64
+ }
65
+ }
66
+
67
+ /* All component shadows: those on disk plus any opened (possibly unsaved) ones. */
68
+ const shadowNames = (): string[] => {
69
+ const disk = [...new Bun.Glob('**/*.abide').scanSync({ cwd, onlyFiles: true })]
70
+ .filter((relative) => !relative.includes('node_modules'))
71
+ .map((relative) => resolve(cwd, relative))
72
+ return [...new Set([...disk, ...overlays.keys()])].map(suffixed)
73
+ }
74
+
75
+ const moduleResolutionHost: ts.ModuleResolutionHost = {
76
+ fileExists: (fileName) =>
77
+ fileName === assets.path ||
78
+ (isShadow(fileName) ? exists(sourceOf(fileName)) : ts.sys.fileExists(fileName)),
79
+ readFile: (fileName) =>
80
+ fileName === assets.path
81
+ ? assets.content
82
+ : isShadow(fileName)
83
+ ? shadowText(sourceOf(fileName))
84
+ : ts.sys.readFile(fileName),
85
+ }
86
+
87
+ const host: ts.LanguageServiceHost = {
88
+ getScriptFileNames: () => [assets.path, ...fileNames, ...shadowNames()],
89
+ getScriptVersion: (fileName) => String(versions.get(fileName) ?? 0),
90
+ getScriptSnapshot: (fileName) => {
91
+ if (fileName === assets.path) {
92
+ return ts.ScriptSnapshot.fromString(assets.content)
93
+ }
94
+ if (isShadow(fileName)) {
95
+ return exists(sourceOf(fileName))
96
+ ? ts.ScriptSnapshot.fromString(shadowText(sourceOf(fileName)))
97
+ : undefined
98
+ }
99
+ const text = ts.sys.readFile(fileName)
100
+ return text === undefined ? undefined : ts.ScriptSnapshot.fromString(text)
101
+ },
102
+ getCurrentDirectory: () => cwd,
103
+ getCompilationSettings: () => options,
104
+ getDefaultLibFileName: (compilerOptions) => ts.getDefaultLibFilePath(compilerOptions),
105
+ fileExists: moduleResolutionHost.fileExists,
106
+ readFile: moduleResolutionHost.readFile,
107
+ readDirectory: ts.sys.readDirectory,
108
+ directoryExists: ts.sys.directoryExists,
109
+ getDirectories: ts.sys.getDirectories,
110
+ resolveModuleNames: resolveAbideImports(options, moduleResolutionHost),
111
+ }
112
+ const service = ts.createLanguageService(host, ts.createDocumentRegistry())
113
+
114
+ const bump = (abidePath: string): void => {
115
+ const fileName = suffixed(abidePath)
116
+ versions.set(fileName, (versions.get(fileName) ?? 0) + 1)
117
+ }
118
+
119
+ return {
120
+ update(abidePath, text) {
121
+ overlays.set(abidePath, text)
122
+ bump(abidePath)
123
+ },
124
+ close(abidePath) {
125
+ overlays.delete(abidePath)
126
+ bump(abidePath)
127
+ },
128
+ diagnostics(abidePath) {
129
+ const fileName = suffixed(abidePath)
130
+ /* Fetching diagnostics drives getScriptSnapshot → shadowText, so the
131
+ shadows/parseErrors caches are current before we read them. */
132
+ const raw = [
133
+ ...service.getSyntacticDiagnostics(fileName),
134
+ ...service.getSemanticDiagnostics(fileName),
135
+ ]
136
+ const parseError = parseErrors.get(abidePath)
137
+ if (parseError !== undefined) {
138
+ return [
139
+ {
140
+ file: abidePath,
141
+ start: 0,
142
+ length: 0,
143
+ message: parseError,
144
+ category: ts.DiagnosticCategory.Error,
145
+ },
146
+ ]
147
+ }
148
+ const mappings = shadows.get(abidePath)?.mappings ?? []
149
+ return raw.flatMap((diagnostic) => {
150
+ if (diagnostic.start === undefined) {
151
+ return []
152
+ }
153
+ const located = remapShadowDiagnostic(
154
+ mappings,
155
+ diagnostic.start,
156
+ diagnostic.length ?? 0,
157
+ )
158
+ if (located === undefined) {
159
+ return []
160
+ }
161
+ return [
162
+ {
163
+ file: abidePath,
164
+ start: located.start,
165
+ length: located.length,
166
+ message: ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'),
167
+ category: diagnostic.category,
168
+ },
169
+ ]
170
+ })
171
+ },
172
+ quickInfo(abidePath, sourceOffset) {
173
+ const fileName = suffixed(abidePath)
174
+ /* Compile the shadow first so its mappings are current before we
175
+ translate the source offset into shadow coordinates. */
176
+ shadowText(abidePath)
177
+ const mappings = shadows.get(abidePath)?.mappings ?? []
178
+ const shadowOffset = sourceToShadowOffset(mappings, sourceOffset)
179
+ if (shadowOffset === undefined) {
180
+ return undefined
181
+ }
182
+ const info = service.getQuickInfoAtPosition(fileName, shadowOffset)
183
+ if (info === undefined) {
184
+ return undefined
185
+ }
186
+ /* The reported span is in shadow coordinates; map it back so the editor
187
+ highlights the matching source. Falls back to the hovered offset. */
188
+ const span = remapShadowDiagnostic(mappings, info.textSpan.start, info.textSpan.length)
189
+ return {
190
+ text: ts.displayPartsToString(info.displayParts),
191
+ documentation: ts.displayPartsToString(info.documentation),
192
+ start: span?.start ?? sourceOffset,
193
+ length: span?.length ?? 1,
194
+ }
195
+ },
196
+ }
197
+ }
@@ -0,0 +1,96 @@
1
+ import { resolve } from 'node:path'
2
+ import ts from 'typescript'
3
+ import { assetModulesFile } from './assetModulesFile.ts'
4
+ import { compileShadow } from './compileShadow.ts'
5
+ import { loadShadowTsConfig } from './loadShadowTsConfig.ts'
6
+ import { resolveAbideImports } from './resolveAbideImports.ts'
7
+ import { shadowNaming } from './shadowNaming.ts'
8
+ import type { CompiledShadow } from './types/CompiledShadow.ts'
9
+
10
+ const { suffixed, isShadow, sourceOf } = shadowNaming
11
+
12
+ export type ShadowProgram = {
13
+ program: ts.Program
14
+ /* Compiled shadow (code + mappings) per `.abide` path, populated as the host
15
+ materialises each source file; the diagnostic remapper reads the mappings. */
16
+ shadows: Map<string, CompiledShadow>
17
+ /* Files whose template failed to parse — surfaced as a diagnostic at offset 0. */
18
+ parseErrors: Map<string, string>
19
+ abidePaths: string[]
20
+ }
21
+
22
+ /*
23
+ Builds a `ts.Program` over the project's real `.ts` files plus a virtual shadow
24
+ `.ts` for every `.abide` component, behind a CompilerHost that serves shadow text
25
+ for any `*.abide.ts` name and resolves `.abide` imports to their shadows. Reuses
26
+ the project's tsconfig (lib/paths/baseUrl) so the shadows type-check against the
27
+ same world the app does; `noUnusedLocals`/`noUnusedParameters` are forced off
28
+ because the shadow legitimately declares scope bindings a template may not read.
29
+ */
30
+ export function createShadowProgram(cwd: string, abidePaths?: string[]): ShadowProgram {
31
+ const { options, fileNames } = loadShadowTsConfig(cwd)
32
+ const shadows = new Map<string, CompiledShadow>()
33
+ const parseErrors = new Map<string, string>()
34
+ /* The components to root the program at — caller-supplied (one project's files)
35
+ or, by default, every `.abide` under `cwd`. Imported components resolve on
36
+ demand through the host, so an explicit subset still type-checks fully. */
37
+ const rootAbidePaths =
38
+ abidePaths ??
39
+ [...new Bun.Glob('**/*.abide').scanSync({ cwd, onlyFiles: true })]
40
+ .filter((relative) => !relative.includes('node_modules'))
41
+ .map((relative) => resolve(cwd, relative))
42
+
43
+ /* Compiles (and caches) a `.abide` file's shadow; a template parse error yields
44
+ a minimal valid module and a recorded message so the program still builds. */
45
+ const shadowText = (abidePath: string): string => {
46
+ const source = ts.sys.readFile(abidePath) ?? ''
47
+ try {
48
+ const compiled = compileShadow(source)
49
+ shadows.set(abidePath, compiled)
50
+ parseErrors.delete(abidePath)
51
+ return compiled.code
52
+ } catch (error) {
53
+ shadows.set(abidePath, { code: '', mappings: [] })
54
+ parseErrors.set(abidePath, error instanceof Error ? error.message : String(error))
55
+ return 'export default function (): void {}\n'
56
+ }
57
+ }
58
+
59
+ /* Ambient declarations for bundler-handled asset imports (`*.css`, …). */
60
+ const assets = assetModulesFile(cwd)
61
+
62
+ const host = ts.createCompilerHost(options, true)
63
+ const originalGetSourceFile = host.getSourceFile.bind(host)
64
+ host.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreate) => {
65
+ if (fileName === assets.path) {
66
+ return ts.createSourceFile(fileName, assets.content, languageVersionOrOptions, true)
67
+ }
68
+ if (isShadow(fileName)) {
69
+ return ts.createSourceFile(
70
+ fileName,
71
+ shadowText(sourceOf(fileName)),
72
+ languageVersionOrOptions,
73
+ true,
74
+ ts.ScriptKind.TS,
75
+ )
76
+ }
77
+ return originalGetSourceFile(fileName, languageVersionOrOptions, onError, shouldCreate)
78
+ }
79
+ host.fileExists = (fileName) =>
80
+ fileName === assets.path ||
81
+ (isShadow(fileName) ? ts.sys.fileExists(sourceOf(fileName)) : ts.sys.fileExists(fileName))
82
+ host.readFile = (fileName) => {
83
+ if (fileName === assets.path) {
84
+ return assets.content
85
+ }
86
+ return isShadow(fileName) ? shadowText(sourceOf(fileName)) : ts.sys.readFile(fileName)
87
+ }
88
+ host.resolveModuleNames = resolveAbideImports(options, host)
89
+
90
+ const program = ts.createProgram({
91
+ rootNames: [assets.path, ...fileNames, ...rootAbidePaths.map((path) => suffixed(path))],
92
+ options,
93
+ host,
94
+ })
95
+ return { program, shadows, parseErrors, abidePaths: rootAbidePaths }
96
+ }