@starci/hfs 4.11.22 → 4.12.2

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 (1088) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +31 -31
  3. package/ci/cli.d.mts +15 -0
  4. package/ci/cli.mjs +71 -52
  5. package/ci/github.d.mts +43 -0
  6. package/ci/github.mjs +33 -28
  7. package/ci/local.d.mts +12 -0
  8. package/ci/local.mjs +145 -108
  9. package/ci/secret.d.mts +15 -0
  10. package/ci/secret.mjs +31 -21
  11. package/ci/vars.d.mts +17 -0
  12. package/ci/vars.mjs +47 -33
  13. package/ci/verify.d.mts +18 -0
  14. package/ci/verify.mjs +52 -40
  15. package/codemod/button-intent.d.mts +63 -0
  16. package/codemod/button-intent.mjs +338 -285
  17. package/coverage/cli.d.mts +28 -0
  18. package/coverage/cli.mjs +65 -51
  19. package/db/backup-receipt.d.mts +28 -0
  20. package/db/backup-receipt.mjs +78 -58
  21. package/db/drift.d.mts +86 -0
  22. package/db/drift.mjs +213 -180
  23. package/db/dump.d.mts +52 -0
  24. package/db/dump.mjs +63 -56
  25. package/db/entity-list.d.mts +4 -0
  26. package/db/entity-list.mjs +0 -2
  27. package/db/image.d.mts +8 -0
  28. package/db/image.mjs +1 -2
  29. package/db/migrate.d.mts +104 -0
  30. package/db/migrate.mjs +207 -167
  31. package/db/new.d.mts +11 -0
  32. package/db/new.mjs +25 -25
  33. package/db/post-cutover.d.mts +5 -0
  34. package/db/post-cutover.mjs +89 -82
  35. package/db/postgres.d.mts +71 -0
  36. package/db/postgres.mjs +62 -61
  37. package/emit/compiler.d.mts +3 -0
  38. package/emit/compiler.mjs +25 -27
  39. package/emit/contracts.d.mts +35 -0
  40. package/emit/contracts.mjs +46 -50
  41. package/emit/events.d.mts +9 -0
  42. package/emit/events.mjs +19 -20
  43. package/emit/form-bounds.d.mts +83 -0
  44. package/emit/form-bounds.mjs +133 -117
  45. package/emit/graphql-input-bounds.d.mts +63 -0
  46. package/emit/graphql-input-bounds.mjs +90 -79
  47. package/emit/input-bounds.d.mts +30 -0
  48. package/emit/input-bounds.mjs +29 -27
  49. package/emit/operation-schemas.d.mts +24 -0
  50. package/emit/operation-schemas.mjs +136 -116
  51. package/emit/operations-worker.d.mts +1 -0
  52. package/emit/operations-worker.mjs +9 -7
  53. package/emit/operations.d.mts +47 -0
  54. package/emit/operations.mjs +124 -133
  55. package/emit/schema-worker.d.mts +1 -0
  56. package/emit/schema-worker.mjs +57 -50
  57. package/emit/static-graph.d.mts +48 -0
  58. package/emit/static-graph.mjs +766 -640
  59. package/emit/type-schema.d.mts +29 -0
  60. package/emit/type-schema.mjs +153 -140
  61. package/lint/bound-sys.cjs +27 -33
  62. package/lint/chunk.d.mts +17 -0
  63. package/lint/chunk.mjs +41 -31
  64. package/lint/run.d.mts +120 -0
  65. package/lint/run.mjs +414 -325
  66. package/package.json +21 -4
  67. package/release/candidate-ci.d.mts +46 -0
  68. package/release/candidate-ci.mjs +76 -70
  69. package/release/gate.d.mts +120 -0
  70. package/release/gate.mjs +358 -330
  71. package/release/index.d.mts +68 -0
  72. package/release/index.mjs +95 -73
  73. package/release/lint-report.d.mts +14 -0
  74. package/release/lint-report.mjs +33 -32
  75. package/release/push.d.mts +32 -0
  76. package/release/push.mjs +92 -79
  77. package/release/records.d.mts +18 -0
  78. package/release/records.mjs +22 -21
  79. package/release/sonar-quality-gate.d.mts +18 -0
  80. package/release/sonar-quality-gate.mjs +60 -52
  81. package/release/urgent.d.mts +20 -0
  82. package/release/urgent.mjs +76 -74
  83. package/report/order.d.mts +1 -0
  84. package/report/sonar.d.mts +73 -0
  85. package/report/sonar.mjs +82 -89
  86. package/runtime/engine/admission.d.mts +209 -0
  87. package/runtime/engine/admission.mjs +225 -204
  88. package/runtime/engine/by-code-unit.d.mts +5 -0
  89. package/runtime/engine/by-code-unit.mjs +6 -6
  90. package/runtime/engine/config.d.mts +333 -0
  91. package/runtime/engine/config.mjs +486 -328
  92. package/runtime/engine/db/blob.d.mts +83 -0
  93. package/runtime/engine/db/blob.mjs +344 -268
  94. package/runtime/engine/db/event-compact.d.mts +21 -0
  95. package/runtime/engine/db/event-compact.mjs +34 -38
  96. package/runtime/engine/db/machine-connection.d.mts +68 -0
  97. package/runtime/engine/db/machine-connection.mjs +166 -119
  98. package/runtime/engine/db/machine-open.d.mts +26 -0
  99. package/runtime/engine/db/machine-open.mjs +59 -45
  100. package/runtime/engine/db/machine-schema.d.mts +34 -0
  101. package/runtime/engine/db/machine-schema.mjs +102 -83
  102. package/runtime/engine/db/machine.d.mts +1746 -0
  103. package/runtime/engine/db/machine.mjs +1040 -734
  104. package/runtime/engine/db/provider-reservations.d.mts +169 -0
  105. package/runtime/engine/db/provider-reservations.mjs +141 -119
  106. package/runtime/engine/db/provision-lock.d.mts +23 -0
  107. package/runtime/engine/db/provision-lock.mjs +14 -14
  108. package/runtime/engine/db/ref-value.d.mts +19 -0
  109. package/runtime/engine/db/ref-value.mjs +36 -35
  110. package/runtime/engine/db/sqlite-types.d.mts +28 -0
  111. package/runtime/engine/db/sqlite-types.mjs +4 -0
  112. package/runtime/engine/digest.d.mts +4 -0
  113. package/runtime/engine/digest.mjs +16 -7
  114. package/runtime/engine/invalid-config.d.mts +13 -0
  115. package/runtime/engine/invalid-config.mjs +17 -11
  116. package/runtime/engine/model-config.d.mts +91 -0
  117. package/runtime/engine/model-config.mjs +98 -76
  118. package/runtime/engine/orca-config.d.mts +26 -0
  119. package/runtime/engine/orca-config.mjs +22 -17
  120. package/runtime/engine/plain-object.d.mts +2 -0
  121. package/runtime/engine/refuse.d.mts +9 -0
  122. package/runtime/engine/refuse.mjs +3 -6
  123. package/runtime/engine/release-config.d.mts +19 -0
  124. package/runtime/engine/release-config.mjs +22 -18
  125. package/runtime/engine/removed-vocabulary.d.mts +12 -0
  126. package/runtime/engine/removed-vocabulary.mjs +21 -20
  127. package/runtime/engine/resources-config.d.mts +34 -0
  128. package/runtime/engine/resources-config.mjs +42 -35
  129. package/runtime/engine/runtime-root.d.mts +28 -0
  130. package/runtime/engine/runtime-root.mjs +11 -13
  131. package/runtime/engine/secrets.d.mts +41 -0
  132. package/runtime/engine/secrets.mjs +170 -102
  133. package/runtime/engine/sonar-config.d.mts +10 -0
  134. package/runtime/engine/sonar-config.mjs +16 -13
  135. package/runtime/engine/temp-root.d.mts +17 -0
  136. package/runtime/engine/temp-root.mjs +3 -9
  137. package/runtime/engine/yaml.d.mts +9 -0
  138. package/runtime/knowledge/hfs/canon-pins.yaml +10 -10
  139. package/runtime/knowledge/hfs/ci-standard.yaml +2 -2
  140. package/runtime/knowledge/hfs/rules.yaml +95 -6
  141. package/runtime/knowledge/hfs/slots.yaml +3 -3
  142. package/runtime/knowledge/sonar-gate.yaml +1 -1
  143. package/runtime/modules/kernel/failure-codes.yaml +43 -32
  144. package/runtime/modules/schemas/application-stacks.schema.yaml +3 -3
  145. package/runtime/packages/cli/src/catalog.generated.d.mts +13 -0
  146. package/runtime/packages/cli/src/catalog.generated.mjs +1853 -14824
  147. package/runtime/packages/cli/src/validate-args.d.mts +74 -0
  148. package/runtime/packages/cli/src/validate-args.mjs +183 -171
  149. package/runtime/packages/jest-preset/sonar-exclusions.cjs +5 -5
  150. package/runtime/scripts/api/fs/claim-file.d.mts +12 -0
  151. package/runtime/scripts/api/fs/claim-file.mjs +31 -17
  152. package/runtime/scripts/api/fs/ensure-temp-root.d.mts +4 -0
  153. package/runtime/scripts/api/fs/ensure-temp-root.mjs +15 -14
  154. package/runtime/scripts/api/fs/forbidden-root.d.mts +15 -0
  155. package/runtime/scripts/api/fs/forbidden-root.mjs +31 -23
  156. package/runtime/scripts/api/fs/is-link-like.d.mts +10 -0
  157. package/runtime/scripts/api/fs/is-link-like.mjs +25 -11
  158. package/runtime/scripts/api/fs/lib.d.mts +12 -0
  159. package/runtime/scripts/api/fs/lib.mjs +28 -8
  160. package/runtime/scripts/api/fs/make-temp-dir.d.mts +5 -0
  161. package/runtime/scripts/api/fs/make-temp-dir.mjs +3 -4
  162. package/runtime/scripts/api/fs/rename-over.d.mts +13 -0
  163. package/runtime/scripts/api/fs/rename-over.mjs +16 -10
  164. package/runtime/scripts/api/fs/safe-remove.d.mts +25 -0
  165. package/runtime/scripts/api/fs/safe-remove.mjs +129 -71
  166. package/runtime/scripts/api/git/add.d.mts +3 -0
  167. package/runtime/scripts/api/git/add.mjs +0 -1
  168. package/runtime/scripts/api/git/cat-file.d.mts +3 -0
  169. package/runtime/scripts/api/git/cat-file.mjs +0 -1
  170. package/runtime/scripts/api/git/check-ignore.d.mts +3 -0
  171. package/runtime/scripts/api/git/check-ignore.mjs +0 -1
  172. package/runtime/scripts/api/git/commit-tree.d.mts +3 -0
  173. package/runtime/scripts/api/git/commit-tree.mjs +0 -1
  174. package/runtime/scripts/api/git/config-get.d.mts +10 -0
  175. package/runtime/scripts/api/git/config-get.mjs +1 -2
  176. package/runtime/scripts/api/git/diff.d.mts +3 -0
  177. package/runtime/scripts/api/git/diff.mjs +0 -1
  178. package/runtime/scripts/api/git/init.d.mts +7 -0
  179. package/runtime/scripts/api/git/init.mjs +1 -2
  180. package/runtime/scripts/api/git/is-ancestor.d.mts +5 -0
  181. package/runtime/scripts/api/git/is-ancestor.mjs +0 -1
  182. package/runtime/scripts/api/git/lib.d.mts +67 -0
  183. package/runtime/scripts/api/git/lib.mjs +32 -32
  184. package/runtime/scripts/api/git/ls-files.d.mts +3 -0
  185. package/runtime/scripts/api/git/ls-files.mjs +0 -1
  186. package/runtime/scripts/api/git/ls-tree.d.mts +3 -0
  187. package/runtime/scripts/api/git/ls-tree.mjs +0 -1
  188. package/runtime/scripts/api/git/merge-base.d.mts +5 -0
  189. package/runtime/scripts/api/git/merge-base.mjs +2 -3
  190. package/runtime/scripts/api/git/remote.d.mts +3 -0
  191. package/runtime/scripts/api/git/remote.mjs +0 -1
  192. package/runtime/scripts/api/git/rev-parse-query.d.mts +3 -0
  193. package/runtime/scripts/api/git/rev-parse-query.mjs +0 -1
  194. package/runtime/scripts/api/git/show.d.mts +3 -0
  195. package/runtime/scripts/api/git/show.mjs +0 -1
  196. package/runtime/scripts/api/git/tag.d.mts +3 -0
  197. package/runtime/scripts/api/git/tag.mjs +0 -1
  198. package/runtime/scripts/api/git/update-ref.d.mts +7 -0
  199. package/runtime/scripts/api/git/update-ref.mjs +1 -2
  200. package/runtime/scripts/api/git/write-tree.d.mts +3 -0
  201. package/runtime/scripts/api/git/write-tree.mjs +0 -1
  202. package/runtime/scripts/api/node/lib.d.mts +7 -0
  203. package/runtime/scripts/api/node/lib.mjs +17 -7
  204. package/runtime/scripts/api/node/run-node.d.mts +3 -0
  205. package/runtime/scripts/api/node/run-node.mjs +0 -3
  206. package/runtime/scripts/api/process/resolve-real-tool.d.mts +12 -0
  207. package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -38
  208. package/runtime/scripts/api/process/run-program.d.mts +3 -0
  209. package/runtime/scripts/api/process/run-program.mjs +5 -2
  210. package/runtime/scripts/api/sops/decrypt.d.mts +9 -0
  211. package/runtime/scripts/api/sops/decrypt.mjs +1 -2
  212. package/runtime/scripts/api/sops/lib.d.mts +149 -0
  213. package/runtime/scripts/api/sops/lib.mjs +417 -318
  214. package/runtime/scripts/api/sops/resolve-sops.d.mts +3 -0
  215. package/runtime/scripts/api/sops/resolve-sops.mjs +1 -2
  216. package/runtime/scripts/api/sops/seal.d.mts +19 -0
  217. package/runtime/scripts/api/sops/seal.mjs +14 -10
  218. package/runtime/scripts/api/sops/selected-age-recipient.d.mts +3 -0
  219. package/runtime/scripts/api/sops/selected-age-recipient.mjs +1 -2
  220. package/runtime/scripts/api/sops/update-keys.d.mts +16 -0
  221. package/runtime/scripts/api/sops/update-keys.mjs +11 -8
  222. package/runtime/scripts/cli/gen-catalog.d.mts +42 -0
  223. package/runtime/scripts/cli/gen-catalog.mjs +72 -0
  224. package/runtime/scripts/gates/runtime-host.d.mts +23 -0
  225. package/runtime/scripts/gates/runtime-host.mjs +48 -41
  226. package/runtime/scripts/gates/sonar-gate.d.mts +219 -0
  227. package/runtime/scripts/gates/sonar-gate.mjs +166 -153
  228. package/runtime/scripts/gates/starcistacks-ci.d.mts +35 -0
  229. package/runtime/scripts/gates/starcistacks-ci.mjs +47 -39
  230. package/runtime/scripts/gates/starcistacks-form.d.mts +80 -0
  231. package/runtime/scripts/gates/starcistacks-form.mjs +16 -14
  232. package/runtime/scripts/gates/starcistacks-runtime.d.mts +1 -0
  233. package/runtime/scripts/gates/starcistacks-value-file.d.mts +2 -0
  234. package/runtime/scripts/gates/starcistacks-value-file.mjs +14 -11
  235. package/runtime/scripts/gates/starcistacks.d.mts +141 -0
  236. package/runtime/scripts/gates/starcistacks.mjs +470 -355
  237. package/runtime/scripts/guards/git-pathspec.d.mts +48 -0
  238. package/runtime/scripts/guards/git-pathspec.mjs +215 -130
  239. package/runtime/scripts/guards/git-policy.d.mts +30 -0
  240. package/runtime/scripts/guards/git-policy.mjs +278 -235
  241. package/runtime/scripts/guards/hook-io.d.mts +22 -0
  242. package/runtime/scripts/guards/hook-io.mjs +77 -63
  243. package/runtime/scripts/guards/push-scan.d.mts +31 -0
  244. package/runtime/scripts/guards/push-scan.mjs +93 -80
  245. package/runtime/scripts/guards/release-push-gate.d.mts +22 -0
  246. package/runtime/scripts/guards/release-push-gate.mjs +40 -38
  247. package/runtime/scripts/hfs/allows.d.mts +24 -0
  248. package/runtime/scripts/hfs/allows.mjs +37 -38
  249. package/runtime/scripts/hfs/app-wiring.d.mts +72 -0
  250. package/runtime/scripts/hfs/app-wiring.mjs +197 -167
  251. package/runtime/scripts/hfs/architecture/ast-walks.d.mts +89 -0
  252. package/runtime/scripts/hfs/architecture/ast-walks.mjs +180 -163
  253. package/runtime/scripts/hfs/architecture/automatic-gates.d.mts +21 -0
  254. package/runtime/scripts/hfs/architecture/automatic-gates.mjs +80 -73
  255. package/runtime/scripts/hfs/architecture/backend-app-files.d.mts +10 -0
  256. package/runtime/scripts/hfs/architecture/backend-app-files.mjs +88 -77
  257. package/runtime/scripts/hfs/architecture/backend.d.mts +5 -0
  258. package/runtime/scripts/hfs/architecture/backend.mjs +378 -357
  259. package/runtime/scripts/hfs/architecture/background-unowned.d.mts +25 -0
  260. package/runtime/scripts/hfs/architecture/background-unowned.mjs +201 -187
  261. package/runtime/scripts/hfs/architecture/canon-clones.d.mts +8 -0
  262. package/runtime/scripts/hfs/architecture/canon-clones.mjs +260 -209
  263. package/runtime/scripts/hfs/architecture/canon-jsx-clones.d.mts +5 -0
  264. package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +149 -116
  265. package/runtime/scripts/hfs/architecture/client-reaches-server.d.mts +28 -0
  266. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +72 -68
  267. package/runtime/scripts/hfs/architecture/clones.d.mts +54 -0
  268. package/runtime/scripts/hfs/architecture/clones.mjs +212 -217
  269. package/runtime/scripts/hfs/architecture/config-unread.d.mts +14 -0
  270. package/runtime/scripts/hfs/architecture/config-unread.mjs +7 -9
  271. package/runtime/scripts/hfs/architecture/config.d.mts +74 -0
  272. package/runtime/scripts/hfs/architecture/config.mjs +302 -268
  273. package/runtime/scripts/hfs/architecture/connection-map.d.mts +33 -0
  274. package/runtime/scripts/hfs/architecture/connection-map.mjs +258 -225
  275. package/runtime/scripts/hfs/architecture/constructor-deps.d.mts +57 -0
  276. package/runtime/scripts/hfs/architecture/constructor-deps.mjs +80 -71
  277. package/runtime/scripts/hfs/architecture/context-coupling.d.mts +21 -0
  278. package/runtime/scripts/hfs/architecture/context-coupling.mjs +82 -77
  279. package/runtime/scripts/hfs/architecture/context-map.d.mts +102 -0
  280. package/runtime/scripts/hfs/architecture/context-map.mjs +267 -234
  281. package/runtime/scripts/hfs/architecture/context-owner.d.mts +15 -0
  282. package/runtime/scripts/hfs/architecture/context-owner.mjs +73 -61
  283. package/runtime/scripts/hfs/architecture/context-platform-tables.d.mts +18 -0
  284. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -43
  285. package/runtime/scripts/hfs/architecture/context-transaction.d.mts +20 -0
  286. package/runtime/scripts/hfs/architecture/context-transaction.mjs +54 -52
  287. package/runtime/scripts/hfs/architecture/contract-fixture-guard.d.mts +37 -0
  288. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +113 -104
  289. package/runtime/scripts/hfs/architecture/contracts-readonly.d.mts +32 -0
  290. package/runtime/scripts/hfs/architecture/contracts-readonly.mjs +288 -270
  291. package/runtime/scripts/hfs/architecture/contracts.d.mts +30 -0
  292. package/runtime/scripts/hfs/architecture/contracts.mjs +408 -393
  293. package/runtime/scripts/hfs/architecture/cross-app-duplicate.d.mts +27 -0
  294. package/runtime/scripts/hfs/architecture/cross-app-duplicate.mjs +50 -51
  295. package/runtime/scripts/hfs/architecture/dead-exports-bindings.d.mts +21 -0
  296. package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +143 -119
  297. package/runtime/scripts/hfs/architecture/dead-exports.d.mts +32 -0
  298. package/runtime/scripts/hfs/architecture/dead-exports.mjs +286 -228
  299. package/runtime/scripts/hfs/architecture/default-deny.d.mts +21 -0
  300. package/runtime/scripts/hfs/architecture/default-deny.mjs +129 -110
  301. package/runtime/scripts/hfs/architecture/doc-language.d.mts +17 -0
  302. package/runtime/scripts/hfs/architecture/doc-language.mjs +24 -19
  303. package/runtime/scripts/hfs/architecture/entity-registry.d.mts +49 -0
  304. package/runtime/scripts/hfs/architecture/entity-registry.mjs +20 -22
  305. package/runtime/scripts/hfs/architecture/entrypoint.d.mts +13 -0
  306. package/runtime/scripts/hfs/architecture/entrypoint.mjs +47 -45
  307. package/runtime/scripts/hfs/architecture/error-codes.d.mts +16 -0
  308. package/runtime/scripts/hfs/architecture/error-codes.mjs +37 -35
  309. package/runtime/scripts/hfs/architecture/error-masked.d.mts +16 -0
  310. package/runtime/scripts/hfs/architecture/error-masked.mjs +55 -59
  311. package/runtime/scripts/hfs/architecture/fe-slot-allows.d.mts +38 -0
  312. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +24 -23
  313. package/runtime/scripts/hfs/architecture/feature-shape.d.mts +26 -0
  314. package/runtime/scripts/hfs/architecture/feature-shape.mjs +40 -38
  315. package/runtime/scripts/hfs/architecture/framework-pinned.d.mts +3 -0
  316. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +21 -21
  317. package/runtime/scripts/hfs/architecture/frontend-block-render.d.mts +26 -0
  318. package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +106 -98
  319. package/runtime/scripts/hfs/architecture/frontend-grammar.d.mts +7 -0
  320. package/runtime/scripts/hfs/architecture/frontend-grammar.mjs +153 -150
  321. package/runtime/scripts/hfs/architecture/frontend-routing.d.mts +23 -0
  322. package/runtime/scripts/hfs/architecture/frontend-routing.mjs +161 -149
  323. package/runtime/scripts/hfs/architecture/frontend-world-render.d.mts +72 -0
  324. package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +343 -305
  325. package/runtime/scripts/hfs/architecture/frontend-world.d.mts +94 -0
  326. package/runtime/scripts/hfs/architecture/frontend-world.mjs +340 -294
  327. package/runtime/scripts/hfs/architecture/frontend.d.mts +31 -0
  328. package/runtime/scripts/hfs/architecture/frontend.mjs +174 -184
  329. package/runtime/scripts/hfs/architecture/function-spec-providers.d.mts +27 -0
  330. package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +124 -106
  331. package/runtime/scripts/hfs/architecture/hfs-graph.d.mts +78 -0
  332. package/runtime/scripts/hfs/architecture/hfs-graph.mjs +52 -48
  333. package/runtime/scripts/hfs/architecture/hfs.d.mts +135 -0
  334. package/runtime/scripts/hfs/architecture/hfs.mjs +328 -282
  335. package/runtime/scripts/hfs/architecture/hooks-are-hooks.d.mts +24 -0
  336. package/runtime/scripts/hfs/architecture/hooks-are-hooks.mjs +81 -71
  337. package/runtime/scripts/hfs/architecture/i18n-keys.d.mts +31 -0
  338. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +155 -141
  339. package/runtime/scripts/hfs/architecture/identity.d.mts +7 -0
  340. package/runtime/scripts/hfs/architecture/identity.mjs +141 -125
  341. package/runtime/scripts/hfs/architecture/index.d.mts +101 -0
  342. package/runtime/scripts/hfs/architecture/index.mjs +272 -272
  343. package/runtime/scripts/hfs/architecture/injection-token-exported.d.mts +21 -0
  344. package/runtime/scripts/hfs/architecture/injection-token-exported.mjs +45 -43
  345. package/runtime/scripts/hfs/architecture/jwt-ast.d.mts +16 -0
  346. package/runtime/scripts/hfs/architecture/jwt-ast.mjs +195 -176
  347. package/runtime/scripts/hfs/architecture/machine-ast.d.mts +88 -0
  348. package/runtime/scripts/hfs/architecture/machine-ast.mjs +163 -155
  349. package/runtime/scripts/hfs/architecture/managed-scripts.d.mts +2 -0
  350. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +19 -20
  351. package/runtime/scripts/hfs/architecture/module-per-transport.d.mts +35 -0
  352. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +177 -172
  353. package/runtime/scripts/hfs/architecture/next-data-contract.d.mts +35 -0
  354. package/runtime/scripts/hfs/architecture/next-data-contract.mjs +100 -78
  355. package/runtime/scripts/hfs/architecture/next-data-inference.d.mts +39 -0
  356. package/runtime/scripts/hfs/architecture/next-data-inference.mjs +170 -154
  357. package/runtime/scripts/hfs/architecture/next-data-key.d.mts +50 -0
  358. package/runtime/scripts/hfs/architecture/next-data-key.mjs +311 -275
  359. package/runtime/scripts/hfs/architecture/next-data-symbols.d.mts +5 -0
  360. package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +17 -17
  361. package/runtime/scripts/hfs/architecture/next-data.d.mts +36 -0
  362. package/runtime/scripts/hfs/architecture/next-data.mjs +351 -334
  363. package/runtime/scripts/hfs/architecture/operation-contract-roots.d.mts +10 -0
  364. package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +39 -37
  365. package/runtime/scripts/hfs/architecture/owners.d.mts +5 -0
  366. package/runtime/scripts/hfs/architecture/owners.mjs +97 -98
  367. package/runtime/scripts/hfs/architecture/package-shape.d.mts +26 -0
  368. package/runtime/scripts/hfs/architecture/package-shape.mjs +56 -55
  369. package/runtime/scripts/hfs/architecture/presentation.d.mts +24 -0
  370. package/runtime/scripts/hfs/architecture/presentation.mjs +138 -130
  371. package/runtime/scripts/hfs/architecture/reachability.d.mts +25 -0
  372. package/runtime/scripts/hfs/architecture/reachability.mjs +258 -241
  373. package/runtime/scripts/hfs/architecture/register-once.d.mts +18 -0
  374. package/runtime/scripts/hfs/architecture/register-once.mjs +152 -139
  375. package/runtime/scripts/hfs/architecture/registration.d.mts +15 -0
  376. package/runtime/scripts/hfs/architecture/registration.mjs +301 -267
  377. package/runtime/scripts/hfs/architecture/required-files.d.mts +64 -0
  378. package/runtime/scripts/hfs/architecture/required-files.mjs +172 -167
  379. package/runtime/scripts/hfs/architecture/route-files-thin.d.mts +23 -0
  380. package/runtime/scripts/hfs/architecture/route-files-thin.mjs +85 -77
  381. package/runtime/scripts/hfs/architecture/schema-owner.d.mts +34 -0
  382. package/runtime/scripts/hfs/architecture/schema-owner.mjs +206 -181
  383. package/runtime/scripts/hfs/architecture/server-action.d.mts +22 -0
  384. package/runtime/scripts/hfs/architecture/server-action.mjs +48 -48
  385. package/runtime/scripts/hfs/architecture/side-boundary.d.mts +3 -0
  386. package/runtime/scripts/hfs/architecture/side-boundary.mjs +2 -5
  387. package/runtime/scripts/hfs/architecture/source-names-shape.d.mts +85 -0
  388. package/runtime/scripts/hfs/architecture/source-names-shape.mjs +261 -259
  389. package/runtime/scripts/hfs/architecture/source-names.d.mts +7 -0
  390. package/runtime/scripts/hfs/architecture/source-names.mjs +304 -278
  391. package/runtime/scripts/hfs/architecture/sql-keys.d.mts +5 -0
  392. package/runtime/scripts/hfs/architecture/sql-keys.mjs +277 -194
  393. package/runtime/scripts/hfs/architecture/sql-owner.d.mts +30 -0
  394. package/runtime/scripts/hfs/architecture/sql-owner.mjs +236 -194
  395. package/runtime/scripts/hfs/architecture/sql-returning.d.mts +22 -0
  396. package/runtime/scripts/hfs/architecture/sql-returning.mjs +46 -45
  397. package/runtime/scripts/hfs/architecture/sql-token-forms.d.mts +21 -0
  398. package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +86 -74
  399. package/runtime/scripts/hfs/architecture/sql-tokens.d.mts +32 -0
  400. package/runtime/scripts/hfs/architecture/sql-tokens.mjs +456 -341
  401. package/runtime/scripts/hfs/architecture/staged-consumers.d.mts +7 -0
  402. package/runtime/scripts/hfs/architecture/staged-consumers.mjs +35 -30
  403. package/runtime/scripts/hfs/architecture/surface.d.mts +26 -0
  404. package/runtime/scripts/hfs/architecture/surface.mjs +64 -74
  405. package/runtime/scripts/hfs/architecture/symbols.d.mts +11 -0
  406. package/runtime/scripts/hfs/architecture/symbols.mjs +209 -216
  407. package/runtime/scripts/hfs/architecture/test-world-files.d.mts +45 -0
  408. package/runtime/scripts/hfs/architecture/test-world-files.mjs +165 -155
  409. package/runtime/scripts/hfs/architecture/tiers.d.mts +29 -0
  410. package/runtime/scripts/hfs/architecture/tiers.mjs +161 -154
  411. package/runtime/scripts/hfs/architecture/transport-owner.d.mts +37 -0
  412. package/runtime/scripts/hfs/architecture/transport-owner.mjs +155 -149
  413. package/runtime/scripts/hfs/architecture/type-context.d.mts +60 -0
  414. package/runtime/scripts/hfs/architecture/type-context.mjs +255 -250
  415. package/runtime/scripts/hfs/architecture/typescript.d.mts +94 -0
  416. package/runtime/scripts/hfs/architecture/typescript.mjs +358 -318
  417. package/runtime/scripts/hfs/architecture/unit-spec-providers.d.mts +34 -0
  418. package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +110 -92
  419. package/runtime/scripts/hfs/architecture.d.mts +13 -0
  420. package/runtime/scripts/hfs/architecture.mjs +39 -29
  421. package/runtime/scripts/hfs/canon-pins.d.mts +26 -0
  422. package/runtime/scripts/hfs/canon-pins.mjs +5 -8
  423. package/runtime/scripts/hfs/catalog-once.d.mts +2 -0
  424. package/runtime/scripts/hfs/catalog-once.mjs +8 -9
  425. package/runtime/scripts/hfs/check-results.d.mts +29 -0
  426. package/runtime/scripts/hfs/check-results.mjs +14 -18
  427. package/runtime/scripts/hfs/check.d.mts +144 -0
  428. package/runtime/scripts/hfs/check.mjs +309 -329
  429. package/runtime/scripts/hfs/ci-declaration.d.mts +77 -0
  430. package/runtime/scripts/hfs/ci-declaration.mjs +99 -87
  431. package/runtime/scripts/hfs/coverage-from.d.mts +22 -0
  432. package/runtime/scripts/hfs/coverage-from.mjs +52 -49
  433. package/runtime/scripts/hfs/coverage-scope.d.mts +87 -0
  434. package/runtime/scripts/hfs/coverage-scope.mjs +139 -142
  435. package/runtime/scripts/hfs/db-baseline-verb.d.mts +84 -0
  436. package/runtime/scripts/hfs/db-baseline-verb.mjs +327 -266
  437. package/runtime/scripts/hfs/db-errors.d.mts +2 -0
  438. package/runtime/scripts/hfs/db-errors.mjs +2 -1
  439. package/runtime/scripts/hfs/db-plan-verb.d.mts +33 -0
  440. package/runtime/scripts/hfs/db-plan-verb.mjs +174 -128
  441. package/runtime/scripts/hfs/db-restamp-verb.d.mts +5 -0
  442. package/runtime/scripts/hfs/db-restamp-verb.mjs +94 -70
  443. package/runtime/scripts/hfs/db-squash.d.mts +117 -0
  444. package/runtime/scripts/hfs/db-squash.mjs +414 -351
  445. package/runtime/scripts/hfs/declaration-shape.d.mts +3 -0
  446. package/runtime/scripts/hfs/declaration-shape.mjs +140 -103
  447. package/runtime/scripts/hfs/declaration-slots.d.mts +18 -0
  448. package/runtime/scripts/hfs/declaration-slots.mjs +64 -61
  449. package/runtime/scripts/hfs/doc-commands.d.mts +71 -0
  450. package/runtime/scripts/hfs/doc-commands.mjs +257 -250
  451. package/runtime/scripts/hfs/edition-slots.d.mts +37 -0
  452. package/runtime/scripts/hfs/edition-slots.mjs +43 -40
  453. package/runtime/scripts/hfs/example-secrets.d.mts +18 -0
  454. package/runtime/scripts/hfs/example-secrets.mjs +173 -154
  455. package/runtime/scripts/hfs/gate-threshold.d.mts +20 -0
  456. package/runtime/scripts/hfs/gate-threshold.mjs +14 -22
  457. package/runtime/scripts/hfs/grammar-presentation.d.mts +74 -0
  458. package/runtime/scripts/hfs/grammar-presentation.mjs +109 -106
  459. package/runtime/scripts/hfs/linear-text.d.mts +6 -0
  460. package/runtime/scripts/hfs/linear-text.mjs +20 -20
  461. package/runtime/scripts/hfs/manifest-shape.d.mts +216 -0
  462. package/runtime/scripts/hfs/manifest-shape.mjs +399 -324
  463. package/runtime/scripts/hfs/param-names.d.mts +3 -0
  464. package/runtime/scripts/hfs/param-names.mjs +6 -11
  465. package/runtime/scripts/hfs/path-findings.d.mts +22 -0
  466. package/runtime/scripts/hfs/path-findings.mjs +120 -100
  467. package/runtime/scripts/hfs/pin-findings.d.mts +19 -0
  468. package/runtime/scripts/hfs/pin-findings.mjs +26 -21
  469. package/runtime/scripts/hfs/refusal-codes.d.mts +1 -0
  470. package/runtime/scripts/hfs/refusal-codes.mjs +2 -2
  471. package/runtime/scripts/hfs/repo-identity.d.mts +15 -0
  472. package/runtime/scripts/hfs/repo-identity.mjs +55 -42
  473. package/runtime/scripts/hfs/rule-catalog.d.mts +77 -0
  474. package/runtime/scripts/hfs/rule-catalog.mjs +353 -257
  475. package/runtime/scripts/hfs/rule-params-shape.d.mts +10 -0
  476. package/runtime/scripts/hfs/rule-params-shape.mjs +60 -47
  477. package/runtime/scripts/hfs/rules/a15-findings.d.mts +18 -0
  478. package/runtime/scripts/hfs/rules/a15-findings.mjs +59 -55
  479. package/runtime/scripts/hfs/rules/app-env-required.d.mts +9 -0
  480. package/runtime/scripts/hfs/rules/app-env-required.mjs +13 -13
  481. package/runtime/scripts/hfs/rules/app-root.d.mts +15 -0
  482. package/runtime/scripts/hfs/rules/app-root.mjs +20 -21
  483. package/runtime/scripts/hfs/rules/app-workflow-findings.d.mts +12 -0
  484. package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +4 -4
  485. package/runtime/scripts/hfs/rules/assets.d.mts +13 -0
  486. package/runtime/scripts/hfs/rules/assets.mjs +58 -46
  487. package/runtime/scripts/hfs/rules/boot-proof.d.mts +11 -0
  488. package/runtime/scripts/hfs/rules/boot-proof.mjs +7 -8
  489. package/runtime/scripts/hfs/rules/bypass-markers.d.mts +9 -0
  490. package/runtime/scripts/hfs/rules/bypass-markers.mjs +7 -12
  491. package/runtime/scripts/hfs/rules/canon-copy-drift.d.mts +10 -0
  492. package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +70 -68
  493. package/runtime/scripts/hfs/rules/ci-custody.d.mts +7 -0
  494. package/runtime/scripts/hfs/rules/ci-custody.mjs +72 -73
  495. package/runtime/scripts/hfs/rules/ci-standard.d.mts +12 -0
  496. package/runtime/scripts/hfs/rules/ci-standard.mjs +149 -142
  497. package/runtime/scripts/hfs/rules/cli.d.mts +7 -0
  498. package/runtime/scripts/hfs/rules/cli.mjs +24 -23
  499. package/runtime/scripts/hfs/rules/contract-compat.d.mts +11 -0
  500. package/runtime/scripts/hfs/rules/contract-compat.mjs +64 -53
  501. package/runtime/scripts/hfs/rules/contract.d.mts +26 -0
  502. package/runtime/scripts/hfs/rules/contract.mjs +126 -111
  503. package/runtime/scripts/hfs/rules/coverage-below.d.mts +17 -0
  504. package/runtime/scripts/hfs/rules/coverage-below.mjs +200 -167
  505. package/runtime/scripts/hfs/rules/database-access.d.mts +12 -0
  506. package/runtime/scripts/hfs/rules/database-access.mjs +231 -202
  507. package/runtime/scripts/hfs/rules/database-baseline.d.mts +22 -0
  508. package/runtime/scripts/hfs/rules/database-baseline.mjs +104 -104
  509. package/runtime/scripts/hfs/rules/database-config.d.mts +11 -0
  510. package/runtime/scripts/hfs/rules/database-config.mjs +101 -135
  511. package/runtime/scripts/hfs/rules/database-constants.d.mts +36 -0
  512. package/runtime/scripts/hfs/rules/database-constants.mjs +7 -7
  513. package/runtime/scripts/hfs/rules/database-migrations.d.mts +41 -0
  514. package/runtime/scripts/hfs/rules/database-migrations.mjs +428 -388
  515. package/runtime/scripts/hfs/rules/database-plpgsql.d.mts +5 -0
  516. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +278 -259
  517. package/runtime/scripts/hfs/rules/database-queue-sources.d.mts +4 -0
  518. package/runtime/scripts/hfs/rules/database-queue-sources.mjs +48 -43
  519. package/runtime/scripts/hfs/rules/database-queues.d.mts +15 -0
  520. package/runtime/scripts/hfs/rules/database-queues.mjs +211 -182
  521. package/runtime/scripts/hfs/rules/database-sql.d.mts +16 -0
  522. package/runtime/scripts/hfs/rules/database-sql.mjs +394 -394
  523. package/runtime/scripts/hfs/rules/database-transaction.d.mts +3 -0
  524. package/runtime/scripts/hfs/rules/database-transaction.mjs +25 -27
  525. package/runtime/scripts/hfs/rules/database.d.mts +22 -0
  526. package/runtime/scripts/hfs/rules/database.mjs +42 -58
  527. package/runtime/scripts/hfs/rules/deploy-scan.d.mts +10 -0
  528. package/runtime/scripts/hfs/rules/deploy-scan.mjs +177 -168
  529. package/runtime/scripts/hfs/rules/deploy-workflow.d.mts +3 -0
  530. package/runtime/scripts/hfs/rules/deploy-workflow.mjs +194 -171
  531. package/runtime/scripts/hfs/rules/deps.d.mts +6 -0
  532. package/runtime/scripts/hfs/rules/deps.mjs +61 -60
  533. package/runtime/scripts/hfs/rules/doc-fresh.d.mts +11 -0
  534. package/runtime/scripts/hfs/rules/doc-fresh.mjs +242 -223
  535. package/runtime/scripts/hfs/rules/docker-health.d.mts +9 -0
  536. package/runtime/scripts/hfs/rules/docker-health.mjs +222 -196
  537. package/runtime/scripts/hfs/rules/docker.d.mts +13 -0
  538. package/runtime/scripts/hfs/rules/docker.mjs +234 -208
  539. package/runtime/scripts/hfs/rules/edition.d.mts +18 -0
  540. package/runtime/scripts/hfs/rules/edition.mjs +103 -101
  541. package/runtime/scripts/hfs/rules/env-parity.d.mts +25 -0
  542. package/runtime/scripts/hfs/rules/env-parity.mjs +278 -252
  543. package/runtime/scripts/hfs/rules/env-value-shape.d.mts +21 -0
  544. package/runtime/scripts/hfs/rules/env-value-shape.mjs +82 -67
  545. package/runtime/scripts/hfs/rules/event-bus.d.mts +17 -0
  546. package/runtime/scripts/hfs/rules/event-bus.mjs +145 -133
  547. package/runtime/scripts/hfs/rules/event-tables.d.mts +7 -0
  548. package/runtime/scripts/hfs/rules/event-tables.mjs +77 -75
  549. package/runtime/scripts/hfs/rules/fe-build-args.d.mts +10 -0
  550. package/runtime/scripts/hfs/rules/fe-build-args.mjs +116 -99
  551. package/runtime/scripts/hfs/rules/fe-contract-documents.d.mts +7 -0
  552. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +121 -111
  553. package/runtime/scripts/hfs/rules/fe-no-tests.d.mts +9 -0
  554. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +37 -36
  555. package/runtime/scripts/hfs/rules/fe-stack.d.mts +23 -0
  556. package/runtime/scripts/hfs/rules/fe-stack.mjs +108 -105
  557. package/runtime/scripts/hfs/rules/feature-files.d.mts +10 -0
  558. package/runtime/scripts/hfs/rules/feature-files.mjs +14 -19
  559. package/runtime/scripts/hfs/rules/frontend-tree.d.mts +18 -0
  560. package/runtime/scripts/hfs/rules/frontend-tree.mjs +105 -91
  561. package/runtime/scripts/hfs/rules/integration-specs.d.mts +7 -0
  562. package/runtime/scripts/hfs/rules/integration-specs.mjs +190 -177
  563. package/runtime/scripts/hfs/rules/kinds.d.mts +6 -0
  564. package/runtime/scripts/hfs/rules/kinds.mjs +88 -81
  565. package/runtime/scripts/hfs/rules/lexicon.d.mts +9 -0
  566. package/runtime/scripts/hfs/rules/lexicon.mjs +43 -40
  567. package/runtime/scripts/hfs/rules/lint-suppression.d.mts +5 -0
  568. package/runtime/scripts/hfs/rules/lint-suppression.mjs +22 -20
  569. package/runtime/scripts/hfs/rules/lite-proof-lane.d.mts +9 -0
  570. package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +59 -58
  571. package/runtime/scripts/hfs/rules/lite-secrets.d.mts +12 -0
  572. package/runtime/scripts/hfs/rules/lite-secrets.mjs +60 -63
  573. package/runtime/scripts/hfs/rules/mcp-tools.d.mts +7 -0
  574. package/runtime/scripts/hfs/rules/mcp-tools.mjs +56 -41
  575. package/runtime/scripts/hfs/rules/monorepo.d.mts +17 -0
  576. package/runtime/scripts/hfs/rules/monorepo.mjs +153 -138
  577. package/runtime/scripts/hfs/rules/peer-integrations.d.mts +7 -0
  578. package/runtime/scripts/hfs/rules/peer-integrations.mjs +39 -36
  579. package/runtime/scripts/hfs/rules/pipeline.d.mts +7 -0
  580. package/runtime/scripts/hfs/rules/pipeline.mjs +53 -53
  581. package/runtime/scripts/hfs/rules/proof-commands.d.mts +14 -0
  582. package/runtime/scripts/hfs/rules/proof-commands.mjs +52 -41
  583. package/runtime/scripts/hfs/rules/read.d.mts +7 -0
  584. package/runtime/scripts/hfs/rules/read.mjs +19 -15
  585. package/runtime/scripts/hfs/rules/release-provenance.d.mts +12 -0
  586. package/runtime/scripts/hfs/rules/release-provenance.mjs +196 -159
  587. package/runtime/scripts/hfs/rules/repo-local-checks.d.mts +5 -0
  588. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +19 -17
  589. package/runtime/scripts/hfs/rules/rule-types.d.mts +40 -0
  590. package/runtime/scripts/hfs/rules/rule-types.mjs +4 -0
  591. package/runtime/scripts/hfs/rules/saga-delivery.d.mts +2 -0
  592. package/runtime/scripts/hfs/rules/saga-delivery.mjs +58 -50
  593. package/runtime/scripts/hfs/rules/saga.d.mts +7 -0
  594. package/runtime/scripts/hfs/rules/saga.mjs +151 -145
  595. package/runtime/scripts/hfs/rules/script-hygiene.d.mts +11 -0
  596. package/runtime/scripts/hfs/rules/script-hygiene.mjs +112 -95
  597. package/runtime/scripts/hfs/rules/secret-custody-only.d.mts +7 -0
  598. package/runtime/scripts/hfs/rules/secret-custody-only.mjs +29 -35
  599. package/runtime/scripts/hfs/rules/secrets.d.mts +29 -0
  600. package/runtime/scripts/hfs/rules/secrets.mjs +45 -44
  601. package/runtime/scripts/hfs/rules/services.d.mts +7 -0
  602. package/runtime/scripts/hfs/rules/services.mjs +148 -148
  603. package/runtime/scripts/hfs/rules/spec-placement.d.mts +8 -0
  604. package/runtime/scripts/hfs/rules/spec-placement.mjs +12 -13
  605. package/runtime/scripts/hfs/rules/stack-tooling.d.mts +11 -0
  606. package/runtime/scripts/hfs/rules/stack-tooling.mjs +45 -52
  607. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.d.mts +30 -0
  608. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.mjs +149 -0
  609. package/runtime/scripts/hfs/rules/stacks-deploy.d.mts +7 -0
  610. package/runtime/scripts/hfs/rules/stacks-deploy.mjs +32 -42
  611. package/runtime/scripts/hfs/rules/stacks-ingress.d.mts +16 -0
  612. package/runtime/scripts/hfs/rules/stacks-ingress.mjs +62 -64
  613. package/runtime/scripts/hfs/rules/stacks-lite-backing.d.mts +17 -0
  614. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -116
  615. package/runtime/scripts/hfs/rules/stacks-release.d.mts +26 -0
  616. package/runtime/scripts/hfs/rules/stacks-release.mjs +335 -309
  617. package/runtime/scripts/hfs/rules/stacks-runtime.d.mts +31 -0
  618. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +130 -124
  619. package/runtime/scripts/hfs/rules/stacks-swarm.d.mts +5 -0
  620. package/runtime/scripts/hfs/rules/stacks-swarm.mjs +366 -344
  621. package/runtime/scripts/hfs/rules/stacks.d.mts +7 -0
  622. package/runtime/scripts/hfs/rules/stacks.mjs +37 -38
  623. package/runtime/scripts/hfs/rules/staged-specs.d.mts +10 -0
  624. package/runtime/scripts/hfs/rules/staged-specs.mjs +14 -18
  625. package/runtime/scripts/hfs/rules/supply-chain.d.mts +10 -0
  626. package/runtime/scripts/hfs/rules/supply-chain.mjs +143 -150
  627. package/runtime/scripts/hfs/rules/test-topology.d.mts +5 -0
  628. package/runtime/scripts/hfs/rules/test-topology.mjs +23 -21
  629. package/runtime/scripts/hfs/rules/text-integrity.d.mts +9 -0
  630. package/runtime/scripts/hfs/rules/text-integrity.mjs +47 -43
  631. package/runtime/scripts/hfs/rules/unused-symbol-flow.d.mts +22 -0
  632. package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +226 -204
  633. package/runtime/scripts/hfs/rules/unused-symbol-ledger.d.mts +7 -0
  634. package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +70 -49
  635. package/runtime/scripts/hfs/rules/unused-symbol-properties.d.mts +12 -0
  636. package/runtime/scripts/hfs/rules/unused-symbol-properties.mjs +141 -126
  637. package/runtime/scripts/hfs/rules/unused-symbol-translators.d.mts +8 -0
  638. package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +160 -140
  639. package/runtime/scripts/hfs/rules/unused-symbol-values.d.mts +9 -0
  640. package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +138 -125
  641. package/runtime/scripts/hfs/rules/unused-symbol.d.mts +11 -0
  642. package/runtime/scripts/hfs/rules/unused-symbol.mjs +283 -253
  643. package/runtime/scripts/hfs/rules/workflow-contexts.d.mts +8 -0
  644. package/runtime/scripts/hfs/rules/workflow-contexts.mjs +79 -67
  645. package/runtime/scripts/hfs/runtime-rules/git-triggers.d.mts +6 -0
  646. package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +36 -35
  647. package/runtime/scripts/hfs/runtime-rules/hook-shape.d.mts +10 -0
  648. package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +45 -42
  649. package/runtime/scripts/hfs/runtime-rules/source-ast.d.mts +39 -0
  650. package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +130 -116
  651. package/runtime/scripts/hfs/runtime-rules/workflow-source.d.mts +5 -0
  652. package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +8 -7
  653. package/runtime/scripts/hfs/sealed-members.d.mts +22 -0
  654. package/runtime/scripts/hfs/sealed-members.mjs +79 -75
  655. package/runtime/scripts/hfs/secret-bootstrap-crypto.d.mts +12 -0
  656. package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +151 -167
  657. package/runtime/scripts/hfs/secret-document.d.mts +16 -0
  658. package/runtime/scripts/hfs/secret-document.mjs +59 -75
  659. package/runtime/scripts/hfs/secret-edit.d.mts +14 -0
  660. package/runtime/scripts/hfs/secret-edit.mjs +115 -135
  661. package/runtime/scripts/hfs/secret-errors.d.mts +4 -0
  662. package/runtime/scripts/hfs/secret-errors.mjs +19 -16
  663. package/runtime/scripts/hfs/secret-files.d.mts +20 -0
  664. package/runtime/scripts/hfs/secret-files.mjs +103 -112
  665. package/runtime/scripts/hfs/secret-init.d.mts +108 -0
  666. package/runtime/scripts/hfs/secret-init.mjs +304 -346
  667. package/runtime/scripts/hfs/secret-output.d.mts +18 -0
  668. package/runtime/scripts/hfs/secret-output.mjs +52 -80
  669. package/runtime/scripts/hfs/secret-prompt.d.mts +39 -0
  670. package/runtime/scripts/hfs/secret-prompt.mjs +108 -93
  671. package/runtime/scripts/hfs/secret-sops.d.mts +29 -0
  672. package/runtime/scripts/hfs/secret-sops.mjs +161 -199
  673. package/runtime/scripts/hfs/secret-standard.d.mts +89 -0
  674. package/runtime/scripts/hfs/secret-standard.mjs +300 -264
  675. package/runtime/scripts/hfs/secret-store.d.mts +36 -0
  676. package/runtime/scripts/hfs/secret-store.mjs +120 -136
  677. package/runtime/scripts/hfs/secret.d.mts +40 -0
  678. package/runtime/scripts/hfs/secret.mjs +254 -222
  679. package/runtime/scripts/hfs/slot-app-view.d.mts +11 -0
  680. package/runtime/scripts/hfs/slot-app-view.mjs +69 -74
  681. package/runtime/scripts/hfs/slot-classify.d.mts +75 -0
  682. package/runtime/scripts/hfs/slot-classify.mjs +42 -38
  683. package/runtime/scripts/hfs/slot-errors.d.mts +6 -0
  684. package/runtime/scripts/hfs/slot-errors.mjs +8 -7
  685. package/runtime/scripts/hfs/slot-imports.d.mts +8 -0
  686. package/runtime/scripts/hfs/slot-imports.mjs +70 -63
  687. package/runtime/scripts/hfs/slot-manifest-shape.d.mts +9 -0
  688. package/runtime/scripts/hfs/slot-manifest-shape.mjs +74 -52
  689. package/runtime/scripts/hfs/slot-match.d.mts +50 -0
  690. package/runtime/scripts/hfs/slot-match.mjs +122 -111
  691. package/runtime/scripts/hfs/slot-path.d.mts +1 -0
  692. package/runtime/scripts/hfs/slot-path.mjs +0 -2
  693. package/runtime/scripts/hfs/slot-required.d.mts +11 -0
  694. package/runtime/scripts/hfs/slot-required.mjs +65 -59
  695. package/runtime/scripts/hfs/slot-semantic-problems.d.mts +9 -0
  696. package/runtime/scripts/hfs/slot-semantic-problems.mjs +138 -112
  697. package/runtime/scripts/hfs/slot-side-problems.d.mts +3 -0
  698. package/runtime/scripts/hfs/slot-side-problems.mjs +23 -19
  699. package/runtime/scripts/hfs/slots.d.mts +188 -0
  700. package/runtime/scripts/hfs/slots.mjs +175 -152
  701. package/runtime/scripts/hfs/sql/pg-parse.d.mts +9 -0
  702. package/runtime/scripts/hfs/sql/pg-parse.mjs +25 -25
  703. package/runtime/scripts/hfs/stack-config-kit.d.mts +22 -0
  704. package/runtime/scripts/hfs/stack-config-kit.mjs +21 -17
  705. package/runtime/scripts/hfs/stack-deploy-config.d.mts +155 -0
  706. package/runtime/scripts/hfs/stack-deploy-config.mjs +345 -273
  707. package/runtime/scripts/hfs/stack-ingress-config.d.mts +74 -0
  708. package/runtime/scripts/hfs/stack-ingress-config.mjs +211 -177
  709. package/runtime/scripts/hfs/stacks-gate.d.mts +52 -0
  710. package/runtime/scripts/hfs/stacks-gate.mjs +557 -397
  711. package/runtime/scripts/hfs/starcistacks-runtime.d.mts +7 -0
  712. package/runtime/scripts/hfs/starcistacks-runtime.mjs +51 -40
  713. package/runtime/scripts/hfs/test-world-slot.d.mts +2 -0
  714. package/runtime/scripts/hfs/test-world-slot.mjs +0 -1
  715. package/runtime/scripts/hfs/trailing-slashes.d.mts +2 -0
  716. package/runtime/scripts/hfs/trailing-slashes.mjs +4 -4
  717. package/runtime/scripts/hfs/tree-findings.d.mts +9 -0
  718. package/runtime/scripts/hfs/tree-findings.mjs +18 -17
  719. package/runtime/scripts/hfs/tree.d.mts +35 -0
  720. package/runtime/scripts/hfs/tree.mjs +56 -46
  721. package/runtime/scripts/hfs/typescript-programs.d.mts +36 -0
  722. package/runtime/scripts/hfs/typescript-programs.mjs +66 -69
  723. package/runtime/scripts/hfs/view.d.mts +45 -0
  724. package/runtime/scripts/hfs/view.mjs +38 -40
  725. package/runtime/scripts/lib/bypass-markers.d.mts +15 -0
  726. package/runtime/scripts/lib/bypass-markers.mjs +210 -197
  727. package/runtime/scripts/lib/cli-arg.d.mts +67 -0
  728. package/runtime/scripts/lib/cli-arg.mjs +59 -63
  729. package/runtime/scripts/lib/command-tokens.d.mts +11 -0
  730. package/runtime/scripts/lib/command-tokens.mjs +77 -78
  731. package/runtime/scripts/lib/compose-values.d.mts +6 -0
  732. package/runtime/scripts/lib/compose-values.mjs +7 -7
  733. package/runtime/scripts/lib/css-rules.d.mts +36 -0
  734. package/runtime/scripts/lib/css-rules.mjs +181 -171
  735. package/runtime/scripts/lib/deployment-findings.d.mts +9 -0
  736. package/runtime/scripts/lib/deployment-findings.mjs +4 -4
  737. package/runtime/scripts/lib/dockerfile.d.mts +39 -0
  738. package/runtime/scripts/lib/dockerfile.mjs +131 -114
  739. package/runtime/scripts/lib/dom-tree.d.mts +7 -0
  740. package/runtime/scripts/lib/dom-tree.mjs +3 -3
  741. package/runtime/scripts/lib/env.d.mts +12 -0
  742. package/runtime/scripts/lib/env.mjs +3 -6
  743. package/runtime/scripts/lib/escape.d.mts +6 -0
  744. package/runtime/scripts/lib/escape.mjs +2 -6
  745. package/runtime/scripts/lib/event-contract.d.mts +21 -0
  746. package/runtime/scripts/lib/event-contract.mjs +73 -78
  747. package/runtime/scripts/lib/event-items.d.mts +20 -0
  748. package/runtime/scripts/lib/event-items.mjs +27 -15
  749. package/runtime/scripts/lib/example-refs.d.mts +69 -0
  750. package/runtime/scripts/lib/example-refs.mjs +145 -129
  751. package/runtime/scripts/lib/fs-kind.d.mts +12 -0
  752. package/runtime/scripts/lib/fs-kind.mjs +20 -10
  753. package/runtime/scripts/lib/git-hooks-dir.d.mts +15 -0
  754. package/runtime/scripts/lib/git-hooks-dir.mjs +16 -16
  755. package/runtime/scripts/lib/git.d.mts +24 -0
  756. package/runtime/scripts/lib/git.mjs +15 -16
  757. package/runtime/scripts/lib/glob.d.mts +4 -0
  758. package/runtime/scripts/lib/glob.mjs +23 -14
  759. package/runtime/scripts/lib/grammar-lint.d.mts +47 -0
  760. package/runtime/scripts/lib/grammar-lint.mjs +33 -37
  761. package/runtime/scripts/lib/grammar-vendor-parity-jsx.d.mts +40 -0
  762. package/runtime/scripts/lib/grammar-vendor-parity-jsx.mjs +285 -266
  763. package/runtime/scripts/lib/grammar-vendor-parity.d.mts +61 -0
  764. package/runtime/scripts/lib/grammar-vendor-parity.mjs +209 -216
  765. package/runtime/scripts/lib/graphql-contract.d.mts +53 -0
  766. package/runtime/scripts/lib/graphql-contract.mjs +201 -198
  767. package/runtime/scripts/lib/graphql-sdl.d.mts +66 -0
  768. package/runtime/scripts/lib/graphql-sdl.mjs +230 -205
  769. package/runtime/scripts/lib/hook-limits.d.mts +11 -0
  770. package/runtime/scripts/lib/hook-limits.mjs +0 -1
  771. package/runtime/scripts/lib/i18n.d.mts +48 -0
  772. package/runtime/scripts/lib/i18n.mjs +32 -35
  773. package/runtime/scripts/lib/in-order.d.mts +12 -0
  774. package/runtime/scripts/lib/in-order.mjs +57 -38
  775. package/runtime/scripts/lib/is-main.d.mts +6 -0
  776. package/runtime/scripts/lib/is-main.mjs +11 -4
  777. package/runtime/scripts/lib/js-lex.d.mts +32 -0
  778. package/runtime/scripts/lib/js-lex.mjs +196 -162
  779. package/runtime/scripts/lib/json-clone.d.mts +11 -0
  780. package/runtime/scripts/lib/json-clone.mjs +45 -36
  781. package/runtime/scripts/lib/json-schema.d.mts +2 -0
  782. package/runtime/scripts/lib/json-schema.mjs +127 -90
  783. package/runtime/scripts/lib/json.d.mts +16 -0
  784. package/runtime/scripts/lib/json.mjs +26 -14
  785. package/runtime/scripts/lib/language.d.mts +44 -0
  786. package/runtime/scripts/lib/language.mjs +133 -129
  787. package/runtime/scripts/lib/list.d.mts +17 -0
  788. package/runtime/scripts/lib/list.mjs +9 -14
  789. package/runtime/scripts/lib/loosening-budgets.d.mts +12 -0
  790. package/runtime/scripts/lib/loosening-budgets.mjs +35 -29
  791. package/runtime/scripts/lib/loosening-config.d.mts +64 -0
  792. package/runtime/scripts/lib/loosening-config.mjs +267 -236
  793. package/runtime/scripts/lib/loosening-state.d.mts +77 -0
  794. package/runtime/scripts/lib/loosening-state.mjs +134 -128
  795. package/runtime/scripts/lib/mutation-fence.d.mts +11 -0
  796. package/runtime/scripts/lib/mutation-fence.mjs +10 -5
  797. package/runtime/scripts/lib/normalize.d.mts +12 -0
  798. package/runtime/scripts/lib/normalize.mjs +11 -11
  799. package/runtime/scripts/lib/numeric-match.d.mts +2 -0
  800. package/runtime/scripts/lib/numeric-match.mjs +2 -2
  801. package/runtime/scripts/lib/package-at.d.mts +24 -0
  802. package/runtime/scripts/lib/package-at.mjs +34 -31
  803. package/runtime/scripts/lib/path-key.d.mts +76 -0
  804. package/runtime/scripts/lib/path-key.mjs +53 -38
  805. package/runtime/scripts/lib/pid-alive.d.mts +2 -0
  806. package/runtime/scripts/lib/pid-alive.mjs +10 -3
  807. package/runtime/scripts/lib/properties.d.mts +2 -0
  808. package/runtime/scripts/lib/properties.mjs +17 -11
  809. package/runtime/scripts/lib/provision-operation-schema.d.mts +4 -0
  810. package/runtime/scripts/lib/provision-operation-schema.mjs +4 -5
  811. package/runtime/scripts/lib/read-text.d.mts +12 -0
  812. package/runtime/scripts/lib/read-text.mjs +30 -17
  813. package/runtime/scripts/lib/redact.d.mts +52 -0
  814. package/runtime/scripts/lib/redact.mjs +135 -121
  815. package/runtime/scripts/lib/regex.d.mts +2 -0
  816. package/runtime/scripts/lib/regex.mjs +1 -2
  817. package/runtime/scripts/lib/roots.d.mts +32 -0
  818. package/runtime/scripts/lib/roots.mjs +5 -15
  819. package/runtime/scripts/lib/runtime-example.d.mts +1 -0
  820. package/runtime/scripts/lib/runtime-example.mjs +10 -8
  821. package/runtime/scripts/lib/same-text.d.mts +2 -0
  822. package/runtime/scripts/lib/same-text.mjs +0 -1
  823. package/runtime/scripts/lib/sealed-member.d.mts +16 -0
  824. package/runtime/scripts/lib/sealed-member.mjs +8 -13
  825. package/runtime/scripts/lib/secret-patterns.d.mts +30 -0
  826. package/runtime/scripts/lib/secret-patterns.mjs +175 -163
  827. package/runtime/scripts/lib/shell-source.d.mts +2 -0
  828. package/runtime/scripts/lib/shell-source.mjs +0 -1
  829. package/runtime/scripts/lib/sleep-sync.d.mts +2 -0
  830. package/runtime/scripts/lib/sleep-sync.mjs +5 -6
  831. package/runtime/scripts/lib/sops-envelope.d.mts +34 -0
  832. package/runtime/scripts/lib/sops-envelope.mjs +148 -120
  833. package/runtime/scripts/lib/source-phrases.d.mts +4 -0
  834. package/runtime/scripts/lib/source-phrases.mjs +13 -13
  835. package/runtime/scripts/lib/sql-ast.d.mts +13 -0
  836. package/runtime/scripts/lib/sql-ast.mjs +19 -18
  837. package/runtime/scripts/lib/sqlite.d.mts +21 -0
  838. package/runtime/scripts/lib/sqlite.mjs +3 -9
  839. package/runtime/scripts/lib/stack-declaration.d.mts +51 -0
  840. package/runtime/scripts/lib/stack-declaration.mjs +27 -20
  841. package/runtime/scripts/lib/stack-services.d.mts +73 -0
  842. package/runtime/scripts/lib/stack-services.mjs +128 -129
  843. package/runtime/scripts/lib/starciwork-boundary.d.mts +10 -0
  844. package/runtime/scripts/lib/starciwork-boundary.mjs +98 -92
  845. package/runtime/scripts/lib/swarm-stack.d.mts +24 -0
  846. package/runtime/scripts/lib/swarm-stack.mjs +112 -100
  847. package/runtime/scripts/lib/trim-end.d.mts +2 -0
  848. package/runtime/scripts/lib/trim-end.mjs +4 -4
  849. package/runtime/scripts/lib/ts-analysis.d.mts +24 -0
  850. package/runtime/scripts/lib/ts-analysis.mjs +28 -26
  851. package/runtime/scripts/lib/ts-ast.d.mts +36 -0
  852. package/runtime/scripts/lib/ts-ast.mjs +36 -42
  853. package/runtime/scripts/lib/walk.d.mts +19 -0
  854. package/runtime/scripts/lib/walk.mjs +33 -27
  855. package/runtime/scripts/lib/work-edition.d.mts +10 -0
  856. package/runtime/scripts/lib/work-edition.mjs +29 -21
  857. package/runtime/scripts/lib/workflow-events.d.mts +2 -0
  858. package/runtime/scripts/lib/workflow-events.mjs +5 -4
  859. package/runtime/scripts/lib/worktree-exclude.d.mts +16 -0
  860. package/runtime/scripts/lib/worktree-exclude.mjs +6 -8
  861. package/runtime/scripts/lib/yaml-cached.d.mts +2 -0
  862. package/runtime/scripts/lib/yaml-cached.mjs +4 -4
  863. package/runtime/scripts/machine/artifact-hold.d.mts +26 -0
  864. package/runtime/scripts/machine/artifact-hold.mjs +22 -23
  865. package/runtime/scripts/work/asset-slot.d.mts +96 -0
  866. package/runtime/scripts/work/asset-slot.mjs +201 -175
  867. package/runtime/scripts/work/draw/draw-dna-anatomy.d.mts +30 -0
  868. package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +40 -36
  869. package/runtime/scripts/work/draw/draw-dna-findings.d.mts +12 -0
  870. package/runtime/scripts/work/draw/draw-dna-findings.mjs +240 -206
  871. package/runtime/scripts/work/draw/draw-dna-selector.d.mts +7 -0
  872. package/runtime/scripts/work/draw/draw-dna-selector.mjs +28 -28
  873. package/runtime/scripts/work/draw/draw-dna.d.mts +191 -0
  874. package/runtime/scripts/work/draw/draw-dna.mjs +283 -249
  875. package/runtime/scripts/work/grammar-proposal.d.mts +83 -0
  876. package/runtime/scripts/work/grammar-proposal.mjs +215 -178
  877. package/runtime/scripts/work/work-io.d.mts +62 -0
  878. package/runtime/scripts/work/work-io.mjs +82 -63
  879. package/scaffold/add-app.d.mts +15 -0
  880. package/scaffold/add-app.mjs +111 -163
  881. package/scaffold/add-cli-lite.d.mts +8 -0
  882. package/scaffold/add-cli-lite.mjs +173 -207
  883. package/scaffold/add-compose.d.mts +44 -0
  884. package/scaffold/add-compose.mjs +62 -62
  885. package/scaffold/add-database-lite.d.mts +2 -0
  886. package/scaffold/add-database-lite.mjs +10 -10
  887. package/scaffold/add-fe-layout.d.mts +16 -0
  888. package/scaffold/add-fe-layout.mjs +23 -23
  889. package/scaffold/add-fe-overlay.d.mts +17 -0
  890. package/scaffold/add-fe-overlay.mjs +76 -78
  891. package/scaffold/add-fe-page.d.mts +41 -0
  892. package/scaffold/add-fe-page.mjs +84 -89
  893. package/scaffold/add-fe-unit.d.mts +59 -0
  894. package/scaffold/add-fe-unit.mjs +205 -197
  895. package/scaffold/add-inbox-lite.d.mts +17 -0
  896. package/scaffold/add-inbox-lite.mjs +209 -264
  897. package/scaffold/add-plan.d.mts +68 -0
  898. package/scaffold/add-plan.mjs +164 -149
  899. package/scaffold/add-queue-lite.d.mts +34 -0
  900. package/scaffold/add-queue-lite.mjs +267 -267
  901. package/scaffold/add-table.d.mts +16 -0
  902. package/scaffold/add-table.mjs +405 -442
  903. package/scaffold/add.d.mts +34 -0
  904. package/scaffold/add.mjs +260 -246
  905. package/scaffold/app.d.mts +198 -0
  906. package/scaffold/app.mjs +413 -391
  907. package/scaffold/edition-gate.d.mts +49 -0
  908. package/scaffold/edition-gate.mjs +19 -29
  909. package/scaffold/image.d.mts +4 -0
  910. package/scaffold/image.mjs +12 -12
  911. package/scaffold/lite-exports.d.mts +15 -0
  912. package/scaffold/lite-exports.mjs +262 -255
  913. package/scaffold/pattern-file-slots.d.mts +7 -0
  914. package/scaffold/pattern-file-slots.mjs +29 -24
  915. package/scaffold/service.d.mts +60 -0
  916. package/scaffold/service.mjs +297 -279
  917. package/scaffold/test-world.d.mts +31 -0
  918. package/scaffold/test-world.mjs +71 -78
  919. package/scaffold/yaml-block-edit.d.mts +23 -0
  920. package/scaffold/yaml-block-edit.mjs +95 -87
  921. package/scripts/sync-bundles.d.mts +31 -0
  922. package/src/fixtures/bypass-index.d.mts +4 -0
  923. package/src/fixtures/hfs-stack-tooling/passing.d.mts +8 -0
  924. package/src/fixtures/hfs-stack-tooling/violating.d.mts +19 -0
  925. package/src/fixtures/hfs-stacks-full/model-unavailable.d.mts +10 -0
  926. package/src/fixtures/hfs-stacks-full/passing.d.mts +19 -0
  927. package/src/fixtures/hfs-stacks-full/violating.d.mts +10 -0
  928. package/src/fixtures/loosening/adversarial.d.mts +4 -0
  929. package/src/fixtures/loosening/forms.d.mts +16 -0
  930. package/src/fixtures/loosening/swallows.d.mts +5 -0
  931. package/src/helpers/hfs-arch-fixture.d.mts +47 -0
  932. package/src/helpers/hfs-cli-fixture.d.mts +65 -0
  933. package/src/helpers/hfs-hfs-docker-rules-fixture.d.mts +5 -0
  934. package/src/helpers/hfs-secret-fixture.d.mts +19 -0
  935. package/src/helpers/pre-push-fixture.d.mts +21 -0
  936. package/src/helpers/stack-compose.d.mts +6 -0
  937. package/src/helpers/swarm-stack-fixture.d.mts +18 -0
  938. package/src/helpers/tmpdir.d.mts +2 -0
  939. package/src/main.d.mts +58 -0
  940. package/src/main.mjs +493 -348
  941. package/stack/age-install.d.mts +13 -0
  942. package/stack/age-install.mjs +28 -25
  943. package/stack/backup.d.mts +11 -0
  944. package/stack/backup.mjs +76 -69
  945. package/stack/build-args.d.mts +7 -0
  946. package/stack/build-args.mjs +22 -23
  947. package/stack/build.d.mts +8 -0
  948. package/stack/build.mjs +138 -119
  949. package/stack/cli.d.mts +55 -0
  950. package/stack/cli.mjs +187 -130
  951. package/stack/config.d.mts +197 -0
  952. package/stack/config.mjs +47 -33
  953. package/stack/context.d.mts +122 -0
  954. package/stack/context.mjs +63 -65
  955. package/stack/converge.d.mts +13 -0
  956. package/stack/converge.mjs +73 -69
  957. package/stack/deploy.d.mts +88 -0
  958. package/stack/deploy.mjs +272 -224
  959. package/stack/digest.d.mts +8 -0
  960. package/stack/digest.mjs +1 -6
  961. package/stack/docker-transport.d.mts +5 -0
  962. package/stack/docker-transport.mjs +101 -93
  963. package/stack/edge-alias.d.mts +42 -0
  964. package/stack/edge-alias.mjs +62 -60
  965. package/stack/errors.d.mts +18 -0
  966. package/stack/errors.mjs +8 -10
  967. package/stack/image-scan.d.mts +20 -0
  968. package/stack/image-scan.mjs +114 -101
  969. package/stack/ingress-create.d.mts +4 -0
  970. package/stack/ingress-create.mjs +82 -86
  971. package/stack/ingress-publish.d.mts +6 -0
  972. package/stack/ingress-publish.mjs +194 -182
  973. package/stack/ingress.d.mts +55 -0
  974. package/stack/ingress.mjs +534 -524
  975. package/stack/jobs.d.mts +12 -0
  976. package/stack/jobs.mjs +35 -34
  977. package/stack/live-restore.d.mts +35 -0
  978. package/stack/live-restore.mjs +120 -125
  979. package/stack/post-deploy.d.mts +8 -0
  980. package/stack/post-deploy.mjs +25 -25
  981. package/stack/prepare.d.mts +24 -0
  982. package/stack/prepare.mjs +213 -200
  983. package/stack/private-file.d.mts +5 -0
  984. package/stack/private-file.mjs +9 -9
  985. package/stack/provision.d.mts +25 -0
  986. package/stack/provision.mjs +64 -63
  987. package/stack/prune.d.mts +11 -0
  988. package/stack/prune.mjs +38 -27
  989. package/stack/release-store.d.mts +28 -0
  990. package/stack/release-store.mjs +68 -67
  991. package/stack/remote.d.mts +83 -0
  992. package/stack/remote.mjs +176 -162
  993. package/stack/render.d.mts +14 -0
  994. package/stack/render.mjs +132 -124
  995. package/stack/retire.d.mts +9 -0
  996. package/stack/retire.mjs +31 -34
  997. package/stack/sealed.d.mts +46 -0
  998. package/stack/sealed.mjs +78 -82
  999. package/stack/server-key.d.mts +67 -0
  1000. package/stack/server-key.mjs +217 -203
  1001. package/stack/ssh-session.d.mts +29 -0
  1002. package/stack/ssh-session.mjs +133 -123
  1003. package/stack/target-binding.d.mts +21 -0
  1004. package/stack/target-binding.mjs +68 -44
  1005. package/stack/task.d.mts +12 -0
  1006. package/stack/task.mjs +26 -31
  1007. package/stack/urgent-floor.d.mts +106 -0
  1008. package/stack/urgent-floor.mjs +211 -160
  1009. package/stack/urgent-release.d.mts +38 -0
  1010. package/stack/urgent-release.mjs +26 -22
  1011. package/stack/verify.d.mts +14 -0
  1012. package/stack/verify.mjs +75 -65
  1013. package/sync/ci-commands.d.mts +26 -0
  1014. package/sync/ci-commands.mjs +181 -182
  1015. package/sync/cli.d.mts +8 -0
  1016. package/sync/cli.mjs +9 -9
  1017. package/sync/format.d.mts +38 -0
  1018. package/sync/format.mjs +30 -24
  1019. package/sync/hygiene.d.mts +23 -0
  1020. package/sync/hygiene.mjs +113 -99
  1021. package/sync/index.d.mts +237 -0
  1022. package/sync/index.mjs +457 -436
  1023. package/sync/managed.d.mts +23 -0
  1024. package/sync/managed.mjs +104 -94
  1025. package/sync/quality-services.d.mts +35 -0
  1026. package/sync/quality-services.mjs +48 -41
  1027. package/sync/readme-badges.d.mts +13 -0
  1028. package/sync/readme-badges.mjs +45 -44
  1029. package/sync/sonar-key.d.mts +31 -0
  1030. package/sync/sonar-key.mjs +29 -28
  1031. package/sync/stack-images.d.mts +36 -0
  1032. package/sync/stack-images.mjs +85 -95
  1033. package/sync/ts-strict.d.mts +14 -0
  1034. package/sync/ts-strict.mjs +43 -34
  1035. package/templates/app/ci-workflows/github/workflows/ci.yml +1 -1
  1036. package/templates/app/ci-workflows/github/workflows/images.yml +1 -1
  1037. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +2 -2
  1038. package/templates/app/ci-workflows/github/workflows/stack-key-restore.yml +1 -1
  1039. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -1
  1040. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +3 -3
  1041. package/templates/app/ci-workflows-lite/github/workflows/images.yml +1 -1
  1042. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +2 -2
  1043. package/templates/app/ci-workflows-lite/github/workflows/stack-key-restore.yml +1 -1
  1044. package/templates/app/codegen-lite/scripts/codegen.mjs +1 -1
  1045. package/templates/app/db-bootstrap/db/bootstrap.sql +1 -1
  1046. package/templates/app/db-image/starcistacks/images/db/Dockerfile +1 -1
  1047. package/templates/app/hooks/husky/pre-commit +2 -2
  1048. package/templates/app/package-scripts/db.json +3 -3
  1049. package/templates/app/package-scripts/package.json +1 -1
  1050. package/templates/app/quality-config/sonar-project.properties +1 -1
  1051. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +2 -2
  1052. package/templates/app/skeleton/.starcistacks/production/README.md +4 -4
  1053. package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +8 -3
  1054. package/templates/app/skeleton/README.md +1 -1
  1055. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +2 -2
  1056. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +1 -1
  1057. package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +6 -2
  1058. package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +3 -2
  1059. package/templates/app/skeleton-lite/.starcistacks/production/README.md +5 -5
  1060. package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +7 -2
  1061. package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +3 -2
  1062. package/templates/app/skeleton-lite/README.md +2 -2
  1063. package/templates/be/skeleton/apps/cli/src/compose/platform.ts +1 -1
  1064. package/templates/be/skeleton/apps/cli/src/main.ts +6 -4
  1065. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +12 -0
  1066. package/templates/be/skeleton/src/modules/platform/database/abstract.entity.ts +19 -0
  1067. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
  1068. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +19 -0
  1069. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +4 -3
  1070. package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +1 -1
  1071. package/templates/be/skeleton/src/modules/platform/logging/logging.options.ts +5 -2
  1072. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +1 -1
  1073. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.spec.ts +40 -0
  1074. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +1 -0
  1075. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.spec.ts +48 -1
  1076. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +5 -0
  1077. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +5 -0
  1078. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +1 -1
  1079. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +7 -3
  1080. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +7 -1
  1081. package/templates/be/table/entity.ts.tpl +4 -15
  1082. package/upgrade/check.d.mts +9 -0
  1083. package/upgrade/check.mjs +8 -8
  1084. package/upgrade/file-state.d.mts +6 -0
  1085. package/upgrade/file-state.mjs +32 -40
  1086. package/upgrade/index.d.mts +13 -0
  1087. package/upgrade/index.mjs +122 -151
  1088. package/vendor-types.d.mts +8 -0
