@akanjs/devkit 3.0.0-beta.9 → 3.0.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 (341) hide show
  1. package/DEV_RUNTIME_KNOBS.md +44 -26
  2. package/README.ko.md +21 -7
  3. package/README.md +17 -8
  4. package/abstractDoc.test.ts +6 -15
  5. package/abstractDoc.ts +6 -8
  6. package/agentsIndex.test.ts +4 -7
  7. package/agentsIndex.ts +6 -22
  8. package/akanApp/BackendImportGraph.test.ts +8 -22
  9. package/akanApp/BackendImportGraph.ts +1 -20
  10. package/akanApp/akanApp.host.test.ts +56 -3
  11. package/akanApp/akanApp.host.ts +218 -278
  12. package/akanApp/devBootLatch.test.ts +39 -0
  13. package/akanApp/devBootLatch.ts +39 -0
  14. package/akanApp/devHostPolicy.test.ts +81 -35
  15. package/akanApp/devHostPolicy.ts +41 -102
  16. package/akanConfig/akanBin.test.ts +62 -0
  17. package/akanConfig/akanBin.ts +78 -0
  18. package/akanConfig/akanConfig.test.ts +439 -141
  19. package/akanConfig/akanConfig.ts +359 -275
  20. package/akanConfig/index.ts +1 -0
  21. package/akanConfig/types.ts +22 -8
  22. package/akanContext.ts +110 -160
  23. package/akanMcpContract.ts +28 -73
  24. package/appSelectionMemory.ts +1 -4
  25. package/applicationBuildReporter.ts +37 -5
  26. package/applicationBuildRunner.test.ts +41 -5
  27. package/applicationBuildRunner.ts +71 -63
  28. package/applicationTestPreload.ts +3 -12
  29. package/artifact/implicitRootLayout.test.ts +32 -30
  30. package/artifact/implicitRootLayout.ts +58 -106
  31. package/artifact/routeSeedIndex.test.ts +7 -6
  32. package/artifact/routeSeedIndex.ts +11 -44
  33. package/biome.base.json +35 -2
  34. package/biomeBase.ts +2 -5
  35. package/cloud/cloudApi.test.ts +202 -0
  36. package/cloud/cloudApi.ts +77 -39
  37. package/cloud/configLock.test.ts +64 -0
  38. package/cloud/configLock.ts +96 -0
  39. package/cloud/constants.ts +26 -5
  40. package/cloud/globalConfig.ts +71 -32
  41. package/codeAgent/agent/AkanCodeServices.ts +97 -0
  42. package/codeAgent/agent/AkanContextFiles.ts +94 -0
  43. package/codeAgent/agent/CodeAgent.ts +551 -0
  44. package/codeAgent/agent/CodeAgentAsks.ts +66 -0
  45. package/codeAgent/agent/CodeAgentEventMapper.ts +225 -0
  46. package/codeAgent/agent/CodeAgentGate.ts +93 -0
  47. package/codeAgent/agent/CodeAgentProxy.ts +82 -0
  48. package/codeAgent/agent/CodeAgentRpcHost.ts +103 -0
  49. package/codeAgent/agent/CodeAgentRpcListener.ts +109 -0
  50. package/codeAgent/agent/CodeAgentStreamPrinter.ts +86 -0
  51. package/codeAgent/agent/CodeAgentSuspended.ts +85 -0
  52. package/codeAgent/agent/CodeAgentUi.ts +47 -0
  53. package/codeAgent/agent/CodeMailbox.ts +148 -0
  54. package/codeAgent/agent/CodeSessionFork.ts +56 -0
  55. package/codeAgent/agent/CodeSessionIndex.ts +78 -0
  56. package/codeAgent/agent/SubagentPool.ts +214 -0
  57. package/codeAgent/agent/akanCodeModel.ts +47 -0
  58. package/codeAgent/agent/akanCodePaths.ts +31 -0
  59. package/codeAgent/agent/akanContextFiles.test.ts +114 -0
  60. package/codeAgent/agent/akanSystemPrompt.ts +46 -0
  61. package/codeAgent/agent/codeAgent.test.ts +178 -0
  62. package/codeAgent/agent/codeAgentContract.test.ts +523 -0
  63. package/codeAgent/agent/codeAgentProxy.test.ts +74 -0
  64. package/codeAgent/agent/codeAgentRpcListener.test.ts +113 -0
  65. package/codeAgent/agent/codeAgentSuspended.test.ts +47 -0
  66. package/codeAgent/agent/codeMailbox.test.ts +76 -0
  67. package/codeAgent/agent/codeSessionFork.test.ts +58 -0
  68. package/codeAgent/agent/codeSessionIndex.test.ts +77 -0
  69. package/codeAgent/agent/consoleToStderr.ts +8 -0
  70. package/codeAgent/agent/jsonLines.ts +29 -0
  71. package/codeAgent/agent/stringArg.ts +5 -0
  72. package/codeAgent/feedback/DevLogFeedback.ts +82 -0
  73. package/codeAgent/feedback/PreviewChrome.ts +82 -0
  74. package/codeAgent/feedback/PreviewFeedback.ts +46 -0
  75. package/codeAgent/feedback/PreviewView.ts +95 -0
  76. package/codeAgent/feedback/TurnFeedback.ts +98 -0
  77. package/codeAgent/feedback/VerifyFeedback.ts +40 -0
  78. package/codeAgent/feedback/previewChrome.test.ts +73 -0
  79. package/codeAgent/index.ts +34 -0
  80. package/codeAgent/skills/akan-code/SKILL.md +130 -0
  81. package/codeAgent/skills/akan-debug/SKILL.md +42 -0
  82. package/codeAgent/skills/akan-deps/SKILL.md +50 -0
  83. package/codeAgent/skills/akan-err/SKILL.md +39 -0
  84. package/codeAgent/skills/akan-module/SKILL.md +45 -0
  85. package/codeAgent/skills/akan-scaffold/SKILL.md +76 -0
  86. package/codeAgent/skills/akan-scalar/SKILL.md +52 -0
  87. package/codeAgent/skills/akan-service/SKILL.md +34 -0
  88. package/codeAgent/skills/akan-store/SKILL.md +67 -0
  89. package/codeAgent/skills/akan-ui/SKILL.md +63 -0
  90. package/codeAgent/skills/akan-validate/SKILL.md +44 -0
  91. package/codeAgent/tools/AkanCli.ts +50 -0
  92. package/codeAgent/tools/AkanCodePlugins.ts +136 -0
  93. package/codeAgent/tools/AkanEditScope.ts +48 -0
  94. package/codeAgent/tools/AkanEnvKeys.ts +50 -0
  95. package/codeAgent/tools/AkanToolPack.ts +92 -0
  96. package/codeAgent/tools/AkanVerifier.ts +48 -0
  97. package/codeAgent/tools/AskToolPack.ts +99 -0
  98. package/codeAgent/tools/MailToolPack.ts +76 -0
  99. package/codeAgent/tools/McpClient.ts +187 -0
  100. package/codeAgent/tools/McpOAuth.ts +233 -0
  101. package/codeAgent/tools/McpOAuthLoopback.ts +64 -0
  102. package/codeAgent/tools/McpServerConfig.ts +129 -0
  103. package/codeAgent/tools/McpSignIn.ts +158 -0
  104. package/codeAgent/tools/McpTokenStore.ts +81 -0
  105. package/codeAgent/tools/McpToolPack.ts +199 -0
  106. package/codeAgent/tools/SessionToolPack.ts +91 -0
  107. package/codeAgent/tools/WebToolPack.ts +147 -0
  108. package/codeAgent/tools/akanCodePlugins.test.ts +677 -0
  109. package/codeAgent/tools/askToolPack.test.ts +116 -0
  110. package/codeAgent/tools/mcpOAuth.test.ts +612 -0
  111. package/codeAgent/tools/mcpServerConfig.test.ts +212 -0
  112. package/codegenLock.test.ts +4 -13
  113. package/codegenLock.ts +3 -17
  114. package/commandDecorators/argMeta.ts +1 -5
  115. package/commandDecorators/camelToKebabCase.ts +1 -0
  116. package/commandDecorators/command.ts +46 -102
  117. package/commandDecorators/commandBuilder.ts +30 -61
  118. package/commandDecorators/commandDecorators.test.ts +2 -10
  119. package/commandDecorators/dependencyBuilder.ts +10 -1
  120. package/commandDecorators/helpFormatter.ts +68 -145
  121. package/commandDecorators/index.ts +0 -2
  122. package/commandDecorators/targetMeta.ts +9 -7
  123. package/createTunnel.ts +7 -14
  124. package/csrE2e/csrE2eHarness.fixture.ts +505 -0
  125. package/csrE2e/csrFastRefresh.e2e.test.ts +233 -0
  126. package/csrE2e/csrPageStack.e2e.test.ts +252 -0
  127. package/csrE2e/csrPatchFirst.e2e.test.ts +87 -0
  128. package/csrE2e/csrRootLayout.e2e.test.ts +134 -0
  129. package/csrE2e/devHmrLatency.e2e.test.ts +391 -0
  130. package/csrE2e/registryVendor.e2e.test.ts +221 -0
  131. package/csrE2e/ssrRegistry.e2e.test.ts +644 -0
  132. package/dependencyScanner.test.ts +4 -16
  133. package/dependencyScanner.ts +31 -80
  134. package/devkitUtils.test.ts +48 -20
  135. package/executors.linkFallback.test.ts +103 -0
  136. package/executors.test.ts +176 -106
  137. package/executors.ts +212 -498
  138. package/fileEditor.ts +9 -37
  139. package/{getDirname.test.ts → fileSys.test.ts} +5 -3
  140. package/fileSys.ts +22 -9
  141. package/formSetterScanner.ts +3 -16
  142. package/frontendBuild/allRoutesBuilder.ts +7 -21
  143. package/frontendBuild/autoImportSync.test.ts +27 -38
  144. package/frontendBuild/autoImportSync.ts +31 -65
  145. package/frontendBuild/buildRouteClient.test.ts +123 -37
  146. package/frontendBuild/bundleDefine.test.ts +12 -0
  147. package/frontendBuild/bundleDefine.ts +16 -0
  148. package/frontendBuild/clientBuildTypes.ts +5 -36
  149. package/frontendBuild/clientEntriesBundler.ts +9 -40
  150. package/frontendBuild/clientEntryDiscovery.test.ts +112 -0
  151. package/frontendBuild/clientEntryDiscovery.ts +122 -110
  152. package/frontendBuild/csrArtifactBuilder.ts +9 -31
  153. package/frontendBuild/csrDevArtifactWriter.test.ts +151 -0
  154. package/frontendBuild/csrDevArtifactWriter.ts +307 -0
  155. package/frontendBuild/csrDevBundler.test.ts +66 -0
  156. package/frontendBuild/csrDevBundler.ts +95 -0
  157. package/frontendBuild/csrDevFactoryCheck.test.ts +33 -0
  158. package/frontendBuild/csrDevFactoryCheck.ts +39 -0
  159. package/frontendBuild/csrDevModuleCompiler.test.ts +293 -0
  160. package/frontendBuild/csrDevModuleCompiler.ts +422 -0
  161. package/frontendBuild/csrDevPatcher.test.ts +572 -0
  162. package/frontendBuild/csrDevPatcher.ts +548 -0
  163. package/frontendBuild/csrDevPaths.ts +145 -0
  164. package/frontendBuild/csrDevResolver.test.ts +239 -0
  165. package/frontendBuild/csrDevResolver.ts +363 -0
  166. package/frontendBuild/csrDevTypes.ts +61 -0
  167. package/frontendBuild/csrEntryFiles.ts +24 -0
  168. package/frontendBuild/cssCandidateCache.test.ts +0 -6
  169. package/frontendBuild/cssCandidateCache.ts +6 -41
  170. package/frontendBuild/cssCompiler.ts +31 -82
  171. package/frontendBuild/cssImportResolver.ts +6 -19
  172. package/frontendBuild/devChangePlanner.ts +7 -10
  173. package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
  174. package/frontendBuild/devGeneratedIndexSync.ts +1 -4
  175. package/frontendBuild/devRegistryBundler.ts +192 -0
  176. package/frontendBuild/fontOptimizer.test.ts +6 -14
  177. package/frontendBuild/fontOptimizer.ts +15 -72
  178. package/frontendBuild/fontPruner.test.ts +5 -10
  179. package/frontendBuild/fontPruner.ts +5 -20
  180. package/frontendBuild/frontendBuild.test.ts +57 -70
  181. package/frontendBuild/hmrChangeClassifier.ts +2 -2
  182. package/frontendBuild/hmrWatcher.test.ts +59 -32
  183. package/frontendBuild/hmrWatcher.ts +31 -74
  184. package/frontendBuild/index.ts +4 -0
  185. package/frontendBuild/pagesBundleBuilder.ts +28 -30
  186. package/frontendBuild/pagesEntrySourceGenerator.ts +56 -6
  187. package/frontendBuild/precompressArtifacts.ts +5 -18
  188. package/frontendBuild/registryMetadataFingerprint.test.ts +63 -0
  189. package/frontendBuild/registryMetadataFingerprint.ts +28 -0
  190. package/frontendBuild/routeClientBuilder.ts +100 -62
  191. package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
  192. package/frontendBuild/serverGraphFile.test.ts +77 -0
  193. package/frontendBuild/serverGraphFile.ts +93 -0
  194. package/frontendBuild/sourceMtimeIndex.test.ts +41 -97
  195. package/frontendBuild/sourceMtimeIndex.ts +19 -130
  196. package/frontendBuild/ssrBaseArtifactBuilder.ts +19 -13
  197. package/frontendBuild/ssrDevBundler.ts +85 -0
  198. package/frontendBuild/styleContract.ts +1 -8
  199. package/frontendBuild/themeValidator.ts +4 -26
  200. package/frontendBuild/watchRootResolver.test.ts +23 -42
  201. package/frontendBuild/watchRootResolver.ts +5 -27
  202. package/getRelatedCnsts.ts +12 -92
  203. package/incrementalBuilder/buildBatch.proc.ts +147 -63
  204. package/incrementalBuilder/buildBatchProtocol.ts +13 -38
  205. package/incrementalBuilder/buildBatchRunner.test.ts +65 -0
  206. package/incrementalBuilder/buildBatchRunner.ts +26 -38
  207. package/incrementalBuilder/builderChannel.test.ts +24 -49
  208. package/incrementalBuilder/builderChannel.ts +6 -37
  209. package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
  210. package/incrementalBuilder/builderRequestRouter.ts +5 -24
  211. package/incrementalBuilder/builderWorkQueue.test.ts +94 -0
  212. package/incrementalBuilder/builderWorkQueue.ts +126 -0
  213. package/incrementalBuilder/devWatchBatch.test.ts +21 -24
  214. package/incrementalBuilder/incrementalBuilder.host.test.ts +53 -56
  215. package/incrementalBuilder/incrementalBuilder.host.ts +68 -81
  216. package/incrementalBuilder/incrementalBuilder.proc.test.ts +270 -0
  217. package/incrementalBuilder/incrementalBuilder.proc.ts +596 -208
  218. package/index.ts +5 -19
  219. package/integration/devResourceProbe.ts +50 -56
  220. package/integration/devStability.integration.test.ts +105 -199
  221. package/integration/devStabilityHarness.test.ts +13 -28
  222. package/integration/devStabilityHarness.ts +65 -330
  223. package/integration/ssrMemoryProbe.ts +41 -167
  224. package/libSource.test.ts +4 -15
  225. package/libSource.ts +19 -31
  226. package/lint/__fixtures__/no-document-cookie/bad.tsx +4 -0
  227. package/lint/__fixtures__/no-document-cookie/good.tsx +7 -0
  228. package/lint/__fixtures__/no-web-only-api-outside-webkit/bad.tsx +7 -0
  229. package/lint/__fixtures__/no-web-only-api-outside-webkit/good.tsx +11 -0
  230. package/lint/__fixtures__/no-web-storage/bad.tsx +6 -0
  231. package/lint/__fixtures__/no-web-storage/good.tsx +7 -0
  232. package/lint/gritRules.test.ts +8 -24
  233. package/lint/no-deep-internal-import.grit +2 -2
  234. package/lint/no-document-cookie.grit +29 -0
  235. package/lint/no-redeclare-predefined-endpoint.grit +2 -1
  236. package/lint/no-web-only-api-outside-webkit.grit +44 -0
  237. package/lint/no-web-storage.grit +30 -0
  238. package/linter.test.ts +1 -2
  239. package/linter.ts +26 -116
  240. package/mobile/desktopBin.test.ts +182 -0
  241. package/mobile/desktopBin.ts +144 -0
  242. package/mobile/desktopServerStage.test.ts +252 -0
  243. package/mobile/desktopServerStage.ts +178 -0
  244. package/mobile/index.ts +9 -0
  245. package/mobile/mobileTarget.test.ts +57 -8
  246. package/mobile/mobileTarget.ts +45 -26
  247. package/mobile/nativeApi.test.ts +30 -0
  248. package/mobile/nativeApi.ts +40 -0
  249. package/mobile/nativeApp.test.ts +184 -0
  250. package/mobile/nativeApp.ts +454 -0
  251. package/mobile/nativeAppLine.test.ts +69 -0
  252. package/mobile/nativeAppLine.ts +71 -0
  253. package/mobile/nativeConfig.test.ts +438 -0
  254. package/mobile/nativeConfig.ts +294 -0
  255. package/mobile/nativePluginFolders.test.ts +81 -0
  256. package/mobile/nativePluginFolders.ts +60 -0
  257. package/mobile/nativeWebDir.test.ts +80 -0
  258. package/mobile/nativeWebDir.ts +66 -0
  259. package/mobile/placeholderAppId.test.ts +13 -0
  260. package/mobile/placeholderAppId.ts +16 -0
  261. package/mobile/usageDescriptions.test.ts +27 -0
  262. package/mobile/usageDescriptions.ts +24 -0
  263. package/package.json +11 -11
  264. package/packageExports.test.ts +3 -18
  265. package/packageExportsMap.ts +3 -19
  266. package/piDependencyPins.test.ts +46 -0
  267. package/platformTest/BunTestReport.test.ts +60 -0
  268. package/platformTest/BunTestReport.ts +65 -0
  269. package/platformTest/IdleWatchedProcess.test.ts +56 -0
  270. package/platformTest/IdleWatchedProcess.ts +73 -0
  271. package/platformTest/LinuxDockerTarget.ts +105 -0
  272. package/platformTest/PlatformTestRun.test.ts +64 -0
  273. package/platformTest/PlatformTestRun.ts +141 -0
  274. package/platformTest/PlatformTestTarget.ts +142 -0
  275. package/platformTest/TestSnapshot.test.ts +72 -0
  276. package/platformTest/TestSnapshot.ts +103 -0
  277. package/platformTest/WindowsSshTarget.ts +151 -0
  278. package/prompter.ts +3 -13
  279. package/qualityScanner.test.ts +9 -26
  280. package/qualityScanner.ts +200 -286
  281. package/recipeScanner.test.ts +7 -12
  282. package/recipeScanner.ts +9 -38
  283. package/repoIdentity.ts +2 -9
  284. package/routeSourceValidator.test.ts +0 -1
  285. package/routeSourceValidator.ts +7 -42
  286. package/scanInfo.ts +91 -225
  287. package/selectModel.ts +1 -2
  288. package/semver.ts +3 -5
  289. package/slicePlanner.test.ts +6 -24
  290. package/slicePlanner.ts +11 -32
  291. package/spinner.test.ts +3 -8
  292. package/spinner.ts +4 -16
  293. package/sshTunnel.ts +1 -6
  294. package/ssrScanner.test.ts +1 -6
  295. package/ssrScanner.ts +103 -113
  296. package/stripAnsi.ts +3 -0
  297. package/subspace.test.ts +9 -25
  298. package/subspace.ts +48 -115
  299. package/subspaceConfig.ts +3 -11
  300. package/testHelpers.ts +194 -0
  301. package/transforms/asyncDefaultExportDetector.ts +3 -11
  302. package/transforms/barrelAnalyzer.ts +43 -135
  303. package/transforms/barrelImportsPlugin.ts +38 -175
  304. package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
  305. package/transforms/externalizeFrameworkPlugin.ts +13 -87
  306. package/transforms/moduleSyntax.ts +32 -0
  307. package/transforms/rscUseClientTransform.ts +42 -20
  308. package/transforms/serverEnvPlugin.test.ts +103 -0
  309. package/transforms/serverEnvPlugin.ts +41 -0
  310. package/transforms/transforms.test.ts +166 -44
  311. package/transforms/tsconfigPackageResolver.test.ts +6 -24
  312. package/transforms/useClientBundlePlugin.ts +6 -23
  313. package/typeChecker.ts +7 -63
  314. package/types.ts +2 -0
  315. package/uploadRelease.ts +10 -25
  316. package/workflow/artifacts.ts +18 -0
  317. package/workflow/executor.test.ts +1 -12
  318. package/workflow/executor.ts +101 -110
  319. package/workflow/index.ts +0 -1
  320. package/workflow/moduleIndex.test.ts +4 -15
  321. package/workflow/moduleIndex.ts +9 -49
  322. package/workflow/plan.ts +18 -25
  323. package/workflow/render.ts +80 -96
  324. package/workflow/rolloutGate.test.ts +1 -1
  325. package/workflow/source.ts +52 -69
  326. package/workflow/sourceAst.ts +50 -0
  327. package/workspaceLayout.test.ts +18 -3
  328. package/workspaceLayout.ts +22 -23
  329. package/abstractCompactor.ts +0 -112
  330. package/aiEditor.test.ts +0 -60
  331. package/aiEditor.ts +0 -387
  332. package/applicationReleasePackager.ts +0 -209
  333. package/capacitorApp.test.ts +0 -372
  334. package/capacitorApp.ts +0 -1648
  335. package/commandDecorators/commandMeta.ts +0 -7
  336. package/commandDecorators/types.ts +0 -10
  337. package/getDirname.ts +0 -4
  338. package/guideline.ts +0 -19
  339. package/local/optimize-resource/ipcprobe/child.ts +0 -1
  340. package/local/optimize-resource/ipcprobe/parent.ts +0 -11
  341. package/workflow/primitive.ts +0 -59
