@endora-commerce/cli 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/dist/bin/endora.d.ts +28 -0
  4. package/dist/bin/endora.d.ts.map +1 -0
  5. package/dist/bin/endora.js +926 -0
  6. package/dist/bin/endora.js.map +1 -0
  7. package/dist/check/estate.d.ts +189 -0
  8. package/dist/check/estate.d.ts.map +1 -0
  9. package/dist/check/estate.js +1037 -0
  10. package/dist/check/estate.js.map +1 -0
  11. package/dist/check/hosts.d.ts +25 -0
  12. package/dist/check/hosts.d.ts.map +1 -0
  13. package/dist/check/hosts.js +1347 -0
  14. package/dist/check/hosts.js.map +1 -0
  15. package/dist/check/index.d.ts +60 -0
  16. package/dist/check/index.d.ts.map +1 -0
  17. package/dist/check/index.js +111 -0
  18. package/dist/check/index.js.map +1 -0
  19. package/dist/check/layout.d.ts +136 -0
  20. package/dist/check/layout.d.ts.map +1 -0
  21. package/dist/check/layout.js +262 -0
  22. package/dist/check/layout.js.map +1 -0
  23. package/dist/check/ledger.d.ts +98 -0
  24. package/dist/check/ledger.d.ts.map +1 -0
  25. package/dist/check/ledger.js +173 -0
  26. package/dist/check/ledger.js.map +1 -0
  27. package/dist/check/peer-owners.d.ts +116 -0
  28. package/dist/check/peer-owners.d.ts.map +1 -0
  29. package/dist/check/peer-owners.js +225 -0
  30. package/dist/check/peer-owners.js.map +1 -0
  31. package/dist/check/report.d.ts +33 -0
  32. package/dist/check/report.d.ts.map +1 -0
  33. package/dist/check/report.js +107 -0
  34. package/dist/check/report.js.map +1 -0
  35. package/dist/check/run.d.ts +147 -0
  36. package/dist/check/run.d.ts.map +1 -0
  37. package/dist/check/run.js +111 -0
  38. package/dist/check/run.js.map +1 -0
  39. package/dist/checks.d.ts +17 -0
  40. package/dist/checks.d.ts.map +1 -0
  41. package/dist/checks.js +17 -0
  42. package/dist/checks.js.map +1 -0
  43. package/dist/dev/index.d.ts +83 -0
  44. package/dist/dev/index.d.ts.map +1 -0
  45. package/dist/dev/index.js +298 -0
  46. package/dist/dev/index.js.map +1 -0
  47. package/dist/generate/divergence.d.ts +38 -0
  48. package/dist/generate/divergence.d.ts.map +1 -0
  49. package/dist/generate/divergence.js +237 -0
  50. package/dist/generate/divergence.js.map +1 -0
  51. package/dist/generate/index.d.ts +90 -0
  52. package/dist/generate/index.d.ts.map +1 -0
  53. package/dist/generate/index.js +369 -0
  54. package/dist/generate/index.js.map +1 -0
  55. package/dist/index.d.ts +23 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +35 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/inputs/declaration.d.ts +18 -0
  60. package/dist/inputs/declaration.d.ts.map +1 -0
  61. package/dist/inputs/declaration.js +64 -0
  62. package/dist/inputs/declaration.js.map +1 -0
  63. package/dist/inputs/env-file.d.ts +73 -0
  64. package/dist/inputs/env-file.d.ts.map +1 -0
  65. package/dist/inputs/env-file.js +134 -0
  66. package/dist/inputs/env-file.js.map +1 -0
  67. package/dist/inputs/prompt.d.ts +21 -0
  68. package/dist/inputs/prompt.d.ts.map +1 -0
  69. package/dist/inputs/prompt.js +59 -0
  70. package/dist/inputs/prompt.js.map +1 -0
  71. package/dist/inputs/resolve.d.ts +163 -0
  72. package/dist/inputs/resolve.d.ts.map +1 -0
  73. package/dist/inputs/resolve.js +290 -0
  74. package/dist/inputs/resolve.js.map +1 -0
  75. package/dist/install/host.d.ts +27 -0
  76. package/dist/install/host.d.ts.map +1 -0
  77. package/dist/install/host.js +90 -0
  78. package/dist/install/host.js.map +1 -0
  79. package/dist/install/index.d.ts +173 -0
  80. package/dist/install/index.d.ts.map +1 -0
  81. package/dist/install/index.js +793 -0
  82. package/dist/install/index.js.map +1 -0
  83. package/dist/install/wizard.d.ts +144 -0
  84. package/dist/install/wizard.d.ts.map +1 -0
  85. package/dist/install/wizard.js +362 -0
  86. package/dist/install/wizard.js.map +1 -0
  87. package/dist/lib/admin-artefacts.d.ts +70 -0
  88. package/dist/lib/admin-artefacts.d.ts.map +1 -0
  89. package/dist/lib/admin-artefacts.js +354 -0
  90. package/dist/lib/admin-artefacts.js.map +1 -0
  91. package/dist/lib/admin-surfaces.d.ts +298 -0
  92. package/dist/lib/admin-surfaces.d.ts.map +1 -0
  93. package/dist/lib/admin-surfaces.js +669 -0
  94. package/dist/lib/admin-surfaces.js.map +1 -0
  95. package/dist/lib/delegated-composer.d.ts +85 -0
  96. package/dist/lib/delegated-composer.d.ts.map +1 -0
  97. package/dist/lib/delegated-composer.js +241 -0
  98. package/dist/lib/delegated-composer.js.map +1 -0
  99. package/dist/lib/divergence-artefacts.d.ts +305 -0
  100. package/dist/lib/divergence-artefacts.d.ts.map +1 -0
  101. package/dist/lib/divergence-artefacts.js +828 -0
  102. package/dist/lib/divergence-artefacts.js.map +1 -0
  103. package/dist/lib/divergence.d.ts +337 -0
  104. package/dist/lib/divergence.d.ts.map +1 -0
  105. package/dist/lib/divergence.js +1005 -0
  106. package/dist/lib/divergence.js.map +1 -0
  107. package/dist/lib/docs-artefacts.d.ts +395 -0
  108. package/dist/lib/docs-artefacts.d.ts.map +1 -0
  109. package/dist/lib/docs-artefacts.js +781 -0
  110. package/dist/lib/docs-artefacts.js.map +1 -0
  111. package/dist/lib/emitted-exports.d.ts +21 -0
  112. package/dist/lib/emitted-exports.d.ts.map +1 -0
  113. package/dist/lib/emitted-exports.js +96 -0
  114. package/dist/lib/emitted-exports.js.map +1 -0
  115. package/dist/lib/emitted-freshness.d.ts +112 -0
  116. package/dist/lib/emitted-freshness.d.ts.map +1 -0
  117. package/dist/lib/emitted-freshness.js +288 -0
  118. package/dist/lib/emitted-freshness.js.map +1 -0
  119. package/dist/lib/entity-index-artefact.d.ts +95 -0
  120. package/dist/lib/entity-index-artefact.d.ts.map +1 -0
  121. package/dist/lib/entity-index-artefact.js +210 -0
  122. package/dist/lib/entity-index-artefact.js.map +1 -0
  123. package/dist/lib/instance-build-inputs.d.ts +108 -0
  124. package/dist/lib/instance-build-inputs.d.ts.map +1 -0
  125. package/dist/lib/instance-build-inputs.js +165 -0
  126. package/dist/lib/instance-build-inputs.js.map +1 -0
  127. package/dist/lib/module-docs.d.ts +473 -0
  128. package/dist/lib/module-docs.d.ts.map +1 -0
  129. package/dist/lib/module-docs.js +711 -0
  130. package/dist/lib/module-docs.js.map +1 -0
  131. package/dist/lib/module-package-subpaths.d.ts +56 -0
  132. package/dist/lib/module-package-subpaths.d.ts.map +1 -0
  133. package/dist/lib/module-package-subpaths.js +223 -0
  134. package/dist/lib/module-package-subpaths.js.map +1 -0
  135. package/dist/lib/module-packages.d.ts +200 -0
  136. package/dist/lib/module-packages.d.ts.map +1 -0
  137. package/dist/lib/module-packages.js +580 -0
  138. package/dist/lib/module-packages.js.map +1 -0
  139. package/dist/lib/module-population.d.ts +129 -0
  140. package/dist/lib/module-population.d.ts.map +1 -0
  141. package/dist/lib/module-population.js +172 -0
  142. package/dist/lib/module-population.js.map +1 -0
  143. package/dist/lib/module-roots.d.ts +337 -0
  144. package/dist/lib/module-roots.d.ts.map +1 -0
  145. package/dist/lib/module-roots.js +586 -0
  146. package/dist/lib/module-roots.js.map +1 -0
  147. package/dist/lib/nested-checkouts.d.ts +33 -0
  148. package/dist/lib/nested-checkouts.d.ts.map +1 -0
  149. package/dist/lib/nested-checkouts.js +160 -0
  150. package/dist/lib/nested-checkouts.js.map +1 -0
  151. package/dist/lib/platform-root.d.ts +43 -0
  152. package/dist/lib/platform-root.d.ts.map +1 -0
  153. package/dist/lib/platform-root.js +134 -0
  154. package/dist/lib/platform-root.js.map +1 -0
  155. package/dist/lib/platform-surface.d.ts +235 -0
  156. package/dist/lib/platform-surface.d.ts.map +1 -0
  157. package/dist/lib/platform-surface.js +393 -0
  158. package/dist/lib/platform-surface.js.map +1 -0
  159. package/dist/lib/port-registrations.d.ts +223 -0
  160. package/dist/lib/port-registrations.d.ts.map +1 -0
  161. package/dist/lib/port-registrations.js +532 -0
  162. package/dist/lib/port-registrations.js.map +1 -0
  163. package/dist/lib/read-size.d.ts +154 -0
  164. package/dist/lib/read-size.d.ts.map +1 -0
  165. package/dist/lib/read-size.js +182 -0
  166. package/dist/lib/read-size.js.map +1 -0
  167. package/dist/lib/registration-owners.d.ts +79 -0
  168. package/dist/lib/registration-owners.d.ts.map +1 -0
  169. package/dist/lib/registration-owners.js +77 -0
  170. package/dist/lib/registration-owners.js.map +1 -0
  171. package/dist/lib/release-index.d.ts +53 -0
  172. package/dist/lib/release-index.d.ts.map +1 -0
  173. package/dist/lib/release-index.js +162 -0
  174. package/dist/lib/release-index.js.map +1 -0
  175. package/dist/lib/repeating-timers.d.ts +79 -0
  176. package/dist/lib/repeating-timers.d.ts.map +1 -0
  177. package/dist/lib/repeating-timers.js +189 -0
  178. package/dist/lib/repeating-timers.js.map +1 -0
  179. package/dist/lib/source-text.d.ts +34 -0
  180. package/dist/lib/source-text.d.ts.map +1 -0
  181. package/dist/lib/source-text.js +80 -0
  182. package/dist/lib/source-text.js.map +1 -0
  183. package/dist/lib/specifiers.d.ts +20 -0
  184. package/dist/lib/specifiers.d.ts.map +1 -0
  185. package/dist/lib/specifiers.js +130 -0
  186. package/dist/lib/specifiers.js.map +1 -0
  187. package/dist/lib/sql-tables.d.ts +166 -0
  188. package/dist/lib/sql-tables.d.ts.map +1 -0
  189. package/dist/lib/sql-tables.js +464 -0
  190. package/dist/lib/sql-tables.js.map +1 -0
  191. package/dist/lib/switchable-modules.d.ts +54 -0
  192. package/dist/lib/switchable-modules.d.ts.map +1 -0
  193. package/dist/lib/switchable-modules.js +104 -0
  194. package/dist/lib/switchable-modules.js.map +1 -0
  195. package/dist/lib/tailwind-sources.d.ts +136 -0
  196. package/dist/lib/tailwind-sources.d.ts.map +1 -0
  197. package/dist/lib/tailwind-sources.js +307 -0
  198. package/dist/lib/tailwind-sources.js.map +1 -0
  199. package/dist/lib/ui-layer.d.ts +54 -0
  200. package/dist/lib/ui-layer.d.ts.map +1 -0
  201. package/dist/lib/ui-layer.js +57 -0
  202. package/dist/lib/ui-layer.js.map +1 -0
  203. package/dist/lib/workspace-packages.d.ts +186 -0
  204. package/dist/lib/workspace-packages.d.ts.map +1 -0
  205. package/dist/lib/workspace-packages.js +351 -0
  206. package/dist/lib/workspace-packages.js.map +1 -0
  207. package/dist/new-instance/deploy.d.ts +211 -0
  208. package/dist/new-instance/deploy.d.ts.map +1 -0
  209. package/dist/new-instance/deploy.js +1381 -0
  210. package/dist/new-instance/deploy.js.map +1 -0
  211. package/dist/new-instance/docs-toolchain.d.ts +66 -0
  212. package/dist/new-instance/docs-toolchain.d.ts.map +1 -0
  213. package/dist/new-instance/docs-toolchain.js +69 -0
  214. package/dist/new-instance/docs-toolchain.js.map +1 -0
  215. package/dist/new-instance/host.d.ts +124 -0
  216. package/dist/new-instance/host.d.ts.map +1 -0
  217. package/dist/new-instance/host.js +276 -0
  218. package/dist/new-instance/host.js.map +1 -0
  219. package/dist/new-instance/index.d.ts +118 -0
  220. package/dist/new-instance/index.d.ts.map +1 -0
  221. package/dist/new-instance/index.js +567 -0
  222. package/dist/new-instance/index.js.map +1 -0
  223. package/dist/new-instance/modules.d.ts +188 -0
  224. package/dist/new-instance/modules.d.ts.map +1 -0
  225. package/dist/new-instance/modules.js +392 -0
  226. package/dist/new-instance/modules.js.map +1 -0
  227. package/dist/new-instance/template.d.ts +505 -0
  228. package/dist/new-instance/template.d.ts.map +1 -0
  229. package/dist/new-instance/template.js +1886 -0
  230. package/dist/new-instance/template.js.map +1 -0
  231. package/dist/new-module/emit.d.ts +67 -0
  232. package/dist/new-module/emit.d.ts.map +1 -0
  233. package/dist/new-module/emit.js +1393 -0
  234. package/dist/new-module/emit.js.map +1 -0
  235. package/dist/new-module/host.d.ts +67 -0
  236. package/dist/new-module/host.d.ts.map +1 -0
  237. package/dist/new-module/host.js +224 -0
  238. package/dist/new-module/host.js.map +1 -0
  239. package/dist/new-module/index.d.ts +32 -0
  240. package/dist/new-module/index.d.ts.map +1 -0
  241. package/dist/new-module/index.js +193 -0
  242. package/dist/new-module/index.js.map +1 -0
  243. package/dist/new-module/spec.d.ts +188 -0
  244. package/dist/new-module/spec.d.ts.map +1 -0
  245. package/dist/new-module/spec.js +404 -0
  246. package/dist/new-module/spec.js.map +1 -0
  247. package/dist/new-module/text.d.ts +15 -0
  248. package/dist/new-module/text.d.ts.map +1 -0
  249. package/dist/new-module/text.js +22 -0
  250. package/dist/new-module/text.js.map +1 -0
  251. package/dist/new-storefront/dockerfile.d.ts +20 -0
  252. package/dist/new-storefront/dockerfile.d.ts.map +1 -0
  253. package/dist/new-storefront/dockerfile.js +131 -0
  254. package/dist/new-storefront/dockerfile.js.map +1 -0
  255. package/dist/new-storefront/gitignore.d.ts +23 -0
  256. package/dist/new-storefront/gitignore.d.ts.map +1 -0
  257. package/dist/new-storefront/gitignore.js +39 -0
  258. package/dist/new-storefront/gitignore.js.map +1 -0
  259. package/dist/new-storefront/index.d.ts +93 -0
  260. package/dist/new-storefront/index.d.ts.map +1 -0
  261. package/dist/new-storefront/index.js +329 -0
  262. package/dist/new-storefront/index.js.map +1 -0
  263. package/dist/new-storefront/npmrc.d.ts +98 -0
  264. package/dist/new-storefront/npmrc.d.ts.map +1 -0
  265. package/dist/new-storefront/npmrc.js +217 -0
  266. package/dist/new-storefront/npmrc.js.map +1 -0
  267. package/dist/new-storefront/reference.d.ts +189 -0
  268. package/dist/new-storefront/reference.d.ts.map +1 -0
  269. package/dist/new-storefront/reference.js +430 -0
  270. package/dist/new-storefront/reference.js.map +1 -0
  271. package/dist/new-storefront/rewrite.d.ts +171 -0
  272. package/dist/new-storefront/rewrite.d.ts.map +1 -0
  273. package/dist/new-storefront/rewrite.js +701 -0
  274. package/dist/new-storefront/rewrite.js.map +1 -0
  275. package/dist/release-index.json +284 -0
  276. package/dist/rules/action-route-permissions.d.ts +141 -0
  277. package/dist/rules/action-route-permissions.d.ts.map +1 -0
  278. package/dist/rules/action-route-permissions.js +556 -0
  279. package/dist/rules/action-route-permissions.js.map +1 -0
  280. package/dist/rules/bundle-pairing.d.ts +74 -0
  281. package/dist/rules/bundle-pairing.d.ts.map +1 -0
  282. package/dist/rules/bundle-pairing.js +281 -0
  283. package/dist/rules/bundle-pairing.js.map +1 -0
  284. package/dist/rules/channel-resolution.d.ts +17 -0
  285. package/dist/rules/channel-resolution.d.ts.map +1 -0
  286. package/dist/rules/channel-resolution.js +382 -0
  287. package/dist/rules/channel-resolution.js.map +1 -0
  288. package/dist/rules/command-coverage.d.ts +210 -0
  289. package/dist/rules/command-coverage.d.ts.map +1 -0
  290. package/dist/rules/command-coverage.js +714 -0
  291. package/dist/rules/command-coverage.js.map +1 -0
  292. package/dist/rules/container-imports.d.ts +60 -0
  293. package/dist/rules/container-imports.d.ts.map +1 -0
  294. package/dist/rules/container-imports.js +158 -0
  295. package/dist/rules/container-imports.js.map +1 -0
  296. package/dist/rules/default-language-prose.d.ts +212 -0
  297. package/dist/rules/default-language-prose.d.ts.map +1 -0
  298. package/dist/rules/default-language-prose.js +710 -0
  299. package/dist/rules/default-language-prose.js.map +1 -0
  300. package/dist/rules/diacritic-folds.d.ts +238 -0
  301. package/dist/rules/diacritic-folds.d.ts.map +1 -0
  302. package/dist/rules/diacritic-folds.js +681 -0
  303. package/dist/rules/diacritic-folds.js.map +1 -0
  304. package/dist/rules/entity-tenant-classification.d.ts +171 -0
  305. package/dist/rules/entity-tenant-classification.d.ts.map +1 -0
  306. package/dist/rules/entity-tenant-classification.js +323 -0
  307. package/dist/rules/entity-tenant-classification.js.map +1 -0
  308. package/dist/rules/entry-presence.d.ts +142 -0
  309. package/dist/rules/entry-presence.d.ts.map +1 -0
  310. package/dist/rules/entry-presence.js +339 -0
  311. package/dist/rules/entry-presence.js.map +1 -0
  312. package/dist/rules/entry-scope.d.ts +91 -0
  313. package/dist/rules/entry-scope.d.ts.map +1 -0
  314. package/dist/rules/entry-scope.js +404 -0
  315. package/dist/rules/entry-scope.js.map +1 -0
  316. package/dist/rules/env-inputs.d.ts +222 -0
  317. package/dist/rules/env-inputs.d.ts.map +1 -0
  318. package/dist/rules/env-inputs.js +951 -0
  319. package/dist/rules/env-inputs.js.map +1 -0
  320. package/dist/rules/kernel-boundary.d.ts +37 -0
  321. package/dist/rules/kernel-boundary.d.ts.map +1 -0
  322. package/dist/rules/kernel-boundary.js +195 -0
  323. package/dist/rules/kernel-boundary.js.map +1 -0
  324. package/dist/rules/nul-bytes.d.ts +233 -0
  325. package/dist/rules/nul-bytes.d.ts.map +1 -0
  326. package/dist/rules/nul-bytes.js +332 -0
  327. package/dist/rules/nul-bytes.js.map +1 -0
  328. package/dist/rules/platform-surface.d.ts +479 -0
  329. package/dist/rules/platform-surface.d.ts.map +1 -0
  330. package/dist/rules/platform-surface.js +749 -0
  331. package/dist/rules/platform-surface.js.map +1 -0
  332. package/dist/rules/port-catches.d.ts +225 -0
  333. package/dist/rules/port-catches.d.ts.map +1 -0
  334. package/dist/rules/port-catches.js +1374 -0
  335. package/dist/rules/port-catches.js.map +1 -0
  336. package/dist/rules/port-shape.d.ts +213 -0
  337. package/dist/rules/port-shape.d.ts.map +1 -0
  338. package/dist/rules/port-shape.js +670 -0
  339. package/dist/rules/port-shape.js.map +1 -0
  340. package/dist/rules/queue-names.d.ts +108 -0
  341. package/dist/rules/queue-names.d.ts.map +1 -0
  342. package/dist/rules/queue-names.js +395 -0
  343. package/dist/rules/queue-names.js.map +1 -0
  344. package/dist/rules/singleton-identity.d.ts +205 -0
  345. package/dist/rules/singleton-identity.d.ts.map +1 -0
  346. package/dist/rules/singleton-identity.js +830 -0
  347. package/dist/rules/singleton-identity.js.map +1 -0
  348. package/dist/rules/subscribe-seam.d.ts +121 -0
  349. package/dist/rules/subscribe-seam.d.ts.map +1 -0
  350. package/dist/rules/subscribe-seam.js +594 -0
  351. package/dist/rules/subscribe-seam.js.map +1 -0
  352. package/dist/rules/transaction-context.d.ts +40 -0
  353. package/dist/rules/transaction-context.d.ts.map +1 -0
  354. package/dist/rules/transaction-context.js +294 -0
  355. package/dist/rules/transaction-context.js.map +1 -0
  356. package/package.json +59 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The release index — what this CLI's release published, written at build
