@askrjs/cli 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +140 -0
  3. package/dist/add-DqhqRzBQ.js +555 -0
  4. package/dist/add-DqhqRzBQ.js.map +1 -0
  5. package/dist/add.js +3 -0
  6. package/dist/cli.js +91 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/create.js +923 -0
  9. package/dist/create.js.map +1 -0
  10. package/dist/is-direct-execution-Cdlr-ZUl.js +20 -0
  11. package/dist/is-direct-execution-Cdlr-ZUl.js.map +1 -0
  12. package/dist/openapi.js +127 -0
  13. package/dist/openapi.js.map +1 -0
  14. package/dist/skills/askr-accessibility/SKILL.md +68 -0
  15. package/dist/skills/askr-accessibility/agents/openai.yaml +4 -0
  16. package/dist/skills/askr-agent-execution/SKILL.md +85 -0
  17. package/dist/skills/askr-agent-execution/agents/openai.yaml +4 -0
  18. package/dist/skills/askr-agent-workflows/SKILL.md +57 -0
  19. package/dist/skills/askr-agent-workflows/agents/openai.yaml +4 -0
  20. package/dist/skills/askr-api-integration/SKILL.md +79 -0
  21. package/dist/skills/askr-api-integration/agents/openai.yaml +4 -0
  22. package/dist/skills/askr-app-builder/SKILL.md +99 -0
  23. package/dist/skills/askr-app-builder/agents/openai.yaml +4 -0
  24. package/dist/skills/askr-auth-access/SKILL.md +74 -0
  25. package/dist/skills/askr-auth-access/agents/openai.yaml +4 -0
  26. package/dist/skills/askr-cli-vite/SKILL.md +76 -0
  27. package/dist/skills/askr-cli-vite/agents/openai.yaml +4 -0
  28. package/dist/skills/askr-dashboard-charts/SKILL.md +82 -0
  29. package/dist/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
  30. package/dist/skills/askr-design-system/SKILL.md +86 -0
  31. package/dist/skills/askr-design-system/agents/openai.yaml +4 -0
  32. package/dist/skills/askr-env-config/SKILL.md +74 -0
  33. package/dist/skills/askr-env-config/agents/openai.yaml +4 -0
  34. package/dist/skills/askr-error-loading-empty/SKILL.md +89 -0
  35. package/dist/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
  36. package/dist/skills/askr-file-upload-artifacts/SKILL.md +77 -0
  37. package/dist/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
  38. package/dist/skills/askr-forms-tables-crud/SKILL.md +98 -0
  39. package/dist/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
  40. package/dist/skills/askr-mental-model/SKILL.md +109 -0
  41. package/dist/skills/askr-mental-model/agents/openai.yaml +4 -0
  42. package/dist/skills/askr-migration-react/SKILL.md +81 -0
  43. package/dist/skills/askr-migration-react/agents/openai.yaml +4 -0
  44. package/dist/skills/askr-observability-debugging/SKILL.md +83 -0
  45. package/dist/skills/askr-observability-debugging/agents/openai.yaml +4 -0
  46. package/dist/skills/askr-project-structure/SKILL.md +79 -0
  47. package/dist/skills/askr-project-structure/agents/openai.yaml +4 -0
  48. package/dist/skills/askr-query-mutation/SKILL.md +115 -0
  49. package/dist/skills/askr-query-mutation/agents/openai.yaml +4 -0
  50. package/dist/skills/askr-realtime-streaming/SKILL.md +76 -0
  51. package/dist/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
  52. package/dist/skills/askr-resources-data/SKILL.md +100 -0
  53. package/dist/skills/askr-resources-data/agents/openai.yaml +4 -0
  54. package/dist/skills/askr-routing-layouts/SKILL.md +107 -0
  55. package/dist/skills/askr-routing-layouts/agents/openai.yaml +4 -0
  56. package/dist/skills/askr-runtime-reactivity/SKILL.md +92 -0
  57. package/dist/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
  58. package/dist/skills/askr-ssr-ssg/SKILL.md +76 -0
  59. package/dist/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
  60. package/dist/skills/askr-testing-determinism/SKILL.md +75 -0
  61. package/dist/skills/askr-testing-determinism/agents/openai.yaml +4 -0
  62. package/dist/skills/askr-theming/SKILL.md +86 -0
  63. package/dist/skills/askr-theming/agents/openai.yaml +4 -0
  64. package/dist/skills/askr-ui-composition/SKILL.md +92 -0
  65. package/dist/skills/askr-ui-composition/agents/openai.yaml +4 -0
  66. package/dist/skills-Bh0mEhIx.js +682 -0
  67. package/dist/skills-Bh0mEhIx.js.map +1 -0
  68. package/dist/skills.js +3 -0
  69. package/dist/ssg.js +188 -0
  70. package/dist/ssg.js.map +1 -0
  71. package/dist/templates/full-stack/AGENTS.md +12 -0
  72. package/dist/templates/full-stack/README.md +18 -0
  73. package/dist/templates/full-stack/gitignore.template +4 -0
  74. package/dist/templates/full-stack/index.html +14 -0
  75. package/dist/templates/full-stack/package.json +37 -0
  76. package/dist/templates/full-stack/server.ts +13 -0
  77. package/dist/templates/full-stack/src/action-authorizations.ts +10 -0
  78. package/dist/templates/full-stack/src/actions/create-message.ts +10 -0
  79. package/dist/templates/full-stack/src/i18n.ts +8 -0
  80. package/dist/templates/full-stack/src/main.tsx +12 -0
  81. package/dist/templates/full-stack/src/pages/home.tsx +25 -0
  82. package/dist/templates/full-stack/src/pages/layout.tsx +33 -0
  83. package/dist/templates/full-stack/src/pages/not-found.tsx +4 -0
  84. package/dist/templates/full-stack/src/routes.tsx +20 -0
  85. package/dist/templates/full-stack/src/schemas.ts +11 -0
  86. package/dist/templates/full-stack/src/server/action-registry.ts +12 -0
  87. package/dist/templates/full-stack/src/server/actions/create-message.ts +14 -0
  88. package/dist/templates/full-stack/src/server/app.ts +66 -0
  89. package/dist/templates/full-stack/src/server/dependencies.ts +55 -0
  90. package/dist/templates/full-stack/src/server/entry-server.ts +8 -0
  91. package/dist/templates/full-stack/src/telemetry.ts +4 -0
  92. package/dist/templates/full-stack/src/vite-server.d.ts +6 -0
  93. package/dist/templates/full-stack/tests/actions/create-message.test.ts +13 -0
  94. package/dist/templates/full-stack/tsconfig.json +16 -0
  95. package/dist/templates/full-stack/vite.config.ts +11 -0
  96. package/dist/templates/spa/AGENTS.md +60 -0
  97. package/dist/templates/spa/README.md +96 -0
  98. package/dist/templates/spa/gitignore.template +16 -0
  99. package/dist/templates/spa/index.html +13 -0
  100. package/dist/templates/spa/package.json +35 -0
  101. package/dist/templates/spa/src/adapters/operations-client.ts +90 -0
  102. package/dist/templates/spa/src/components/shared/metric-card.tsx +27 -0
  103. package/dist/templates/spa/src/components/shared/status-badge.tsx +24 -0
  104. package/dist/templates/spa/src/features/operations/operations.query.ts +9 -0
  105. package/dist/templates/spa/src/main.tsx +10 -0
  106. package/dist/templates/spa/src/pages/_layout.tsx +9 -0
  107. package/dist/templates/spa/src/pages/_routes.tsx +27 -0
  108. package/dist/templates/spa/src/pages/app/_layout.tsx +94 -0
  109. package/dist/templates/spa/src/pages/app/_routes.tsx +10 -0
  110. package/dist/templates/spa/src/pages/app/admin-home.tsx +152 -0
  111. package/dist/templates/spa/src/pages/app/agent-runs.tsx +93 -0
  112. package/dist/templates/spa/src/pages/app/settings.tsx +91 -0
  113. package/dist/templates/spa/src/pages/auth/_layout.tsx +38 -0
  114. package/dist/templates/spa/src/pages/auth/_routes.tsx +6 -0
  115. package/dist/templates/spa/src/pages/auth/login.tsx +63 -0
  116. package/dist/templates/spa/src/pages/not-found.tsx +22 -0
  117. package/dist/templates/spa/src/pages/public/_layout.tsx +47 -0
  118. package/dist/templates/spa/src/pages/public/_routes.tsx +6 -0
  119. package/dist/templates/spa/src/pages/public/home.tsx +143 -0
  120. package/dist/templates/spa/src/shared/format.ts +12 -0
  121. package/dist/templates/spa/src/shared/navigation.ts +15 -0
  122. package/dist/templates/spa/src/styles/components.css +49 -0
  123. package/dist/templates/spa/src/styles/layout.css +192 -0
  124. package/dist/templates/spa/src/styles/reset.css +44 -0
  125. package/dist/templates/spa/src/styles/theme.css +57 -0
  126. package/dist/templates/spa/src/styles/tokens.css +20 -0
  127. package/dist/templates/spa/src/styles.css +7 -0
  128. package/dist/templates/spa/src/styles.d.ts +1 -0
  129. package/dist/templates/spa/tests/app.test.tsx +37 -0
  130. package/dist/templates/spa/tests/components/shared.test.tsx +12 -0
  131. package/dist/templates/spa/tests/resources.test.ts +22 -0
  132. package/dist/templates/spa/tsconfig.json +20 -0
  133. package/dist/templates/spa/tsconfig.node.json +10 -0
  134. package/dist/templates/spa/vite.config.ts +24 -0
  135. package/dist/templates/spa/vitest.config.ts +17 -0
  136. package/dist/templates/ssg/AGENTS.md +55 -0
  137. package/dist/templates/ssg/README.md +39 -0
  138. package/dist/templates/ssg/gitignore.template +17 -0
  139. package/dist/templates/ssg/index.html +13 -0
  140. package/dist/templates/ssg/package.json +35 -0
  141. package/dist/templates/ssg/src/app.tsx +14 -0
  142. package/dist/templates/ssg/src/components/badge.tsx +3 -0
  143. package/dist/templates/ssg/src/components/counter.tsx +30 -0
  144. package/dist/templates/ssg/src/components/site-shell.tsx +111 -0
  145. package/dist/templates/ssg/src/jsx.d.ts +23 -0
  146. package/dist/templates/ssg/src/main.tsx +8 -0
  147. package/dist/templates/ssg/src/pages/about.tsx +82 -0
  148. package/dist/templates/ssg/src/pages/content.tsx +63 -0
  149. package/dist/templates/ssg/src/pages/example.tsx +97 -0
  150. package/dist/templates/ssg/src/pages/home.tsx +51 -0
  151. package/dist/templates/ssg/src/resources/user.ts +15 -0
  152. package/dist/templates/ssg/src/routes.tsx +15 -0
  153. package/dist/templates/ssg/src/styles.css +89 -0
  154. package/dist/templates/ssg/src/vite-env.d.ts +5 -0
  155. package/dist/templates/ssg/ssg.config.ts +34 -0
  156. package/dist/templates/ssg/tests/app.test.tsx +19 -0
  157. package/dist/templates/ssg/tests/components/counter.test.tsx +18 -0
  158. package/dist/templates/ssg/tests/resources.test.ts +11 -0
  159. package/dist/templates/ssg/tests/ssg-config.test.ts +11 -0
  160. package/dist/templates/ssg/tsconfig.json +20 -0
  161. package/dist/templates/ssg/tsconfig.node.json +10 -0
  162. package/dist/templates/ssg/vite.config.ts +24 -0
  163. package/dist/templates/ssg/vitest.config.ts +17 -0
  164. package/dist/templates/ssr/AGENTS.md +28 -0
  165. package/dist/templates/ssr/README.md +38 -0
  166. package/dist/templates/ssr/gitignore.template +16 -0
  167. package/dist/templates/ssr/index.html +13 -0
  168. package/dist/templates/ssr/package.json +34 -0
  169. package/dist/templates/ssr/server.ts +16 -0
  170. package/dist/templates/ssr/src/app.tsx +21 -0
  171. package/dist/templates/ssr/src/components/counter.tsx +26 -0
  172. package/dist/templates/ssr/src/entry-server.tsx +10 -0
  173. package/dist/templates/ssr/src/main.tsx +11 -0
  174. package/dist/templates/ssr/src/pages/about.tsx +75 -0
  175. package/dist/templates/ssr/src/pages/example.tsx +113 -0
  176. package/dist/templates/ssr/src/pages/home.tsx +56 -0
  177. package/dist/templates/ssr/src/resources/user.ts +15 -0
  178. package/dist/templates/ssr/src/routes.tsx +13 -0
  179. package/dist/templates/ssr/src/styles.css +148 -0
  180. package/dist/templates/ssr/src/vite-server.d.ts +7 -0
  181. package/dist/templates/ssr/tests/app.test.tsx +24 -0
  182. package/dist/templates/ssr/tests/components/counter.test.tsx +13 -0
  183. package/dist/templates/ssr/tests/resources.test.ts +11 -0
  184. package/dist/templates/ssr/tsconfig.json +22 -0
  185. package/dist/templates/ssr/tsconfig.node.json +10 -0
  186. package/dist/templates/ssr/tsconfig.server.json +15 -0
  187. package/dist/templates/ssr/vite.config.ts +25 -0
  188. package/dist/templates/ssr/vitest.config.ts +13 -0
  189. package/dist/templates/startkit/AGENTS.md +77 -0
  190. package/dist/templates/startkit/README.md +192 -0
  191. package/dist/templates/startkit/gitignore.template +16 -0
  192. package/dist/templates/startkit/index.html +13 -0
  193. package/dist/templates/startkit/package.json +35 -0
  194. package/dist/templates/startkit/src/components/app-header.tsx +93 -0
  195. package/dist/templates/startkit/src/components/app-sidebar.tsx +95 -0
  196. package/dist/templates/startkit/src/components/data-table.tsx +80 -0
  197. package/dist/templates/startkit/src/components/empty-state.tsx +13 -0
  198. package/dist/templates/startkit/src/components/page-header.tsx +23 -0
  199. package/dist/templates/startkit/src/components/stat-card.tsx +24 -0
  200. package/dist/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
  201. package/dist/templates/startkit/src/features/accounts/account-table.tsx +79 -0
  202. package/dist/templates/startkit/src/lib/format.ts +31 -0
  203. package/dist/templates/startkit/src/lib/mock-data.ts +441 -0
  204. package/dist/templates/startkit/src/lib/routes.ts +116 -0
  205. package/dist/templates/startkit/src/main.tsx +12 -0
  206. package/dist/templates/startkit/src/pages/_layout.tsx +56 -0
  207. package/dist/templates/startkit/src/pages/auth/_layout.tsx +7 -0
  208. package/dist/templates/startkit/src/pages/auth/login.tsx +129 -0
  209. package/dist/templates/startkit/src/pages/home.tsx +83 -0
  210. package/dist/templates/startkit/src/pages/not-found.tsx +24 -0
  211. package/dist/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
  212. package/dist/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
  213. package/dist/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
  214. package/dist/templates/startkit/src/pages/workspace/settings.tsx +218 -0
  215. package/dist/templates/startkit/src/router.tsx +7 -0
  216. package/dist/templates/startkit/src/routes/auth-config.ts +38 -0
  217. package/dist/templates/startkit/src/routes/auth.ts +8 -0
  218. package/dist/templates/startkit/src/routes/index.ts +28 -0
  219. package/dist/templates/startkit/src/routes/public.ts +8 -0
  220. package/dist/templates/startkit/src/routes/workspace/accounts.ts +8 -0
  221. package/dist/templates/startkit/src/routes/workspace/index.ts +14 -0
  222. package/dist/templates/startkit/src/styles/components.css +396 -0
  223. package/dist/templates/startkit/src/styles/layout.css +192 -0
  224. package/dist/templates/startkit/src/styles/reset.css +38 -0
  225. package/dist/templates/startkit/src/styles/theme.css +76 -0
  226. package/dist/templates/startkit/src/styles/tokens.css +67 -0
  227. package/dist/templates/startkit/src/styles.css +7 -0
  228. package/dist/templates/startkit/src/toast.ts +55 -0
  229. package/dist/templates/startkit/src/utils/join-classes.ts +4 -0
  230. package/dist/templates/startkit/src/vite-env.d.ts +5 -0
  231. package/dist/templates/startkit/tests/app.test.tsx +32 -0
  232. package/dist/templates/startkit/tests/preferences.test.ts +43 -0
  233. package/dist/templates/startkit/tests/resources.test.ts +82 -0
  234. package/dist/templates/startkit/tsconfig.json +20 -0
  235. package/dist/templates/startkit/tsconfig.node.json +10 -0
  236. package/dist/templates/startkit/vite.config.ts +32 -0
  237. package/dist/templates/startkit/vitest.config.ts +13 -0
  238. package/dist/update-DyW1na5V.js +1140 -0
  239. package/dist/update-DyW1na5V.js.map +1 -0
  240. package/dist/update.js +3 -0
  241. package/package.json +84 -0
  242. package/skills/askr-accessibility/SKILL.md +68 -0
  243. package/skills/askr-accessibility/agents/openai.yaml +4 -0
  244. package/skills/askr-agent-execution/SKILL.md +85 -0
  245. package/skills/askr-agent-execution/agents/openai.yaml +4 -0
  246. package/skills/askr-agent-workflows/SKILL.md +57 -0
  247. package/skills/askr-agent-workflows/agents/openai.yaml +4 -0
  248. package/skills/askr-api-integration/SKILL.md +79 -0
  249. package/skills/askr-api-integration/agents/openai.yaml +4 -0
  250. package/skills/askr-app-builder/SKILL.md +99 -0
  251. package/skills/askr-app-builder/agents/openai.yaml +4 -0
  252. package/skills/askr-auth-access/SKILL.md +74 -0
  253. package/skills/askr-auth-access/agents/openai.yaml +4 -0
  254. package/skills/askr-cli-vite/SKILL.md +76 -0
  255. package/skills/askr-cli-vite/agents/openai.yaml +4 -0
  256. package/skills/askr-dashboard-charts/SKILL.md +82 -0
  257. package/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
  258. package/skills/askr-design-system/SKILL.md +86 -0
  259. package/skills/askr-design-system/agents/openai.yaml +4 -0
  260. package/skills/askr-env-config/SKILL.md +74 -0
  261. package/skills/askr-env-config/agents/openai.yaml +4 -0
  262. package/skills/askr-error-loading-empty/SKILL.md +89 -0
  263. package/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
  264. package/skills/askr-file-upload-artifacts/SKILL.md +77 -0
  265. package/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
  266. package/skills/askr-forms-tables-crud/SKILL.md +98 -0
  267. package/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
  268. package/skills/askr-mental-model/SKILL.md +109 -0
  269. package/skills/askr-mental-model/agents/openai.yaml +4 -0
  270. package/skills/askr-migration-react/SKILL.md +81 -0
  271. package/skills/askr-migration-react/agents/openai.yaml +4 -0
  272. package/skills/askr-observability-debugging/SKILL.md +83 -0
  273. package/skills/askr-observability-debugging/agents/openai.yaml +4 -0
  274. package/skills/askr-project-structure/SKILL.md +79 -0
  275. package/skills/askr-project-structure/agents/openai.yaml +4 -0
  276. package/skills/askr-query-mutation/SKILL.md +115 -0
  277. package/skills/askr-query-mutation/agents/openai.yaml +4 -0
  278. package/skills/askr-realtime-streaming/SKILL.md +76 -0
  279. package/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
  280. package/skills/askr-resources-data/SKILL.md +100 -0
  281. package/skills/askr-resources-data/agents/openai.yaml +4 -0
  282. package/skills/askr-routing-layouts/SKILL.md +107 -0
  283. package/skills/askr-routing-layouts/agents/openai.yaml +4 -0
  284. package/skills/askr-runtime-reactivity/SKILL.md +92 -0
  285. package/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
  286. package/skills/askr-ssr-ssg/SKILL.md +76 -0
  287. package/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
  288. package/skills/askr-testing-determinism/SKILL.md +75 -0
  289. package/skills/askr-testing-determinism/agents/openai.yaml +4 -0
  290. package/skills/askr-theming/SKILL.md +86 -0
  291. package/skills/askr-theming/agents/openai.yaml +4 -0
  292. package/skills/askr-ui-composition/SKILL.md +92 -0
  293. package/skills/askr-ui-composition/agents/openai.yaml +4 -0
  294. package/templates/full-stack/AGENTS.md +12 -0
  295. package/templates/full-stack/README.md +18 -0
  296. package/templates/full-stack/gitignore.template +4 -0
  297. package/templates/full-stack/index.html +14 -0
  298. package/templates/full-stack/package.json +37 -0
  299. package/templates/full-stack/server.ts +13 -0
  300. package/templates/full-stack/src/action-authorizations.ts +10 -0
  301. package/templates/full-stack/src/actions/create-message.ts +10 -0
  302. package/templates/full-stack/src/i18n.ts +8 -0
  303. package/templates/full-stack/src/main.tsx +12 -0
  304. package/templates/full-stack/src/pages/home.tsx +25 -0
  305. package/templates/full-stack/src/pages/layout.tsx +33 -0
  306. package/templates/full-stack/src/pages/not-found.tsx +4 -0
  307. package/templates/full-stack/src/routes.tsx +20 -0
  308. package/templates/full-stack/src/schemas.ts +11 -0
  309. package/templates/full-stack/src/server/action-registry.ts +12 -0
  310. package/templates/full-stack/src/server/actions/create-message.ts +14 -0
  311. package/templates/full-stack/src/server/app.ts +66 -0
  312. package/templates/full-stack/src/server/dependencies.ts +55 -0
  313. package/templates/full-stack/src/server/entry-server.ts +8 -0
  314. package/templates/full-stack/src/telemetry.ts +4 -0
  315. package/templates/full-stack/src/vite-server.d.ts +6 -0
  316. package/templates/full-stack/tests/actions/create-message.test.ts +13 -0
  317. package/templates/full-stack/tsconfig.json +16 -0
  318. package/templates/full-stack/vite.config.ts +11 -0
  319. package/templates/spa/AGENTS.md +60 -0
  320. package/templates/spa/README.md +96 -0
  321. package/templates/spa/gitignore.template +16 -0
  322. package/templates/spa/index.html +13 -0
  323. package/templates/spa/package.json +35 -0
  324. package/templates/spa/src/adapters/operations-client.ts +90 -0
  325. package/templates/spa/src/components/shared/metric-card.tsx +27 -0
  326. package/templates/spa/src/components/shared/status-badge.tsx +24 -0
  327. package/templates/spa/src/features/operations/operations.query.ts +9 -0
  328. package/templates/spa/src/main.tsx +10 -0
  329. package/templates/spa/src/pages/_layout.tsx +9 -0
  330. package/templates/spa/src/pages/_routes.tsx +27 -0
  331. package/templates/spa/src/pages/app/_layout.tsx +94 -0
  332. package/templates/spa/src/pages/app/_routes.tsx +10 -0
  333. package/templates/spa/src/pages/app/admin-home.tsx +152 -0
  334. package/templates/spa/src/pages/app/agent-runs.tsx +93 -0
  335. package/templates/spa/src/pages/app/settings.tsx +91 -0
  336. package/templates/spa/src/pages/auth/_layout.tsx +38 -0
  337. package/templates/spa/src/pages/auth/_routes.tsx +6 -0
  338. package/templates/spa/src/pages/auth/login.tsx +63 -0
  339. package/templates/spa/src/pages/not-found.tsx +22 -0
  340. package/templates/spa/src/pages/public/_layout.tsx +47 -0
  341. package/templates/spa/src/pages/public/_routes.tsx +6 -0
  342. package/templates/spa/src/pages/public/home.tsx +143 -0
  343. package/templates/spa/src/shared/format.ts +12 -0
  344. package/templates/spa/src/shared/navigation.ts +15 -0
  345. package/templates/spa/src/styles/components.css +49 -0
  346. package/templates/spa/src/styles/layout.css +192 -0
  347. package/templates/spa/src/styles/reset.css +44 -0
  348. package/templates/spa/src/styles/theme.css +57 -0
  349. package/templates/spa/src/styles/tokens.css +20 -0
  350. package/templates/spa/src/styles.css +7 -0
  351. package/templates/spa/src/styles.d.ts +1 -0
  352. package/templates/spa/tests/app.test.tsx +37 -0
  353. package/templates/spa/tests/components/shared.test.tsx +12 -0
  354. package/templates/spa/tests/resources.test.ts +22 -0
  355. package/templates/spa/tsconfig.json +20 -0
  356. package/templates/spa/tsconfig.node.json +10 -0
  357. package/templates/spa/vite.config.ts +24 -0
  358. package/templates/spa/vitest.config.ts +17 -0
  359. package/templates/ssg/AGENTS.md +55 -0
  360. package/templates/ssg/README.md +39 -0
  361. package/templates/ssg/gitignore.template +17 -0
  362. package/templates/ssg/index.html +13 -0
  363. package/templates/ssg/package.json +35 -0
  364. package/templates/ssg/src/app.tsx +14 -0
  365. package/templates/ssg/src/components/badge.tsx +3 -0
  366. package/templates/ssg/src/components/counter.tsx +30 -0
  367. package/templates/ssg/src/components/site-shell.tsx +111 -0
  368. package/templates/ssg/src/jsx.d.ts +23 -0
  369. package/templates/ssg/src/main.tsx +8 -0
  370. package/templates/ssg/src/pages/about.tsx +82 -0
  371. package/templates/ssg/src/pages/content.tsx +63 -0
  372. package/templates/ssg/src/pages/example.tsx +97 -0
  373. package/templates/ssg/src/pages/home.tsx +51 -0
  374. package/templates/ssg/src/resources/user.ts +15 -0
  375. package/templates/ssg/src/routes.tsx +15 -0
  376. package/templates/ssg/src/styles.css +89 -0
  377. package/templates/ssg/src/vite-env.d.ts +5 -0
  378. package/templates/ssg/ssg.config.ts +34 -0
  379. package/templates/ssg/tests/app.test.tsx +19 -0
  380. package/templates/ssg/tests/components/counter.test.tsx +18 -0
  381. package/templates/ssg/tests/resources.test.ts +11 -0
  382. package/templates/ssg/tests/ssg-config.test.ts +11 -0
  383. package/templates/ssg/tsconfig.json +20 -0
  384. package/templates/ssg/tsconfig.node.json +10 -0
  385. package/templates/ssg/vite.config.ts +24 -0
  386. package/templates/ssg/vitest.config.ts +17 -0
  387. package/templates/ssr/AGENTS.md +28 -0
  388. package/templates/ssr/README.md +38 -0
  389. package/templates/ssr/gitignore.template +16 -0
  390. package/templates/ssr/index.html +13 -0
  391. package/templates/ssr/package.json +34 -0
  392. package/templates/ssr/server.ts +16 -0
  393. package/templates/ssr/src/app.tsx +21 -0
  394. package/templates/ssr/src/components/counter.tsx +26 -0
  395. package/templates/ssr/src/entry-server.tsx +10 -0
  396. package/templates/ssr/src/main.tsx +11 -0
  397. package/templates/ssr/src/pages/about.tsx +75 -0
  398. package/templates/ssr/src/pages/example.tsx +113 -0
  399. package/templates/ssr/src/pages/home.tsx +56 -0
  400. package/templates/ssr/src/resources/user.ts +15 -0
  401. package/templates/ssr/src/routes.tsx +13 -0
  402. package/templates/ssr/src/styles.css +148 -0
  403. package/templates/ssr/src/vite-server.d.ts +7 -0
  404. package/templates/ssr/tests/app.test.tsx +24 -0
  405. package/templates/ssr/tests/components/counter.test.tsx +13 -0
  406. package/templates/ssr/tests/resources.test.ts +11 -0
  407. package/templates/ssr/tsconfig.json +22 -0
  408. package/templates/ssr/tsconfig.node.json +10 -0
  409. package/templates/ssr/tsconfig.server.json +15 -0
  410. package/templates/ssr/vite.config.ts +25 -0
  411. package/templates/ssr/vitest.config.ts +13 -0
  412. package/templates/startkit/AGENTS.md +77 -0
  413. package/templates/startkit/README.md +192 -0
  414. package/templates/startkit/gitignore.template +16 -0
  415. package/templates/startkit/index.html +13 -0
  416. package/templates/startkit/package.json +35 -0
  417. package/templates/startkit/src/components/app-header.tsx +93 -0
  418. package/templates/startkit/src/components/app-sidebar.tsx +95 -0
  419. package/templates/startkit/src/components/data-table.tsx +80 -0
  420. package/templates/startkit/src/components/empty-state.tsx +13 -0
  421. package/templates/startkit/src/components/page-header.tsx +23 -0
  422. package/templates/startkit/src/components/stat-card.tsx +24 -0
  423. package/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
  424. package/templates/startkit/src/features/accounts/account-table.tsx +79 -0
  425. package/templates/startkit/src/lib/format.ts +31 -0
  426. package/templates/startkit/src/lib/mock-data.ts +441 -0
  427. package/templates/startkit/src/lib/routes.ts +116 -0
  428. package/templates/startkit/src/main.tsx +12 -0
  429. package/templates/startkit/src/pages/_layout.tsx +56 -0
  430. package/templates/startkit/src/pages/auth/_layout.tsx +7 -0
  431. package/templates/startkit/src/pages/auth/login.tsx +129 -0
  432. package/templates/startkit/src/pages/home.tsx +83 -0
  433. package/templates/startkit/src/pages/not-found.tsx +24 -0
  434. package/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
  435. package/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
  436. package/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
  437. package/templates/startkit/src/pages/workspace/settings.tsx +218 -0
  438. package/templates/startkit/src/router.tsx +7 -0
  439. package/templates/startkit/src/routes/auth-config.ts +38 -0
  440. package/templates/startkit/src/routes/auth.ts +8 -0
  441. package/templates/startkit/src/routes/index.ts +28 -0
  442. package/templates/startkit/src/routes/public.ts +8 -0
  443. package/templates/startkit/src/routes/workspace/accounts.ts +8 -0
  444. package/templates/startkit/src/routes/workspace/index.ts +14 -0
  445. package/templates/startkit/src/styles/components.css +396 -0
  446. package/templates/startkit/src/styles/layout.css +192 -0
  447. package/templates/startkit/src/styles/reset.css +38 -0
  448. package/templates/startkit/src/styles/theme.css +76 -0
  449. package/templates/startkit/src/styles/tokens.css +67 -0
  450. package/templates/startkit/src/styles.css +7 -0
  451. package/templates/startkit/src/toast.ts +55 -0
  452. package/templates/startkit/src/utils/join-classes.ts +4 -0
  453. package/templates/startkit/src/vite-env.d.ts +5 -0
  454. package/templates/startkit/tests/app.test.tsx +32 -0
  455. package/templates/startkit/tests/preferences.test.ts +43 -0
  456. package/templates/startkit/tests/resources.test.ts +82 -0
  457. package/templates/startkit/tsconfig.json +20 -0
  458. package/templates/startkit/tsconfig.node.json +10 -0
  459. package/templates/startkit/vite.config.ts +32 -0
  460. package/templates/startkit/vitest.config.ts +13 -0