@@ -17,668 +17,794 @@
17
17
  * Injected: `ts` (the TypeScript module), `host.read(file)` (text or null) and `host.resolve(fromFile, specifier)` (an
18
18
  * absolute file of the repository, or null for an external package). Pure of the file system otherwise.
19
19
  */
20
-
21
20
  const NEST_COMMON = '@nestjs/common';
22
21
  const NEST_GRAPHQL = '@nestjs/graphql';
23
-
24
22
  /** GraphQL server options that change the printed schema and that this reader does not model: presence is an error. */
25
23
  const SCHEMA_OPTIONS_NOT_MODELED = ['buildSchemaOptions', 'typeDefs', 'schema', 'transformSchema', 'transformAutoSchemaFile'];
26
-
27
24
  const undef = { t: 'undef' };
28
25
  const nul = { t: 'nul' };
29
26
  const free = (why) => ({ t: 'free', why });
30
-
31
27
  /**
32
28
  * JavaScript's abstract equality (`==`) for the literal kinds this graph forces - string, number, boolean - without
33
29
  * the `==` operator: one type compares strictly, a boolean compares as its number, and a number meets a string as
34
30
  * Number(string), exactly as the language coerces them (so '' == 0, '1' == true, NaN never equals).
35
31
  */
36
32
  export function looseLiteralEqual(x, y) {
37
- if (typeof x === typeof y) return x === y;
38
- if (typeof x === 'boolean') return looseLiteralEqual(Number(x), y);
39
- if (typeof y === 'boolean') return looseLiteralEqual(x, Number(y));
40
- if (typeof x === 'number' && typeof y === 'string') return x === Number(y);
41
- if (typeof x === 'string' && typeof y === 'number') return Number(x) === y;
42
- return false;
33
+ if (typeof x === typeof y)
34
+ return x === y;
35
+ if (typeof x === 'boolean')
36
+ return looseLiteralEqual(Number(x), y);
37
+ if (typeof y === 'boolean')
38
+ return looseLiteralEqual(x, Number(y));
39
+ if (typeof x === 'number' && typeof y === 'string')
40
+ return x === Number(y);
41
+ if (typeof x === 'string' && typeof y === 'number')
42
+ return Number(x) === y;
43
+ return false;
43
44
  }
