@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,42 @@
1
+ import ts from 'typescript'
2
+
3
+ /*
4
+ The signal binding names a `<script>` nested in a control-flow branch declares
5
+ (`state`/`derived`/`prop`). The back-end adds them to the deref scope so both the
6
+ script body and the branch's markup rewrite `{a}` → `a.value` — these stay PLAIN
7
+ signals (local to the branch's render, owned by its scope, re-seeded from the
8
+ in-scope data each mount), unlike the top-level component script which desugars to
9
+ the serializable `doc`.
10
+ */
11
+ export function nestedBindingNames(code: string): Set<string> {
12
+ const source = ts.createSourceFile('nested.ts', code, ts.ScriptTarget.Latest, true)
13
+ const names = new Set<string>()
14
+ for (const statement of source.statements) {
15
+ if (!ts.isVariableStatement(statement)) {
16
+ continue
17
+ }
18
+ for (const declaration of statement.declarationList.declarations) {
19
+ const callee = signalCallee(declaration)
20
+ if (
21
+ (callee === 'state' || callee === 'derived' || callee === 'prop') &&
22
+ ts.isIdentifier(declaration.name)
23
+ ) {
24
+ names.add(declaration.name.text)
25
+ }
26
+ }
27
+ }
28
+ return names
29
+ }
30
+
31
+ /* The callee name of a `NAME = state(...)` / `derived(...)` / `prop(...)` declaration. */
32
+ function signalCallee(declaration: ts.VariableDeclaration): string | undefined {
33
+ const initializer = declaration.initializer
34
+ if (
35
+ initializer !== undefined &&
36
+ ts.isCallExpression(initializer) &&
37
+ ts.isIdentifier(initializer.expression)
38
+ ) {
39
+ return initializer.expression.text
40
+ }
41
+ return undefined
42
+ }
@@ -0,0 +1,30 @@
1
+ import type { ShadowMapping } from './types/CompiledShadow.ts'
2
+
3
+ /*
4
+ Relocates a diagnostic's shadow span back to the original `.abide` source. The
5
+ diagnostic must *overlap* a mapped segment (a verbatim-emitted expression);
6
+ diagnostics confined to synthesised scaffolding overlap nothing and are dropped —
7
+ that is the filter that keeps shadow-internal noise out of the editor. Overlap
8
+ (not containment) is required because TypeScript often reports a whole-expression
9
+ mismatch at the synthetic wrapping `(`, one char before the mapped span; the
10
+ result is clamped into the segment so it lands on real source either way.
11
+ */
12
+ export function remapShadowDiagnostic(
13
+ mappings: ShadowMapping[],
14
+ shadowStart: number,
15
+ shadowLength: number,
16
+ ): { start: number; length: number } | undefined {
17
+ const shadowEnd = shadowStart + Math.max(shadowLength, 1)
18
+ const mapping = mappings.find(
19
+ (entry) => shadowStart < entry.shadowStart + entry.length && entry.shadowStart < shadowEnd,
20
+ )
21
+ if (mapping === undefined) {
22
+ return undefined
23
+ }
24
+ const clampedStart = Math.max(shadowStart, mapping.shadowStart)
25
+ const segmentEnd = mapping.shadowStart + mapping.length
26
+ return {
27
+ start: mapping.sourceStart + (clampedStart - mapping.shadowStart),
28
+ length: Math.max(1, Math.min(shadowEnd, segmentEnd) - clampedStart),
29
+ }
30
+ }
@@ -0,0 +1,85 @@
1
+ import ts from 'typescript'
2
+
3
+ /*
4
+ Rewrites references to a component's signal bindings into the document form the
5
+ rest of the pipeline understands: a `state` binding `count` becomes `model.count`
6
+ (data access `lowerDocAccess` then lowers to a patch/read), and a `derived`
7
+ binding `total` becomes `total.value`. Only value-position identifiers are
8
+ touched — declaration names, parameter names, and property names are collected
9
+ into a skip set first, and object shorthand (`{ count }`) is expanded to
10
+ `{ count: model.count }`. This is the bridge from the signal surface the author
11
+ writes to the patch substrate underneath.
12
+ */
13
+ export function renameSignalRefs(
14
+ code: string,
15
+ stateNames: ReadonlySet<string>,
16
+ derivedNames: ReadonlySet<string>,
17
+ ): string {
18
+ const source = ts.createSourceFile('component.ts', code, ts.ScriptTarget.Latest, true)
19
+
20
+ /* Identifier nodes that are names, not value reads — never rewritten. */
21
+ const skip = new Set<ts.Node>()
22
+ const collect = (node: ts.Node): void => {
23
+ if (ts.isPropertyAccessExpression(node)) {
24
+ skip.add(node.name)
25
+ }
26
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
27
+ skip.add(node.name)
28
+ }
29
+ if (ts.isParameter(node) && ts.isIdentifier(node.name)) {
30
+ skip.add(node.name)
31
+ }
32
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
33
+ skip.add(node.name)
34
+ }
35
+ if (
36
+ (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) &&
37
+ node.name !== undefined
38
+ ) {
39
+ skip.add(node.name)
40
+ }
41
+ ts.forEachChild(node, collect)
42
+ }
43
+ collect(source)
44
+
45
+ const result = ts.transform(source, [
46
+ (context) => (root) => {
47
+ const visit = (node: ts.Node): ts.Node => {
48
+ /* Shorthand `{ count }` → `{ count: model.count }` / `{ total: total.value }`. */
49
+ if (ts.isShorthandPropertyAssignment(node)) {
50
+ const replacement = referenceFor(node.name.text, stateNames, derivedNames)
51
+ if (replacement !== undefined) {
52
+ return ts.factory.createPropertyAssignment(node.name.text, replacement)
53
+ }
54
+ }
55
+ if (ts.isIdentifier(node) && !skip.has(node)) {
56
+ const replacement = referenceFor(node.text, stateNames, derivedNames)
57
+ if (replacement !== undefined) {
58
+ return replacement
59
+ }
60
+ }
61
+ return ts.visitEachChild(node, visit, context)
62
+ }
63
+ return ts.visitNode(root, visit) as ts.SourceFile
64
+ },
65
+ ])
66
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })
67
+ const output = printer.printFile(result.transformed[0] as ts.SourceFile)
68
+ result.dispose()
69
+ return output
70
+ }
71
+
72
+ /* `model.<name>` for a state binding, `<name>.value` for a derived one, else undefined. */
73
+ function referenceFor(
74
+ name: string,
75
+ stateNames: ReadonlySet<string>,
76
+ derivedNames: ReadonlySet<string>,
77
+ ): ts.Expression | undefined {
78
+ if (stateNames.has(name)) {
79
+ return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('model'), name)
80
+ }
81
+ if (derivedNames.has(name)) {
82
+ return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(name), 'value')
83
+ }
84
+ return undefined
85
+ }
@@ -0,0 +1,29 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import ts from 'typescript'
3
+
4
+ /*
5
+ A module-name resolver shared by the shadow Program (check) and LanguageService
6
+ (LSP). A relative `./X.abide` import resolves directly to its virtual shadow
7
+ `./X.abide.ts` (the host serves shadow text for any `*.abide.ts` name), so
8
+ cross-component prop checking works. An aliased `.abide` (`$ui/X.abide`) falls
9
+ through to TypeScript's own resolver, which applies the tsconfig `paths` and —
10
+ because the host reports the shadow `.abide.ts` exists — lands on the same
11
+ shadow. Every other specifier (`abide/*`, `$server/*`, plain relative `.ts`,
12
+ asset modules covered by the ambient declarations) resolves through TypeScript
13
+ directly, exactly as for the real module.
14
+ */
15
+ export function resolveAbideImports(
16
+ options: ts.CompilerOptions,
17
+ host: ts.ModuleResolutionHost,
18
+ ): (moduleNames: string[], containingFile: string) => (ts.ResolvedModule | undefined)[] {
19
+ return (moduleNames, containingFile) =>
20
+ moduleNames.map((name) => {
21
+ if (name.endsWith('.abide')) {
22
+ const relative = resolve(dirname(containingFile), name)
23
+ if (ts.sys.fileExists(relative)) {
24
+ return { resolvedFileName: `${relative}.ts`, extension: ts.Extension.Ts }
25
+ }
26
+ }
27
+ return ts.resolveModuleName(name, containingFile, options, host).resolvedModule
28
+ })
29
+ }
@@ -0,0 +1,115 @@
1
+ /*
2
+ Scopes a component's CSS to its own elements by appending an attribute selector
3
+ (`[data-a-<hash>]`) to each rule's key compound selector — the proven approach
4
+ (every element the component renders carries the attribute, so descendant
5
+ selectors still resolve, but styles never leak out). At-rule preludes (`@media`,
6
+ etc.) pass through untouched while the nested rules inside them are still scoped.
7
+ The attribute is inserted before any pseudo (`a:hover` → `a[attr]:hover`) so the
8
+ selector stays valid.
9
+ */
10
+ export function scopeCss(css: string, attribute: string): string {
11
+ let result = ''
12
+ let prelude = '' // chars accumulated since the last brace
13
+ let depth = 0
14
+ let keyframesDepth = -1 // brace depth of the open @keyframes block, or -1 when outside one
15
+ for (const char of css) {
16
+ if (char === '{') {
17
+ const insideKeyframes = keyframesDepth !== -1 && depth >= keyframesDepth
18
+ if (prelude.trim().startsWith('@')) {
19
+ /* At-rule prelude: leave it; its inner rules scope on their own. A
20
+ @keyframes block is the exception — its `from`/`to`/`%` steps aren't
21
+ selectors, so track its depth and leave the steps inside it bare. */
22
+ if (/^@(-[a-z]+-)?keyframes\b/i.test(prelude.trim())) {
23
+ keyframesDepth = depth + 1
24
+ }
25
+ result += `${prelude}{`
26
+ } else if (insideKeyframes) {
27
+ result += `${prelude}{` // a keyframe step (from/to/%) — not a selector
28
+ } else {
29
+ result += `${scopeSelectorList(prelude, attribute)} {`
30
+ }
31
+ depth += 1
32
+ prelude = ''
33
+ } else if (char === '}') {
34
+ result += `${prelude}}`
35
+ prelude = ''
36
+ depth -= 1
37
+ if (keyframesDepth !== -1 && depth < keyframesDepth) {
38
+ keyframesDepth = -1
39
+ }
40
+ } else {
41
+ prelude += char
42
+ }
43
+ }
44
+ return result + prelude
45
+ }
46
+
47
+ /* Scopes each selector in a comma-separated list, splitting at top-level commas
48
+ only so a `,` inside `:is(.a, .b)` / `[attr=","]` doesn't fragment a selector. */
49
+ function scopeSelectorList(prelude: string, attribute: string): string {
50
+ return splitSelectorList(prelude)
51
+ .map((selector) => scopeSelector(selector.trim(), attribute))
52
+ .join(', ')
53
+ }
54
+
55
+ /* Splits a selector list on commas that aren't nested inside `()` or `[]`. */
56
+ function splitSelectorList(prelude: string): string[] {
57
+ const selectors: string[] = []
58
+ let current = ''
59
+ let nesting = 0
60
+ for (const char of prelude) {
61
+ if (char === '(' || char === '[') {
62
+ nesting += 1
63
+ } else if (char === ')' || char === ']') {
64
+ nesting -= 1
65
+ }
66
+ if (char === ',' && nesting === 0) {
67
+ selectors.push(current)
68
+ current = ''
69
+ } else {
70
+ current += char
71
+ }
72
+ }
73
+ selectors.push(current)
74
+ return selectors
75
+ }
76
+
77
+ /* Appends `[attribute]` to a selector's last compound, before any pseudo. */
78
+ function scopeSelector(selector: string, attribute: string): string {
79
+ if (selector === '') {
80
+ return selector
81
+ }
82
+ const match = selector.match(/^(.*?)([^\s>+~]+)$/)
83
+ if (match === null) {
84
+ return `${selector}[${attribute}]`
85
+ }
86
+ const prefix = match[1] ?? ''
87
+ const last = match[2] ?? ''
88
+ const pseudo = pseudoIndex(last)
89
+ const scopedLast =
90
+ pseudo === -1
91
+ ? `${last}[${attribute}]`
92
+ : `${last.slice(0, pseudo)}[${attribute}]${last.slice(pseudo)}`
93
+ return `${prefix}${scopedLast}`
94
+ }
95
+
96
+ /*
97
+ Index of the first pseudo-class/element colon in a compound — i.e. a `:` at
98
+ bracket depth zero. Skips colons inside an attribute selector's value
99
+ (e.g. `a[href='http://x']`), which must not be treated as a pseudo boundary.
100
+ Returns -1 when the compound has no pseudo.
101
+ */
102
+ function pseudoIndex(compound: string): number {
103
+ let depth = 0
104
+ for (let index = 0; index < compound.length; index += 1) {
105
+ const char = compound[index]
106
+ if (char === '[') {
107
+ depth += 1
108
+ } else if (char === ']') {
109
+ depth -= 1
110
+ } else if (char === ':' && depth === 0) {
111
+ return index
112
+ }
113
+ }
114
+ return -1
115
+ }
@@ -0,0 +1,11 @@
1
+ /*
2
+ A `.abide` component's virtual shadow is the same absolute path with `.ts`
3
+ appended (`Foo.abide` → `Foo.abide.ts`). The suffix lets a TypeScript host tell a
4
+ shadow apart from a real file and recover the source path. Shared by the one-shot
5
+ Program (`createShadowProgram`) and the incremental LanguageService (the LSP).
6
+ */
7
+ export const shadowNaming = {
8
+ suffixed: (abidePath: string): string => `${abidePath}.ts`,
9
+ isShadow: (fileName: string): boolean => fileName.endsWith('.abide.ts'),
10
+ sourceOf: (shadowName: string): string => shadowName.slice(0, -'.ts'.length),
11
+ }
@@ -0,0 +1,24 @@
1
+ import type { ShadowMapping } from './types/CompiledShadow.ts'
2
+
3
+ /*
4
+ Translates an offset in the original `.abide` source to the equivalent offset in
5
+ its type-checking shadow — the inverse of `remapShadowDiagnostic`. Drives
6
+ position-based language-service queries (hover, completion, …) from an editor
7
+ position: find the verbatim-emitted segment whose source span covers the offset
8
+ and shift it into shadow coordinates. An offset outside every mapped span
9
+ (whitespace, markup, framework syntax the shadow doesn't emit verbatim) has no
10
+ shadow position, so the query is skipped.
11
+ */
12
+ export function sourceToShadowOffset(
13
+ mappings: ShadowMapping[],
14
+ sourceOffset: number,
15
+ ): number | undefined {
16
+ const mapping = mappings.find(
17
+ (entry) =>
18
+ entry.sourceStart <= sourceOffset && sourceOffset < entry.sourceStart + entry.length,
19
+ )
20
+ if (mapping === undefined) {
21
+ return undefined
22
+ }
23
+ return mapping.shadowStart + (sourceOffset - mapping.sourceStart)
24
+ }
@@ -0,0 +1,13 @@
1
+ import type { TemplateNode } from './types/TemplateNode.ts'
2
+
3
+ /* The value of a static attribute on an element node, or undefined when absent.
4
+ Used to read directive attributes like `slot` / `slot name` off the template. */
5
+ export function staticAttrValue(
6
+ node: Extract<TemplateNode, { kind: 'element' }>,
7
+ name: string,
8
+ ): string | undefined {
9
+ const attr = node.attrs.find(
10
+ (candidate) => candidate.kind === 'static' && candidate.name === name,
11
+ )
12
+ return attr !== undefined && attr.kind === 'static' ? attr.value : undefined
13
+ }
@@ -0,0 +1,32 @@
1
+ import ts from 'typescript'
2
+
3
+ /*
4
+ Removes `effect(...)` calls from a script for the SSR back-end. Effects are client
5
+ lifecycle — they touch the DOM / run side effects and emit no HTML, so the server
6
+ render (a snapshot of the pre-effect markup, like every framework) must not run
7
+ them. Every `effect(<args>)` call is replaced by `undefined`, dropping its body:
8
+ an `effect(() => …)` statement becomes a no-op, and a `const stop = effect(…)`
9
+ binding keeps a defined (unused) name. Client compilation keeps effects untouched.
10
+ */
11
+ export function stripEffects(code: string): string {
12
+ const source = ts.createSourceFile('script.ts', code, ts.ScriptTarget.Latest, true)
13
+ const result = ts.transform(source, [
14
+ (context) => (root) => {
15
+ const visit = (node: ts.Node): ts.Node => {
16
+ if (
17
+ ts.isCallExpression(node) &&
18
+ ts.isIdentifier(node.expression) &&
19
+ node.expression.text === 'effect'
20
+ ) {
21
+ return ts.factory.createIdentifier('undefined')
22
+ }
23
+ return ts.visitEachChild(node, visit, context)
24
+ }
25
+ return ts.visitNode(root, visit) as ts.SourceFile
26
+ },
27
+ ])
28
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })
29
+ const output = printer.printFile(result.transformed[0] as ts.SourceFile)
30
+ result.dispose()
31
+ return output
32
+ }
@@ -0,0 +1,14 @@
1
+ import type ts from 'typescript'
2
+
3
+ /*
4
+ A type-check diagnostic relocated onto a `.abide` source file: `start`/`length`
5
+ are an offset range in the original component file (not the shadow), ready for a
6
+ CLI to render or the LSP to convert to a line/character range.
7
+ */
8
+ export type AbideDiagnostic = {
9
+ file: string
10
+ start: number
11
+ length: number
12
+ message: string
13
+ category: ts.DiagnosticCategory
14
+ }
@@ -0,0 +1,25 @@
1
+ import type { TemplateNode } from './TemplateNode.ts'
2
+
3
+ /*
4
+ The shared front-end result for a component, consumed by both the client
5
+ (`generateBuild`) and server (`generateSSR`) code generators: the lowered script
6
+ (signal surface desugared to the doc patch/read API), the signal binding names
7
+ (so template expressions rewrite consistently), and the parsed template tree.
8
+ */
9
+ export type AnalyzedComponent = {
10
+ script: string
11
+ /* Top-level import statements hoisted out of the script (e.g. child
12
+ components), placed at module scope by the module wrapper. */
13
+ imports: string
14
+ stateNames: Set<string>
15
+ derivedNames: Set<string>
16
+ nodes: TemplateNode[]
17
+ /* One entry per non-empty `<style>` in the template (in source order): the scope
18
+ attribute its covered elements carry (annotated onto `nodes`) and the scoped
19
+ CSS to bundle. A top-level `<style>` covers the whole component; a nested one
20
+ covers only its sibling subtree. Empty for a component with no style. */
21
+ styles: { attribute: string; css: string }[]
22
+ /* False when the template contains an `await` block (not adoptable yet) — the
23
+ router mounts (re-renders) rather than hydrates such a page. */
24
+ hydratable: boolean
25
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ The type-checking shadow of a `.abide` component: a synthetic `.ts` module that
3
+ reconstructs the author-facing scope with value types and references every
4
+ template expression in a checkable position, plus the segment map that relocates
5
+ a diagnostic in the shadow back to the original `.abide` source.
6
+
7
+ Each mapping covers one verbatim-emitted span: `length` characters at `shadowStart`
8
+ in the shadow correspond to the same `length` characters at `sourceStart` in the
9
+ `.abide` file (expressions are emitted unchanged, so the spans are equal length).
10
+ A shadow offset inside a mapping translates to `sourceStart + (offset - shadowStart)`;
11
+ an offset in no mapping is synthesised scaffolding and its diagnostic is dropped.
12
+ */
13
+ export type ShadowMapping = { shadowStart: number; sourceStart: number; length: number }
14
+
15
+ export type CompiledShadow = { code: string; mappings: ShadowMapping[] }
@@ -0,0 +1,16 @@
1
+ /*
2
+ An element attribute. `static` is a literal; `expression` is `name={code}` bound
3
+ reactively; `event` is `on<event>={code}` where `code` evaluates to the handler;
4
+ `bind` is `bind:<property>={lvalue}`, a two-way binding whose `code` is the
5
+ writable doc path read into the property and written back on input; `attach` is
6
+ `attach={code}` where `code` evaluates to an attachment `(node) => teardown` run
7
+ at build with node-lifetime teardown. `loc` is the
8
+ absolute offset of `code` in the original `.abide` source (see TextPart) —
9
+ optional, set only when the parser tracks positions for the type-checking shadow.
10
+ */
11
+ export type TemplateAttr =
12
+ | { kind: 'static'; name: string; value: string }
13
+ | { kind: 'expression'; name: string; code: string; loc?: number }
14
+ | { kind: 'event'; event: string; code: string; loc?: number }
15
+ | { kind: 'bind'; property: string; code: string; loc?: number }
16
+ | { kind: 'attach'; code: string; loc?: number }
@@ -0,0 +1,78 @@
1
+ import type { TemplateAttr } from './TemplateAttr.ts'
2
+ import type { TextPart } from './TextPart.ts'
3
+
4
+ /*
5
+ A parsed template node. `text` carries interpolation parts; `element` carries
6
+ attributes and children; `each` is the `<template each as key>` control flow over
7
+ a list. (if/await/switch are future siblings.)
8
+
9
+ `loc` (where present) is the absolute offset of the node's primary expression in
10
+ the original `.abide` source — additive, set only when the parser tracks
11
+ positions for the type-checking shadow, ignored by the runtime back-ends.
12
+ */
13
+ export type TemplateNode =
14
+ | { kind: 'text'; parts: TextPart[] }
15
+ | { kind: 'script'; code: string }
16
+ /* A `<style>` declared in the template. `css` is its raw body, read structurally
17
+ so a `<style>` inside an expression isn't mistaken for one. The node stays in
18
+ place: it scopes its sibling subtree, so the front-end derives each scope
19
+ attribute and the elements it covers from the node's position (see
20
+ `analyzeComponent`). Emits no DOM/markup. */
21
+ | { kind: 'style'; css: string }
22
+ | {
23
+ kind: 'element'
24
+ tag: string
25
+ attrs: TemplateAttr[]
26
+ children: TemplateNode[]
27
+ /* The scope attributes (`data-a-…`) this element carries — one per `<style>`
28
+ active at its position (its own sibling list plus every ancestor's),
29
+ filled by `analyzeComponent`. Absent until annotated. */
30
+ scopes?: string[]
31
+ }
32
+ | {
33
+ kind: 'each'
34
+ items: string
35
+ as: string
36
+ key: string | undefined
37
+ /* `await` on the tag → `items` is an AsyncIterable, drained on the client. */
38
+ async: boolean
39
+ children: TemplateNode[]
40
+ loc?: number
41
+ }
42
+ | { kind: 'if'; condition: string; children: TemplateNode[]; loc?: number }
43
+ | {
44
+ kind: 'await'
45
+ promise: string
46
+ /* `then` riding the `await` tag (`<template await={p} then={v}>`) makes the
47
+ block BLOCKING: no pending branch, children are the resolved content bound
48
+ to `as`, SSR settles before the first flush. Absent → streaming. */
49
+ blocking: boolean
50
+ as: string | undefined
51
+ children: TemplateNode[]
52
+ loc?: number
53
+ }
54
+ | { kind: 'try'; children: TemplateNode[] }
55
+ | {
56
+ kind: 'branch'
57
+ branch: 'then' | 'catch' | 'finally'
58
+ as: string | undefined
59
+ children: TemplateNode[]
60
+ }
61
+ | {
62
+ kind: 'component'
63
+ name: string
64
+ props: { name: string; code: string; loc?: number }[]
65
+ children: TemplateNode[]
66
+ }
67
+ | { kind: 'switch'; subject: string; children: TemplateNode[]; loc?: number }
68
+ | { kind: 'case'; match: string | undefined; children: TemplateNode[]; loc?: number }
69
+ /* A `<template name="row" args={item}>` snippet: a named, scope-capturing
70
+ builder declared once and called like a function (`{row(item)}`). `params`
71
+ is the raw `args` source spliced into the builder's parameter list. */
72
+ | {
73
+ kind: 'snippet'
74
+ name: string
75
+ params: string | undefined
76
+ children: TemplateNode[]
77
+ loc?: number
78
+ }
@@ -0,0 +1,8 @@
1
+ /* A piece of a text node: literal characters, or a `{expr}` interpolation whose
2
+ `code` is lowered and bound reactively. `loc` is the absolute offset of the
3
+ expression's first character in the original `.abide` source — present only
4
+ when the parser was given the source's base offset; the runtime back-ends
5
+ ignore it, the type-checking shadow maps diagnostics through it. */
6
+ export type TextPart =
7
+ | { kind: 'static'; value: string }
8
+ | { kind: 'expression'; code: string; loc?: number }
@@ -0,0 +1,28 @@
1
+ import { createComputedNode } from './runtime/createComputedNode.ts'
2
+ import { OWNER } from './runtime/OWNER.ts'
3
+ import { readNode } from './runtime/readNode.ts'
4
+ import type { Derived } from './runtime/types/Derived.ts'
5
+ import { unlinkDeps } from './runtime/unlinkDeps.ts'
6
+
7
+ /*
8
+ A read-only reactive cell computed from other cells — the abide replacement for
9
+ `$derived`. Lazy: it recomputes on read only when a dependency has changed, and
10
+ never serializes (it is re-derived from its inputs on resume). Read via `.value`.
11
+ */
12
+ // @readme plumbing
13
+ export function derived<T>(compute: () => T): Derived<T> {
14
+ const node = createComputedNode(compute as () => unknown)
15
+ /* Tear down with the enclosing scope, the way an effect does. A computed only
16
+ unlinks from its sources when it re-runs (`runNode` re-tracking); one read
17
+ once and then abandoned never re-runs, so absent this it would sit in its
18
+ source signals' subscriber lists forever — re-marked dirty on every write to
19
+ them — for the source's lifetime. Outside a scope it owns its own life (no-op). */
20
+ if (OWNER.current !== undefined) {
21
+ OWNER.current.push(() => unlinkDeps(node))
22
+ }
23
+ return {
24
+ get value(): T {
25
+ return readNode(node) as T
26
+ },
27
+ }
28
+ }
@@ -0,0 +1,15 @@
1
+ import { createDoc } from './runtime/createDoc.ts'
2
+ import type { Doc } from './runtime/types/Doc.ts'
3
+
4
+ /*
5
+ Creates a reactive document: a single immutable, serializable tree addressed by
6
+ path, where every change is a patch. `doc.read(path)` is path-granular reactive
7
+ read; `doc.replace/add/remove` emit patches that wake only the readers whose
8
+ paths the change touched. This is the substrate the whole framework stands on —
9
+ deep reactivity, resumability, undo, and sync all reduce to "a patch over a
10
+ path", so they share one mechanism instead of being bolted on.
11
+ */
12
+ // @readme plumbing
13
+ export function doc(initial: unknown = {}): Doc {
14
+ return createDoc(initial)
15
+ }
@@ -0,0 +1,34 @@
1
+ import { snippetPayload } from '../../shared/snippet.ts'
2
+ import { claimChild } from '../runtime/claimChild.ts'
3
+ import { RENDER } from '../runtime/RENDER.ts'
4
+
5
+ /*
6
+ A `{snippet(args)}` interpolation: mount the branded builder's nodes at this
7
+ position. The builder builds straight into `parent` — sequential build order
8
+ places it correctly among siblings, and its effects join the surrounding
9
+ component scope (so they tear down with it). The body's reactive reads update
10
+ fine-grained via those effects; an enclosing `each` re-mounts on list changes.
11
+
12
+ On hydrate the builder runs against the server-rendered nodes between the
13
+ `<!--abide:snippet-->`/`<!--/abide:snippet-->` markers — its `openChild`/`appendText`
14
+ claim them in place. The cursor is advanced past the open marker before, and past
15
+ the close marker after, so the markers themselves are skipped.
16
+ */
17
+ // @readme plumbing
18
+ export function appendSnippet(parent: Node, read: () => unknown): void {
19
+ const builder = snippetPayload(read())
20
+ if (typeof builder !== 'function') {
21
+ return
22
+ }
23
+ const mount = builder as (host: Node) => void
24
+ const hydration = RENDER.hydration
25
+ if (hydration !== undefined) {
26
+ const open = claimChild(hydration, parent)
27
+ hydration.next.set(parent, open === null ? null : open.nextSibling)
28
+ mount(parent)
29
+ const close = claimChild(hydration, parent)
30
+ hydration.next.set(parent, close === null ? null : close.nextSibling)
31
+ return
32
+ }
33
+ mount(parent)
34
+ }
@@ -0,0 +1,27 @@
1
+ import { claimChild } from '../runtime/claimChild.ts'
2
+ import { RENDER } from '../runtime/RENDER.ts'
3
+
4
+ /*
5
+ A static (non-reactive) text node under `parent`: created and appended (create
6
+ mode), or claimed from the server-rendered text (hydrate mode). As with reactive
7
+ text, a merged SSR text node is split at this literal's length so the next claim
8
+ lines up; nothing is bound since the text never changes.
9
+ */
10
+ // @readme plumbing
11
+ export function appendStatic(parent: Node, value: string, splitAlways = false): void {
12
+ const hydration = RENDER.hydration
13
+ if (hydration !== undefined) {
14
+ const node = claimChild(hydration, parent) as unknown as Text
15
+ /* Split even on an exact-length consume when a sibling text binding follows
16
+ (`splitAlways`), so it gets its own node; see appendText for the rationale. */
17
+ if (
18
+ node !== null &&
19
+ (splitAlways ? value.length <= node.data.length : value.length < node.data.length)
20
+ ) {
21
+ node.splitText(value.length)
22
+ }
23
+ hydration.next.set(parent, node === null ? null : node.nextSibling)
24
+ return
25
+ }
26
+ parent.appendChild(document.createTextNode(value))
27
+ }