@ykdz/template 0.0.35 → 0.0.37

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 (720) hide show
  1. package/dist/application.d.ts +131 -14
  2. package/dist/application.js +307 -206
  3. package/dist/command-result.d.ts +9 -0
  4. package/dist/command-result.js +231 -0
  5. package/dist/main.d.ts +4 -1
  6. package/dist/main.js +321 -49
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +159 -45
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +2816 -535
  9. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.d.ts +39 -0
  10. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.js +178 -0
  11. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.d.ts +2 -2
  12. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.js +1 -1
  13. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.d.ts +31 -2
  14. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +44 -47
  15. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.d.ts +1 -1
  16. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.js +1 -1
  17. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.d.ts +10 -7
  18. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.js +11 -7
  19. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.d.ts +6 -4
  20. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +8 -7
  21. package/node_modules/@ykdz/template-builtin-presets/dist/src/template-sources.d.ts +1 -1
  22. package/node_modules/@ykdz/template-builtin-presets/dist/src/template-sources.js +1 -1
  23. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.d.ts +31 -2
  24. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +111 -64
  25. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.d.ts +31 -2
  26. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +37 -29
  27. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.d.ts +48 -2
  28. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +203 -155
  29. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.d.ts +26 -2
  30. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +21 -9
  31. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.d.ts +22 -2
  32. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +48 -38
  33. package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/bin/semver.js +0 -0
  34. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/README.md +1 -1
  35. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/dist/index.cjs +427 -504
  36. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/dist/index.d.cts +427 -32
  37. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/dist/index.d.mts +427 -32
  38. package/node_modules/@ykdz/template-builtin-presets/node_modules/valibot/dist/index.min.cjs +2 -0
  39. package/node_modules/@ykdz/template-builtin-presets/node_modules/valibot/dist/index.min.mjs +2 -0
  40. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/dist/index.mjs +418 -504
  41. package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/package.json +7 -2
  42. package/node_modules/@ykdz/template-builtin-presets/package.json +30 -16
  43. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +5 -5
  44. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +4 -4
  45. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-diagnostics.yml +4 -4
  46. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check.yml +3 -3
  47. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.pnpmfile.mjs +19 -0
  48. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/AGENTS.md.template +11 -0
  49. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/devcontainer.json +1 -2
  50. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.dynamic.txt +1 -0
  51. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.yaml +5 -5
  52. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/check-toolchain-versions.ts +556 -0
  53. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.json +4 -6
  54. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.packing-hook.json +7 -0
  55. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo.json +1 -1
  56. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/turbo.json +19 -1
  57. package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/node-pnpm.Dockerfile +4 -6
  58. package/node_modules/@ykdz/template-builtin-presets/templates/shared/oxc/tsconfig.config.json +2 -1
  59. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/tsconfig.app.json +1 -1
  60. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/tsconfig.node.json +2 -2
  61. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/CHANGELOG.md.template +17 -0
  62. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/RELEASING.md +17 -0
  63. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/artifact.ts +1271 -0
  64. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/changelog.ts +283 -0
  65. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +99 -0
  66. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-readiness.ts +66 -0
  67. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/cli-command-identity.ts +4 -0
  68. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/handoff.ts +450 -0
  69. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/publish.ts +483 -0
  70. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/readiness.ts +1146 -0
  71. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.ts +819 -0
  72. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +119 -0
  73. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/root-tsconfig.json +8 -0
  74. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/tsconfig.json +4 -0
  75. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +6 -0
  76. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/README.md +48 -0
  77. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/CHANGELOG.md.template +17 -0
  78. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-APACHE-2.0.txt +202 -0
  79. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-MIT.txt +21 -0
  80. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/README.md.template +5 -0
  81. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +3336 -0
  82. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/setup.sh +221 -0
  83. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +133 -0
  84. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli.ts +4 -3
  85. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/main.ts +5 -4
  86. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +14 -13
  87. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +76 -0
  88. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.build.json +2 -0
  89. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.json +2 -2
  90. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/tsconfig.build.json +2 -1
  91. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/tsconfig.json +2 -2
  92. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/scripts/reset.ts +3 -0
  93. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/db.ts +3 -4
  94. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/readiness.ts +6 -5
  95. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/storage.ts +93 -0
  96. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/tsconfig.build.json +8 -2
  97. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/tsconfig.json +3 -7
  98. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/turbo.json +1 -1
  99. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/drizzle.config.ts +5 -5
  100. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/tsconfig.build.json +2 -1
  101. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/tsconfig.json +2 -2
  102. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/.env.example +2 -1
  103. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/Dockerfile +25 -17
  104. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/Dockerfile.dockerignore +4 -4
  105. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +5 -25
  106. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/scripts/check-standalone-deployment.ts +17 -15
  107. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/playwright-teardown.ts +6 -7
  108. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.app.json +1 -2
  109. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.json +0 -1
  110. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.node.json +2 -3
  111. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.test.json +0 -1
  112. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/turbo.json +0 -8
  113. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vite.config.ts +3 -39
  114. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/tsconfig.json +7 -2
  115. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/root/playwright.config.ts +34 -0
  116. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/{web → root}/test/e2e/app.spec.ts +3 -3
  117. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/root/test/e2e/fixtures.ts +15 -0
  118. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/root/tsconfig.json +3 -0
  119. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/src/api.ts +1 -3
  120. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/turbo.json +0 -4
  121. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/vite.config.ts +2 -0
  122. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.d.ts +2 -2
  123. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.js +10 -5
  124. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +16 -54
  125. package/node_modules/@ykdz/template-core/dist/module-graph.js +140 -105
  126. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +47 -11
  127. package/node_modules/@ykdz/template-core/dist/package-contribution.js +92 -0
  128. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +21 -16
  129. package/node_modules/@ykdz/template-core/dist/preset-definition.d.ts +82 -13
  130. package/node_modules/@ykdz/template-core/dist/preset-definition.js +16 -1
  131. package/node_modules/@ykdz/template-core/dist/project-blueprint.d.ts +56 -0
  132. package/node_modules/@ykdz/template-core/dist/project-blueprint.js +271 -0
  133. package/node_modules/@ykdz/template-core/dist/project-github.d.ts +6 -4
  134. package/node_modules/@ykdz/template-core/dist/project-github.js +4 -4
  135. package/node_modules/@ykdz/template-core/dist/project-linking-v2.d.ts +4 -4
  136. package/node_modules/@ykdz/template-core/dist/project-linking-v2.js +14 -8
  137. package/node_modules/@ykdz/template-core/dist/project-projection.d.ts +29 -1
  138. package/node_modules/@ykdz/template-core/dist/project-projection.js +501 -29
  139. package/node_modules/@ykdz/template-core/dist/release-toolchain-snapshot.d.ts +10 -0
  140. package/node_modules/@ykdz/template-core/dist/release-toolchain-snapshot.js +9 -0
  141. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +0 -2
  142. package/node_modules/@ykdz/template-core/dist/renderer.js +17 -38
  143. package/node_modules/@ykdz/template-core/dist/template-boundary-check.d.ts +2 -2
  144. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +21 -9
  145. package/node_modules/@ykdz/template-core/node_modules/valibot/LICENSE.md +9 -0
  146. package/node_modules/@ykdz/template-core/node_modules/valibot/README.md +94 -0
  147. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.cjs +7897 -0
  148. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.d.cts +16579 -0
  149. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.d.mts +16579 -0
  150. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.min.cjs +2 -0
  151. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.min.mjs +2 -0
  152. package/node_modules/@ykdz/template-core/node_modules/valibot/dist/index.mjs +7577 -0
  153. package/node_modules/@ykdz/template-core/node_modules/valibot/package.json +84 -0
  154. package/node_modules/@ykdz/template-core/package.json +0 -2
  155. package/node_modules/hosted-git-info/LICENSE +13 -0
  156. package/node_modules/hosted-git-info/README.md +138 -0
  157. package/node_modules/hosted-git-info/lib/from-url.js +122 -0
  158. package/node_modules/hosted-git-info/lib/hosts.js +229 -0
  159. package/node_modules/hosted-git-info/lib/index.js +227 -0
  160. package/node_modules/hosted-git-info/lib/parse-url.js +79 -0
  161. package/node_modules/hosted-git-info/package.json +57 -0
  162. package/node_modules/jsonc-parser/CHANGELOG.md +76 -0
  163. package/node_modules/jsonc-parser/LICENSE.md +21 -0
  164. package/node_modules/jsonc-parser/README.md +364 -0
  165. package/node_modules/jsonc-parser/SECURITY.md +41 -0
  166. package/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
  167. package/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
  168. package/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
  169. package/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
  170. package/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
  171. package/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
  172. package/node_modules/jsonc-parser/lib/esm/main.js +178 -0
  173. package/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
  174. package/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
  175. package/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
  176. package/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
  177. package/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
  178. package/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
  179. package/node_modules/jsonc-parser/lib/umd/main.js +194 -0
  180. package/node_modules/jsonc-parser/package.json +37 -0
  181. package/node_modules/lru-cache/LICENSE.md +55 -0
  182. package/node_modules/lru-cache/README.md +469 -0
  183. package/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.d.ts.map +1 -0
  184. package/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.js.map +1 -0
  185. package/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.d.ts +5 -0
  186. package/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
  187. package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +1400 -0
  188. package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -0
  189. package/node_modules/lru-cache/dist/commonjs/browser/index.js +1733 -0
  190. package/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -0
  191. package/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
  192. package/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +7 -0
  193. package/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts +12 -0
  194. package/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts.map +1 -0
  195. package/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
  196. package/node_modules/lru-cache/dist/commonjs/browser/perf.js.map +1 -0
  197. package/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.cjs.map +1 -0
  198. package/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
  199. package/node_modules/lru-cache/dist/commonjs/diagnostics-channel.d.ts +5 -0
  200. package/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
  201. package/node_modules/lru-cache/dist/commonjs/index.d.ts +1400 -0
  202. package/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -0
  203. package/node_modules/lru-cache/dist/commonjs/index.js +1733 -0
  204. package/node_modules/lru-cache/dist/commonjs/index.js.map +1 -0
  205. package/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
  206. package/node_modules/lru-cache/dist/commonjs/index.min.js.map +7 -0
  207. package/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.d.ts.map +1 -0
  208. package/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.js.map +1 -0
  209. package/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.d.ts +5 -0
  210. package/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
  211. package/node_modules/lru-cache/dist/commonjs/node/index.d.ts +1400 -0
  212. package/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -0
  213. package/node_modules/lru-cache/dist/commonjs/node/index.js +1733 -0
  214. package/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -0
  215. package/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
  216. package/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +7 -0
  217. package/node_modules/lru-cache/dist/commonjs/node/perf.d.ts +12 -0
  218. package/node_modules/lru-cache/dist/commonjs/node/perf.d.ts.map +1 -0
  219. package/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
  220. package/node_modules/lru-cache/dist/commonjs/node/perf.js.map +1 -0
  221. package/node_modules/lru-cache/dist/commonjs/package.json +3 -0
  222. package/node_modules/lru-cache/dist/commonjs/perf.d.ts +12 -0
  223. package/node_modules/lru-cache/dist/commonjs/perf.d.ts.map +1 -0
  224. package/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
  225. package/node_modules/lru-cache/dist/commonjs/perf.js.map +1 -0
  226. package/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
  227. package/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.js.map +1 -0
  228. package/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.d.ts +5 -0
  229. package/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.js +7 -0
  230. package/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts +1400 -0
  231. package/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts.map +1 -0
  232. package/node_modules/lru-cache/dist/commonjs/react-native/index.js +1733 -0
  233. package/node_modules/lru-cache/dist/commonjs/react-native/index.js.map +1 -0
  234. package/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts +12 -0
  235. package/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts.map +1 -0
  236. package/node_modules/lru-cache/dist/commonjs/react-native/perf.js +10 -0
  237. package/node_modules/lru-cache/dist/commonjs/react-native/perf.js.map +1 -0
  238. package/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.d.ts.map +1 -0
  239. package/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.js.map +1 -0
  240. package/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.d.ts +5 -0
  241. package/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
  242. package/node_modules/lru-cache/dist/esm/browser/index.d.ts +1400 -0
  243. package/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -0
  244. package/node_modules/lru-cache/dist/esm/browser/index.js +1729 -0
  245. package/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -0
  246. package/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
  247. package/node_modules/lru-cache/dist/esm/browser/index.min.js.map +7 -0
  248. package/node_modules/lru-cache/dist/esm/browser/perf.d.ts +12 -0
  249. package/node_modules/lru-cache/dist/esm/browser/perf.d.ts.map +1 -0
  250. package/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
  251. package/node_modules/lru-cache/dist/esm/browser/perf.js.map +1 -0
  252. package/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
  253. package/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.mjs.map +1 -0
  254. package/node_modules/lru-cache/dist/esm/diagnostics-channel.d.ts +5 -0
  255. package/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
  256. package/node_modules/lru-cache/dist/esm/index.d.ts +1400 -0
  257. package/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -0
  258. package/node_modules/lru-cache/dist/esm/index.js +1729 -0
  259. package/node_modules/lru-cache/dist/esm/index.js.map +1 -0
  260. package/node_modules/lru-cache/dist/esm/index.min.js +2 -0
  261. package/node_modules/lru-cache/dist/esm/index.min.js.map +7 -0
  262. package/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.d.ts.map +1 -0
  263. package/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.js.map +1 -0
  264. package/node_modules/lru-cache/dist/esm/node/diagnostics-channel.d.ts +5 -0
  265. package/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
  266. package/node_modules/lru-cache/dist/esm/node/index.d.ts +1400 -0
  267. package/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -0
  268. package/node_modules/lru-cache/dist/esm/node/index.js +1729 -0
  269. package/node_modules/lru-cache/dist/esm/node/index.js.map +1 -0
  270. package/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
  271. package/node_modules/lru-cache/dist/esm/node/index.min.js.map +7 -0
  272. package/node_modules/lru-cache/dist/esm/node/perf.d.ts +12 -0
  273. package/node_modules/lru-cache/dist/esm/node/perf.d.ts.map +1 -0
  274. package/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
  275. package/node_modules/lru-cache/dist/esm/node/perf.js.map +1 -0
  276. package/node_modules/lru-cache/dist/esm/package.json +3 -0
  277. package/node_modules/lru-cache/dist/esm/perf.d.ts +12 -0
  278. package/node_modules/lru-cache/dist/esm/perf.d.ts.map +1 -0
  279. package/node_modules/lru-cache/dist/esm/perf.js +7 -0
  280. package/node_modules/lru-cache/dist/esm/perf.js.map +1 -0
  281. package/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
  282. package/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.js.map +1 -0
  283. package/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.d.ts +5 -0
  284. package/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.js +4 -0
  285. package/node_modules/lru-cache/dist/esm/react-native/index.d.ts +1400 -0
  286. package/node_modules/lru-cache/dist/esm/react-native/index.d.ts.map +1 -0
  287. package/node_modules/lru-cache/dist/esm/react-native/index.js +1729 -0
  288. package/node_modules/lru-cache/dist/esm/react-native/index.js.map +1 -0
  289. package/node_modules/lru-cache/dist/esm/react-native/perf.d.ts +12 -0
  290. package/node_modules/lru-cache/dist/esm/react-native/perf.d.ts.map +1 -0
  291. package/node_modules/lru-cache/dist/esm/react-native/perf.js +7 -0
  292. package/node_modules/lru-cache/dist/esm/react-native/perf.js.map +1 -0
  293. package/node_modules/lru-cache/package.json +180 -0
  294. package/node_modules/npm-package-arg/LICENSE +15 -0
  295. package/node_modules/npm-package-arg/README.md +104 -0
  296. package/node_modules/npm-package-arg/lib/npa.js +479 -0
  297. package/node_modules/npm-package-arg/node_modules/semver/LICENSE +15 -0
  298. package/node_modules/npm-package-arg/node_modules/semver/README.md +680 -0
  299. package/node_modules/npm-package-arg/node_modules/semver/bin/semver.js +195 -0
  300. package/node_modules/npm-package-arg/node_modules/semver/classes/comparator.js +143 -0
  301. package/node_modules/npm-package-arg/node_modules/semver/classes/index.js +7 -0
  302. package/node_modules/npm-package-arg/node_modules/semver/classes/range.js +577 -0
  303. package/node_modules/npm-package-arg/node_modules/semver/classes/semver.js +350 -0
  304. package/node_modules/npm-package-arg/node_modules/semver/functions/clean.js +8 -0
  305. package/node_modules/npm-package-arg/node_modules/semver/functions/cmp.js +54 -0
  306. package/node_modules/npm-package-arg/node_modules/semver/functions/coerce.js +62 -0
  307. package/node_modules/npm-package-arg/node_modules/semver/functions/compare-build.js +9 -0
  308. package/node_modules/npm-package-arg/node_modules/semver/functions/compare-loose.js +5 -0
  309. package/node_modules/npm-package-arg/node_modules/semver/functions/compare.js +7 -0
  310. package/node_modules/npm-package-arg/node_modules/semver/functions/diff.js +60 -0
  311. package/node_modules/npm-package-arg/node_modules/semver/functions/eq.js +5 -0
  312. package/node_modules/npm-package-arg/node_modules/semver/functions/gt.js +5 -0
  313. package/node_modules/npm-package-arg/node_modules/semver/functions/gte.js +5 -0
  314. package/node_modules/npm-package-arg/node_modules/semver/functions/inc.js +21 -0
  315. package/node_modules/npm-package-arg/node_modules/semver/functions/lt.js +5 -0
  316. package/node_modules/npm-package-arg/node_modules/semver/functions/lte.js +5 -0
  317. package/node_modules/npm-package-arg/node_modules/semver/functions/major.js +5 -0
  318. package/node_modules/npm-package-arg/node_modules/semver/functions/minor.js +5 -0
  319. package/node_modules/npm-package-arg/node_modules/semver/functions/neq.js +5 -0
  320. package/node_modules/npm-package-arg/node_modules/semver/functions/parse.js +18 -0
  321. package/node_modules/npm-package-arg/node_modules/semver/functions/patch.js +5 -0
  322. package/node_modules/npm-package-arg/node_modules/semver/functions/prerelease.js +8 -0
  323. package/node_modules/npm-package-arg/node_modules/semver/functions/rcompare.js +5 -0
  324. package/node_modules/npm-package-arg/node_modules/semver/functions/rsort.js +5 -0
  325. package/node_modules/npm-package-arg/node_modules/semver/functions/satisfies.js +12 -0
  326. package/node_modules/npm-package-arg/node_modules/semver/functions/sort.js +5 -0
  327. package/node_modules/npm-package-arg/node_modules/semver/functions/truncate.js +48 -0
  328. package/node_modules/npm-package-arg/node_modules/semver/functions/valid.js +8 -0
  329. package/node_modules/npm-package-arg/node_modules/semver/index.js +93 -0
  330. package/node_modules/npm-package-arg/node_modules/semver/internal/constants.js +37 -0
  331. package/node_modules/npm-package-arg/node_modules/semver/internal/debug.js +11 -0
  332. package/node_modules/npm-package-arg/node_modules/semver/internal/identifiers.js +29 -0
  333. package/node_modules/npm-package-arg/node_modules/semver/internal/lrucache.js +42 -0
  334. package/node_modules/npm-package-arg/node_modules/semver/internal/parse-options.js +17 -0
  335. package/node_modules/npm-package-arg/node_modules/semver/internal/re.js +223 -0
  336. package/node_modules/npm-package-arg/node_modules/semver/package.json +78 -0
  337. package/node_modules/npm-package-arg/node_modules/semver/preload.js +4 -0
  338. package/node_modules/npm-package-arg/node_modules/semver/range.bnf +17 -0
  339. package/node_modules/npm-package-arg/node_modules/semver/ranges/gtr.js +6 -0
  340. package/node_modules/npm-package-arg/node_modules/semver/ranges/intersects.js +9 -0
  341. package/node_modules/npm-package-arg/node_modules/semver/ranges/ltr.js +6 -0
  342. package/node_modules/npm-package-arg/node_modules/semver/ranges/max-satisfying.js +27 -0
  343. package/node_modules/npm-package-arg/node_modules/semver/ranges/min-satisfying.js +26 -0
  344. package/node_modules/npm-package-arg/node_modules/semver/ranges/min-version.js +63 -0
  345. package/node_modules/npm-package-arg/node_modules/semver/ranges/outside.js +82 -0
  346. package/node_modules/npm-package-arg/node_modules/semver/ranges/simplify.js +49 -0
  347. package/node_modules/npm-package-arg/node_modules/semver/ranges/subset.js +249 -0
  348. package/node_modules/npm-package-arg/node_modules/semver/ranges/to-comparators.js +10 -0
  349. package/node_modules/npm-package-arg/node_modules/semver/ranges/valid.js +13 -0
  350. package/node_modules/npm-package-arg/package.json +60 -0
  351. package/node_modules/picomatch/LICENSE +21 -0
  352. package/node_modules/picomatch/README.md +743 -0
  353. package/node_modules/picomatch/index.js +17 -0
  354. package/node_modules/picomatch/lib/constants.js +184 -0
  355. package/node_modules/picomatch/lib/parse.js +1425 -0
  356. package/node_modules/picomatch/lib/picomatch.js +361 -0
  357. package/node_modules/picomatch/lib/scan.js +403 -0
  358. package/node_modules/picomatch/lib/utils.js +72 -0
  359. package/node_modules/picomatch/package.json +83 -0
  360. package/node_modules/picomatch/posix.js +3 -0
  361. package/node_modules/proc-log/LICENSE +15 -0
  362. package/node_modules/proc-log/README.md +226 -0
  363. package/node_modules/proc-log/lib/index.js +158 -0
  364. package/node_modules/proc-log/package.json +46 -0
  365. package/node_modules/smol-toml/LICENSE +24 -0
  366. package/node_modules/smol-toml/README.md +605 -0
  367. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  368. package/node_modules/smol-toml/dist/date.js +156 -0
  369. package/node_modules/smol-toml/dist/error.d.ts +37 -0
  370. package/node_modules/smol-toml/dist/error.js +67 -0
  371. package/node_modules/smol-toml/dist/extract.js +289 -0
  372. package/node_modules/smol-toml/dist/index.cjs +770 -0
  373. package/node_modules/smol-toml/dist/index.d.ts +44 -0
  374. package/node_modules/smol-toml/dist/index.js +34 -0
  375. package/node_modules/smol-toml/dist/parse.d.ts +73 -0
  376. package/node_modules/smol-toml/dist/parse.js +164 -0
  377. package/node_modules/smol-toml/dist/primitive.js +151 -0
  378. package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
  379. package/node_modules/smol-toml/dist/stringify.js +219 -0
  380. package/node_modules/smol-toml/dist/struct.js +156 -0
  381. package/node_modules/smol-toml/dist/util.d.ts +43 -0
  382. package/node_modules/smol-toml/dist/util.js +57 -0
  383. package/node_modules/smol-toml/package.json +68 -0
  384. package/node_modules/typescript/bin/tsc +0 -0
  385. package/node_modules/typescript/bin/tsserver +0 -0
  386. package/node_modules/unbash/LICENSE +15 -0
  387. package/node_modules/unbash/README.md +289 -0
  388. package/node_modules/unbash/dist/ansi-c.d.ts +5 -0
  389. package/node_modules/unbash/dist/ansi-c.js +130 -0
  390. package/node_modules/unbash/dist/arithmetic.d.ts +11 -0
  391. package/node_modules/unbash/dist/arithmetic.js +530 -0
  392. package/node_modules/unbash/dist/assignment.d.ts +15 -0
  393. package/node_modules/unbash/dist/assignment.js +118 -0
  394. package/node_modules/unbash/dist/chars.d.ts +41 -0
  395. package/node_modules/unbash/dist/chars.js +41 -0
  396. package/node_modules/unbash/dist/command.d.ts +14 -0
  397. package/node_modules/unbash/dist/command.js +41 -0
  398. package/node_modules/unbash/dist/heredoc.d.ts +18 -0
  399. package/node_modules/unbash/dist/heredoc.js +25 -0
  400. package/node_modules/unbash/dist/internal-types.d.ts +87 -0
  401. package/node_modules/unbash/dist/internal-types.js +1 -0
  402. package/node_modules/unbash/dist/lexer.d.ts +202 -0
  403. package/node_modules/unbash/dist/lexer.js +3930 -0
  404. package/node_modules/unbash/dist/parser.d.ts +4 -0
  405. package/node_modules/unbash/dist/parser.js +1295 -0
  406. package/node_modules/unbash/dist/parts.d.ts +17 -0
  407. package/node_modules/unbash/dist/parts.js +82 -0
  408. package/node_modules/unbash/dist/printer.d.ts +2 -0
  409. package/node_modules/unbash/dist/printer.js +536 -0
  410. package/node_modules/unbash/dist/types.d.ts +494 -0
  411. package/node_modules/unbash/dist/types.js +1 -0
  412. package/node_modules/unbash/dist/word.d.ts +22 -0
  413. package/node_modules/unbash/dist/word.js +102 -0
  414. package/node_modules/unbash/package.json +80 -0
  415. package/node_modules/validate-npm-package-name/LICENSE +6 -0
  416. package/node_modules/validate-npm-package-name/README.md +120 -0
  417. package/node_modules/validate-npm-package-name/lib/builtin-modules.json +1 -0
  418. package/node_modules/validate-npm-package-name/lib/index.js +114 -0
  419. package/node_modules/validate-npm-package-name/package.json +59 -0
  420. package/node_modules/yaml/LICENSE +13 -0
  421. package/node_modules/yaml/README.md +172 -0
  422. package/node_modules/yaml/bin.mjs +11 -0
  423. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  424. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  425. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  426. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  427. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  428. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  429. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  430. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  431. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  432. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  433. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +226 -0
  434. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  435. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  436. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  437. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  438. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  439. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  440. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  441. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  442. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  443. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  444. package/node_modules/yaml/browser/dist/errors.js +57 -0
  445. package/node_modules/yaml/browser/dist/index.js +17 -0
  446. package/node_modules/yaml/browser/dist/log.js +11 -0
  447. package/node_modules/yaml/browser/dist/nodes/Alias.js +118 -0
  448. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  449. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  450. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  451. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  452. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  453. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  454. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  455. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  456. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  457. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  458. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  459. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  460. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  461. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  462. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  463. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  464. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  465. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  466. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  467. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  468. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  469. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  470. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  471. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  472. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  473. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  474. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  475. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  476. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  477. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  478. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  479. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  480. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  481. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  482. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  483. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  484. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  485. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  486. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  487. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  488. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  489. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  490. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  491. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  492. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  493. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  494. package/node_modules/yaml/browser/dist/util.js +11 -0
  495. package/node_modules/yaml/browser/dist/visit.js +233 -0
  496. package/node_modules/yaml/browser/index.js +5 -0
  497. package/node_modules/yaml/browser/package.json +3 -0
  498. package/node_modules/yaml/dist/cli.d.ts +8 -0
  499. package/node_modules/yaml/dist/cli.mjs +201 -0
  500. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  501. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  502. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  503. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  504. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  505. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  506. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  507. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  508. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  509. package/node_modules/yaml/dist/compose/composer.js +224 -0
  510. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  511. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  512. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  513. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  514. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  515. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  516. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  517. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  518. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  519. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  520. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  521. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +228 -0
  522. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  523. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  524. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  525. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  526. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  527. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  528. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  529. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  530. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  531. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  532. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  533. package/node_modules/yaml/dist/doc/Document.js +337 -0
  534. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  535. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  536. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  537. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  538. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  539. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  540. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  541. package/node_modules/yaml/dist/doc/directives.js +178 -0
  542. package/node_modules/yaml/dist/errors.d.ts +21 -0
  543. package/node_modules/yaml/dist/errors.js +62 -0
  544. package/node_modules/yaml/dist/index.d.ts +25 -0
  545. package/node_modules/yaml/dist/index.js +50 -0
  546. package/node_modules/yaml/dist/log.d.ts +3 -0
  547. package/node_modules/yaml/dist/log.js +19 -0
  548. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  549. package/node_modules/yaml/dist/nodes/Alias.js +120 -0
  550. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  551. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  552. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  553. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  554. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  555. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  556. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  557. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  558. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  559. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  560. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  561. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  562. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  563. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  564. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  565. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  566. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  567. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  568. package/node_modules/yaml/dist/options.d.ts +350 -0
  569. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  570. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  571. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  572. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  573. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  574. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  575. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  576. package/node_modules/yaml/dist/parse/cst.js +112 -0
  577. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  578. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  579. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  580. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  581. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  582. package/node_modules/yaml/dist/parse/parser.js +980 -0
  583. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  584. package/node_modules/yaml/dist/public-api.js +107 -0
  585. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  586. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  587. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  588. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  589. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  590. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  591. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  592. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  593. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  594. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  595. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  596. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  597. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  598. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  599. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  600. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  601. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  602. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  603. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  604. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  605. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  606. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  607. package/node_modules/yaml/dist/schema/tags.js +99 -0
  608. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  609. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  610. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  611. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  612. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  613. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  614. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  615. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  616. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  617. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  618. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  619. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  620. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  621. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  622. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  623. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  624. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  625. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  626. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  627. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  628. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  629. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  630. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  631. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  632. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  633. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  634. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  635. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  636. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  637. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  638. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  639. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  640. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  641. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  642. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  643. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  644. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  645. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  646. package/node_modules/yaml/dist/test-events.js +134 -0
  647. package/node_modules/yaml/dist/util.d.ts +16 -0
  648. package/node_modules/yaml/dist/util.js +28 -0
  649. package/node_modules/yaml/dist/visit.d.ts +102 -0
  650. package/node_modules/yaml/dist/visit.js +236 -0
  651. package/node_modules/yaml/package.json +97 -0
  652. package/node_modules/yaml/util.js +2 -0
  653. package/package.json +23 -21
  654. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/check-boundaries.ts +0 -12
  655. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-root-owned-task.ts +0 -69
  656. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/global-setup.ts +0 -21
  657. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/vitest.config.ts +0 -7
  658. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/playwright.config.ts +0 -90
  659. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.d.ts +0 -33
  660. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.js +0 -182
  661. package/node_modules/@ykdz/template-core/dist/toolchain-baseline-update.d.ts +0 -45
  662. package/node_modules/@ykdz/template-core/dist/toolchain-baseline-update.js +0 -27
  663. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.d.ts +0 -35
  664. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.js +0 -189
  665. package/node_modules/valibot/dist/index.min.cjs +0 -2
  666. package/node_modules/valibot/dist/index.min.mjs +0 -2
  667. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/LICENSE +0 -0
  668. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/README.md +0 -0
  669. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/classes/comparator.js +0 -0
  670. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/classes/index.js +0 -0
  671. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/classes/range.js +0 -0
  672. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/classes/semver.js +0 -0
  673. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/clean.js +0 -0
  674. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/cmp.js +0 -0
  675. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/coerce.js +0 -0
  676. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/compare-build.js +0 -0
  677. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/compare-loose.js +0 -0
  678. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/compare.js +0 -0
  679. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/diff.js +0 -0
  680. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/eq.js +0 -0
  681. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/gt.js +0 -0
  682. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/gte.js +0 -0
  683. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/inc.js +0 -0
  684. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/lt.js +0 -0
  685. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/lte.js +0 -0
  686. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/major.js +0 -0
  687. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/minor.js +0 -0
  688. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/neq.js +0 -0
  689. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/parse.js +0 -0
  690. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/patch.js +0 -0
  691. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/prerelease.js +0 -0
  692. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/rcompare.js +0 -0
  693. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/rsort.js +0 -0
  694. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/satisfies.js +0 -0
  695. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/sort.js +0 -0
  696. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/truncate.js +0 -0
  697. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/functions/valid.js +0 -0
  698. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/index.js +0 -0
  699. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/constants.js +0 -0
  700. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/debug.js +0 -0
  701. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/identifiers.js +0 -0
  702. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/lrucache.js +0 -0
  703. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/parse-options.js +0 -0
  704. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/internal/re.js +0 -0
  705. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/package.json +0 -0
  706. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/preload.js +0 -0
  707. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/range.bnf +0 -0
  708. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/gtr.js +0 -0
  709. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/intersects.js +0 -0
  710. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/ltr.js +0 -0
  711. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/max-satisfying.js +0 -0
  712. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/min-satisfying.js +0 -0
  713. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/min-version.js +0 -0
  714. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/outside.js +0 -0
  715. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/simplify.js +0 -0
  716. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/subset.js +0 -0
  717. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/to-comparators.js +0 -0
  718. /package/node_modules/{semver → @ykdz/template-builtin-presets/node_modules/semver}/ranges/valid.js +0 -0
  719. /package/node_modules/{valibot → @ykdz/template-builtin-presets/node_modules/valibot}/LICENSE.md +0 -0
  720. /package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/{types.d.ts → types.ts} +0 -0
