@topogram/cli 0.3.64 → 0.3.66

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 (278) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +716 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/adoption/reporting.js +1 -1
  5. package/src/agent-brief.js +7 -21
  6. package/src/agent-ops/query-builders/auth.js +375 -0
  7. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  8. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  9. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  10. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  11. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  12. package/src/agent-ops/query-builders/change-risk.js +25 -0
  13. package/src/agent-ops/query-builders/common.js +149 -0
  14. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  15. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  16. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  17. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  18. package/src/agent-ops/query-builders/work-packets.js +417 -0
  19. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  20. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  21. package/src/agent-ops/query-builders/workflow-presets-core.js +677 -0
  22. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  23. package/src/agent-ops/query-builders.d.ts +26 -26
  24. package/src/agent-ops/query-builders.js +42 -5021
  25. package/src/archive/jsonl.js +2 -2
  26. package/src/archive/resolver-bridge.js +1 -1
  27. package/src/archive/unarchive.js +2 -1
  28. package/src/catalog/constants.js +10 -0
  29. package/src/catalog/copy.js +65 -0
  30. package/src/catalog/diagnostics.js +15 -0
  31. package/src/catalog/entries.js +42 -0
  32. package/src/catalog/files.js +67 -0
  33. package/src/catalog/provenance.js +123 -0
  34. package/src/catalog/source.js +150 -0
  35. package/src/catalog/validation.js +252 -0
  36. package/src/catalog.d.ts +2 -0
  37. package/src/catalog.js +18 -746
  38. package/src/cli/command-parsers/project.js +3 -0
  39. package/src/cli/command-parsers/shared.js +1 -1
  40. package/src/cli/commands/agent.js +2 -2
  41. package/src/cli/commands/catalog/check.js +31 -0
  42. package/src/cli/commands/catalog/copy.js +59 -0
  43. package/src/cli/commands/catalog/doctor.js +248 -0
  44. package/src/cli/commands/catalog/help.js +21 -0
  45. package/src/cli/commands/catalog/list.js +52 -0
  46. package/src/cli/commands/catalog/runner.js +92 -0
  47. package/src/cli/commands/catalog/shared.js +17 -0
  48. package/src/cli/commands/catalog/show.js +134 -0
  49. package/src/cli/commands/catalog.js +30 -615
  50. package/src/cli/commands/check.js +3 -3
  51. package/src/cli/commands/doctor.js +2 -9
  52. package/src/cli/commands/generator-policy/package-info.js +162 -0
  53. package/src/cli/commands/generator-policy/payloads.js +372 -0
  54. package/src/cli/commands/generator-policy/printers.js +159 -0
  55. package/src/cli/commands/generator-policy/runner.js +81 -0
  56. package/src/cli/commands/generator-policy/shared.js +39 -0
  57. package/src/cli/commands/generator-policy.js +15 -783
  58. package/src/cli/commands/import/adopt.js +170 -0
  59. package/src/cli/commands/import/check.js +91 -0
  60. package/src/cli/commands/import/diff.js +84 -0
  61. package/src/cli/commands/import/help.js +47 -0
  62. package/src/cli/commands/import/paths.js +269 -0
  63. package/src/cli/commands/import/plan.js +292 -0
  64. package/src/cli/commands/import/refresh.js +471 -0
  65. package/src/cli/commands/import/status-history.js +196 -0
  66. package/src/cli/commands/import/workspace.js +233 -0
  67. package/src/cli/commands/import.js +33 -1732
  68. package/src/cli/commands/migrate.js +153 -0
  69. package/src/cli/commands/package/constants.js +17 -0
  70. package/src/cli/commands/package/doctor.js +240 -0
  71. package/src/cli/commands/package/help.js +27 -0
  72. package/src/cli/commands/package/lockfile.js +135 -0
  73. package/src/cli/commands/package/npm.js +97 -0
  74. package/src/cli/commands/package/reporting.js +35 -0
  75. package/src/cli/commands/package/runner.js +33 -0
  76. package/src/cli/commands/package/shared.js +9 -0
  77. package/src/cli/commands/package/update-cli.js +252 -0
  78. package/src/cli/commands/package/versions.js +35 -0
  79. package/src/cli/commands/package.js +29 -813
  80. package/src/cli/commands/query/change-plan.js +68 -0
  81. package/src/cli/commands/query/definitions.js +202 -0
  82. package/src/cli/commands/query/import-adopt.js +121 -0
  83. package/src/cli/commands/query/runner/artifacts.js +102 -0
  84. package/src/cli/commands/query/runner/boundaries.js +211 -0
  85. package/src/cli/commands/query/runner/change.js +182 -0
  86. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  87. package/src/cli/commands/query/runner/index.js +31 -0
  88. package/src/cli/commands/query/runner/output.js +12 -0
  89. package/src/cli/commands/query/runner/workflow.js +241 -0
  90. package/src/cli/commands/query/runner.js +3 -0
  91. package/src/cli/commands/query/workflow-context.js +5 -0
  92. package/src/cli/commands/query/workspace.js +270 -0
  93. package/src/cli/commands/query.js +9 -1300
  94. package/src/cli/commands/source.js +3 -12
  95. package/src/cli/commands/template/baseline.js +100 -0
  96. package/src/cli/commands/template/check.js +467 -0
  97. package/src/cli/commands/template/constants.js +8 -0
  98. package/src/cli/commands/template/diagnostics.js +26 -0
  99. package/src/cli/commands/template/help.js +28 -0
  100. package/src/cli/commands/template/lifecycle.js +404 -0
  101. package/src/cli/commands/template/list-show.js +287 -0
  102. package/src/cli/commands/template/policy.js +422 -0
  103. package/src/cli/commands/template/shared.js +127 -0
  104. package/src/cli/commands/template/updates.js +352 -0
  105. package/src/cli/commands/template-runner.js +6 -6
  106. package/src/cli/commands/template.js +41 -2143
  107. package/src/cli/commands/trust.js +1 -1
  108. package/src/cli/commands/workflow.js +6 -1
  109. package/src/cli/dispatcher.js +6 -1
  110. package/src/cli/help.js +15 -14
  111. package/src/cli/migration-guidance.js +1 -1
  112. package/src/cli/output-safety.js +2 -1
  113. package/src/cli/path-normalization.js +3 -13
  114. package/src/generator/api/contracts.js +497 -0
  115. package/src/generator/api/metadata.js +221 -0
  116. package/src/generator/api/openapi.js +559 -0
  117. package/src/generator/api/schema.js +124 -0
  118. package/src/generator/api/types.d.ts +98 -0
  119. package/src/generator/api.js +3 -1195
  120. package/src/generator/context/domain-page.js +1 -1
  121. package/src/generator/context/shared/domain-sdlc.js +282 -0
  122. package/src/generator/context/shared/maintained-boundary.js +665 -0
  123. package/src/generator/context/shared/metrics.js +85 -0
  124. package/src/generator/context/shared/primitives.js +64 -0
  125. package/src/generator/context/shared/relationships.js +453 -0
  126. package/src/generator/context/shared/summaries.js +263 -0
  127. package/src/generator/context/shared/types.d.ts +207 -0
  128. package/src/generator/context/shared.d.ts +42 -0
  129. package/src/generator/context/shared.js +80 -1390
  130. package/src/generator/context/slice/core.js +397 -0
  131. package/src/generator/context/slice/sdlc.js +417 -0
  132. package/src/generator/context/slice/ui-packets.js +183 -0
  133. package/src/generator/context/slice.js +2 -859
  134. package/src/generator/context/task-mode.js +2 -2
  135. package/src/generator/registry/index.js +507 -0
  136. package/src/generator/registry.js +18 -504
  137. package/src/generator/runtime/environment/index.js +666 -0
  138. package/src/generator/runtime/environment.js +4 -666
  139. package/src/generator/runtime/runtime-check/index.js +554 -0
  140. package/src/generator/runtime/runtime-check.js +4 -554
  141. package/src/generator/runtime/shared/index.js +572 -0
  142. package/src/generator/runtime/shared.js +19 -570
  143. package/src/generator/sdlc/doc-page.js +1 -1
  144. package/src/generator/shared.d.ts +2 -0
  145. package/src/generator/surfaces/databases/lifecycle-shared.js +1 -1
  146. package/src/generator/surfaces/native/swiftui-templates/README.generated.md +1 -1
  147. package/src/generator/surfaces/shared.d.ts +3 -0
  148. package/src/generator/widget-conformance/behavior-report.js +258 -0
  149. package/src/generator/widget-conformance/checks.js +371 -0
  150. package/src/generator/widget-conformance/projection-context.js +200 -0
  151. package/src/generator/widget-conformance/report.js +166 -0
  152. package/src/generator/widget-conformance/types.d.ts +121 -0
  153. package/src/generator/widget-conformance.js +3 -824
  154. package/src/import/core/context.d.ts +3 -0
  155. package/src/import/core/context.js +5 -7
  156. package/src/import/core/contracts.d.ts +1 -0
  157. package/src/import/core/registry.d.ts +4 -0
  158. package/src/import/core/runner/candidates.js +337 -0
  159. package/src/import/core/runner/options.js +22 -0
  160. package/src/import/core/runner/reports.js +51 -0
  161. package/src/import/core/runner/run.js +79 -0
  162. package/src/import/core/runner/tracks.js +150 -0
  163. package/src/import/core/runner/ui-drafts.js +393 -0
  164. package/src/import/core/runner.js +3 -698
  165. package/src/import/core/shared/api-routes.js +221 -0
  166. package/src/import/core/shared/candidates.js +97 -0
  167. package/src/import/core/shared/files.js +177 -0
  168. package/src/import/core/shared/next-app.js +389 -0
  169. package/src/import/core/shared/types.d.ts +51 -0
  170. package/src/import/core/shared/ui-routes.js +230 -0
  171. package/src/import/core/shared.js +60 -861
  172. package/src/new-project/constants.js +128 -0
  173. package/src/new-project/create.js +90 -0
  174. package/src/new-project/json.js +28 -0
  175. package/src/new-project/metadata.js +96 -0
  176. package/src/new-project/package-spec.js +161 -0
  177. package/src/new-project/project-files.js +351 -0
  178. package/src/new-project/template-policy.js +269 -0
  179. package/src/new-project/template-resolution.js +370 -0
  180. package/src/new-project/template-snapshots.js +442 -0
  181. package/src/new-project/template-updates.js +512 -0
  182. package/src/new-project/types.d.ts +83 -0
  183. package/src/new-project.js +6 -2277
  184. package/src/parser.d.ts +87 -1
  185. package/src/parser.js +118 -0
  186. package/src/policy/review-boundaries.d.ts +15 -0
  187. package/src/project-config/index.js +591 -0
  188. package/src/project-config.js +19 -561
  189. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  190. package/src/resolver/enrich/bug.js +2 -0
  191. package/src/resolver/enrich/pitch.js +2 -0
  192. package/src/resolver/enrich/requirement.js +2 -0
  193. package/src/resolver/enrich/task.js +2 -0
  194. package/src/resolver/index.js +19 -2089
  195. package/src/resolver/normalize.js +384 -1
  196. package/src/resolver/plans.js +168 -0
  197. package/src/resolver/projections-api.js +494 -0
  198. package/src/resolver/projections-db.js +133 -0
  199. package/src/resolver/projections-ui.js +317 -0
  200. package/src/resolver/shapes.js +251 -0
  201. package/src/resolver/shared.js +278 -0
  202. package/src/resolver/widgets.js +132 -0
  203. package/src/sdlc/adopt.js +6 -5
  204. package/src/sdlc/paths.js +3 -5
  205. package/src/sdlc/scaffold.js +2 -1
  206. package/src/template-trust/constants.js +62 -0
  207. package/src/template-trust/content.js +258 -0
  208. package/src/template-trust/diff.js +92 -0
  209. package/src/template-trust/policy.js +61 -0
  210. package/src/template-trust/record.js +90 -0
  211. package/src/template-trust/status.js +182 -0
  212. package/src/template-trust.js +24 -687
  213. package/src/text-helpers.d.ts +1 -0
  214. package/src/topogram-types.d.ts +69 -0
  215. package/src/validator/common.js +488 -0
  216. package/src/validator/data-model.js +237 -0
  217. package/src/validator/docs.js +167 -0
  218. package/src/validator/expressions.js +146 -1
  219. package/src/validator/index.d.ts +23 -0
  220. package/src/validator/index.js +32 -3585
  221. package/src/validator/kinds.d.ts +41 -0
  222. package/src/validator/kinds.js +2 -0
  223. package/src/validator/model-helpers.js +46 -0
  224. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  225. package/src/validator/per-kind/bug.js +6 -0
  226. package/src/validator/per-kind/domain.js +15 -2
  227. package/src/validator/per-kind/pitch.js +7 -0
  228. package/src/validator/per-kind/requirement.js +5 -0
  229. package/src/validator/per-kind/task.js +7 -0
  230. package/src/validator/per-kind/widget.js +14 -0
  231. package/src/validator/projections/api-http-async.js +410 -0
  232. package/src/validator/projections/api-http-authz.js +88 -0
  233. package/src/validator/projections/api-http-core.js +205 -0
  234. package/src/validator/projections/api-http-policies.js +339 -0
  235. package/src/validator/projections/api-http-responses.js +233 -0
  236. package/src/validator/projections/api-http.js +44 -0
  237. package/src/validator/projections/db.js +353 -0
  238. package/src/validator/projections/generator-defaults.js +45 -0
  239. package/src/validator/projections/helpers.js +87 -0
  240. package/src/validator/projections/ui-helpers.js +214 -0
  241. package/src/validator/projections/ui-navigation.js +344 -0
  242. package/src/validator/projections/ui-structure.js +364 -0
  243. package/src/validator/projections/ui-widgets.js +493 -0
  244. package/src/validator/projections/ui.js +46 -0
  245. package/src/validator/registry.js +48 -1
  246. package/src/validator/utils.d.ts +20 -0
  247. package/src/validator/utils.js +115 -12
  248. package/src/widget-behavior.d.ts +1 -0
  249. package/src/workflows/import-app/api/collect.js +221 -0
  250. package/src/workflows/import-app/api/openapi.js +257 -0
  251. package/src/workflows/import-app/api/routes.js +327 -0
  252. package/src/workflows/import-app/api/sources.js +22 -0
  253. package/src/workflows/import-app/api.js +2 -797
  254. package/src/workflows/reconcile/adoption-plan/build.js +212 -0
  255. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  256. package/src/workflows/reconcile/adoption-plan/outputs.js +153 -0
  257. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  258. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  259. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  260. package/src/workflows/reconcile/adoption-plan.js +30 -740
  261. package/src/workflows/reconcile/auth/closures.js +115 -0
  262. package/src/workflows/reconcile/auth/formatters.js +142 -0
  263. package/src/workflows/reconcile/auth/inference.js +330 -0
  264. package/src/workflows/reconcile/auth/roles.js +122 -0
  265. package/src/workflows/reconcile/auth.js +35 -690
  266. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  267. package/src/workflows/reconcile/bundle-core.js +12 -598
  268. package/src/workflows/reconcile/candidate-model.js +18 -2
  269. package/src/workflows/reconcile/canonical-surface.js +1 -1
  270. package/src/workflows/reconcile/impacts/adoption-plan.js +196 -0
  271. package/src/workflows/reconcile/impacts/indexes.js +105 -0
  272. package/src/workflows/reconcile/impacts/patches.js +252 -0
  273. package/src/workflows/reconcile/impacts/reports.js +80 -0
  274. package/src/workflows/reconcile/impacts.js +14 -623
  275. package/src/workflows/reconcile/renderers.js +41 -6
  276. package/src/workflows/shared.js +5 -11
  277. package/src/workspace-docs.d.ts +29 -0
  278. package/src/workspace-paths.js +328 -0
