@topogram/cli 0.3.63 → 0.3.65

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 (344) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.d.ts +6 -0
  4. package/src/adoption/plan.js +12 -703
  5. package/src/adoption/reporting.d.ts +10 -0
  6. package/src/adoption/review-groups.d.ts +6 -0
  7. package/src/agent-brief.d.ts +3 -0
  8. package/src/agent-brief.js +495 -0
  9. package/src/agent-ops/query-builders/auth.js +375 -0
  10. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  11. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  12. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  13. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  14. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  15. package/src/agent-ops/query-builders/change-risk.js +25 -0
  16. package/src/agent-ops/query-builders/common.js +149 -0
  17. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  18. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  19. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  20. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  21. package/src/agent-ops/query-builders/work-packets.js +417 -0
  22. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  23. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  24. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  25. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  26. package/src/agent-ops/query-builders.d.ts +26 -0
  27. package/src/agent-ops/query-builders.js +42 -5021
  28. package/src/archive/archive.d.ts +2 -0
  29. package/src/archive/compact.d.ts +1 -0
  30. package/src/archive/unarchive.d.ts +1 -0
  31. package/src/catalog/constants.js +10 -0
  32. package/src/catalog/copy.js +60 -0
  33. package/src/catalog/diagnostics.js +15 -0
  34. package/src/catalog/entries.js +42 -0
  35. package/src/catalog/files.js +67 -0
  36. package/src/catalog/provenance.js +122 -0
  37. package/src/catalog/source.js +150 -0
  38. package/src/catalog/validation.js +252 -0
  39. package/src/catalog.d.ts +12 -0
  40. package/src/catalog.js +18 -750
  41. package/src/cli/catalog-alias.d.ts +1 -0
  42. package/src/cli/command-parser.js +38 -0
  43. package/src/cli/command-parsers/core.js +102 -0
  44. package/src/cli/command-parsers/generator.js +39 -0
  45. package/src/cli/command-parsers/import.js +44 -0
  46. package/src/cli/command-parsers/legacy-workflow.js +21 -0
  47. package/src/cli/command-parsers/project.js +47 -0
  48. package/src/cli/command-parsers/sdlc.js +47 -0
  49. package/src/cli/command-parsers/shared.js +51 -0
  50. package/src/cli/command-parsers/template.js +48 -0
  51. package/src/cli/commands/agent.js +47 -0
  52. package/src/cli/commands/catalog/check.js +31 -0
  53. package/src/cli/commands/catalog/copy.js +59 -0
  54. package/src/cli/commands/catalog/doctor.js +248 -0
  55. package/src/cli/commands/catalog/help.js +21 -0
  56. package/src/cli/commands/catalog/list.js +52 -0
  57. package/src/cli/commands/catalog/runner.js +92 -0
  58. package/src/cli/commands/catalog/shared.js +17 -0
  59. package/src/cli/commands/catalog/show.js +134 -0
  60. package/src/cli/commands/catalog.js +32 -0
  61. package/src/cli/commands/check.js +268 -0
  62. package/src/cli/commands/doctor.js +268 -0
  63. package/src/cli/commands/emit.js +149 -0
  64. package/src/cli/commands/generate.js +96 -0
  65. package/src/cli/commands/generator-policy/package-info.js +162 -0
  66. package/src/cli/commands/generator-policy/payloads.js +372 -0
  67. package/src/cli/commands/generator-policy/printers.js +159 -0
  68. package/src/cli/commands/generator-policy/runner.js +81 -0
  69. package/src/cli/commands/generator-policy/shared.js +39 -0
  70. package/src/cli/commands/generator-policy.js +17 -0
  71. package/src/cli/commands/generator.js +443 -0
  72. package/src/cli/commands/import/adopt.js +170 -0
  73. package/src/cli/commands/import/check.js +91 -0
  74. package/src/cli/commands/import/diff.js +84 -0
  75. package/src/cli/commands/import/help.js +47 -0
  76. package/src/cli/commands/import/paths.js +277 -0
  77. package/src/cli/commands/import/plan.js +284 -0
  78. package/src/cli/commands/import/refresh.js +470 -0
  79. package/src/cli/commands/import/status-history.js +196 -0
  80. package/src/cli/commands/import/workspace.js +230 -0
  81. package/src/cli/commands/import-runner.js +157 -0
  82. package/src/cli/commands/import.js +35 -0
  83. package/src/cli/commands/inspect.js +55 -0
  84. package/src/cli/commands/new.js +94 -0
  85. package/src/cli/commands/package/constants.js +17 -0
  86. package/src/cli/commands/package/doctor.js +240 -0
  87. package/src/cli/commands/package/help.js +27 -0
  88. package/src/cli/commands/package/lockfile.js +135 -0
  89. package/src/cli/commands/package/npm.js +97 -0
  90. package/src/cli/commands/package/reporting.js +35 -0
  91. package/src/cli/commands/package/runner.js +33 -0
  92. package/src/cli/commands/package/shared.js +9 -0
  93. package/src/cli/commands/package/update-cli.js +252 -0
  94. package/src/cli/commands/package/versions.js +35 -0
  95. package/src/cli/commands/package.js +31 -0
  96. package/src/cli/commands/query/change-plan.js +68 -0
  97. package/src/cli/commands/query/definitions.js +202 -0
  98. package/src/cli/commands/query/import-adopt.js +121 -0
  99. package/src/cli/commands/query/runner/artifacts.js +102 -0
  100. package/src/cli/commands/query/runner/boundaries.js +211 -0
  101. package/src/cli/commands/query/runner/change.js +182 -0
  102. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  103. package/src/cli/commands/query/runner/index.js +31 -0
  104. package/src/cli/commands/query/runner/output.js +12 -0
  105. package/src/cli/commands/query/runner/workflow.js +241 -0
  106. package/src/cli/commands/query/runner.js +3 -0
  107. package/src/cli/commands/query/workflow-context.js +5 -0
  108. package/src/cli/commands/query/workspace.js +274 -0
  109. package/src/cli/commands/query.js +11 -0
  110. package/src/cli/commands/release-rollout.js +257 -0
  111. package/src/cli/commands/release-shared.js +528 -0
  112. package/src/cli/commands/release-status.js +429 -0
  113. package/src/cli/commands/release.js +107 -0
  114. package/src/cli/commands/sdlc.js +168 -0
  115. package/src/cli/commands/setup.js +76 -0
  116. package/src/cli/commands/source.js +291 -0
  117. package/src/cli/commands/template/baseline.js +100 -0
  118. package/src/cli/commands/template/check.js +466 -0
  119. package/src/cli/commands/template/constants.js +8 -0
  120. package/src/cli/commands/template/diagnostics.js +26 -0
  121. package/src/cli/commands/template/help.js +28 -0
  122. package/src/cli/commands/template/lifecycle.js +404 -0
  123. package/src/cli/commands/template/list-show.js +287 -0
  124. package/src/cli/commands/template/policy.js +422 -0
  125. package/src/cli/commands/template/shared.js +127 -0
  126. package/src/cli/commands/template/updates.js +352 -0
  127. package/src/cli/commands/template-runner.js +198 -0
  128. package/src/cli/commands/template.js +43 -0
  129. package/src/cli/commands/trust.js +219 -0
  130. package/src/cli/commands/version.js +40 -0
  131. package/src/cli/commands/widget.js +168 -0
  132. package/src/cli/commands/workflow.js +63 -0
  133. package/src/cli/dispatcher.js +392 -0
  134. package/src/cli/help-dispatch.js +188 -0
  135. package/src/cli/help.js +296 -0
  136. package/src/cli/migration-guidance.js +59 -0
  137. package/src/cli/options.js +96 -0
  138. package/src/cli/output-safety.js +107 -0
  139. package/src/cli/path-normalization.js +29 -0
  140. package/src/cli.js +47 -11711
  141. package/src/example-implementation.d.ts +2 -0
  142. package/src/format.d.ts +1 -0
  143. package/src/generator/api/contracts.js +497 -0
  144. package/src/generator/api/metadata.js +221 -0
  145. package/src/generator/api/openapi.js +559 -0
  146. package/src/generator/api/schema.js +124 -0
  147. package/src/generator/api/types.d.ts +98 -0
  148. package/src/generator/api.js +3 -1195
  149. package/src/generator/check.d.ts +1 -0
  150. package/src/generator/context/bundle.d.ts +1 -0
  151. package/src/generator/context/shared/domain-sdlc.js +282 -0
  152. package/src/generator/context/shared/maintained-boundary.js +665 -0
  153. package/src/generator/context/shared/metrics.js +85 -0
  154. package/src/generator/context/shared/primitives.js +64 -0
  155. package/src/generator/context/shared/relationships.js +453 -0
  156. package/src/generator/context/shared/summaries.js +263 -0
  157. package/src/generator/context/shared/types.d.ts +207 -0
  158. package/src/generator/context/shared.d.ts +44 -0
  159. package/src/generator/context/shared.js +80 -1390
  160. package/src/generator/context/slice/core.js +397 -0
  161. package/src/generator/context/slice/sdlc.js +417 -0
  162. package/src/generator/context/slice/ui-packets.js +183 -0
  163. package/src/generator/context/slice.js +2 -859
  164. package/src/generator/native/parity-bundle.js +2 -1
  165. package/src/generator/registry/index.js +507 -0
  166. package/src/generator/registry.js +18 -504
  167. package/src/generator/runtime/environment/index.js +666 -0
  168. package/src/generator/runtime/environment.js +4 -666
  169. package/src/generator/runtime/runtime-check/index.js +554 -0
  170. package/src/generator/runtime/runtime-check.js +4 -554
  171. package/src/generator/runtime/shared/index.js +572 -0
  172. package/src/generator/runtime/shared.js +19 -570
  173. package/src/generator/shared.d.ts +2 -0
  174. package/src/generator/surfaces/shared.d.ts +3 -0
  175. package/src/generator/surfaces/web/html-escape.js +22 -0
  176. package/src/generator/surfaces/web/react.js +10 -8
  177. package/src/generator/surfaces/web/sveltekit.js +7 -5
  178. package/src/generator/surfaces/web/vanilla.js +8 -4
  179. package/src/generator/widget-conformance/behavior-report.js +258 -0
  180. package/src/generator/widget-conformance/checks.js +371 -0
  181. package/src/generator/widget-conformance/projection-context.js +200 -0
  182. package/src/generator/widget-conformance/report.js +166 -0
  183. package/src/generator/widget-conformance/types.d.ts +121 -0
  184. package/src/generator/widget-conformance.js +3 -824
  185. package/src/generator.d.ts +2 -0
  186. package/src/github-client.js +520 -0
  187. package/src/import/core/context.d.ts +3 -0
  188. package/src/import/core/contracts.d.ts +1 -0
  189. package/src/import/core/registry.d.ts +4 -0
  190. package/src/import/core/runner/candidates.js +217 -0
  191. package/src/import/core/runner/options.js +22 -0
  192. package/src/import/core/runner/reports.js +50 -0
  193. package/src/import/core/runner/run.js +79 -0
  194. package/src/import/core/runner/tracks.js +150 -0
  195. package/src/import/core/runner/ui-drafts.js +337 -0
  196. package/src/import/core/runner.js +3 -698
  197. package/src/import/core/shared/api-routes.js +221 -0
  198. package/src/import/core/shared/candidates.js +97 -0
  199. package/src/import/core/shared/files.js +177 -0
  200. package/src/import/core/shared/next-app.js +389 -0
  201. package/src/import/core/shared/types.d.ts +51 -0
  202. package/src/import/core/shared/ui-routes.js +230 -0
  203. package/src/import/core/shared.js +67 -910
  204. package/src/import/extractors/api/flutter-dio.js +4 -8
  205. package/src/import/extractors/api/react-native-repository.js +4 -8
  206. package/src/import/index.d.ts +4 -0
  207. package/src/import/provenance.d.ts +4 -0
  208. package/src/new-project/constants.js +128 -0
  209. package/src/new-project/create.js +83 -0
  210. package/src/new-project/json.js +28 -0
  211. package/src/new-project/metadata.js +96 -0
  212. package/src/new-project/package-spec.js +161 -0
  213. package/src/new-project/project-files.js +348 -0
  214. package/src/new-project/template-policy.js +269 -0
  215. package/src/new-project/template-resolution.js +368 -0
  216. package/src/new-project/template-snapshots.js +430 -0
  217. package/src/new-project/template-updates.js +512 -0
  218. package/src/new-project/types.d.ts +83 -0
  219. package/src/new-project.js +6 -2188
  220. package/src/npm-safety.js +79 -0
  221. package/src/parser.d.ts +87 -0
  222. package/src/parser.js +118 -0
  223. package/src/path-helpers.d.ts +1 -0
  224. package/src/path-helpers.js +20 -0
  225. package/src/policy/review-boundaries.d.ts +15 -0
  226. package/src/project-config/index.js +564 -0
  227. package/src/project-config.js +19 -560
  228. package/src/reconcile/docs.d.ts +8 -0
  229. package/src/reconcile/journeys.d.ts +1 -0
  230. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  231. package/src/resolver/enrich/bug.js +2 -0
  232. package/src/resolver/enrich/pitch.js +2 -0
  233. package/src/resolver/enrich/requirement.js +2 -0
  234. package/src/resolver/enrich/task.js +2 -0
  235. package/src/resolver/index.js +19 -2089
  236. package/src/resolver/normalize.js +384 -1
  237. package/src/resolver/plans.js +168 -0
  238. package/src/resolver/projections-api.js +494 -0
  239. package/src/resolver/projections-db.js +133 -0
  240. package/src/resolver/projections-ui.js +317 -0
  241. package/src/resolver/shapes.js +251 -0
  242. package/src/resolver/shared.js +278 -0
  243. package/src/resolver/widgets.js +132 -0
  244. package/src/resolver.d.ts +1 -0
  245. package/src/runtime-support.js +29 -0
  246. package/src/sdlc/adopt.d.ts +1 -0
  247. package/src/sdlc/check.d.ts +1 -0
  248. package/src/sdlc/explain.d.ts +1 -0
  249. package/src/sdlc/release.d.ts +1 -0
  250. package/src/sdlc/scaffold.d.ts +1 -0
  251. package/src/sdlc/transition.d.ts +1 -0
  252. package/src/template-trust/constants.js +62 -0
  253. package/src/template-trust/content.js +258 -0
  254. package/src/template-trust/diff.js +92 -0
  255. package/src/template-trust/policy.js +61 -0
  256. package/src/template-trust/record.js +90 -0
  257. package/src/template-trust/status.js +182 -0
  258. package/src/template-trust.js +24 -687
  259. package/src/text-helpers.d.ts +7 -0
  260. package/src/text-helpers.js +245 -0
  261. package/src/topogram-config.js +306 -0
  262. package/src/topogram-types.d.ts +69 -0
  263. package/src/validator/common.js +488 -0
  264. package/src/validator/data-model.js +237 -0
  265. package/src/validator/docs.js +167 -0
  266. package/src/validator/expressions.js +146 -1
  267. package/src/validator/index.d.ts +23 -0
  268. package/src/validator/index.js +32 -3585
  269. package/src/validator/kinds.d.ts +41 -0
  270. package/src/validator/kinds.js +2 -0
  271. package/src/validator/model-helpers.js +46 -0
  272. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  273. package/src/validator/per-kind/bug.js +6 -0
  274. package/src/validator/per-kind/domain.js +15 -2
  275. package/src/validator/per-kind/pitch.js +7 -0
  276. package/src/validator/per-kind/requirement.js +5 -0
  277. package/src/validator/per-kind/task.js +7 -0
  278. package/src/validator/per-kind/widget.js +14 -0
  279. package/src/validator/projections/api-http-async.js +410 -0
  280. package/src/validator/projections/api-http-authz.js +88 -0
  281. package/src/validator/projections/api-http-core.js +205 -0
  282. package/src/validator/projections/api-http-policies.js +339 -0
  283. package/src/validator/projections/api-http-responses.js +233 -0
  284. package/src/validator/projections/api-http.js +44 -0
  285. package/src/validator/projections/db.js +353 -0
  286. package/src/validator/projections/generator-defaults.js +45 -0
  287. package/src/validator/projections/helpers.js +87 -0
  288. package/src/validator/projections/ui-helpers.js +214 -0
  289. package/src/validator/projections/ui-navigation.js +344 -0
  290. package/src/validator/projections/ui-structure.js +364 -0
  291. package/src/validator/projections/ui-widgets.js +493 -0
  292. package/src/validator/projections/ui.js +46 -0
  293. package/src/validator/registry.js +48 -1
  294. package/src/validator/utils.d.ts +20 -0
  295. package/src/validator/utils.js +115 -12
  296. package/src/validator.d.ts +2 -0
  297. package/src/widget-behavior.d.ts +1 -0
  298. package/src/workflows/adoption/index.js +26 -0
  299. package/src/workflows/docs-generate.js +262 -0
  300. package/src/workflows/docs-scan.js +703 -0
  301. package/src/workflows/docs.js +15 -0
  302. package/src/workflows/import-app/api/collect.js +221 -0
  303. package/src/workflows/import-app/api/openapi.js +257 -0
  304. package/src/workflows/import-app/api/routes.js +327 -0
  305. package/src/workflows/import-app/api/sources.js +22 -0
  306. package/src/workflows/import-app/api.js +4 -0
  307. package/src/workflows/import-app/db.js +538 -0
  308. package/src/workflows/import-app/index.js +30 -0
  309. package/src/workflows/import-app/shared.js +218 -0
  310. package/src/workflows/import-app/ui.js +443 -0
  311. package/src/workflows/import-app/workflow.js +159 -0
  312. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  313. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  314. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  315. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  316. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  317. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  318. package/src/workflows/reconcile/adoption-plan.js +32 -0
  319. package/src/workflows/reconcile/auth/closures.js +115 -0
  320. package/src/workflows/reconcile/auth/formatters.js +142 -0
  321. package/src/workflows/reconcile/auth/inference.js +330 -0
  322. package/src/workflows/reconcile/auth/roles.js +122 -0
  323. package/src/workflows/reconcile/auth.js +37 -0
  324. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  325. package/src/workflows/reconcile/bundle-core.js +14 -0
  326. package/src/workflows/reconcile/bundle-shared.js +75 -0
  327. package/src/workflows/reconcile/candidate-model.js +477 -0
  328. package/src/workflows/reconcile/canonical-surface.js +264 -0
  329. package/src/workflows/reconcile/gap-report.js +333 -0
  330. package/src/workflows/reconcile/ids.js +6 -0
  331. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  332. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  333. package/src/workflows/reconcile/impacts/patches.js +252 -0
  334. package/src/workflows/reconcile/impacts/reports.js +80 -0
  335. package/src/workflows/reconcile/impacts.js +16 -0
  336. package/src/workflows/reconcile/index.js +7 -0
  337. package/src/workflows/reconcile/renderers.js +461 -0
  338. package/src/workflows/reconcile/summary.js +90 -0
  339. package/src/workflows/reconcile/workflow.js +309 -0
  340. package/src/workflows/shared.js +189 -0
  341. package/src/workflows/types.d.ts +93 -0
  342. package/src/workflows.d.ts +1 -0
  343. package/src/workflows.js +10 -7652
  344. package/src/workspace-docs.d.ts +29 -0
