@askrjs/cli 0.0.2 → 0.0.4

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 (310) hide show
  1. package/README.md +46 -7
  2. package/dist/add.d.ts +16 -0
  3. package/dist/add.js +558 -1
  4. package/dist/cli.d.ts +5 -0
  5. package/dist/cli.js +43 -16
  6. package/dist/create.d.ts +5 -0
  7. package/dist/create.js +104 -26
  8. package/dist/directory-swap-DWoHtx7C.js +35 -0
  9. package/dist/discovery-Difb7Y4G.js +323 -0
  10. package/dist/generate.d.ts +5 -0
  11. package/dist/generate.js +461 -0
  12. package/dist/is-direct-execution-Cdlr-ZUl.js +0 -2
  13. package/dist/openapi.d.ts +25 -0
  14. package/dist/openapi.js +49 -16
  15. package/dist/planner-VAj7qlxr.js +285 -0
  16. package/dist/range-YUs9eimn.js +125 -0
  17. package/dist/registry-CyrRHRG5.js +209 -0
  18. package/dist/skills/askr-dashboard-charts/SKILL.md +61 -44
  19. package/dist/skills/askr-dashboard-charts/agents/openai.yaml +2 -2
  20. package/dist/skills/askr-ssr-ssg/SKILL.md +3 -1
  21. package/dist/{skills-Bh0mEhIx.js → skills-B7CbWur9.js} +89 -26
  22. package/dist/skills.d.ts +18 -0
  23. package/dist/skills.js +1 -1
  24. package/dist/specification-DXnDOC-0.js +49 -0
  25. package/dist/ssg-config.d.ts +41 -0
  26. package/dist/ssg-config.js +1 -0
  27. package/dist/ssg.d.ts +61 -0
  28. package/dist/ssg.js +360 -24
  29. package/dist/templates/full-stack/AGENTS.md +0 -1
  30. package/dist/templates/full-stack/README.md +0 -1
  31. package/dist/templates/full-stack/index.html +0 -1
  32. package/dist/templates/full-stack/package.json +5 -3
  33. package/dist/templates/full-stack/server.ts +5 -9
  34. package/dist/templates/full-stack/src/action-authorizations.ts +2 -2
  35. package/dist/templates/full-stack/src/actions/create-message.ts +5 -5
  36. package/dist/templates/full-stack/src/i18n.ts +4 -4
  37. package/dist/templates/full-stack/src/main.tsx +4 -5
  38. package/dist/templates/full-stack/src/pages/home.tsx +5 -5
  39. package/dist/templates/full-stack/src/pages/layout.tsx +15 -5
  40. package/dist/templates/full-stack/src/pages/not-found.tsx +5 -2
  41. package/dist/templates/full-stack/src/routes.tsx +11 -12
  42. package/dist/templates/full-stack/src/schemas.ts +1 -2
  43. package/dist/templates/full-stack/src/server/action-registry.ts +5 -10
  44. package/dist/templates/full-stack/src/server/actions/create-message.ts +4 -4
  45. package/dist/templates/full-stack/src/server/app.ts +67 -57
  46. package/dist/templates/full-stack/src/server/dependencies.ts +10 -10
  47. package/dist/templates/full-stack/src/server/entry-server.ts +3 -3
  48. package/dist/templates/full-stack/src/telemetry.ts +1 -2
  49. package/dist/templates/full-stack/tests/actions/create-message.test.ts +7 -8
  50. package/dist/templates/full-stack/tsconfig.json +1 -2
  51. package/dist/templates/full-stack/vite.config.ts +5 -6
  52. package/dist/templates/spa/AGENTS.md +1 -1
  53. package/dist/templates/spa/package.json +3 -4
  54. package/dist/templates/spa/src/adapters/operations-client.ts +7 -2
  55. package/dist/templates/spa/src/pages/app/_routes.tsx +2 -0
  56. package/dist/templates/spa/src/pages/app/admin-home.tsx +21 -3
  57. package/dist/templates/spa/src/pages/public/_routes.tsx +2 -0
  58. package/dist/templates/spa/src/styles.css +1 -1
  59. package/dist/templates/spa/tsconfig.json +2 -1
  60. package/dist/templates/spa/vitest.config.ts +0 -4
  61. package/dist/templates/ssg/README.md +1 -1
  62. package/dist/templates/ssg/package.json +1 -1
  63. package/dist/templates/ssg/ssg.config.ts +7 -0
  64. package/dist/templates/ssg/tests/ssg-config.test.ts +5 -3
  65. package/dist/templates/ssg/tsconfig.json +2 -1
  66. package/dist/templates/ssg/vitest.config.ts +0 -4
  67. package/dist/templates/ssr/package.json +2 -2
  68. package/dist/templates/ssr/server.ts +4 -10
  69. package/dist/templates/ssr/src/entry-server.tsx +6 -4
  70. package/dist/templates/startkit/package.json +2 -2
  71. package/dist/templates/startkit/src/lib/mock-data.ts +17 -39
  72. package/dist/templates/startkit/tsconfig.json +2 -1
  73. package/dist/update.d.ts +41 -0
  74. package/dist/update.js +282 -2
  75. package/dist/writer-D8qe_7ud.js +226 -0
  76. package/package.json +23 -22
  77. package/dist/add-DqhqRzBQ.js +0 -555
  78. package/dist/add-DqhqRzBQ.js.map +0 -1
  79. package/dist/cli.js.map +0 -1
  80. package/dist/create.js.map +0 -1
  81. package/dist/is-direct-execution-Cdlr-ZUl.js.map +0 -1
  82. package/dist/openapi.js.map +0 -1
  83. package/dist/skills-Bh0mEhIx.js.map +0 -1
  84. package/dist/ssg.js.map +0 -1
  85. package/dist/templates/full-stack/src/vite-server.d.ts +0 -6
  86. package/dist/templates/spa/src/styles.d.ts +0 -1
  87. package/dist/templates/ssg/src/vite-env.d.ts +0 -5
  88. package/dist/templates/ssr/src/vite-server.d.ts +0 -7
  89. package/dist/templates/startkit/src/vite-env.d.ts +0 -5
  90. package/dist/update-DyW1na5V.js +0 -1140
  91. package/dist/update-DyW1na5V.js.map +0 -1
  92. package/skills/askr-accessibility/SKILL.md +0 -68
  93. package/skills/askr-accessibility/agents/openai.yaml +0 -4
  94. package/skills/askr-agent-execution/SKILL.md +0 -85
  95. package/skills/askr-agent-execution/agents/openai.yaml +0 -4
  96. package/skills/askr-agent-workflows/SKILL.md +0 -57
  97. package/skills/askr-agent-workflows/agents/openai.yaml +0 -4
  98. package/skills/askr-api-integration/SKILL.md +0 -79
  99. package/skills/askr-api-integration/agents/openai.yaml +0 -4
  100. package/skills/askr-app-builder/SKILL.md +0 -99
  101. package/skills/askr-app-builder/agents/openai.yaml +0 -4
  102. package/skills/askr-auth-access/SKILL.md +0 -74
  103. package/skills/askr-auth-access/agents/openai.yaml +0 -4
  104. package/skills/askr-cli-vite/SKILL.md +0 -76
  105. package/skills/askr-cli-vite/agents/openai.yaml +0 -4
  106. package/skills/askr-dashboard-charts/SKILL.md +0 -82
  107. package/skills/askr-dashboard-charts/agents/openai.yaml +0 -4
  108. package/skills/askr-design-system/SKILL.md +0 -86
  109. package/skills/askr-design-system/agents/openai.yaml +0 -4
  110. package/skills/askr-env-config/SKILL.md +0 -74
  111. package/skills/askr-env-config/agents/openai.yaml +0 -4
  112. package/skills/askr-error-loading-empty/SKILL.md +0 -89
  113. package/skills/askr-error-loading-empty/agents/openai.yaml +0 -4
  114. package/skills/askr-file-upload-artifacts/SKILL.md +0 -77
  115. package/skills/askr-file-upload-artifacts/agents/openai.yaml +0 -4
  116. package/skills/askr-forms-tables-crud/SKILL.md +0 -98
  117. package/skills/askr-forms-tables-crud/agents/openai.yaml +0 -4
  118. package/skills/askr-mental-model/SKILL.md +0 -109
  119. package/skills/askr-mental-model/agents/openai.yaml +0 -4
  120. package/skills/askr-migration-react/SKILL.md +0 -81
  121. package/skills/askr-migration-react/agents/openai.yaml +0 -4
  122. package/skills/askr-observability-debugging/SKILL.md +0 -83
  123. package/skills/askr-observability-debugging/agents/openai.yaml +0 -4
  124. package/skills/askr-project-structure/SKILL.md +0 -79
  125. package/skills/askr-project-structure/agents/openai.yaml +0 -4
  126. package/skills/askr-query-mutation/SKILL.md +0 -115
  127. package/skills/askr-query-mutation/agents/openai.yaml +0 -4
  128. package/skills/askr-realtime-streaming/SKILL.md +0 -76
  129. package/skills/askr-realtime-streaming/agents/openai.yaml +0 -4
  130. package/skills/askr-resources-data/SKILL.md +0 -100
  131. package/skills/askr-resources-data/agents/openai.yaml +0 -4
  132. package/skills/askr-routing-layouts/SKILL.md +0 -107
  133. package/skills/askr-routing-layouts/agents/openai.yaml +0 -4
  134. package/skills/askr-runtime-reactivity/SKILL.md +0 -92
  135. package/skills/askr-runtime-reactivity/agents/openai.yaml +0 -4
  136. package/skills/askr-ssr-ssg/SKILL.md +0 -76
  137. package/skills/askr-ssr-ssg/agents/openai.yaml +0 -4
  138. package/skills/askr-testing-determinism/SKILL.md +0 -75
  139. package/skills/askr-testing-determinism/agents/openai.yaml +0 -4
  140. package/skills/askr-theming/SKILL.md +0 -86
  141. package/skills/askr-theming/agents/openai.yaml +0 -4
  142. package/skills/askr-ui-composition/SKILL.md +0 -92
  143. package/skills/askr-ui-composition/agents/openai.yaml +0 -4
  144. package/templates/full-stack/AGENTS.md +0 -12
  145. package/templates/full-stack/README.md +0 -18
  146. package/templates/full-stack/gitignore.template +0 -4
  147. package/templates/full-stack/index.html +0 -14
  148. package/templates/full-stack/package.json +0 -37
  149. package/templates/full-stack/server.ts +0 -13
  150. package/templates/full-stack/src/action-authorizations.ts +0 -10
  151. package/templates/full-stack/src/actions/create-message.ts +0 -10
  152. package/templates/full-stack/src/i18n.ts +0 -8
  153. package/templates/full-stack/src/main.tsx +0 -12
  154. package/templates/full-stack/src/pages/home.tsx +0 -25
  155. package/templates/full-stack/src/pages/layout.tsx +0 -33
  156. package/templates/full-stack/src/pages/not-found.tsx +0 -4
  157. package/templates/full-stack/src/routes.tsx +0 -20
  158. package/templates/full-stack/src/schemas.ts +0 -11
  159. package/templates/full-stack/src/server/action-registry.ts +0 -12
  160. package/templates/full-stack/src/server/actions/create-message.ts +0 -14
  161. package/templates/full-stack/src/server/app.ts +0 -66
  162. package/templates/full-stack/src/server/dependencies.ts +0 -55
  163. package/templates/full-stack/src/server/entry-server.ts +0 -8
  164. package/templates/full-stack/src/telemetry.ts +0 -4
  165. package/templates/full-stack/src/vite-server.d.ts +0 -6
  166. package/templates/full-stack/tests/actions/create-message.test.ts +0 -13
  167. package/templates/full-stack/tsconfig.json +0 -16
  168. package/templates/full-stack/vite.config.ts +0 -11
  169. package/templates/spa/AGENTS.md +0 -60
  170. package/templates/spa/README.md +0 -96
  171. package/templates/spa/gitignore.template +0 -16
  172. package/templates/spa/index.html +0 -13
  173. package/templates/spa/package.json +0 -35
  174. package/templates/spa/src/adapters/operations-client.ts +0 -90
  175. package/templates/spa/src/components/shared/metric-card.tsx +0 -27
  176. package/templates/spa/src/components/shared/status-badge.tsx +0 -24
  177. package/templates/spa/src/features/operations/operations.query.ts +0 -9
  178. package/templates/spa/src/main.tsx +0 -10
  179. package/templates/spa/src/pages/_layout.tsx +0 -9
  180. package/templates/spa/src/pages/_routes.tsx +0 -27
  181. package/templates/spa/src/pages/app/_layout.tsx +0 -94
  182. package/templates/spa/src/pages/app/_routes.tsx +0 -10
  183. package/templates/spa/src/pages/app/admin-home.tsx +0 -152
  184. package/templates/spa/src/pages/app/agent-runs.tsx +0 -93
  185. package/templates/spa/src/pages/app/settings.tsx +0 -91
  186. package/templates/spa/src/pages/auth/_layout.tsx +0 -38
  187. package/templates/spa/src/pages/auth/_routes.tsx +0 -6
  188. package/templates/spa/src/pages/auth/login.tsx +0 -63
  189. package/templates/spa/src/pages/not-found.tsx +0 -22
  190. package/templates/spa/src/pages/public/_layout.tsx +0 -47
  191. package/templates/spa/src/pages/public/_routes.tsx +0 -6
  192. package/templates/spa/src/pages/public/home.tsx +0 -143
  193. package/templates/spa/src/shared/format.ts +0 -12
  194. package/templates/spa/src/shared/navigation.ts +0 -15
  195. package/templates/spa/src/styles/components.css +0 -49
  196. package/templates/spa/src/styles/layout.css +0 -192
  197. package/templates/spa/src/styles/reset.css +0 -44
  198. package/templates/spa/src/styles/theme.css +0 -57
  199. package/templates/spa/src/styles/tokens.css +0 -20
  200. package/templates/spa/src/styles.css +0 -7
  201. package/templates/spa/src/styles.d.ts +0 -1
  202. package/templates/spa/tests/app.test.tsx +0 -37
  203. package/templates/spa/tests/components/shared.test.tsx +0 -12
  204. package/templates/spa/tests/resources.test.ts +0 -22
  205. package/templates/spa/tsconfig.json +0 -20
  206. package/templates/spa/tsconfig.node.json +0 -10
  207. package/templates/spa/vite.config.ts +0 -24
  208. package/templates/spa/vitest.config.ts +0 -17
  209. package/templates/ssg/AGENTS.md +0 -55
  210. package/templates/ssg/README.md +0 -39
  211. package/templates/ssg/gitignore.template +0 -17
  212. package/templates/ssg/index.html +0 -13
  213. package/templates/ssg/package.json +0 -35
  214. package/templates/ssg/src/app.tsx +0 -14
  215. package/templates/ssg/src/components/badge.tsx +0 -3
  216. package/templates/ssg/src/components/counter.tsx +0 -30
  217. package/templates/ssg/src/components/site-shell.tsx +0 -111
  218. package/templates/ssg/src/jsx.d.ts +0 -23
  219. package/templates/ssg/src/main.tsx +0 -8
  220. package/templates/ssg/src/pages/about.tsx +0 -82
  221. package/templates/ssg/src/pages/content.tsx +0 -63
  222. package/templates/ssg/src/pages/example.tsx +0 -97
  223. package/templates/ssg/src/pages/home.tsx +0 -51
  224. package/templates/ssg/src/resources/user.ts +0 -15
  225. package/templates/ssg/src/routes.tsx +0 -15
  226. package/templates/ssg/src/styles.css +0 -89
  227. package/templates/ssg/src/vite-env.d.ts +0 -5
  228. package/templates/ssg/ssg.config.ts +0 -34
  229. package/templates/ssg/tests/app.test.tsx +0 -19
  230. package/templates/ssg/tests/components/counter.test.tsx +0 -18
  231. package/templates/ssg/tests/resources.test.ts +0 -11
  232. package/templates/ssg/tests/ssg-config.test.ts +0 -11
  233. package/templates/ssg/tsconfig.json +0 -20
  234. package/templates/ssg/tsconfig.node.json +0 -10
  235. package/templates/ssg/vite.config.ts +0 -24
  236. package/templates/ssg/vitest.config.ts +0 -17
  237. package/templates/ssr/AGENTS.md +0 -28
  238. package/templates/ssr/README.md +0 -38
  239. package/templates/ssr/gitignore.template +0 -16
  240. package/templates/ssr/index.html +0 -13
  241. package/templates/ssr/package.json +0 -34
  242. package/templates/ssr/server.ts +0 -16
  243. package/templates/ssr/src/app.tsx +0 -21
  244. package/templates/ssr/src/components/counter.tsx +0 -26
  245. package/templates/ssr/src/entry-server.tsx +0 -10
  246. package/templates/ssr/src/main.tsx +0 -11
  247. package/templates/ssr/src/pages/about.tsx +0 -75
  248. package/templates/ssr/src/pages/example.tsx +0 -113
  249. package/templates/ssr/src/pages/home.tsx +0 -56
  250. package/templates/ssr/src/resources/user.ts +0 -15
  251. package/templates/ssr/src/routes.tsx +0 -13
  252. package/templates/ssr/src/styles.css +0 -148
  253. package/templates/ssr/src/vite-server.d.ts +0 -7
  254. package/templates/ssr/tests/app.test.tsx +0 -24
  255. package/templates/ssr/tests/components/counter.test.tsx +0 -13
  256. package/templates/ssr/tests/resources.test.ts +0 -11
  257. package/templates/ssr/tsconfig.json +0 -22
  258. package/templates/ssr/tsconfig.node.json +0 -10
  259. package/templates/ssr/tsconfig.server.json +0 -15
  260. package/templates/ssr/vite.config.ts +0 -25
  261. package/templates/ssr/vitest.config.ts +0 -13
  262. package/templates/startkit/AGENTS.md +0 -77
  263. package/templates/startkit/README.md +0 -192
  264. package/templates/startkit/gitignore.template +0 -16
  265. package/templates/startkit/index.html +0 -13
  266. package/templates/startkit/package.json +0 -35
  267. package/templates/startkit/src/components/app-header.tsx +0 -93
  268. package/templates/startkit/src/components/app-sidebar.tsx +0 -95
  269. package/templates/startkit/src/components/data-table.tsx +0 -80
  270. package/templates/startkit/src/components/empty-state.tsx +0 -13
  271. package/templates/startkit/src/components/page-header.tsx +0 -23
  272. package/templates/startkit/src/components/stat-card.tsx +0 -24
  273. package/templates/startkit/src/features/accounts/account-filters.tsx +0 -61
  274. package/templates/startkit/src/features/accounts/account-table.tsx +0 -79
  275. package/templates/startkit/src/lib/format.ts +0 -31
  276. package/templates/startkit/src/lib/mock-data.ts +0 -441
  277. package/templates/startkit/src/lib/routes.ts +0 -116
  278. package/templates/startkit/src/main.tsx +0 -12
  279. package/templates/startkit/src/pages/_layout.tsx +0 -56
  280. package/templates/startkit/src/pages/auth/_layout.tsx +0 -7
  281. package/templates/startkit/src/pages/auth/login.tsx +0 -129
  282. package/templates/startkit/src/pages/home.tsx +0 -83
  283. package/templates/startkit/src/pages/not-found.tsx +0 -24
  284. package/templates/startkit/src/pages/workspace/_layout.tsx +0 -17
  285. package/templates/startkit/src/pages/workspace/accounts/index.tsx +0 -217
  286. package/templates/startkit/src/pages/workspace/dashboard.tsx +0 -118
  287. package/templates/startkit/src/pages/workspace/settings.tsx +0 -218
  288. package/templates/startkit/src/router.tsx +0 -7
  289. package/templates/startkit/src/routes/auth-config.ts +0 -38
  290. package/templates/startkit/src/routes/auth.ts +0 -8
  291. package/templates/startkit/src/routes/index.ts +0 -28
  292. package/templates/startkit/src/routes/public.ts +0 -8
  293. package/templates/startkit/src/routes/workspace/accounts.ts +0 -8
  294. package/templates/startkit/src/routes/workspace/index.ts +0 -14
  295. package/templates/startkit/src/styles/components.css +0 -396
  296. package/templates/startkit/src/styles/layout.css +0 -192
  297. package/templates/startkit/src/styles/reset.css +0 -38
  298. package/templates/startkit/src/styles/theme.css +0 -76
  299. package/templates/startkit/src/styles/tokens.css +0 -67
  300. package/templates/startkit/src/styles.css +0 -7
  301. package/templates/startkit/src/toast.ts +0 -55
  302. package/templates/startkit/src/utils/join-classes.ts +0 -4
  303. package/templates/startkit/src/vite-env.d.ts +0 -5
  304. package/templates/startkit/tests/app.test.tsx +0 -32
  305. package/templates/startkit/tests/preferences.test.ts +0 -43
  306. package/templates/startkit/tests/resources.test.ts +0 -82
  307. package/templates/startkit/tsconfig.json +0 -20
  308. package/templates/startkit/tsconfig.node.json +0 -10
  309. package/templates/startkit/vite.config.ts +0 -32
  310. package/templates/startkit/vitest.config.ts +0 -13