@@ -0,0 +1,35 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {import("./update-cli.js").PackageUpdateCliPayload} payload
5
+ * @returns {void}
6
+ */
7
+ export function printPackageUpdateCli(payload) {
8
+ for (const diagnostic of payload.diagnostics) {
9
+ if (diagnostic.severity === "warning") {
10
+ console.warn(`Warning: ${diagnostic.message}`);
11
+ }
12
+ }
13
+ console.log(`Updated ${payload.packageName} to ^${payload.requestedVersion}.`);
14
+ if (payload.requestedLatest) {
15
+ console.log(`Resolved latest version: ${payload.requestedVersion}`);
16
+ }
17
+ console.log(`Checked package: ${payload.packageName}@${payload.checkedVersion} via ${payload.packageCheckSource}`);
18
+ console.log(`Updated dependency: ${payload.dependencySpec} via ${payload.dependencyUpdatedBy}`);
19
+ if (payload.lockfileSanitized) {
20
+ console.log("Lockfile: refreshed existing @topogram/cli entry from registry metadata");
21
+ }
22
+ if (payload.versionConventionUpdated) {
23
+ console.log(`Version convention: updated ${payload.versionConventionPath}`);
24
+ }
25
+ console.log(`Checks run: ${payload.scriptsRun.join(", ") || "none"}`);
26
+ if (payload.skippedScripts.length > 0) {
27
+ console.log(`Checks skipped: ${payload.skippedScripts.join(", ")}`);
28
+ }
29
+ console.log("");
30
+ console.log("Next steps:");
31
+ console.log(" git diff package.json package-lock.json");
32
+ console.log(` git commit -am "Update Topogram CLI to ${payload.requestedVersion}"`);
33
+ console.log(" git push");
34
+ console.log(" confirm the repo verification workflow passes");
35
+ }
@@ -0,0 +1,33 @@
1
+ // @ts-check
2
+
3
+ import { stableStringify } from "../../../format.js";
4
+ import { printPackageHelp } from "./help.js";
5
+ import { printPackageUpdateCli } from "./reporting.js";
6
+ import { buildPackageUpdateCliPayload } from "./update-cli.js";
7
+
8
+ /**
9
+ * @param {{
10
+ * commandArgs: Record<string, any>,
11
+ * inputPath: string|null|undefined,
12
+ * json: boolean
13
+ * }} context
14
+ * @returns {number}
15
+ */
16
+ export function runPackageCommand(context) {
17
+ const { commandArgs, inputPath, json } = context;
18
+ if (commandArgs.packageCommand !== "update-cli") {
19
+ throw new Error(`Unknown package command '${commandArgs.packageCommand}'`);
20
+ }
21
+ if (!inputPath) {
22
+ console.error("Missing required <version>.");
23
+ printPackageHelp();
24
+ return 1;
25
+ }
26
+ const payload = buildPackageUpdateCliPayload(inputPath);
27
+ if (json) {
28
+ console.log(stableStringify(payload));
29
+ } else {
30
+ printPackageUpdateCli(payload);
31
+ }
32
+ return 0;
33
+ }
@@ -0,0 +1,9 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {unknown} error
5
+ * @returns {string}
6
+ */
7
+ export function messageFromError(error) {
8
+ return error instanceof Error ? error.message : String(error);
9
+ }
@@ -0,0 +1,252 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import { assertSafeNpmSpec } from "../../../npm-safety.js";
7
+ import {
8
+ CLI_PACKAGE_NAME,
9
+ NPMJS_REGISTRY,
10
+ PACKAGE_UPDATE_CLI_INFO_SCRIPTS,
11
+ PACKAGE_UPDATE_CLI_VERIFICATION_SCRIPTS
12
+ } from "./constants.js";
13
+ import { sanitizeTopogramLockForPackageUpdate } from "./lockfile.js";
14
+ import { formatPackageUpdateNpmError, latestTopogramCliVersion, runNpmForPackageUpdate } from "./npm.js";
15
+ import { messageFromError } from "./shared.js";
16
+ import { isPackageVersion } from "./versions.js";
17
+
18
+ /**
19
+ * @typedef {{
20
+ * ok: boolean,
21
+ * packageName: string,
22
+ * requestedVersion: string,
23
+ * requestedLatest: boolean,
24
+ * dependencySpec: string,
25
+ * checkedVersion: string,
26
+ * packageCheckSource: "npm",
27
+ * dependencyUpdatedBy: "npm-install"|"manifest-lockfile"|"version-convention",
28
+ * lockfileSanitized: boolean,
29
+ * versionConventionUpdated: boolean,
30
+ * versionConventionPath: string|null,
31
+ * scriptsRun: string[],
32
+ * skippedScripts: string[],
33
+ * diagnostics: Array<Record<string, any>>,
34
+ * errors: string[]
35
+ * }} PackageUpdateCliPayload
36
+ */
37
+
38
+ /**
39
+ * @param {string} requested
40
+ * @param {{ cwd?: string }} [options]
41
+ * @returns {PackageUpdateCliPayload}
42
+ */
43
+ export function buildPackageUpdateCliPayload(requested, options = {}) {
44
+ const cwd = options.cwd || process.cwd();
45
+ const requestedLatest = requested === "latest" || requested === "--latest";
46
+ /** @type {Array<Record<string, any>>} */
47
+ const diagnostics = [];
48
+ const version = requestedLatest
49
+ ? resolveLatestTopogramCliVersionForPackageUpdate(cwd, diagnostics)
50
+ : requested;
51
+ if (!isPackageVersion(version)) {
52
+ throw new Error("topogram package update-cli requires <version> or --latest.");
53
+ }
54
+ const exactSpec = `${CLI_PACKAGE_NAME}@${version}`;
55
+ const dependencySpec = `${CLI_PACKAGE_NAME}@^${version}`;
56
+ assertSafeNpmSpec(exactSpec);
57
+ assertSafeNpmSpec(dependencySpec);
58
+ const view = runNpmForPackageUpdate(["view", `--registry=${NPMJS_REGISTRY}`, "--", exactSpec, "version"], cwd);
59
+ let checkedVersion = null;
60
+ const packageCheckSource = "npm";
61
+ if (view.status !== 0) {
62
+ throw new Error(formatPackageUpdateNpmError(exactSpec, "inspect", view));
63
+ } else {
64
+ checkedVersion = String(view.stdout || "").trim().replace(/^"|"$/g, "");
65
+ if (checkedVersion !== version) {
66
+ throw new Error(`Expected ${exactSpec}, but npm returned version '${checkedVersion || "(empty)"}'.`);
67
+ }
68
+ }
69
+ const lockfileSanitized = sanitizeTopogramLockForPackageUpdate(cwd, version);
70
+ const dependencyUpdatedBy = "npm-install";
71
+ const install = runNpmForPackageUpdate(["install", "--save-dev", `--registry=${NPMJS_REGISTRY}`, "--", dependencySpec], cwd);
72
+ if (install.status !== 0) {
73
+ throw new Error(formatPackageUpdateNpmError(dependencySpec, "install", install));
74
+ }
75
+ const versionConvention = writeTopogramCliVersionConventionIfPresent(cwd, version);
76
+ const packageJson = readPackageJsonForUpdate(cwd);
77
+ const scripts = packageJson.scripts && typeof packageJson.scripts === "object" ? packageJson.scripts : {};
78
+ const scriptsRun = [];
79
+ const skippedScripts = [];
80
+ const scriptsToRun = packageUpdateCliScriptsToRun(scripts);
81
+ for (const scriptName of PACKAGE_UPDATE_CLI_INFO_SCRIPTS) {
82
+ if (!Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
83
+ skippedScripts.push(scriptName);
84
+ }
85
+ }
86
+ for (const scriptName of PACKAGE_UPDATE_CLI_VERIFICATION_SCRIPTS) {
87
+ if (!Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
88
+ skippedScripts.push(scriptName);
89
+ } else if (!scriptsToRun.includes(scriptName)) {
90
+ const coveringScript = scriptsToRun.find((candidate) =>
91
+ PACKAGE_UPDATE_CLI_VERIFICATION_SCRIPTS.includes(candidate)
92
+ );
93
+ skippedScripts.push(`${scriptName} (covered by ${coveringScript})`);
94
+ }
95
+ }
96
+ for (const scriptName of scriptsToRun) {
97
+ const result = runNpmForPackageUpdate(["run", scriptName], cwd);
98
+ if (result.status !== 0) {
99
+ throw new Error(formatPackageUpdateNpmError(`npm run ${scriptName}`, "check", result));
100
+ }
101
+ scriptsRun.push(scriptName);
102
+ }
103
+ return {
104
+ ok: true,
105
+ packageName: CLI_PACKAGE_NAME,
106
+ requestedVersion: version,
107
+ requestedLatest,
108
+ dependencySpec,
109
+ checkedVersion,
110
+ packageCheckSource,
111
+ dependencyUpdatedBy,
112
+ lockfileSanitized,
113
+ versionConventionUpdated: versionConvention.updated,
114
+ versionConventionPath: versionConvention.path,
115
+ scriptsRun,
116
+ skippedScripts,
117
+ diagnostics,
118
+ errors: []
119
+ };
120
+ }
121
+
122
+ /**
123
+ * @param {Record<string, any>} scripts
124
+ * @returns {string[]}
125
+ */
126
+ function packageUpdateCliScriptsToRun(scripts) {
127
+ const selected = [];
128
+ for (const scriptName of PACKAGE_UPDATE_CLI_INFO_SCRIPTS) {
129
+ if (Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
130
+ selected.push(scriptName);
131
+ }
132
+ }
133
+ const verificationScript = PACKAGE_UPDATE_CLI_VERIFICATION_SCRIPTS.find((scriptName) =>
134
+ Object.prototype.hasOwnProperty.call(scripts, scriptName)
135
+ );
136
+ if (verificationScript) {
137
+ selected.push(verificationScript);
138
+ }
139
+ return selected;
140
+ }
141
+
142
+ /**
143
+ * @param {string} cwd
144
+ * @param {Array<Record<string, any>>} diagnostics
145
+ * @returns {string}
146
+ */
147
+ function resolveLatestTopogramCliVersionForPackageUpdate(cwd, diagnostics) {
148
+ try {
149
+ return latestTopogramCliVersion(cwd);
150
+ } catch (error) {
151
+ throw new Error(messageFromError(error));
152
+ }
153
+ }
154
+
155
+ /**
156
+ * @param {string} cwd
157
+ * @param {string} version
158
+ * @returns {{ updated: boolean, path: string|null }}
159
+ */
160
+ function writeTopogramCliVersionConventionIfPresent(cwd, version) {
161
+ const versionPath = path.join(cwd, "topogram-cli.version");
162
+ if (!fs.existsSync(versionPath)) {
163
+ return { updated: false, path: null };
164
+ }
165
+ fs.writeFileSync(versionPath, `${version}\n`, "utf8");
166
+ return { updated: true, path: versionPath };
167
+ }
168
+
169
+ /**
170
+ * @param {string} cwd
171
+ * @returns {Record<string, any>}
172
+ */
173
+ function readPackageJsonForUpdate(cwd) {
174
+ const packagePath = path.join(cwd, "package.json");
175
+ if (!fs.existsSync(packagePath)) {
176
+ throw new Error("topogram package update-cli must be run from a package directory with package.json.");
177
+ }
178
+ return JSON.parse(fs.readFileSync(packagePath, "utf8"));
179
+ }
180
+
181
+ /**
182
+ * @param {string} cwd
183
+ * @param {string} version
184
+ * @param {string} dependencySpec
185
+ * @returns {{ packageJsonUpdated: boolean, lockfileUpdated: boolean }}
186
+ */
187
+ function updateTopogramCliDependencyFiles(cwd, version, dependencySpec) {
188
+ const packagePath = path.join(cwd, "package.json");
189
+ const packageJson = readPackageJsonForUpdate(cwd);
190
+ const hasDevDependency = packageJson.devDependencies &&
191
+ typeof packageJson.devDependencies === "object" &&
192
+ Object.prototype.hasOwnProperty.call(packageJson.devDependencies, CLI_PACKAGE_NAME);
193
+ const hasDependency = packageJson.dependencies &&
194
+ typeof packageJson.dependencies === "object" &&
195
+ Object.prototype.hasOwnProperty.call(packageJson.dependencies, CLI_PACKAGE_NAME);
196
+ const hasVersionConvention = fs.existsSync(path.join(cwd, "topogram-cli.version"));
197
+ const shouldUpdatePackageJson = hasDevDependency || hasDependency || !hasVersionConvention;
198
+ if (!shouldUpdatePackageJson) {
199
+ return { packageJsonUpdated: false, lockfileUpdated: false };
200
+ }
201
+ if (hasDependency && !hasDevDependency) {
202
+ packageJson.dependencies[CLI_PACKAGE_NAME] = dependencySpec.slice(`${CLI_PACKAGE_NAME}@`.length);
203
+ } else {
204
+ packageJson.devDependencies = packageJson.devDependencies && typeof packageJson.devDependencies === "object"
205
+ ? packageJson.devDependencies
206
+ : {};
207
+ packageJson.devDependencies[CLI_PACKAGE_NAME] = dependencySpec.slice(`${CLI_PACKAGE_NAME}@`.length);
208
+ }
209
+ if (hasDevDependency && packageJson.dependencies && typeof packageJson.dependencies === "object") {
210
+ delete packageJson.dependencies[CLI_PACKAGE_NAME];
211
+ }
212
+ fs.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
213
+
214
+ const lockPath = path.join(cwd, "package-lock.json");
215
+ if (!fs.existsSync(lockPath)) {
216
+ return { packageJsonUpdated: true, lockfileUpdated: false };
217
+ }
218
+ const lock = JSON.parse(fs.readFileSync(lockPath, "utf8"));
219
+ lock.packages = lock.packages && typeof lock.packages === "object" ? lock.packages : {};
220
+ lock.packages[""] = lock.packages[""] && typeof lock.packages[""] === "object" ? lock.packages[""] : {};
221
+ const rootEntry = lock.packages[""];
222
+ const lockHasDependency = rootEntry.dependencies &&
223
+ typeof rootEntry.dependencies === "object" &&
224
+ Object.prototype.hasOwnProperty.call(rootEntry.dependencies, CLI_PACKAGE_NAME);
225
+ if (lockHasDependency && !hasDevDependency) {
226
+ rootEntry.dependencies[CLI_PACKAGE_NAME] = dependencySpec.slice(`${CLI_PACKAGE_NAME}@`.length);
227
+ } else {
228
+ rootEntry.devDependencies = rootEntry.devDependencies && typeof rootEntry.devDependencies === "object"
229
+ ? rootEntry.devDependencies
230
+ : {};
231
+ rootEntry.devDependencies[CLI_PACKAGE_NAME] = dependencySpec.slice(`${CLI_PACKAGE_NAME}@`.length);
232
+ }
233
+ if ((hasDevDependency || !lockHasDependency) && rootEntry.dependencies && typeof rootEntry.dependencies === "object") {
234
+ delete lock.packages[""].dependencies[CLI_PACKAGE_NAME];
235
+ }
236
+ const entryPath = `node_modules/${CLI_PACKAGE_NAME}`;
237
+ const existingEntry = lock.packages[entryPath] && typeof lock.packages[entryPath] === "object"
238
+ ? lock.packages[entryPath]
239
+ : {};
240
+ lock.packages[entryPath] = {
241
+ ...existingEntry,
242
+ version,
243
+ dev: true,
244
+ license: existingEntry.license || "Apache-2.0",
245
+ bin: existingEntry.bin || { topogram: "src/cli.js" },
246
+ engines: existingEntry.engines || { node: ">=20" }
247
+ };
248
+ delete lock.packages[entryPath].resolved;
249
+ delete lock.packages[entryPath].integrity;
250
+ fs.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`, "utf8");
251
+ return { packageJsonUpdated: true, lockfileUpdated: true };
252
+ }
@@ -0,0 +1,35 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {string} left
5
+ * @param {string} right
6
+ * @returns {number}
7
+ */
8
+ export function compareSemver(left, right) {
9
+ const leftParts = left.split(/[.-]/).slice(0, 3).map((part) => Number.parseInt(part, 10) || 0);
10
+ const rightParts = right.split(/[.-]/).slice(0, 3).map((part) => Number.parseInt(part, 10) || 0);
11
+ for (let index = 0; index < 3; index += 1) {
12
+ if (leftParts[index] > rightParts[index]) return 1;
13
+ if (leftParts[index] < rightParts[index]) return -1;
14
+ }
15
+ return 0;
16
+ }
17
+
18
+ /**
19
+ * @param {string|null} value
20
+ * @returns {string|null}
21
+ */
22
+ export function normalizeRegistryUrl(value) {
23
+ if (!value) {
24
+ return null;
25
+ }
26
+ return value.trim().replace(/\/+$/, "");
27
+ }
28
+
29
+ /**
30
+ * @param {string} value
31
+ * @returns {boolean}
32
+ */
33
+ export function isPackageVersion(value) {
34
+ return /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value);
35
+ }