@@ -0,0 +1,79 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ export const LOCAL_NPMRC_ENV = "TOPOGRAM_ALLOW_LOCAL_NPMRC";
7
+
8
+ /**
9
+ * @param {string} spec
10
+ * @returns {string}
11
+ */
12
+ export function assertSafeNpmSpec(spec) {
13
+ if (typeof spec !== "string" || spec.trim().length === 0) {
14
+ throw new Error("Empty npm package spec.");
15
+ }
16
+ if (spec.startsWith("-")) {
17
+ throw new Error(`Refusing npm package spec starting with '-': '${spec}'.`);
18
+ }
19
+ if (/[\s\r\n\0]/.test(spec)) {
20
+ throw new Error(`Invalid characters in npm package spec: '${spec}'.`);
21
+ }
22
+ return spec;
23
+ }
24
+
25
+ /**
26
+ * @param {string|undefined} value
27
+ * @returns {boolean}
28
+ */
29
+ export function localNpmrcAllowedByEnv(value = process.env[LOCAL_NPMRC_ENV]) {
30
+ return value === "1" || value === "true" || value === "yes";
31
+ }
32
+
33
+ /**
34
+ * @param {string} cwd
35
+ * @returns {{ exists: boolean, path: string, enabled: boolean, reason: string }}
36
+ */
37
+ export function localNpmrcStatus(cwd = process.cwd()) {
38
+ const npmrcPath = path.join(cwd, ".npmrc");
39
+ const exists = fs.existsSync(npmrcPath);
40
+ if (process.env.NPM_CONFIG_USERCONFIG) {
41
+ return {
42
+ exists,
43
+ path: npmrcPath,
44
+ enabled: false,
45
+ reason: "NPM_CONFIG_USERCONFIG is already set explicitly."
46
+ };
47
+ }
48
+ if (!exists) {
49
+ return {
50
+ exists,
51
+ path: npmrcPath,
52
+ enabled: false,
53
+ reason: "No local .npmrc was found."
54
+ };
55
+ }
56
+ if (!localNpmrcAllowedByEnv()) {
57
+ return {
58
+ exists,
59
+ path: npmrcPath,
60
+ enabled: false,
61
+ reason: `Local .npmrc is ignored unless ${LOCAL_NPMRC_ENV}=1 or --allow-local-npmrc is used.`
62
+ };
63
+ }
64
+ return {
65
+ exists,
66
+ path: npmrcPath,
67
+ enabled: true,
68
+ reason: `Local .npmrc is enabled by ${LOCAL_NPMRC_ENV}.`
69
+ };
70
+ }
71
+
72
+ /**
73
+ * @param {string} cwd
74
+ * @returns {Record<string, string>}
75
+ */
76
+ export function localNpmrcEnv(cwd = process.cwd()) {
77
+ const status = localNpmrcStatus(cwd);
78
+ return status.enabled ? { NPM_CONFIG_USERCONFIG: status.path } : {};
79
+ }
@@ -0,0 +1,87 @@
1
+ import type { TopogramDoc } from "./workspace-docs.js";
2
+
3
+ export interface ParserPosition {
4
+ line: number;
5
+ column: number;
6
+ offset: number;
7
+ }
8
+
9
+ export interface LexerToken {
10
+ type: string;
11
+ value: string;
12
+ start: ParserPosition;
13
+ end: ParserPosition;
14
+ }
15
+
16
+ export interface AstLocation {
17
+ file: string;
18
+ start: ParserPosition;
19
+ end: ParserPosition;
20
+ }
21
+
22
+ export interface AstScalar {
23
+ type: "string" | "symbol";
24
+ value: string;
25
+ loc: AstLocation;
26
+ }
27
+
28
+ export interface AstList {
29
+ type: "list";
30
+ items: AstValue[];
31
+ loc: AstLocation;
32
+ }
33
+
34
+ export interface AstSequence {
35
+ type: "sequence";
36
+ items: AstValue[];
37
+ loc: AstLocation;
38
+ }
39
+
40
+ export interface AstBlock {
41
+ type: "block";
42
+ entries: AstBlockEntry[];
43
+ loc: AstLocation;
44
+ }
45
+
46
+ export type AstValue = AstScalar | AstList | AstSequence | AstBlock;
47
+
48
+ export interface AstBlockEntry {
49
+ type: "block_entry";
50
+ items: AstValue[];
51
+ loc: AstLocation;
52
+ }
53
+
54
+ export interface AstField {
55
+ type: "field";
56
+ key: string;
57
+ value: AstValue;
58
+ loc: AstLocation;
59
+ }
60
+
61
+ export interface AstStatement {
62
+ type: "statement";
63
+ kind: string;
64
+ id: string;
65
+ from: AstScalar | null;
66
+ fields: AstField[];
67
+ loc: AstLocation;
68
+ }
69
+
70
+ export interface AstDocument {
71
+ type: "document";
72
+ file: string;
73
+ statements: AstStatement[];
74
+ }
75
+
76
+ export interface WorkspaceAst {
77
+ type: "workspace";
78
+ root: string;
79
+ files: AstDocument[];
80
+ docs: TopogramDoc[];
81
+ }
82
+
83
+ export function lex(source: string, filePath?: string): LexerToken[];
84
+ export function parseSource(source: string, filePath?: string): AstDocument;
85
+ export function parseFile(filePath: string): AstDocument;
86
+ export function collectTopogramFiles(inputPath: string): string[];
87
+ export function parsePath(root: string): WorkspaceAst;
package/src/parser.js CHANGED
@@ -1,31 +1,76 @@
1
+ // @ts-check
2
+
1
3
  import fs from "node:fs";