3
+ * (`specs/080-f4-real-scope/rulings.md` D-271 clause 2).
4
+ *
5
+ * ## Why the CLI carries it
6
+ *
7
+ * `endora install` run where nothing of ours is installed — the `npx` front
8
+ * door, from an empty directory — has no module manifest to read: the platform,
9
+ * the admin packages and every module are what the module set is derived from,
10
+ * and none of them can be read without installing them. The install verb
11
+ * therefore provisions a temporary host from this index (`install/host.ts`).
12
+ * It is a fact the CLI publishes **about its own release**, so it is
13
+ * `cli-product.md` R2.3's *"the CLI's own manifest"* class rather than a
14
+ * registry query or a list.
15
+ *
16
+ * ## Derived, and never written by hand
17
+ *
18
+ * {@link publishablePackages} is the one rule: every workspace package under
19
+ * `packages/` whose manifest is not `private` and has a name. The instance
20
+ * acceptance criterion packs exactly that population and imports this function
21
+ * rather than restating it; the index is the same population narrowed to the
22
+ * CLI's own scope, each at the `version` its manifest declares at build time.
23
+ * It lives in `dist` and is never committed, so nothing in the tree can go
24
+ * stale: the publish job builds the versioned tree immediately before it
25
+ * publishes, and a release that is not uniform is recorded as it is. A paid
26
+ * package is in no index because it is not in this workspace (D-265).
27
+ */
28
+ import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
29
+ import { dirname, join } from 'node:path';
30
+ import { fileURLToPath } from 'node:url';
31
+ /** The file's name under the CLI's `dist`. */
32
+ export const RELEASE_INDEX_FILE = 'release-index.json';
33
+ /**
34
+ * Every publishable workspace package under `packagesRoot`, with its directory.
35
+ *
36
+ * A directory holding a `package.json` is a package and is not descended
37
+ * into; one without is a grouping directory (`packages/modules/`) and is. A
38
+ * manifest declaring `private: true`, or no `name`, is not publishable.
39
+ */
40
+ export function publishablePackages(packagesRoot) {
41
+ const found = [];
42
+ const walk = (root) => {
43
+ if (!existsSync(root))
44
+ return;
45
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
46
+ if (!entry.isDirectory())
47
+ continue;
48
+ const dir = join(root, entry.name);
49
+ const manifestPath = join(dir, 'package.json');
50
+ if (!existsSync(manifestPath)) {
51
+ walk(dir);
52
+ continue;
53
+ }
54
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
55
+ if (manifest.private === true || typeof manifest.name !== 'string')
56
+ continue;
57
+ found.push({
58
+ name: manifest.name,
59
+ dir,
60
+ version: typeof manifest.version === 'string' ? manifest.version : undefined,
61
+ });
62
+ }
63
+ };
64
+ walk(packagesRoot);
65
+ return found;
66
+ }
67
+ /**
68
+ * The index over `packagesRoot`, narrowed to `scope` (`@endora-commerce/`).
69
+ *
70
+ * A publishable package that declares no version is a throw rather than a
71
+ * skip: an index short by a package is a host short by a module, and the
72
+ * module set derived from it would be silently smaller than the release.
73
+ */
74
+ export function releaseIndexOf(packagesRoot, scope) {
75
+ const packages = [];
76
+ for (const pkg of publishablePackages(packagesRoot)) {
77
+ if (!pkg.name.startsWith(scope))
78
+ continue;
79
+ if (pkg.version === undefined) {
80
+ throw new Error(`${join(pkg.dir, 'package.json')} is publishable and declares no \`version\`, so the ` +
81
+ 'release index cannot say which version of it this release carries.');
82
+ }
83
+ packages.push({ name: pkg.name, version: pkg.version });
84
+ }
85
+ packages.sort((a, b) => a.name.localeCompare(b.name));
86
+ return { packages };
87
+ }
88
+ /** Read an index back, refusing anything that is not one. `source` names the file. */
89
+ export function parseReleaseIndex(text, source) {
90
+ let parsed;
91
+ try {
92
+ parsed = JSON.parse(text);
93
+ }
94
+ catch (error) {
95
+ throw new Error(`${source} is not JSON (${error instanceof Error ? error.message : String(error)}).`);
96
+ }
97
+ const packages = parsed?.packages;
98
+ if (!Array.isArray(packages)) {
99
+ throw new Error(`${source} holds no \`packages\` list.`);
100
+ }
101
+ const entries = [];
102
+ for (const entry of packages) {
103
+ const name = entry?.name;
104
+ const version = entry?.version;
105
+ if (typeof name !== 'string' || typeof version !== 'string') {
106
+ throw new Error(`${source} holds an entry with no string \`name\` or \`version\`.`);
107
+ }
108
+ entries.push({ name, version });
109
+ }
110
+ if (entries.length === 0) {
111
+ throw new Error(`${source} names no package, so there is nothing to install from it.`);
112
+ }
113
+ return { packages: entries };
114
+ }
115
+ /**
116
+ * Where this CLI's own index is: `dist/` of the nearest package root above
117
+ * this module — the same file from `src/` in a checkout and from `dist/` in an
118
+ * installed tarball.
119
+ */
120
+ export function ownReleaseIndexPath(moduleUrl = import.meta.url) {
121
+ let current = dirname(fileURLToPath(moduleUrl));
122
+ for (;;) {
123
+ if (existsSync(join(current, 'package.json')))
124
+ return join(current, 'dist', RELEASE_INDEX_FILE);
125
+ const parent = dirname(current);
126
+ if (parent === current)
127
+ return join(dirname(fileURLToPath(moduleUrl)), RELEASE_INDEX_FILE);
128
+ current = parent;
129
+ }
130
+ }
131
+ /**
132
+ * The build step: derive the index for the CLI package at `cliDir` and write
133
+ * it into its `dist`.
134
+ *
135
+ * The workspace is found by walking up to `pnpm-workspace.yaml`, and the
136
+ * scope comes off the CLI's own name — nothing here is written down. Called by
137
+ * `scripts/write-release-index.mjs`, which the package's `build` runs after
138
+ * `tsc`; a failure fails the build rather than shipping a CLI with no index.
139
+ */
140
+ export function writeReleaseIndex(cliDir) {
141
+ const own = JSON.parse(readFileSync(join(cliDir, 'package.json'), 'utf8'));
142
+ const scope = typeof own.name === 'string' ? /^(@[^/]+\/)/.exec(own.name)?.[1] : undefined;
143
+ if (scope === undefined) {
144
+ throw new Error(`${join(cliDir, 'package.json')} declares no scoped name to derive a scope from.`);
145
+ }
146
+ let root = cliDir;
147
+ while (!existsSync(join(root, 'pnpm-workspace.yaml'))) {
148
+ const parent = dirname(root);
149
+ if (parent === root) {
150
+ throw new Error(`no pnpm-workspace.yaml above ${cliDir}: the release index is derived from a checkout.`);
151
+ }
152
+ root = parent;
153
+ }
154
+ const index = releaseIndexOf(join(root, 'packages'), scope);
155
+ const platform = `${scope}platform`;
156
+ if (!index.packages.some((entry) => entry.name === platform)) {
157
+ throw new Error(`${platform} is not among the publishable packages under ${join(root, 'packages')}.`);
158
+ }
159
+ writeFileSync(join(cliDir, 'dist', RELEASE_INDEX_FILE), `${JSON.stringify(index, null, 2)}\n`, 'utf8');
160
+ return index;
161
+ }
162
+ //# sourceMappingURL=release-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-index.js","sourceRoot":"","sources":["../../src/lib/release-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The one recognizer for "this file starts a repeating execution of its own"
3
+ * (issue #128).
4
+ *
5
+ * Two checks ask that question and used to answer it separately.
6
+ * `check-entry-presence.ts` reads the callback and knows a repeating timer is
7
+ * not only a `setInterval`: a `setTimeout` whose callback re-arms a timer is the
8
+ * same entry point wearing a different constructor. `check-entry-scope.ts`
9
+ * grepped for `setInterval(` — so `search`'s reindex loop, which is exactly that
10
+ * `setTimeout`, was never in its population, and the `interval=4` it printed
11
+ * every run read as a settled count rather than as one spelling's worth of
12
+ * coverage.
13
+ *
14
+ * The fix is a shared recognizer rather than a second one. Lending only the last
15
+ * predicate (`isSelfRescheduling`) would have left the caller to re-implement the
16
+ * parse, the callback binding and the enclosing-function name — most of the
17
+ * recognizer — and those are precisely the parts that drift. So the whole shape
18
+ * lives here and both checks consume it; neither owns it.
19
+ *
20
+ * What this deliberately does **not** decide: what to do about a site it finds.
21
+ * `check-entry-presence` asks whether the callback decides presence,
22
+ * `check-entry-scope` whether the file opens a scope. The shapes are shared, the
23
+ * rules are not.
24
+ *
25
+ * ## Limits, and why they are the same for both callers
26
+ *
27
+ * - A one-shot `setTimeout` — an `AbortController` deadline, a sleep between
28
+ * retries — is not a repeating entry point and is not reported.
29
+ * - A callback that is an identifier bound in another file cannot be read, so
30
+ * a `setTimeout` reached that way is invisible. A `setInterval` is reported
31
+ * anyway, with a null callback: it repeats whatever its callback turns out to
32
+ * be, and what a check cannot see it must not vouch for.
33
+ * - A scheduler hidden behind an imported helper is invisible. The analysis is
34
+ * single-file and syntactic; if that shape arrives, this module has to grow.
35
+ */
36
+ import ts from 'typescript';
37
+ /** The scheduling call a site was built from. */
38
+ export type RepeatingTimerConstruct = 'setInterval' | 'setTimeout';
39
+ export interface RepeatingTimerSite {
40
+ readonly construct: RepeatingTimerConstruct;
41
+ /** The scheduling call itself, for reporting a position. */
42
+ readonly call: ts.CallExpression;
43
+ /**
44
+ * The callback body, or `null` when the argument could not be bound to a
45
+ * function in this file. Only a `setInterval` site can carry `null`.
46
+ */
47
+ readonly callback: ts.Node | null;
48
+ /** 1-based line of the scheduling call. */
49
+ readonly line: number;
50
+ /** The nearest enclosing named function, or `<module scope>`. */
51
+ readonly scheduler: string;
52
+ }
53
+ export declare const MODULE_SCOPE = "<module scope>";
54
+ /** Parse with parent pointers — every predicate below walks upwards. */
55
+ export declare function parseScript(file: string, source: string): ts.SourceFile;
56
+ /** The trailing identifier of a callee: `globalThis.setInterval` → `setInterval`. */
57
+ export declare function calleeName(node: ts.CallExpression): string | null;
58
+ /** The receiver of a call, as its trailing identifier: `process.on` → `process`. */
59
+ export declare function receiverName(node: ts.CallExpression): string | null;
60
+ export declare function stringLiteralOf(node: ts.Node): string | null;
61
+ export type FunctionLike = ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration;
62
+ export declare function isFunctionLike(node: ts.Node): node is FunctionLike;
63
+ /** File-local `function f(){}` / `const f = () => {}` bindings, by name. */
64
+ export declare function localFunctions(sf: ts.SourceFile): Map<string, FunctionLike>;
65
+ /** The nearest named function around `node`, for the ledger key. */
66
+ export declare function enclosingName(node: ts.Node): string | null;
67
+ /** True when the subtree contains a call to one of `names` (as identifier or tail). */
68
+ export declare function callsAnyOf(root: ts.Node, names: ReadonlySet<string>): boolean;
69
+ /**
70
+ * A `setTimeout` repeats only when its callback re-arms a timer itself, or calls
71
+ * back into the function that armed this one. That is the single shape a one-shot
72
+ * deadline cannot accidentally match.
73
+ */
74
+ export declare function isSelfRescheduling(callback: ts.Node, armedBy: string | null): boolean;
75
+ /** Resolve a callback argument to a function body in this file, if we can read one. */
76
+ export declare function callbackOf(argument: ts.Node | undefined, bindings: ReadonlyMap<string, FunctionLike>): ts.Node | null;
77
+ /** Every repeating-timer entry point in one parsed file, in source order. */
78
+ export declare function findRepeatingTimerSites(sf: ts.SourceFile): RepeatingTimerSite[];
79
+ //# sourceMappingURL=repeating-timers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repeating-timers.d.ts","sourceRoot":"","sources":["../../src/lib/repeating-timers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,iDAAiD;AACjD,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,YAAY,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,uBAAuB,CAAC;IAC5C,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAE7C,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,CAEvE;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAKjE;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAOnE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,IAAI,CAU5D;AAED,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,kBAAkB,GAAG,EAAE,CAAC,mBAAmB,CAAC;AAE7F,wBAAgB,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,IAAI,YAAY,CAElE;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAiB3E;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,IAAI,CAuB1D;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAe7E;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAIrF;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CACxB,QAAQ,EAAE,EAAE,CAAC,IAAI,GAAG,SAAS,EAC7B,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,GAC1C,EAAE,CAAC,IAAI,GAAG,IAAI,CAKhB;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,GAAG,kBAAkB,EAAE,CAkC/E"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * The one recognizer for "this file starts a repeating execution of its own"
3
+ * (issue #128).
4
+ *
5
+ * Two checks ask that question and used to answer it separately.
6
+ * `check-entry-presence.ts` reads the callback and knows a repeating timer is
7
+ * not only a `setInterval`: a `setTimeout` whose callback re-arms a timer is the
8
+ * same entry point wearing a different constructor. `check-entry-scope.ts`
9
+ * grepped for `setInterval(` — so `search`'s reindex loop, which is exactly that
10
+ * `setTimeout`, was never in its population, and the `interval=4` it printed
11
+ * every run read as a settled count rather than as one spelling's worth of
12
+ * coverage.
13
+ *
14
+ * The fix is a shared recognizer rather than a second one. Lending only the last
15
+ * predicate (`isSelfRescheduling`) would have left the caller to re-implement the
16
+ * parse, the callback binding and the enclosing-function name — most of the
17
+ * recognizer — and those are precisely the parts that drift. So the whole shape
18
+ * lives here and both checks consume it; neither owns it.
19
+ *
20
+ * What this deliberately does **not** decide: what to do about a site it finds.
21
+ * `check-entry-presence` asks whether the callback decides presence,
22
+ * `check-entry-scope` whether the file opens a scope. The shapes are shared, the
23
+ * rules are not.
24
+ *
25
+ * ## Limits, and why they are the same for both callers
26
+ *
27
+ * - A one-shot `setTimeout` — an `AbortController` deadline, a sleep between
28
+ * retries — is not a repeating entry point and is not reported.
29
+ * - A callback that is an identifier bound in another file cannot be read, so
30
+ * a `setTimeout` reached that way is invisible. A `setInterval` is reported
31
+ * anyway, with a null callback: it repeats whatever its callback turns out to
32
+ * be, and what a check cannot see it must not vouch for.
33
+ * - A scheduler hidden behind an imported helper is invisible. The analysis is
34
+ * single-file and syntactic; if that shape arrives, this module has to grow.
35
+ */
36
+ import ts from 'typescript';
37
+ export const MODULE_SCOPE = '<module scope>';
38
+ /** Parse with parent pointers — every predicate below walks upwards. */
39
+ export function parseScript(file, source) {
40
+ return ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);
41
+ }
42
+ /** The trailing identifier of a callee: `globalThis.setInterval` → `setInterval`. */
43
+ export function calleeName(node) {
44
+ const expression = node.expression;
45
+ if (ts.isIdentifier(expression))
46
+ return expression.text;
47
+ if (ts.isPropertyAccessExpression(expression))
48
+ return expression.name.text;
49
+ return null;
50
+ }
51
+ /** The receiver of a call, as its trailing identifier: `process.on` → `process`. */
52
+ export function receiverName(node) {
53
+ const expression = node.expression;
54
+ if (!ts.isPropertyAccessExpression(expression))
55
+ return null;
56
+ const receiver = expression.expression;
57
+ if (ts.isIdentifier(receiver))
58
+ return receiver.text;
59
+ if (ts.isPropertyAccessExpression(receiver))
60
+ return receiver.name.text;
61
+ return null;
62
+ }
63
+ export function stringLiteralOf(node) {
64
+ if (ts.isStringLiteralLike(node))
65
+ return node.text;
66
+ if (ts.isAsExpression(node) ||
67
+ ts.isNonNullExpression(node) ||
68
+ ts.isParenthesizedExpression(node)) {
69
+ return stringLiteralOf(node.expression);
70
+ }
71
+ return null;
72
+ }
73
+ export function isFunctionLike(node) {
74
+ return ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node);
75
+ }
76
+ /** File-local `function f(){}` / `const f = () => {}` bindings, by name. */
77
+ export function localFunctions(sf) {
78
+ const bindings = new Map();
79
+ const visit = (node) => {
80
+ if (ts.isFunctionDeclaration(node) && node.name) {
81
+ bindings.set(node.name.text, node);
82
+ }
83
+ else if (ts.isVariableDeclaration(node) &&
84
+ ts.isIdentifier(node.name) &&
85
+ node.initializer &&
86
+ isFunctionLike(node.initializer)) {
87
+ bindings.set(node.name.text, node.initializer);
88
+ }
89
+ node.forEachChild(visit);
90
+ };
91
+ sf.forEachChild(visit);
92
+ return bindings;
93
+ }
94
+ /** The nearest named function around `node`, for the ledger key. */
95
+ export function enclosingName(node) {
96
+ for (let cursor = node.parent; cursor; cursor = cursor.parent) {
97
+ if (ts.isFunctionDeclaration(cursor) && cursor.name)
98
+ return cursor.name.text;
99
+ if (ts.isMethodDeclaration(cursor) && ts.isIdentifier(cursor.name))
100
+ return cursor.name.text;
101
+ // `{ plugin: async (app) => { … } }` — the shape every module's plugin body
102
+ // has, and the name a reader would use for it.
103
+ if (ts.isPropertyAssignment(cursor) &&
104
+ ts.isIdentifier(cursor.name) &&
105
+ isFunctionLike(cursor.initializer)) {
106
+ return cursor.name.text;
107
+ }
108
+ if (ts.isVariableDeclaration(cursor) &&
109
+ ts.isIdentifier(cursor.name) &&
110
+ cursor.initializer &&
111
+ isFunctionLike(cursor.initializer)) {
112
+ return cursor.name.text;
113
+ }
114
+ }
115
+ return null;
116
+ }
117
+ /** True when the subtree contains a call to one of `names` (as identifier or tail). */
118
+ export function callsAnyOf(root, names) {
119
+ let found = false;
120
+ const visit = (node) => {
121
+ if (found)
122
+ return;
123
+ if (ts.isCallExpression(node)) {
124
+ const name = calleeName(node);
125
+ if (name !== null && names.has(name)) {
126
+ found = true;
127
+ return;
128
+ }
129
+ }
130
+ node.forEachChild(visit);
131
+ };
132
+ root.forEachChild(visit);
133
+ return found;
134
+ }
135
+ const TIMER_CALLS = new Set(['setInterval', 'setTimeout']);
136
+ /**
137
+ * A `setTimeout` repeats only when its callback re-arms a timer itself, or calls
138
+ * back into the function that armed this one. That is the single shape a one-shot
139
+ * deadline cannot accidentally match.
140
+ */
141
+ export function isSelfRescheduling(callback, armedBy) {
142
+ if (callsAnyOf(callback, TIMER_CALLS))
143
+ return true;
144
+ if (armedBy === null)
145
+ return false;
146
+ return callsAnyOf(callback, new Set([armedBy]));
147
+ }
148
+ /** Resolve a callback argument to a function body in this file, if we can read one. */
149
+ export function callbackOf(argument, bindings) {
150
+ if (argument === undefined)
151
+ return null;
152
+ if (isFunctionLike(argument))
153
+ return argument;
154
+ if (ts.isIdentifier(argument))
155
+ return bindings.get(argument.text) ?? null;
156
+ return null;
157
+ }
158
+ /** Every repeating-timer entry point in one parsed file, in source order. */
159
+ export function findRepeatingTimerSites(sf) {
160
+ const bindings = localFunctions(sf);
161
+ const sites = [];
162
+ const record = (call, construct, callback) => {
163
+ sites.push({
164
+ construct,
165
+ call,
166
+ callback,
167
+ line: sf.getLineAndCharacterOfPosition(call.getStart(sf)).line + 1,
168
+ scheduler: enclosingName(call) ?? MODULE_SCOPE,
169
+ });
170
+ };
171
+ const visit = (node) => {
172
+ if (ts.isCallExpression(node)) {
173
+ const name = calleeName(node);
174
+ if (name === 'setInterval' || name === 'setTimeout') {
175
+ const callback = callbackOf(node.arguments[0], bindings);
176
+ if (name === 'setInterval') {
177
+ record(node, 'setInterval', callback);
178
+ }
179
+ else if (callback !== null && isSelfRescheduling(callback, enclosingName(node))) {
180
+ record(node, 'setTimeout', callback);
181
+ }
182
+ }
183
+ }
184
+ node.forEachChild(visit);
185
+ };
186
+ sf.forEachChild(visit);
187
+ return sites;
188
+ }
189
+ //# sourceMappingURL=repeating-timers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repeating-timers.js","sourceRoot":"","sources":["../../src/lib/repeating-timers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The tree's one comment stripper (issue #241).
3
+ *
4
+ * ## Why this is not two regexes
5
+ *
6
+ * "Remove the comments before matching" was written three times in this
7
+ * repository, independently, and each copy was a pair of regexes — one for
8
+ * `/* … *\/`, one for `//` — whose **order** decided whether it was correct.
9
+ * There is no correct order. Run the block pass first and a `//` line ending in
10
+ * a route glob opens a block comment: `harness-parity.test.ts` did exactly that
11
+ * over `test/helpers/test-server.ts`, whose line 1544 ends
12
+ * `… under /api/v1/admin/assets/` plus a star, and the pass ran on to the next
13
+ * real terminator — **1135 of 2767 lines, 41% of the file**. Every
14
+ * `expect(harnessCode).not.toContain(…)` inside that window was green because
15
+ * the text was gone, `runBootHooks(`, `errorEnvelope` and
16
+ * `resolvePreferredLanguage` among them. Run the line pass first and the
17
+ * symmetric hole opens: a `//` inside a block comment truncates it. And in
18
+ * either order a string literal holding a comment token — `'/*'` in
19
+ * `assets_library`'s wildcard-MIME test, `'image/*, *\/*;q=0.5'` in
20
+ * `pim_ergonode`'s Accept header — opens or closes a comment that is not there.
21
+ *
22
+ * So this asks the parser instead. `ts` is already a backend dependency and
23
+ * already the input to nineteen checks; a scanner that knows what a string
24
+ * literal is has no order to get wrong.
25
+ *
26
+ * ## Blanked, not deleted
27
+ *
28
+ * Every comment character becomes a space and every newline survives, so a line
29
+ * number in the result is a line number in the source. A stripper that deletes
30
+ * shifts every finding below the first comment onto a line the reader cannot
31
+ * open, and the three copies this replaces all did.
32
+ */
33
+ export declare function codeOnly(source: string, fileName?: string): string;
34
+ //# sourceMappingURL=source-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-text.d.ts","sourceRoot":"","sources":["../../src/lib/source-text.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,MAAM,CAiBvE"}
@@ -0,0 +1,80 @@
1
+ import ts from 'typescript';
2
+ /**
3
+ * The tree's one comment stripper (issue #241).
4
+ *
5
+ * ## Why this is not two regexes
6
+ *
7
+ * "Remove the comments before matching" was written three times in this
8
+ * repository, independently, and each copy was a pair of regexes — one for
9
+ * `/* … *\/`, one for `//` — whose **order** decided whether it was correct.
10
+ * There is no correct order. Run the block pass first and a `//` line ending in
11
+ * a route glob opens a block comment: `harness-parity.test.ts` did exactly that
12
+ * over `test/helpers/test-server.ts`, whose line 1544 ends
13
+ * `… under /api/v1/admin/assets/` plus a star, and the pass ran on to the next
14
+ * real terminator — **1135 of 2767 lines, 41% of the file**. Every
15
+ * `expect(harnessCode).not.toContain(…)` inside that window was green because
16
+ * the text was gone, `runBootHooks(`, `errorEnvelope` and
17
+ * `resolvePreferredLanguage` among them. Run the line pass first and the
18
+ * symmetric hole opens: a `//` inside a block comment truncates it. And in
19
+ * either order a string literal holding a comment token — `'/*'` in
20
+ * `assets_library`'s wildcard-MIME test, `'image/*, *\/*;q=0.5'` in
21
+ * `pim_ergonode`'s Accept header — opens or closes a comment that is not there.
22
+ *
23
+ * So this asks the parser instead. `ts` is already a backend dependency and
24
+ * already the input to nineteen checks; a scanner that knows what a string
25
+ * literal is has no order to get wrong.
26
+ *
27
+ * ## Blanked, not deleted
28
+ *
29
+ * Every comment character becomes a space and every newline survives, so a line
30
+ * number in the result is a line number in the source. A stripper that deletes
31
+ * shifts every finding below the first comment onto a line the reader cannot
32
+ * open, and the three copies this replaces all did.
33
+ */
34
+ export function codeOnly(source, fileName = 'source.ts') {
35
+ const scriptKind = fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
36
+ const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.ES2022, true, scriptKind);
37
+ const characters = [...source];
38
+ for (const range of commentRanges(sourceFile, source)) {
39
+ for (let index = range.pos; index < range.end; index += 1) {
40
+ if (characters[index] !== '\n')
41
+ characters[index] = ' ';
42
+ }
43
+ }
44
+ return characters.join('');
45
+ }
46
+ /**
47
+ * Every comment span the parser saw, sorted.
48
+ *
49
+ * Trivia hangs off token positions rather than off nodes of its own, so the
50
+ * walk asks at both ends of every node: a comment is leading trivia for the
51
+ * token after it and trailing trivia for the token before it, and the file's
52
+ * last comment is leading trivia of the end-of-file token. Ranges repeat under
53
+ * that walk, which is what the `seen` set is for.
54
+ */
55
+ function commentRanges(sourceFile, source) {
56
+ const found = [];
57
+ const seen = new Set();
58
+ const collect = (position) => {
59
+ const ranges = [
60
+ ...(ts.getLeadingCommentRanges(source, position) ?? []),
61
+ ...(ts.getTrailingCommentRanges(source, position) ?? []),
62
+ ];
63
+ for (const range of ranges) {
64
+ const key = `${range.pos}:${range.end}`;
65
+ if (seen.has(key))
66
+ continue;
67
+ seen.add(key);
68
+ found.push(range);
69
+ }
70
+ };
71
+ const visit = (node) => {
72
+ collect(node.getFullStart());
73
+ collect(node.getEnd());
74
+ for (const child of node.getChildren(sourceFile))
75
+ visit(child);
76
+ };
77
+ visit(sourceFile);
78
+ return found.sort((a, b) => a.pos - b.pos);
79
+ }
80
+ //# sourceMappingURL=source-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-text.js","sourceRoot":"","sources":["../../src/lib/source-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,QAAQ,GAAG,WAAW;IAC7D,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;IACpF,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,QAAQ,EACR,MAAM,EACN,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,EACJ,UAAU,CACX,CAAC;IAEF,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC;QACtD,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC1D,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI;gBAAE,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,UAAyB,EAAE,MAAc;IAC9D,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAQ,EAAE;QACzC,MAAM,MAAM,GAAG;YACb,GAAG,CAAC,EAAE,CAAC,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;YACvD,GAAG,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;SACzD,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QACpC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAElB,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,20 @@
1
+ /** The shape a specifier was written in. See the header for why each is listed. */
2
+ export type SpecifierKind = 'value-import' | 'type-only-import' | 'mixed-type-specifier' | 're-export' | 'side-effect-import' | 'dynamic-import' | 'require-call' | 'import-type-node';
3
+ /** One specifier as it was written, with everything a boundary rule needs of it. */
4
+ export interface NamedSpecifier {
5
+ /** The specifier exactly as written, extension and all. */
6
+ readonly text: string;
7
+ readonly kind: SpecifierKind;
8
+ /** What the import takes: a reviewer's first question is shape or behaviour. */
9
+ readonly bindings: readonly string[];
10
+ readonly line: number;
11
+ }
12
+ /**
13
+ * Every module specifier `source` names, in source order.
14
+ *
15
+ * `file` is used only for the source-file name the compiler API wants and for
16
+ * line numbers; nothing here touches disk, so a caller may pass a path that does
17
+ * not exist — which is what lets both checks' fixtures enter at the top.
18
+ */
19
+ export declare function namedSpecifiers(source: string, file: string): NamedSpecifier[];
20
+ //# sourceMappingURL=specifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specifiers.d.ts","sourceRoot":"","sources":["../../src/lib/specifiers.ts"],"names":[],"mappings":"AAsCA,mFAAmF;AACnF,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,kBAAkB,GAClB,sBAAsB,GACtB,WAAW,GACX,oBAAoB,GACpB,gBAAgB,GAChB,cAAc,GACd,kBAAkB,CAAC;AAEvB,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AA2CD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAqD9E"}