@@ -1,19 +1,26 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { existsSync, readFileSync } from "node:fs";
2
3
  import path from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
- import { composeCiDiagnosticArtifacts } from "#template-core/ci-diagnostic-artifact";
5
- import { collectGeneratedManifestCatalogReferences, selectTemplateDependencyCatalogEntries, } from "#template-core/dependency-catalog";
6
- import { planDevelopmentContainerToolLayersSync, } from "#template-core/development-container-tool-layer";
7
- import { editorCustomizationForCapabilities, loadEditorCustomizationDeclarations, } from "#template-core/editor-customization";
8
- import { checkEnvironmentNeedFact, checkEnvironmentNeedFromFact, deploymentEnvironmentNeedFact, deploymentEnvironmentNeedFromFact, renderDeploymentCheckCommand, renderFixCommand, renderRootCheckCommand, } from "#template-core/module-graph";
9
- import { assertPackageContribution, } from "#template-core/package-contribution";
10
- import { assertProjectBlueprintV2, validateProjectBlueprintV2 as validateCoreProjectBlueprintV2, } from "#template-core/project-blueprint-v2";
11
- import { projectCheckWorkflowTemplateSource, projectCheckWorkflowTemplateReplacements, projectDependabotTemplateReplacements, } from "#template-core/project-github";
12
- import { planExplicitProjectLinks } from "#template-core/project-linking-v2";
13
- import { resolveTemplateSource, } from "#template-core/renderer";
5
+ import { isDeepStrictEqual } from "node:util";
6
+ import { composeCiDiagnosticArtifacts } from "@ykdz/template-core/ci-diagnostic-artifact";
7
+ import { collectGeneratedManifestCatalogReferences, selectTemplateDependencyCatalogEntries, } from "@ykdz/template-core/dependency-catalog";
8
+ import { planDevelopmentContainerToolLayersSync, } from "@ykdz/template-core/development-container-tool-layer";
9
+ import { editorCustomizationForCapabilities, loadEditorCustomizationDeclarations, } from "@ykdz/template-core/editor-customization";
10
+ import { normalizeEnvironmentNeeds, parseEnvironmentNeedsMetadata, playwrightBrowserAssetsEnvironmentNeed, renderDeploymentCheckCommand, renderFixCommand, renderRootCheckCommand, renderTurboRunCommand, shellCheckEnvironmentNeed, } from "@ykdz/template-core/module-graph";
11
+ import { assertPackageContribution, assertPackageContributionCommandNames, } from "@ykdz/template-core/package-contribution";
12
+ import { assertProjectBlueprint, assertProjectBlueprintDraft, isValidNewNpmPackageName, validateNewPackagePath, validateProjectBlueprint as validateCoreProjectBlueprint, } from "@ykdz/template-core/project-blueprint";
13
+ import { projectCheckWorkflowTemplateSource, projectCheckWorkflowTemplateReplacements, projectDependabotTemplateReplacements, } from "@ykdz/template-core/project-github";
14
+ import { canConsumeNodePackageNameImport, canLinkNodePackageRoles, canProvideSourceConditionPackageNameImport, planExplicitProjectLinks, } from "@ykdz/template-core/project-linking-v2";
15
+ import { validateProjectProjectionPlan } from "@ykdz/template-core/project-projection";
16
+ import { releaseToolchainSnapshot } from "@ykdz/template-core/release-toolchain-snapshot";
17
+ import { resolveTemplateSource, } from "@ykdz/template-core/renderer";
18
+ import { parse as parseToml } from "smol-toml";
19
+ import ts from "typescript";
20
+ import { isValidDefaultPackageScope, parseGenerationRecord, } from "./generation-record.js";
14
21
  import { rustBinDefinition } from "./rust-bin/definition.js";
15
22
  import { githubCliDevelopmentContainerToolLayer } from "./shared/development-container.js";
16
- import { typescriptConfigContribution, typescriptConfigPackageDefinition, typescriptConfigPackageName, } from "./shared/typescript.js";
23
+ import { typescriptConfigContribution, typescriptConfigPackageDefinition, typescriptConfigReplayAdapter, } from "./shared/typescript.js";
17
24
  import { vuePnpmDependencyOverrides } from "./shared/vue.js";
18
25
  import { templateSources } from "./template-sources.js";
19
26
  import { tsCliDefinition } from "./ts-cli/definition.js";
@@ -21,6 +28,21 @@ import { tsLibDefinition } from "./ts-lib/definition.js";
21
28
  import { vikeAppDefinition } from "./vike-app/definition.js";
22
29
  import { vueAppDefinition } from "./vue-app/definition.js";
23
30
  import { vueHonoAppDefinition } from "./vue-hono-app/definition.js";
31
+ const localTemplateMetadataStateKey = Symbol("localTemplateMetadataState");
32
+ export class PackageAdditionBusinessConflict extends Error {
33
+ kind;
34
+ existing;
35
+ requested;
36
+ missingLink;
37
+ constructor(kind, existing, requested, missingLink) {
38
+ super("Package Addition business conflict");
39
+ this.kind = kind;
40
+ this.existing = existing;
41
+ this.requested = requested;
42
+ if (missingLink !== undefined)
43
+ this.missingLink = missingLink;
44
+ }
45
+ }
24
46
  const environmentNeedsPath = ".template/environment-needs.json";