44
-
45
45
  export function createGraphReader({ ts, host }) {
46
- const files = new Map();
47
- const classes = new Map();
48
- const thunks = new WeakMap();
49
-
50
- const where = (node) => {
51
- const sf = node.getSourceFile();
52
- const { line } = sf.getLineAndCharacterOfPosition(node.getStart(sf));
53
- return `${sf.fileName}:${line + 1}`;
54
- };
55
-
56
- // ---- files: imports, declarations, exports ----
57
- function info(file) {
58
- if (files.has(file)) return files.get(file);
59
- const text = host.read(file);
60
- if (text === null || text === undefined) throw new Error(`cannot read ${file}`);
61
- const sourceFile = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
62
- const record = { sourceFile, imports: new Map(), decls: new Map(), exports: new Map(), stars: [] };
63
- files.set(file, record);
64
- const exported = (node) => (ts.getSyntacticModifierFlags(node) & ts.ModifierFlags.Export) !== 0;
65
- const isDefault = (node) => (ts.getSyntacticModifierFlags(node) & ts.ModifierFlags.Default) !== 0;
66
- for (const statement of sourceFile.statements) {
67
- if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
68
- const spec = statement.moduleSpecifier.text;
69
- const clause = statement.importClause;
70
- if (!clause) continue;
71
- if (clause.name) record.imports.set(clause.name.text, { spec, name: 'default' });
72
- if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
73
- for (const element of clause.namedBindings.elements) record.imports.set(element.name.text, { spec, name: (element.propertyName ?? element.name).text });
74
- } else if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) record.imports.set(clause.namedBindings.name.text, { spec, name: '*' });
75
- } else if ((ts.isClassDeclaration(statement) || ts.isFunctionDeclaration(statement)) && statement.name) {
76
- record.decls.set(statement.name.text, { kind: ts.isClassDeclaration(statement) ? 'class' : 'function', node: statement });
77
- if (exported(statement)) record.exports.set(isDefault(statement) ? 'default' : statement.name.text, { local: statement.name.text });
78
- } else if (ts.isVariableStatement(statement)) {
79
- for (const declaration of statement.declarationList.declarations) {
80
- if (ts.isIdentifier(declaration.name)) {
81
- record.decls.set(declaration.name.text, { kind: 'var', node: declaration });
82
- if (exported(statement)) record.exports.set(declaration.name.text, { local: declaration.name.text });
83
- } else {
84
- for (const element of declaration.name.elements ?? []) {
85
- if (ts.isBindingElement(element) && ts.isIdentifier(element.name)) {
86
- record.decls.set(element.name.text, { kind: 'opaque', node: element });
87
- if (exported(statement)) record.exports.set(element.name.text, { local: element.name.text });
88
- }
46
+ const internals = ts;
47
+ const files = new Map();
48
+ const classes = new Map();
49
+ const thunks = new WeakMap();
50
+ const where = (node) => {
51
+ const sf = node.getSourceFile();
52
+ const { line } = sf.getLineAndCharacterOfPosition(node.getStart(sf));
53
+ return `${sf.fileName}:${line + 1}`;
54
+ };
55
+ // ---- files: imports, declarations, exports ----
56
+ function info(file) {
57
+ const known = files.get(file);
58
+ if (known)
59
+ return known;
60
+ const text = host.read(file);
61
+ if (text === null || text === undefined)
62
+ throw new Error(`cannot read ${file}`);
63
+ const sourceFile = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
64
+ const record = { sourceFile, imports: new Map(), decls: new Map(), exports: new Map(), stars: [] };
65
+ files.set(file, record);
66
+ const exported = (node) => (internals.getSyntacticModifierFlags(node) & ts.ModifierFlags.Export) !== 0;
67
+ const isDefault = (node) => (internals.getSyntacticModifierFlags(node) & ts.ModifierFlags.Default) !== 0;
68
+ for (const statement of sourceFile.statements) {
69
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
70
+ const spec = statement.moduleSpecifier.text;
71
+ const clause = statement.importClause;
72
+ if (!clause)
73
+ continue;
74
+ if (clause.name)
75
+ record.imports.set(clause.name.text, { spec, name: 'default' });
76
+ if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
77
+ for (const element of clause.namedBindings.elements)
78
+ record.imports.set(element.name.text, { spec, name: (element.propertyName ?? element.name).text });
79
+ }
80
+ else if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings))
81
+ record.imports.set(clause.namedBindings.name.text, { spec, name: '*' });
82
+ }
83
+ else if ((ts.isClassDeclaration(statement) || ts.isFunctionDeclaration(statement)) && statement.name) {
84
+ record.decls.set(statement.name.text, ts.isClassDeclaration(statement) ? { kind: 'class', node: statement } : { kind: 'function', node: statement });
85
+ if (exported(statement))
86
+ record.exports.set(isDefault(statement) ? 'default' : statement.name.text, { local: statement.name.text });
87
+ }
88
+ else if (ts.isVariableStatement(statement)) {
89
+ for (const declaration of statement.declarationList.declarations) {
90
+ if (ts.isIdentifier(declaration.name)) {
91
+ record.decls.set(declaration.name.text, { kind: 'var', node: declaration });
92
+ if (exported(statement))
93
+ record.exports.set(declaration.name.text, { local: declaration.name.text });
94
+ }
95
+ else {
96
+ for (const element of declaration.name.elements ?? []) {
97
+ if (ts.isBindingElement(element) && ts.isIdentifier(element.name)) {
98
+ record.decls.set(element.name.text, { kind: 'opaque', node: element });
99
+ if (exported(statement))
100
+ record.exports.set(element.name.text, { local: element.name.text });
101
+ }
102
+ }
103
+ }
104
+ }
89
105
  }
90
- }
106
+ else if (ts.isEnumDeclaration(statement)) {
107
+ record.decls.set(statement.name.text, { kind: 'opaque', node: statement });
108
+ if (exported(statement))
109
+ record.exports.set(statement.name.text, { local: statement.name.text });
110
+ }
111
+ else if (ts.isExportDeclaration(statement) && !statement.isTypeOnly) {
112
+ const spec = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null;
113
+ if (statement.exportClause && ts.isNamedExports(statement.exportClause)) {
114
+ for (const element of statement.exportClause.elements) {
115
+ if (element.isTypeOnly)
116
+ continue;
117
+ record.exports.set(element.name.text, spec ? { spec, name: (element.propertyName ?? element.name).text } : { local: (element.propertyName ?? element.name).text });
118
+ }
119
+ }
120
+ else if (!statement.exportClause && spec)
121
+ record.stars.push(spec);
122
+ }
123
+ else if (ts.isExportAssignment(statement))
124
+ record.exports.set('default', { expression: statement.expression });
91
125
  }