@@ -0,0 +1,293 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import type { App } from "../commandDecorators";
6
+ import { CsrDevModuleCompiler } from "./csrDevModuleCompiler";
7
+ import { CsrDevPaths } from "./csrDevPaths";
8
+ import { CsrDevResolver } from "./csrDevResolver";
9
+ import type { CsrDevCompiledModule, CsrDevContext } from "./csrDevTypes";
10
+
11
+ const context: CsrDevContext = {
12
+ pageEntries: [],
13
+ basePaths: [],
14
+ htmlBasePaths: [],
15
+ define: {},
16
+ optimizeImports: [],
17
+ configKey: "key",
18
+ refreshFile: null,
19
+ };
20
+
21
+ //? esbuild's own interop helpers, as a pre-bundled chunk ships them (@mermaid-js/parser's dist/chunks).
22
+ const prebundled = `var __create = Object.create;
23
+ var __defProp = Object.defineProperty;
24
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
25
+ var __getOwnPropNames = Object.getOwnPropertyNames;
26
+ var __getProtoOf = Object.getPrototypeOf;
27
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
28
+ var __copyProps = (to, from, except, desc) => {
29
+ if (from && typeof from === "object" || typeof from === "function") {
30
+ for (let key of __getOwnPropNames(from))
31
+ if (!__hasOwnProp.call(to, key) && key !== except)
32
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
33
+ }
34
+ return to;
35
+ };
36
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
38
+ var parts = {};
39
+ __reExport(parts, { a: 1 });
40
+ var wrapped = __toESM({ b: 2 });
41
+ export { parts, wrapped };
42
+ `;
43
+
44
+ //? The development checks jotai's and zustand's ESM builds ship, as written in jotai/esm/vanilla.mjs.
45
+ const jotai = `let keyCount = 0;
46
+ export function atom(read) {
47
+ const key = \`atom\${++keyCount}\`;
48
+ return {
49
+ read,
50
+ toString() {
51
+ return (import.meta.env ? import.meta.env.MODE : void 0) !== "production" && this.debugLabel ? key + ":" + this.debugLabel : key;
52
+ },
53
+ };
54
+ }
55
+ `;
56
+ const zustand = `export const devtools = (fn) => (import.meta.env ? import.meta.env.MODE : void 0) !== "production" ? "dev" : fn;
57
+ `;
58
+
59
+ describe("CsrDevModuleCompiler", () => {
60
+ let root: string;
61
+ const origin = "http://localhost:8283";
62
+ const file = (relative: string) => path.join(root, relative);
63
+ const logged: string[] = [];
64
+ const compile = async (relative: string | string[], { prepass = false }: { prepass?: boolean } = {}) => {
65
+ const files = (Array.isArray(relative) ? relative : [relative]).map(file);
66
+ const paths = new CsrDevPaths(root);
67
+ const resolver = new CsrDevResolver({ paths, context, entryFiles: prepass ? files : [] });
68
+ if (prepass) await resolver.prepass();
69
+ const compiler = new CsrDevModuleCompiler({
70
+ app: { verbose: () => undefined, logger: { error: (message: string) => logged.push(message) } } as unknown as App,
71
+ paths,
72
+ resolver,
73
+ context,
74
+ outDir: file("out"),
75
+ routePrefix: "/_akan/registry/",
76
+ });
77
+ return { resolver, ...(await compiler.compile(files, new Set())) };
78
+ };
79
+ //? As the page runs a factory: a classic script whose only globals are the runtime and the window.
80
+ const run = (module: CsrDevCompiledModule | undefined) => {
81
+ const helpers = new Map<string, Record<string, unknown>>();
82
+ const akan = {
83
+ defineHelpers: (hash: string, define: () => Record<string, unknown>) => helpers.set(hash, define()),
84
+ helpers: (hash: string) => helpers.get(hash),
85
+ };
86
+ if (module?.helpers) new Function("__akan", module.helpers.definition)(akan);
87
+ const factory = new Function("__akan", "self", `return (${module?.factory});`)(akan, {
88
+ location: { href: `${origin}/en/dashboard` },
89
+ });
90
+ const record = { exports: {} as Record<string, unknown> };
91
+ factory.call(
92
+ record.exports,
93
+ () => ({}),
94
+ record,
95
+ record.exports,
96
+ () => undefined,
97
+ () => (type: unknown) => type,
98
+ async () => ({}),
99
+ );
100
+ return record.exports;
101
+ };
102
+
103
+ beforeAll(async () => {
104
+ root = CsrDevPaths.realpath(await mkdtemp(path.join(os.tmpdir(), "akan-csr-dev-compiler-")));
105
+ await Bun.write(file("node_modules/prebundled/chunk.mjs"), prebundled);
106
+ await Bun.write(file("node_modules/bare-reexport/index.mjs"), "export const parts = __reExport({}, { a: 1 });\n");
107
+ await Bun.write(file("node_modules/bare-toesm/index.mjs"), "export const wrapped = __toESM({ b: 2 });\n");
108
+ await Bun.write(file("node_modules/jotai/esm/vanilla.mjs"), jotai);
109
+ await Bun.write(file("node_modules/zustand/esm/middleware.mjs"), zustand);
110
+ await Bun.write(
111
+ file("apps/demo/ui/meta.ts"),
112
+ [
113
+ "export const url = import.meta.url;",
114
+ "export const env = import.meta.env;",
115
+ 'export const asset = new URL("./x.wasm", import.meta.url).href;',
116
+ 'export const label = "import.meta.env";',
117
+ "",
118
+ ].join("\n"),
119
+ );
120
+ //? The shape of an app's useClient.ts: a macro whose module graph reaches server code that reads import.meta.
121
+ await Bun.write(
122
+ file("apps/demo/lib/macroDep.ts"),
123
+ 'import { createRequire } from "node:module";\nconst req = createRequire(import.meta.url);\nexport const depUrl = import.meta.url;\nexport const hasRequire = typeof req;\n',
124
+ );
125
+ await Bun.write(
126
+ file("apps/demo/lib/macro.ts"),
127
+ 'import { depUrl, hasRequire } from "./macroDep";\nexport const serialized = () => ({ depUrl, hasRequire });\n',
128
+ );
129
+ await Bun.write(
130
+ file("apps/demo/lib/useClient.ts"),
131
+ [
132
+ 'import { used } from "barrel";',
133
+ 'import { serialized } from "./macro" with { type: "macro" };',
134
+ "export const signal = serialized();",
135
+ "export const own = import.meta.url;",
136
+ 'export const label = "import.meta.url";',
137
+ "export const barrel = used;",
138
+ "",
139
+ ].join("\n"),
140
+ );
141
+ await Bun.write(file("node_modules/with-bin/index.mjs"), "#!/usr/bin/env node\nexport const a = 1;\n");
142
+ await Bun.write(file("node_modules/awaits/index.mjs"), "export const a = await Promise.resolve(1);\n");
143
+ await Bun.write(file("apps/demo/ui/awaits.ts"), "export const a = await Promise.resolve(1);\n");
144
+ await Bun.write(
145
+ file("node_modules/barrel/package.json"),
146
+ JSON.stringify({
147
+ name: "barrel",
148
+ type: "module",
149
+ main: "index.js",
150
+ sideEffects: false,
151
+ imports: {
152
+ "#where": { node: "./where.node.js", default: "./where.browser.js" },
153
+ "#other": { node: "./other.node.js", default: "./other.browser.js" },
154
+ },
155
+ }),
156
+ );
157
+ await Bun.write(
158
+ file("node_modules/barrel/index.js"),
159
+ 'export { used } from "./used.js";\nexport { unused } from "./unused.js";\nexport { other } from "#other";\n',
160
+ );
161
+ await Bun.write(file("node_modules/barrel/used.js"), "export const used = 1;\n");
162
+ await Bun.write(
163
+ file("node_modules/barrel/unused.js"),
164
+ 'import { where } from "#where";\nexport const unused = where;\n',
165
+ );
166
+ await Bun.write(
167
+ file("node_modules/barrel/where.node.js"),
168
+ 'import path from "node:path";\nexport const where = path.sep;\n',
169
+ );
170
+ await Bun.write(file("node_modules/barrel/where.browser.js"), 'export const where = "browser";\n');
171
+ await Bun.write(
172
+ file("node_modules/barrel/other.node.js"),
173
+ 'import path from "node:path";\nexport const other = path.sep;\n',
174
+ );
175
+ await Bun.write(file("node_modules/barrel/other.browser.js"), 'export const other = "browser";\n');
176
+ await Bun.write(file("apps/demo/entry.ts"), 'import { used } from "barrel";\nexport const run = used;\n');
177
+ await Bun.write(
178
+ file("node_modules/inspectish/package.json"),
179
+ JSON.stringify({ name: "inspectish", main: "index.js", browser: { "./util.inspect.js": false, fs: false } }),
180
+ );
181
+ await Bun.write(
182
+ file("node_modules/inspectish/index.js"),
183
+ 'var inspect = require("./util.inspect");\nvar fs = require("fs");\nmodule.exports = { inspect, fs };\n',
184
+ );
185
+ await Bun.write(file("node_modules/inspectish/util.inspect.js"), 'module.exports = require("util").inspect;\n');
186
+ });
187
+
188
+ afterAll(async () => {
189
+ await rm(root, { recursive: true, force: true });
190
+ });
191
+
192
+ test("a pre-bundled file keeps its own __reExport and __toESM, which Bun leaves in place of its own", async () => {
193
+ const { modules } = await compile("node_modules/prebundled/chunk.mjs");
194
+ const [module] = modules;
195
+ expect(module?.id).toBe("node_modules/prebundled/chunk.mjs");
196
+ const factory = module?.factory ?? "";
197
+ expect(factory).toContain("var __reExport = (target, mod, secondTarget) => (");
198
+ expect(factory).toContain("var __toESM = (mod, isNodeMode, target) => (");
199
+ expect(factory).not.toContain("__akan.reExport");
200
+ expect(factory).not.toContain("__akan.toESM");
201
+ expect(factory).not.toContain("__akanMeta");
202
+ expect(run(module)).toMatchObject({ parts: { a: 1 }, wrapped: { b: 2 } });
203
+ });
204
+
205
+ test.each([
206
+ ["__reExport", "node_modules/bare-reexport/index.mjs"],
207
+ ["__toESM", "node_modules/bare-toesm/index.mjs"],
208
+ ])("a %s call with no definition anywhere still stops the build", async (name, relative) => {
209
+ await expect(compile(relative)).rejects.toThrow(`Bun's ${name} helper no longer reads`);
210
+ });
211
+
212
+ test("jotai's and zustand's import.meta.env checks run as a classic script and take the ESM bundle's branch", async () => {
213
+ const [{ modules: jotaiModules }, { modules: zustandModules }] = await Promise.all([
214
+ compile("node_modules/jotai/esm/vanilla.mjs"),
215
+ compile("node_modules/zustand/esm/middleware.mjs"),
216
+ ]);
217
+ const [jotaiModule] = jotaiModules;
218
+ const [zustandModule] = zustandModules;
219
+ expect(jotaiModule?.factory).not.toContain("import.meta");
220
+ expect(zustandModule?.factory).not.toContain("import.meta");
221
+ const labeled = Object.assign((run(jotaiModule).atom as (read: unknown) => object)(null), { debugLabel: "count" });
222
+ expect(String(labeled)).toBe("atom1:count");
223
+ expect((run(zustandModule).devtools as (fn: unknown) => unknown)("prod")).toBe("dev");
224
+ });
225
+
226
+ test("an app module reads import.meta as a browser module does, on its own path and with no env", async () => {
227
+ const [module] = (await compile("apps/demo/ui/meta.ts")).modules;
228
+ expect(module?.factory).not.toContain("file://");
229
+ expect(run(module)).toEqual({
230
+ url: `${origin}/apps/demo/ui/meta.ts`,
231
+ env: undefined,
232
+ asset: `${origin}/apps/demo/ui/x.wasm`,
233
+ label: "import.meta.env",
234
+ });
235
+ });
236
+
237
+ test("a macro runs with its modules' own import.meta, and the file importing it still reads the browser's", async () => {
238
+ const { modules } = await compile("apps/demo/lib/useClient.ts", { prepass: true });
239
+ const module = modules.find((compiled) => compiled.id === "apps/demo/lib/useClient.ts");
240
+ expect(module?.deps.some((dep) => dep.includes(`${path.join("node_modules", "barrel")}${path.sep}`))).toBe(true);
241
+ expect(run(module)).toMatchObject({
242
+ signal: { depUrl: Bun.pathToFileURL(file("apps/demo/lib/macroDep.ts")).href, hasRequire: "function" },
243
+ own: `${origin}/apps/demo/lib/useClient.ts`,
244
+ label: "import.meta.url",
245
+ });
246
+ });
247
+
248
+ test("a file or re-export the browser build tree-shook away resolves with the browser condition", async () => {
249
+ const { modules, resolver } = await compile("apps/demo/entry.ts", { prepass: true });
250
+ const ids = modules.map((module) => module.id);
251
+ expect(ids).toContain("node_modules/barrel/unused.js");
252
+ expect(ids).toContain("node_modules/barrel/where.browser.js");
253
+ expect(ids).not.toContain("node_modules/barrel/where.node.js");
254
+ expect(ids).toContain("node_modules/barrel/other.browser.js");
255
+ expect(ids).not.toContain("node_modules/barrel/other.node.js");
256
+ expect([...resolver.fallbacks]).toEqual([]);
257
+ });
258
+
259
+ test("what a package's browser field maps to false is an empty stub, not the file or the Node built-in", async () => {
260
+ const { modules } = await compile("node_modules/inspectish/index.js");
261
+ expect(modules.map((module) => module.id)).toEqual(["node_modules/inspectish/index.js"]);
262
+ expect(modules[0]?.deps.sort()).toEqual(["stub:empty:fs", "stub:empty:node_modules/inspectish/util.inspect.js"]);
263
+ });
264
+
265
+ test("a package's #! line is a comment in its factory, so the package loads", async () => {
266
+ const [module] = (await compile("node_modules/with-bin/index.mjs")).modules;
267
+ expect(module?.factory).not.toContain("#!");
268
+ expect(run(module)).toEqual({ a: 1 });
269
+ });
270
+
271
+ test("a package file Bun cannot build as CommonJS is left out, named in the log, and the rest still builds", async () => {
272
+ logged.length = 0;
273
+ const { modules } = await compile(["node_modules/awaits/index.mjs", "node_modules/zustand/esm/middleware.mjs"]);
274
+ const left = modules.find((module) => module.id === "node_modules/awaits/index.mjs");
275
+ expect(modules.map((module) => module.id)).toContain("node_modules/zustand/esm/middleware.mjs");
276
+ expect(left?.deps).toEqual([]);
277
+ expect(() => run(left)).toThrow(
278
+ "[akan-csr] node_modules/awaits/index.mjs was left out of the dev registry: a top-level await",
279
+ );
280
+ expect(logged).toEqual([
281
+ expect.stringContaining(
282
+ "[csr-dev] node_modules/awaits/index.mjs is left out of the dev registry: a top-level await",
283
+ ),
284
+ ]);
285
+ expect(logged[0]).toContain("(node_modules/awaits/index.mjs:1)");
286
+ });
287
+
288
+ test("app code Bun cannot build as CommonJS still fails the build with Bun's messages", async () => {
289
+ const failure = await compile("apps/demo/ui/awaits.ts").catch((error: unknown) => error);
290
+ expect(failure).toBeInstanceOf(AggregateError);
291
+ expect(String((failure as AggregateError).errors[0])).toContain('"await" can only be used');
292
+ });
293
+ });