@@ -0,0 +1,1140 @@
1
+ import { t as isDirectExecution } from "./is-direct-execution-Cdlr-ZUl.js";
2
+ import { createRequire } from "node:module";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { existsSync } from "node:fs";
6
+ import { randomUUID } from "node:crypto";
7
+ import { parseDocument } from "yaml";
8
+ import { minimatch } from "minimatch";
9
+ import semver from "semver";
10
+ import { applyEdits, modify, parse } from "jsonc-parser";
11
+ //#region src/update/range.ts
12
+ const FULL_VERSION = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
13
+ const PARTIAL_VERSION = String.raw`\d+(?:\.\d+){0,2}`;
14
+ function analyzeAtomicRange(specification) {
15
+ const value = specification.trim();
16
+ if (/^(?:\*|x|X)$/.test(value)) return {
17
+ shape: null,
18
+ tracking: true,
19
+ reason: "wildcard range tracks the selected tag"
20
+ };
21
+ if (new RegExp(`^${FULL_VERSION}$`).test(value) && semver.valid(value)) return {
22
+ shape: { kind: "exact" },
23
+ tracking: false,
24
+ reason: ""
25
+ };
26
+ const operator = value.match(new RegExp(`^([~^])\\s*(${FULL_VERSION}|${PARTIAL_VERSION})$`));
27
+ if (operator && semver.validRange(value)) return {
28
+ shape: {
29
+ kind: "operator",
30
+ operator: operator[1]
31
+ },
32
+ tracking: false,
33
+ reason: ""
34
+ };
35
+ const bounded = value.match(/^((?:>=|>)\s*\d+(?:\.\d+){0,2})\s+(?:<|<=)\s*\d+(?:\.\d+){0,2}$/);
36
+ if (bounded && semver.validRange(value)) return {
37
+ shape: {
38
+ kind: "bounded",
39
+ lower: bounded[1].replace(/\s+/g, "")
40
+ },
41
+ tracking: false,
42
+ reason: ""
43
+ };
44
+ const xRange = value.match(/^(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?$/);
45
+ if (xRange && semver.validRange(value)) {
46
+ const parts = xRange.slice(1).filter((part) => part !== void 0);
47
+ return {
48
+ shape: {
49
+ kind: "x",
50
+ parts,
51
+ wildcard: parts.find((part) => /^[xX*]$/.test(part)) ?? null
52
+ },
53
+ tracking: false,
54
+ reason: ""
55
+ };
56
+ }
57
+ return {
58
+ shape: null,
59
+ tracking: false,
60
+ reason: "unsupported complex semver range"
61
+ };
62
+ }
63
+ function analyzeRange(specification) {
64
+ const clauses = specification.split("||").map((clause) => clause.trim());
65
+ if (clauses.length === 1) return analyzeAtomicRange(specification);
66
+ if (clauses.some((clause) => clause.length === 0)) return {
67
+ shape: null,
68
+ tracking: false,
69
+ reason: "unsupported complex semver range"
70
+ };
71
+ const analyzed = clauses.map(analyzeAtomicRange);
72
+ if (analyzed.some((entry) => !entry.shape || entry.shape.kind === "union" || entry.tracking)) return {
73
+ shape: null,
74
+ tracking: false,
75
+ reason: "unsupported complex semver union"
76
+ };
77
+ const minimums = clauses.map((clause) => semver.minVersion(clause));
78
+ if (minimums.some((version) => version === null)) return {
79
+ shape: null,
80
+ tracking: false,
81
+ reason: "unsupported complex semver union"
82
+ };
83
+ let highestIndex = 0;
84
+ for (let index = 1; index < minimums.length; index += 1) if (semver.gt(minimums[index], minimums[highestIndex])) highestIndex = index;
85
+ return {
86
+ shape: {
87
+ kind: "union",
88
+ clauses: analyzed.map((entry) => entry.shape),
89
+ sourceClauses: clauses,
90
+ highestIndex
91
+ },
92
+ tracking: false,
93
+ reason: ""
94
+ };
95
+ }
96
+ function isBreakingChange(allowedVersion, targetVersion) {
97
+ const allowed = new semver.SemVer(allowedVersion);
98
+ const target = new semver.SemVer(targetVersion);
99
+ if (allowed.major !== target.major) return true;
100
+ return allowed.major === 0 && allowed.minor !== target.minor;
101
+ }
102
+ function nextBreakingBoundary(version) {
103
+ const parsed = new semver.SemVer(version);
104
+ return parsed.major === 0 ? `0.${parsed.minor + 1}.0` : `${parsed.major + 1}.0.0`;
105
+ }
106
+ function rewriteXRange(shape, target) {
107
+ const parsed = new semver.SemVer(target);
108
+ const count = shape.parts.length;
109
+ if (shape.wildcard) {
110
+ const wildcardIndex = shape.parts.findIndex((part) => /^[xX*]$/.test(part));
111
+ if (wildcardIndex === 0) return shape.wildcard;
112
+ if (wildcardIndex === 1) return `${parsed.major}.${shape.wildcard}`;
113
+ return `${parsed.major}.${parsed.minor}.${shape.wildcard}`;
114
+ }
115
+ if (count === 1) return String(parsed.major);
116
+ return `${parsed.major}.${parsed.minor}`;
117
+ }
118
+ function rewriteAtomic(shape, target, forcedBreaking) {
119
+ if (shape.kind === "exact") return target;
120
+ if (shape.kind === "operator") return `${shape.operator}${target}`;
121
+ if (shape.kind === "x") return rewriteXRange(shape, target);
122
+ const boundary = nextBreakingBoundary(target);
123
+ return forcedBreaking ? `>=${target} <${boundary}` : `${shape.lower} <${boundary}`;
124
+ }
125
+ function rewriteRange(shape, target, forcedBreaking) {
126
+ if (shape.kind !== "union") return rewriteAtomic(shape, target, forcedBreaking);
127
+ const highestShape = shape.clauses[shape.highestIndex];
128
+ if (forcedBreaking) return rewriteAtomic(highestShape, target, true);
129
+ const rewritten = [...shape.sourceClauses];
130
+ rewritten[shape.highestIndex] = rewriteAtomic(highestShape, target, false);
131
+ return rewritten.join(" || ");
132
+ }
133
+ //#endregion
134
+ //#region src/update/npm-adapters.ts
135
+ const require = createRequire(import.meta.url);
136
+ const npmPackageArg = require("npm-package-arg");
137
+ const mapDeclaredWorkspaces = require("@npmcli/map-workspaces");
138
+ const npmRegistryFetch = require("npm-registry-fetch");
139
+ const NpmConfig = require("@npmcli/config");
140
+ const npmConfigDefinitions = require("@npmcli/config/lib/definitions");
141
+ //#endregion
142
+ //#region src/update/types.ts
143
+ const DEPENDENCY_SECTIONS = [
144
+ "dependencies",
145
+ "devDependencies",
146
+ "optionalDependencies",
147
+ "peerDependencies"
148
+ ];
149
+ //#endregion
150
+ //#region src/update/discovery.ts
151
+ async function isFile(filePath) {
152
+ return (await fs.stat(filePath).catch(() => null))?.isFile() ?? false;
153
+ }
154
+ async function readManifest(manifestPath) {
155
+ let source;
156
+ try {
157
+ source = await fs.readFile(manifestPath, "utf8");
158
+ } catch {
159
+ throw new Error(`Unable to read manifest: ${manifestPath}`);
160
+ }
161
+ try {
162
+ const value = JSON.parse(source.replace(/^\uFEFF/, ""));
163
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error();
164
+ return value;
165
+ } catch {
166
+ throw new Error(`Malformed package manifest: ${manifestPath}`);
167
+ }
168
+ }
169
+ function packageWorkspacePatterns(manifest) {
170
+ if (!("workspaces" in manifest)) return null;
171
+ const declaration = manifest.workspaces;
172
+ const patterns = Array.isArray(declaration) ? declaration : declaration && typeof declaration === "object" && !Array.isArray(declaration) ? declaration.packages : null;
173
+ if (!Array.isArray(patterns) || patterns.some((pattern) => typeof pattern !== "string")) throw new Error("Invalid package.json workspaces declaration; expected an array of paths.");
174
+ return patterns;
175
+ }
176
+ async function pnpmWorkspacePatterns(root) {
177
+ const workspacePath = path.join(root, "pnpm-workspace.yaml");
178
+ if (!await isFile(workspacePath)) return null;
179
+ const document = parseDocument(await fs.readFile(workspacePath, "utf8"), { prettyErrors: false });
180
+ if (document.errors.length > 0) throw new Error(`Malformed pnpm workspace declaration: ${workspacePath}`);
181
+ const value = document.toJS();
182
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid pnpm workspace declaration; expected a mapping with packages.");
183
+ const packages = value.packages;
184
+ if (!Array.isArray(packages) || packages.some((pattern) => typeof pattern !== "string")) throw new Error("Invalid pnpm workspace declaration; expected packages to be an array.");
185
+ return packages;
186
+ }
187
+ async function findProjectRoot(start) {
188
+ const resolved = path.resolve(start);
189
+ if (!(await fs.stat(resolved).catch(() => null))?.isDirectory()) throw new Error(`Working directory does not exist: ${resolved}`);
190
+ let directory = resolved;
191
+ let nearestManifestDirectory = null;
192
+ while (true) {
193
+ const manifestPath = path.join(directory, "package.json");
194
+ const hasManifest = await isFile(manifestPath);
195
+ if (hasManifest) {
196
+ const manifest = await readManifest(manifestPath);
197
+ nearestManifestDirectory ??= directory;
198
+ if (packageWorkspacePatterns(manifest) !== null) return directory;
199
+ }
200
+ if (await isFile(path.join(directory, "pnpm-workspace.yaml"))) {
201
+ if (!hasManifest) throw new Error(`Workspace root is missing package.json: ${directory}`);
202
+ await pnpmWorkspacePatterns(directory);
203
+ return directory;
204
+ }
205
+ const parent = path.dirname(directory);
206
+ if (parent === directory) break;
207
+ directory = parent;
208
+ }
209
+ if (nearestManifestDirectory) return nearestManifestDirectory;
210
+ throw new Error(`No package.json found from ${resolved}.`);
211
+ }
212
+ function parsePolicy(manifest) {
213
+ const empty = {
214
+ ignore: [],
215
+ tags: {}
216
+ };
217
+ if (!("askr" in manifest)) return empty;
218
+ if (!manifest.askr || typeof manifest.askr !== "object" || Array.isArray(manifest.askr)) throw new Error("Invalid askr update configuration in the workspace root.");
219
+ const update = manifest.askr.update;
220
+ if (update === void 0) return empty;
221
+ if (!update || typeof update !== "object" || Array.isArray(update)) throw new Error("Invalid askr.update configuration in the workspace root.");
222
+ const config = update;
223
+ const ignore = config.ignore ?? [];
224
+ const tags = config.tags ?? {};
225
+ if (!Array.isArray(ignore) || ignore.some((entry) => typeof entry !== "string")) throw new Error("Invalid askr.update.ignore configuration; expected an array of patterns.");
226
+ if (!tags || typeof tags !== "object" || Array.isArray(tags) || Object.entries(tags).some(([name, tag]) => !name || typeof tag !== "string" || !tag)) throw new Error("Invalid askr.update.tags configuration; expected package-to-tag strings.");
227
+ return {
228
+ ignore,
229
+ tags
230
+ };
231
+ }
232
+ function relativeManifestPath(root, manifestPath) {
233
+ return path.relative(root, manifestPath).split(path.sep).join("/") || "package.json";
234
+ }
235
+ function workspaceName(manifest, fallback) {
236
+ return typeof manifest.name === "string" && manifest.name.trim() ? manifest.name : fallback;
237
+ }
238
+ async function discoverWorkspaces(root) {
239
+ const rootManifestPath = path.join(root, "package.json");
240
+ const rootManifest = await readManifest(rootManifestPath);
241
+ const policy = parsePolicy(rootManifest);
242
+ const packagePatterns = packageWorkspacePatterns(rootManifest) ?? [];
243
+ const pnpmPatterns = await pnpmWorkspacePatterns(root) ?? [];
244
+ const patterns = [...packagePatterns, ...pnpmPatterns];
245
+ const mapped = patterns.length > 0 ? await mapDeclaredWorkspaces({
246
+ cwd: root,
247
+ pkg: { workspaces: patterns }
248
+ }) : /* @__PURE__ */ new Map();
249
+ const rootName = workspaceName(rootManifest, "(root)");
250
+ if (mapped.has(rootName)) throw new Error(`Duplicate workspace name '${rootName}' includes the workspace root.`);
251
+ const workspaces = [{
252
+ name: rootName,
253
+ directory: root,
254
+ manifestPath: rootManifestPath,
255
+ relativeManifestPath: "package.json",
256
+ manifest: rootManifest,
257
+ isRoot: true
258
+ }];
259
+ for (const [mappedName, directory] of mapped) {
260
+ const manifestPath = path.join(directory, "package.json");
261
+ const manifest = await readManifest(manifestPath);
262
+ workspaces.push({
263
+ name: workspaceName(manifest, mappedName),
264
+ directory,
265
+ manifestPath,
266
+ relativeManifestPath: relativeManifestPath(root, manifestPath),
267
+ manifest,
268
+ isRoot: false
269
+ });
270
+ }
271
+ workspaces.sort((left, right) => {
272
+ if (left.isRoot !== right.isRoot) return left.isRoot ? -1 : 1;
273
+ return left.name.localeCompare(right.name) || left.manifestPath.localeCompare(right.manifestPath);
274
+ });
275
+ return {
276
+ policy,
277
+ rootManifest,
278
+ workspaces
279
+ };
280
+ }
281
+ function matchesAny(value, patterns) {
282
+ return patterns.some((pattern) => minimatch(value, pattern, { dot: true }));
283
+ }
284
+ function classifySpecification(packageName, specification, directory, localNames) {
285
+ if (localNames.has(packageName)) return {
286
+ kind: "local",
287
+ registryManaged: false,
288
+ reason: "dependency resolves to a discovered workspace"
289
+ };
290
+ if (/^workspace:/i.test(specification)) return {
291
+ kind: "local",
292
+ registryManaged: false,
293
+ reason: "workspace protocol is not registry-managed"
294
+ };
295
+ if (/^link:/i.test(specification)) return {
296
+ kind: "local",
297
+ registryManaged: false,
298
+ reason: "link protocol is not registry-managed"
299
+ };
300
+ let parsed;
301
+ try {
302
+ parsed = npmPackageArg.resolve(packageName, specification, directory);
303
+ } catch {
304
+ return {
305
+ kind: "manual",
306
+ registryManaged: false,
307
+ reason: "unsupported dependency specification"
308
+ };
309
+ }
310
+ if ([
311
+ "directory",
312
+ "file",
313
+ "git",
314
+ "remote"
315
+ ].includes(parsed.type)) return {
316
+ kind: "local",
317
+ registryManaged: false,
318
+ reason: `${parsed.type} specification is not registry-managed`
319
+ };
320
+ if (parsed.type === "alias") return {
321
+ kind: "manual",
322
+ registryManaged: false,
323
+ reason: "npm aliases require manual review"
324
+ };
325
+ if (parsed.type === "tag") return {
326
+ kind: "current",
327
+ registryManaged: true,
328
+ reason: "tracking tag is not rewritten"
329
+ };
330
+ if (parsed.type !== "range" && parsed.type !== "version") return {
331
+ kind: "manual",
332
+ registryManaged: false,
333
+ reason: "unsupported dependency specification"
334
+ };
335
+ const analysis = analyzeRange(specification);
336
+ if (analysis.tracking) return {
337
+ kind: "current",
338
+ registryManaged: true,
339
+ reason: analysis.reason
340
+ };
341
+ if (!analysis.shape) return {
342
+ kind: "manual",
343
+ registryManaged: false,
344
+ reason: analysis.reason
345
+ };
346
+ return {
347
+ kind: "fetch",
348
+ registryManaged: true,
349
+ reason: ""
350
+ };
351
+ }
352
+ function collectOccurrences(root, workspaces, localNames, policy, packagePatterns) {
353
+ const occurrences = [];
354
+ for (const workspace of workspaces) for (const section of DEPENDENCY_SECTIONS) {
355
+ const dependencies = workspace.manifest[section];
356
+ if (dependencies === void 0) continue;
357
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) throw new Error(`Invalid ${section} in ${workspace.relativeManifestPath}; expected an object.`);
358
+ for (const [packageName, specification] of Object.entries(dependencies)) {
359
+ if (typeof specification !== "string") throw new Error(`Invalid ${section}.${packageName} in ${workspace.relativeManifestPath}.`);
360
+ if (packagePatterns.length > 0 && !matchesAny(packageName, packagePatterns)) continue;
361
+ if (packagePatterns.length === 0 && matchesAny(packageName, policy.ignore)) continue;
362
+ occurrences.push({
363
+ package: packageName,
364
+ workspace: workspace.name,
365
+ manifestPath: workspace.manifestPath,
366
+ relativeManifestPath: relativeManifestPath(root, workspace.manifestPath),
367
+ section,
368
+ currentSpecification: specification,
369
+ ...classifySpecification(packageName, specification, workspace.directory, localNames)
370
+ });
371
+ }
372
+ }
373
+ const sectionOrder = new Map(DEPENDENCY_SECTIONS.map((section, index) => [section, index]));
374
+ occurrences.sort((left, right) => left.package.localeCompare(right.package) || left.workspace.localeCompare(right.workspace) || left.relativeManifestPath.localeCompare(right.relativeManifestPath) || sectionOrder.get(left.section) - sectionOrder.get(right.section));
375
+ return occurrences;
376
+ }
377
+ async function discoverProject(options) {
378
+ const root = await findProjectRoot(options.cwd);
379
+ const { policy, workspaces } = await discoverWorkspaces(root);
380
+ const selectedWorkspaces = options.workspacePatterns.length === 0 ? workspaces : workspaces.filter((workspace) => matchesAny(workspace.name, options.workspacePatterns));
381
+ if (selectedWorkspaces.length === 0) throw new Error("No discovered workspace matches the requested --workspace filters.");
382
+ const localNames = new Set(workspaces.map((workspace) => workspace.name));
383
+ return {
384
+ root,
385
+ workspaces,
386
+ selectedWorkspaces,
387
+ policy,
388
+ occurrences: collectOccurrences(root, selectedWorkspaces, localNames, policy, options.packagePatterns),
389
+ contextOccurrences: collectOccurrences(root, selectedWorkspaces, localNames, {
390
+ ignore: [],
391
+ tags: policy.tags
392
+ }, [])
393
+ };
394
+ }
395
+ //#endregion
396
+ //#region src/update/planner.ts
397
+ const STATUS_PRIORITY = {
398
+ current: 0,
399
+ local: 1,
400
+ safe: 2,
401
+ breaking: 3,
402
+ manual: 4,
403
+ error: 5
404
+ };
405
+ function publishedVersions(packument) {
406
+ return Object.keys(packument.versions ?? {}).filter((version) => semver.valid(version) !== null).sort(semver.compare);
407
+ }
408
+ function selectedTarget(packument, tag) {
409
+ const value = packument["dist-tags"]?.[tag];
410
+ return typeof value === "string" && semver.valid(value) ? value : null;
411
+ }
412
+ function plannedOccurrence(occurrence, packument, failure, selectedTag, force) {
413
+ const base = {
414
+ workspace: occurrence.workspace,
415
+ manifestPath: occurrence.manifestPath,
416
+ relativeManifestPath: occurrence.relativeManifestPath,
417
+ section: occurrence.section,
418
+ currentSpecification: occurrence.currentSpecification,
419
+ proposedSpecification: null,
420
+ allowedVersion: null
421
+ };
422
+ if (occurrence.kind === "local") return {
423
+ targetVersion: null,
424
+ occurrence: {
425
+ ...base,
426
+ status: "local",
427
+ reason: occurrence.reason
428
+ }
429
+ };
430
+ if (occurrence.kind === "manual") return {
431
+ targetVersion: null,
432
+ occurrence: {
433
+ ...base,
434
+ status: "manual",
435
+ reason: occurrence.reason
436
+ }
437
+ };
438
+ if (failure) return {
439
+ targetVersion: null,
440
+ occurrence: {
441
+ ...base,
442
+ status: "error",
443
+ reason: failure
444
+ }
445
+ };
446
+ if (occurrence.kind === "current") return {
447
+ targetVersion: packument ? selectedTarget(packument, selectedTag) : null,
448
+ occurrence: {
449
+ ...base,
450
+ status: "current",
451
+ reason: occurrence.reason
452
+ }
453
+ };
454
+ if (!packument) return {
455
+ targetVersion: null,
456
+ occurrence: {
457
+ ...base,
458
+ status: "error",
459
+ reason: "package metadata is unavailable"
460
+ }
461
+ };
462
+ const targetVersion = selectedTarget(packument, selectedTag);
463
+ if (!targetVersion) return {
464
+ targetVersion: null,
465
+ occurrence: {
466
+ ...base,
467
+ status: "error",
468
+ reason: `dist-tag '${selectedTag}' is not published`
469
+ }
470
+ };
471
+ const versions = publishedVersions(packument);
472
+ if (!versions.includes(targetVersion)) return {
473
+ targetVersion: null,
474
+ occurrence: {
475
+ ...base,
476
+ status: "error",
477
+ reason: `dist-tag '${selectedTag}' does not identify a published version`
478
+ }
479
+ };
480
+ const allowedVersion = semver.maxSatisfying(versions, occurrence.currentSpecification);
481
+ if (!allowedVersion) return {
482
+ targetVersion,
483
+ occurrence: {
484
+ ...base,
485
+ status: "manual",
486
+ reason: "no published version satisfies the current specification"
487
+ }
488
+ };
489
+ if (semver.satisfies(targetVersion, occurrence.currentSpecification) || !semver.gt(targetVersion, allowedVersion)) return {
490
+ targetVersion,
491
+ occurrence: {
492
+ ...base,
493
+ allowedVersion,
494
+ status: "current",
495
+ reason: "selected target is already covered by the current specification"
496
+ }
497
+ };
498
+ const analysis = analyzeRange(occurrence.currentSpecification);
499
+ if (!analysis.shape) return {
500
+ targetVersion,
501
+ occurrence: {
502
+ ...base,
503
+ allowedVersion,
504
+ status: "manual",
505
+ reason: analysis.reason
506
+ }
507
+ };
508
+ const breaking = isBreakingChange(allowedVersion, targetVersion);
509
+ const eligible = !breaking || force;
510
+ return {
511
+ targetVersion,
512
+ occurrence: {
513
+ ...base,
514
+ allowedVersion,
515
+ proposedSpecification: eligible ? rewriteRange(analysis.shape, targetVersion, breaking) : null,
516
+ status: breaking ? "breaking" : "safe",
517
+ reason: breaking ? eligible ? "breaking update included by --force" : "breaking update requires --upgrade --force" : "compatible update is available"
518
+ }
519
+ };
520
+ }
521
+ function occurrenceKey(occurrence, packageName) {
522
+ return [
523
+ occurrence.manifestPath,
524
+ occurrence.section,
525
+ packageName ?? occurrence.package,
526
+ occurrence.currentSpecification
527
+ ].join("\0");
528
+ }
529
+ function resolveSpecificationVersion(specification, packument) {
530
+ const versions = publishedVersions(packument);
531
+ let parsed;
532
+ try {
533
+ parsed = npmPackageArg.resolve("placeholder", specification);
534
+ } catch {
535
+ return null;
536
+ }
537
+ if (parsed.type === "tag") {
538
+ const tagged = packument["dist-tags"]?.[parsed.rawSpec];
539
+ return typeof tagged === "string" && semver.valid(tagged) ? tagged : null;
540
+ }
541
+ if (parsed.type === "version") return semver.valid(parsed.rawSpec);
542
+ if (parsed.type === "range") return semver.maxSatisfying(versions, parsed.rawSpec);
543
+ return null;
544
+ }
545
+ function versionMetadata(packument, version) {
546
+ const metadata = packument.versions?.[version];
547
+ return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : null;
548
+ }
549
+ function applyPeerCompatibilityGuard(decisions, contextOccurrences, packuments) {
550
+ const plannedByKey = /* @__PURE__ */ new Map();
551
+ for (const decision of decisions) for (const occurrence of decision.occurrences) plannedByKey.set(occurrenceKey(occurrence, decision.package), occurrence);
552
+ const contextByWorkspace = /* @__PURE__ */ new Map();
553
+ for (const occurrence of contextOccurrences) {
554
+ const entries = contextByWorkspace.get(occurrence.workspace) ?? [];
555
+ entries.push(occurrence);
556
+ contextByWorkspace.set(occurrence.workspace, entries);
557
+ }
558
+ for (const [workspace, context] of contextByWorkspace) {
559
+ const states = context.flatMap((dependency) => {
560
+ if (!dependency.registryManaged) return [];
561
+ const packument = packuments.get(dependency.package);
562
+ if (!packument) return [];
563
+ const planned = plannedByKey.get(occurrenceKey(dependency));
564
+ const currentVersion = resolveSpecificationVersion(dependency.currentSpecification, packument);
565
+ const futureVersion = resolveSpecificationVersion(planned?.proposedSpecification ?? dependency.currentSpecification, packument);
566
+ return currentVersion && futureVersion ? [{
567
+ dependency,
568
+ packument,
569
+ planned,
570
+ currentVersion,
571
+ futureVersion,
572
+ changed: Boolean(planned?.proposedSpecification)
573
+ }] : [];
574
+ });
575
+ const blockers = /* @__PURE__ */ new Map();
576
+ for (const provider of states) {
577
+ const currentPeers = versionMetadata(provider.packument, provider.currentVersion)?.peerDependencies ?? {};
578
+ const futurePeers = versionMetadata(provider.packument, provider.futureVersion)?.peerDependencies ?? {};
579
+ const peerNames = /* @__PURE__ */ new Set([...Object.keys(currentPeers), ...Object.keys(futurePeers)]);
580
+ for (const peerName of peerNames) {
581
+ const currentRequirement = currentPeers[peerName];
582
+ const futureRequirement = futurePeers[peerName];
583
+ if (futureRequirement !== void 0 && typeof futureRequirement !== "string") continue;
584
+ for (const peer of states.filter((state) => state.dependency.package === peerName)) {
585
+ const currentAccepted = typeof currentRequirement !== "string" || semver.satisfies(peer.currentVersion, currentRequirement);
586
+ const futureAccepted = typeof futureRequirement !== "string" || semver.satisfies(peer.futureVersion, futureRequirement);
587
+ if (!currentAccepted || futureAccepted) continue;
588
+ const reason = `${provider.dependency.package}@${provider.futureVersion} requires ${peerName}@${futureRequirement}`;
589
+ if (provider.changed && provider.planned) blockers.set(provider.planned, reason);
590
+ if (peer.changed && peer.planned) blockers.set(peer.planned, reason);
591
+ }
592
+ }
593
+ }
594
+ for (const [planned, reason] of blockers) {
595
+ planned.status = "manual";
596
+ planned.proposedSpecification = null;
597
+ planned.reason = reason;
598
+ }
599
+ }
600
+ }
601
+ function aggregateStatus(occurrences) {
602
+ return occurrences.reduce((status, occurrence) => STATUS_PRIORITY[occurrence.status] > STATUS_PRIORITY[status] ? occurrence.status : status, "current");
603
+ }
604
+ function summarize(decisions) {
605
+ const summary = {
606
+ packages: decisions.length,
607
+ occurrences: 0,
608
+ changedOccurrences: 0,
609
+ current: 0,
610
+ safe: 0,
611
+ breaking: 0,
612
+ local: 0,
613
+ manual: 0,
614
+ error: 0
615
+ };
616
+ for (const decision of decisions) {
617
+ decision.status = aggregateStatus(decision.occurrences);
618
+ decision.reason = decision.occurrences.find((entry) => entry.status === decision.status)?.reason ?? "";
619
+ summary[decision.status] += 1;
620
+ summary.occurrences += decision.occurrences.length;
621
+ summary.changedOccurrences += decision.occurrences.filter((entry) => entry.proposedSpecification).length;
622
+ }
623
+ return summary;
624
+ }
625
+ function planUpdates(options) {
626
+ const failures = options.failures ?? /* @__PURE__ */ new Map();
627
+ const tags = options.tags ?? {};
628
+ const grouped = /* @__PURE__ */ new Map();
629
+ for (const occurrence of options.occurrences) {
630
+ const entries = grouped.get(occurrence.package) ?? [];
631
+ entries.push(occurrence);
632
+ grouped.set(occurrence.package, entries);
633
+ }
634
+ const decisions = [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([packageName, occurrences]) => {
635
+ const selectedTag = options.cliTag ?? tags[packageName] ?? "latest";
636
+ const planned = occurrences.map((occurrence) => plannedOccurrence(occurrence, options.packuments.get(packageName), failures.get(packageName), selectedTag, options.force ?? false));
637
+ const targetVersion = planned.find((entry) => entry.targetVersion)?.targetVersion ?? null;
638
+ const plannedOccurrences = planned.map((entry) => entry.occurrence);
639
+ const status = aggregateStatus(plannedOccurrences);
640
+ return {
641
+ package: packageName,
642
+ selectedTag,
643
+ targetVersion,
644
+ status,
645
+ reason: plannedOccurrences.find((entry) => entry.status === status)?.reason ?? "",
646
+ occurrences: plannedOccurrences
647
+ };
648
+ });
649
+ const selectedNames = new Set(grouped.keys());
650
+ for (const [packageName, failure] of [...failures].sort(([left], [right]) => left.localeCompare(right))) {
651
+ if (selectedNames.has(packageName)) continue;
652
+ const context = (options.contextOccurrences ?? []).filter((occurrence) => occurrence.package === packageName).map((occurrence) => ({
653
+ workspace: occurrence.workspace,
654
+ manifestPath: occurrence.manifestPath,
655
+ relativeManifestPath: occurrence.relativeManifestPath,
656
+ section: occurrence.section,
657
+ currentSpecification: occurrence.currentSpecification,
658
+ proposedSpecification: null,
659
+ allowedVersion: null,
660
+ status: "error",
661
+ reason: `peer compatibility lookup failed: ${failure}`
662
+ }));
663
+ decisions.push({
664
+ package: packageName,
665
+ selectedTag: options.cliTag ?? tags[packageName] ?? "latest",
666
+ targetVersion: null,
667
+ status: "error",
668
+ reason: `peer compatibility lookup failed: ${failure}`,
669
+ occurrences: context
670
+ });
671
+ }
672
+ decisions.sort((left, right) => left.package.localeCompare(right.package));
673
+ applyPeerCompatibilityGuard(decisions, options.contextOccurrences ?? options.occurrences, options.packuments);
674
+ const summary = summarize(decisions);
675
+ return {
676
+ decisions,
677
+ summary,
678
+ hasErrors: summary.error > 0
679
+ };
680
+ }
681
+ //#endregion
682
+ //#region src/update/registry.ts
683
+ const ABBREVIATED_PACKUMENT = "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*";
684
+ function npmPathFromExecutable(executable) {
685
+ let directory = path.dirname(path.resolve(executable));
686
+ for (let depth = 0; depth < 5; depth += 1) {
687
+ const manifestPath = path.join(directory, "package.json");
688
+ if (existsSync(manifestPath)) try {
689
+ if (createRequire(import.meta.url)(manifestPath).name === "npm") return directory;
690
+ } catch {}
691
+ const parent = path.dirname(directory);
692
+ if (parent === directory) break;
693
+ directory = parent;
694
+ }
695
+ return null;
696
+ }
697
+ function resolveNpmPath(env) {
698
+ if (env.npm_execpath) {
699
+ const fromEnvironment = npmPathFromExecutable(env.npm_execpath);
700
+ if (fromEnvironment) return fromEnvironment;
701
+ }
702
+ const executableDirectory = path.dirname(process.execPath);
703
+ const installed = (process.platform === "win32" ? [path.join(executableDirectory, "node_modules", "npm")] : [path.resolve(executableDirectory, "..", "lib", "node_modules", "npm")]).find((candidate) => existsSync(path.join(candidate, "package.json")));
704
+ if (installed) return installed;
705
+ return path.dirname(createRequire(import.meta.url).resolve("@npmcli/config/package.json"));
706
+ }
707
+ async function loadNpmConfiguration(root, env = process.env) {
708
+ try {
709
+ const config = new NpmConfig({
710
+ argv: [],
711
+ cwd: root,
712
+ definitions: npmConfigDefinitions.definitions,
713
+ env,
714
+ flatten: npmConfigDefinitions.flatten,
715
+ npmPath: resolveNpmPath(env),
716
+ shorthands: npmConfigDefinitions.shorthands
717
+ });
718
+ await config.load();
719
+ if (!config.validate()) throw new Error("Invalid npm configuration");
720
+ return { ...config.flat };
721
+ } catch {
722
+ throw new Error("Unable to load or validate npm configuration.");
723
+ }
724
+ }
725
+ function sanitizeRegistryError(error) {
726
+ const value = error && typeof error === "object" ? error : {};
727
+ if (value.statusCode === 404) return "package was not found in the selected registry";
728
+ if (value.statusCode === 401 || value.statusCode === 403) return "registry authentication or authorization failed";
729
+ const code = typeof value.code === "string" ? value.code.toUpperCase() : "";
730
+ if ([
731
+ "ETIMEDOUT",
732
+ "ETIMEOUT",
733
+ "FETCH_ERROR",
734
+ "ECONNRESET"
735
+ ].includes(code)) return "registry request timed out or was interrupted";
736
+ if (/^[A-Z][A-Z0-9_]{1,30}$/.test(code)) return `registry request failed (${code})`;
737
+ return "registry request failed";
738
+ }
739
+ function isRecord(value) {
740
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
741
+ }
742
+ function isPackument(value) {
743
+ return isRecord(value) && isRecord(value["dist-tags"]) && isRecord(value.versions);
744
+ }
745
+ async function fetchPackuments(packageNames, configuration, fetchJson = npmRegistryFetch.json.bind(npmRegistryFetch)) {
746
+ const names = [...new Set(packageNames)].sort((left, right) => left.localeCompare(right));
747
+ const packuments = /* @__PURE__ */ new Map();
748
+ const failures = /* @__PURE__ */ new Map();
749
+ let nextIndex = 0;
750
+ const worker = async () => {
751
+ while (nextIndex < names.length) {
752
+ const packageName = names[nextIndex];
753
+ nextIndex += 1;
754
+ const spec = npmPackageArg(packageName);
755
+ try {
756
+ const result = await fetchJson(`/${spec.escapedName}`, {
757
+ ...configuration,
758
+ headers: {
759
+ ...configuration.headers,
760
+ accept: ABBREVIATED_PACKUMENT
761
+ },
762
+ offline: false,
763
+ preferOffline: false,
764
+ preferOnline: true,
765
+ spec
766
+ });
767
+ if (!isPackument(result)) failures.set(packageName, "registry returned malformed package metadata");
768
+ else packuments.set(packageName, result);
769
+ } catch (error) {
770
+ failures.set(packageName, sanitizeRegistryError(error));
771
+ }
772
+ }
773
+ };
774
+ await Promise.all(Array.from({ length: Math.min(8, names.length) }, worker));
775
+ return {
776
+ packuments,
777
+ failures
778
+ };
779
+ }
780
+ //#endregion
781
+ //#region src/update/writer.ts
782
+ function groupEdits(edits) {
783
+ const grouped = /* @__PURE__ */ new Map();
784
+ for (const edit of edits) {
785
+ const entries = grouped.get(edit.manifestPath) ?? [];
786
+ entries.push(edit);
787
+ grouped.set(edit.manifestPath, entries);
788
+ }
789
+ for (const entries of grouped.values()) entries.sort((left, right) => left.section.localeCompare(right.section) || left.package.localeCompare(right.package));
790
+ return new Map([...grouped].sort(([left], [right]) => left.localeCompare(right)));
791
+ }
792
+ function renderReplacement(source, edits) {
793
+ const errors = [];
794
+ const manifest = parse(source, errors, { allowTrailingComma: true });
795
+ if (errors.length > 0 || !manifest || typeof manifest !== "object" || Array.isArray(manifest)) throw new Error("Manifest changed to invalid JSON before writing.");
796
+ let result = source;
797
+ for (const edit of edits) {
798
+ const dependencies = manifest[edit.section];
799
+ if ((dependencies && typeof dependencies === "object" && !Array.isArray(dependencies) ? dependencies[edit.package] : void 0) !== edit.currentSpecification) throw new Error(`Manifest changed before writing: ${edit.manifestPath}`);
800
+ result = applyEdits(result, modify(result, [edit.section, edit.package], edit.proposedSpecification, {}));
801
+ }
802
+ return result;
803
+ }
804
+ async function cleanup(paths) {
805
+ await Promise.all(paths.map((filePath) => fs.rm(filePath, { force: true }).catch(() => void 0)));
806
+ }
807
+ async function rollback(replaced) {
808
+ let complete = true;
809
+ for (const staged of [...replaced].reverse()) {
810
+ const rollbackPath = path.join(path.dirname(staged.manifestPath), `.${path.basename(staged.manifestPath)}.askr-rollback-${randomUUID()}`);
811
+ try {
812
+ await fs.writeFile(rollbackPath, staged.original, {
813
+ flag: "wx",
814
+ mode: staged.mode
815
+ });
816
+ await fs.rename(rollbackPath, staged.manifestPath);
817
+ } catch {
818
+ complete = false;
819
+ await fs.rm(rollbackPath, { force: true }).catch(() => void 0);
820
+ }
821
+ }
822
+ return complete;
823
+ }
824
+ async function writeManifestEdits(edits, options = {}) {
825
+ if (edits.length === 0) return 0;
826
+ const staged = [];
827
+ const replace = options.replace ?? fs.rename;
828
+ try {
829
+ for (const [manifestPath, manifestEdits] of groupEdits(edits)) {
830
+ const [original, stat] = await Promise.all([fs.readFile(manifestPath), fs.stat(manifestPath)]);
831
+ const replacement = renderReplacement(original.toString("utf8"), manifestEdits);
832
+ const temporaryPath = path.join(path.dirname(manifestPath), `.${path.basename(manifestPath)}.askr-update-${randomUUID()}`);
833
+ await fs.writeFile(temporaryPath, replacement, {
834
+ flag: "wx",
835
+ mode: stat.mode
836
+ });
837
+ staged.push({
838
+ manifestPath,
839
+ original,
840
+ replacement,
841
+ temporaryPath,
842
+ mode: stat.mode
843
+ });
844
+ }
845
+ } catch (error) {
846
+ await cleanup(staged.map((entry) => entry.temporaryPath));
847
+ throw error;
848
+ }
849
+ const replaced = [];
850
+ try {
851
+ for (const manifest of staged) {
852
+ await replace(manifest.temporaryPath, manifest.manifestPath);
853
+ replaced.push(manifest);
854
+ }
855
+ } catch {
856
+ const rollbackComplete = await rollback(replaced);
857
+ await cleanup(staged.map((entry) => entry.temporaryPath));
858
+ throw new Error(rollbackComplete ? "Manifest replacement failed; completed replacements were rolled back." : "Manifest replacement failed and rollback was incomplete.");
859
+ }
860
+ return edits.length;
861
+ }
862
+ //#endregion
863
+ //#region src/bin/update.ts
864
+ function helpText() {
865
+ return [
866
+ "askr update - Plan or apply dependency manifest updates",
867
+ "",
868
+ "Usage:",
869
+ " askr update [packages...] [options]",
870
+ "",
871
+ "Options:",
872
+ " -u, --upgrade Apply compatible package.json edits",
873
+ " -f, --force Include breaking updates (requires --upgrade)",
874
+ " --cwd <dir> Resolve a project from another directory",
875
+ " --workspace <glob> Select workspace names (repeatable)",
876
+ " --tag <tag> Use one registry dist-tag for selected packages",
877
+ " --json Emit one deterministic JSON object on stdout",
878
+ " --help, -h Show this help message",
879
+ "",
880
+ "Notes:",
881
+ " Package arguments are minimatch patterns and override persistent ignores.",
882
+ " The command is dry-run by default and changes package.json files only.",
883
+ " Lockfiles, installs, and lifecycle scripts are never touched."
884
+ ].join("\n");
885
+ }
886
+ function optionValue(args, index, option, errors) {
887
+ if (index + 1 >= args.length || args[index + 1].startsWith("-")) {
888
+ errors.push(`Missing value for ${option}`);
889
+ return null;
890
+ }
891
+ return args[index + 1];
892
+ }
893
+ function parseArgs(args) {
894
+ const parsed = {
895
+ cwd: process.cwd(),
896
+ force: false,
897
+ help: false,
898
+ json: false,
899
+ packagePatterns: [],
900
+ upgrade: false,
901
+ workspacePatterns: [],
902
+ errors: []
903
+ };
904
+ let positionalOnly = false;
905
+ for (let index = 0; index < args.length; index += 1) {
906
+ const argument = args[index];
907
+ if (positionalOnly) parsed.packagePatterns.push(argument);
908
+ else if (argument === "--") positionalOnly = true;
909
+ else if (argument === "--help" || argument === "-h") parsed.help = true;
910
+ else if (argument === "--upgrade" || argument === "-u") parsed.upgrade = true;
911
+ else if (argument === "--force" || argument === "-f") parsed.force = true;
912
+ else if (argument === "--json") parsed.json = true;
913
+ else if (argument === "--cwd") {
914
+ const value = optionValue(args, index, "--cwd", parsed.errors);
915
+ if (value !== null) {
916
+ parsed.cwd = path.resolve(value);
917
+ index += 1;
918
+ }
919
+ } else if (argument.startsWith("--cwd=")) parsed.cwd = path.resolve(argument.slice(6));
920
+ else if (argument === "--workspace") {
921
+ const value = optionValue(args, index, "--workspace", parsed.errors);
922
+ if (value !== null) {
923
+ parsed.workspacePatterns.push(value);
924
+ index += 1;
925
+ }
926
+ } else if (argument.startsWith("--workspace=")) parsed.workspacePatterns.push(argument.slice(12));
927
+ else if (argument === "--tag") {
928
+ const value = optionValue(args, index, "--tag", parsed.errors);
929
+ if (value !== null) {
930
+ parsed.tag = value;
931
+ index += 1;
932
+ }
933
+ } else if (argument.startsWith("--tag=")) parsed.tag = argument.slice(6);
934
+ else if (argument.startsWith("-")) parsed.errors.push(`Unknown option: ${argument}`);
935
+ else parsed.packagePatterns.push(argument);
936
+ }
937
+ if (parsed.force && !parsed.upgrade) parsed.errors.push("--force requires --upgrade");
938
+ if (parsed.tag !== void 0 && (!parsed.tag || /\s/.test(parsed.tag))) parsed.errors.push("--tag must be a non-empty dist-tag without whitespace");
939
+ if (parsed.workspacePatterns.some((pattern) => !pattern)) parsed.errors.push("--workspace patterns must not be empty");
940
+ if (parsed.packagePatterns.some((pattern) => !pattern)) parsed.errors.push("Package patterns must not be empty");
941
+ return parsed;
942
+ }
943
+ function emptySummary() {
944
+ return {
945
+ packages: 0,
946
+ occurrences: 0,
947
+ changedOccurrences: 0,
948
+ current: 0,
949
+ safe: 0,
950
+ breaking: 0,
951
+ local: 0,
952
+ manual: 0,
953
+ error: 0
954
+ };
955
+ }
956
+ function serializableDecision(decision) {
957
+ return {
958
+ package: decision.package,
959
+ selectedTag: decision.selectedTag,
960
+ targetVersion: decision.targetVersion,
961
+ status: decision.status,
962
+ reason: decision.reason,
963
+ occurrences: decision.occurrences.map((occurrence) => ({
964
+ workspace: occurrence.workspace,
965
+ manifest: occurrence.relativeManifestPath,
966
+ section: occurrence.section,
967
+ currentSpecification: occurrence.currentSpecification,
968
+ proposedSpecification: occurrence.proposedSpecification,
969
+ allowedVersion: occurrence.allowedVersion,
970
+ status: occurrence.status,
971
+ reason: occurrence.reason
972
+ }))
973
+ };
974
+ }
975
+ function selectedWorkspaceJson(root, workspaces) {
976
+ return workspaces.map((workspace) => ({
977
+ name: workspace.name,
978
+ path: path.relative(root, workspace.directory).split(path.sep).join("/") || ".",
979
+ manifest: workspace.relativeManifestPath
980
+ }));
981
+ }
982
+ function emitJson(io, options) {
983
+ io.log(JSON.stringify({
984
+ root: options.root,
985
+ workspaces: options.workspaces,
986
+ summary: options.summary,
987
+ decisions: options.decisions.map(serializableDecision),
988
+ applied: { occurrences: options.applied },
989
+ errors: options.errors
990
+ }, null, 2));
991
+ }
992
+ function rangeText(occurrence) {
993
+ if (occurrence.proposedSpecification) return `${occurrence.currentSpecification} → ${occurrence.proposedSpecification}`;
994
+ if (occurrence.status === "breaking") return `${occurrence.currentSpecification} (skipped; use -u -f)`;
995
+ return `${occurrence.currentSpecification} (${occurrence.reason})`;
996
+ }
997
+ function renderTable(rows) {
998
+ const headings = [
999
+ "Package",
1000
+ "Allowed",
1001
+ "Latest",
1002
+ "Status",
1003
+ "Range"
1004
+ ];
1005
+ const widths = headings.map((heading, column) => Math.max(heading.length, ...rows.map((row) => row[column].length)));
1006
+ return [headings, ...rows].map((row) => row.map((value, column) => column === row.length - 1 ? value : value.padEnd(widths[column])).join(" "));
1007
+ }
1008
+ function emitHuman(io, decisions, summary, applied, upgrade) {
1009
+ const byWorkspace = /* @__PURE__ */ new Map();
1010
+ for (const decision of decisions) for (const occurrence of decision.occurrences) {
1011
+ if (occurrence.status === "current") continue;
1012
+ const rows = byWorkspace.get(occurrence.workspace) ?? [];
1013
+ rows.push([
1014
+ decision.package,
1015
+ occurrence.allowedVersion ?? "-",
1016
+ decision.targetVersion ?? "-",
1017
+ occurrence.status,
1018
+ rangeText(occurrence)
1019
+ ]);
1020
+ byWorkspace.set(occurrence.workspace, rows);
1021
+ }
1022
+ if (byWorkspace.size === 0) io.log("All selected dependencies are current.");
1023
+ else {
1024
+ let first = true;
1025
+ for (const [workspace, rows] of byWorkspace) {
1026
+ if (!first) io.log("");
1027
+ first = false;
1028
+ io.log(workspace);
1029
+ for (const line of renderTable(rows)) io.log(line);
1030
+ }
1031
+ }
1032
+ const counts = [
1033
+ "safe",
1034
+ "breaking",
1035
+ "current",
1036
+ "manual",
1037
+ "local",
1038
+ "error"
1039
+ ].filter((status) => summary[status] > 0).map((status) => `${summary[status]} ${status}`).join(", ");
1040
+ io.log("");
1041
+ io.log(`Scanned ${summary.packages} package${summary.packages === 1 ? "" : "s"}${counts ? `: ${counts}` : "."}`);
1042
+ if (upgrade) io.log(`Updated ${applied} manifest occurrence${applied === 1 ? "" : "s"}.`);
1043
+ else if (summary.changedOccurrences > 0) io.log(`Dry run: ${summary.changedOccurrences} manifest occurrence${summary.changedOccurrences === 1 ? "" : "s"} can be updated; rerun with -u to apply.`);
1044
+ }
1045
+ function collectEdits(decisions) {
1046
+ return decisions.flatMap((decision) => decision.occurrences.flatMap((occurrence) => occurrence.proposedSpecification ? [{
1047
+ manifestPath: occurrence.manifestPath,
1048
+ section: occurrence.section,
1049
+ package: decision.package,
1050
+ currentSpecification: occurrence.currentSpecification,
1051
+ proposedSpecification: occurrence.proposedSpecification
1052
+ }] : []));
1053
+ }
1054
+ async function defaultRegistry(root, packageNames) {
1055
+ return fetchPackuments(packageNames, await loadNpmConfiguration(root));
1056
+ }
1057
+ async function runUpdateCli(args, io = console, runtime = {}) {
1058
+ const parsed = parseArgs(args);
1059
+ if (parsed.help && parsed.errors.length === 0) {
1060
+ io.log(helpText());
1061
+ return 0;
1062
+ }
1063
+ if (parsed.errors.length > 0) {
1064
+ for (const error of parsed.errors) io.error(`askr update: ${error}`);
1065
+ if (parsed.json) emitJson(io, {
1066
+ root: null,
1067
+ workspaces: [],
1068
+ summary: emptySummary(),
1069
+ decisions: [],
1070
+ applied: 0,
1071
+ errors: parsed.errors
1072
+ });
1073
+ return 1;
1074
+ }
1075
+ let root = null;
1076
+ let selectedWorkspaces = [];
1077
+ try {
1078
+ const project = await discoverProject({
1079
+ cwd: parsed.cwd,
1080
+ packagePatterns: parsed.packagePatterns,
1081
+ workspacePatterns: parsed.workspacePatterns
1082
+ });
1083
+ root = project.root;
1084
+ selectedWorkspaces = project.selectedWorkspaces;
1085
+ const lookupNames = project.occurrences.some((occurrence) => occurrence.kind === "fetch") ? project.contextOccurrences.filter((occurrence) => occurrence.registryManaged).map((occurrence) => occurrence.package) : [];
1086
+ const registry = runtime.registry ?? defaultRegistry;
1087
+ const results = lookupNames.length > 0 ? await registry(project.root, lookupNames) : {
1088
+ packuments: /* @__PURE__ */ new Map(),
1089
+ failures: /* @__PURE__ */ new Map()
1090
+ };
1091
+ const plan = planUpdates({
1092
+ occurrences: project.occurrences,
1093
+ contextOccurrences: project.contextOccurrences,
1094
+ packuments: results.packuments,
1095
+ failures: results.failures,
1096
+ tags: project.policy.tags,
1097
+ cliTag: parsed.tag,
1098
+ force: parsed.force
1099
+ });
1100
+ let applied = 0;
1101
+ const errors = [];
1102
+ if (!plan.hasErrors && parsed.upgrade) try {
1103
+ applied = await (runtime.writer ?? writeManifestEdits)(collectEdits(plan.decisions));
1104
+ } catch {
1105
+ errors.push("Unable to replace package manifests; completed replacements were rolled back when possible.");
1106
+ }
1107
+ if (plan.hasErrors) errors.push("One or more registry lookups or package plans failed.");
1108
+ if (parsed.json) emitJson(io, {
1109
+ root: project.root,
1110
+ workspaces: selectedWorkspaceJson(project.root, project.selectedWorkspaces),
1111
+ summary: plan.summary,
1112
+ decisions: plan.decisions,
1113
+ applied,
1114
+ errors
1115
+ });
1116
+ else emitHuman(io, plan.decisions, plan.summary, applied, parsed.upgrade);
1117
+ for (const error of errors) io.error(`askr update: ${error}`);
1118
+ return errors.length > 0 ? 1 : 0;
1119
+ } catch (error) {
1120
+ const message = error instanceof Error ? error.message : "Update failed.";
1121
+ io.error(`askr update: ${message}`);
1122
+ if (parsed.json) emitJson(io, {
1123
+ root,
1124
+ workspaces: root ? selectedWorkspaceJson(root, selectedWorkspaces) : [],
1125
+ summary: emptySummary(),
1126
+ decisions: [],
1127
+ applied: 0,
1128
+ errors: [message]
1129
+ });
1130
+ return 1;
1131
+ }
1132
+ }
1133
+ async function main() {
1134
+ process.exit(await runUpdateCli(process.argv.slice(2)));
1135
+ }
1136
+ if (isDirectExecution(import.meta.url)) main();
1137
+ //#endregion
1138
+ export { runUpdateCli as t };
1139
+
1140
+ //# sourceMappingURL=update-DyW1na5V.js.map