25
47
  const packageManifestKeyOrder = [
26
48
  "name",
@@ -53,8 +75,8 @@ const packageConditionKeyOrder = ["source", "types", "default"];
53
75
  export function resolveBuiltInTemplateSource(source, relativePath) {
54
76
  return resolveTemplateSource(source, relativePath);
55
77
  }
56
- export function validateProjectBlueprintV2(value) {
57
- return validateCoreProjectBlueprintV2(value);
78
+ export function validateProjectBlueprint(value) {
79
+ return validateCoreProjectBlueprint(value);
58
80
  }
59
81
  class PresetRegistry {
60
82
  #definitions;
@@ -64,6 +86,14 @@ class PresetRegistry {
64
86
  new Set(names).size !== names.length) {
65
87
  throw new Error("Preset Registry requires unique non-empty Definition names");
66
88
  }
89
+ for (const definition of definitions) {
90
+ const adapterIdentities = definition.packageContributionReplayAdapters.map((adapter) => adapter.identity);
91
+ if (adapterIdentities.length === 0 ||
92
+ adapterIdentities.some((identity) => identity.length === 0) ||
93
+ new Set(adapterIdentities).size !== adapterIdentities.length) {
94
+ throw new Error(`Built-in Preset ${definition.metadata.name} requires unique non-empty Package Contribution replay adapters`);
95
+ }
96
+ }
67
97
  this.#definitions = [...definitions].toSorted((left, right) => left.metadata.name.localeCompare(right.metadata.name));
68
98
  }
69
99
  all() {
@@ -84,245 +114,437 @@ export const builtInPresetRegistry = new PresetRegistry([
84
114
  vueHonoAppDefinition,
85
115
  vikeAppDefinition,
86
116
  ]);
87
- /** Registry-derived Template Source roots checked independently of render plans. */
88
- export function builtInPresetTemplateSourceContexts() {
89
- return [
90
- ...builtInPresetRegistry.all().map((definition) => ({
91
- name: definition.metadata.name,
92
- root: resolveBuiltInTemplateSource(definition.source, "."),
93
- })),
94
- {
95
- name: "foundation",
96
- root: resolveBuiltInTemplateSource(templateSources.foundation, "."),
97
- },
98
- {
99
- name: "shared-devcontainer",
100
- root: resolveBuiltInTemplateSource(templateSources.sharedDevcontainer, "."),
117
+ export function createGenerationContext(options) {
118
+ const repositoryName = path.basename(path.resolve(options.targetDir));
119
+ const defaultPackageScope = options.defaultPackageScope ?? repositoryName;
120
+ return {
121
+ targetDir: options.targetDir,
122
+ repositoryName,
123
+ defaultPackageScope,
124
+ foundationPackages: {
125
+ typescriptConfiguration: {
126
+ name: `@${defaultPackageScope}/typescript-config`,
127
+ },
101
128
  },
102
- {
103
- name: "shared-oxc",
104
- root: resolveBuiltInTemplateSource(templateSources.sharedOxc, "."),
129
+ toolchain: options.toolchain,
130
+ };
131
+ }
132
+ function isRecord(value) {
133
+ return typeof value === "object" && value !== null && !Array.isArray(value);
134
+ }
135
+ const packageDefinitionIdDomain = "ykdz.template.package-definition-id.v1";
136
+ function packageDefinitionIdDigest(value) {
137
+ return `package-${createHash("sha256")
138
+ .update(JSON.stringify(value))
139
+ .digest("hex")}`;
140
+ }
141
+ function allocatePackageDefinitionId(options) {
142
+ const creationFacts = {
143
+ domain: packageDefinitionIdDomain,
144
+ definition: {
145
+ name: options.definition.name,
146
+ path: options.definition.path,
147
+ role: options.definition.role,
105
148
  },
106
- {
107
- name: "shared-vue",
108
- root: resolveBuiltInTemplateSource(templateSources.vue, "."),
149
+ provenance: {
150
+ definitionName: options.provenance.definitionName,
151
+ planningContribution: options.provenance.planningContribution,
152
+ contributionIdentity: options.provenance.contributionIdentity,
109
153
  },
110
- ];
154
+ };
155
+ let nonce = 0;
156
+ while (true) {
157
+ const candidate = packageDefinitionIdDigest(nonce === 0
158
+ ? creationFacts
159
+ : {
160
+ creationFacts,
161
+ occupiedIds: [...options.occupiedIds].toSorted(),
162
+ nonce,
163
+ });
164
+ if (!options.occupiedIds.has(candidate))
165
+ return candidate;
166
+ nonce += 1;
167
+ }
168
+ }
169
+ function persistPackageDefinition(options) {
170
+ const packageDefinitionId = allocatePackageDefinitionId(options);
171
+ options.occupiedIds.add(packageDefinitionId);
172
+ return { ...options.definition, packageDefinitionId };
173
+ }
174
+ function readGenerationRecord(options) {
175
+ const generationPath = path.join(options.repositoryRoot, ".template/generation.json");
176
+ return parseGenerationRecord(readJsonFile(generationPath, "Generation Record facts"));
111
177
  }
112
178
  /**
113
- * Derives direct Template Source checks from every registered Definition's
114
- * actual initial contributions, without maintaining a second Preset catalog.
179
+ * Package Addition 的目标根 package.json 允许两种 Node 声明:旧仓库的纯大版本
180
+ * ("24")与精确版本("24.16.0"),两者都能派生大版本;范围表达式与两段版本拒绝。
115
181
  */
116
- export function builtInPresetTemplateSourceCheckContexts() {
117
- return builtInPresetRegistry.all().flatMap((definition) => {
118
- const context = createGenerationContext({
119
- targetDir: path.join("generated-repository", "template-source", definition.metadata.name),
120
- toolchain: { nodeLtsMajor: "24", packageManagerPin: "pnpm@11.11.0" },
121
- });
122
- const plan = planGeneratedRepositoryInitialization({ definition, context });
123
- const contributions = definition.planInitializationContributions?.(context) ?? [definition.planInitialization(context)];
124
- return contributions.map((contribution) => ({
125
- definition,
126
- contribution,
127
- plan,
128
- }));
129
- });
182
+ const nodeMajorOrExactVersionPattern = /^(\d+)(?:\.(\d+)\.(\d+))?$/u;
183
+ /** 与 npm packageManager 字段一致的精确 pnpm pin(可带预发布或构建元数据)。 */
184
+ const exactPnpmPinPattern = /^pnpm@\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/u;
185
+ /**
186
+ * 目标根现行版本声明缺失或形状错误时的显式带形状内部失败:点名文件与字段、实际值与修正动作,
187
+ * 由 Package Addition 准备边界传递给命令层;其他 metadata 错误保持通用。
188
+ */
189
+ class PackageAdditionTargetDeclarationFailure extends Error {
190
+ field;
191
+ suggestion;
192
+ constructor(file, field, requirement, actualDeclaration, suggestion) {
193
+ super(`加包需要目标仓库根 ${file} 的 ${field} ${requirement},实际收到 ${actualDeclaration}。${suggestion}`);
194
+ this.field = field;
195
+ this.suggestion = suggestion;
196
+ }
130
197
  }
131
- export function createGenerationContext(options) {
132
- const projectName = path.basename(path.resolve(options.targetDir));
198
+ /**
199
+ * Package Addition 的版本上下文来自目标仓库根 package.json 的当前声明,因此升级过
200
+ * Node 或 pnpm 的仓库会继续按自身版本加包;Generation Record 的 toolchain 只保留为
201
+ * 初始化历史。
202
+ */
203
+ function readPackageAdditionVersionFacts(repositoryRoot) {
204
+ const manifest = readRepositoryJsonRecord({
205
+ repositoryRoot,
206
+ relativePath: "package.json",
207
+ label: "root Manifest",
208
+ });
209
+ const nodeDeclaration = isRecord(manifest.engines)
210
+ ? manifest.engines.node
211
+ : undefined;
212
+ const nodeDeclarationMatch = typeof nodeDeclaration === "string"
213
+ ? nodeMajorOrExactVersionPattern.exec(nodeDeclaration)
214
+ : undefined;
215
+ const nodeLtsMajor = nodeDeclarationMatch?.[1];
216
+ if (nodeLtsMajor === undefined || typeof nodeDeclaration !== "string") {
217
+ throw new PackageAdditionTargetDeclarationFailure("package.json", "engines.node", '声明单个 Node 大版本("24")或精确 Node 版本("24.16.0")', JSON.stringify(nodeDeclaration ?? null), "请先修改根 package.json 的 engines.node 声明再加包。");
218
+ }
219
+ const packageManagerDeclaration = manifest.packageManager;
220
+ if (typeof packageManagerDeclaration !== "string" ||
221
+ !exactPnpmPinPattern.test(packageManagerDeclaration)) {
222
+ throw new PackageAdditionTargetDeclarationFailure("package.json", "packageManager", '声明精确 pnpm 版本("pnpm@11.21.0")', JSON.stringify(packageManagerDeclaration ?? null), "请先修改根 package.json 的 packageManager 声明再加包。");
223
+ }
224
+ // 根只声明大版本时没有诚实的精确 patch 可传,保持缺省而不伪造。
133
225
  return {
134
- targetDir: options.targetDir,
135
- projectName,
136
- scope: options.scope ?? projectName,
137
- toolchain: options.toolchain,
226
+ toolchain: {
227
+ nodeLtsMajor,
228
+ packageManagerPin: packageManagerDeclaration,
229
+ ...(nodeDeclarationMatch?.[2] === undefined
230
+ ? {}
231
+ : { nodeVersion: nodeDeclaration }),
232
+ },
233
+ rootNodeDeclaration: nodeDeclaration,
138
234
  };
139
235
  }
140
- function isRecord(value) {
141
- return typeof value === "object" && value !== null && !Array.isArray(value);
236
+ /** 生成仓库根 Rust 声明的唯一文件名;所有权判定与投影保留都只经这个接缝引用它。 */
237
+ const rootRustDeclarationFileName = "rust-toolchain.toml";
238
+ /**
239
+ * 已选用 Rust 的目标仓库由根 rust-toolchain.toml 的 channel 拥有后续 Rust 版本选择,因此加包
240
+ * 按该现行声明重放根投影与开发容器初值。声明缺失、非法 TOML 或 channel 形状错误时在此失败,
241
+ * 不回退 CLI 发版快照、Generation Record 历史或 ambient 环境。
242
+ */
243
+ function readPackageAdditionTargetRustChannel(repositoryRoot) {
244
+ const relativePath = rootRustDeclarationFileName;
245
+ const filePath = path.join(repositoryRoot, relativePath);
246
+ if (!existsSync(filePath)) {
247
+ throw new PackageAdditionTargetDeclarationFailure(relativePath, "[toolchain].channel", "存在", "文件不存在", `请先创建根 ${relativePath},在 [toolchain] 表内声明 channel 再加包。`);
248
+ }
249
+ let declaration;
250
+ try {
251
+ declaration = parseToml(readFileSync(filePath, "utf8"));
252
+ }
253
+ catch (error) {
254
+ throw new PackageAdditionTargetDeclarationFailure(relativePath, "[toolchain].channel", "是有效 TOML 声明", `无法解析:${error instanceof Error ? error.message : String(error)}`, `请先修正根 ${relativePath} 的 TOML 语法,使 [toolchain] 表内声明 channel 再加包。`);
255
+ }
256
+ const toolchain = isRecord(declaration) ? declaration.toolchain : undefined;
257
+ const channel = isRecord(toolchain) ? toolchain.channel : undefined;
258
+ if (typeof channel !== "string" || channel.trim().length === 0) {
259
+ throw new PackageAdditionTargetDeclarationFailure(relativePath, "[toolchain].channel", "为非空字符串", JSON.stringify(channel ?? null), `请先在根 ${relativePath} 的 [toolchain] 表内写入 channel 再加包。`);
260
+ }
261
+ return channel;
142
262
  }
143
- function readGenerationRecord(options) {
144
- const generationPath = path.join(options.context.targetDir, ".template/generation.json");
145
- let value;
263
+ /**
264
+ * Root Rust 来源的最小接缝:从 rust-toolchain.toml 正文结构化读出 `[toolchain].channel`。
265
+ * 复用加包路径同一 smol-toml 真源,供模板仓投影值门核对 M5;不引入第二套版本或文件名表。
266
+ * 正文非法 TOML 或缺少非空 channel 时返回不可解释,由调用方按缺失/漂移分类,不静默跳过。
267
+ */
268
+ export function readRustToolchainChannelFromToml(contents) {
269
+ let declaration;
146
270
  try {
147
- value = JSON.parse(readFileSync(generationPath, "utf8"));
271
+ declaration = parseToml(contents);
148
272
  }
149
273
  catch (error) {
150
- throw new Error(`Package Addition requires valid Generation Record facts: ${error instanceof Error ? error.message : String(error)}`);
151
- }
152
- if (isRecord(value)) {
153
- for (const key of Object.keys(value)) {
154
- if (![
155
- "schemaVersion",
156
- "preset",
157
- "templateVersion",
158
- "toolchain",
159
- "packages",
160
- ].includes(key)) {
161
- throw new Error(`Package Addition Generation Record contains unknown field: ${key}`);
162
- }
163
- }
164
- if (isRecord(value.toolchain)) {
165
- for (const key of Object.keys(value.toolchain)) {
166
- if (!["nodeLtsMajor", "packageManagerPin"].includes(key)) {
167
- throw new Error(`Package Addition Generation Record toolchain contains unknown field: ${key}`);
168
- }
169
- }
170
- }
274
+ return {
275
+ reason: `不是有效 TOML 声明:${error instanceof Error ? error.message : String(error)}`,
276
+ status: "unreadable",
277
+ };
171
278
  }
172
- if (!isRecord(value) ||
173
- value.schemaVersion !== 1 ||
174
- typeof value.preset !== "string" ||
175
- value.templateVersion !== "0.0.0" ||
176
- !isRecord(value.toolchain) ||
177
- typeof value.toolchain.nodeLtsMajor !== "string" ||
178
- typeof value.toolchain.packageManagerPin !== "string" ||
179
- !Array.isArray(value.packages)) {
180
- throw new Error("Package Addition requires a supported Generation Record in .template/generation.json");
181
- }
182
- const packages = [];
183
- for (const [index, item] of value.packages.entries()) {
184
- if (isRecord(item)) {
185
- for (const key of Object.keys(item)) {
186
- if (!["path", "definitionName", "planningContribution"].includes(key)) {
187
- throw new Error(`Package Addition Generation Record packages[${index}] contains unknown field: ${key}`);
188
- }
189
- }
190
- }
191
- if (!isRecord(item) ||
192
- typeof item.path !== "string" ||
193
- typeof item.definitionName !== "string" ||
194
- !["foundationPlan", "planInitialization", "planPackageAddition"].includes(String(item.planningContribution))) {
195
- throw new Error(`Package Addition requires valid package planning facts at .template/generation.json packages[${index}]`);
196
- }
197
- packages.push(item);
279
+ const toolchain = isRecord(declaration) ? declaration.toolchain : undefined;
280
+ const channel = isRecord(toolchain) ? toolchain.channel : undefined;
281
+ if (typeof channel !== "string" || channel.trim().length === 0) {
282
+ return {
283
+ reason: `[toolchain].channel 必须是非空字符串,实际为 ${JSON.stringify(channel ?? null)}`,
284
+ status: "unreadable",
285
+ };
198
286
  }
199
- const blueprintPaths = options.blueprint.packages
200
- .map((definition) => definition.path)
201
- .toSorted();
202
- const recordedPaths = packages.map((item) => item.path).toSorted();
203
- if (JSON.stringify(blueprintPaths) !== JSON.stringify(recordedPaths) ||
204
- new Set(recordedPaths).size !== recordedPaths.length) {
205
- throw new Error("Package Addition requires Generation Record packages to match the current Project Blueprint");
287
+ return { channel, status: "explained" };
288
+ }
289
+ function readJsonFile(filePath, label) {
290
+ try {
291
+ return JSON.parse(readFileSync(filePath, "utf8"));
206
292
  }
207
- const generationRecord = {
208
- schemaVersion: 1,
209
- preset: value.preset,
210
- templateVersion: value.templateVersion,
211
- toolchain: {
212
- nodeLtsMajor: value.toolchain.nodeLtsMajor,
213
- packageManagerPin: value.toolchain.packageManagerPin,
214
- },
215
- packages,
293
+ catch (error) {
294
+ throw new Error(`Package Addition requires valid ${label}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
295
+ }
296
+ }
297
+ function barePackageDefinition(definition) {
298
+ return {
299
+ name: definition.name,
300
+ path: definition.path,
301
+ role: definition.role,
216
302
  };
217
- assertGenerationRecordFoundationConsistency({
218
- context: options.context,
219
- blueprint: options.blueprint,
220
- generationRecord,
221
- });
222
- return generationRecord;
223
303
  }
224
- function assertGenerationRecordFoundationConsistency(options) {
225
- const configDefinition = typescriptConfigPackageDefinition(options.context);
226
- const foundationRecords = options.generationRecord.packages.filter((record) => record.planningContribution === "foundationPlan");
227
- if (foundationRecords.length !== 1 ||
228
- foundationRecords[0].definitionName !== "foundation" ||
229
- foundationRecords[0].path !== configDefinition.path) {
230
- throw new Error("Package Addition Generation Record must contain exactly one Foundation TypeScript configuration provenance record");
304
+ function preflightLocalTemplateMetadata(options) {
305
+ const definitionsById = new Map(options.blueprint.packages.map((definition) => [
306
+ definition.packageDefinitionId,
307
+ definition,
308
+ ]));
309
+ const joinedPackages = options.generationRecord.packages.map((record) => {
310
+ const definition = definitionsById.get(record.packageDefinitionId);
311
+ if (definition === undefined) {
312
+ throw new Error(`Generation Record Package Definition ID ${record.packageDefinitionId} has no matching Project Blueprint Package Definition`);
313
+ }
314
+ if (record.path !== definition.path) {
315
+ throw new Error(`Generation Record path witness ${record.path} for Package Definition ID ${record.packageDefinitionId} conflicts with Project Blueprint path ${definition.path}`);
316
+ }
317
+ return { record, definition: barePackageDefinition(definition) };
318
+ });
319
+ const recordedIds = new Set(options.generationRecord.packages.map((record) => record.packageDefinitionId));
320
+ const unrecordedDefinition = options.blueprint.packages.find((definition) => !recordedIds.has(definition.packageDefinitionId));
321
+ if (unrecordedDefinition !== undefined) {
322
+ throw new Error(`Project Blueprint Package Definition ID ${unrecordedDefinition.packageDefinitionId} has no matching Generation Record provenance`);
231
323
  }
232
- const initialRecords = options.generationRecord.packages.filter((record) => record.planningContribution === "planInitialization");
233
- if (initialRecords.length === 0) {
234
- throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} has no initial Package provenance`);
324
+ const records = options.generationRecord.packages.filter((record) => record.planningContribution === "foundationPlan");
325
+ if (records.length !== 1) {
326
+ throw new Error(`Package Addition requires exactly one Foundation Package Planning Provenance record; found ${records.length}`);
235
327
  }
236
- const conflictingRecord = initialRecords.find((record) => record.definitionName !== options.generationRecord.preset);
237
- if (conflictingRecord !== undefined) {
238
- throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} conflicts with initial Package provenance ${conflictingRecord.definitionName} for Blueprint package ${conflictingRecord.path}`);
328
+ const record = records[0];
329
+ if (record.definitionName !== "foundation") {
330
+ throw new Error(`Foundation Package Planning Provenance at ${record.path} must use definitionName foundation; received ${record.definitionName}`);
239
331
  }
240
- let rootDefinition;
332
+ if (record.contributionIdentity !== typescriptConfigReplayAdapter.identity) {
333
+ throw new Error(`Foundation TypeScript Configuration Package provenance must use contribution identity ${typescriptConfigReplayAdapter.identity}`);
334
+ }
335
+ const foundationPackage = joinedPackages.find((candidate) => candidate.record === record);
336
+ let initialDefinition;
241
337
  try {
242
- rootDefinition = builtInPresetRegistry.require(options.generationRecord.preset);
338
+ initialDefinition = builtInPresetRegistry.require(options.generationRecord.preset);
243
339
  }
244
340
  catch {
245
341
  throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} is not a registered Built-in Preset`);
246
342
  }
247
- const initialBlueprint = rootDefinition.blueprint(options.context);
248
- assertProjectBlueprintV2(initialBlueprint);
249
- const expectedPaths = initialBlueprint.packages
250
- .map((definition) => definition.path)
251
- .toSorted();
252
- const recordedInitialPaths = initialRecords
253
- .map((record) => record.path)
254
- .toSorted();
255
- if (JSON.stringify(recordedInitialPaths) !== JSON.stringify(expectedPaths)) {
256
- throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} expects initial Blueprint packages ${expectedPaths.join(", ")}, but initial provenance records ${recordedInitialPaths.join(", ")}`);
343
+ const initialRecords = options.generationRecord.packages.filter((candidate) => candidate.planningContribution === "planInitialization");
344
+ if (initialRecords.length === 0) {
345
+ throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} has no initial Package provenance`);
346
+ }
347
+ const conflictingRecord = initialRecords.find((candidate) => candidate.definitionName !== options.generationRecord.preset);
348
+ if (conflictingRecord !== undefined) {
349
+ throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} conflicts with initial Package provenance ${conflictingRecord.definitionName} for Blueprint package ${conflictingRecord.path}`);
350
+ }
351
+ const preparedWithoutInitialLookup = joinedPackages.map((candidate) => {
352
+ if (candidate.record === record) {
353
+ return {
354
+ ...candidate,
355
+ owner: "foundation",
356
+ adapter: typescriptConfigReplayAdapter,
357
+ kind: "foundation",
358
+ };
359
+ }
360
+ let definition;
361
+ try {
362
+ definition = builtInPresetRegistry.require(candidate.record.definitionName);
363
+ }
364
+ catch {
365
+ throw new Error(`Package Addition Generation Record Package Planning Provenance references unknown Built-in Preset ${candidate.record.definitionName} for Blueprint package ${candidate.record.path}`);
366
+ }
367
+ if (candidate.record.planningContribution === "planPackageAddition" &&
368
+ definition.planPackageAddition === undefined) {
369
+ throw new Error(`Package Addition Generation Record Package Planning Provenance references unsupported Package Addition for Built-in Preset ${candidate.record.definitionName} at ${candidate.record.path}`);
370
+ }
371
+ return {
372
+ ...candidate,
373
+ owner: definition.metadata.name,
374
+ adapter: requireRecordReplayAdapter({
375
+ owner: definition.metadata.name,
376
+ adapters: definition.packageContributionReplayAdapters,
377
+ record: candidate.record,
378
+ }),
379
+ kind: "package",
380
+ };
381
+ });
382
+ const initialPlanningKeys = initialRecords.map((candidate) => `${candidate.definitionName}:${candidate.contributionIdentity}`);
383
+ if (new Set(initialPlanningKeys).size !== initialPlanningKeys.length) {
384
+ throw new Error("Package Addition Generation Record contains duplicate initialization contribution identity");
257
385
  }
258
- for (const expectedDefinition of initialBlueprint.packages) {
259
- const currentDefinition = options.blueprint.packages.find((definition) => definition.path === expectedDefinition.path);
260
- if (currentDefinition === undefined ||
261
- !packageDefinitionsEqual(currentDefinition, expectedDefinition)) {
262
- throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} cannot reproduce initial Blueprint Package Definition ${expectedDefinition.name} at ${expectedDefinition.path} (${expectedDefinition.role})`);
386
+ if (initialDefinition.initialPrimaryPackage !== undefined) {
387
+ if (initialRecords.length !== 1) {
388
+ throw new Error(`${initialDefinition.metadata.name} requires exactly one initial Primary Package Contribution provenance record`);
263
389
  }
264
390
  }
265
- for (const expectedIntent of initialBlueprint.packageLinkIntents ?? []) {
266
- if (!(options.blueprint.packageLinkIntents ?? []).some((currentIntent) => packageLinkIntentsEqual(currentIntent, expectedIntent))) {
267
- throw new Error(`Package Addition Generation Record preset ${options.generationRecord.preset} cannot reproduce initial Blueprint Package Link Intent ${expectedIntent.consumerPackagePath} -> ${expectedIntent.providerPackagePath}`);
391
+ else {
392
+ for (const adapter of initialDefinition.packageContributionReplayAdapters) {
393
+ const matchingRecords = initialRecords.filter((candidate) => candidate.contributionIdentity === adapter.identity);
394
+ if (matchingRecords.length !== 1) {
395
+ throw new Error(`${initialDefinition.metadata.name} requires exactly one initial ${adapter.identity} Package Contribution provenance record`);
396
+ }
268
397
  }
269
398
  }
399
+ const initialDefinitions = new Map(preparedWithoutInitialLookup.flatMap((candidate) => candidate.record.planningContribution === "planInitialization"
400
+ ? [[candidate.record.contributionIdentity, candidate.definition]]
401
+ : []));
402
+ const initialPackages = {
403
+ require(identity) {
404
+ const definition = initialDefinitions.get(identity);
405
+ if (definition === undefined) {
406
+ throw new Error(`${initialDefinition.metadata.name} has no preflighted initial ${identity} Package Definition`);
407
+ }
408
+ return definition;
409
+ },
410
+ };
411
+ const noInitialPackages = {
412
+ require(identity) {
413
+ throw new Error(`Foundation replay adapter does not declare initial Package ${identity}`);
414
+ },
415
+ };
416
+ return {
417
+ foundationPackage,
418
+ replays: preparedWithoutInitialLookup.map((candidate) => ({
419
+ ...candidate,
420
+ initialPackages: candidate.kind === "foundation" ? noInitialPackages : initialPackages,
421
+ })),
422
+ };
270
423
  }
271
- function environmentNeedOwner(value) {
272
- if (!isRecord(value))
273
- return undefined;
274
- if (value.kind === "workspace-orchestration" && value.path === ".") {
275
- return { kind: "workspace-orchestration", path: "." };
424
+ export function loadLocalTemplateMetadata(repositoryRoot) {
425
+ const resolvedRoot = path.resolve(repositoryRoot);
426
+ const blueprintPath = path.join(resolvedRoot, ".template/blueprint.json");
427
+ let blueprint;
428
+ try {
429
+ blueprint = assertProjectBlueprint(readJsonFile(blueprintPath, "Project Blueprint facts"));
276
430
  }
277
- if (value.kind === "package-boundary" && typeof value.path === "string") {
278
- return { kind: "package-boundary", path: value.path };
431
+ catch (error) {
432
+ throw new Error(`Package Addition requires a supported Project Blueprint in .template/blueprint.json: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
279
433
  }
280
- return undefined;
434
+ const generationRecord = readGenerationRecord({
435
+ repositoryRoot: resolvedRoot,
436
+ });
437
+ const preflight = preflightLocalTemplateMetadata({
438
+ blueprint,
439
+ generationRecord,
440
+ });
441
+ const rootVersions = readPackageAdditionVersionFacts(resolvedRoot);
442
+ const nodeFactsContext = {
443
+ targetDir: resolvedRoot,
444
+ repositoryName: generationRecord.repositoryName,
445
+ defaultPackageScope: generationRecord.defaultPackageScope,
446
+ foundationPackages: {
447
+ typescriptConfiguration: {
448
+ name: preflight.foundationPackage.definition.name,
449
+ },
450
+ },
451
+ toolchain: rootVersions.toolchain,
452
+ };
453
+ let context = nodeFactsContext;
454
+ let planningState = replayLocalTemplateMetadata({
455
+ context: nodeFactsContext,
456
+ preflight,
457
+ });
458
+ // 已有 Rust 能力事实的目标仓库由自己的根 rust-toolchain.toml 拥有后续版本选择:读出该现行
459
+ // channel 后重放,使根声明与开发容器初值来自同一个目标根事实;首次引入 Rust 的仓库还没有
460
+ // 该声明,保持缺省上下文交由建源路径处理。
461
+ if (normalizeRustToolchain([
462
+ planningState.foundationContribution,
463
+ ...planningState.packageContributions,
464
+ ]) !== undefined) {
465
+ context = {
466
+ ...nodeFactsContext,
467
+ toolchain: {
468
+ ...nodeFactsContext.toolchain,
469
+ rustVersion: readPackageAdditionTargetRustChannel(resolvedRoot),
470
+ },
471
+ };
472
+ planningState = replayLocalTemplateMetadata({ context, preflight });
473
+ }
474
+ return {
475
+ blueprint,
476
+ context,
477
+ [localTemplateMetadataStateKey]: {
478
+ generationRecord,
479
+ rootNodeDeclaration: rootVersions.rootNodeDeclaration,
480
+ ...planningState,
481
+ },
482
+ };
281
483
  }
282
- function assertEnvironmentNeedFactKeys(value, allowedKeys, context) {
283
- for (const key of Object.keys(value)) {
284
- if (!allowedKeys.includes(key)) {
285
- throw new Error(`Package Addition Environment Need ${context} contains unknown field: ${key}`);
286
- }
484
+ function requireReplayAdapter(options) {
485
+ const adapter = options.adapters.find((candidate) => candidate.identity === options.identity);
486
+ if (adapter === undefined) {
487
+ throw new Error(`unknown Package Contribution replay adapter ${options.identity}; expected ${options.adapters.map((candidate) => candidate.identity).join(", ")} for ${options.owner}`);
287
488
  }
489
+ return adapter;
288
490
  }
289
- function persistedCheckEnvironmentNeedFact(value, index) {
290
- if (!isRecord(value))
291
- return undefined;
292
- const context = `check[${index}]`;
293
- switch (value.kind) {
294
- case "playwright-browser-assets":
295
- assertEnvironmentNeedFactKeys(value, ["kind", "browser", "owner"], context);
296
- break;
297
- case "shellcheck-command":
298
- assertEnvironmentNeedFactKeys(value, ["kind", "owner"], context);
299
- break;
300
- case "rust-toolchain":
301
- assertEnvironmentNeedFactKeys(value, ["kind", "owner", "toolchain"], context);
302
- break;
303
- default:
304
- return undefined;
305
- }
306
- if (isRecord(value.owner)) {
307
- assertEnvironmentNeedFactKeys(value.owner, ["kind", "path"], `${context}.owner`);
308
- }
309
- const owner = environmentNeedOwner(value.owner);
310
- if (owner === undefined)
311
- return undefined;
312
- switch (value.kind) {
313
- case "playwright-browser-assets":
314
- return value.browser === "chromium"
315
- ? { kind: value.kind, browser: value.browser, owner }
316
- : undefined;
317
- case "shellcheck-command":
318
- return { kind: value.kind, owner };
319
- case "rust-toolchain":
320
- return value.toolchain === "stable"
321
- ? { kind: value.kind, toolchain: value.toolchain, owner }
322
- : undefined;
323
- default:
324
- return undefined;
491
+ function requireRecordReplayAdapter(options) {
492
+ try {
493
+ return requireReplayAdapter({
494
+ owner: options.owner,
495
+ adapters: options.adapters,
496
+ identity: options.record.contributionIdentity,
497
+ });
498
+ }
499
+ catch (error) {
500
+ throw new Error(`Package Planning Provenance ${options.owner}:${options.record.contributionIdentity} (${options.record.planningContribution}) at ${options.record.path} failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
501
+ }
502
+ }
503
+ function packageLeafName(packageDefinition) {
504
+ return packageDefinition.name.slice(packageDefinition.name.lastIndexOf("/") + 1);
505
+ }
506
+ function replayPersistedPackageContribution(options) {
507
+ let contribution;
508
+ try {
509
+ contribution = options.adapter.replay({
510
+ context: options.context,
511
+ planningContribution: options.record.planningContribution,
512
+ packageDefinition: options.packageDefinition,
513
+ packageLeafName: packageLeafName(options.packageDefinition),
514
+ initialPackages: options.initialPackages,
515
+ });
516
+ }
517
+ catch (error) {
518
+ throw new Error(`Package Planning Provenance ${options.owner}:${options.record.contributionIdentity} (${options.record.planningContribution}) at ${options.record.path} failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
519
+ }
520
+ if (!packageDefinitionsEqual(contribution.definition, options.packageDefinition)) {
521
+ throw new Error(`Package Planning Provenance ${options.owner}:${options.record.contributionIdentity} at ${options.record.path} expected ${options.packageDefinition.name} / ${options.packageDefinition.path} / ${options.packageDefinition.role}, received ${contribution.definition.name} / ${contribution.definition.path} / ${contribution.definition.role}`);
325
522
  }
523
+ return options.adapter.identify(contribution);
524
+ }
525
+ function replayLocalTemplateMetadata(options) {
526
+ let foundationContribution;
527
+ const packageContributions = [];
528
+ for (const replay of options.preflight.replays) {
529
+ const contribution = replayPersistedPackageContribution({
530
+ context: options.context,
531
+ owner: replay.owner,
532
+ adapter: replay.adapter,
533
+ record: replay.record,
534
+ packageDefinition: replay.definition,
535
+ initialPackages: replay.initialPackages,
536
+ });
537
+ if (replay.kind === "foundation") {
538
+ foundationContribution = contribution;
539
+ }
540
+ else {
541
+ packageContributions.push(contribution);
542
+ }
543
+ }
544
+ if (foundationContribution === undefined) {
545
+ throw new Error("Package Addition Generation Record is missing its validated Foundation contribution");
546
+ }
547
+ return { foundationContribution, packageContributions };
326
548
  }
327
549
  function readPersistedEnvironmentNeeds(targetDir) {
328
550
  const filePath = path.join(targetDir, environmentNeedsPath);
@@ -334,116 +556,97 @@ function readPersistedEnvironmentNeeds(targetDir) {
334
556
  value = JSON.parse(readFileSync(filePath, "utf8"));
335
557
  }
336
558
  catch (error) {
337
- throw new Error(`Package Addition requires valid Check Environment Need facts: ${error instanceof Error ? error.message : String(error)}`);
559
+ throw new Error(`Package Addition requires valid Check Environment Need facts: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
338
560
  }
339
- if (isRecord(value)) {
340
- for (const key of Object.keys(value)) {
341
- if (!["schemaVersion", "check", "deployment"].includes(key)) {
342
- throw new Error(`Package Addition Environment Need facts contain unknown field: ${key}`);
343
- }
344
- }
345
- }
346
- if (!isRecord(value) ||
347
- value.schemaVersion !== 1 ||
348
- !Array.isArray(value.check) ||
349
- !Array.isArray(value.deployment)) {
350
- throw new Error(`Package Addition requires valid Check Environment Need facts in ${environmentNeedsPath}`);
351
- }
352
- const check = value.check.map(persistedCheckEnvironmentNeedFact);
353
- if (check.some((fact) => fact === undefined)) {
354
- throw new Error(`Package Addition requires supported Check Environment Need facts in ${environmentNeedsPath}`);
561
+ try {
562
+ return parseEnvironmentNeedsMetadata(value);
355
563
  }
356
- if (value.deployment.some((fact, index) => {
357
- if (!isRecord(fact) || fact.kind !== "docker-engine")
358
- return true;
359
- assertEnvironmentNeedFactKeys(fact, ["kind"], `deployment[${index}]`);
360
- return false;
361
- })) {
362
- throw new Error(`Package Addition requires supported deployment Environment Need facts in ${environmentNeedsPath}`);
564
+ catch (error) {
565
+ throw new Error(`Package Addition requires valid Environment Need metadata in ${environmentNeedsPath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
363
566
  }
364
- return {
365
- check: check.map(checkEnvironmentNeedFromFact),
366
- deployment: value.deployment.map((fact) => deploymentEnvironmentNeedFromFact(fact)),
367
- };
368
- }
369
- function uniqueEnvironmentNeeds(needs) {
370
- const seen = new Set();
371
- return needs.filter((need) => {
372
- const key = JSON.stringify(need);
373
- if (seen.has(key))
374
- return false;
375
- seen.add(key);
376
- return true;
377
- });
378
567
  }
379
568
  function readExistingPackageAdditionState(options) {
380
- const generationRecord = readGenerationRecord(options);
381
- const persistedEnvironmentNeeds = readPersistedEnvironmentNeeds(options.context.targetDir);
569
+ const { blueprint, context } = options.localTemplateMetadata;
570
+ const state = options.localTemplateMetadata[localTemplateMetadataStateKey];
571
+ const { foundationContribution, generationRecord, packageContributions: contributions, } = state;
572
+ const persistedEnvironmentNeeds = readPersistedEnvironmentNeeds(context.targetDir);
573
+ const allContributions = [foundationContribution, ...contributions];
574
+ const deploymentCheck = normalizeDeploymentCheck(allContributions);
575
+ const vueHonoJointE2e = normalizeVueHonoJointE2e(allContributions);
576
+ const databasePreparation = normalizeDatabasePreparation(allContributions);
382
577
  const manifestTruthByPackagePath = new Map();
383
- const contributions = generationRecord.packages.flatMap((record) => {
384
- if (record.planningContribution === "foundationPlan") {
385
- return [];
386
- }
387
- const expectedDefinition = options.blueprint.packages.find((definition) => definition.path === record.path);
388
- const definition = builtInPresetRegistry.require(record.definitionName);
389
- let candidates;
390
- if (record.planningContribution === "planInitialization") {
391
- candidates = definition.planInitializationContributions?.(options.context) ?? [definition.planInitialization(options.context)];
392
- }
393
- else {
394
- if (definition.planPackageAddition === undefined) {
395
- throw new Error(`Generation Record Definition ${record.definitionName} no longer supports Package Addition`);
396
- }
397
- const packageLeafName = expectedDefinition.name.split("/")[1];
398
- if (!packageLeafName) {
399
- throw new Error(`Generation Record package has an invalid name: ${expectedDefinition.name}`);
400
- }
401
- candidates = [
402
- definition.planPackageAddition({
403
- context: options.context,
404
- packageLeafName,
405
- packagePath: expectedDefinition.path,
406
- }),
407
- ];
408
- }
409
- const contribution = candidates.find((candidate) => packageDefinitionsEqual(candidate.definition, expectedDefinition));
410
- if (contribution === undefined) {
411
- throw new Error(`Generation Record cannot reproduce Package Definition ${expectedDefinition.name} at ${expectedDefinition.path}`);
578
+ const requiredManifestTruthPackagePaths = new Set(options.requiredManifestTruthPackagePaths ?? []);
579
+ const packageByName = new Map(allContributions.map((contribution) => [
580
+ contribution.definition.name,
581
+ contribution,
582
+ ]));
583
+ const capabilityPackageNames = [
584
+ ...(databasePreparation === undefined
585
+ ? []
586
+ : [
587
+ databasePreparation.databasePackageName,
588
+ databasePreparation.migrationPackageName,
589
+ ...Object.values(databasePreparation.consumers),
590
+ ]),
591
+ ...(deploymentCheck === undefined
592
+ ? []
593
+ : [
594
+ deploymentCheck.applicationPackageName,
595
+ deploymentCheck.databasePackageName,
596
+ deploymentCheck.migrationPackageName,
597
+ ]),
598
+ ];
599
+ for (const packageName of capabilityPackageNames) {
600
+ const contribution = packageByName.get(packageName);
601
+ if (contribution !== undefined) {
602
+ requiredManifestTruthPackagePaths.add(contribution.definition.path);
412
603
  }
413
- return [contribution];
414
- });
415
- for (const packagePath of new Set(options.manifestTruthPackagePaths ?? [])) {
416
- const expectedDefinition = options.blueprint.packages.find((definition) => definition.path === packagePath);
417
- if (expectedDefinition === undefined) {
604
+ }
605
+ for (const packagePath of requiredManifestTruthPackagePaths) {
606
+ if (!blueprint.packages.some((definition) => definition.path === packagePath)) {
418
607
  throw new Error(`Package Addition requires manifest truth for unknown Package Path ${packagePath}`);
419
608
  }
420
- const manifestPath = path.join(options.context.targetDir, packagePath, "package.json");
609
+ }
610
+ for (const expectedDefinition of blueprint.packages) {
611
+ const manifestPath = path.join(context.targetDir, expectedDefinition.path, "package.json");
612
+ if (!existsSync(manifestPath) &&
613
+ !requiredManifestTruthPackagePaths.has(expectedDefinition.path)) {
614
+ continue;
615
+ }
421
616
  let manifest;
422
617
  try {
423
618
  manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
424
619
  }
425
620
  catch (error) {
426
- throw new Error(`Package Addition requires manifest truth for ${expectedDefinition.path}: ${error instanceof Error ? error.message : String(error)}`);
621
+ throw new Error(`Package Addition requires manifest truth for ${expectedDefinition.path}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
427
622
  }
428
623
  if (!isRecord(manifest) || manifest.name !== expectedDefinition.name) {
429
624
  throw new Error(`Package Addition requires manifest truth for ${expectedDefinition.path}: expected name ${expectedDefinition.name}`);
430
625
  }
431
626
  manifestTruthByPackagePath.set(expectedDefinition.path, manifest);
432
627
  }
433
- const reconstructedCheckFacts = uniqueEnvironmentNeeds(contributions.flatMap((contribution) => contribution.environmentNeeds)).map(checkEnvironmentNeedFact);
434
- const reconstructedDeploymentFacts = uniqueEnvironmentNeeds(contributions.flatMap((contribution) => contribution.deploymentEnvironmentNeeds ?? [])).map(deploymentEnvironmentNeedFact);
435
- const persistedCheckFacts = persistedEnvironmentNeeds.check.map(checkEnvironmentNeedFact);
436
- const persistedDeploymentFacts = persistedEnvironmentNeeds.deployment.map(deploymentEnvironmentNeedFact);
437
- if (JSON.stringify(reconstructedCheckFacts) !==
438
- JSON.stringify(persistedCheckFacts) ||
439
- JSON.stringify(reconstructedDeploymentFacts) !==
440
- JSON.stringify(persistedDeploymentFacts)) {
441
- throw new Error("Package Addition requires persisted Environment Need facts to match the reproducible Project Projection");
628
+ assertCapabilityRepositoryTruth({
629
+ repositoryRoot: context.targetDir,
630
+ blueprint,
631
+ contributions: allContributions,
632
+ packageByName,
633
+ manifestTruthByPackagePath,
634
+ databasePreparation,
635
+ deploymentCheck,
636
+ vueHonoJointE2e,
637
+ });
638
+ const reconstructedEnvironmentNeeds = normalizeEnvironmentNeeds({
639
+ check: foundationCheckEnvironmentNeeds(allContributions, deploymentCheck, vueHonoJointE2e),
640
+ deployment: deploymentCheck?.environmentNeeds ?? [],
641
+ });
642
+ if (JSON.stringify(reconstructedEnvironmentNeeds) !==
643
+ JSON.stringify(persistedEnvironmentNeeds)) {
644
+ throw new Error("Package Addition requires persisted Environment Needs to match the reproducible Project Projection");
442
645
  }
443
646
  return {
647
+ foundationContribution,
444
648
  contributions,
445
649
  manifestTruthByPackagePath,
446
- deploymentEnvironmentNeeds: persistedEnvironmentNeeds.deployment,
447
650
  generationRecord,
448
651
  };
449
652
  }
@@ -452,6 +655,13 @@ function packageDefinitionsEqual(left, right) {
452
655
  left.path === right.path &&
453
656
  left.role === right.role);
454
657
  }
658
+ function requirePersistedPackageDefinition(blueprint, definition) {
659
+ const persisted = blueprint.packages.find((candidate) => packageDefinitionsEqual(candidate, definition));
660
+ if (persisted === undefined) {
661
+ throw new Error(`Project Blueprint has no persisted Package Definition for ${definition.name} at ${definition.path} (${definition.role})`);
662
+ }
663
+ return persisted;
664
+ }
455
665
  function packageLinkIntentsEqual(left, right) {
456
666
  return (left.consumerPackagePath === right.consumerPackagePath &&
457
667
  left.providerPackagePath === right.providerPackagePath);
@@ -484,13 +694,14 @@ function contributedDevcontainerComposition(options) {
484
694
  buildArguments: [
485
695
  {
486
696
  name: "NODE_VERSION",
487
- value: options.context.toolchain.nodeLtsMajor,
488
- },
489
- {
490
- name: "PACKAGE_MANAGER_PIN",
491
- value: options.context.toolchain.packageManagerPin,
697
+ // 根 Node 声明原文是 M1 槽位唯一来源;major 与快照字段不得另作真源。
698
+ value: options.rootNodeDeclaration,
492
699
  },
493
700
  ],
701
+ probes: [
702
+ { identity: "procps", command: "ps", args: ["--version"] },
703
+ { identity: "bubblewrap", command: "bwrap", args: ["--version"] },
704
+ ],
494
705
  mounts: [
495
706
  {
496
707
  identity: "pnpm-store",
@@ -510,9 +721,8 @@ function contributedDevcontainerComposition(options) {
510
721
  from: "devcontainer.json",
511
722
  to: ".devcontainer/devcontainer.json",
512
723
  replacements: {
513
- PROJECT_NAME: options.context.projectName,
514
- NODE_LTS_MAJOR: options.context.toolchain.nodeLtsMajor,
515
- PACKAGE_MANAGER_PIN: options.context.toolchain.packageManagerPin,
724
+ PROJECT_NAME: options.context.repositoryName,
725
+ NODE_VERSION: options.rootNodeDeclaration,
516
726
  },
517
727
  },
518
728
  {
@@ -556,122 +766,1055 @@ function contributedDevcontainerComposition(options) {
556
766
  probes: layerPlan.probes,
557
767
  };
558
768
  }
559
- function contributedFoundationTemplateFileOperations(contributions) {
560
- const byIdentity = new Map();
561
- const outputOwners = new Map();
562
- for (const file of contributions.flatMap((contribution) => contribution.foundation.templateFiles ?? [])) {
563
- const previous = byIdentity.get(file.identity);
564
- if (previous !== undefined) {
565
- const previousFingerprint = JSON.stringify({
566
- source: resolveTemplateSource(previous.source, previous.from),
567
- from: previous.from,
568
- to: previous.to,
569
- replacements: previous.replacements ?? {},
570
- });
571
- const fingerprint = JSON.stringify({
572
- source: resolveTemplateSource(file.source, file.from),
573
- from: file.from,
574
- to: file.to,
575
- replacements: file.replacements ?? {},
576
- });
577
- if (fingerprint !== previousFingerprint) {
578
- throw new Error(`Foundation Template File identity ${file.identity} has conflicting descriptors`);
579
- }
580
- continue;
769
+ function normalizeDatabasePreparation(contributions) {
770
+ const declarations = contributions.flatMap((contribution) => {
771
+ const capability = contribution.foundation.databasePreparation;
772
+ if (capability === undefined)
773
+ return [];
774
+ if (capability.kind !== "sqlite-database-preparation") {
775
+ throw new Error("Database Preparation has an unsupported capability kind");
581
776
  }
582
- const outputOwner = outputOwners.get(file.to);
583
- if (outputOwner !== undefined) {
584
- throw new Error(`Foundation Template File output ${file.to} is declared by both ${outputOwner} and ${file.identity}`);
777
+ const consumers = Object.fromEntries(capability.consumers.map((consumer) => [
778
+ consumer.kind,
779
+ consumer.packageName,
780
+ ]));
781
+ if (capability.consumers.length !== 3 ||
782
+ new Set(capability.consumers.map((consumer) => consumer.kind)).size !==
783
+ 3 ||
784
+ consumers["application-dev"] === undefined ||
785
+ consumers["database-test"] === undefined ||
786
+ consumers["application-e2e"] === undefined) {
787
+ throw new Error("Database Preparation must declare application-dev, database-test, and application-e2e consumers exactly once");
585
788
  }
586
- byIdentity.set(file.identity, file);
587
- outputOwners.set(file.to, file.identity);
588
- }
589
- return [...byIdentity.values()]
590
- .toSorted((left, right) => left.identity.localeCompare(right.identity))
591
- .map((file) => ({
592
- kind: "writeTextTemplate",
593
- source: file.source,
594
- from: file.from,
595
- to: file.to,
596
- replacements: { ...file.replacements },
597
- }));
598
- }
599
- function assertCompatibleRustToolchainFacts(contributions) {
600
- const facts = contributions.flatMap((contribution) => {
601
- const rust = contribution.foundation.toolchains.rust;
602
- return rust === undefined
603
- ? []
604
- : [
605
- JSON.stringify({
606
- toolchain: rust.toolchain,
607
- components: [...new Set(rust.components)].toSorted(),
789
+ const normalizedConsumers = {
790
+ "application-dev": consumers["application-dev"],
791
+ "database-test": consumers["database-test"],
792
+ "application-e2e": consumers["application-e2e"],
793
+ };
794
+ return [
795
+ {
796
+ databasePackageName: contribution.definition.name,
797
+ migrationPackageName: capability.migrationPackageName,
798
+ consumers: normalizedConsumers,
799
+ fingerprint: JSON.stringify({
800
+ databasePackageName: contribution.definition.name,
801
+ migrationPackageName: capability.migrationPackageName,
802
+ consumers: normalizedConsumers,
803
+ profiles: ["dev", "test", "e2e"],
608
804
  }),
609
- ];
805
+ },
806
+ ];
610
807
  });
611
- if (new Set(facts).size > 1) {
612
- throw new Error("Foundation requires compatible Rust toolchain facts");
808
+ const first = declarations.at(0);
809
+ if (first === undefined)
810
+ return undefined;
811
+ if (declarations.some((item) => item.fingerprint !== first.fingerprint)) {
812
+ throw new Error("Database Preparation has conflicting capability declarations");
613
813
  }
814
+ return first;
614
815
  }
615
- function composeDependencyMaintenancePolicy(contributions) {
616
- const ecosystems = [
617
- ...new Set(contributions.flatMap((contribution) => contribution.foundation.dependencyMaintenance.ecosystems)),
618
- ];
619
- const directories = {};
620
- const extraDirectories = {};
621
- for (const ecosystem of ecosystems) {
622
- const candidates = [
623
- ...new Set(contributions.flatMap((contribution) => {
624
- const policy = contribution.foundation.dependencyMaintenance;
625
- const primary = policy.directories?.[ecosystem];
626
- return [
627
- ...(primary === undefined ? [] : [primary]),
628
- ...(policy.extraDirectories?.[ecosystem] ?? []),
629
- ];
630
- })),
631
- ];
632
- const [primary, ...extra] = candidates;
633
- if (primary !== undefined)
634
- directories[ecosystem] = primary;
635
- if (extra.length > 0)
636
- extraDirectories[ecosystem] = extra;
637
- }
816
+ function databasePreparationCommands(preparation) {
817
+ const run = (profile, packageName, task) => `DATABASE_PROFILE=${profile} pnpm --filter ${packageName} run ${task}`;
638
818
  return {
639
- ecosystems,
640
- ...(Object.keys(directories).length === 0 ? {} : { directories }),
641
- ...(Object.keys(extraDirectories).length === 0 ? {} : { extraDirectories }),
642
- interval: "weekly",
819
+ "database:prepare:dev": [
820
+ run("dev", preparation.migrationPackageName, "db:push"),
821
+ run("dev", preparation.databasePackageName, "db:seed:example"),
822
+ ].join(" && "),
823
+ "database:prepare:test": [
824
+ run("test", preparation.databasePackageName, "db:reset"),
825
+ run("test", preparation.migrationPackageName, "db:push"),
826
+ run("test", preparation.databasePackageName, "db:seed:example"),
827
+ ].join(" && "),
828
+ "database:prepare:e2e": [
829
+ run("e2e", preparation.databasePackageName, "db:reset"),
830
+ run("e2e", preparation.migrationPackageName, "db:push"),
831
+ run("e2e", preparation.databasePackageName, "db:seed:example"),
832
+ ].join(" && "),
833
+ dev: `pnpm run database:prepare:dev && turbo watch dev --filter=${preparation.consumers["application-dev"]}`,
643
834
  };
644
835
  }
645
- function foundationPlan(options) {
646
- assertProjectBlueprintV2(options.blueprint);
647
- const configDefinition = typescriptConfigPackageDefinition(options.context);
648
- const persistedConfigDefinition = options.blueprint.packages.find((definition) => definition.name === configDefinition.name ||
649
- definition.path === configDefinition.path);
650
- if (persistedConfigDefinition === undefined ||
651
- !packageDefinitionsEqual(persistedConfigDefinition, configDefinition)) {
652
- throw new Error("Project Blueprint must contain the Foundation TypeScript configuration Package Definition");
653
- }
654
- const initialProjectLinkPlan = planExplicitProjectLinks({
655
- blueprint: options.blueprint,
656
- contributions: options.contributions,
657
- ...(options.manifestTruthByPackagePath === undefined
836
+ function databasePreparationTurboTasks(preparation) {
837
+ return {
838
+ "//#database:prepare:dev": { cache: false },
839
+ "//#database:prepare:test": { cache: false },
840
+ "//#database:prepare:e2e": { cache: false },
841
+ [`${preparation.databasePackageName}#test`]: {
842
+ dependsOn: ["//#database:prepare:test"],
843
+ },
844
+ [`${preparation.migrationPackageName}#typecheck`]: {
845
+ dependsOn: [`${preparation.databasePackageName}#build`],
846
+ },
847
+ [`${preparation.consumers["application-dev"]}#typecheck`]: {
848
+ dependsOn: [`${preparation.databasePackageName}#build`],
849
+ },
850
+ [`${preparation.consumers["application-dev"]}#dev`]: {
851
+ dependsOn: [`${preparation.databasePackageName}#build`],
852
+ cache: false,
853
+ persistent: true,
854
+ },
855
+ [`${preparation.consumers["application-e2e"]}#test:e2e`]: {
856
+ dependsOn: [
857
+ "//#database:prepare:e2e",
858
+ `${preparation.databasePackageName}#build`,
859
+ "build",
860
+ ],
861
+ cache: false,
862
+ },
863
+ };
864
+ }
865
+ function deploymentTurboTasks(deploymentCheck) {
866
+ return {
867
+ "//#deployment": {
868
+ dependsOn: [
869
+ `${deploymentCheck.applicationPackageName}#build`,
870
+ `${deploymentCheck.databasePackageName}#build`,
871
+ `${deploymentCheck.migrationPackageName}#build`,
872
+ ],
873
+ cache: false,
874
+ },
875
+ };
876
+ }
877
+ function vueHonoJointE2eTurboTasks(e2e) {
878
+ return {
879
+ "//#test:e2e": {
880
+ dependsOn: [`${e2e.apiPackageName}#build`, `${e2e.webPackageName}#build`],
881
+ cache: false,
882
+ },
883
+ };
884
+ }
885
+ function assertDatabasePreparationManifestTruth(options) {
886
+ const { preparation, packageByName, manifestTruthByPackagePath } = options;
887
+ if (preparation === undefined || manifestTruthByPackagePath === undefined) {
888
+ return;
889
+ }
890
+ const expectedTasks = [
891
+ [preparation.databasePackageName, "build"],
892
+ [preparation.databasePackageName, "db:reset"],
893
+ [preparation.databasePackageName, "db:seed:example"],
894
+ [preparation.databasePackageName, "test"],
895
+ [preparation.migrationPackageName, "db:push"],
896
+ [preparation.migrationPackageName, "typecheck"],
897
+ [preparation.consumers["application-dev"], "dev"],
898
+ [preparation.consumers["application-dev"], "typecheck"],
899
+ [preparation.consumers["application-e2e"], "build"],
900
+ [preparation.consumers["application-e2e"], "test:e2e"],
901
+ ];
902
+ for (const [packageName, taskName] of expectedTasks) {
903
+ const contribution = requireContributionByName(packageByName, packageName, "Database Preparation");
904
+ const manifest = requireManifestTruth(manifestTruthByPackagePath, contribution, "Database Preparation");
905
+ const actualScripts = manifest.scripts;
906
+ const expectedScripts = contribution.manifest.scripts;
907
+ const actual = isRecord(actualScripts)
908
+ ? actualScripts[taskName]
909
+ : undefined;
910
+ const expected = isRecord(expectedScripts)
911
+ ? expectedScripts[taskName]
912
+ : undefined;
913
+ if (actual !== expected) {
914
+ throw new Error(`Database Preparation requires exact ${packageName} script ${taskName}`);
915
+ }
916
+ }
917
+ }
918
+ function normalizeDeploymentCheck(contributions) {
919
+ const declarations = contributions.flatMap((contribution) => {
920
+ const check = contribution.foundation.deploymentCheck;
921
+ if (check === undefined)
922
+ return [];
923
+ if (check.kind !== "application-container-with-database-migrations") {
924
+ throw new Error("Deployment Check has an unsupported capability kind");
925
+ }
926
+ return [{ ...check, declaringPackagePath: contribution.definition.path }];
927
+ });
928
+ if (declarations.length > 1) {
929
+ throw new Error("Deployment Check has multiple capability declarations");
930
+ }
931
+ return declarations.at(0);
932
+ }
933
+ function normalizeVueHonoJointE2e(contributions) {
934
+ const declarations = contributions.flatMap((contribution) => {
935
+ const e2e = contribution.foundation.vueHonoJointE2e;
936
+ if (e2e === undefined)
937
+ return [];
938
+ if (e2e.kind !== "vue-hono-joint-e2e") {
939
+ throw new Error("Vue-Hono joint E2E has an unsupported capability kind");
940
+ }
941
+ return [
942
+ {
943
+ ...e2e,
944
+ webPackageName: contribution.definition.name,
945
+ declaringPackagePath: contribution.definition.path,
946
+ },
947
+ ];
948
+ });
949
+ if (declarations.length > 1) {
950
+ throw new Error("Vue-Hono joint E2E has multiple capability declarations");
951
+ }
952
+ return declarations.at(0);
953
+ }
954
+ function requireContributionByName(packageByName, packageName, capability) {
955
+ const contribution = packageByName.get(packageName);
956
+ if (contribution === undefined) {
957
+ throw new Error(`${capability} references unknown Package ${packageName}`);
958
+ }
959
+ return contribution;
960
+ }
961
+ function requireManifestTruth(manifestTruthByPackagePath, contribution, capability) {
962
+ const manifest = manifestTruthByPackagePath.get(contribution.definition.path);
963
+ if (manifest === undefined) {
964
+ throw new Error(`${capability} requires manifest truth for ${contribution.definition.path}`);
965
+ }
966
+ return manifest;
967
+ }
968
+ function assertExpectedRecordMembers(options) {
969
+ if (!isRecord(options.expected)) {
970
+ throw new Error(`${options.label} replay did not provide object truth`);
971
+ }
972
+ if (!isRecord(options.actual)) {
973
+ throw new Error(`${options.label} must be an object`);
974
+ }
975
+ for (const [key, expectedValue] of Object.entries(options.expected)) {
976
+ if (!isDeepStrictEqual(options.actual[key], expectedValue)) {
977
+ throw new Error(`${options.label} must preserve replayed member ${key}`);
978
+ }
979
+ }
980
+ }
981
+ function assertArtifactConditionOrder(options) {
982
+ if (!isRecord(options.expected) || !isRecord(options.actual))
983
+ return;
984
+ const conditionNames = ["source", "types", "default"];
985
+ const expectedConditions = Object.keys(options.expected).filter((name) => conditionNames.includes(name));
986
+ if (!expectedConditions.includes("source") ||
987
+ !expectedConditions.some((name) => name === "types" || name === "default")) {
988
+ return;
989
+ }
990
+ const actualConditions = Object.keys(options.actual).filter((name) => expectedConditions.includes(name));
991
+ if (!isDeepStrictEqual(actualConditions, expectedConditions)) {
992
+ throw new Error(`${options.label} must preserve replayed condition order`);
993
+ }
994
+ }
995
+ function assertDatabaseArtifactConditionTruth(options) {
996
+ if (!isRecord(options.actual) || !isRecord(options.expected))
997
+ return;
998
+ for (const [memberName, expectedMember] of Object.entries(options.expected)) {
999
+ assertArtifactConditionOrder({
1000
+ actual: options.actual[memberName],
1001
+ expected: expectedMember,
1002
+ label: `${options.label} ${memberName}`,
1003
+ });
1004
+ }
1005
+ }
1006
+ function assertDatabaseArtifactManifestTruth(options) {
1007
+ if (options.preparation === undefined)
1008
+ return;
1009
+ const database = requireContributionByName(options.packageByName, options.preparation.databasePackageName, "Database Preparation");
1010
+ const actual = requireManifestTruth(options.manifestTruthByPackagePath, database, "Database Preparation");
1011
+ const expected = database.manifest;
1012
+ if (actual.type !== expected.type || expected.type !== "module") {
1013
+ throw new Error(`Database Preparation requires ${database.definition.name} manifest type module`);
1014
+ }
1015
+ if (!Array.isArray(expected.files)) {
1016
+ throw new Error(`Database Preparation replay for ${database.definition.name} did not provide files truth`);
1017
+ }
1018
+ const actualFiles = actual.files;
1019
+ if (!Array.isArray(actualFiles) ||
1020
+ expected.files.some((expectedFile) => !actualFiles.some((actualFile) => isDeepStrictEqual(actualFile, expectedFile)))) {
1021
+ throw new Error(`Database Preparation requires ${database.definition.name} public build files`);
1022
+ }
1023
+ assertExpectedRecordMembers({
1024
+ actual: actual.exports,
1025
+ expected: expected.exports,
1026
+ label: `Database Preparation ${database.definition.name} exports`,
1027
+ });
1028
+ assertDatabaseArtifactConditionTruth({
1029
+ actual: actual.exports,
1030
+ expected: expected.exports,
1031
+ label: `Database Preparation ${database.definition.name} exports`,
1032
+ });
1033
+ assertExpectedRecordMembers({
1034
+ actual: actual.imports,
1035
+ expected: expected.imports,
1036
+ label: `Database Preparation ${database.definition.name} imports`,
1037
+ });
1038
+ assertDatabaseArtifactConditionTruth({
1039
+ actual: actual.imports,
1040
+ expected: expected.imports,
1041
+ label: `Database Preparation ${database.definition.name} imports`,
1042
+ });
1043
+ }
1044
+ function assertDatabaseProjectLinkManifestTruth(options) {
1045
+ if (options.preparation === undefined)
1046
+ return;
1047
+ const database = requireContributionByName(options.packageByName, options.preparation.databasePackageName, "Database Preparation");
1048
+ const expectedLinks = planExplicitProjectLinks({
1049
+ blueprint: options.blueprint,
1050
+ contributions: options.contributions,
1051
+ });
1052
+ for (const intent of options.blueprint.packageLinkIntents ?? []) {
1053
+ if (intent.providerPackagePath !== database.definition.path)
1054
+ continue;
1055
+ const consumer = options.contributions.find((candidate) => candidate.definition.path === intent.consumerPackagePath);
1056
+ if (consumer === undefined) {
1057
+ throw new Error(`Database Preparation Project Link references unknown consumer ${intent.consumerPackagePath}`);
1058
+ }
1059
+ const actual = requireManifestTruth(options.manifestTruthByPackagePath, consumer, "Database Preparation Project Link");
1060
+ if (!isRecord(actual.dependencies) ||
1061
+ actual.dependencies[database.definition.name] !== "workspace:*") {
1062
+ throw new Error(`Database Preparation requires ${consumer.definition.name} to depend on ${database.definition.name} through workspace:*`);
1063
+ }
1064
+ const expectedMetadata = expectedLinks.manifestPatchesByPackagePath.get(consumer.definition.path)?.dependenciesMeta?.[database.definition.name];
1065
+ if (actual.dependenciesMeta !== undefined &&
1066
+ !isRecord(actual.dependenciesMeta)) {
1067
+ throw new Error(`Database Preparation requires valid dependency metadata in ${consumer.definition.name}`);
1068
+ }
1069
+ const actualMetadata = isRecord(actual.dependenciesMeta)
1070
+ ? actual.dependenciesMeta[database.definition.name]
1071
+ : undefined;
1072
+ if (!isDeepStrictEqual(actualMetadata, expectedMetadata)) {
1073
+ throw new Error(`Database Preparation requires replayed Project Link metadata for ${consumer.definition.name} -> ${database.definition.name}`);
1074
+ }
1075
+ }
1076
+ }
1077
+ function assertDeploymentBuildManifestTruth(options) {
1078
+ if (options.deploymentCheck === undefined)
1079
+ return;
1080
+ for (const packageName of [
1081
+ options.deploymentCheck.applicationPackageName,
1082
+ options.deploymentCheck.databasePackageName,
1083
+ options.deploymentCheck.migrationPackageName,
1084
+ ]) {
1085
+ const contribution = requireContributionByName(options.packageByName, packageName, "Deployment Check");
1086
+ const actual = requireManifestTruth(options.manifestTruthByPackagePath, contribution, "Deployment Check");
1087
+ const actualBuild = isRecord(actual.scripts)
1088
+ ? actual.scripts.build
1089
+ : undefined;
1090
+ const expectedBuild = isRecord(contribution.manifest.scripts)
1091
+ ? contribution.manifest.scripts.build
1092
+ : undefined;
1093
+ if (typeof expectedBuild !== "string" || actualBuild !== expectedBuild) {
1094
+ throw new Error(`Deployment Check requires exact ${packageName} manifest script build`);
1095
+ }
1096
+ }
1097
+ }
1098
+ function assertVueHonoJointE2eManifestTruth(options) {
1099
+ if (options.e2e === undefined)
1100
+ return;
1101
+ if (options.e2e.apiPackageName === options.e2e.webPackageName) {
1102
+ throw new Error("Vue-Hono joint E2E requires distinct API and web Packages");
1103
+ }
1104
+ const expectedTasks = [
1105
+ [options.e2e.apiPackageName, "build"],
1106
+ [options.e2e.apiPackageName, "start"],
1107
+ [options.e2e.webPackageName, "build"],
1108
+ [options.e2e.webPackageName, "preview"],
1109
+ ];
1110
+ for (const [packageName, taskName] of expectedTasks) {
1111
+ const contribution = requireContributionByName(options.packageByName, packageName, "Vue-Hono joint E2E");
1112
+ const actual = requireManifestTruth(options.manifestTruthByPackagePath, contribution, "Vue-Hono joint E2E");
1113
+ const expected = isRecord(contribution.manifest.scripts)
1114
+ ? contribution.manifest.scripts[taskName]
1115
+ : undefined;
1116
+ const actualScript = isRecord(actual.scripts)
1117
+ ? actual.scripts[taskName]
1118
+ : undefined;
1119
+ if (typeof expected !== "string" || actualScript !== expected) {
1120
+ throw new Error(`Vue-Hono joint E2E requires exact ${packageName} manifest script ${taskName}`);
1121
+ }
1122
+ }
1123
+ }
1124
+ function readRepositoryJsonRecord(options) {
1125
+ const value = readJsonFile(path.join(options.repositoryRoot, options.relativePath), `${options.label} in ${options.relativePath}`);
1126
+ if (!isRecord(value)) {
1127
+ throw new Error(`Package Addition requires ${options.label} in ${options.relativePath} to be an object`);
1128
+ }
1129
+ return value;
1130
+ }
1131
+ function assertRootCapabilityManifestTruth(options) {
1132
+ if (options.databasePreparation === undefined &&
1133
+ options.deploymentCheck === undefined &&
1134
+ options.vueHonoJointE2e === undefined) {
1135
+ return;
1136
+ }
1137
+ const manifest = readRepositoryJsonRecord({
1138
+ repositoryRoot: options.repositoryRoot,
1139
+ relativePath: "package.json",
1140
+ label: "root Manifest Truth",
1141
+ });
1142
+ if (!isRecord(manifest.scripts)) {
1143
+ throw new Error("Package Addition requires root manifest scripts truth");
1144
+ }
1145
+ const expectedScripts = {
1146
+ ...(options.databasePreparation === undefined
1147
+ ? {}
1148
+ : databasePreparationCommands(options.databasePreparation)),
1149
+ ...(options.deploymentCheck === undefined
1150
+ ? {}
1151
+ : {
1152
+ deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
1153
+ "check:deployment": renderDeploymentCheckCommand(),
1154
+ }),
1155
+ ...(options.vueHonoJointE2e === undefined
1156
+ ? {}
1157
+ : { "test:e2e": "playwright test" }),
1158
+ };
1159
+ for (const [scriptName, expectedCommand] of Object.entries(expectedScripts)) {
1160
+ if (manifest.scripts[scriptName] !== expectedCommand) {
1161
+ throw new Error(`Package Addition requires exact root manifest script ${scriptName}`);
1162
+ }
1163
+ }
1164
+ }
1165
+ function assertTurboTaskTruth(options) {
1166
+ if (!isRecord(options.config.tasks)) {
1167
+ throw new Error(`${options.label} requires Turbo tasks truth`);
1168
+ }
1169
+ for (const [taskName, expectedTask] of Object.entries(options.expectedTasks)) {
1170
+ const actualTask = options.config.tasks[taskName];
1171
+ if (!isRecord(actualTask)) {
1172
+ throw new Error(`${options.label} requires Turbo task ${taskName}`);
1173
+ }
1174
+ for (const [field, expectedValue] of Object.entries(expectedTask)) {
1175
+ const actualValue = actualTask[field];
1176
+ if (Array.isArray(expectedValue)) {
1177
+ if (!Array.isArray(actualValue) ||
1178
+ expectedValue.some((expectedMember) => !actualValue.includes(expectedMember))) {
1179
+ throw new Error(`${options.label} requires Turbo task ${taskName} ${field}`);
1180
+ }
1181
+ }
1182
+ else if (!isDeepStrictEqual(actualValue, expectedValue)) {
1183
+ throw new Error(`${options.label} requires Turbo task ${taskName} ${field}`);
1184
+ }
1185
+ }
1186
+ }
1187
+ }
1188
+ function assertCapabilityPackageTurboInheritanceTruth(options) {
1189
+ if (!Array.isArray(options.config.extends) ||
1190
+ options.config.extends.length !== 1 ||
1191
+ options.config.extends[0] !== "//") {
1192
+ throw new Error(`${options.label} requires exact Turbo extends truth`);
1193
+ }
1194
+ }
1195
+ function effectiveCapabilityTaskDependencies(options) {
1196
+ if (options.localTask === undefined) {
1197
+ if (!isRecord(options.inheritedTask)) {
1198
+ throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1199
+ }
1200
+ return options.inheritedTask.dependsOn;
1201
+ }
1202
+ if (!isRecord(options.localTask)) {
1203
+ throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1204
+ }
1205
+ const extendsValue = options.localTask.extends;
1206
+ if (extendsValue !== undefined && typeof extendsValue !== "boolean") {
1207
+ throw new Error(`${options.label} requires Turbo task ${options.taskName} extends truth`);
1208
+ }
1209
+ if (extendsValue === false || options.localTask.dependsOn !== undefined) {
1210
+ return options.localTask.dependsOn;
1211
+ }
1212
+ if (!isRecord(options.inheritedTask)) {
1213
+ throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1214
+ }
1215
+ return options.inheritedTask.dependsOn;
1216
+ }
1217
+ function assertCapabilityConsumerTurboTruth(options) {
1218
+ const turboByPackagePath = new Map();
1219
+ for (const [qualifiedTaskName, expectedTask] of Object.entries(options.expectedTasks)) {
1220
+ if (expectedTask.dependsOn === undefined)
1221
+ continue;
1222
+ const separator = qualifiedTaskName.lastIndexOf("#");
1223
+ if (separator <= 0)
1224
+ continue;
1225
+ const packageName = qualifiedTaskName.slice(0, separator);
1226
+ const taskName = qualifiedTaskName.slice(separator + 1);
1227
+ const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1228
+ const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
1229
+ readRepositoryJsonRecord({
1230
+ repositoryRoot: options.repositoryRoot,
1231
+ relativePath: `${contribution.definition.path}/turbo.json`,
1232
+ label: `${contribution.definition.name} Turbo Truth`,
1233
+ });
1234
+ turboByPackagePath.set(contribution.definition.path, packageTurbo);
1235
+ if (!isRecord(packageTurbo.tasks)) {
1236
+ throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo tasks truth`);
1237
+ }
1238
+ assertCapabilityPackageTurboInheritanceTruth({
1239
+ config: packageTurbo,
1240
+ label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1241
+ });
1242
+ const localTask = packageTurbo.tasks[taskName];
1243
+ const localDependencies = effectiveCapabilityTaskDependencies({
1244
+ localTask,
1245
+ inheritedTask: expectedTask,
1246
+ label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1247
+ taskName,
1248
+ });
1249
+ if (!Array.isArray(localDependencies) ||
1250
+ expectedTask.dependsOn.some((expectedDependency) => !localDependencies.includes(expectedDependency))) {
1251
+ throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task ${taskName} dependsOn`);
1252
+ }
1253
+ }
1254
+ for (const packageName of options.buildConsumerPackageNames) {
1255
+ const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1256
+ const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
1257
+ readRepositoryJsonRecord({
1258
+ repositoryRoot: options.repositoryRoot,
1259
+ relativePath: `${contribution.definition.path}/turbo.json`,
1260
+ label: `${contribution.definition.name} Turbo Truth`,
1261
+ });
1262
+ turboByPackagePath.set(contribution.definition.path, packageTurbo);
1263
+ if (!isRecord(packageTurbo.tasks)) {
1264
+ throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo tasks truth`);
1265
+ }
1266
+ assertCapabilityPackageTurboInheritanceTruth({
1267
+ config: packageTurbo,
1268
+ label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1269
+ });
1270
+ const localBuild = packageTurbo.tasks.build;
1271
+ const qualifiedBuild = isRecord(options.rootTurbo.tasks)
1272
+ ? options.rootTurbo.tasks[`${packageName}#build`]
1273
+ : undefined;
1274
+ const genericBuild = isRecord(options.rootTurbo.tasks)
1275
+ ? options.rootTurbo.tasks.build
1276
+ : undefined;
1277
+ const dependencies = effectiveCapabilityTaskDependencies({
1278
+ localTask: localBuild,
1279
+ inheritedTask: qualifiedBuild === undefined ? genericBuild : qualifiedBuild,
1280
+ label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1281
+ taskName: "build",
1282
+ });
1283
+ if (!Array.isArray(dependencies) ||
1284
+ !dependencies.some((dependency) => dependency === "^build" ||
1285
+ dependency === `${options.databasePackageName}#build`)) {
1286
+ throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task build dependsOn`);
1287
+ }
1288
+ }
1289
+ }
1290
+ function assertCapabilityTurboTruth(options) {
1291
+ if (options.databasePreparation === undefined &&
1292
+ options.deploymentCheck === undefined &&
1293
+ options.vueHonoJointE2e === undefined) {
1294
+ return;
1295
+ }
1296
+ const rootTurbo = readRepositoryJsonRecord({
1297
+ repositoryRoot: options.repositoryRoot,
1298
+ relativePath: "turbo.json",
1299
+ label: "root Turbo Truth",
1300
+ });
1301
+ assertTurboTaskTruth({
1302
+ config: rootTurbo,
1303
+ expectedTasks: {
1304
+ ...(options.databasePreparation === undefined
1305
+ ? {}
1306
+ : databasePreparationTurboTasks(options.databasePreparation)),
1307
+ ...(options.deploymentCheck === undefined
1308
+ ? {}
1309
+ : deploymentTurboTasks(options.deploymentCheck)),
1310
+ ...(options.vueHonoJointE2e === undefined
1311
+ ? {}
1312
+ : vueHonoJointE2eTurboTasks(options.vueHonoJointE2e)),
1313
+ },
1314
+ label: "Package Addition root Turbo Truth",
1315
+ });
1316
+ if (options.databasePreparation === undefined)
1317
+ return;
1318
+ const database = requireContributionByName(options.packageByName, options.databasePreparation.databasePackageName, "Database Preparation");
1319
+ const databaseTurbo = readRepositoryJsonRecord({
1320
+ repositoryRoot: options.repositoryRoot,
1321
+ relativePath: `${database.definition.path}/turbo.json`,
1322
+ label: `${database.definition.name} Turbo Truth`,
1323
+ });
1324
+ assertTurboTaskTruth({
1325
+ config: databaseTurbo,
1326
+ expectedTasks: { build: { outputs: ["dist/**"] } },
1327
+ label: `Package Addition ${database.definition.name} Turbo Truth`,
1328
+ });
1329
+ assertCapabilityConsumerTurboTruth({
1330
+ repositoryRoot: options.repositoryRoot,
1331
+ rootTurbo,
1332
+ expectedTasks: databasePreparationTurboTasks(options.databasePreparation),
1333
+ buildConsumerPackageNames: [
1334
+ options.databasePreparation.migrationPackageName,
1335
+ ...new Set(Object.values(options.databasePreparation.consumers)),
1336
+ ],
1337
+ databasePackageName: options.databasePreparation.databasePackageName,
1338
+ packageByName: options.packageByName,
1339
+ });
1340
+ }
1341
+ function unwrapTypeScriptExpression(expression) {
1342
+ return ts.isParenthesizedExpression(expression) ||
1343
+ ts.isAsExpression(expression) ||
1344
+ ts.isSatisfiesExpression(expression) ||
1345
+ ts.isTypeAssertionExpression(expression)
1346
+ ? unwrapTypeScriptExpression(expression.expression)
1347
+ : expression;
1348
+ }
1349
+ function typeScriptPropertyName(name) {
1350
+ return ts.isIdentifier(name) || ts.isStringLiteralLike(name)
1351
+ ? name.text
1352
+ : undefined;
1353
+ }
1354
+ function finalObjectLiteralPropertyValue(expression, propertyName) {
1355
+ let hasUnverifiableOverride = false;
1356
+ for (const property of [...expression.properties].reverse()) {
1357
+ if (ts.isSpreadAssignment(property)) {
1358
+ hasUnverifiableOverride = true;
1359
+ continue;
1360
+ }
1361
+ const name = typeScriptPropertyName(property.name);
1362
+ if (name === propertyName) {
1363
+ if (!ts.isPropertyAssignment(property) || hasUnverifiableOverride) {
1364
+ return undefined;
1365
+ }
1366
+ return property.initializer;
1367
+ }
1368
+ if (name === undefined) {
1369
+ hasUnverifiableOverride = true;
1370
+ }
1371
+ }
1372
+ return undefined;
1373
+ }
1374
+ function assertDatabaseViteRuntimeTruth(options) {
1375
+ if (options.deploymentCheck === undefined)
1376
+ return;
1377
+ const application = requireContributionByName(options.packageByName, options.deploymentCheck.applicationPackageName, "Deployment Check");
1378
+ const configPath = `${application.definition.path}/vite.config.ts`;
1379
+ let sourceText;
1380
+ try {
1381
+ sourceText = readFileSync(path.join(options.repositoryRoot, configPath), "utf8");
1382
+ }
1383
+ catch (error) {
1384
+ throw new Error(`Package Addition requires Vite runtime truth in ${configPath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
1385
+ }
1386
+ const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1387
+ if ((sourceFile.parseDiagnostics ?? []).length > 0) {
1388
+ throw new Error(`Package Addition requires valid Vite runtime truth in ${configPath}`);
1389
+ }
1390
+ const exportAssignment = sourceFile.statements.find((statement) => ts.isExportAssignment(statement) && !statement.isExportEquals);
1391
+ const exported = exportAssignment === undefined
1392
+ ? undefined
1393
+ : unwrapTypeScriptExpression(exportAssignment.expression);
1394
+ const configCall = exported !== undefined &&
1395
+ ts.isCallExpression(exported) &&
1396
+ ts.isIdentifier(exported.expression) &&
1397
+ exported.expression.text === "defineConfig"
1398
+ ? exported
1399
+ : undefined;
1400
+ const configArgument = configCall?.arguments[0];
1401
+ const config = configArgument === undefined
1402
+ ? undefined
1403
+ : unwrapTypeScriptExpression(configArgument);
1404
+ const ssrValue = config !== undefined && ts.isObjectLiteralExpression(config)
1405
+ ? finalObjectLiteralPropertyValue(config, "ssr")
1406
+ : undefined;
1407
+ const ssr = ssrValue === undefined ? undefined : unwrapTypeScriptExpression(ssrValue);
1408
+ const externalValue = ssr !== undefined && ts.isObjectLiteralExpression(ssr)
1409
+ ? finalObjectLiteralPropertyValue(ssr, "external")
1410
+ : undefined;
1411
+ const external = externalValue === undefined
1412
+ ? undefined
1413
+ : unwrapTypeScriptExpression(externalValue);
1414
+ const expectedPackageName = options.deploymentCheck.databasePackageName;
1415
+ const externalPackageNames = external !== undefined && ts.isArrayLiteralExpression(external)
1416
+ ? external.elements.flatMap((element) => ts.isStringLiteralLike(element) ? [element.text] : [])
1417
+ : external !== undefined && ts.isStringLiteralLike(external)
1418
+ ? [external.text]
1419
+ : [];
1420
+ if (!externalPackageNames.includes(expectedPackageName)) {
1421
+ throw new Error(`Package Addition requires ${configPath} to externalize ${expectedPackageName} through Vite SSR`);
1422
+ }
1423
+ }
1424
+ function assertVueHonoJointE2ePlaywrightTruth(options) {
1425
+ if (options.e2e === undefined)
1426
+ return;
1427
+ const configPath = "playwright.config.ts";
1428
+ let sourceText;
1429
+ try {
1430
+ sourceText = readFileSync(path.join(options.repositoryRoot, configPath), "utf8");
1431
+ }
1432
+ catch (error) {
1433
+ throw new Error(`Package Addition requires Vue-Hono joint E2E root Playwright truth in ${configPath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
1434
+ }
1435
+ const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1436
+ if ((sourceFile.parseDiagnostics ?? []).length > 0) {
1437
+ throw new Error(`Package Addition requires valid Vue-Hono joint E2E root Playwright truth in ${configPath}`);
1438
+ }
1439
+ const exportAssignment = sourceFile.statements.find((statement) => ts.isExportAssignment(statement) && !statement.isExportEquals);
1440
+ const exported = exportAssignment === undefined
1441
+ ? undefined
1442
+ : unwrapTypeScriptExpression(exportAssignment.expression);
1443
+ const configCall = exported !== undefined &&
1444
+ ts.isCallExpression(exported) &&
1445
+ ts.isIdentifier(exported.expression) &&
1446
+ exported.expression.text === "defineConfig"
1447
+ ? exported
1448
+ : undefined;
1449
+ const configArgument = configCall?.arguments[0];
1450
+ const config = configArgument === undefined
1451
+ ? undefined
1452
+ : unwrapTypeScriptExpression(configArgument);
1453
+ const webServerValue = config !== undefined && ts.isObjectLiteralExpression(config)
1454
+ ? finalObjectLiteralPropertyValue(config, "webServer")
1455
+ : undefined;
1456
+ const webServers = webServerValue === undefined
1457
+ ? undefined
1458
+ : unwrapTypeScriptExpression(webServerValue);
1459
+ if (webServers === undefined ||
1460
+ !ts.isArrayLiteralExpression(webServers) ||
1461
+ webServers.elements.length !== 2) {
1462
+ throw new Error(`Package Addition requires two static Vue-Hono joint E2E web servers in ${configPath}`);
1463
+ }
1464
+ const expectedServers = [
1465
+ {
1466
+ command: `pnpm --filter ${options.e2e.apiPackageName} --fail-if-no-match run start`,
1467
+ portEnvironment: "PORT",
1468
+ portVariable: "apiPort",
1469
+ portInput: "PLAYWRIGHT_API_PORT",
1470
+ stdout: "/Hono API listening on (?<VITE_API_BASE_URL>http:\\/\\/localhost:\\d+)/",
1471
+ },
1472
+ {
1473
+ command: `pnpm --filter ${options.e2e.webPackageName} --fail-if-no-match run preview --host 127.0.0.1 --strictPort`,
1474
+ portEnvironment: "PLAYWRIGHT_WEB_PORT",
1475
+ portVariable: "webPort",
1476
+ portInput: "PLAYWRIGHT_WEB_PORT",
1477
+ stdout: "/Local:\\s+(?<PLAYWRIGHT_WEB_URL>http:\\/\\/127\\.0\\.0\\.1:\\d+)/",
1478
+ },
1479
+ ];
1480
+ for (const [index, expected] of expectedServers.entries()) {
1481
+ const server = unwrapTypeScriptExpression(webServers.elements[index]);
1482
+ if (!ts.isObjectLiteralExpression(server)) {
1483
+ throw new Error(`Package Addition requires static Vue-Hono joint E2E web server ${index + 1} in ${configPath}`);
1484
+ }
1485
+ const command = finalObjectLiteralPropertyValue(server, "command");
1486
+ if (command === undefined ||
1487
+ !ts.isStringLiteralLike(command) ||
1488
+ command.text !== expected.command) {
1489
+ throw new Error(`Package Addition requires exact Vue-Hono joint E2E web server ${index + 1} command in ${configPath}`);
1490
+ }
1491
+ const environmentValue = finalObjectLiteralPropertyValue(server, "env");
1492
+ const environment = environmentValue === undefined
1493
+ ? undefined
1494
+ : unwrapTypeScriptExpression(environmentValue);
1495
+ const environmentProperty = environment !== undefined && ts.isObjectLiteralExpression(environment)
1496
+ ? environment.properties[0]
1497
+ : undefined;
1498
+ const portValue = environmentProperty !== undefined &&
1499
+ ts.isPropertyAssignment(environmentProperty) &&
1500
+ !ts.isComputedPropertyName(environmentProperty.name) &&
1501
+ (ts.isIdentifier(environmentProperty.name) ||
1502
+ ts.isStringLiteral(environmentProperty.name)) &&
1503
+ environmentProperty.name.text === expected.portEnvironment
1504
+ ? unwrapTypeScriptExpression(environmentProperty.initializer)
1505
+ : undefined;
1506
+ if (environment === undefined ||
1507
+ !ts.isObjectLiteralExpression(environment) ||
1508
+ environment.properties.length !== 1 ||
1509
+ portValue === undefined ||
1510
+ !ts.isIdentifier(portValue) ||
1511
+ portValue.text !== expected.portVariable) {
1512
+ throw new Error(`Package Addition requires Vue-Hono joint E2E web server ${index + 1} ${expected.portEnvironment} environment in ${configPath}`);
1513
+ }
1514
+ const waitValue = finalObjectLiteralPropertyValue(server, "wait");
1515
+ const wait = waitValue === undefined
1516
+ ? undefined
1517
+ : unwrapTypeScriptExpression(waitValue);
1518
+ const stdout = wait !== undefined && ts.isObjectLiteralExpression(wait)
1519
+ ? finalObjectLiteralPropertyValue(wait, "stdout")
1520
+ : undefined;
1521
+ if (stdout === undefined ||
1522
+ !ts.isRegularExpressionLiteral(stdout) ||
1523
+ stdout.text !== expected.stdout) {
1524
+ throw new Error(`Package Addition requires static Vue-Hono joint E2E web server ${index + 1} stdout capture in ${configPath}`);
1525
+ }
1526
+ const reuseExistingServer = finalObjectLiteralPropertyValue(server, "reuseExistingServer");
1527
+ if (reuseExistingServer?.kind !== ts.SyntaxKind.FalseKeyword) {
1528
+ throw new Error(`Package Addition requires Vue-Hono joint E2E web server ${index + 1} native cleanup in ${configPath}`);
1529
+ }
1530
+ }
1531
+ const expectedPortInputs = expectedServers.map(({ portVariable, portInput }) => ({ portVariable, portInput }));
1532
+ for (const expected of expectedPortInputs) {
1533
+ const declarations = sourceFile.statements
1534
+ .filter(ts.isVariableStatement)
1535
+ .flatMap((statement) => statement.declarationList.declarations.map((declaration) => ({
1536
+ declaration,
1537
+ declarationList: statement.declarationList,
1538
+ })))
1539
+ .filter(({ declaration }) => ts.isIdentifier(declaration.name) &&
1540
+ declaration.name.text === expected.portVariable);
1541
+ const declaration = declarations[0];
1542
+ if (declarations.length !== 1 ||
1543
+ declaration === undefined ||
1544
+ (declaration.declarationList.flags & ts.NodeFlags.Const) === 0) {
1545
+ throw new Error(`Package Addition requires one top-level const Vue-Hono joint E2E ${expected.portVariable} in ${configPath}`);
1546
+ }
1547
+ const initializer = declaration.declaration.initializer;
1548
+ const left = initializer !== undefined &&
1549
+ ts.isBinaryExpression(initializer) &&
1550
+ initializer.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken
1551
+ ? initializer.left
1552
+ : undefined;
1553
+ const right = initializer !== undefined &&
1554
+ ts.isBinaryExpression(initializer) &&
1555
+ initializer.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken
1556
+ ? initializer.right
1557
+ : undefined;
1558
+ const environmentInput = left !== undefined &&
1559
+ ts.isPropertyAccessExpression(left) &&
1560
+ ts.isPropertyAccessExpression(left.expression) &&
1561
+ ts.isIdentifier(left.expression.expression) &&
1562
+ left.expression.expression.text === "process" &&
1563
+ left.expression.name.text === "env"
1564
+ ? left.name.text
1565
+ : undefined;
1566
+ if (environmentInput !== expected.portInput ||
1567
+ right === undefined ||
1568
+ !ts.isStringLiteralLike(right) ||
1569
+ right.text !== "0") {
1570
+ throw new Error(`Package Addition requires Vue-Hono joint E2E ${expected.portVariable} to read ${expected.portInput} or static port 0 in ${configPath}`);
1571
+ }
1572
+ }
1573
+ }
1574
+ function assertCapabilityRepositoryTruth(options) {
1575
+ assertDatabasePreparationManifestTruth({
1576
+ preparation: options.databasePreparation,
1577
+ packageByName: options.packageByName,
1578
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1579
+ });
1580
+ assertDatabaseArtifactManifestTruth({
1581
+ preparation: options.databasePreparation,
1582
+ packageByName: options.packageByName,
1583
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1584
+ });
1585
+ assertDatabaseProjectLinkManifestTruth({
1586
+ blueprint: options.blueprint,
1587
+ contributions: options.contributions,
1588
+ preparation: options.databasePreparation,
1589
+ packageByName: options.packageByName,
1590
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1591
+ });
1592
+ assertDeploymentBuildManifestTruth({
1593
+ deploymentCheck: options.deploymentCheck,
1594
+ packageByName: options.packageByName,
1595
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1596
+ });
1597
+ assertVueHonoJointE2eManifestTruth({
1598
+ e2e: options.vueHonoJointE2e,
1599
+ packageByName: options.packageByName,
1600
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1601
+ });
1602
+ assertVueHonoJointE2ePlaywrightTruth({
1603
+ repositoryRoot: options.repositoryRoot,
1604
+ e2e: options.vueHonoJointE2e,
1605
+ });
1606
+ assertRootCapabilityManifestTruth(options);
1607
+ assertCapabilityTurboTruth(options);
1608
+ assertDatabaseViteRuntimeTruth(options);
1609
+ }
1610
+ function foundationCheckEnvironmentNeeds(contributions, deploymentCheck, vueHonoJointE2e) {
1611
+ return [
1612
+ ...contributions.flatMap((contribution) => contribution.environmentNeeds),
1613
+ ...(vueHonoJointE2e === undefined
1614
+ ? []
1615
+ : [
1616
+ playwrightBrowserAssetsEnvironmentNeed({
1617
+ browser: "chromium",
1618
+ owner: { kind: "workspace-orchestration", path: "." },
1619
+ }),
1620
+ ]),
1621
+ ...(deploymentCheck === undefined
1622
+ ? []
1623
+ : [
1624
+ shellCheckEnvironmentNeed({
1625
+ kind: "workspace-orchestration",
1626
+ path: ".",
1627
+ }),
1628
+ ]),
1629
+ ];
1630
+ }
1631
+ function deploymentCheckDevelopmentContainerToolLayers(deploymentCheck) {
1632
+ if (deploymentCheck === undefined)
1633
+ return [];
1634
+ return [
1635
+ {
1636
+ identity: "shellcheck",
1637
+ dockerfile: deploymentCheck.sources.shellCheckDockerfile,
1638
+ requires: ["node-pnpm"],
1639
+ probes: [
1640
+ {
1641
+ identity: "shellcheck",
1642
+ command: "shellcheck",
1643
+ args: ["--version"],
1644
+ },
1645
+ ],
1646
+ },
1647
+ {
1648
+ identity: "docker-client",
1649
+ dockerfile: deploymentCheck.sources.dockerClientToolLayer,
1650
+ requires: ["node-pnpm"],
1651
+ mounts: [
1652
+ {
1653
+ identity: "docker-socket",
1654
+ type: "bind",
1655
+ source: "/var/run/docker.sock",
1656
+ target: "/var/run/docker.sock",
1657
+ },
1658
+ ],
1659
+ probes: [
1660
+ {
1661
+ identity: "docker-cli",
1662
+ command: "docker",
1663
+ args: ["--version"],
1664
+ failureMessage: "Docker CLI is unavailable; rebuild the Development Container to install the Docker Client Tool Layer.",
1665
+ },
1666
+ {
1667
+ identity: "docker-daemon",
1668
+ command: "docker",
1669
+ args: ["version"],
1670
+ failureMessage: "Docker daemon is inaccessible through /var/run/docker.sock; verify the host daemon is running and the standard socket is accessible.",
1671
+ },
1672
+ ],
1673
+ },
1674
+ ];
1675
+ }
1676
+ function normalizeRustToolchain(contributions) {
1677
+ const declarations = contributions.flatMap((contribution) => {
1678
+ const rust = contribution.foundation.toolchains.rust;
1679
+ return rust === undefined
1680
+ ? []
1681
+ : [
1682
+ {
1683
+ ...rust,
1684
+ components: [...new Set(rust.components)].toSorted(),
1685
+ },
1686
+ ];
1687
+ });
1688
+ const fingerprints = declarations.map((rust) => JSON.stringify({
1689
+ toolchain: rust.toolchain,
1690
+ components: rust.components,
1691
+ configurationSource: resolveTemplateSource(rust.configurationSource.source, rust.configurationSource.from),
1692
+ }));
1693
+ if (new Set(fingerprints).size > 1) {
1694
+ throw new Error("Foundation requires compatible Rust toolchain facts");
1695
+ }
1696
+ return declarations.at(0);
1697
+ }
1698
+ function composeDependencyMaintenancePolicy(contributions, deploymentCheck) {
1699
+ const ecosystems = [
1700
+ ...new Set([
1701
+ ...contributions.flatMap((contribution) => contribution.foundation.dependencyMaintenance.ecosystems),
1702
+ ...(deploymentCheck === undefined ? [] : ["docker"]),
1703
+ ]),
1704
+ ];
1705
+ const directories = {};
1706
+ const extraDirectories = {};
1707
+ for (const ecosystem of ecosystems) {
1708
+ const candidates = [
1709
+ ...new Set([
1710
+ ...contributions.flatMap((contribution) => {
1711
+ const policy = contribution.foundation.dependencyMaintenance;
1712
+ const primary = policy.directories?.[ecosystem];
1713
+ return [
1714
+ ...(primary === undefined ? [] : [primary]),
1715
+ ...(policy.extraDirectories?.[ecosystem] ?? []),
1716
+ ];
1717
+ }),
1718
+ ...(ecosystem === "docker" && deploymentCheck !== undefined
1719
+ ? ["/"]
1720
+ : []),
1721
+ ]),
1722
+ ];
1723
+ const [primary, ...extra] = candidates;
1724
+ if (primary !== undefined)
1725
+ directories[ecosystem] = primary;
1726
+ if (extra.length > 0)
1727
+ extraDirectories[ecosystem] = extra;
1728
+ }
1729
+ return {
1730
+ ecosystems,
1731
+ ...(Object.keys(directories).length === 0 ? {} : { directories }),
1732
+ ...(Object.keys(extraDirectories).length === 0 ? {} : { extraDirectories }),
1733
+ interval: "weekly",
1734
+ };
1735
+ }
1736
+ function localTypescriptConfigurationSpecifier(options) {
1737
+ const relativePackagePath = path.posix.relative(options.consumerPackagePath, options.configurationPackagePath);
1738
+ if (relativePackagePath.length === 0) {
1739
+ throw new Error("TypeScript Configuration Package must have a distinct Package Path");
1740
+ }
1741
+ return `link:${relativePackagePath}`;
1742
+ }
1743
+ function publicCliCandidate(contributions) {
1744
+ const candidates = contributions.filter((contribution) => contribution.foundation.npmPublication?.kind === "public-cli-candidate");
1745
+ if (candidates.length > 1) {
1746
+ throw new Error(`Generated Repository Plan supports at most one public CLI candidate; found ${candidates.map((candidate) => `${candidate.definition.name} at ${candidate.definition.path}`).join(", ")}`);
1747
+ }
1748
+ const candidate = candidates[0];
1749
+ if (candidate !== undefined && candidate.definition.role !== "cli-tool") {
1750
+ throw new Error(`Public CLI candidate ${candidate.definition.name} must use the cli-tool Package role`);
1751
+ }
1752
+ return candidate;
1753
+ }
1754
+ function renderPublicationRootCheckCommand(candidatePackagePath) {
1755
+ return [
1756
+ "pnpm run boundaries",
1757
+ renderTurboRunCommand(["format:check", "lint", "typecheck", "test"], [], {
1758
+ continueAfterFailure: true,
1759
+ taskPrefix: true,
1760
+ }),
1761
+ renderTurboRunCommand(["build", "test:e2e"], [`--filter=!./${candidatePackagePath}`], { continueAfterFailure: true, taskPrefix: true }),
1762
+ "pnpm run publication:artifact",
1763
+ ].join(" && ");
1764
+ }
1765
+ /**
1766
+ * 票 26 清单单源:把 plan 声明的镜像槽位集合投影成生成检查器携带的清单文本。
1767
+ * 转义 `$` 是必要的:清单文本注入模板字面量,未转义的 `$` 会被当成 TypeScript 插值。
1768
+ */
1769
+ function renderToolchainMirrorSlotManifest(reconciliation) {
1770
+ const slots = reconciliation.flatMap((policy) => policy.driver === "canonical"
1771
+ ? []
1772
+ : (policy.mirrorSlots ?? []).map((slot) => ({
1773
+ id: slot.id,
1774
+ path: policy.path,
1775
+ location: slot.location,
1776
+ })));
1777
+ return JSON.stringify(slots, null, 2).replaceAll("$", String.raw `\$`);
1778
+ }
1779
+ function foundationPlan(options) {
1780
+ assertProjectBlueprint(options.blueprint);
1781
+ const configContribution = options.foundationContribution;
1782
+ const configDefinition = configContribution.definition;
1783
+ if (!options.blueprint.packages.some((definition) => packageDefinitionsEqual(definition, configDefinition))) {
1784
+ throw new Error("Project Blueprint must contain the Foundation TypeScript configuration Package Definition");
1785
+ }
1786
+ const initialProjectLinkPlan = planExplicitProjectLinks({
1787
+ blueprint: options.blueprint,
1788
+ contributions: options.contributions,
1789
+ ...(options.manifestTruthByPackagePath === undefined
658
1790
  ? {}
659
1791
  : {
660
1792
  manifestTruthByPackagePath: options.manifestTruthByPackagePath,
661
1793
  }),
662
1794
  });
663
- const injectedProviderNames = new Set([...initialProjectLinkPlan.manifestPatchesByPackagePath.values()].flatMap((patch) => Object.entries(patch.dependenciesMeta)
1795
+ const injectedProviderNames = new Set([...initialProjectLinkPlan.manifestPatchesByPackagePath.values()].flatMap((patch) => Object.entries(patch.dependenciesMeta ?? {})
664
1796
  .filter(([, metadata]) => metadata.injected)
665
1797
  .map(([name]) => name)));
666
- const configPackageName = typescriptConfigPackageName(options.context);
1798
+ const configPackageName = options.context.foundationPackages.typescriptConfiguration.name;
1799
+ if (configDefinition.name !== configPackageName) {
1800
+ throw new Error(`Generation Context TypeScript Configuration Package ${configPackageName} conflicts with Blueprint Package Definition ${configDefinition.name}`);
1801
+ }
1802
+ const publicationCandidate = publicCliCandidate(options.contributions);
667
1803
  const packageContributions = options.contributions.map((contribution) => {
668
- const ownsTypeScriptConfig = contribution.operations.some((operation) => "to" in operation &&
669
- operation.to === `${contribution.definition.path}/tsconfig.json`);
670
- if (!ownsTypeScriptConfig)
1804
+ if (contribution.foundation.typescriptConfigurationPackage === undefined) {
671
1805
  return contribution;
1806
+ }
672
1807
  const dependencyField = injectedProviderNames.has(contribution.definition.name)
673
1808
  ? "dependencies"
674
1809
  : "devDependencies";
1810
+ const dependencySpecifier = dependencyField === "devDependencies" &&
1811
+ (contribution.manifest.private !== true ||
1812
+ publicationCandidate?.definition.path === contribution.definition.path)
1813
+ ? localTypescriptConfigurationSpecifier({
1814
+ consumerPackagePath: contribution.definition.path,
1815
+ configurationPackagePath: configDefinition.path,
1816
+ })
1817
+ : "workspace:*";
675
1818
  const existingDependencies = contribution.manifest[dependencyField];
676
1819
  return {
677
1820
  ...contribution,
@@ -679,49 +1822,138 @@ function foundationPlan(options) {
679
1822
  ...contribution.manifest,
680
1823
  [dependencyField]: {
681
1824
  ...(isRecord(existingDependencies) ? existingDependencies : {}),
682
- [configPackageName]: "workspace:*",
1825
+ [configPackageName]: dependencySpecifier,
683
1826
  },
684
1827
  },
685
1828
  };
686
1829
  });
687
- const configContribution = typescriptConfigContribution(options.context);
1830
+ const requiresPackingHook = packageContributions.some((contribution) => {
1831
+ const developmentDependencies = contribution.manifest.devDependencies;
1832
+ return (isRecord(developmentDependencies) &&
1833
+ typeof developmentDependencies[configPackageName] === "string" &&
1834
+ developmentDependencies[configPackageName].startsWith("link:"));
1835
+ });
688
1836
  const contributions = [configContribution, ...packageContributions];
689
- const generationRecord = options.generationRecord ?? {
690
- schemaVersion: 1,
1837
+ assertPackageContributionCommandNames(contributions.map((contribution) => {
1838
+ const manifest = options.manifestTruthByPackagePath?.get(contribution.definition.path);
1839
+ return manifest === undefined
1840
+ ? contribution
1841
+ : { ...contribution, manifest };
1842
+ }));
1843
+ const candidateRecord = options.generationRecord ?? {
1844
+ schemaVersion: 2,
1845
+ repositoryName: options.context.repositoryName,
1846
+ defaultPackageScope: options.context.defaultPackageScope,
691
1847
  preset: options.definition.metadata.name,
692
1848
  templateVersion: "0.0.0",
693
- toolchain: options.context.toolchain,
1849
+ // 显式只投影 v2 的两个历史字段,上下文里的精确 Node 事实不得进入持久记录。
1850
+ toolchain: {
1851
+ nodeLtsMajor: options.context.toolchain.nodeLtsMajor,
1852
+ packageManagerPin: options.context.toolchain.packageManagerPin,
1853
+ },
694
1854
  packages: [
695
- ...options.contributions.map((contribution) => ({
696
- path: contribution.definition.path,
697
- definitionName: options.definition.metadata.name,
698
- planningContribution: options.mode === "initialization"
1855
+ ...options.contributions.map((contribution) => {
1856
+ const planningContribution = options.mode === "initialization"
699
1857
  ? "planInitialization"
700
- : "planPackageAddition",
701
- })),
1858
+ : "planPackageAddition";
1859
+ return {
1860
+ packageDefinitionId: requirePersistedPackageDefinition(options.blueprint, contribution.definition).packageDefinitionId,
1861
+ path: contribution.definition.path,
1862
+ definitionName: options.definition.metadata.name,
1863
+ planningContribution,
1864
+ contributionIdentity: requireReplayAdapter({
1865
+ owner: options.definition.metadata.name,
1866
+ adapters: options.definition.packageContributionReplayAdapters,
1867
+ identity: contribution.planningIdentity,
1868
+ }).identity,
1869
+ };
1870
+ }),
702
1871
  {
1872
+ packageDefinitionId: requirePersistedPackageDefinition(options.blueprint, configDefinition).packageDefinitionId,
703
1873
  path: configDefinition.path,
704
1874
  definitionName: "foundation",
705
1875
  planningContribution: "foundationPlan",
1876
+ contributionIdentity: typescriptConfigReplayAdapter.identity,
706
1877
  },
707
1878
  ],
708
1879
  };
709
- const environmentNeeds = uniqueEnvironmentNeeds(contributions.flatMap((item) => item.environmentNeeds));
710
- const deploymentEnvironmentNeeds = uniqueEnvironmentNeeds([
711
- ...(options.existingDeploymentEnvironmentNeeds ?? []),
712
- ...contributions.flatMap((item) => item.deploymentEnvironmentNeeds ?? []),
713
- ]);
714
- const persistedEnvironmentNeeds = {
715
- schemaVersion: 1,
716
- check: environmentNeeds.map(checkEnvironmentNeedFact),
717
- deployment: deploymentEnvironmentNeeds.map(deploymentEnvironmentNeedFact),
718
- };
719
- const hasDeploymentTask = contributions.some((contribution) => {
720
- const scripts = contribution.manifest.scripts;
721
- return (typeof scripts === "object" &&
722
- scripts !== null &&
723
- typeof scripts.deployment === "string");
1880
+ const generationRecord = parseGenerationRecord(candidateRecord);
1881
+ const deploymentCheck = normalizeDeploymentCheck(contributions);
1882
+ const vueHonoJointE2e = normalizeVueHonoJointE2e(contributions);
1883
+ const databasePreparation = normalizeDatabasePreparation(contributions);
1884
+ const rustToolchain = normalizeRustToolchain(contributions);
1885
+ const packageByName = new Map(contributions.map((contribution) => [
1886
+ contribution.definition.name,
1887
+ contribution,
1888
+ ]));
1889
+ const deploymentPackages = deploymentCheck === undefined
1890
+ ? undefined
1891
+ : {
1892
+ application: requireContributionByName(packageByName, deploymentCheck.applicationPackageName, "Deployment Check"),
1893
+ database: requireContributionByName(packageByName, deploymentCheck.databasePackageName, "Deployment Check"),
1894
+ migration: requireContributionByName(packageByName, deploymentCheck.migrationPackageName, "Deployment Check"),
1895
+ };
1896
+ if (databasePreparation !== undefined) {
1897
+ const migration = packageByName.get(databasePreparation.migrationPackageName);
1898
+ if (migration === undefined) {
1899
+ throw new Error("Database Preparation references an unknown migration Package");
1900
+ }
1901
+ for (const packageName of Object.values(databasePreparation.consumers)) {
1902
+ if (!packageByName.has(packageName)) {
1903
+ throw new Error("Database Preparation references an unknown consumer Package");
1904
+ }
1905
+ }
1906
+ if (databasePreparation.consumers["database-test"] !==
1907
+ databasePreparation.databasePackageName) {
1908
+ throw new Error("Database Preparation database-test consumer must be its owner");
1909
+ }
1910
+ }
1911
+ assertDatabasePreparationManifestTruth({
1912
+ preparation: databasePreparation,
1913
+ packageByName,
1914
+ manifestTruthByPackagePath: options.manifestTruthByPackagePath,
1915
+ });
1916
+ if (deploymentCheck !== undefined) {
1917
+ const deploymentPackageNames = [
1918
+ deploymentCheck.applicationPackageName,
1919
+ deploymentCheck.databasePackageName,
1920
+ deploymentCheck.migrationPackageName,
1921
+ ];
1922
+ if (new Set(deploymentPackageNames).size !== 3) {
1923
+ throw new Error("Deployment Check requires three distinct Packages");
1924
+ }
1925
+ if (deploymentPackages?.application.definition.path !==
1926
+ deploymentCheck.declaringPackagePath) {
1927
+ throw new Error("Deployment Check must be declared by its application Package");
1928
+ }
1929
+ if (databasePreparation !== undefined &&
1930
+ (databasePreparation.databasePackageName !==
1931
+ deploymentCheck.databasePackageName ||
1932
+ databasePreparation.migrationPackageName !==
1933
+ deploymentCheck.migrationPackageName)) {
1934
+ throw new Error("Deployment Check must use the Database Preparation Packages");
1935
+ }
1936
+ for (const packageName of deploymentPackageNames) {
1937
+ const contribution = requireContributionByName(packageByName, packageName, "Deployment Check");
1938
+ const manifest = options.manifestTruthByPackagePath?.get(contribution.definition.path) ??
1939
+ contribution.manifest;
1940
+ const expectedBuild = isRecord(contribution.manifest.scripts)
1941
+ ? contribution.manifest.scripts.build
1942
+ : undefined;
1943
+ const actualBuild = isRecord(manifest.scripts)
1944
+ ? manifest.scripts.build
1945
+ : undefined;
1946
+ if (typeof expectedBuild !== "string" || actualBuild !== expectedBuild) {
1947
+ throw new Error(`Deployment Check requires exact ${packageName} manifest script build`);
1948
+ }
1949
+ }
1950
+ }
1951
+ const persistedEnvironmentNeeds = normalizeEnvironmentNeeds({
1952
+ check: foundationCheckEnvironmentNeeds(contributions, deploymentCheck, vueHonoJointE2e),
1953
+ deployment: deploymentCheck?.environmentNeeds ?? [],
724
1954
  });
1955
+ const environmentNeeds = persistedEnvironmentNeeds.check;
1956
+ const deploymentEnvironmentNeeds = persistedEnvironmentNeeds.deployment;
725
1957
  const contributionPackagePaths = contributions.map((contribution) => contribution.definition.path);
726
1958
  if (new Set(contributionPackagePaths).size !== contributionPackagePaths.length)
727
1959
  throw new Error("Package Contributions must have unique Package Paths");
@@ -736,13 +1968,26 @@ function foundationPlan(options) {
736
1968
  const ciDiagnosticArtifactDeclarations = contributions.flatMap((contribution) => contribution.ciDiagnosticArtifacts ?? []);
737
1969
  const ciDiagnosticArtifacts = composeCiDiagnosticArtifacts({
738
1970
  packagePaths: blueprintPackagePaths,
739
- declarations: ciDiagnosticArtifactDeclarations,
1971
+ declarations: [
1972
+ ...ciDiagnosticArtifactDeclarations,
1973
+ ...(vueHonoJointE2e === undefined
1974
+ ? []
1975
+ : [
1976
+ {
1977
+ kind: "playwright",
1978
+ owner: { kind: "workspace-orchestration", path: "." },
1979
+ },
1980
+ ]),
1981
+ ],
740
1982
  });
741
- assertCompatibleRustToolchainFacts(contributions);
742
1983
  const contributedToolLayers = contributions.flatMap((contribution) => contribution.foundation.developmentContainerToolLayers ?? []);
743
1984
  const developmentContainer = contributedDevcontainerComposition({
744
1985
  context: options.context,
745
- layers: contributedToolLayers,
1986
+ rootNodeDeclaration: options.rootNodeDeclaration,
1987
+ layers: [
1988
+ ...contributedToolLayers,
1989
+ ...deploymentCheckDevelopmentContainerToolLayers(deploymentCheck),
1990
+ ],
746
1991
  });
747
1992
  const workspacePackageGlobs = [
748
1993
  "apps/*",
@@ -757,34 +2002,79 @@ function foundationPlan(options) {
757
2002
  ]),
758
2003
  ];
759
2004
  const editorCustomization = editorCustomizationForCapabilities(contributions.flatMap((contribution) => contribution.foundation.editorCapabilities), loadEditorCustomizationDeclarations(resolveTemplateSource(templateSources.editorCustomization, "capabilities.json")));
760
- const dependencyMaintenancePolicy = composeDependencyMaintenancePolicy(contributions);
2005
+ const dependencyMaintenancePolicy = composeDependencyMaintenancePolicy(contributions, deploymentCheck);
2006
+ const rootOwnedE2e = vueHonoJointE2e !== undefined;
2007
+ const rootAutomationPaths = rootOwnedE2e ? "scripts test" : "scripts";
761
2008
  const rootManifest = {
762
- name: options.context.projectName,
763
- version: "0.0.0",
2009
+ name: options.context.repositoryName,
764
2010
  private: true,
765
2011
  type: "module",
2012
+ ...(publicationCandidate === undefined
2013
+ ? {}
2014
+ : {
2015
+ imports: {
2016
+ "#npm-publication/*": "./scripts/npm-publication/*.ts",
2017
+ },
2018
+ }),
766
2019
  scripts: {
767
- check: renderRootCheckCommand(),
768
- boundaries: "node --conditions=source scripts/check-boundaries.ts",
769
- ...(hasDeploymentTask
770
- ? { "check:deployment": renderDeploymentCheckCommand() }
771
- : {}),
2020
+ check: publicationCandidate === undefined
2021
+ ? renderRootCheckCommand()
2022
+ : renderPublicationRootCheckCommand(publicationCandidate.definition.path),
2023
+ // Cargo 会在首次代理调用时按根 rust-toolchain.toml 安装版本与组件;先经唯一根任务完成解析,再并行运行各 Rust 包的 Cargo 检查。
2024
+ ...(rustToolchain === undefined
2025
+ ? {}
2026
+ : { "toolchain:prepare": "cargo --version" }),
2027
+ boundaries: "turbo boundaries --no-color && node --conditions=source scripts/check-toolchain-versions.ts",
2028
+ ...(databasePreparation === undefined
2029
+ ? {}
2030
+ : databasePreparationCommands(databasePreparation)),
2031
+ ...(publicationCandidate === undefined
2032
+ ? {}
2033
+ : {
2034
+ "publication:readiness": "node --conditions=source scripts/npm-publication/check-readiness.ts",
2035
+ "publication:artifact": "node --conditions=source scripts/npm-publication/check-artifact.ts",
2036
+ }),
2037
+ ...(deploymentCheck === undefined
2038
+ ? {}
2039
+ : {
2040
+ deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
2041
+ "check:deployment": renderDeploymentCheckCommand(),
2042
+ }),
2043
+ ...(rootOwnedE2e ? { "test:e2e": "playwright test" } : {}),
772
2044
  fix: renderFixCommand(),
773
- "format:check": "node --conditions=source scripts/run-root-owned-task.ts format:check",
774
- "format:write": "node --conditions=source scripts/run-root-owned-task.ts format:write",
775
- lint: "node --conditions=source scripts/run-root-owned-task.ts lint",
776
- "lint:fix": "node --conditions=source scripts/run-root-owned-task.ts lint:fix",
2045
+ "format:check": `oxfmt --list-different --no-error-on-unmatched-pattern package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json tsconfig.json tsconfig.config.json *.config.ts .pnpmfile.mjs .gitignore .dockerignore Dockerfile TODO.md rust-toolchain.toml .vscode .github .devcontainer ${rootAutomationPaths}`,
2046
+ "format:write": `oxfmt --write --no-error-on-unmatched-pattern package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json tsconfig.json tsconfig.config.json *.config.ts .pnpmfile.mjs .gitignore .dockerignore Dockerfile TODO.md rust-toolchain.toml .vscode .github .devcontainer ${rootAutomationPaths}`,
2047
+ lint: deploymentCheck === undefined
2048
+ ? `oxlint --quiet --format=unix --no-error-on-unmatched-pattern *.config.ts .pnpmfile.mjs ${rootAutomationPaths}`
2049
+ : `shellcheck scripts/container-entrypoint.sh && oxlint --quiet --format=unix --no-error-on-unmatched-pattern *.config.ts .pnpmfile.mjs ${rootAutomationPaths}`,
2050
+ "lint:fix": `oxlint --format=unix --no-error-on-unmatched-pattern *.config.ts .pnpmfile.mjs ${rootAutomationPaths} --fix`,
777
2051
  typecheck: "tsc -p tsconfig.json --noEmit --pretty false",
778
2052
  },
779
2053
  devDependencies: {
780
2054
  "@types/node": "catalog:",
2055
+ ...(rootOwnedE2e ? { "@playwright/test": "catalog:" } : {}),
2056
+ ...(publicationCandidate === undefined
2057
+ ? {}
2058
+ : {
2059
+ "@types/semver": "catalog:",
2060
+ "@types/spdx-expression-parse": "catalog:",
2061
+ }),
781
2062
  oxfmt: "catalog:",
782
2063
  oxlint: "catalog:",
783
2064
  "oxlint-tsgolint": "catalog:",
2065
+ "smol-toml": "catalog:",
2066
+ ...(publicationCandidate === undefined
2067
+ ? {}
2068
+ : {
2069
+ semver: "catalog:",
2070
+ "spdx-expression-parse": "catalog:",
2071
+ npm: "catalog:",
2072
+ tar: "catalog:",
2073
+ }),
784
2074
  turbo: "catalog:",
785
2075
  "typescript-7": "catalog:",
786
2076
  },
787
- engines: { node: options.context.toolchain.nodeLtsMajor },
2077
+ engines: { node: options.rootNodeDeclaration },
788
2078
  packageManager: options.context.toolchain.packageManagerPin,
789
2079
  };
790
2080
  const dependencyCatalog = selectTemplateDependencyCatalogEntries(collectGeneratedManifestCatalogReferences([
@@ -824,8 +2114,7 @@ function foundationPlan(options) {
824
2114
  };
825
2115
  const workflowTemplateSource = projectCheckWorkflowTemplateSource({
826
2116
  packagePaths: blueprintPackagePaths,
827
- deploymentEnvironmentNeeds,
828
- hasDeploymentTask,
2117
+ deploymentCheck,
829
2118
  diagnosticArtifacts: ciDiagnosticArtifacts,
830
2119
  });
831
2120
  const workflowOperation = ciDiagnosticArtifacts.length === 0
@@ -847,6 +2136,16 @@ function foundationPlan(options) {
847
2136
  };
848
2137
  const workflowOperations = [
849
2138
  workflowOperation,
2139
+ ...(publicationCandidate === undefined
2140
+ ? []
2141
+ : [
2142
+ {
2143
+ kind: "copyFile",
2144
+ source: templateSources.tsCli,
2145
+ from: "publication/release.yml",
2146
+ to: ".github/workflows/release.yml",
2147
+ },
2148
+ ]),
850
2149
  {
851
2150
  kind: "writeTextTemplate",
852
2151
  source: templateSources.foundation,
@@ -857,6 +2156,70 @@ function foundationPlan(options) {
857
2156
  ];
858
2157
  const projectLinkPlan = initialProjectLinkPlan;
859
2158
  const turboBoundaryTags = turboBoundaryTagsForContributions(contributions);
2159
+ const reconciliation = [
2160
+ { path: "tsconfig.json", driver: "structured" },
2161
+ { path: "turbo.json", driver: "structured" },
2162
+ {
2163
+ path: ".devcontainer/devcontainer.json",
2164
+ driver: "structured",
2165
+ identitySets: [developmentContainer.mountIdentitySet],
2166
+ // M1:根 engines.node 原文拥有的静态镜像槽位;Core 只见位置,不见文件语义。
2167
+ // 设计写作 /build.args/NODE_VERSION;RFC 6901 下点号不是分隔符,取同位置的标准形。
2168
+ mirrorSlots: [
2169
+ {
2170
+ id: "node-version-build-arg",
2171
+ location: {
2172
+ kind: "json-pointer",
2173
+ pointer: "/build/args/NODE_VERSION",
2174
+ },
2175
+ },
2176
+ // M5:仅当本 plan 选用 Rust 时接入同一机制,值由根 rust-toolchain.toml channel 拥有。
2177
+ // 声明只给位置、不含版本值,故已含 Rust 的目标在加包时 Before/After 清单逐字节相同,
2178
+ // reconciliationPoliciesCompatible 不因 M5 扩展把合法加包变成策略不兼容。
2179
+ ...(rustToolchain === undefined
2180
+ ? []
2181
+ : [
2182
+ {
2183
+ id: "rust-toolchain-build-arg",
2184
+ location: {
2185
+ kind: "json-pointer",
2186
+ pointer: "/build/args/RUST_TOOLCHAIN",
2187
+ },
2188
+ },
2189
+ ]),
2190
+ ],
2191
+ },
2192
+ ...(deploymentCheck === undefined || deploymentPackages === undefined
2193
+ ? []
2194
+ : [
2195
+ {
2196
+ path: "Dockerfile",
2197
+ driver: "text",
2198
+ // M2:同一 rootNodeDeclaration 投影的锚定 ARG 默认值。
2199
+ mirrorSlots: [
2200
+ {
2201
+ id: "node-version-deployment-arg",
2202
+ location: { kind: "text-anchor", name: "NODE_VERSION" },
2203
+ },
2204
+ ],
2205
+ },
2206
+ ]),
2207
+ {
2208
+ path: ".vscode/extensions.json",
2209
+ driver: "structured",
2210
+ identitySets: [
2211
+ {
2212
+ location: "/recommendations",
2213
+ identity: { kind: "self" },
2214
+ },
2215
+ ],
2216
+ },
2217
+ { path: ".template/blueprint.json", driver: "canonical" },
2218
+ { path: environmentNeedsPath, driver: "canonical" },
2219
+ { path: ".template/generation.json", driver: "canonical" },
2220
+ ];
2221
+ // 票 26 清单单源:生成检查器携带的槽位清单是上面声明的投影,不是第二份真源。
2222
+ const toolchainMirrorSlotManifest = renderToolchainMirrorSlotManifest(reconciliation);
860
2223
  const initializationFoundationOperations = [
861
2224
  {
862
2225
  kind: "writeJson",
@@ -866,35 +2229,98 @@ function foundationPlan(options) {
866
2229
  nestedKeyOrder: packageConditionKeyOrder,
867
2230
  },
868
2231
  workspaceOperation,
2232
+ ...(requiresPackingHook
2233
+ ? [
2234
+ {
2235
+ kind: "copyFile",
2236
+ source: templateSources.foundation,
2237
+ from: ".pnpmfile.mjs",
2238
+ to: ".pnpmfile.mjs",
2239
+ },
2240
+ ]
2241
+ : []),
869
2242
  {
870
2243
  kind: "copyFile",
871
2244
  source: templateSources.foundation,
872
2245
  from: "gitignore",
873
2246
  to: ".gitignore",
874
2247
  },
2248
+ {
2249
+ kind: "copyFile",
2250
+ source: templateSources.foundation,
2251
+ from: "AGENTS.md.template",
2252
+ to: "AGENTS.md",
2253
+ },
875
2254
  {
876
2255
  kind: "copyFile",
877
2256
  source: templateSources.foundation,
878
2257
  from: "turbo.json",
879
2258
  to: "turbo.json",
880
2259
  },
2260
+ ...(vueHonoJointE2e === undefined
2261
+ ? []
2262
+ : [
2263
+ {
2264
+ kind: "mergeJson",
2265
+ to: "turbo.json",
2266
+ value: { tasks: vueHonoJointE2eTurboTasks(vueHonoJointE2e) },
2267
+ multilineArrays: ["tasks.//#test:e2e.dependsOn"],
2268
+ },
2269
+ ]),
2270
+ ...(deploymentCheck === undefined
2271
+ ? []
2272
+ : [
2273
+ {
2274
+ kind: "mergeJson",
2275
+ to: "turbo.json",
2276
+ value: {
2277
+ tasks: deploymentTurboTasks(deploymentCheck),
2278
+ },
2279
+ multilineArrays: ["tasks.//#deployment.dependsOn"],
2280
+ },
2281
+ ]),
2282
+ ...(databasePreparation === undefined
2283
+ ? []
2284
+ : [
2285
+ {
2286
+ kind: "mergeJson",
2287
+ to: "turbo.json",
2288
+ value: {
2289
+ tasks: databasePreparationTurboTasks(databasePreparation),
2290
+ },
2291
+ multilineArrays: [
2292
+ `tasks.${databasePreparation.migrationPackageName}#typecheck.dependsOn`,
2293
+ `tasks.${databasePreparation.consumers["application-dev"]}#typecheck.dependsOn`,
2294
+ `tasks.${databasePreparation.consumers["application-dev"]}#dev.dependsOn`,
2295
+ `tasks.${databasePreparation.consumers["application-e2e"]}#test:e2e.dependsOn`,
2296
+ ],
2297
+ },
2298
+ ]),
2299
+ ...(publicationCandidate === undefined
2300
+ ? []
2301
+ : [
2302
+ {
2303
+ kind: "mergeJsonTemplate",
2304
+ source: templateSources.tsCli,
2305
+ from: "publication/turbo.json",
2306
+ to: "turbo.json",
2307
+ },
2308
+ ]),
881
2309
  ...turboBoundaryTags.map((tag) => ({
882
2310
  kind: "mergeJsonTemplate",
883
2311
  source: templateSources.foundation,
884
2312
  from: `turbo-boundary-tags/${tag}.json`,
885
2313
  to: "turbo.json",
2314
+ multilineArrays: deploymentCheck === undefined ? [] : ["tasks.//#deployment.dependsOn"],
886
2315
  })),
887
2316
  {
888
- kind: "copyFile",
889
- source: templateSources.foundation,
890
- from: "scripts/check-boundaries.ts",
891
- to: "scripts/check-boundaries.ts",
892
- },
893
- {
894
- kind: "copyFile",
2317
+ kind: "writeTextTemplate",
895
2318
  source: templateSources.foundation,
896
- from: "scripts/run-root-owned-task.ts",
897
- to: "scripts/run-root-owned-task.ts",
2319
+ from: "scripts/check-toolchain-versions.ts",
2320
+ to: "scripts/check-toolchain-versions.ts",
2321
+ replacements: {
2322
+ TOOLCHAIN_MIRROR_SLOT_MANIFEST: toolchainMirrorSlotManifest,
2323
+ },
898
2324
  },
899
2325
  {
900
2326
  kind: "copyFile",
@@ -902,6 +2328,58 @@ function foundationPlan(options) {
902
2328
  from: "tsconfig.json",
903
2329
  to: "tsconfig.json",
904
2330
  },
2331
+ ...(vueHonoJointE2e === undefined
2332
+ ? []
2333
+ : [
2334
+ {
2335
+ kind: "mergeJsonTemplate",
2336
+ source: templateSources.vueHonoApp,
2337
+ from: "root/tsconfig.json",
2338
+ to: "tsconfig.json",
2339
+ },
2340
+ {
2341
+ kind: "writeTextTemplate",
2342
+ source: templateSources.vueHonoApp,
2343
+ from: "root/playwright.config.ts",
2344
+ to: "playwright.config.ts",
2345
+ replacements: {
2346
+ API_PACKAGE_NAME: vueHonoJointE2e.apiPackageName,
2347
+ WEB_PACKAGE_NAME: vueHonoJointE2e.webPackageName,
2348
+ },
2349
+ },
2350
+ {
2351
+ kind: "copyFile",
2352
+ source: templateSources.vueHonoApp,
2353
+ from: "root/test/e2e/fixtures.ts",
2354
+ to: "test/e2e/fixtures.ts",
2355
+ },
2356
+ {
2357
+ kind: "copyFile",
2358
+ source: templateSources.vueHonoApp,
2359
+ from: "root/test/e2e/app.spec.ts",
2360
+ to: "test/e2e/app.spec.ts",
2361
+ },
2362
+ ]),
2363
+ ...(publicationCandidate === undefined
2364
+ ? []
2365
+ : [
2366
+ {
2367
+ kind: "mergeJsonTemplate",
2368
+ source: templateSources.tsCli,
2369
+ from: "publication/root-tsconfig.json",
2370
+ to: "tsconfig.json",
2371
+ },
2372
+ ]),
2373
+ ...(requiresPackingHook && publicationCandidate === undefined
2374
+ ? [
2375
+ {
2376
+ kind: "mergeJsonTemplate",
2377
+ source: templateSources.foundation,
2378
+ from: "tsconfig.packing-hook.json",
2379
+ to: "tsconfig.json",
2380
+ },
2381
+ ]
2382
+ : []),
905
2383
  {
906
2384
  kind: "copyFile",
907
2385
  source: templateSources.sharedOxc,
@@ -920,6 +2398,135 @@ function foundationPlan(options) {
920
2398
  from: "oxfmt.config.ts",
921
2399
  to: "oxfmt.config.ts",
922
2400
  },
2401
+ ...(publicationCandidate === undefined
2402
+ ? []
2403
+ : [
2404
+ {
2405
+ kind: "copyFile",
2406
+ source: templateSources.tsCli,
2407
+ from: "publication/readiness.ts",
2408
+ to: "scripts/npm-publication/readiness.ts",
2409
+ },
2410
+ {
2411
+ kind: "copyFile",
2412
+ source: templateSources.tsCli,
2413
+ from: "publication/artifact.ts",
2414
+ to: "scripts/npm-publication/artifact.ts",
2415
+ },
2416
+ {
2417
+ kind: "copyFile",
2418
+ source: templateSources.tsCli,
2419
+ from: "publication/handoff.ts",
2420
+ to: "scripts/npm-publication/handoff.ts",
2421
+ },
2422
+ {
2423
+ kind: "writeTextTemplate",
2424
+ source: templateSources.tsCli,
2425
+ from: "publication/check-artifact.ts",
2426
+ to: "scripts/npm-publication/check-artifact.ts",
2427
+ replacements: {
2428
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2429
+ },
2430
+ },
2431
+ {
2432
+ kind: "writeTextTemplate",
2433
+ source: templateSources.tsCli,
2434
+ from: "publication/publish.ts",
2435
+ to: "scripts/npm-publication/publish.ts",
2436
+ replacements: {
2437
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2438
+ },
2439
+ },
2440
+ {
2441
+ kind: "writeTextTemplate",
2442
+ source: templateSources.tsCli,
2443
+ from: "publication/release.ts",
2444
+ to: "scripts/npm-publication/release.ts",
2445
+ replacements: {
2446
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2447
+ },
2448
+ },
2449
+ {
2450
+ kind: "writeTextTemplate",
2451
+ source: templateSources.tsCli,
2452
+ from: "publication/check-readiness.ts",
2453
+ to: "scripts/npm-publication/check-readiness.ts",
2454
+ replacements: {
2455
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2456
+ },
2457
+ },
2458
+ {
2459
+ kind: "copyFile",
2460
+ source: templateSources.tsCli,
2461
+ from: "publication/changelog.ts",
2462
+ to: "scripts/npm-publication/changelog.ts",
2463
+ },
2464
+ {
2465
+ kind: "copyFile",
2466
+ source: templateSources.tsCli,
2467
+ from: "publication/RELEASING.md",
2468
+ to: "RELEASING.md",
2469
+ },
2470
+ {
2471
+ kind: "copyFile",
2472
+ source: templateSources.tsCli,
2473
+ from: "src/cli-command-identity.ts",
2474
+ to: "scripts/npm-publication/cli-command-identity.ts",
2475
+ },
2476
+ {
2477
+ kind: "writeTextTemplate",
2478
+ source: templateSources.tsCli,
2479
+ from: "publication-setup/setup.sh",
2480
+ to: "scripts/npm-publication-setup/setup.sh",
2481
+ replacements: {
2482
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2483
+ },
2484
+ },
2485
+ {
2486
+ kind: "setExecutable",
2487
+ path: "scripts/npm-publication-setup/setup.sh",
2488
+ executable: true,
2489
+ },
2490
+ {
2491
+ kind: "copyFile",
2492
+ source: templateSources.tsCli,
2493
+ from: "publication-setup/README.md",
2494
+ to: "scripts/npm-publication-setup/README.md",
2495
+ },
2496
+ {
2497
+ kind: "writeTextTemplate",
2498
+ source: templateSources.tsCli,
2499
+ from: "publication-setup/bridge.ts",
2500
+ to: "scripts/npm-publication-setup/bridge.ts",
2501
+ replacements: {
2502
+ PUBLIC_CLI_PACKAGE_PATH: publicationCandidate.definition.path,
2503
+ },
2504
+ },
2505
+ {
2506
+ kind: "copyFile",
2507
+ source: templateSources.tsCli,
2508
+ from: "publication-setup/assets/LICENSE-MIT.txt",
2509
+ to: "scripts/npm-publication-setup/assets/LICENSE-MIT.txt",
2510
+ },
2511
+ {
2512
+ kind: "copyFile",
2513
+ source: templateSources.tsCli,
2514
+ from: "publication-setup/assets/LICENSE-APACHE-2.0.txt",
2515
+ to: "scripts/npm-publication-setup/assets/LICENSE-APACHE-2.0.txt",
2516
+ },
2517
+ {
2518
+ kind: "copyFile",
2519
+ source: templateSources.tsCli,
2520
+ from: "publication-setup/assets/README.md.template",
2521
+ to: "scripts/npm-publication-setup/assets/README.md.template",
2522
+ },
2523
+ {
2524
+ kind: "copyFile",
2525
+ source: templateSources.tsCli,
2526
+ from: "publication-setup/assets/CHANGELOG.md.template",
2527
+ to: "scripts/npm-publication-setup/assets/CHANGELOG.md.template",
2528
+ },
2529
+ ]),
923
2530
  {
924
2531
  kind: "writeJson",
925
2532
  to: ".vscode/extensions.json",
@@ -934,7 +2541,67 @@ function foundationPlan(options) {
934
2541
  value: editorCustomization.settings,
935
2542
  },
936
2543
  ...developmentContainer.operations,
937
- ...contributedFoundationTemplateFileOperations(contributions),
2544
+ ...(rustToolchain === undefined
2545
+ ? []
2546
+ : [
2547
+ {
2548
+ kind: "writeTextTemplate",
2549
+ source: rustToolchain.configurationSource.source,
2550
+ from: rustToolchain.configurationSource.from,
2551
+ to: "rust-toolchain.toml",
2552
+ replacements: { RUST_TOOLCHAIN: rustToolchain.toolchain },
2553
+ },
2554
+ ]),
2555
+ ...(deploymentCheck === undefined || deploymentPackages === undefined
2556
+ ? []
2557
+ : [
2558
+ {
2559
+ kind: "writeTextTemplate",
2560
+ source: deploymentCheck.sources.dockerfile.source,
2561
+ from: deploymentCheck.sources.dockerfile.from,
2562
+ to: "Dockerfile",
2563
+ replacements: {
2564
+ NODE_VERSION: options.rootNodeDeclaration,
2565
+ APPLICATION_PACKAGE_NAME: deploymentPackages.application.definition.name,
2566
+ APPLICATION_PACKAGE_PATH: deploymentPackages.application.definition.path,
2567
+ DATABASE_PACKAGE_NAME: deploymentPackages.database.definition.name,
2568
+ DATABASE_PACKAGE_PATH: deploymentPackages.database.definition.path,
2569
+ MIGRATION_PACKAGE_NAME: deploymentPackages.migration.definition.name,
2570
+ MIGRATION_PACKAGE_PATH: deploymentPackages.migration.definition.path,
2571
+ TYPESCRIPT_CONFIG_PACKAGE_PATH: configDefinition.path,
2572
+ },
2573
+ },
2574
+ {
2575
+ kind: "writeTextTemplate",
2576
+ source: deploymentCheck.sources.dockerIgnore.source,
2577
+ from: deploymentCheck.sources.dockerIgnore.from,
2578
+ to: ".dockerignore",
2579
+ replacements: {
2580
+ APPLICATION_PACKAGE_PATH: deploymentPackages.application.definition.path,
2581
+ DATABASE_PACKAGE_PATH: deploymentPackages.database.definition.path,
2582
+ },
2583
+ },
2584
+ {
2585
+ kind: "writeTextTemplate",
2586
+ source: deploymentCheck.sources.checker.source,
2587
+ from: deploymentCheck.sources.checker.from,
2588
+ to: "scripts/check-standalone-deployment.ts",
2589
+ replacements: {
2590
+ APPLICATION_PACKAGE_NAME: deploymentPackages.application.definition.name,
2591
+ },
2592
+ },
2593
+ {
2594
+ kind: "copyFile",
2595
+ source: deploymentCheck.sources.controlScript.source,
2596
+ from: deploymentCheck.sources.controlScript.from,
2597
+ to: "scripts/container-entrypoint.sh",
2598
+ },
2599
+ {
2600
+ kind: "setExecutable",
2601
+ path: "scripts/container-entrypoint.sh",
2602
+ executable: true,
2603
+ },
2604
+ ]),
938
2605
  ...workflowOperations,
939
2606
  {
940
2607
  kind: "writeJson",
@@ -1007,27 +2674,6 @@ function foundationPlan(options) {
1007
2674
  ...plannedFoundationOperations.map((operation) => withProvenance(operation, foundationProvenance)),
1008
2675
  ...linkOperations.map((operation) => withProvenance(operation, foundationProvenance)),
1009
2676
  ];
1010
- const reconciliation = [
1011
- { path: "turbo.json", driver: "structured" },
1012
- {
1013
- path: ".devcontainer/devcontainer.json",
1014
- driver: "structured",
1015
- identitySets: [developmentContainer.mountIdentitySet],
1016
- },
1017
- {
1018
- path: ".vscode/extensions.json",
1019
- driver: "structured",
1020
- identitySets: [
1021
- {
1022
- location: "/recommendations",
1023
- identity: { kind: "self" },
1024
- },
1025
- ],
1026
- },
1027
- { path: ".template/blueprint.json", driver: "canonical" },
1028
- { path: environmentNeedsPath, driver: "canonical" },
1029
- { path: ".template/generation.json", driver: "canonical" },
1030
- ];
1031
2677
  return {
1032
2678
  definitionName: options.definition.metadata.name,
1033
2679
  plannerSourceFile: options.definition.plannerSourceFile,
@@ -1036,6 +2682,7 @@ function foundationPlan(options) {
1036
2682
  : "planInitialization",
1037
2683
  blueprint: options.blueprint,
1038
2684
  generationRecord,
2685
+ packageContributions,
1039
2686
  operations,
1040
2687
  reconciliation,
1041
2688
  developmentContainer: {
@@ -1045,6 +2692,21 @@ function foundationPlan(options) {
1045
2692
  probes: developmentContainer.probes,
1046
2693
  },
1047
2694
  environmentNeeds,
2695
+ deploymentCheck: deploymentCheck === undefined
2696
+ ? undefined
2697
+ : {
2698
+ kind: deploymentCheck.kind,
2699
+ applicationPackageName: deploymentCheck.applicationPackageName,
2700
+ databasePackageName: deploymentCheck.databasePackageName,
2701
+ migrationPackageName: deploymentCheck.migrationPackageName,
2702
+ environmentNeeds: deploymentCheck.environmentNeeds,
2703
+ },
2704
+ vueHonoJointE2e: vueHonoJointE2e === undefined
2705
+ ? undefined
2706
+ : {
2707
+ kind: vueHonoJointE2e.kind,
2708
+ apiPackageName: vueHonoJointE2e.apiPackageName,
2709
+ },
1048
2710
  deploymentEnvironmentNeeds,
1049
2711
  ciDiagnosticArtifacts,
1050
2712
  manifests: [...contributions.map((item) => item.manifest), rootManifest],
@@ -1057,73 +2719,454 @@ function foundationPlan(options) {
1057
2719
  ],
1058
2720
  };
1059
2721
  }
1060
- export function planGeneratedRepositoryInitialization(options) {
1061
- const presetBlueprint = options.definition.blueprint(options.context);
2722
+ function hasConfigurablePrimaryPackage(definition) {
2723
+ return definition.initialPrimaryPackage !== undefined;
2724
+ }
2725
+ function deduplicateInitializationInputIssues(issues) {
2726
+ return issues.filter((issue, index) => issues.findIndex((candidate) => candidate.code === issue.code) === index);
2727
+ }
2728
+ function collectInitializationInput(options) {
2729
+ const issues = [];
2730
+ const definition = options.definition ??
2731
+ (options.preset === undefined
2732
+ ? undefined
2733
+ : builtInPresetRegistry
2734
+ .all()
2735
+ .find((candidate) => candidate.metadata.name === options.preset));
2736
+ if (definition === undefined) {
2737
+ return {
2738
+ status: "input-invalid",
2739
+ issues: [{ code: "PRESET_UNKNOWN" }],
2740
+ };
2741
+ }
2742
+ const scopeOverride = options.overrides?.scope;
2743
+ const normalizedScope = scopeOverride?.startsWith("@") === true
2744
+ ? scopeOverride.slice(1)
2745
+ : scopeOverride;
2746
+ const nameOverride = options.overrides?.name;
2747
+ const pathOverride = options.overrides?.path;
2748
+ const repositoryName = path.basename(path.resolve(options.targetDir));
2749
+ const configurablePrimaryPackage = definition.initialPrimaryPackage !== undefined;
2750
+ if (!configurablePrimaryPackage &&
2751
+ (nameOverride !== undefined || pathOverride !== undefined)) {
2752
+ issues.push({ code: "FIXED_TOPOLOGY_OVERRIDE" });
2753
+ }
2754
+ let validNameOverride = nameOverride !== undefined &&
2755
+ isValidNewNpmPackageName(`@x/${nameOverride}`);
2756
+ if (nameOverride !== undefined && !validNameOverride) {
2757
+ issues.push({ code: "INVALID_PACKAGE_NAME" });
2758
+ }
2759
+ if (pathOverride !== undefined) {
2760
+ const pathValidation = validateNewPackagePath(pathOverride);
2761
+ if (!pathValidation.hasValidShape) {
2762
+ issues.push({ code: "INVALID_PACKAGE_PATH" });
2763
+ }
2764
+ if (pathValidation.reservedWorkspaceCollection !== undefined) {
2765
+ issues.push({ code: "RESERVED_PACKAGE_PATH" });
2766
+ }
2767
+ }
2768
+ let validScopeOverride = normalizedScope !== undefined &&
2769
+ scopeOverride === scopeOverride?.trim() &&
2770
+ isValidDefaultPackageScope(normalizedScope) &&
2771
+ isValidNewNpmPackageName(`@${normalizedScope}/typescript-config`);
2772
+ if (normalizedScope !== undefined && !validScopeOverride) {
2773
+ issues.push({ code: "INVALID_PACKAGE_SCOPE" });
2774
+ }
2775
+ let validRepositoryScope = isValidDefaultPackageScope(repositoryName) &&
2776
+ isValidNewNpmPackageName(`@${repositoryName}/typescript-config`);
2777
+ if (normalizedScope === undefined && !validRepositoryScope) {
2778
+ issues.push({ code: "INVALID_REPOSITORY_SCOPE" });
2779
+ }
2780
+ const resolvedScope = validScopeOverride
2781
+ ? (normalizedScope ?? "repository")
2782
+ : validRepositoryScope
2783
+ ? repositoryName
2784
+ : "repository";
2785
+ const resolvedLeaf = configurablePrimaryPackage &&
2786
+ nameOverride !== undefined &&
2787
+ validNameOverride
2788
+ ? nameOverride
2789
+ : configurablePrimaryPackage
2790
+ ? definition.initialPrimaryPackage?.defaultLeafName
2791
+ : undefined;
2792
+ if (resolvedLeaf !== undefined &&
2793
+ !isValidNewNpmPackageName(`@${resolvedScope}/${resolvedLeaf}`)) {
2794
+ if (nameOverride !== undefined) {
2795
+ validNameOverride = false;
2796
+ issues.push({ code: "INVALID_PACKAGE_NAME" });
2797
+ }
2798
+ else if (scopeOverride !== undefined) {
2799
+ validScopeOverride = false;
2800
+ issues.push({ code: "INVALID_PACKAGE_SCOPE" });
2801
+ }
2802
+ else {
2803
+ validRepositoryScope = false;
2804
+ issues.push({ code: "INVALID_REPOSITORY_SCOPE" });
2805
+ }
2806
+ }
2807
+ const initialPrimaryPackage = definition.initialPrimaryPackage;
2808
+ const foundationDefinition = typescriptConfigPackageDefinition({
2809
+ foundationPackages: {
2810
+ typescriptConfiguration: {
2811
+ name: `@${resolvedScope}/typescript-config`,
2812
+ },
2813
+ },
2814
+ });
2815
+ if ((nameOverride !== undefined &&
2816
+ `@${resolvedScope}/${nameOverride}` === foundationDefinition.name) ||
2817
+ pathOverride === foundationDefinition.path) {
2818
+ issues.push({ code: "CONFLICTING_PACKAGE_IDENTITY" });
2819
+ }
2820
+ if (issues.length > 0) {
2821
+ return {
2822
+ status: "input-invalid",
2823
+ issues: deduplicateInitializationInputIssues(issues),
2824
+ };
2825
+ }
2826
+ return {
2827
+ status: "valid",
2828
+ definition,
2829
+ normalizedScope,
2830
+ nameOverride,
2831
+ pathOverride,
2832
+ repositoryName,
2833
+ configurablePrimaryPackage,
2834
+ validScopeOverride,
2835
+ validRepositoryScope,
2836
+ resolvedScope,
2837
+ initialPrimaryPackage,
2838
+ foundationDefinition,
2839
+ };
2840
+ }
2841
+ export function validateGeneratedRepositoryInitializationInput(options) {
2842
+ const input = collectInitializationInput(options);
2843
+ return input.status === "input-invalid" ? input : { status: "valid" };
2844
+ }
2845
+ function errorDiagnostics(error) {
2846
+ return (error instanceof Error ? error.message : String(error))
2847
+ .split("\n")
2848
+ .filter((diagnostic) => diagnostic.length > 0);
2849
+ }
2850
+ function preparePresetInitialization(options) {
2851
+ if (!hasConfigurablePrimaryPackage(options.definition)) {
2852
+ const diagnostics = [];
2853
+ let presetBlueprint;
2854
+ let contributions;
2855
+ try {
2856
+ presetBlueprint = assertProjectBlueprintDraft(options.definition.blueprint(options.context));
2857
+ }
2858
+ catch (error) {
2859
+ diagnostics.push(...errorDiagnostics(error));
2860
+ }
2861
+ try {
2862
+ contributions = options.definition.planInitializationContributions?.(options.context) ?? [options.definition.planInitialization(options.context)];
2863
+ }
2864
+ catch (error) {
2865
+ diagnostics.push(...errorDiagnostics(error));
2866
+ }
2867
+ if (diagnostics.length > 0)
2868
+ throw new Error(diagnostics.join("\n"));
2869
+ return {
2870
+ presetBlueprint: presetBlueprint,
2871
+ contributions: contributions,
2872
+ };
2873
+ }
2874
+ const capability = options.definition.initialPrimaryPackage;
2875
+ const leafName = options.overrides?.name ?? capability.defaultLeafName;
2876
+ const resolvedPackageIdentity = {
2877
+ leafName,
2878
+ definition: {
2879
+ name: `@${options.context.defaultPackageScope}/${leafName}`,
2880
+ path: options.overrides?.path ??
2881
+ capability.defaultPackagePath({ packageLeafName: leafName }),
2882
+ role: capability.role,
2883
+ },
2884
+ };
2885
+ const diagnostics = [];
2886
+ let presetBlueprint;
2887
+ let contribution;
2888
+ try {
2889
+ presetBlueprint = assertProjectBlueprintDraft({
2890
+ schemaVersion: 3,
2891
+ packages: [resolvedPackageIdentity.definition],
2892
+ });
2893
+ }
2894
+ catch (error) {
2895
+ diagnostics.push(...errorDiagnostics(error));
2896
+ }
2897
+ try {
2898
+ contribution = capability.planInitialContribution({
2899
+ context: options.context,
2900
+ resolvedPackageIdentity,
2901
+ });
2902
+ }
2903
+ catch (error) {
2904
+ diagnostics.push(...errorDiagnostics(error));
2905
+ }
2906
+ if (diagnostics.length > 0)
2907
+ throw new Error(diagnostics.join("\n"));
2908
+ return {
2909
+ presetBlueprint: presetBlueprint,
2910
+ contributions: [contribution],
2911
+ resolvedPackageIdentity,
2912
+ };
2913
+ }
2914
+ function planPreparedRepositoryInitialization(options) {
2915
+ const { presetBlueprint, contributions } = options;
1062
2916
  const configDefinition = typescriptConfigPackageDefinition(options.context);
1063
- if (presetBlueprint.packages.some((definition) => definition.name === configDefinition.name ||
1064
- definition.path === configDefinition.path)) {
1065
- throw new Error("Preset Blueprint must not redefine the Foundation TypeScript configuration Package Definition");
2917
+ const foundationIdentityDiagnostics = presetBlueprint.packages.flatMap((definition) => [
2918
+ ...(definition.name === configDefinition.name
2919
+ ? [
2920
+ `Initial package name ${definition.name} conflicts with Foundation package ${configDefinition.name}`,
2921
+ ]
2922
+ : []),
2923
+ ...(definition.path === configDefinition.path
2924
+ ? [
2925
+ `Initial Package Path ${definition.path} conflicts with Foundation Package Path ${configDefinition.path}`,
2926
+ ]
2927
+ : []),
2928
+ ]);
2929
+ if (foundationIdentityDiagnostics.length > 0) {
2930
+ throw new Error(foundationIdentityDiagnostics.join("\n"));
1066
2931
  }
2932
+ const occupiedIds = new Set();
1067
2933
  const blueprint = {
1068
2934
  ...presetBlueprint,
1069
- packages: [...presetBlueprint.packages, configDefinition],
2935
+ packages: [
2936
+ ...presetBlueprint.packages.map((definition) => {
2937
+ const contribution = contributions.find((candidate) => packageDefinitionsEqual(candidate.definition, definition));
2938
+ if (contribution === undefined) {
2939
+ throw new Error(`Preset Blueprint Package Definition ${definition.path} has no initialization Package Contribution`);
2940
+ }
2941
+ return persistPackageDefinition({
2942
+ definition,
2943
+ provenance: {
2944
+ definitionName: options.definition.metadata.name,
2945
+ planningContribution: "planInitialization",
2946
+ contributionIdentity: requireReplayAdapter({
2947
+ owner: options.definition.metadata.name,
2948
+ adapters: options.definition.packageContributionReplayAdapters,
2949
+ identity: contribution.planningIdentity,
2950
+ }).identity,
2951
+ },
2952
+ occupiedIds,
2953
+ });
2954
+ }),
2955
+ persistPackageDefinition({
2956
+ definition: configDefinition,
2957
+ provenance: {
2958
+ definitionName: "foundation",
2959
+ planningContribution: "foundationPlan",
2960
+ contributionIdentity: typescriptConfigReplayAdapter.identity,
2961
+ },
2962
+ occupiedIds,
2963
+ }),
2964
+ ],
1070
2965
  };
1071
- const contributions = options.definition.planInitializationContributions?.(options.context) ?? [options.definition.planInitialization(options.context)];
1072
2966
  return foundationPlan({
1073
2967
  definition: options.definition,
1074
2968
  context: options.context,
1075
2969
  blueprint,
2970
+ foundationContribution: typescriptConfigReplayAdapter.identify(typescriptConfigContribution(options.context, configDefinition)),
1076
2971
  contributions,
1077
2972
  mode: "initialization",
2973
+ rootNodeDeclaration: options.rootNodeDeclaration,
1078
2974
  });
1079
2975
  }
1080
- export function planGeneratedRepositoryPackageAddition(options) {
1081
- assertProjectBlueprintV2(options.blueprint);
1082
- if (!options.definition.planPackageAddition)
1083
- throw new Error(`Built-in Preset ${options.definition.metadata.name} does not support Package Addition`);
1084
- const packagePath = options.packagePath ??
1085
- options.definition.defaultPackagePath?.({
1086
- context: options.context,
1087
- packageLeafName: options.packageLeafName,
1088
- });
1089
- if (packagePath === undefined) {
1090
- throw new Error(`Built-in Preset ${options.definition.metadata.name} must own a default Package Path or receive an explicit Package Path`);
2976
+ function assertPreflightedInitializationPlan(plan) {
2977
+ const projectionDiagnostics = validateProjectProjectionPlan({
2978
+ operations: plan.operations,
2979
+ reconciliation: plan.reconciliation,
2980
+ });
2981
+ if (projectionDiagnostics.length > 0) {
2982
+ throw new Error(projectionDiagnostics.join("\n"));
1091
2983
  }
1092
- const contribution = options.definition.planPackageAddition({
2984
+ return plan;
2985
+ }
2986
+ /** 精确 Node 事实必须是有三段补丁号的版本,不接受纯大版本或两段形式。 */
2987
+ const exactNodeVersionPattern = /^\d+\.\d+\.\d+$/u;
2988
+ /**
2989
+ * 私有根的 Node 声明:上下文带已知精确值时沿用该精确值,并校验其大版本与 nodeLtsMajor 一致;
2990
+ * 缺省时沿用原有大版本声明。这条缺省路径不作为新生成公开包范围的推导来源。
2991
+ */
2992
+ function resolvePrivateRootNodeDeclaration(toolchain) {
2993
+ const { nodeLtsMajor, nodeVersion } = toolchain;
2994
+ if (nodeVersion === undefined)
2995
+ return nodeLtsMajor;
2996
+ if (!exactNodeVersionPattern.test(nodeVersion)) {
2997
+ throw new Error(`Generation Context 的 toolchain.nodeVersion 必须是精确三段 Node 版本("24.16.0"),实际收到 ${JSON.stringify(nodeVersion)}。`);
2998
+ }
2999
+ if (nodeVersion.slice(0, nodeVersion.indexOf(".")) !== nodeLtsMajor) {
3000
+ throw new Error(`Generation Context 的 toolchain.nodeVersion ${nodeVersion} 与 nodeLtsMajor ${nodeLtsMajor} 大版本不一致。`);
3001
+ }
3002
+ return nodeVersion;
3003
+ }
3004
+ /**
3005
+ * 直接规划接缝:调用方自带 Generation Context,私有根沿用其 Node 声明;上下文带精确事实时
3006
+ * 私有根得到精确版本。生产初始化由 prepareGeneratedRepositoryInitialization 投影 CLI 发版快照。
3007
+ */
3008
+ export function planGeneratedRepositoryInitialization(options) {
3009
+ const prepared = preparePresetInitialization(options);
3010
+ return assertPreflightedInitializationPlan(planPreparedRepositoryInitialization({
3011
+ definition: options.definition,
1093
3012
  context: options.context,
1094
- packageLeafName: options.packageLeafName,
1095
- packagePath,
3013
+ presetBlueprint: prepared.presetBlueprint,
3014
+ contributions: prepared.contributions,
3015
+ rootNodeDeclaration: resolvePrivateRootNodeDeclaration(options.context.toolchain),
3016
+ }));
3017
+ }
3018
+ /**
3019
+ * 初始化只消费随 CLI 发版的不可变工具链快照:私有根得到精确 Node 与 pnpm pin,
3020
+ * 选用 Rust 的仓库根 toolchain 声明得到快照的精确 Rust 版本,Generation Record 与容器等
3021
+ * 消费者继续得到派生的大版本。不读在线版本源,也不接受调用方版本。
3022
+ */
3023
+ const initializationSnapshotToolchain = {
3024
+ nodeLtsMajor: releaseToolchainSnapshot.nodeVersion.slice(0, releaseToolchainSnapshot.nodeVersion.indexOf(".")),
3025
+ packageManagerPin: releaseToolchainSnapshot.packageManagerPin,
3026
+ nodeVersion: releaseToolchainSnapshot.nodeVersion,
3027
+ rustVersion: releaseToolchainSnapshot.rustVersion,
3028
+ };
3029
+ export function prepareGeneratedRepositoryInitialization(options) {
3030
+ const input = collectInitializationInput(options);
3031
+ if (input.status === "input-invalid")
3032
+ return input;
3033
+ const { definition, normalizedScope, nameOverride, pathOverride, repositoryName, configurablePrimaryPackage, validScopeOverride, validRepositoryScope, resolvedScope, initialPrimaryPackage, foundationDefinition, } = input;
3034
+ let derivedPackagePath;
3035
+ if (initialPrimaryPackage !== undefined) {
3036
+ try {
3037
+ derivedPackagePath = initialPrimaryPackage.defaultPackagePath({
3038
+ packageLeafName: nameOverride ?? initialPrimaryPackage.defaultLeafName,
3039
+ });
3040
+ }
3041
+ catch {
3042
+ return { status: "operation-failure", phase: "preset" };
3043
+ }
3044
+ const derivedPathValidation = validateNewPackagePath(derivedPackagePath);
3045
+ if (!derivedPathValidation.hasValidShape ||
3046
+ derivedPathValidation.reservedWorkspaceCollection !== undefined) {
3047
+ return { status: "operation-failure", phase: "preset" };
3048
+ }
3049
+ if ((nameOverride === undefined &&
3050
+ `@${resolvedScope}/${initialPrimaryPackage.defaultLeafName}` ===
3051
+ foundationDefinition.name) ||
3052
+ (pathOverride === undefined &&
3053
+ derivedPackagePath === foundationDefinition.path)) {
3054
+ return { status: "operation-failure", phase: "preset" };
3055
+ }
3056
+ }
3057
+ const context = createGenerationContext({
3058
+ targetDir: options.targetDir,
3059
+ defaultPackageScope: validScopeOverride
3060
+ ? (normalizedScope ?? "repository")
3061
+ : validRepositoryScope
3062
+ ? repositoryName
3063
+ : "repository",
3064
+ toolchain: initializationSnapshotToolchain,
1096
3065
  });
3066
+ const safeIdentityOverrides = {
3067
+ ...(configurablePrimaryPackage && nameOverride !== undefined
3068
+ ? { name: nameOverride }
3069
+ : {}),
3070
+ ...(configurablePrimaryPackage && pathOverride !== undefined
3071
+ ? { path: pathOverride }
3072
+ : derivedPackagePath === undefined
3073
+ ? {}
3074
+ : { path: derivedPackagePath }),
3075
+ };
3076
+ let prepared;
3077
+ try {
3078
+ prepared = preparePresetInitialization({
3079
+ definition,
3080
+ context,
3081
+ ...(Object.keys(safeIdentityOverrides).length === 0
3082
+ ? {}
3083
+ : { overrides: safeIdentityOverrides }),
3084
+ });
3085
+ }
3086
+ catch {
3087
+ return { status: "operation-failure", phase: "preset" };
3088
+ }
3089
+ let plan;
3090
+ try {
3091
+ plan = planPreparedRepositoryInitialization({
3092
+ definition,
3093
+ context,
3094
+ presetBlueprint: prepared.presetBlueprint,
3095
+ contributions: prepared.contributions,
3096
+ // 私有根与上下文共用同一精确 Node 事实的推导点,避免根声明与上下文出现两个来源。
3097
+ rootNodeDeclaration: resolvePrivateRootNodeDeclaration(context.toolchain),
3098
+ });
3099
+ if (validateProjectProjectionPlan({
3100
+ operations: plan.operations,
3101
+ reconciliation: plan.reconciliation,
3102
+ }).length > 0) {
3103
+ return { status: "operation-failure", phase: "preflight" };
3104
+ }
3105
+ }
3106
+ catch {
3107
+ return { status: "operation-failure", phase: "planning" };
3108
+ }
3109
+ return {
3110
+ status: "ready",
3111
+ context,
3112
+ resolved: {
3113
+ preset: definition.metadata.name,
3114
+ topology: prepared.resolvedPackageIdentity === undefined
3115
+ ? "fixed"
3116
+ : "configurable-primary-package",
3117
+ packages: prepared.presetBlueprint.packages.map(({ name, path }) => ({
3118
+ name,
3119
+ path,
3120
+ })),
3121
+ scope: context.defaultPackageScope,
3122
+ },
3123
+ ...(prepared.resolvedPackageIdentity === undefined
3124
+ ? {}
3125
+ : { resolvedPackageIdentity: prepared.resolvedPackageIdentity }),
3126
+ plan,
3127
+ publicationSetup: publicCliCandidate(prepared.contributions) === undefined
3128
+ ? null
3129
+ : { command: "./scripts/npm-publication-setup/setup.sh" },
3130
+ };
3131
+ }
3132
+ function planGeneratedRepositoryPackageAdditionFromPreparedContribution(options) {
3133
+ const { blueprint: persistedBlueprint, context } = options.localTemplateMetadata;
3134
+ const { rootNodeDeclaration } = options.localTemplateMetadata[localTemplateMetadataStateKey];
3135
+ assertProjectBlueprint(persistedBlueprint);
3136
+ const contribution = options.contribution;
1097
3137
  const requestedPackageLinkIntents = [...new Set(options.linkFrom ?? [])].map((consumerPackagePath) => ({
1098
3138
  consumerPackagePath,
1099
3139
  providerPackagePath: contribution.definition.path,
1100
3140
  }));
1101
- const conflictingPackage = options.blueprint.packages.find((existing) => existing.name === contribution.definition.name ||
3141
+ const conflictingPackage = persistedBlueprint.packages.find((existing) => existing.name === contribution.definition.name ||
1102
3142
  existing.path === contribution.definition.path);
1103
3143
  if (conflictingPackage !== undefined) {
1104
3144
  const isExactPackageDefinition = packageDefinitionsEqual(conflictingPackage, contribution.definition);
1105
- const existingPackageLinkIntents = options.blueprint.packageLinkIntents ?? [];
3145
+ const existingPackageLinkIntents = persistedBlueprint.packageLinkIntents ?? [];
1106
3146
  const missingPackageLinkIntent = requestedPackageLinkIntents.find((requested) => !existingPackageLinkIntents.some((existing) => packageLinkIntentsEqual(existing, requested)));
1107
3147
  if (isExactPackageDefinition && missingPackageLinkIntent === undefined) {
1108
3148
  const existing = readExistingPackageAdditionState(options);
1109
3149
  const plan = foundationPlan({
1110
3150
  definition: options.definition,
1111
- context: options.context,
1112
- blueprint: options.blueprint,
3151
+ context,
3152
+ blueprint: persistedBlueprint,
3153
+ foundationContribution: existing.foundationContribution,
1113
3154
  contributions: existing.contributions,
1114
3155
  renderContributions: [],
1115
- existingDeploymentEnvironmentNeeds: existing.deploymentEnvironmentNeeds,
3156
+ manifestTruthByPackagePath: existing.manifestTruthByPackagePath,
1116
3157
  generationRecord: existing.generationRecord,
1117
3158
  mode: "addition",
3159
+ rootNodeDeclaration,
1118
3160
  });
1119
3161
  const currentProjection = foundationPlan({
1120
3162
  definition: options.definition,
1121
- context: options.context,
1122
- blueprint: options.blueprint,
3163
+ context,
3164
+ blueprint: persistedBlueprint,
3165
+ foundationContribution: existing.foundationContribution,
1123
3166
  contributions: existing.contributions,
1124
- existingDeploymentEnvironmentNeeds: existing.deploymentEnvironmentNeeds,
1125
3167
  generationRecord: existing.generationRecord,
1126
3168
  mode: "initialization",
3169
+ rootNodeDeclaration,
1127
3170
  });
1128
3171
  return {
1129
3172
  ...plan,
@@ -1142,94 +3185,120 @@ export function planGeneratedRepositoryPackageAddition(options) {
1142
3185
  };
1143
3186
  }
1144
3187
  if (isExactPackageDefinition) {
1145
- throw new Error(`Package Addition conflicts because requested Package Link Intent ${missingPackageLinkIntent.consumerPackagePath} -> ${missingPackageLinkIntent.providerPackagePath} does not already exist`);
3188
+ throw new PackageAdditionBusinessConflict("missing-link", conflictingPackage, contribution.definition, missingPackageLinkIntent);
1146
3189
  }
1147
- throw new Error(`Package Addition conflicts with existing Package Definition ${conflictingPackage.name} at ${conflictingPackage.path} (${conflictingPackage.role}); requested ${contribution.definition.name} at ${contribution.definition.path} (${contribution.definition.role})`);
3190
+ throw new PackageAdditionBusinessConflict("identity", conflictingPackage, contribution.definition);
1148
3191
  }
3192
+ const contributionIdentity = requireReplayAdapter({
3193
+ owner: options.definition.metadata.name,
3194
+ adapters: options.definition.packageContributionReplayAdapters,
3195
+ identity: contribution.planningIdentity,
3196
+ }).identity;
3197
+ const persistedContributionDefinition = persistPackageDefinition({
3198
+ definition: contribution.definition,
3199
+ provenance: {
3200
+ definitionName: options.definition.metadata.name,
3201
+ planningContribution: "planPackageAddition",
3202
+ contributionIdentity,
3203
+ },
3204
+ occupiedIds: new Set(persistedBlueprint.packages.map((definition) => definition.packageDefinitionId)),
3205
+ });
1149
3206
  const blueprint = {
1150
- ...options.blueprint,
1151
- packages: [...options.blueprint.packages, contribution.definition],
3207
+ ...persistedBlueprint,
3208
+ packages: [...persistedBlueprint.packages, persistedContributionDefinition],
1152
3209
  ...(requestedPackageLinkIntents.length > 0
1153
3210
  ? {
1154
3211
  packageLinkIntents: [
1155
- ...(options.blueprint.packageLinkIntents ?? []),
3212
+ ...(persistedBlueprint.packageLinkIntents ?? []),
1156
3213
  ...requestedPackageLinkIntents,
1157
3214
  ],
1158
3215
  }
1159
3216
  : {}),
1160
3217
  };
1161
- assertProjectBlueprintV2(blueprint);
1162
- const manifestTruthPackagePaths = requestedPackageLinkIntents.length === 0
3218
+ assertProjectBlueprint(blueprint);
3219
+ const requiredManifestTruthPackagePaths = requestedPackageLinkIntents.length === 0
1163
3220
  ? []
1164
3221
  : [
1165
- ...(options.blueprint.packageLinkIntents ?? []).flatMap((intent) => [
3222
+ ...(persistedBlueprint.packageLinkIntents ?? []).flatMap((intent) => [
1166
3223
  intent.consumerPackagePath,
1167
3224
  intent.providerPackagePath,
1168
3225
  ]),
1169
3226
  ...requestedPackageLinkIntents.map((intent) => intent.consumerPackagePath),
1170
3227
  ];
1171
3228
  const existing = readExistingPackageAdditionState({
1172
- ...options,
1173
- manifestTruthPackagePaths,
3229
+ localTemplateMetadata: options.localTemplateMetadata,
3230
+ requiredManifestTruthPackagePaths,
1174
3231
  });
1175
3232
  const generationRecord = {
1176
3233
  ...existing.generationRecord,
1177
3234
  packages: [
1178
3235
  ...existing.generationRecord.packages,
1179
3236
  {
3237
+ packageDefinitionId: persistedContributionDefinition.packageDefinitionId,
1180
3238
  path: contribution.definition.path,
1181
3239
  definitionName: options.definition.metadata.name,
1182
3240
  planningContribution: "planPackageAddition",
3241
+ contributionIdentity,
1183
3242
  },
1184
3243
  ],
1185
3244
  };
1186
3245
  const beforeProjection = foundationPlan({
1187
3246
  definition: options.definition,
1188
- context: options.context,
1189
- blueprint: options.blueprint,
3247
+ context,
3248
+ blueprint: persistedBlueprint,
3249
+ foundationContribution: existing.foundationContribution,
1190
3250
  contributions: existing.contributions,
1191
- existingDeploymentEnvironmentNeeds: existing.deploymentEnvironmentNeeds,
1192
3251
  generationRecord: existing.generationRecord,
1193
3252
  mode: "initialization",
3253
+ rootNodeDeclaration,
1194
3254
  });
1195
3255
  const afterProjection = foundationPlan({
1196
3256
  definition: options.definition,
1197
- context: options.context,
3257
+ context,
1198
3258
  blueprint,
3259
+ foundationContribution: existing.foundationContribution,
1199
3260
  contributions: [...existing.contributions, contribution],
1200
- existingDeploymentEnvironmentNeeds: existing.deploymentEnvironmentNeeds,
1201
- ...(requestedPackageLinkIntents.length === 0
1202
- ? {}
1203
- : {
1204
- manifestTruthByPackagePath: existing.manifestTruthByPackagePath,
1205
- }),
3261
+ manifestTruthByPackagePath: existing.manifestTruthByPackagePath,
1206
3262
  generationRecord,
1207
3263
  mode: "initialization",
3264
+ rootNodeDeclaration,
1208
3265
  });
1209
3266
  const plan = foundationPlan({
1210
3267
  definition: options.definition,
1211
- context: options.context,
3268
+ context,
1212
3269
  blueprint,
3270
+ foundationContribution: existing.foundationContribution,
1213
3271
  contributions: [...existing.contributions, contribution],
1214
3272
  renderContributions: [contribution],
1215
- existingDeploymentEnvironmentNeeds: existing.deploymentEnvironmentNeeds,
1216
- ...(requestedPackageLinkIntents.length === 0
1217
- ? {}
1218
- : {
1219
- manifestTruthByPackagePath: existing.manifestTruthByPackagePath,
1220
- }),
3273
+ manifestTruthByPackagePath: existing.manifestTruthByPackagePath,
1221
3274
  generationRecord,
1222
3275
  mode: "addition",
3276
+ rootNodeDeclaration,
1223
3277
  });
3278
+ let beforeOperations = beforeProjection.operations;
3279
+ let afterOperations = afterProjection.operations;
3280
+ if (options.existingRootRustDeclaration !== undefined) {
3281
+ const preserveOperation = {
3282
+ kind: "writeText",
3283
+ to: rootRustDeclarationFileName,
3284
+ text: options.existingRootRustDeclaration,
3285
+ };
3286
+ beforeOperations = [...beforeProjection.operations, preserveOperation];
3287
+ afterOperations = afterProjection.operations.map((operation) => operation.kind === "writeTextTemplate" &&
3288
+ "to" in operation &&
3289
+ operation.to === rootRustDeclarationFileName
3290
+ ? preserveOperation
3291
+ : operation);
3292
+ }
1224
3293
  return {
1225
3294
  ...plan,
1226
3295
  projectProjections: {
1227
3296
  before: {
1228
- operations: beforeProjection.operations,
3297
+ operations: beforeOperations,
1229
3298
  reconciliation: beforeProjection.reconciliation,
1230
3299
  },
1231
3300
  after: {
1232
- operations: afterProjection.operations,
3301
+ operations: afterOperations,
1233
3302
  reconciliation: afterProjection.reconciliation,
1234
3303
  },
1235
3304
  preconditions: [
@@ -1242,3 +3311,215 @@ export function planGeneratedRepositoryPackageAddition(options) {
1242
3311
  },
1243
3312
  };
1244
3313
  }
3314
+ export function planGeneratedRepositoryPackageAddition(options) {
3315
+ const { context } = options.localTemplateMetadata;
3316
+ if (options.definition.planPackageAddition === undefined) {
3317
+ throw new Error(`Built-in Preset ${options.definition.metadata.name} does not support Package Addition`);
3318
+ }
3319
+ const packagePath = options.packagePath ??
3320
+ options.definition.defaultPackagePath?.({
3321
+ context,
3322
+ packageLeafName: options.packageLeafName,
3323
+ });
3324
+ if (packagePath === undefined) {
3325
+ throw new Error(`Built-in Preset ${options.definition.metadata.name} must own a default Package Path or receive an explicit Package Path`);
3326
+ }
3327
+ const contribution = options.definition.planPackageAddition({
3328
+ context,
3329
+ packageLeafName: options.packageLeafName,
3330
+ packagePath,
3331
+ });
3332
+ return planGeneratedRepositoryPackageAdditionFromPreparedContribution({
3333
+ ...options,
3334
+ packagePath,
3335
+ contribution,
3336
+ });
3337
+ }
3338
+ function collectPackageAdditionInput(options) {
3339
+ const issues = [];
3340
+ const definition = builtInPresetRegistry
3341
+ .all()
3342
+ .find((candidate) => candidate.metadata.name === options.preset);
3343
+ if (definition === undefined)
3344
+ issues.push({ code: "PRESET_UNKNOWN" });
3345
+ else if (definition.planPackageAddition === undefined)
3346
+ issues.push({ code: "PRESET_NOT_ADDABLE" });
3347
+ if (!isValidNewNpmPackageName(`@x/${options.packageLeafName}`)) {
3348
+ issues.push({ code: "INVALID_PACKAGE_NAME" });
3349
+ }
3350
+ if (options.packagePath !== undefined) {
3351
+ const validation = validateNewPackagePath(options.packagePath);
3352
+ if (!validation.hasValidShape)
3353
+ issues.push({ code: "INVALID_PACKAGE_PATH" });
3354
+ if (validation.reservedWorkspaceCollection !== undefined) {
3355
+ issues.push({ code: "RESERVED_PACKAGE_PATH" });
3356
+ }
3357
+ }
3358
+ const linkFrom = [...new Set(options.linkFrom ?? [])];
3359
+ for (const consumerPackagePath of linkFrom) {
3360
+ const validation = validateNewPackagePath(consumerPackagePath);
3361
+ if (!validation.hasValidShape) {
3362
+ issues.push({ code: "INVALID_LINK_FROM" });
3363
+ }
3364
+ if (validation.reservedWorkspaceCollection !== undefined)
3365
+ issues.push({ code: "RESERVED_LINK_FROM" });
3366
+ }
3367
+ if (issues.length > 0 || definition === undefined) {
3368
+ return { status: "input-invalid", issues };
3369
+ }
3370
+ return { status: "valid", definition, linkFrom };
3371
+ }
3372
+ /**
3373
+ * Command-owned preparation: user input is checked before local metadata or any
3374
+ * Preset default/planner work; all remaining failures are deliberately bounded.
3375
+ */
3376
+ export function prepareGeneratedRepositoryPackageAddition(options) {
3377
+ const input = collectPackageAdditionInput(options);
3378
+ if (input.status === "input-invalid")
3379
+ return input;
3380
+ let localTemplateMetadata;
3381
+ try {
3382
+ localTemplateMetadata = loadLocalTemplateMetadata(options.repositoryRoot);
3383
+ }
3384
+ catch (error) {
3385
+ if (error instanceof PackageAdditionTargetDeclarationFailure) {
3386
+ return {
3387
+ status: "operation-failure",
3388
+ phase: "metadata",
3389
+ diagnostic: { message: error.message, suggestion: error.suggestion },
3390
+ };
3391
+ }
3392
+ return { status: "operation-failure", phase: "metadata" };
3393
+ }
3394
+ if (input.linkFrom.some((consumerPackagePath) => !localTemplateMetadata.blueprint.packages.some((candidate) => candidate.path === consumerPackagePath))) {
3395
+ return {
3396
+ status: "input-invalid",
3397
+ issues: [{ code: "UNKNOWN_LINK_FROM" }],
3398
+ };
3399
+ }
3400
+ let packagePath = options.packagePath;
3401
+ if (packagePath === undefined) {
3402
+ try {
3403
+ packagePath = input.definition.defaultPackagePath?.({
3404
+ context: localTemplateMetadata.context,
3405
+ packageLeafName: options.packageLeafName,
3406
+ });
3407
+ }
3408
+ catch {
3409
+ return { status: "operation-failure", phase: "default" };
3410
+ }
3411
+ const defaultPathValidation = packagePath === undefined
3412
+ ? undefined
3413
+ : validateNewPackagePath(packagePath);
3414
+ if (defaultPathValidation === undefined ||
3415
+ !defaultPathValidation.hasValidShape ||
3416
+ defaultPathValidation.reservedWorkspaceCollection !== undefined) {
3417
+ return { status: "operation-failure", phase: "default" };
3418
+ }
3419
+ }
3420
+ if (packagePath === undefined) {
3421
+ return { status: "operation-failure", phase: "default" };
3422
+ }
3423
+ let provider;
3424
+ try {
3425
+ provider = input.definition.planPackageAddition({
3426
+ context: localTemplateMetadata.context,
3427
+ packageLeafName: options.packageLeafName,
3428
+ packagePath,
3429
+ });
3430
+ }
3431
+ catch {
3432
+ return { status: "operation-failure", phase: "planning" };
3433
+ }
3434
+ // 首次引入 Rust 的加包按目标事实二选一:已有合法根声明由该声明拥有版本并原正文保留;
3435
+ // 没有根声明才以当前 CLI 已验证快照建源。已有 Rust 能力的仓库在 loadLocalTemplateMetadata
3436
+ // 已由根 channel 重放(缺真源在那里失败),不进入这条路径;不可解释的声明在此可行动失败,
3437
+ // 不用快照掩盖。非 Rust 加包不读无关根文件。
3438
+ let additionMetadata = localTemplateMetadata;
3439
+ let preservedRootRustDeclaration;
3440
+ if (provider.foundation.toolchains.rust !== undefined &&
3441
+ localTemplateMetadata.context.toolchain.rustVersion === undefined) {
3442
+ const repositoryRoot = localTemplateMetadata.context.targetDir;
3443
+ const rootDeclarationPath = path.join(repositoryRoot, rootRustDeclarationFileName);
3444
+ const existingDeclaration = existsSync(rootDeclarationPath)
3445
+ ? readFileSync(rootDeclarationPath, "utf8")
3446
+ : undefined;
3447
+ let rustVersion;
3448
+ try {
3449
+ if (existingDeclaration === undefined) {
3450
+ rustVersion = releaseToolchainSnapshot.rustVersion;
3451
+ }
3452
+ else {
3453
+ rustVersion = readPackageAdditionTargetRustChannel(repositoryRoot);
3454
+ preservedRootRustDeclaration = existingDeclaration;
3455
+ }
3456
+ }
3457
+ catch (error) {
3458
+ if (error instanceof PackageAdditionTargetDeclarationFailure) {
3459
+ return {
3460
+ status: "operation-failure",
3461
+ phase: "metadata",
3462
+ diagnostic: { message: error.message, suggestion: error.suggestion },
3463
+ };
3464
+ }
3465
+ return { status: "operation-failure", phase: "metadata" };
3466
+ }
3467
+ additionMetadata = {
3468
+ ...localTemplateMetadata,
3469
+ context: {
3470
+ ...localTemplateMetadata.context,
3471
+ toolchain: {
3472
+ ...localTemplateMetadata.context.toolchain,
3473
+ rustVersion,
3474
+ },
3475
+ },
3476
+ };
3477
+ try {
3478
+ provider = input.definition.planPackageAddition({
3479
+ context: additionMetadata.context,
3480
+ packageLeafName: options.packageLeafName,
3481
+ packagePath,
3482
+ });
3483
+ }
3484
+ catch {
3485
+ return { status: "operation-failure", phase: "planning" };
3486
+ }
3487
+ }
3488
+ const contributionsByPath = new Map(localTemplateMetadata[localTemplateMetadataStateKey].packageContributions.map((contribution) => [
3489
+ contribution.definition.path,
3490
+ contribution,
3491
+ ]));
3492
+ if (input.linkFrom.length > 0 &&
3493
+ (!canProvideSourceConditionPackageNameImport(provider) ||
3494
+ input.linkFrom.some((consumerPackagePath) => {
3495
+ const consumer = contributionsByPath.get(consumerPackagePath);
3496
+ return (consumer === undefined ||
3497
+ !canConsumeNodePackageNameImport(consumer) ||
3498
+ !canLinkNodePackageRoles(consumer.definition.role, provider.definition.role));
3499
+ }))) {
3500
+ return { status: "input-invalid", issues: [{ code: "UNSUPPORTED_LINK" }] };
3501
+ }
3502
+ try {
3503
+ return {
3504
+ status: "ready",
3505
+ definition: input.definition,
3506
+ plan: planGeneratedRepositoryPackageAdditionFromPreparedContribution({
3507
+ definition: input.definition,
3508
+ localTemplateMetadata: additionMetadata,
3509
+ packageLeafName: options.packageLeafName,
3510
+ packagePath,
3511
+ contribution: provider,
3512
+ ...(input.linkFrom.length === 0 ? {} : { linkFrom: input.linkFrom }),
3513
+ ...(preservedRootRustDeclaration === undefined
3514
+ ? {}
3515
+ : { existingRootRustDeclaration: preservedRootRustDeclaration }),
3516
+ }),
3517
+ };
3518
+ }
3519
+ catch (error) {
3520
+ if (error instanceof PackageAdditionBusinessConflict) {
3521
+ return { status: "conflict", conflict: error };
3522
+ }
3523
+ return { status: "operation-failure", phase: "planning" };
3524
+ }
3525
+ }