@@ -0,0 +1,285 @@
1
+ import { n as isBreakingChange, r as rewriteRange, t as analyzeRange } from "./range-YUs9eimn.js";
2
+ import { t as parseDependencySpecification } from "./specification-DXnDOC-0.js";
3
+ import semver from "semver";
4
+ //#region src/update/planner.ts
5
+ const STATUS_PRIORITY = {
6
+ current: 0,
7
+ local: 1,
8
+ safe: 2,
9
+ breaking: 3,
10
+ manual: 4,
11
+ error: 5
12
+ };
13
+ function publishedVersions(packument) {
14
+ return Object.keys(packument.versions ?? {}).filter((version) => semver.valid(version) !== null).sort(semver.compare);
15
+ }
16
+ function selectedTarget(packument, tag) {
17
+ const value = packument["dist-tags"]?.[tag];
18
+ return typeof value === "string" && semver.valid(value) ? value : null;
19
+ }
20
+ function plannedOccurrence(occurrence, packument, failure, selectedTag, force) {
21
+ const base = {
22
+ workspace: occurrence.workspace,
23
+ manifestPath: occurrence.manifestPath,
24
+ relativeManifestPath: occurrence.relativeManifestPath,
25
+ section: occurrence.section,
26
+ currentSpecification: occurrence.currentSpecification,
27
+ proposedSpecification: null,
28
+ allowedVersion: null
29
+ };
30
+ if (occurrence.kind === "local") return {
31
+ targetVersion: null,
32
+ occurrence: {
33
+ ...base,
34
+ status: "local",
35
+ reason: occurrence.reason
36
+ }
37
+ };
38
+ if (occurrence.kind === "manual") return {
39
+ targetVersion: null,
40
+ occurrence: {
41
+ ...base,
42
+ status: "manual",
43
+ reason: occurrence.reason
44
+ }
45
+ };
46
+ if (failure) return {
47
+ targetVersion: null,
48
+ occurrence: {
49
+ ...base,
50
+ status: "error",
51
+ reason: failure
52
+ }
53
+ };
54
+ if (occurrence.kind === "current") return {
55
+ targetVersion: packument ? selectedTarget(packument, selectedTag) : null,
56
+ occurrence: {
57
+ ...base,
58
+ status: "current",
59
+ reason: occurrence.reason
60
+ }
61
+ };
62
+ if (!packument) return {
63
+ targetVersion: null,
64
+ occurrence: {
65
+ ...base,
66
+ status: "error",
67
+ reason: "package metadata is unavailable"
68
+ }
69
+ };
70
+ const targetVersion = selectedTarget(packument, selectedTag);
71
+ if (!targetVersion) return {
72
+ targetVersion: null,
73
+ occurrence: {
74
+ ...base,
75
+ status: "error",
76
+ reason: `dist-tag '${selectedTag}' is not published`
77
+ }
78
+ };
79
+ const versions = publishedVersions(packument);
80
+ if (!versions.includes(targetVersion)) return {
81
+ targetVersion: null,
82
+ occurrence: {
83
+ ...base,
84
+ status: "error",
85
+ reason: `dist-tag '${selectedTag}' does not identify a published version`
86
+ }
87
+ };
88
+ const allowedVersion = semver.maxSatisfying(versions, occurrence.currentSpecification);
89
+ if (!allowedVersion) return {
90
+ targetVersion,
91
+ occurrence: {
92
+ ...base,
93
+ status: "manual",
94
+ reason: "no published version satisfies the current specification"
95
+ }
96
+ };
97
+ if (semver.satisfies(targetVersion, occurrence.currentSpecification) || !semver.gt(targetVersion, allowedVersion)) return {
98
+ targetVersion,
99
+ occurrence: {
100
+ ...base,
101
+ allowedVersion,
102
+ status: "current",
103
+ reason: "selected target is already covered by the current specification"
104
+ }
105
+ };
106
+ const analysis = analyzeRange(occurrence.currentSpecification);
107
+ if (!analysis.shape) return {
108
+ targetVersion,
109
+ occurrence: {
110
+ ...base,
111
+ allowedVersion,
112
+ status: "manual",
113
+ reason: analysis.reason
114
+ }
115
+ };
116
+ const breaking = isBreakingChange(allowedVersion, targetVersion);
117
+ const eligible = !breaking || force;
118
+ return {
119
+ targetVersion,
120
+ occurrence: {
121
+ ...base,
122
+ allowedVersion,
123
+ proposedSpecification: eligible ? rewriteRange(analysis.shape, targetVersion, breaking) : null,
124
+ status: breaking ? "breaking" : "safe",
125
+ reason: breaking ? eligible ? "latest version is eligible for askr upgrade" : "breaking update is available via askr upgrade" : "compatible update is available"
126
+ }
127
+ };
128
+ }
129
+ function occurrenceKey(occurrence, packageName) {
130
+ return [
131
+ occurrence.manifestPath,
132
+ occurrence.section,
133
+ packageName ?? occurrence.package,
134
+ occurrence.currentSpecification
135
+ ].join("\0");
136
+ }
137
+ function resolveSpecificationVersion(specification, packument) {
138
+ const versions = publishedVersions(packument);
139
+ const parsed = parseDependencySpecification(specification);
140
+ if (parsed.type === "tag") {
141
+ const tagged = packument["dist-tags"]?.[parsed.rawSpec];
142
+ return typeof tagged === "string" && semver.valid(tagged) ? tagged : null;
143
+ }
144
+ if (parsed.type === "version") return semver.valid(parsed.rawSpec);
145
+ if (parsed.type === "range") return semver.maxSatisfying(versions, parsed.rawSpec);
146
+ return null;
147
+ }
148
+ function versionMetadata(packument, version) {
149
+ const metadata = packument.versions?.[version];
150
+ return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : null;
151
+ }
152
+ function applyPeerCompatibilityGuard(decisions, contextOccurrences, packuments) {
153
+ const plannedByKey = /* @__PURE__ */ new Map();
154
+ for (const decision of decisions) for (const occurrence of decision.occurrences) plannedByKey.set(occurrenceKey(occurrence, decision.package), occurrence);
155
+ const contextByWorkspace = /* @__PURE__ */ new Map();
156
+ for (const occurrence of contextOccurrences) {
157
+ const entries = contextByWorkspace.get(occurrence.workspace) ?? [];
158
+ entries.push(occurrence);
159
+ contextByWorkspace.set(occurrence.workspace, entries);
160
+ }
161
+ for (const [workspace, context] of contextByWorkspace) {
162
+ const states = context.flatMap((dependency) => {
163
+ if (!dependency.registryManaged) return [];
164
+ const packument = packuments.get(dependency.package);
165
+ if (!packument) return [];
166
+ const planned = plannedByKey.get(occurrenceKey(dependency));
167
+ const currentVersion = resolveSpecificationVersion(dependency.currentSpecification, packument);
168
+ const futureVersion = resolveSpecificationVersion(planned?.proposedSpecification ?? dependency.currentSpecification, packument);
169
+ return currentVersion && futureVersion ? [{
170
+ dependency,
171
+ packument,
172
+ planned,
173
+ currentVersion,
174
+ futureVersion,
175
+ changed: Boolean(planned?.proposedSpecification)
176
+ }] : [];
177
+ });
178
+ const blockers = /* @__PURE__ */ new Map();
179
+ for (const provider of states) {
180
+ const currentPeers = versionMetadata(provider.packument, provider.currentVersion)?.peerDependencies ?? {};
181
+ const futurePeers = versionMetadata(provider.packument, provider.futureVersion)?.peerDependencies ?? {};
182
+ const peerNames = /* @__PURE__ */ new Set([...Object.keys(currentPeers), ...Object.keys(futurePeers)]);
183
+ for (const peerName of peerNames) {
184
+ const currentRequirement = currentPeers[peerName];
185
+ const futureRequirement = futurePeers[peerName];
186
+ if (futureRequirement !== void 0 && typeof futureRequirement !== "string") continue;
187
+ for (const peer of states.filter((state) => state.dependency.package === peerName)) {
188
+ const currentAccepted = typeof currentRequirement !== "string" || semver.satisfies(peer.currentVersion, currentRequirement);
189
+ const futureAccepted = typeof futureRequirement !== "string" || semver.satisfies(peer.futureVersion, futureRequirement);
190
+ if (!currentAccepted || futureAccepted) continue;
191
+ const reason = `${provider.dependency.package}@${provider.futureVersion} requires ${peerName}@${futureRequirement}`;
192
+ if (provider.changed && provider.planned) blockers.set(provider.planned, reason);
193
+ if (peer.changed && peer.planned) blockers.set(peer.planned, reason);
194
+ }
195
+ }
196
+ }
197
+ for (const [planned, reason] of blockers) {
198
+ planned.status = "manual";
199
+ planned.proposedSpecification = null;
200
+ planned.reason = reason;
201
+ }
202
+ }
203
+ }
204
+ function aggregateStatus(occurrences) {
205
+ return occurrences.reduce((status, occurrence) => STATUS_PRIORITY[occurrence.status] > STATUS_PRIORITY[status] ? occurrence.status : status, "current");
206
+ }
207
+ function summarize(decisions) {
208
+ const summary = {
209
+ packages: decisions.length,
210
+ occurrences: 0,
211
+ changedOccurrences: 0,
212
+ current: 0,
213
+ safe: 0,
214
+ breaking: 0,
215
+ local: 0,
216
+ manual: 0,
217
+ error: 0
218
+ };
219
+ for (const decision of decisions) {
220
+ decision.status = aggregateStatus(decision.occurrences);
221
+ decision.reason = decision.occurrences.find((entry) => entry.status === decision.status)?.reason ?? "";
222
+ summary[decision.status] += 1;
223
+ summary.occurrences += decision.occurrences.length;
224
+ summary.changedOccurrences += decision.occurrences.filter((entry) => entry.proposedSpecification).length;
225
+ }
226
+ return summary;
227
+ }
228
+ function planUpdates(options) {
229
+ const failures = options.failures ?? /* @__PURE__ */ new Map();
230
+ const tags = options.tags ?? {};
231
+ const grouped = /* @__PURE__ */ new Map();
232
+ for (const occurrence of options.occurrences) {
233
+ const entries = grouped.get(occurrence.package) ?? [];
234
+ entries.push(occurrence);
235
+ grouped.set(occurrence.package, entries);
236
+ }
237
+ const decisions = [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([packageName, occurrences]) => {
238
+ const selectedTag = options.cliTag ?? tags[packageName] ?? "latest";
239
+ const planned = occurrences.map((occurrence) => plannedOccurrence(occurrence, options.packuments.get(packageName), failures.get(packageName), selectedTag, options.force ?? false));
240
+ const targetVersion = planned.find((entry) => entry.targetVersion)?.targetVersion ?? null;
241
+ const plannedOccurrences = planned.map((entry) => entry.occurrence);
242
+ const status = aggregateStatus(plannedOccurrences);
243
+ return {
244
+ package: packageName,
245
+ selectedTag,
246
+ targetVersion,
247
+ status,
248
+ reason: plannedOccurrences.find((entry) => entry.status === status)?.reason ?? "",
249
+ occurrences: plannedOccurrences
250
+ };
251
+ });
252
+ const selectedNames = new Set(grouped.keys());
253
+ for (const [packageName, failure] of [...failures].sort(([left], [right]) => left.localeCompare(right))) {
254
+ if (selectedNames.has(packageName)) continue;
255
+ const context = (options.contextOccurrences ?? []).filter((occurrence) => occurrence.package === packageName).map((occurrence) => ({
256
+ workspace: occurrence.workspace,
257
+ manifestPath: occurrence.manifestPath,
258
+ relativeManifestPath: occurrence.relativeManifestPath,
259
+ section: occurrence.section,
260
+ currentSpecification: occurrence.currentSpecification,
261
+ proposedSpecification: null,
262
+ allowedVersion: null,
263
+ status: "error",
264
+ reason: `peer compatibility lookup failed: ${failure}`
265
+ }));
266
+ decisions.push({
267
+ package: packageName,
268
+ selectedTag: options.cliTag ?? tags[packageName] ?? "latest",
269
+ targetVersion: null,
270
+ status: "error",
271
+ reason: `peer compatibility lookup failed: ${failure}`,
272
+ occurrences: context
273
+ });
274
+ }
275
+ decisions.sort((left, right) => left.package.localeCompare(right.package));
276
+ applyPeerCompatibilityGuard(decisions, options.contextOccurrences ?? options.occurrences, options.packuments);
277
+ const summary = summarize(decisions);
278
+ return {
279
+ decisions,
280
+ summary,
281
+ hasErrors: summary.error > 0
282
+ };
283
+ }
284
+ //#endregion
285
+ export { planUpdates };
@@ -0,0 +1,125 @@
1
+ import semver from "semver";
2
+ //#region src/update/range.ts
3
+ const FULL_VERSION = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
4
+ const PARTIAL_VERSION = String.raw`\d+(?:\.\d+){0,2}`;
5
+ function analyzeAtomicRange(specification) {
6
+ const value = specification.trim();
7
+ if (/^(?:\*|x|X)$/.test(value)) return {
8
+ shape: null,
9
+ tracking: true,
10
+ reason: "wildcard range tracks the selected tag"
11
+ };
12
+ if (new RegExp(`^${FULL_VERSION}$`).test(value) && semver.valid(value)) return {
13
+ shape: { kind: "exact" },
14
+ tracking: false,
15
+ reason: ""
16
+ };
17
+ const operator = value.match(new RegExp(`^([~^])\\s*(${FULL_VERSION}|${PARTIAL_VERSION})$`));
18
+ if (operator && semver.validRange(value)) return {
19
+ shape: {
20
+ kind: "operator",
21
+ operator: operator[1]
22
+ },
23
+ tracking: false,
24
+ reason: ""
25
+ };
26
+ const bounded = value.match(/^((?:>=|>)\s*\d+(?:\.\d+){0,2})\s+(?:<|<=)\s*\d+(?:\.\d+){0,2}$/);
27
+ if (bounded && semver.validRange(value)) return {
28
+ shape: {
29
+ kind: "bounded",
30
+ lower: bounded[1].replace(/\s+/g, "")
31
+ },
32
+ tracking: false,
33
+ reason: ""
34
+ };
35
+ const xRange = value.match(/^(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?$/);
36
+ if (xRange && semver.validRange(value)) {
37
+ const parts = xRange.slice(1).filter((part) => part !== void 0);
38
+ return {
39
+ shape: {
40
+ kind: "x",
41
+ parts,
42
+ wildcard: parts.find((part) => /^[xX*]$/.test(part)) ?? null
43
+ },
44
+ tracking: false,
45
+ reason: ""
46
+ };
47
+ }
48
+ return {
49
+ shape: null,
50
+ tracking: false,
51
+ reason: "unsupported complex semver range"
52
+ };
53
+ }
54
+ function analyzeRange(specification) {
55
+ const clauses = specification.split("||").map((clause) => clause.trim());
56
+ if (clauses.length === 1) return analyzeAtomicRange(specification);
57
+ if (clauses.some((clause) => clause.length === 0)) return {
58
+ shape: null,
59
+ tracking: false,
60
+ reason: "unsupported complex semver range"
61
+ };
62
+ const analyzed = clauses.map(analyzeAtomicRange);
63
+ if (analyzed.some((entry) => !entry.shape || entry.shape.kind === "union" || entry.tracking)) return {
64
+ shape: null,
65
+ tracking: false,
66
+ reason: "unsupported complex semver union"
67
+ };
68
+ const minimums = clauses.map((clause) => semver.minVersion(clause));
69
+ if (minimums.some((version) => version === null)) return {
70
+ shape: null,
71
+ tracking: false,
72
+ reason: "unsupported complex semver union"
73
+ };
74
+ let highestIndex = 0;
75
+ for (let index = 1; index < minimums.length; index += 1) if (semver.gt(minimums[index], minimums[highestIndex])) highestIndex = index;
76
+ return {
77
+ shape: {
78
+ kind: "union",
79
+ clauses: analyzed.map((entry) => entry.shape),
80
+ sourceClauses: clauses,
81
+ highestIndex
82
+ },
83
+ tracking: false,
84
+ reason: ""
85
+ };
86
+ }
87
+ function isBreakingChange(allowedVersion, targetVersion) {
88
+ const allowed = new semver.SemVer(allowedVersion);
89
+ const target = new semver.SemVer(targetVersion);
90
+ if (allowed.major !== target.major) return true;
91
+ return allowed.major === 0 && allowed.minor !== target.minor;
92
+ }
93
+ function nextBreakingBoundary(version) {
94
+ const parsed = new semver.SemVer(version);
95
+ return parsed.major === 0 ? `0.${parsed.minor + 1}.0` : `${parsed.major + 1}.0.0`;
96
+ }
97
+ function rewriteXRange(shape, target) {
98
+ const parsed = new semver.SemVer(target);
99
+ const count = shape.parts.length;
100
+ if (shape.wildcard) {
101
+ const wildcardIndex = shape.parts.findIndex((part) => /^[xX*]$/.test(part));
102
+ if (wildcardIndex === 0) return shape.wildcard;
103
+ if (wildcardIndex === 1) return `${parsed.major}.${shape.wildcard}`;
104
+ return `${parsed.major}.${parsed.minor}.${shape.wildcard}`;
105
+ }
106
+ if (count === 1) return String(parsed.major);
107
+ return `${parsed.major}.${parsed.minor}`;
108
+ }
109
+ function rewriteAtomic(shape, target, forcedBreaking) {
110
+ if (shape.kind === "exact") return target;
111
+ if (shape.kind === "operator") return `${shape.operator}${target}`;
112
+ if (shape.kind === "x") return rewriteXRange(shape, target);
113
+ const boundary = nextBreakingBoundary(target);
114
+ return forcedBreaking ? `>=${target} <${boundary}` : `${shape.lower} <${boundary}`;
115
+ }
116
+ function rewriteRange(shape, target, forcedBreaking) {
117
+ if (shape.kind !== "union") return rewriteAtomic(shape, target, forcedBreaking);
118
+ const highestShape = shape.clauses[shape.highestIndex];
119
+ if (forcedBreaking) return rewriteAtomic(highestShape, target, true);
120
+ const rewritten = [...shape.sourceClauses];
121
+ rewritten[shape.highestIndex] = rewriteAtomic(highestShape, target, false);
122
+ return rewritten.join(" || ");
123
+ }
124
+ //#endregion
125
+ export { isBreakingChange as n, rewriteRange as r, analyzeRange as t };
@@ -0,0 +1,209 @@
1
+ import { t as parseDependencySpecification } from "./specification-DXnDOC-0.js";
2
+ import path from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import { execFile } from "node:child_process";
5
+ import semver from "semver";
6
+ //#region src/update/registry.ts
7
+ function installedNpmCli(executable) {
8
+ const directories = /* @__PURE__ */ new Set([path.dirname(process.execPath)]);
9
+ if (executable && path.isAbsolute(executable)) directories.add(path.dirname(executable));
10
+ for (const directory of directories) for (const candidate of [path.join(directory, "node_modules", "npm", "bin", "npm-cli.js"), path.resolve(directory, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")]) if (existsSync(candidate)) return candidate;
11
+ return null;
12
+ }
13
+ function npmInvocation(env) {
14
+ const executable = env.npm_execpath;
15
+ const executableName = executable ? path.basename(executable).toLowerCase() : "";
16
+ const isNpmExecutable = executableName === "npm" || executableName === "npm.cmd" || /^npm(?:-cli)?\.(?:cjs|js|mjs)$/.test(executableName);
17
+ if (executable && isNpmExecutable) {
18
+ const extension = path.extname(executable).toLowerCase();
19
+ if ([
20
+ ".cjs",
21
+ ".js",
22
+ ".mjs"
23
+ ].includes(extension)) return {
24
+ executable: process.execPath,
25
+ prefix: [executable]
26
+ };
27
+ const npmCli = installedNpmCli(executable);
28
+ return npmCli ? {
29
+ executable: process.execPath,
30
+ prefix: [npmCli]
31
+ } : {
32
+ executable,
33
+ prefix: []
34
+ };
35
+ }
36
+ const npmCli = installedNpmCli();
37
+ if (npmCli) return {
38
+ executable: process.execPath,
39
+ prefix: [npmCli]
40
+ };
41
+ return {
42
+ executable: process.platform === "win32" ? "npm.cmd" : "npm",
43
+ prefix: []
44
+ };
45
+ }
46
+ function executionEnvironment(env) {
47
+ if (env === process.env) return { ...process.env };
48
+ const inherited = { ...process.env };
49
+ for (const name of Object.keys(inherited)) if (/^npm_config_/i.test(name)) delete inherited[name];
50
+ return {
51
+ ...inherited,
52
+ ...env
53
+ };
54
+ }
55
+ async function loadNpmConfiguration(root, env = process.env) {
56
+ const effectiveEnvironment = executionEnvironment(env);
57
+ return {
58
+ cwd: root,
59
+ env: effectiveEnvironment,
60
+ invocation: npmInvocation(effectiveEnvironment)
61
+ };
62
+ }
63
+ function npmError(error, stderr) {
64
+ const details = `${String(error.code ?? "")}\n${stderr}`;
65
+ const safe = /* @__PURE__ */ new Error("npm registry lookup failed");
66
+ safe.code = (details.match(/\bE(?:401|403|404|CONNRESET|TIMEDOUT|TIMEOUT)\b/i)?.[0])?.toUpperCase() ?? (typeof error.code === "string" ? error.code : "");
67
+ if (safe.code === "E401") safe.statusCode = 401;
68
+ if (safe.code === "E403") safe.statusCode = 403;
69
+ if (safe.code === "E404") safe.statusCode = 404;
70
+ return safe;
71
+ }
72
+ function executeNpmJson(args, configuration, preferOnline) {
73
+ const [command, ...positionals] = args;
74
+ return new Promise((resolve, reject) => {
75
+ execFile(configuration.invocation.executable, [
76
+ ...configuration.invocation.prefix,
77
+ command,
78
+ "--json",
79
+ preferOnline ? "--prefer-online" : "--prefer-offline",
80
+ "--offline=false",
81
+ "--loglevel=error",
82
+ "--update-notifier=false",
83
+ "--",
84
+ ...positionals
85
+ ], {
86
+ cwd: configuration.cwd,
87
+ encoding: "utf8",
88
+ env: configuration.env,
89
+ maxBuffer: 64 * 1024 * 1024,
90
+ windowsHide: true
91
+ }, (error, stdout, stderr) => {
92
+ if (error) {
93
+ reject(npmError(error, stderr));
94
+ return;
95
+ }
96
+ try {
97
+ resolve(JSON.parse(stdout));
98
+ } catch {
99
+ reject(/* @__PURE__ */ new Error("npm registry returned malformed JSON"));
100
+ }
101
+ });
102
+ });
103
+ }
104
+ function isRecord(value) {
105
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
106
+ }
107
+ function basePackument(value) {
108
+ if (!isRecord(value) || !Array.isArray(value.versions) || !isRecord(value["dist-tags"])) return null;
109
+ const versions = value.versions.filter((version) => typeof version === "string");
110
+ if (versions.length === 0) return null;
111
+ return {
112
+ "dist-tags": value["dist-tags"],
113
+ versions: Object.fromEntries(versions.map((version) => [version, { version }]))
114
+ };
115
+ }
116
+ function selectedVersions(packument, specifications) {
117
+ const versions = Object.keys(packument.versions ?? {}).filter((version) => semver.valid(version) !== null);
118
+ const selected = new Set(Object.values(packument["dist-tags"] ?? {}).filter((version) => typeof version === "string" && semver.valid(version) !== null && versions.includes(version)));
119
+ for (const specification of specifications) {
120
+ const parsed = parseDependencySpecification(specification);
121
+ if (parsed.type === "tag") {
122
+ const tagged = packument["dist-tags"]?.[parsed.rawSpec];
123
+ if (typeof tagged === "string" && versions.includes(tagged)) selected.add(tagged);
124
+ } else if (parsed.type === "version") {
125
+ if (versions.includes(parsed.rawSpec)) selected.add(parsed.rawSpec);
126
+ } else if (parsed.type === "range") {
127
+ const matching = semver.maxSatisfying(versions, parsed.rawSpec);
128
+ if (matching) selected.add(matching);
129
+ }
130
+ }
131
+ return [...selected].sort(semver.compare);
132
+ }
133
+ function mergeVersionMetadata(packument, value, selected) {
134
+ const entries = Array.isArray(value) ? value : [value];
135
+ const merged = /* @__PURE__ */ new Set();
136
+ for (const entry of entries) {
137
+ if (typeof entry === "string") {
138
+ if (packument.versions?.[entry]) merged.add(entry);
139
+ continue;
140
+ }
141
+ if (!isRecord(entry) || typeof entry.version !== "string") continue;
142
+ const metadata = packument.versions?.[entry.version];
143
+ if (!isRecord(metadata)) continue;
144
+ if (isRecord(entry.peerDependencies)) metadata.peerDependencies = entry.peerDependencies;
145
+ merged.add(entry.version);
146
+ }
147
+ return selected.every((version) => merged.has(version));
148
+ }
149
+ async function executeNpmView(packageName, configuration, specifications) {
150
+ const packument = basePackument(await executeNpmJson([
151
+ "view",
152
+ packageName,
153
+ "versions",
154
+ "dist-tags"
155
+ ], configuration, true));
156
+ if (!packument) return null;
157
+ const versions = selectedVersions(packument, specifications);
158
+ if (versions.length === 0) return packument;
159
+ return mergeVersionMetadata(packument, await executeNpmJson([
160
+ "view",
161
+ `${packageName}@${versions.join(" || ")}`,
162
+ "version",
163
+ "peerDependencies"
164
+ ], configuration, false), versions) ? packument : null;
165
+ }
166
+ function isPackument(value) {
167
+ return isRecord(value) && isRecord(value["dist-tags"]) && isRecord(value.versions);
168
+ }
169
+ function sanitizeRegistryError(error) {
170
+ const value = error && typeof error === "object" ? error : {};
171
+ if (value.statusCode === 404 || value.code === "E404") return "package was not found in the selected registry";
172
+ if (value.statusCode === 401 || value.statusCode === 403 || value.code === "E401" || value.code === "E403") return "registry authentication or authorization failed";
173
+ const code = typeof value.code === "string" ? value.code.toUpperCase() : "";
174
+ if ([
175
+ "ETIMEDOUT",
176
+ "ETIMEOUT",
177
+ "FETCH_ERROR",
178
+ "ECONNRESET"
179
+ ].includes(code)) return "registry request timed out or was interrupted";
180
+ if (/^[A-Z][A-Z0-9_]{1,30}$/.test(code)) return `registry request failed (${code})`;
181
+ return "registry request failed";
182
+ }
183
+ async function fetchPackuments(packageNames, configuration, options = {}) {
184
+ const names = [...new Set(packageNames)].sort((left, right) => left.localeCompare(right));
185
+ const packuments = /* @__PURE__ */ new Map();
186
+ const failures = /* @__PURE__ */ new Map();
187
+ const viewPackage = options.viewPackage ?? executeNpmView;
188
+ let nextIndex = 0;
189
+ const worker = async () => {
190
+ while (nextIndex < names.length) {
191
+ const packageName = names[nextIndex];
192
+ nextIndex += 1;
193
+ try {
194
+ const result = await viewPackage(packageName, configuration, options.requirements?.specifications?.get(packageName) ?? []);
195
+ if (isPackument(result)) packuments.set(packageName, result);
196
+ else failures.set(packageName, "registry returned malformed package metadata");
197
+ } catch (error) {
198
+ failures.set(packageName, sanitizeRegistryError(error));
199
+ }
200
+ }
201
+ };
202
+ await Promise.all(Array.from({ length: Math.min(8, names.length) }, worker));
203
+ return {
204
+ packuments,
205
+ failures
206
+ };
207
+ }
208
+ //#endregion
209
+ export { fetchPackuments, loadNpmConfiguration };