2
4
  import path from "node:path";
3
5
  import { parseDocsPath } from "./workspace-docs.js";
4
6
 
7
+ /**
8
+ * @typedef {{ line: number, column: number, offset: number }} ParserPosition
9
+ * @typedef {{ type: string, value: string, start: ParserPosition, end: ParserPosition }} LexerToken
10
+ * @typedef {{ file: string, start: ParserPosition, end: ParserPosition }} AstLocation
11
+ * @typedef {{ type: "string" | "symbol", value: string, loc: AstLocation }} AstScalar
12
+ * @typedef {{ type: "list", items: AstValue[], loc: AstLocation }} AstList
13
+ * @typedef {{ type: "sequence", items: AstValue[], loc: AstLocation }} AstSequence
14
+ * @typedef {{ type: "block", entries: AstBlockEntry[], loc: AstLocation }} AstBlock
15
+ * @typedef {AstScalar | AstList | AstSequence | AstBlock} AstValue
16
+ * @typedef {{ type: "block_entry", items: AstValue[], loc: AstLocation }} AstBlockEntry
17
+ * @typedef {{ type: "field", key: string, value: AstValue, loc: AstLocation }} AstField
18
+ * @typedef {{ type: "statement", kind: string, id: string, from: AstScalar | null, fields: AstField[], loc: AstLocation }} AstStatement
19
+ * @typedef {{ type: "document", file: string, statements: AstStatement[] }} AstDocument
20
+ * @typedef {{ type: "workspace", root: string, files: AstDocument[], docs: any[] }} WorkspaceAst
21
+ */
22
+
23
+ /**
24
+ * @param {number} line
25
+ * @param {number} column
26
+ * @param {number} offset
27
+ * @returns {ParserPosition}
28
+ */
5
29
  function createPos(line, column, offset) {
6
30
  return { line, column, offset };
7
31
  }