92
- } else if (ts.isEnumDeclaration(statement)) {
93
- record.decls.set(statement.name.text, { kind: 'opaque', node: statement });
94
- if (exported(statement)) record.exports.set(statement.name.text, { local: statement.name.text });
95
- } else if (ts.isExportDeclaration(statement) && !statement.isTypeOnly) {
96
- const spec = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null;
97
- if (statement.exportClause && ts.isNamedExports(statement.exportClause)) {
98
- for (const element of statement.exportClause.elements) {
99
- if (element.isTypeOnly) continue;
100
- record.exports.set(element.name.text, spec ? { spec, name: (element.propertyName ?? element.name).text } : { local: (element.propertyName ?? element.name).text });
101
- }
102
- } else if (!statement.exportClause && spec) record.stars.push(spec);
103
- } else if (ts.isExportAssignment(statement)) record.exports.set('default', { expression: statement.expression });
104
- }
105
- return record;
106
- }
107
-
108
- const target = (file, spec) => host.resolve(file, spec);
109
-
110
- /** A top-level name of a file: its own declaration, or what an import binding leads to. */
111
- function resolveName(file, name, seen = new Set()) {
112
- const key = `${file}#${name}`;
113
- if (seen.has(key)) return null;
114
- seen.add(key);
115
- const record = info(file);
116
- const decl = record.decls.get(name);
117
- if (decl) return { file, name, ...decl };
118
- const binding = record.imports.get(name);
119
- if (!binding) return null;
120
- const to = target(file, binding.spec);
121
- if (to === null) return { ext: binding.spec, name: binding.name };
122
- if (binding.name === '*') return { opaque: true };
123
- return resolveExport(to, binding.name, seen);
124
- }
125
-
126
- /** A name a file exports, followed through re-exports and `export *`. */
127
- function resolveExport(file, name, seen = new Set()) {
128
- const record = info(file);
129
- const entry = record.exports.get(name);
130
- if (entry?.local) return resolveName(file, entry.local, seen);
131
- if (entry?.spec) {
132
- const to = target(file, entry.spec);
133
- return to === null ? { ext: entry.spec, name: entry.name } : resolveExport(to, entry.name, seen);
134
- }
135
- if (entry?.expression) return { file, name, kind: 'expression', node: entry.expression };
136
- for (const spec of record.stars) {
137
- const to = target(file, spec);
138
- if (to === null) continue;
139
- const found = resolveExport(to, name, seen);
140
- if (found) return found;
141
- }
142
- return null;
143
- }
144
-
145
- const classRef = (found) => {
146
- const key = `${found.file}#${found.name}`;
147
- if (!classes.has(key)) classes.set(key, { t: 'class', file: found.file, name: found.name, node: found.node });
148
- return classes.get(key);
149
- };
150
-
151
- // ---- values ----
152
- const thunk = (node, env) => {
153
- const key = env.cache;
154
- if (!thunks.has(key)) thunks.set(key, new Map());
155
- const memo = thunks.get(key);
156
- if (!memo.has(node)) memo.set(node, { t: 'thunk', node, env, done: false, value: undefined });
157
- return memo.get(node);
158
- };
159
- const lazy = (compute) => ({ t: 'thunk', compute, done: false, value: undefined });
160
- const force = (value) => {
161
- let current = value;
162
- while (current && current.t === 'thunk') {
163
- if (!current.done) {
164
- if (current.forcing) return free('circular value');
165
- current.forcing = true;
166
- current.value = current.compute ? current.compute() : ev(current.node, current.env);
167
- current.forcing = false;
168
- current.done = true;
169
- }
170
- current = current.value;
171
- }
172
- return current;
173
- };
174
- const newEnv = (file, extra = {}) => ({ file, vars: new Map(), cache: {}, depth: 0, ...extra });
175
-
176
- const TRANSPARENT = new Set([ts.SyntaxKind.ParenthesizedExpression, ts.SyntaxKind.AsExpression, ts.SyntaxKind.SatisfiesExpression, ts.SyntaxKind.NonNullExpression, ts.SyntaxKind.TypeAssertionExpression, ts.SyntaxKind.AwaitExpression]);
177
- const unwrapped = (node) => {
178
- let current = node;
179
- while (TRANSPARENT.has(current.kind)) current = current.expression;
180
- return current;
181
- };
182
-
183
- // ---- conditions: only what literals decide is folded; the rest is recorded and judged at the end ----
184
- const undecidedRecords = [];
185
- /** A choice the literals do not decide: both outcomes stay, and it is an error at the end unless they serve the same resolvers. */
186
- function undecided(conditionNode, alts) {
187
- undecidedRecords.push({ node: conditionNode, alts });
188
- return { t: 'alt', alts };
189
- }
190
-
191
- /** The truthiness of a value: true, false, or null when it depends on something unknown. */
192
- function truthiness(value) {
193
- switch (value.t) {
194
- case 'lit': return Boolean(value.v);
195
- case 'undef': case 'nul': return false;
196
- case 'obj': case 'arr': case 'class': case 'fn': case 'dyn': case 'ext': return true;
197
- case 'alt': {
198
- const all = value.alts.map((alt) => truthiness(force(alt)));
199
- return all.every((item) => item === all[0]) ? all[0] : null;
200
- }
201
- default: return null;
202
- }
203
- }
204
-
205
- /** Strict/loose equality of two forced values, or null when unknown. */
206
- function equality(a, b, loose) {
207
- if (a.t === 'free' || b.t === 'free' || a.t === 'alt' || b.t === 'alt') return null;
208
- const nullish = (v) => v.t === 'undef' || v.t === 'nul';
209
- if (nullish(a) && nullish(b)) return loose ? true : a.t === b.t;
210
- if (nullish(a) || nullish(b)) return ['lit', 'class', 'obj', 'arr'].includes(nullish(a) ? b.t : a.t) ? false : null;
211
- if (a.t === 'lit' && b.t === 'lit') return loose ? looseLiteralEqual(a.v, b.v) : a.v === b.v;
212
- if (a.t === 'class' && b.t === 'class') return a === b;
213
- return null;
214
- }
215
-
216
- /** The value of a condition expression: true, false, or null when literals do not decide it. */
217
- function condition(rawNode, env) {
218
- const node = unwrapped(rawNode);
219
- const K = ts.SyntaxKind;
220
- if (ts.isPrefixUnaryExpression(node) && node.operator === K.ExclamationToken) {
221
- const inner = condition(node.operand, env);
222
- return inner === null ? null : !inner;
223
- }
224
- if (ts.isBinaryExpression(node)) {
225
- const op = node.operatorToken.kind;
226
- if (op === K.AmpersandAmpersandToken || op === K.BarBarToken) {
227
- const left = condition(node.left, env);
228
- const right = condition(node.right, env);
229
- if (op === K.AmpersandAmpersandToken) return left === false || right === false ? false : left === true && right === true ? true : null;
230
- return left === true || right === true ? true : left === false && right === false ? false : null;
231
- }
232
- if (op === K.EqualsEqualsEqualsToken || op === K.ExclamationEqualsEqualsToken || op === K.EqualsEqualsToken || op === K.ExclamationEqualsToken) {
233
- const equal = equality(force(thunk(node.left, env)), force(thunk(node.right, env)), op === K.EqualsEqualsToken || op === K.ExclamationEqualsToken);
234
- return equal === null ? null : op === K.EqualsEqualsEqualsToken || op === K.EqualsEqualsToken ? equal : !equal;
235
- }
236
- }
237
- return truthiness(force(thunk(node, env)));
238
- }
239
-
240
- function ev(rawNode, env) {
241
- const node = unwrapped(rawNode);
242
- if (env.depth > 60) return free('evaluation too deep');
243
- if (ts.isIdentifier(node)) return identifier(node.text, node, env);
244
- if (ts.isArrayLiteralExpression(node)) return { t: 'arr', items: node.elements.map((element) => (ts.isSpreadElement(element) ? { t: 'spread', v: thunk(element.expression, env) } : thunk(element, env))) };
245
- if (ts.isObjectLiteralExpression(node)) return objectLiteral(node, env);
246
- if (ts.isConditionalExpression(node)) {
247
- const decided = condition(node.condition, env);
248
- if (decided === true) return thunk(node.whenTrue, env);
249
- if (decided === false) return thunk(node.whenFalse, env);
250
- return undecided(node.condition, [thunk(node.whenTrue, env), thunk(node.whenFalse, env)]);
251
- }
252
- if (ts.isBinaryExpression(node)) {
253
- const op = node.operatorToken.kind;
254
- if (op === ts.SyntaxKind.QuestionQuestionToken) {
255
- const left = force(thunk(node.left, env));
256
- if (left.t === 'undef' || left.t === 'nul') return thunk(node.right, env);
257
- return left.t === 'free' ? undecided(node.left, [left, thunk(node.right, env)]) : left;
258
- }
259
- if (op === ts.SyntaxKind.BarBarToken || op === ts.SyntaxKind.AmpersandAmpersandToken) {
260
- const decided = condition(node.left, env);
261
- const orElse = op === ts.SyntaxKind.BarBarToken;
262
- if (decided === null) return undecided(node.left, [thunk(node.right, env), orElse ? thunk(node.left, env) : undef]);
263
- return decided === orElse ? thunk(node.left, env) : thunk(node.right, env);
264
- }
265
- if (op === ts.SyntaxKind.EqualsToken) return thunk(node.right, env);
266
- return free('binary expression');
267
- }
268
- if (ts.isPropertyAccessExpression(node)) return member(thunk(node.expression, env), node.name.text);
269
- if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression)) return member(thunk(node.expression, env), node.argumentExpression.text);
270
- if (ts.isCallExpression(node)) return call(node, env);
271
- if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) return { t: 'fn', node, env };
272
- if (ts.isStringLiteralLike(node)) return { t: 'lit', v: node.text };
273
- if (ts.isNumericLiteral(node)) return { t: 'lit', v: Number(node.text) };
274
- if (node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword) return { t: 'lit', v: node.kind === ts.SyntaxKind.TrueKeyword };
275
- if (node.kind === ts.SyntaxKind.NullKeyword) return nul;
276
- return free(`unmodelled expression ${ts.SyntaxKind[node.kind]}`);
277
- }
278
-
279
- function identifier(name, node, env) {
280
- if (env.vars.has(name)) return env.vars.get(name);
281
- if (name === 'undefined') return undef;
282
- const found = resolveName(env.file, name);
283
- if (!found) return free(`unresolved name ${name}`);
284
- return declared(found);
285
- }
286
-
287
- function declared(found) {
288
- if (found.ext) return { t: 'ext', spec: found.ext, name: found.name };
289
- if (found.opaque || found.kind === 'opaque') return free('opaque declaration');
290
- if (found.kind === 'class') return classRef(found);
291
- const env = newEnv(found.file);
292
- if (found.kind === 'function') return { t: 'fn', node: found.node, env };
293
- if (found.kind === 'expression') return thunk(found.node, env);
294
- const initializer = found.node.initializer;
295
- return initializer ? thunk(initializer, newEnv(found.file, { cache: found.node })) : free('declaration without a value');
296
- }
297
-
298
- function objectLiteral(node, env) {
299
- const props = new Map();
300
- let open = false;
301
- for (const property of node.properties) {
302
- if (ts.isPropertyAssignment(property) && (ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name))) props.set(property.name.text, thunk(property.initializer, env));
303
- else if (ts.isShorthandPropertyAssignment(property)) props.set(property.name.text, thunk(property.name, env));
304
- else if (ts.isSpreadAssignment(property)) {
305
- const spread = force(thunk(property.expression, env));
306
- if (spread.t === 'obj') {
307
- for (const [key, value] of spread.props) props.set(key, value);
308
- open = open || spread.open;
309
- } else if (spread.t === 'dyn') {
310
- props.set('module', spread.module);
311
- props.set('imports', { t: 'arr', items: spread.imports });
312
- props.set('providers', { t: 'arr', items: spread.providers });
313
- } else open = true;
314
- } else if (ts.isMethodDeclaration(property) && ts.isIdentifier(property.name)) props.set(property.name.text, { t: 'fn', node: property, env });
315
- else open = true;
316
- }
317
- return { t: 'obj', props, open };
318
- }
319
-
320
- function member(baseThunk, key) {
321
- return lazy(() => {
322
- const base = force(baseThunk);
323
- switch (base.t) {
324
- case 'obj':
325
- return base.props.get(key) ?? (base.open ? free(`property ${key} of an open object`) : undef);
326
- case 'dyn':
327
- return key === 'module' ? base.module : key === 'imports' || key === 'providers' ? { t: 'arr', items: base[key] } : undef;
328
- case 'alt':
329
- return { t: 'alt', alts: base.alts.map((alt) => member(alt, key)) };
330
- case 'class': {
331
- const property = base.node.members.find((item) => ts.isPropertyDeclaration(item) && item.name && ts.isIdentifier(item.name) && item.name.text === key && item.initializer);
332
- return property ? thunk(property.initializer, newEnv(base.file, { cache: property })) : free(`static ${key} of ${base.name}`);
126
+ return record;
127
+ }
128
+ const target = (file, spec) => host.resolve(file, spec);
129
+ /** A top-level name of a file: its own declaration, or what an import binding leads to. */
130
+ function resolveName(file, name, seen = new Set()) {
131
+ const key = `${file}#${name}`;
132
+ if (seen.has(key))
133
+ return null;
134
+ seen.add(key);
135
+ const record = info(file);
136
+ const decl = record.decls.get(name);
137
+ if (decl)
138
+ return { file, name, ...decl };
139
+ const binding = record.imports.get(name);
140
+ if (!binding)
141
+ return null;
142
+ const to = target(file, binding.spec);
143
+ if (to === null)
144
+ return { ext: binding.spec, name: binding.name };
145
+ if (binding.name === '*')
146
+ return { opaque: true };
147
+ return resolveExport(to, binding.name, seen);
148
+ }
149
+ /** A name a file exports, followed through re-exports and `export *`. */
150
+ function resolveExport(file, name, seen = new Set()) {
151
+ const record = info(file);
152
+ const entry = record.exports.get(name);
153
+ if (entry && 'local' in entry)
154
+ return resolveName(file, entry.local, seen);
155
+ if (entry && 'spec' in entry) {
156
+ const to = target(file, entry.spec);
157
+ return to === null ? { ext: entry.spec, name: entry.name } : resolveExport(to, entry.name, seen);
158
+ }
159
+ if (entry && 'expression' in entry)
160
+ return { file, name, kind: 'expression', node: entry.expression };
161
+ for (const spec of record.stars) {
162
+ const to = target(file, spec);
163
+ if (to === null)
164
+ continue;
165
+ const found = resolveExport(to, name, seen);
166
+ if (found)
167
+ return found;
333
168
  }
334
- case 'undef':
335
- case 'nul':
336
- return undef;
337
- default:
338
- return free(`property ${key} of ${base.t}`);
339
- }
340
- });
341
- }
342
-
343
- // ---- calls ----
344
- function call(node, env) {
345
- const callee = unwrapped(node.expression);
346
- const args = node.arguments.map((argument) => thunk(argument, env));
347
- if (callee.kind === ts.SyntaxKind.SuperKeyword) return free('super call');
348
- if (ts.isPropertyAccessExpression(callee)) {
349
- if (callee.expression.kind === ts.SyntaxKind.SuperKeyword) return superCall(env);
350
- const base = force(thunk(callee.expression, env));
351
- return methodCall(base, callee.name.text, args, node);
352
- }
353
- const target = force(thunk(callee, env));
354
- if (target.t === 'ext' && target.spec === NEST_COMMON && target.name === 'forwardRef') return args[0] ? lazy(() => callFunction(force(args[0]), [])) : free('forwardRef without a value');
355
- if (target.t === 'fn') return callFunction(target, args);
356
- return free(`call of ${target.t}`);
357
- }
358
-
359
- /** `super.register(...)` of a class built on Nest's ConfigurableModuleBuilder: the class itself, no user additions. */
360
- const superCall = (env) => ({ t: 'dyn', module: env.thisClass ?? free('super outside a class'), imports: [], providers: [], args: [] });
361
-
362
- /** Array methods over a list whose items are known (`arr`) or unknown (`free`: one representative item). */
363
- function arrayMethod(base, name, args) {
364
- const items = base.t === 'arr' ? base.items : [free('an item of a list from the options of a deployment')];
365
- if (name === 'map' || name === 'flatMap') {
366
- const fn = args[0] ? force(args[0]) : null;
367
- if (fn?.t !== 'fn') return free(`${name} without a function`);
368
- const mapped = { t: 'arr', items: items.map((item) => callFunction(fn, [item, undef])) };
369
- return base.t === 'arr' ? mapped : undecided(fn.node, [mapped, { t: 'arr', items: [] }]);
370
- }
371
- if (name === 'filter' || name === 'slice' || name === 'sort' || name === 'reverse') return base;
372
- if (name === 'concat') return { t: 'arr', items: [{ t: 'spread', v: base }, ...args.map((argument) => ({ t: 'spread', v: argument }))] };
373
- return null;
374
- }
375
-
376
- function methodCall(base, name, args, node) {
377
- if ((base.t === 'arr' || base.t === 'free') && ['map', 'flatMap', 'filter', 'slice', 'sort', 'reverse', 'concat'].includes(name)) {
378
- const result = arrayMethod(base, name, args);
379
- if (result) return result;
380
- }
381
- if (base.t === 'alt') return { t: 'alt', alts: base.alts.map((alt) => lazy(() => methodCall(force(alt), name, args, node))) };
382
- if (base.t === 'ext') return { t: 'dyn', module: base, imports: listOf(args[0], 'imports'), providers: [], args, ext: name };
383
- if (base.t === 'class') {
384
- const found = staticMethod(base, name);
385
- if (found) return callFunction({ t: 'fn', node: found.method, env: newEnv(found.owner.file, { thisClass: base }) }, args);
386
- return { t: 'dyn', module: base, imports: [], providers: [], args };
387
- }
388
- return free(`method ${name} of ${base.t} at ${where(node)}`);
389
- }
390
-
391
- /** The static method of a class or of its in-repository base classes; null when none (the base is external). */
392
- function staticMethod(cls, name) {
393
- const method = cls.node.members.find((item) => ts.isMethodDeclaration(item) && item.name && ts.isIdentifier(item.name) && item.name.text === name && (ts.getSyntacticModifierFlags(item) & ts.ModifierFlags.Static) !== 0 && item.body);
394
- if (method) return { method, owner: cls };
395
- const heritage = cls.node.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
396
- if (!heritage) return null;
397
- const base = force(thunk(heritage.expression, newEnv(cls.file)));
398
- return base.t === 'class' ? staticMethod(base, name) : null;
399
- }
400
-
401
- /** The `imports` array a call's first argument carries (forRootAsync-style options), as a list of thunks. */
402
- function listOf(argument, key) {
403
- if (!argument) return [];
404
- const options = force(argument);
405
- if (options.t !== 'obj' || !options.props.has(key)) return [];
406
- return [options.props.get(key)];
407
- }
408
-
409
- function callFunction(fn, args) {
410
- if (fn.t !== 'fn') return free(`call of ${fn.t}`);
411
- const env = newEnv(fn.env.file, { ...fn.env, vars: new Map(fn.env.vars), depth: fn.env.depth + 1, cache: {} });
412
- fn.node.parameters.forEach((parameter, index) => bindParameter(parameter.name, args[index] ?? undef, env));
413
- const body = fn.node.body;
414
- if (!body) return free('function without a body');
415
- if (!ts.isBlock(body)) return thunk(body, env);
416
- const outcome = runStatements(body.statements, env);
417
- return outcome.returned ? outcome.value : undef;
418
- }
419
-
420
- function bindParameter(name, value, env) {
421
- if (ts.isIdentifier(name)) env.vars.set(name.text, value);
422
- else if (ts.isObjectBindingPattern(name)) {
423
- for (const element of name.elements) {
424
- const key = (element.propertyName ?? element.name).text;
425
- if (ts.isIdentifier(element.name)) env.vars.set(element.name.text, member(value, key));
426
- }
427
- }
428
- }
429
-
430
- /** True when a statement returns or changes a list a later `return` may hand back: what an undecided branch must not hide. */
431
- function hasEffect(node) {
432
- let found = false;
433
- const visit = (child) => {
434
- if (found) return;
435
- if (ts.isReturnStatement(child) || (ts.isBinaryExpression(child) && child.operatorToken.kind === ts.SyntaxKind.EqualsToken)) found = true;
436
- else if (ts.isCallExpression(child) && ts.isPropertyAccessExpression(child.expression) && ['push', 'unshift', 'splice'].includes(child.expression.name.text)) found = true;
437
- else if (!ts.isFunctionLike(child)) ts.forEachChild(child, visit);
169
+ return null;
170
+ }
171
+ const classRef = (found) => {
172
+ const key = `${found.file}#${found.name}`;
173
+ const known = classes.get(key);
174
+ if (known)
175
+ return known;
176
+ const created = { t: 'class', file: found.file, name: found.name, node: found.node };
177
+ classes.set(key, created);
178
+ return created;
438
179
  };
439
- visit(node);
440
- return found;
441
- }
442
-
443
- const SILENT_STATEMENTS = new Set([ts.SyntaxKind.EmptyStatement, ts.SyntaxKind.ThrowStatement, ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.ClassDeclaration, ts.SyntaxKind.InterfaceDeclaration, ts.SyntaxKind.TypeAliasDeclaration]);
444
-
445
- /**
446
- * Runs statements in order against an environment: declarations bind lazily, `if` follows the branch its condition decides
447
- * (an undecidable condition over statements that return or change a list is an error), `push` appends to a local list and
448
- * `return` ends the run. Answers `{ returned, value }`. A loop, switch or try that returns or changes a list is an error.
449
- */
450
- function runStatements(statements, env) {
451
- for (const statement of statements) {
452
- if (ts.isVariableStatement(statement)) {
453
- for (const declaration of statement.declarationList.declarations) {
454
- if (declaration.initializer) bindParameter(declaration.name, thunk(declaration.initializer, env), env);
180
+ // ---- values ----
181
+ const thunk = (node, env) => {
182
+ const key = env.cache;
183
+ let memo = thunks.get(key);
184
+ if (!memo) {
185
+ memo = new Map();
186
+ thunks.set(key, memo);
455
187
  }
456
- } else if (ts.isReturnStatement(statement)) return { returned: true, value: statement.expression ? thunk(statement.expression, env) : undef };
457
- else if (ts.isIfStatement(statement)) {
458
- const decided = condition(statement.expression, env);
459
- if (decided === null && hasEffect(statement)) throw new Error(`${where(statement)}: the condition ${statement.expression.getText()} cannot be decided from literals and a branch returns or adds providers; the schema is not known`);
460
- const branch = decided === false ? statement.elseStatement : decided === true ? statement.thenStatement : null;
461
- if (branch) {
462
- const outcome = runStatements(ts.isBlock(branch) ? branch.statements : [branch], env);
463
- if (outcome.returned) return outcome;
188
+ let made = memo.get(node);
189
+ if (!made) {
190
+ made = { t: 'thunk', node, env, done: false, value: undefined };
191
+ memo.set(node, made);
464
192
  }
465
- } else if (ts.isBlock(statement)) {
466
- const outcome = runStatements(statement.statements, env);
467
- if (outcome.returned) return outcome;
468
- } else if (ts.isExpressionStatement(statement)) pushStatement(statement, env);
469
- else if (!SILENT_STATEMENTS.has(statement.kind) && hasEffect(statement)) throw new Error(`${where(statement)}: a ${ts.SyntaxKind[statement.kind]} that returns or changes a list is not modeled by this reader`);
470
- }
471
- return { returned: false, value: undef };
472
- }
473
-
474
- /** `list.push(...)` on a local list and `name = value` on a local name; any other expression statement has no effect here. */
475
- function pushStatement(statement, env) {
476
- const expression = unwrapped(statement.expression);
477
- if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isIdentifier(expression.left) && env.vars.has(expression.left.text)) {
478
- env.vars.set(expression.left.text, thunk(expression.right, env));
479
- return;
480
- }
481
- if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression)) return;
482
- const name = expression.expression.name.text;
483
- if (name !== 'push' && name !== 'unshift') return;
484
- const list = force(thunk(expression.expression.expression, env));
485
- if (list.t !== 'arr') throw new Error(`${where(statement)}: ${name} on something that is not a local list`);
486
- const added = expression.arguments.map((argument) => (ts.isSpreadElement(argument) ? { t: 'spread', v: thunk(argument.expression, env) } : thunk(argument, env)));
487
- if (name === 'push') list.items.push(...added); else list.items.unshift(...added);
488
- }
489
-
490
- // ---- modules ----
491
- const decoratorsOf = (node) => (ts.canHaveDecorators?.(node) ? ts.getDecorators(node) ?? [] : node.decorators ?? []);
492
-
493
- /** The `@Module({...})` metadata object of a class (an obj value), or null. */
494
- function moduleMetadata(cls) {
495
- for (const decorator of decoratorsOf(cls.node)) {
496
- const expression = decorator.expression;
497
- if (!ts.isCallExpression(expression)) continue;
498
- const callee = force(thunk(expression.expression, newEnv(cls.file)));
499
- if (callee.t === 'ext' && callee.spec === NEST_COMMON && callee.name === 'Module') {
500
- const argument = expression.arguments[0];
501
- const metadata = argument ? force(thunk(argument, newEnv(cls.file, { thisClass: cls }))) : { t: 'obj', props: new Map(), open: false };
502
- if (metadata.t !== 'obj' || metadata.open) throw new Error(`${where(expression)}: the @Module metadata of ${cls.name} cannot be decided`);
503
- return metadata;
504
- }
505
- }
506
- return null;
507
- }
508
-
509
- /** Flattens a value into its module/provider entries: arrays, spreads and both branches of a conditional. */
510
- function entries(value, out = []) {
511
- const v = force(value);
512
- if (v.t === 'arr') for (const item of v.items) entries(item.t === 'spread' ? item.v : item, out);
513
- else if (v.t === 'alt') for (const alt of v.alts) entries(alt, out);
514
- else if (v.t !== 'undef' && v.t !== 'nul' && !(v.t === 'lit' && !v.v)) out.push(v);
515
- return out;
516
- }
517
-
518
- const isGraphqlServer = (module) => module.t === 'ext' && module.spec === NEST_GRAPHQL && module.name === 'GraphQLModule';
519
-
520
- /** A module entry as `{ module, dyn }`: a class, an external module, a dynamic module, or a `{ module, ... }` literal. */
521
- function normalize(value, origin) {
522
- if (value.t === 'class' || value.t === 'ext') return { module: value, dyn: null, key: value.t === 'class' ? value : `${value.spec}#${value.name}` };
523
- if (value.t === 'dyn') return { module: force(value.module), dyn: value, key: value };
524
- if (value.t === 'obj' && value.props.has('module')) {
525
- if (value.open && !(value.props.has('imports') && value.props.has('providers'))) throw new Error(`${origin}: a module object with an unknown spread may add imports or providers`);
526
- const dyn = { t: 'dyn', module: value.props.get('module'), imports: value.props.has('imports') ? [value.props.get('imports')] : [], providers: value.props.has('providers') ? [value.props.get('providers')] : [], args: [] };
527
- return { module: force(dyn.module), dyn, key: value };
528
- }
529
- throw new Error(`${origin}: an import cannot be decided (${value.why ?? value.t})`);
530
- }
531
-
532
- /**
533
- * Walks the module graph from a root entry. Answers the module instances `{ module, providers, imports, server }` in
534
- * discovery order; `imports` are instances of the same list. A static class is one instance; every dynamic module value is
535
- * its own instance (Nest keys them by their metadata).
536
- */
537
- function walk(root) {
538
- const order = [];
539
- const seen = new Map();
540
- function visit(entry, origin) {
541
- const nodes = [];
542
- for (const value of entries(entry)) {
543
- const { module, dyn, key } = normalize(value, origin);
544
- if (module.t === 'free') throw new Error(`${origin}: a dynamic module's class cannot be decided (${module.why})`);
545
- if (seen.has(key)) {
546
- nodes.push(seen.get(key));
547
- continue;
193
+ return made;
194
+ };
195
+ const lazy = (compute) => ({ t: 'thunk', compute, done: false, value: undefined });
196
+ const force = (value) => {
197
+ let current = value;
198
+ while (current && current.t === 'thunk') {
199
+ if (!current.done) {
200
+ if (current.forcing)
201
+ return free('circular value');
202
+ current.forcing = true;
203
+ current.value = current.compute ? current.compute() : ev(current.node, current.env); // a thunk without compute carries its node and environment
204
+ current.forcing = false;
205
+ current.done = true;
206
+ }
207
+ current = current.value;
548
208
  }
549
- const node = { module, dynamic: dyn, providers: [], imports: [], server: null };
550
- seen.set(key, node);
551
- order.push(node);
552
- nodes.push(node);
553
- const children = [];
554
- const statics = module.t === 'class' ? moduleMetadata(module) : null;
555
- if (statics?.props.has('imports')) children.push(statics.props.get('imports'));
556
- if (statics?.props.has('providers')) node.providers.push(statics.props.get('providers'));
557
- if (dyn) {
558
- children.push(...dyn.imports);
559
- node.providers.push(...dyn.providers);
560
- if (isGraphqlServer(module)) node.server = dyn;
209
+ return current; // a forced thunk always holds a value
210
+ };
211
+ const newEnv = (file, extra = {}) => ({ file, vars: new Map(), cache: {}, depth: 0, ...extra });
212
+ const TRANSPARENT = new Set([ts.SyntaxKind.ParenthesizedExpression, ts.SyntaxKind.AsExpression, ts.SyntaxKind.SatisfiesExpression, ts.SyntaxKind.NonNullExpression, ts.SyntaxKind.TypeAssertionExpression, ts.SyntaxKind.AwaitExpression]);
213
+ const unwrapped = (node) => {
214
+ let current = node;
215
+ while (TRANSPARENT.has(current.kind))
216
+ current = current.expression; // every kind in TRANSPARENT wraps an expression
217
+ return current;
218
+ };
219
+ // ---- conditions: only what literals decide is folded; the rest is recorded and judged at the end ----
220
+ const undecidedRecords = [];
221
+ /** A choice the literals do not decide: both outcomes stay, and it is an error at the end unless they serve the same resolvers. */
222
+ function undecided(conditionNode, alts) {
223
+ undecidedRecords.push({ node: conditionNode, alts });
224
+ return { t: 'alt', alts };
225
+ }
226
+ /** The truthiness of a value: true, false, or null when it depends on something unknown. */
227
+ function truthiness(value) {
228
+ switch (value.t) {
229
+ case 'lit': return Boolean(value.v);
230
+ case 'undef':
231
+ case 'nul': return false;
232
+ case 'obj':
233
+ case 'arr':
234
+ case 'class':
235
+ case 'fn':
236
+ case 'dyn':
237
+ case 'ext': return true;
238
+ case 'alt': {
239
+ const all = value.alts.map((alt) => truthiness(force(alt)));
240
+ return all.every((item) => item === all[0]) ? all[0] ?? null : null;
241
+ }
242
+ default: return null;
243
+ }
244
+ }
245
+ /** Strict/loose equality of two forced values, or null when unknown. */
246
+ function equality(a, b, loose) {
247
+ if (a.t === 'free' || b.t === 'free' || a.t === 'alt' || b.t === 'alt')
248
+ return null;
249
+ const nullish = (v) => v.t === 'undef' || v.t === 'nul';
250
+ if (nullish(a) && nullish(b))
251
+ return loose ? true : a.t === b.t;
252
+ if (nullish(a) || nullish(b))
253
+ return ['lit', 'class', 'obj', 'arr'].includes(nullish(a) ? b.t : a.t) ? false : null;
254
+ if (a.t === 'lit' && b.t === 'lit')
255
+ return loose ? looseLiteralEqual(a.v, b.v) : a.v === b.v;
256
+ if (a.t === 'class' && b.t === 'class')
257
+ return a === b;
258
+ return null;
259
+ }
260
+ /** The value of a condition expression: true, false, or null when literals do not decide it. */
261
+ function condition(rawNode, env) {
262
+ const node = unwrapped(rawNode);
263
+ const K = ts.SyntaxKind;
264
+ if (ts.isPrefixUnaryExpression(node) && node.operator === K.ExclamationToken) {
265
+ const inner = condition(node.operand, env);
266
+ return inner === null ? null : !inner;
561
267
  }
562
- const name = module.t === 'class' ? `${module.name} (${module.file})` : `${module.name}`;
563
- for (const child of children) node.imports.push(...visit(child, name));
564
- }
565
- return nodes;
566
- }
567
- visit(root, 'the application root');
568
- return order;
569
- }
570
-
571
- /** The instances of the modules a GraphQL server reads: all of them, or the `include` whitelist and its transitive imports. */
572
- function servedNodes(nodes, include) {
573
- if (include.length === 0) return nodes;
574
- const served = new Set();
575
- const pending = nodes.filter((node) => include.includes(node.module));
576
- while (pending.length) {
577
- const node = pending.pop();
578
- if (served.has(node)) continue;
579
- served.add(node);
580
- pending.push(...node.imports);
581
- }
582
- return nodes.filter((node) => served.has(node));
583
- }
584
-
585
- /** The provider classes of instances: plain class providers and `useClass` providers, unique, in order. */
586
- function providerClasses(nodes) {
587
- const found = [];
588
- for (const node of nodes) {
589
- for (const list of node.providers) {
590
- for (const provider of entries(list)) {
591
- const cls = provider.t === 'class' ? provider : provider.t === 'obj' && provider.props.has('useClass') ? force(provider.props.get('useClass')) : null;
592
- if (provider.t === 'free') throw new Error(`${node.module.name ?? 'a module'}: a provider list cannot be decided (${provider.why})`);
593
- if (cls && cls.t === 'class' && !found.includes(cls)) found.push(cls);
268
+ if (ts.isBinaryExpression(node)) {
269
+ const op = node.operatorToken.kind;
270
+ if (op === K.AmpersandAmpersandToken || op === K.BarBarToken) {
271
+ const left = condition(node.left, env);
272
+ const right = condition(node.right, env);
273
+ if (op === K.AmpersandAmpersandToken)
274
+ return left === false || right === false ? false : left === true && right === true ? true : null;
275
+ return left === true || right === true ? true : left === false && right === false ? false : null;
276
+ }
277
+ if (op === K.EqualsEqualsEqualsToken || op === K.ExclamationEqualsEqualsToken || op === K.EqualsEqualsToken || op === K.ExclamationEqualsToken) {
278
+ const equal = equality(force(thunk(node.left, env)), force(thunk(node.right, env)), op === K.EqualsEqualsToken || op === K.ExclamationEqualsToken);
279
+ return equal === null ? null : op === K.EqualsEqualsEqualsToken || op === K.EqualsEqualsToken ? equal : !equal;
280
+ }
594
281
  }
595
- }
596
- }
597
- return found;
598
- }
599
-
600
- /** True when a class carries `@Resolver` or `@Scalar` of @nestjs/graphql (by where the decorator was imported from). */
601
- function graphqlKind(cls) {
602
- for (const decorator of decoratorsOf(cls.node)) {
603
- const expression = ts.isCallExpression(decorator.expression) ? decorator.expression.expression : decorator.expression;
604
- const callee = force(thunk(expression, newEnv(cls.file)));
605
- if (callee.t === 'ext' && callee.spec === NEST_GRAPHQL && (callee.name === 'Resolver' || callee.name === 'Scalar')) return callee.name;
606
- }
607
- return null;
608
- }
609
-
610
- /** The options of a GraphQL server: its literal, or what the factory of `forRootAsync` returns. */
611
- function serverOptions(server, origin) {
612
- const argument = server.args[0];
613
- if (!argument) return { include: [] };
614
- let options = force(argument);
615
- if (options.t === 'obj' && options.props.has('useFactory')) {
616
- const result = callFunction(force(options.props.get('useFactory')), (options.props.has('inject') ? entries(options.props.get('inject')) : []).map(() => free('injected value')));
617
- options = force(result);
618
- }
619
- const objects = options.t === 'alt' ? options.alts.map(force) : [options];
620
- const props = new Map();
621
- for (const object of objects) {
622
- if (object.t !== 'obj' || object.open) throw new Error(`${origin}: the GraphQL server options cannot be decided (${object.why ?? (object.open ? 'an unknown spread' : object.t)})`);
623
- for (const [key, value] of object.props) props.set(key, value);
624
- }
625
- for (const key of SCHEMA_OPTIONS_NOT_MODELED) {
626
- if (props.has(key)) throw new Error(`${origin}: GraphQL server option ${key} changes the schema and is not modeled by this reader`);
627
- }
628
- const auto = props.has('autoSchemaFile') ? force(props.get('autoSchemaFile')) : undef;
629
- if (auto.t === 'undef' || (auto.t === 'lit' && auto.v === false)) throw new Error(`${origin}: the GraphQL server is not code-first (no autoSchemaFile)`);
630
- const include = props.has('include') ? entries(props.get('include')) : [];
631
- if (include.some((item) => item.t !== 'class')) throw new Error(`${origin}: the GraphQL include list cannot be decided`);
632
- return { include };
633
- }
634
-
635
- /** The keys of the resolver and scalar classes one branch of an undecided choice would serve. */
636
- function graphqlClassKeys(alt) {
637
- const keys = new Set();
638
- for (const value of entries(alt)) {
639
- if (value.t === 'class' && graphqlKind(value)) keys.add(`${value.file}#${value.name}`);
640
- const moduleLike = value.t === 'dyn' || (value.t === 'obj' && value.props.has('module')) || (value.t === 'class' && moduleMetadata(value) !== null);
641
- if (!moduleLike) continue;
642
- for (const cls of providerClasses(walk(value))) if (graphqlKind(cls)) keys.add(`${cls.file}#${cls.name}`);
643
- }
644
- return keys;
645
- }
646
-
647
- /**
648
- * Every choice the literals did not decide (a condition on the options of a deployment, an unknown list) must serve the same
649
- * resolvers whichever way it goes; when the branches differ the schema is not known and that is an error, never a guess.
650
- */
651
- function assertUndecidedHarmless() {
652
- for (let at = 0; at < undecidedRecords.length; at += 1) {
653
- const { node, alts } = undecidedRecords[at];
654
- const [first, ...rest] = alts.map(graphqlClassKeys);
655
- for (const other of rest) {
656
- const differing = [...first].filter((key) => !other.has(key)).concat([...other].filter((key) => !first.has(key)));
657
- if (differing.length) throw new Error(`${where(node)}: ${node.getText()} cannot be decided from literals and its branches serve different resolvers (${differing.map((key) => key.split('#')[1]).join(', ')})`);
658
- }
659
- }
660
- }
661
-
662
- /**
663
- * Composes an app root file. Answers null when the file exports no `AppModule` class or its module graph holds no GraphQL server, else
664
- * `{ resolvers: [{ file, name }], scalars: [{ file, name }], include: [{ file, name }] }`.
665
- */
666
- function compose(appFile, exportName = 'AppModule') {
667
- const found = resolveExport(appFile, exportName);
668
- if (!found || found.kind !== 'class') return null;
669
- const root = classRef(found);
670
- const register = staticMethod(root, 'register');
671
- const rootValue = register ? { t: 'arr', items: [root, callFunction({ t: 'fn', node: register.method, env: newEnv(register.owner.file, { thisClass: root }) }, [free('the options of a deployment')])] } : root;
672
- const nodes = walk(rootValue);
673
- const servers = nodes.filter((node) => node.server);
674
- if (servers.length === 0) return null;
675
- if (servers.length > 1) throw new Error(`${appFile} composes ${servers.length} GraphQL servers; a contract snapshot describes exactly one`);
676
- const { include } = serverOptions(servers[0].server, `${exportName} of ${appFile}`);
677
- const classesOf = providerClasses(servedNodes(nodes, include));
678
- assertUndecidedHarmless();
679
- const pick = (kind) => classesOf.filter((cls) => graphqlKind(cls) === kind).map((cls) => ({ file: cls.file, name: cls.name }));
680
- return { resolvers: pick('Resolver'), scalars: pick('Scalar'), include: include.map((cls) => ({ file: cls.file, name: cls.name })) };
681
- }
682
-
683
- return { compose };
282
+ return truthiness(force(thunk(node, env)));
283
+ }
284
+ function ev(rawNode, env) {
285
+ const node = unwrapped(rawNode);
286
+ if (env.depth > 60)
287
+ return free('evaluation too deep');
288
+ if (ts.isIdentifier(node))
289
+ return identifier(node.text, node, env);
290
+ if (ts.isArrayLiteralExpression(node))
291
+ return { t: 'arr', items: node.elements.map((element) => (ts.isSpreadElement(element) ? { t: 'spread', v: thunk(element.expression, env) } : thunk(element, env))) };
292
+ if (ts.isObjectLiteralExpression(node))
293
+ return objectLiteral(node, env);
294
+ if (ts.isConditionalExpression(node)) {
295
+ const decided = condition(node.condition, env);
296
+ if (decided === true)
297
+ return thunk(node.whenTrue, env);
298
+ if (decided === false)
299
+ return thunk(node.whenFalse, env);
300
+ return undecided(node.condition, [thunk(node.whenTrue, env), thunk(node.whenFalse, env)]);
301
+ }
302
+ if (ts.isBinaryExpression(node)) {
303
+ const op = node.operatorToken.kind;
304
+ if (op === ts.SyntaxKind.QuestionQuestionToken) {
305
+ const left = force(thunk(node.left, env));
306
+ if (left.t === 'undef' || left.t === 'nul')
307
+ return thunk(node.right, env);
308
+ return left.t === 'free' ? undecided(node.left, [left, thunk(node.right, env)]) : left;
309
+ }
310
+ if (op === ts.SyntaxKind.BarBarToken || op === ts.SyntaxKind.AmpersandAmpersandToken) {
311
+ const decided = condition(node.left, env);
312
+ const orElse = op === ts.SyntaxKind.BarBarToken;
313
+ if (decided === null)
314
+ return undecided(node.left, [thunk(node.right, env), orElse ? thunk(node.left, env) : undef]);
315
+ return decided === orElse ? thunk(node.left, env) : thunk(node.right, env);
316
+ }
317
+ if (op === ts.SyntaxKind.EqualsToken)
318
+ return thunk(node.right, env);
319
+ return free('binary expression');
320
+ }
321
+ if (ts.isPropertyAccessExpression(node))
322
+ return member(thunk(node.expression, env), node.name.text);
323
+ if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression))
324
+ return member(thunk(node.expression, env), node.argumentExpression.text);
325
+ if (ts.isCallExpression(node))
326
+ return call(node, env);
327
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node))
328
+ return { t: 'fn', node, env };
329
+ if (ts.isStringLiteralLike(node))
330
+ return { t: 'lit', v: node.text };
331
+ if (ts.isNumericLiteral(node))
332
+ return { t: 'lit', v: Number(node.text) };
333
+ if (node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword)
334
+ return { t: 'lit', v: node.kind === ts.SyntaxKind.TrueKeyword };
335
+ if (node.kind === ts.SyntaxKind.NullKeyword)
336
+ return nul;
337
+ return free(`unmodelled expression ${ts.SyntaxKind[node.kind]}`);
338
+ }
339
+ function identifier(name, _node, env) {
340
+ if (env.vars.has(name))
341
+ return env.vars.get(name);
342
+ if (name === 'undefined')
343
+ return undef;
344
+ const found = resolveName(env.file, name);
345
+ if (!found)
346
+ return free(`unresolved name ${name}`);
347
+ return declared(found);
348
+ }
349
+ function declared(found) {
350
+ if ('ext' in found)
351
+ return { t: 'ext', spec: found.ext, name: found.name };
352
+ if ('opaque' in found || found.kind === 'opaque')
353
+ return free('opaque declaration');
354
+ if (found.kind === 'class')
355
+ return classRef(found);
356
+ const env = newEnv(found.file);
357
+ if (found.kind === 'function')
358
+ return { t: 'fn', node: found.node, env };
359
+ if (found.kind === 'expression')
360
+ return thunk(found.node, env);
361
+ const initializer = found.node.initializer;
362
+ return initializer ? thunk(initializer, newEnv(found.file, { cache: found.node })) : free('declaration without a value');
363
+ }
364
+ function objectLiteral(node, env) {
365
+ const props = new Map();
366
+ let open = false;
367
+ for (const property of node.properties) {
368
+ if (ts.isPropertyAssignment(property) && (ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)))
369
+ props.set(property.name.text, thunk(property.initializer, env));
370
+ else if (ts.isShorthandPropertyAssignment(property))
371
+ props.set(property.name.text, thunk(property.name, env));
372
+ else if (ts.isSpreadAssignment(property)) {
373
+ const spread = force(thunk(property.expression, env));
374
+ if (spread.t === 'obj') {
375
+ for (const [key, value] of spread.props)
376
+ props.set(key, value);
377
+ open = open || spread.open;
378
+ }
379
+ else if (spread.t === 'dyn') {
380
+ props.set('module', spread.module);
381
+ props.set('imports', { t: 'arr', items: spread.imports });
382
+ props.set('providers', { t: 'arr', items: spread.providers });
383
+ }
384
+ else
385
+ open = true;
386
+ }
387
+ else if (ts.isMethodDeclaration(property) && ts.isIdentifier(property.name))
388
+ props.set(property.name.text, { t: 'fn', node: property, env });
389
+ else
390
+ open = true;
391
+ }
392
+ return { t: 'obj', props, open };
393
+ }
394
+ function member(baseThunk, key) {
395
+ return lazy(() => {
396
+ const base = force(baseThunk);
397
+ switch (base.t) {
398
+ case 'obj':
399
+ return base.props.get(key) ?? (base.open ? free(`property ${key} of an open object`) : undef);
400
+ case 'dyn':
401
+ return key === 'module' ? base.module : key === 'imports' || key === 'providers' ? { t: 'arr', items: base[key] } : undef;
402
+ case 'alt':
403
+ return { t: 'alt', alts: base.alts.map((alt) => member(alt, key)) };
404
+ case 'class': {
405
+ const property = base.node.members.find((item) => ts.isPropertyDeclaration(item) && item.name !== undefined && ts.isIdentifier(item.name) && item.name.text === key && item.initializer !== undefined);
406
+ return property ? thunk(property.initializer, newEnv(base.file, { cache: property })) : free(`static ${key} of ${base.name}`);
407
+ }
408
+ case 'undef':
409
+ case 'nul':
410
+ return undef;
411
+ default:
412
+ return free(`property ${key} of ${base.t}`);
413
+ }
414
+ });
415
+ }
416
+ // ---- calls ----
417
+ function call(node, env) {
418
+ const callee = unwrapped(node.expression);
419
+ const args = node.arguments.map((argument) => thunk(argument, env));
420
+ if (callee.kind === ts.SyntaxKind.SuperKeyword)
421
+ return free('super call');
422
+ if (ts.isPropertyAccessExpression(callee)) {
423
+ if (callee.expression.kind === ts.SyntaxKind.SuperKeyword)
424
+ return superCall(env);
425
+ const base = force(thunk(callee.expression, env));
426
+ return methodCall(base, callee.name.text, args, node);
427
+ }
428
+ const target = force(thunk(callee, env));
429
+ if (target.t === 'ext' && target.spec === NEST_COMMON && target.name === 'forwardRef') {
430
+ const [forwarded] = args;
431
+ return forwarded ? lazy(() => callFunction(force(forwarded), [])) : free('forwardRef without a value');
432
+ }
433
+ if (target.t === 'fn')
434
+ return callFunction(target, args);
435
+ return free(`call of ${target.t}`);
436
+ }
437
+ /** `super.register(...)` of a class built on Nest's ConfigurableModuleBuilder: the class itself, no user additions. */
438
+ const superCall = (env) => ({ t: 'dyn', module: env.thisClass ?? free('super outside a class'), imports: [], providers: [], args: [] });
439
+ /** Array methods over a list whose items are known (`arr`) or unknown (`free`: one representative item). */
440
+ function arrayMethod(base, name, args) {
441
+ const items = base.t === 'arr' ? base.items : [free('an item of a list from the options of a deployment')];
442
+ if (name === 'map' || name === 'flatMap') {
443
+ const fn = args[0] ? force(args[0]) : null;
444
+ if (fn?.t !== 'fn')
445
+ return free(`${name} without a function`);
446
+ const mapped = { t: 'arr', items: items.map((item) => callFunction(fn, [item, undef])) }; // a spread item is passed on as the interpreter always did
447
+ return base.t === 'arr' ? mapped : undecided(fn.node, [mapped, { t: 'arr', items: [] }]);
448
+ }
449
+ if (name === 'filter' || name === 'slice' || name === 'sort' || name === 'reverse')
450
+ return base;
451
+ if (name === 'concat')
452
+ return { t: 'arr', items: [{ t: 'spread', v: base }, ...args.map((argument) => ({ t: 'spread', v: argument }))] };
453
+ return null;
454
+ }
455
+ function methodCall(base, name, args, node) {
456
+ if ((base.t === 'arr' || base.t === 'free') && ['map', 'flatMap', 'filter', 'slice', 'sort', 'reverse', 'concat'].includes(name)) {
457
+ const result = arrayMethod(base, name, args);
458
+ if (result)
459
+ return result;
460
+ }
461
+ if (base.t === 'alt')
462
+ return { t: 'alt', alts: base.alts.map((alt) => lazy(() => methodCall(force(alt), name, args, node))) };
463
+ if (base.t === 'ext')
464
+ return { t: 'dyn', module: base, imports: listOf(args[0], 'imports'), providers: [], args, ext: name };
465
+ if (base.t === 'class') {
466
+ const found = staticMethod(base, name);
467
+ if (found)
468
+ return callFunction({ t: 'fn', node: found.method, env: newEnv(found.owner.file, { thisClass: base }) }, args);
469
+ return { t: 'dyn', module: base, imports: [], providers: [], args };
470
+ }
471
+ return free(`method ${name} of ${base.t} at ${where(node)}`);
472
+ }
473
+ /** The static method of a class or of its in-repository base classes; null when none (the base is external). */
474
+ function staticMethod(cls, name) {
475
+ const method = cls.node.members.find((item) => ts.isMethodDeclaration(item) && item.name && ts.isIdentifier(item.name) && item.name.text === name && (internals.getSyntacticModifierFlags(item) & ts.ModifierFlags.Static) !== 0 && item.body !== undefined);
476
+ if (method)
477
+ return { method, owner: cls };
478
+ const heritage = cls.node.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
479
+ if (!heritage)
480
+ return null;
481
+ const base = force(thunk(heritage.expression, newEnv(cls.file)));
482
+ return base.t === 'class' ? staticMethod(base, name) : null;
483
+ }
484
+ /** The `imports` array a call's first argument carries (forRootAsync-style options), as a list of thunks. */
485
+ function listOf(argument, key) {
486
+ if (!argument)
487
+ return [];
488
+ const options = force(argument);
489
+ if (options.t !== 'obj' || !options.props.has(key))
490
+ return [];
491
+ return [options.props.get(key)];
492
+ }
493
+ function callFunction(fn, args) {
494
+ if (fn.t !== 'fn')
495
+ return free(`call of ${fn.t}`);
496
+ const env = newEnv(fn.env.file, { ...fn.env, vars: new Map(fn.env.vars), depth: fn.env.depth + 1, cache: {} });
497
+ fn.node.parameters.forEach((parameter, index) => bindParameter(parameter.name, args[index] ?? undef, env));
498
+ const body = fn.node.body;
499
+ if (!body)
500
+ return free('function without a body');
501
+ if (!ts.isBlock(body))
502
+ return thunk(body, env);
503
+ const outcome = runStatements(body.statements, env);
504
+ return outcome.returned ? outcome.value : undef;
505
+ }
506
+ function bindParameter(name, value, env) {
507
+ if (ts.isIdentifier(name))
508
+ env.vars.set(name.text, value);
509
+ else if (ts.isObjectBindingPattern(name)) {
510
+ for (const element of name.elements) {
511
+ const key = (element.propertyName ?? element.name).text; // an identifier key, the only form a module option destructures
512
+ if (ts.isIdentifier(element.name))
513
+ env.vars.set(element.name.text, member(value, key));
514
+ }
515
+ }
516
+ }
517
+ /** True when a statement returns or changes a list a later `return` may hand back: what an undecided branch must not hide. */
518
+ function hasEffect(node) {
519
+ let found = false;
520
+ const visit = (child) => {
521
+ if (found)
522
+ return;
523
+ if (ts.isReturnStatement(child) || (ts.isBinaryExpression(child) && child.operatorToken.kind === ts.SyntaxKind.EqualsToken))
524
+ found = true;
525
+ else if (ts.isCallExpression(child) && ts.isPropertyAccessExpression(child.expression) && ['push', 'unshift', 'splice'].includes(child.expression.name.text))
526
+ found = true;
527
+ else if (!ts.isFunctionLike(child))
528
+ ts.forEachChild(child, visit);
529
+ };
530
+ visit(node);
531
+ return found;
532
+ }
533
+ const SILENT_STATEMENTS = new Set([ts.SyntaxKind.EmptyStatement, ts.SyntaxKind.ThrowStatement, ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.ClassDeclaration, ts.SyntaxKind.InterfaceDeclaration, ts.SyntaxKind.TypeAliasDeclaration]);
534
+ /**
535
+ * Runs statements in order against an environment: declarations bind lazily, `if` follows the branch its condition decides
536
+ * (an undecidable condition over statements that return or change a list is an error), `push` appends to a local list and
537
+ * `return` ends the run. Answers `{ returned, value }`. A loop, switch or try that returns or changes a list is an error.
538
+ */
539
+ function runStatements(statements, env) {
540
+ for (const statement of statements) {
541
+ if (ts.isVariableStatement(statement)) {
542
+ for (const declaration of statement.declarationList.declarations) {
543
+ if (declaration.initializer)
544
+ bindParameter(declaration.name, thunk(declaration.initializer, env), env);
545
+ }
546
+ }
547
+ else if (ts.isReturnStatement(statement))
548
+ return { returned: true, value: statement.expression ? thunk(statement.expression, env) : undef };
549
+ else if (ts.isIfStatement(statement)) {
550
+ const decided = condition(statement.expression, env);
551
+ if (decided === null && hasEffect(statement))
552
+ throw new Error(`${where(statement)}: the condition ${statement.expression.getText()} cannot be decided from literals and a branch returns or adds providers; the schema is not known`);
553
+ const branch = decided === false ? statement.elseStatement : decided === true ? statement.thenStatement : null;
554
+ if (branch) {
555
+ const outcome = runStatements(ts.isBlock(branch) ? branch.statements : [branch], env);
556
+ if (outcome.returned)
557
+ return outcome;
558
+ }
559
+ }
560
+ else if (ts.isBlock(statement)) {
561
+ const outcome = runStatements(statement.statements, env);
562
+ if (outcome.returned)
563
+ return outcome;
564
+ }
565
+ else if (ts.isExpressionStatement(statement))
566
+ pushStatement(statement, env);
567
+ else if (!SILENT_STATEMENTS.has(statement.kind) && hasEffect(statement))
568
+ throw new Error(`${where(statement)}: a ${ts.SyntaxKind[statement.kind]} that returns or changes a list is not modeled by this reader`);
569
+ }
570
+ return { returned: false, value: undef };
571
+ }
572
+ /** `list.push(...)` on a local list and `name = value` on a local name; any other expression statement has no effect here. */
573
+ function pushStatement(statement, env) {
574
+ const expression = unwrapped(statement.expression);
575
+ if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isIdentifier(expression.left) && env.vars.has(expression.left.text)) {
576
+ env.vars.set(expression.left.text, thunk(expression.right, env));
577
+ return;
578
+ }
579
+ if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression))
580
+ return;
581
+ const name = expression.expression.name.text;
582
+ if (name !== 'push' && name !== 'unshift')
583
+ return;
584
+ const list = force(thunk(expression.expression.expression, env));
585
+ if (list.t !== 'arr')
586
+ throw new Error(`${where(statement)}: ${name} on something that is not a local list`);
587
+ const added = expression.arguments.map((argument) => (ts.isSpreadElement(argument) ? { t: 'spread', v: thunk(argument.expression, env) } : thunk(argument, env)));
588
+ if (name === 'push')
589
+ list.items.push(...added);
590
+ else
591
+ list.items.unshift(...added);
592
+ }
593
+ // ---- modules ----
594
+ // reason: the repository's own TypeScript may predate 4.8, where decorators sat on `node.decorators`.
595
+ const decoratorsOf = (node) => (ts.canHaveDecorators?.(node) ? ts.getDecorators(node) ?? [] : node.decorators ?? []);
596
+ /** The `@Module({...})` metadata object of a class (an obj value), or null. */
597
+ function moduleMetadata(cls) {
598
+ for (const decorator of decoratorsOf(cls.node)) {
599
+ const expression = decorator.expression;
600
+ if (!ts.isCallExpression(expression))
601
+ continue;
602
+ const callee = force(thunk(expression.expression, newEnv(cls.file)));
603
+ if (callee.t === 'ext' && callee.spec === NEST_COMMON && callee.name === 'Module') {
604
+ const argument = expression.arguments[0];
605
+ const metadata = argument ? force(thunk(argument, newEnv(cls.file, { thisClass: cls }))) : { t: 'obj', props: new Map(), open: false };
606
+ if (metadata.t !== 'obj' || metadata.open)
607
+ throw new Error(`${where(expression)}: the @Module metadata of ${cls.name} cannot be decided`);
608
+ return metadata;
609
+ }
610
+ }
611
+ return null;
612
+ }
613
+ /** Flattens a value into its module/provider entries: arrays, spreads and both branches of a conditional. */
614
+ function entries(value, out = []) {
615
+ const v = force(value);
616
+ if (v.t === 'arr')
617
+ for (const item of v.items)
618
+ entries(item.t === 'spread' ? item.v : item, out);
619
+ else if (v.t === 'alt')
620
+ for (const alt of v.alts)
621
+ entries(alt, out);
622
+ else if (v.t !== 'undef' && v.t !== 'nul' && !(v.t === 'lit' && !v.v))
623
+ out.push(v);
624
+ return out;
625
+ }
626
+ const isGraphqlServer = (module) => module.t === 'ext' && module.spec === NEST_GRAPHQL && module.name === 'GraphQLModule';
627
+ /** A module entry as `{ module, dyn }`: a class, an external module, a dynamic module, or a `{ module, ... }` literal. */
628
+ function normalize(value, origin) {
629
+ if (value.t === 'class' || value.t === 'ext')
630
+ return { module: value, dyn: null, key: value.t === 'class' ? value : `${value.spec}#${value.name}` };
631
+ if (value.t === 'dyn')
632
+ return { module: force(value.module), dyn: value, key: value };
633
+ if (value.t === 'obj' && value.props.has('module')) {
634
+ if (value.open && !(value.props.has('imports') && value.props.has('providers')))
635
+ throw new Error(`${origin}: a module object with an unknown spread may add imports or providers`);
636
+ const dyn = { t: 'dyn', module: value.props.get('module'), imports: value.props.has('imports') ? [value.props.get('imports')] : [], providers: value.props.has('providers') ? [value.props.get('providers')] : [], args: [] };
637
+ return { module: force(dyn.module), dyn, key: value };
638
+ }
639
+ throw new Error(`${origin}: an import cannot be decided (${(value.t === 'free' ? value.why : undefined) ?? value.t})`);
640
+ }
641
+ /**
642
+ * Walks the module graph from a root entry. Answers the module instances `{ module, providers, imports, server }` in
643
+ * discovery order; `imports` are instances of the same list. A static class is one instance; every dynamic module value is
644
+ * its own instance (Nest keys them by their metadata).
645
+ */
646
+ function walk(root) {
647
+ const order = [];
648
+ const seen = new Map();
649
+ function visit(entry, origin) {
650
+ const nodes = [];
651
+ for (const value of entries(entry)) {
652
+ const { module, dyn, key } = normalize(value, origin);
653
+ if (module.t === 'free')
654
+ throw new Error(`${origin}: a dynamic module's class cannot be decided (${module.why})`);
655
+ if (seen.has(key)) {
656
+ nodes.push(seen.get(key));
657
+ continue;
658
+ }
659
+ const node = { module, dynamic: dyn, providers: [], imports: [], server: null };
660
+ seen.set(key, node);
661
+ order.push(node);
662
+ nodes.push(node);
663
+ const children = [];
664
+ const statics = module.t === 'class' ? moduleMetadata(module) : null;
665
+ if (statics?.props.has('imports'))
666
+ children.push(statics.props.get('imports'));
667
+ if (statics?.props.has('providers'))
668
+ node.providers.push(statics.props.get('providers'));
669
+ if (dyn) {
670
+ children.push(...dyn.imports);
671
+ node.providers.push(...dyn.providers);
672
+ if (isGraphqlServer(module))
673
+ node.server = dyn;
674
+ }
675
+ const name = module.t === 'class' ? `${module.name} (${module.file})` : `${'name' in module ? module.name : undefined}`;
676
+ for (const child of children)
677
+ node.imports.push(...visit(child, name));
678
+ }
679
+ return nodes;
680
+ }
681
+ visit(root, 'the application root');
682
+ return order;
683
+ }
684
+ /** The instances of the modules a GraphQL server reads: all of them, or the `include` whitelist and its transitive imports. */
685
+ function servedNodes(nodes, include) {
686
+ if (include.length === 0)
687
+ return nodes;
688
+ const served = new Set();
689
+ const pending = nodes.filter((node) => include.includes(node.module));
690
+ while (pending.length) {
691
+ const node = pending.pop();
692
+ if (served.has(node))
693
+ continue;
694
+ served.add(node);
695
+ pending.push(...node.imports);
696
+ }
697
+ return nodes.filter((node) => served.has(node));
698
+ }
699
+ /** The provider classes of instances: plain class providers and `useClass` providers, unique, in order. */
700
+ function providerClasses(nodes) {
701
+ const found = [];
702
+ for (const node of nodes) {
703
+ for (const list of node.providers) {
704
+ for (const provider of entries(list)) {
705
+ const cls = provider.t === 'class' ? provider : provider.t === 'obj' && provider.props.has('useClass') ? force(provider.props.get('useClass')) : null;
706
+ if (provider.t === 'free')
707
+ throw new Error(`${('name' in node.module ? node.module.name : undefined) ?? 'a module'}: a provider list cannot be decided (${provider.why})`);
708
+ if (cls && cls.t === 'class' && !found.includes(cls))
709
+ found.push(cls);
710
+ }
711
+ }
712
+ }
713
+ return found;
714
+ }
715
+ /** True when a class carries `@Resolver` or `@Scalar` of @nestjs/graphql (by where the decorator was imported from). */
716
+ function graphqlKind(cls) {
717
+ for (const decorator of decoratorsOf(cls.node)) {
718
+ const expression = ts.isCallExpression(decorator.expression) ? decorator.expression.expression : decorator.expression;
719
+ const callee = force(thunk(expression, newEnv(cls.file)));
720
+ if (callee.t === 'ext' && callee.spec === NEST_GRAPHQL && (callee.name === 'Resolver' || callee.name === 'Scalar'))
721
+ return callee.name;
722
+ }
723
+ return null;
724
+ }
725
+ /** The options of a GraphQL server: its literal, or what the factory of `forRootAsync` returns. */
726
+ function serverOptions(server, origin) {
727
+ const argument = server.args[0];
728
+ if (!argument)
729
+ return { include: [] };
730
+ let options = force(argument);
731
+ if (options.t === 'obj' && options.props.has('useFactory')) {
732
+ const result = callFunction(force(options.props.get('useFactory')), (options.props.has('inject') ? entries(options.props.get('inject')) : []).map(() => free('injected value')));
733
+ options = force(result);
734
+ }
735
+ const objects = options.t === 'alt' ? options.alts.map(force) : [options];
736
+ const props = new Map();
737
+ for (const object of objects) {
738
+ if (object.t !== 'obj' || object.open)
739
+ throw new Error(`${origin}: the GraphQL server options cannot be decided (${(object.t === 'free' ? object.why : undefined) ?? (object.t === 'obj' && object.open ? 'an unknown spread' : object.t)})`);
740
+ for (const [key, value] of object.props)
741
+ props.set(key, value);
742
+ }
743
+ for (const key of SCHEMA_OPTIONS_NOT_MODELED) {
744
+ if (props.has(key))
745
+ throw new Error(`${origin}: GraphQL server option ${key} changes the schema and is not modeled by this reader`);
746
+ }
747
+ const auto = props.has('autoSchemaFile') ? force(props.get('autoSchemaFile')) : undef;
748
+ if (auto.t === 'undef' || (auto.t === 'lit' && auto.v === false))
749
+ throw new Error(`${origin}: the GraphQL server is not code-first (no autoSchemaFile)`);
750
+ const listed = props.has('include') ? entries(props.get('include')) : [];
751
+ const include = listed.filter((item) => item.t === 'class');
752
+ if (include.length !== listed.length)
753
+ throw new Error(`${origin}: the GraphQL include list cannot be decided`);
754
+ return { include };
755
+ }
756
+ /** The keys of the resolver and scalar classes one branch of an undecided choice would serve. */
757
+ function graphqlClassKeys(alt) {
758
+ const keys = new Set();
759
+ for (const value of entries(alt)) {
760
+ if (value.t === 'class' && graphqlKind(value))
761
+ keys.add(`${value.file}#${value.name}`);
762
+ const moduleLike = value.t === 'dyn' || (value.t === 'obj' && value.props.has('module')) || (value.t === 'class' && moduleMetadata(value) !== null);
763
+ if (!moduleLike)
764
+ continue;
765
+ for (const cls of providerClasses(walk(value)))
766
+ if (graphqlKind(cls))
767
+ keys.add(`${cls.file}#${cls.name}`);
768
+ }
769
+ return keys;
770
+ }
771
+ /**
772
+ * Every choice the literals did not decide (a condition on the options of a deployment, an unknown list) must serve the same
773
+ * resolvers whichever way it goes; when the branches differ the schema is not known and that is an error, never a guess.
774
+ */
775
+ function assertUndecidedHarmless() {
776
+ for (let at = 0; at < undecidedRecords.length; at += 1) {
777
+ const { node, alts } = undecidedRecords[at];
778
+ const [first, ...rest] = alts.map(graphqlClassKeys); // an undecided choice always has alternatives
779
+ for (const other of rest) {
780
+ const differing = [...first].filter((key) => !other.has(key)).concat([...other].filter((key) => !first.has(key)));
781
+ if (differing.length)
782
+ throw new Error(`${where(node)}: ${node.getText()} cannot be decided from literals and its branches serve different resolvers (${differing.map((key) => key.split('#')[1]).join(', ')})`);
783
+ }
784
+ }
785
+ }
786
+ /**
787
+ * Composes an app root file. Answers null when the file exports no `AppModule` class or its module graph holds no GraphQL server, else
788
+ * `{ resolvers: [{ file, name }], scalars: [{ file, name }], include: [{ file, name }] }`.
789
+ */
790
+ function compose(appFile, exportName = 'AppModule') {
791
+ const found = resolveExport(appFile, exportName);
792
+ if (!found || !('kind' in found) || found.kind !== 'class')
793
+ return null;
794
+ const root = classRef(found);
795
+ const register = staticMethod(root, 'register');
796
+ const rootValue = register ? { t: 'arr', items: [root, callFunction({ t: 'fn', node: register.method, env: newEnv(register.owner.file, { thisClass: root }) }, [free('the options of a deployment')])] } : root;
797
+ const nodes = walk(rootValue);
798
+ const servers = nodes.filter((node) => node.server !== null);
799
+ if (servers.length === 0)
800
+ return null;
801
+ if (servers.length > 1)
802
+ throw new Error(`${appFile} composes ${servers.length} GraphQL servers; a contract snapshot describes exactly one`);
803
+ const { include } = serverOptions(servers[0].server, `${exportName} of ${appFile}`);
804
+ const classesOf = providerClasses(servedNodes(nodes, include));
805
+ assertUndecidedHarmless();
806
+ const pick = (kind) => classesOf.filter((cls) => graphqlKind(cls) === kind).map((cls) => ({ file: cls.file, name: cls.name }));
807
+ return { resolvers: pick('Resolver'), scalars: pick('Scalar'), include: include.map((cls) => ({ file: cls.file, name: cls.name })) };
808
+ }
809
+ return { compose };
684
810
  }