8
32
 
33
+ /**
34
+ * @param {string} type
35
+ * @param {string} value
36
+ * @param {ParserPosition} start
37
+ * @param {ParserPosition} end
38
+ * @returns {LexerToken}
39
+ */
9
40
  function createToken(type, value, start, end) {
10
41
  return { type, value, start, end };
11
42
  }
12
43
 
44
+ /**
45
+ * @param {string} filePath
46
+ * @param {string} message
47
+ * @param {LexerToken | null | undefined} token
48
+ * @returns {Error}
49
+ */
13
50
  function createError(filePath, message, token) {
14
51
  const line = token?.start?.line ?? 1;
15
52
  const column = token?.start?.column ?? 1;
16
53
  return new Error(`${filePath}:${line}:${column} ${message}`);
17
54
  }
18
55
 
56
+ /**
57
+ * @param {string} source
58
+ * @param {string} [filePath]
59
+ * @returns {LexerToken[]}
60
+ */
19
61
  export function lex(source, filePath = "<memory>") {
62
+ /** @type {LexerToken[]} */
20
63
  const tokens = [];
21
64
  let i = 0;
22
65
  let line = 1;
23
66
  let column = 1;
24
67
 
68
+ /** @returns {ParserPosition} */
25
69
  function pos() {
26
70
  return createPos(line, column, i);
27
71
  }
28
72
 
73
+ /** @param {string} char */
29
74
  function advanceChar(char) {
30
75
  i += 1;
31
76
  if (char === "\n") {
@@ -36,6 +81,12 @@ export function lex(source, filePath = "<memory>") {
36
81
  }
37
82
  }
38
83
 
84
+ /**
85
+ * @param {string} type
86
+ * @param {string} value
87
+ * @param {ParserPosition} start
88
+ * @param {ParserPosition} end
89
+ */
39
90
  function push(type, value, start, end) {
40
91
  tokens.push(createToken(type, value, start, end));
41
92
  }
@@ -166,31 +217,48 @@ export function lex(source, filePath = "<memory>") {
166
217
  }
167
218
 
168
219
  class Parser {
220
+ /**
221
+ * @param {LexerToken[]} tokens
222
+ * @param {string} filePath
223
+ */
169
224
  constructor(tokens, filePath) {
170
225
  this.tokens = tokens;
171
226
  this.filePath = filePath;
172
227
  this.index = 0;
173
228
  }
174
229
 
230
+ /** @returns {LexerToken} */
175
231
  current() {
176
232
  return this.tokens[this.index];
177
233
  }
178
234
 
235
+ /** @returns {LexerToken | undefined} */
179
236
  previous() {
180
237
  return this.tokens[this.index - 1];
181
238
  }
182
239
 
240
+ /** @returns {LexerToken} */
183
241
  advance() {
184
242
  const token = this.current();
185
243
  this.index += 1;
186
244
  return token;
187
245
  }
188
246
 
247
+ /**
248
+ * @param {string} type
249
+ * @param {string} [value]
250
+ * @returns {boolean}
251
+ */
189
252
  check(type, value) {
190
253
  const token = this.current();
191
254
  return token.type === type && (value === undefined || token.value === value);
192
255
  }
193
256
 
257
+ /**
258
+ * @param {string} type
259
+ * @param {string} [value]
260
+ * @returns {LexerToken | null}
261
+ */
194
262
  match(type, value) {
195
263
  if (!this.check(type, value)) {
196
264
  return null;
@@ -198,6 +266,12 @@ class Parser {
198
266
  return this.advance();
199
267
  }
200
268
 
269
+ /**
270
+ * @param {string} type
271
+ * @param {string | undefined} value
272
+ * @param {string} message
273
+ * @returns {LexerToken}
274
+ */
201
275
  expect(type, value, message) {
202
276
  const token = this.current();
203
277
  if (!this.check(type, value)) {
@@ -206,13 +280,16 @@ class Parser {
206
280
  return this.advance();
207
281
  }
208
282
 
283
+ /** @returns {void} */
209
284
  skipNewlines() {
210
285
  while (this.match("newline")) {
211
286
  // Skip layout-only line breaks between statements and fields.
212
287
  }
213
288
  }
214
289
 
290
+ /** @returns {AstDocument} */
215
291
  parseDocument() {
292
+ /** @type {AstStatement[]} */
216
293
  const statements = [];
217
294
  this.skipNewlines();
218
295
 
@@ -228,11 +305,13 @@ class Parser {
228
305
  };
229
306
  }
230
307
 
308
+ /** @returns {AstStatement} */
231
309
  parseStatement() {
232
310
  const kind = this.expect("word", undefined, "Expected statement kind");
233
311
  const id = this.expect("word", undefined, "Expected statement identifier");
234
312
  const start = kind.start;
235
313
 
314
+ /** @type {LexerToken | null} */
236
315
  let from = null;
237
316
  if (this.match("word", "from")) {
238
317
  from = this.expect("word", undefined, "Expected identifier after 'from'");
@@ -242,6 +321,7 @@ class Parser {
242
321
  this.expect("lbrace", undefined, "Expected '{' to start statement body");
243
322
  this.skipNewlines();
244
323
 
324
+ /** @type {AstField[]} */
245
325
  const fields = [];
246
326
  while (!this.check("rbrace")) {
247
327
  fields.push(this.parseField());
@@ -260,6 +340,7 @@ class Parser {
260
340
  };
261
341
  }
262
342
 
343
+ /** @returns {AstField} */
263
344
  parseField() {
264
345
  const key = this.expect("word", undefined, "Expected field name");
265
346
  const start = key.start;
@@ -287,9 +368,11 @@ class Parser {
287
368
  };
288
369
  }
289
370
 
371
+ /** @returns {AstBlock} */
290
372
  parseBlock() {
291
373
  const open = this.expect("lbrace", undefined, "Expected '{' to start block");
292
374
  this.skipNewlines();
375
+ /** @type {AstBlockEntry[]} */
293
376
  const entries = [];
294
377
 
295
378
  while (!this.check("rbrace")) {
@@ -313,7 +396,12 @@ class Parser {
313
396
  };
314
397
  }
315
398
 
399
+ /**
400
+ * @param {string[]} stopTypes
401
+ * @returns {AstValue[]}
402
+ */
316
403
  parseSequenceUntil(stopTypes) {
404
+ /** @type {AstValue[]} */
317
405
  const items = [];
318
406
 
319
407
  while (!stopTypes.includes(this.current().type) && !this.check("eof")) {
@@ -326,6 +414,7 @@ class Parser {
326
414
  return items;
327
415
  }
328
416
 
417
+ /** @returns {AstValue} */
329
418
  parseAtom() {
330
419
  const token = this.current();
331
420
 
@@ -354,8 +443,10 @@ class Parser {
354
443
  throw createError(this.filePath, `Unexpected token '${token.value || token.type}'`, token);
355
444
  }
356
445
 
446
+ /** @returns {AstList} */
357
447
  parseList() {
358
448
  const open = this.expect("lbracket", undefined, "Expected '[' to start list");
449
+ /** @type {AstValue[]} */
359
450
  const items = [];
360
451
 
361
452
  while (!this.check("rbracket")) {
@@ -373,6 +464,10 @@ class Parser {
373
464
  };
374
465
  }
375
466
 
467
+ /**
468
+ * @param {LexerToken} token
469
+ * @returns {AstScalar}
470
+ */
376
471
  nodeFromToken(token) {
377
472
  return {
378
473
  type: "symbol",
@@ -381,6 +476,11 @@ class Parser {
381
476
  };
382
477
  }
383
478
 
479
+ /**
480
+ * @param {ParserPosition} start
481
+ * @param {ParserPosition} end
482
+ * @returns {AstLocation}
483
+ */
384
484
  loc(start, end) {
385
485
  return {
386
486
  file: this.filePath,
@@ -390,17 +490,30 @@ class Parser {
390
490
  }
391
491
  }
392
492
 
493
+ /**
494
+ * @param {string} source
495
+ * @param {string} [filePath]
496
+ * @returns {AstDocument}
497
+ */
393
498
  export function parseSource(source, filePath = "<memory>") {
394
499
  const tokens = lex(source, filePath);
395
500
  const parser = new Parser(tokens, filePath);
396
501
  return parser.parseDocument();
397
502
  }
398
503
 
504
+ /**
505
+ * @param {string} filePath
506
+ * @returns {AstDocument}
507
+ */
399
508
  export function parseFile(filePath) {
400
509
  const source = fs.readFileSync(filePath, "utf8");
401
510
  return parseSource(source, filePath);
402
511
  }
403
512
 
513
+ /**
514
+ * @param {string} inputPath
515
+ * @returns {string[]}
516
+ */
404
517
  export function collectTopogramFiles(inputPath) {
405
518
  const absolutePath = path.resolve(inputPath);
406
519
  const stat = fs.statSync(absolutePath);
@@ -409,6 +522,7 @@ export function collectTopogramFiles(inputPath) {
409
522
  return absolutePath.endsWith(".tg") ? [absolutePath] : [];
410
523
  }
411
524
 
525
+ /** @type {string[]} */
412
526
  const files = [];
413
527
  for (const entry of fs.readdirSync(absolutePath, { withFileTypes: true })) {
414
528
  const childPath = path.join(absolutePath, entry.name);
@@ -427,6 +541,10 @@ export function collectTopogramFiles(inputPath) {
427
541
  return files.sort();
428
542
  }
429
543
 
544
+ /**
545
+ * @param {string} inputPath
546
+ * @returns {WorkspaceAst}
547
+ */
430
548
  export function parsePath(inputPath) {
431
549
  const files = collectTopogramFiles(inputPath);
432
550
  const docs = parseDocsPath(inputPath);
@@ -0,0 +1 @@
1
+ export function relativeTo(from: string, to: string): string;
@@ -0,0 +1,20 @@
1
+ // @ts-check
2
+
3
+ import path from "node:path";
4
+
5
+ /**
6
+ * @param {string} value
7
+ * @returns {string}
8
+ */
9
+ export function toPosixPath(value) {
10
+ return String(value || "").replaceAll("\\", "/").replaceAll(path.sep, "/");
11
+ }
12
+
13
+ /**
14
+ * @param {string} base
15
+ * @param {string} filePath
16
+ * @returns {string}
17
+ */
18
+ export function relativeTo(base, filePath) {
19
+ return toPosixPath(path.relative(base, filePath));
20
+ }
@@ -0,0 +1,15 @@
1
+ export function defaultOwnershipBoundary(): any;
2
+ export function ownershipBoundaryForMaintainedSurface(...args: any[]): any;
3
+ export function reviewBoundaryForCapability(...args: any[]): any;
4
+ export function reviewBoundaryForEntity(...args: any[]): any;
5
+ export function reviewBoundaryForJourneyDoc(...args: any[]): any;
6
+ export function reviewBoundaryForMaintainedClassification(...args: any[]): any;
7
+ export function reviewBoundaryForProjection(...args: any[]): any;
8
+ export function reviewBoundaryForWorkflowDoc(...args: any[]): any;
9
+ export function reviewBoundaryForAcceptanceCriterion(...args: any[]): any;
10
+ export function reviewBoundaryForBug(...args: any[]): any;
11
+ export function reviewBoundaryForDocument(...args: any[]): any;
12
+ export function reviewBoundaryForDomain(...args: any[]): any;
13
+ export function reviewBoundaryForPitch(...args: any[]): any;
14
+ export function reviewBoundaryForRequirement(...args: any[]): any;
15
+ export function reviewBoundaryForTask(...args: any[]): any;