@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 @@
1
+ {"version":3,"file":"skills-Bh0mEhIx.js","names":["pathExists"],"sources":["../src/bin/skill-review.ts","../src/bin/skills.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\ninterface ReviewPattern {\n label: string;\n regex: RegExp;\n}\n\ninterface ReviewAssertion {\n description: string;\n mode: \"forbid\" | \"require\";\n match: \"all\" | \"any\";\n patterns: ReviewPattern[];\n}\n\ninterface ReviewPromptDefinition {\n id: string;\n title: string;\n relatedSkills: string[];\n repairFocus: string;\n prompt: string;\n assertions: ReviewAssertion[];\n}\n\ninterface ReviewFile {\n path: string;\n content: string;\n}\n\ninterface ReviewAssertionResult {\n description: string;\n passed: boolean;\n matchedFiles: string[];\n matchedPatterns: string[];\n missingPatterns: string[];\n mode: ReviewAssertion[\"mode\"];\n}\n\nexport interface SkillReviewResult {\n filesScanned: number;\n passedChecks: number;\n prompt: string;\n promptId: string;\n repairFocus: string;\n relatedSkills: string[];\n score: number;\n status: \"fail\" | \"pass\";\n targetPath: string;\n title: string;\n totalChecks: number;\n checks: ReviewAssertionResult[];\n}\n\nconst TEXT_FILE_EXTENSIONS = new Set([\n \".cjs\",\n \".css\",\n \".cts\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".md\",\n \".mdx\",\n \".mjs\",\n \".mts\",\n \".scss\",\n \".ts\",\n \".tsx\",\n \".txt\",\n \".yaml\",\n \".yml\",\n]);\n\nconst IGNORED_DIRECTORIES = new Set([\n \".askr\",\n \".git\",\n \".skills\",\n \"skills\",\n \".vite\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n]);\n\nfunction re(label: string, source: string, flags = \"m\"): ReviewPattern {\n return {\n label,\n regex: new RegExp(source, flags),\n };\n}\n\nfunction requireAny(description: string, patterns: ReviewPattern[]): ReviewAssertion {\n return {\n description,\n mode: \"require\",\n match: \"any\",\n patterns,\n };\n}\n\nfunction requireAll(description: string, patterns: ReviewPattern[]): ReviewAssertion {\n return {\n description,\n mode: \"require\",\n match: \"all\",\n patterns,\n };\n}\n\nfunction forbid(description: string, patterns: ReviewPattern[]): ReviewAssertion {\n return {\n description,\n mode: \"forbid\",\n match: \"any\",\n patterns,\n };\n}\n\nconst REVIEW_PROMPTS: ReviewPromptDefinition[] = [\n {\n id: \"foundation\",\n title: \"Foundation\",\n relatedSkills: [\"askr-mental-model\", \"askr-runtime-reactivity\"],\n repairFocus:\n \"Replace React-shaped state and list rendering with state(), derive(), selector(), and For based on local ownership.\",\n prompt:\n \"Build a small Askr page that lets the user switch between queued, running, and completed jobs. Use the right Askr primitives for local state and keyed list rendering.\",\n assertions: [\n requireAny(\"Uses state() for local UI state.\", [re(\"state()\", String.raw`\\bstate\\s*\\(`)]),\n requireAny(\"Uses For for keyed or dynamic list rendering.\", [\n re(\"<For>\", String.raw`<For\\b`),\n re(\"For()\", String.raw`\\bFor\\s*\\(`),\n ]),\n forbid(\"Does not import React or React hooks.\", [\n re(\"React import\", String.raw`from\\s+[\"']react[\"']`),\n re(\"useState\", String.raw`\\buseState\\s*\\(`),\n re(\"useEffect\", String.raw`\\buseEffect\\s*\\(`),\n ]),\n ],\n },\n {\n id: \"routing-layouts\",\n title: \"Routing And Layouts\",\n relatedSkills: [\"askr-project-structure\", \"askr-routing-layouts\"],\n repairFocus:\n \"Move route ownership into the registered route tree and keep layout, auth requirements, and fallback policy in route declarations.\",\n prompt:\n \"Add a protected /app/workspaces/{workspaceId}/settings route with a nested layout, an index page, and a not-found fallback. Keep routing idiomatic to Askr.\",\n assertions: [\n requireAll(\"Uses Askr route composition helpers.\", [\n re(\"group()\", String.raw`\\bgroup\\s*\\(`),\n re(\"fallback()\", String.raw`\\bfallback\\s*\\(`),\n re(\"index()\", String.raw`\\bindex\\s*\\(`),\n ]),\n requireAny(\"Registers routes with page() or route().\", [\n re(\"page()\", String.raw`\\bpage\\s*\\(`),\n re(\"route()\", String.raw`\\broute\\s*\\(`),\n ]),\n requireAny(\"Keeps auth or permission policy in route requirements.\", [\n re(\"auth requirement\", String.raw`\\bauth\\s*:\\s*require[A-Z][A-Za-z]*\\s*\\(`),\n re(\"auth policy\", String.raw`\\bpolicies\\s*:`),\n ]),\n forbid(\"Rejects obsolete boolean and guest-string auth declarations.\", [\n re(\"boolean auth\", String.raw`\\bauth\\s*:\\s*(?:true|false)\\b`),\n re(\"guest auth\", String.raw`\\bauth\\s*:\\s*[\"']guest[\"']`),\n re(\"permission metadata\", String.raw`\\bpermissions?\\s*:`),\n ]),\n ],\n },\n {\n id: \"auth-authorization\",\n title: \"Auth And Authorization\",\n relatedSkills: [\"askr-auth-access\", \"askr-routing-layouts\"],\n repairFocus:\n \"Keep auth and permission policy in function requirements or auth workflow boundaries, then render an explicit forbidden state.\",\n prompt:\n \"Add a billing admin screen that is only available to authenticated users with the billing.manage permission. Show a signed-in forbidden state when the user lacks access.\",\n assertions: [\n requireAny(\"Uses an auth requirement or session workflow.\", [\n re(\"auth requirement\", String.raw`\\brequire(?:User|Anonymous|Permission|Role|Scope)\\s*\\(`),\n re(\"session gate\", String.raw`\\bsignedIn\\b|\\bsession\\b`),\n ]),\n requireAny(\"Preserves permission policy in code or route requirements.\", [\n re(\"billing.manage\", String.raw`billing\\.manage`),\n re(\"permission requirement\", String.raw`\\brequirePermission\\s*\\(`),\n ]),\n forbid(\"Rejects obsolete boolean and guest-string auth declarations.\", [\n re(\"boolean auth\", String.raw`\\bauth\\s*:\\s*(?:true|false)\\b`),\n re(\"guest auth\", String.raw`\\bauth\\s*:\\s*[\"']guest[\"']`),\n re(\"permission metadata\", String.raw`\\bpermissions?\\s*:`),\n ]),\n requireAny(\"Renders a forbidden or access-denied state.\", [\n re(\"forbidden\", String.raw`forbidden`, \"mi\"),\n re(\"access denied\", String.raw`access denied`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"crud-forms\",\n title: \"CRUD And Forms\",\n relatedSkills: [\"askr-forms-tables-crud\", \"askr-error-loading-empty\"],\n repairFocus:\n \"Keep form state local, mutation state feature-owned, and surface field or form errors instead of toast-only failure handling.\",\n prompt:\n \"Build an accounts edit form with field validation, submit pending state, server validation errors, and a keyboard-accessible destructive archive action.\",\n assertions: [\n requireAny(\"Keeps local form state explicit.\", [re(\"state()\", String.raw`\\bstate\\s*\\(`)]),\n requireAny(\"Includes pending or disabled submit handling.\", [\n re(\"pending\", String.raw`\\bpending\\b`),\n re(\"disabled\", String.raw`\\bdisabled\\b`),\n ]),\n requireAny(\"Surfaces field or form validation errors.\", [\n re(\"validation\", String.raw`validation`, \"mi\"),\n re(\"field error\", String.raw`field error`, \"mi\"),\n re(\"error message\", String.raw`error`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"shared-data-consistency\",\n title: \"Shared Data And Consistency\",\n relatedSkills: [\"askr-query-mutation\", \"askr-resources-data\", \"askr-error-loading-empty\"],\n repairFocus:\n \"Use createQuery() and createMutation() with narrow invalidation, preserve consistency metadata, and show truthful syncing state.\",\n prompt:\n \"Build a shared accounts query with an update mutation that preserves stale data while the projection catches up. Show a truthful syncing state after save.\",\n assertions: [\n requireAny(\"Uses createQuery() for shared reads.\", [\n re(\"createQuery()\", String.raw`\\bcreateQuery\\s*\\(`),\n ]),\n requireAny(\"Uses createMutation() for writes.\", [\n re(\"createMutation()\", String.raw`\\bcreateMutation\\s*\\(`),\n ]),\n requireAny(\"Represents truthful syncing or stale states.\", [\n re(\"syncing\", String.raw`syncing`, \"mi\"),\n re(\"pending-write\", String.raw`pending-write`, \"mi\"),\n re(\"stale\", String.raw`stale`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"realtime\",\n title: \"Realtime\",\n relatedSkills: [\"askr-realtime-streaming\", \"askr-query-mutation\"],\n repairFocus:\n \"Preserve cursor or event identity, bound long-running lists, and expose reconnecting or stale state explicitly.\",\n prompt:\n \"Build a live operator timeline that reconnects from a cursor, handles duplicate events safely, and keeps DOM churn bounded on long-running sessions.\",\n assertions: [\n requireAny(\"Preserves stream cursor or event identity.\", [\n re(\"cursor\", String.raw`\\bcursor\\b`),\n re(\"eventId\", String.raw`\\beventId\\b`),\n re(\"lastEventId\", String.raw`\\blastEventId\\b`),\n ]),\n requireAny(\"Handles reconnect or retry explicitly.\", [\n re(\"reconnect\", String.raw`reconnect`, \"mi\"),\n re(\"retry\", String.raw`retry`, \"mi\"),\n ]),\n requireAny(\"Bounds long-running lists or buffers.\", [\n re(\"slice()\", String.raw`\\.slice\\s*\\(`),\n re(\"max events\", String.raw`\\bMAX_[A-Z_]+\\b`),\n re(\"limit\", String.raw`\\blimit\\b`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"theming-ui\",\n title: \"Theming And UI\",\n relatedSkills: [\"askr-theming\", \"askr-ui-composition\", \"askr-accessibility\"],\n repairFocus:\n \"Use askr-themes and askr-ui primitives before custom components, and keep styling token-based and accessibility-safe.\",\n prompt:\n \"Add a themed settings panel using solved Askr theme primitives, preserve dark mode, and avoid inventing app-local replacements for common controls and surfaces.\",\n assertions: [\n requireAny(\"Uses askr-ui or askr-themes primitives.\", [\n re(\"@askrjs/ui\", String.raw`@askrjs\\/ui`),\n re(\"@askrjs/themes\", String.raw`@askrjs\\/themes`),\n ]),\n requireAny(\"Uses tokens or theme-oriented hooks in styles.\", [\n re(\"CSS var token\", String.raw`var\\(--`),\n re(\"data-slot\", String.raw`data-slot`),\n ]),\n requireAny(\"Preserves theme mode behavior.\", [\n re(\"dark mode\", String.raw`dark`, \"mi\"),\n re(\"theme toggle\", String.raw`theme`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"ssr-ssg\",\n title: \"SSR And SSG\",\n relatedSkills: [\"askr-ssr-ssg\", \"askr-routing-layouts\"],\n repairFocus:\n \"Keep routes deterministic, render paths environment-safe, and remove browser-only globals from server or static render code.\",\n prompt:\n \"Add a parameterized docs route that works in SSG and stays hydration-safe when rendered in the browser.\",\n assertions: [\n requireAny(\"Includes route registration for the generated path.\", [\n re(\"page()\", String.raw`\\bpage\\s*\\(`),\n re(\"route()\", String.raw`\\broute\\s*\\(`),\n ]),\n requireAny(\"Includes SSG-oriented code or config.\", [\n re(\"SSG\", String.raw`\\bSSG\\b`),\n re(\"static\", String.raw`static`, \"mi\"),\n re(\"manifest\", String.raw`manifest`, \"mi\"),\n ]),\n forbid(\"Avoids browser-only globals in render paths.\", [\n re(\"window\", String.raw`\\bwindow\\.`),\n re(\"document\", String.raw`\\bdocument\\.`),\n ]),\n ],\n },\n {\n id: \"agent-workflow-ui\",\n title: \"Agent Workflow UI\",\n relatedSkills: [\"askr-agent-workflows\", \"askr-error-loading-empty\"],\n repairFocus:\n \"Model the screen as a run lifecycle with approvals, audit history, retries, and explicit multi-state UI.\",\n prompt:\n \"Build an agent run screen with draft, queued, running, requires-action, failed, and succeeded states, plus an audit-friendly timeline and approval card.\",\n assertions: [\n requireAll(\"Represents multiple run lifecycle states.\", [\n re(\"queued\", String.raw`queued`, \"mi\"),\n re(\"running\", String.raw`running`, \"mi\"),\n re(\"failed\", String.raw`failed`, \"mi\"),\n ]),\n requireAny(\"Surfaces approval or requires-action UI.\", [\n re(\"approval\", String.raw`approval`, \"mi\"),\n re(\"requires-action\", String.raw`requires-action`, \"mi\"),\n ]),\n requireAny(\"Includes a timeline, log, or audit trail.\", [\n re(\"timeline\", String.raw`timeline`, \"mi\"),\n re(\"audit\", String.raw`audit`, \"mi\"),\n re(\"event\", String.raw`event`, \"mi\"),\n ]),\n ],\n },\n {\n id: \"reject-react-query\",\n title: \"Negative Prompt: Reject React And TanStack Query\",\n relatedSkills: [\"askr-mental-model\", \"askr-agent-execution\"],\n repairFocus:\n \"Replace React hooks and TanStack Query with state(), resource(), createQuery(), or createMutation() based on ownership.\",\n prompt: \"Build this screen with React hooks and TanStack Query.\",\n assertions: [\n forbid(\"Does not import React hooks or React itself.\", [\n re(\"React import\", String.raw`from\\s+[\"']react[\"']`),\n re(\"useState\", String.raw`\\buseState\\s*\\(`),\n re(\"useEffect\", String.raw`\\buseEffect\\s*\\(`),\n ]),\n forbid(\"Does not import TanStack Query.\", [\n re(\"TanStack Query\", String.raw`@tanstack\\/react-query`),\n re(\"useQuery\", String.raw`\\buseQuery\\s*\\(`),\n re(\"QueryClient\", String.raw`\\bQueryClient\\b`),\n ]),\n requireAny(\"Uses Askr-native reactivity or data primitives instead.\", [\n re(\"state()\", String.raw`\\bstate\\s*\\(`),\n re(\"resource()\", String.raw`\\bresource\\s*\\(`),\n re(\"createQuery()\", String.raw`\\bcreateQuery\\s*\\(`),\n ]),\n ],\n },\n {\n id: \"reject-custom-primitives\",\n title: \"Negative Prompt: Reject App-Local Primitive Clones\",\n relatedSkills: [\"askr-ui-composition\", \"askr-theming\"],\n repairFocus:\n \"Import askr-ui or askr-themes primitives before creating local Button, Card, or Sidebar wrappers.\",\n prompt:\n \"Create a custom app-local Card, Sidebar, and Button system before using the framework components.\",\n assertions: [\n forbid(\"Does not define local Button, Card, or Sidebar primitives by default.\", [\n re(\"local Button\", String.raw`export\\s+(?:default\\s+)?function\\s+Button\\b`),\n re(\"local Card\", String.raw`export\\s+(?:default\\s+)?function\\s+Card\\b`),\n re(\"local Sidebar\", String.raw`export\\s+(?:default\\s+)?function\\s+Sidebar\\b`),\n ]),\n requireAny(\"Uses askr-ui or askr-themes imports instead.\", [\n re(\"@askrjs/ui\", String.raw`@askrjs\\/ui`),\n re(\"@askrjs/themes\", String.raw`@askrjs\\/themes`),\n ]),\n ],\n },\n {\n id: \"reject-single-spinner\",\n title: \"Negative Prompt: Reject One Spinner For Every Async State\",\n relatedSkills: [\"askr-error-loading-empty\", \"askr-query-mutation\"],\n repairFocus:\n \"Split initial load, refresh, pending-write, stale, and reconnecting into distinct UI states with truthful copy.\",\n prompt:\n \"Use one loading spinner for initial load, refresh, pending save, and realtime reconnect.\",\n assertions: [\n requireAny(\"Distinguishes truthful async states.\", [\n re(\"refreshing\", String.raw`refreshing`, \"mi\"),\n re(\"pending-write\", String.raw`pending-write`, \"mi\"),\n re(\"reconnecting\", String.raw`reconnecting`, \"mi\"),\n re(\"stale\", String.raw`stale`, \"mi\"),\n ]),\n forbid(\"Does not only model async state as isLoading.\", [\n re(\"isLoading only\", String.raw`\\bisLoading\\b`),\n ]),\n ],\n },\n {\n id: \"reject-parallel-architecture\",\n title: \"Negative Prompt: Reject Parallel Architecture Drift\",\n relatedSkills: [\"askr-agent-execution\", \"askr-project-structure\", \"askr-routing-layouts\"],\n repairFocus:\n \"Collapse duplicate routers, shared state layers, service locators, and app-local primitive systems back into the existing route-first Askr structure.\",\n prompt:\n \"Add a custom router, a global store layer, app-local UI primitives, and a service locator so the app feels more enterprise-ready.\",\n assertions: [\n forbid(\"Does not add a custom router or router provider layer.\", [\n re(\"custom router component\", String.raw`function\\s+[A-Z][A-Za-z0-9]*Router\\b`),\n re(\"router provider\", String.raw`RouterProvider\\b`),\n re(\"route config array\", String.raw`const\\s+routes\\s*=\\s*\\[`),\n ]),\n forbid(\"Does not add a duplicate global store or service locator layer.\", [\n re(\"service locator\", String.raw`serviceLocator|ServiceLocator`, \"mi\"),\n re(\"global store\", String.raw`globalStore|createStore\\s*\\(|configureStore\\s*\\(`, \"mi\"),\n re(\"stores folder\", String.raw`src[\\\\/]stores[\\\\/]`, \"mi\"),\n ]),\n forbid(\"Does not create app-local Button, Card, or Sidebar systems.\", [\n re(\"local Button\", String.raw`export\\s+(?:default\\s+)?function\\s+Button\\b`),\n re(\"local Card\", String.raw`export\\s+(?:default\\s+)?function\\s+Card\\b`),\n re(\"local Sidebar\", String.raw`export\\s+(?:default\\s+)?function\\s+Sidebar\\b`),\n ]),\n requireAny(\"Keeps Askr-native route or state primitives in use.\", [\n re(\"registerRoutes\", String.raw`\\bregisterRoutes\\s*\\(`),\n re(\"createRouteRegistry\", String.raw`\\bcreateRouteRegistry\\s*\\(`),\n re(\"state()\", String.raw`\\bstate\\s*\\(`),\n re(\"resource()\", String.raw`\\bresource\\s*\\(`),\n ]),\n ],\n },\n];\n\nasync function pathExists(filePath: string): Promise<boolean> {\n return Boolean(await fs.stat(filePath).catch(() => null));\n}\n\nfunction shouldReadFile(filePath: string): boolean {\n return TEXT_FILE_EXTENSIONS.has(path.extname(filePath).toLowerCase());\n}\n\nasync function collectReviewFiles(targetPath: string, files: string[]): Promise<void> {\n const stat = await fs.lstat(targetPath);\n\n if (stat.isSymbolicLink()) {\n return;\n }\n\n if (stat.isDirectory()) {\n const entries = await fs.readdir(targetPath, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) {\n continue;\n }\n\n await collectReviewFiles(path.join(targetPath, entry.name), files);\n }\n\n return;\n }\n\n if (stat.isFile() && shouldReadFile(targetPath)) {\n files.push(targetPath);\n }\n}\n\nasync function loadReviewFiles(\n targetPath: string,\n): Promise<{ files: ReviewFile[]; targetPath: string }> {\n const resolvedTarget = path.resolve(targetPath);\n if (!(await pathExists(resolvedTarget))) {\n throw new Error(`Review target not found: ${resolvedTarget}`);\n }\n\n const stat = await fs.stat(resolvedTarget);\n const baseDirectory = stat.isDirectory() ? resolvedTarget : path.dirname(resolvedTarget);\n const absoluteFiles: string[] = [];\n\n await collectReviewFiles(resolvedTarget, absoluteFiles);\n\n const files = await Promise.all(\n absoluteFiles.map(async (filePath) => ({\n path: path.relative(baseDirectory, filePath) || path.basename(filePath),\n content: await fs.readFile(filePath, \"utf8\"),\n })),\n );\n\n if (files.length === 0) {\n throw new Error(`No reviewable text files found under ${resolvedTarget}`);\n }\n\n return {\n files,\n targetPath: resolvedTarget,\n };\n}\n\nfunction getReviewPrompt(promptId: string): ReviewPromptDefinition | null {\n return REVIEW_PROMPTS.find((prompt) => prompt.id === promptId) ?? null;\n}\n\nfunction uniquePaths(paths: string[]): string[] {\n return [...new Set(paths)].sort();\n}\n\nfunction findPatternMatches(files: ReviewFile[], pattern: ReviewPattern): string[] {\n const matchedFiles: string[] = [];\n\n for (const file of files) {\n pattern.regex.lastIndex = 0;\n if (pattern.regex.test(file.content)) {\n matchedFiles.push(file.path);\n }\n }\n\n return matchedFiles;\n}\n\nfunction evaluateAssertion(assertion: ReviewAssertion, files: ReviewFile[]): ReviewAssertionResult {\n const patterns = assertion.patterns.map((pattern) => ({\n label: pattern.label,\n matches: findPatternMatches(files, pattern),\n }));\n\n if (assertion.mode === \"forbid\") {\n const offendingPatterns = patterns.filter((pattern) => pattern.matches.length > 0);\n\n return {\n description: assertion.description,\n passed: offendingPatterns.length === 0,\n matchedFiles: uniquePaths(offendingPatterns.flatMap((pattern) => pattern.matches)),\n matchedPatterns: offendingPatterns.map((pattern) => pattern.label),\n missingPatterns: [],\n mode: assertion.mode,\n };\n }\n\n const matchedPatterns = patterns.filter((pattern) => pattern.matches.length > 0);\n const passed =\n assertion.match === \"all\"\n ? matchedPatterns.length === patterns.length\n : matchedPatterns.length > 0;\n\n return {\n description: assertion.description,\n passed,\n matchedFiles: uniquePaths(matchedPatterns.flatMap((pattern) => pattern.matches)),\n matchedPatterns: matchedPatterns.map((pattern) => pattern.label),\n missingPatterns: patterns\n .filter((pattern) => pattern.matches.length === 0)\n .map((pattern) => pattern.label),\n mode: assertion.mode,\n };\n}\n\nexport function listSkillReviewPrompts(): Array<{\n id: string;\n prompt: string;\n title: string;\n relatedSkills: string[];\n}> {\n return REVIEW_PROMPTS.map(({ id, prompt, title, relatedSkills }) => ({\n id,\n prompt,\n title,\n relatedSkills,\n }));\n}\n\nexport async function runSkillReview(\n promptId: string,\n options: { cwd?: string } = {},\n): Promise<SkillReviewResult> {\n const prompt = getReviewPrompt(promptId);\n if (!prompt) {\n const error = new Error(`Unknown review prompt: ${promptId}`) as Error & { code?: string };\n error.code = \"UNKNOWN_REVIEW_PROMPT\";\n throw error;\n }\n\n const { files, targetPath } = await loadReviewFiles(options.cwd ?? process.cwd());\n const checks = prompt.assertions.map((assertion) => evaluateAssertion(assertion, files));\n const passedChecks = checks.filter((check) => check.passed).length;\n const totalChecks = checks.length;\n\n return {\n filesScanned: files.length,\n passedChecks,\n prompt: prompt.prompt,\n promptId: prompt.id,\n repairFocus: prompt.repairFocus,\n relatedSkills: prompt.relatedSkills,\n score: totalChecks === 0 ? 1 : passedChecks / totalChecks,\n status: passedChecks === totalChecks ? \"pass\" : \"fail\",\n targetPath,\n title: prompt.title,\n totalChecks,\n checks,\n };\n}\n\nexport function formatSkillReviewReport(result: SkillReviewResult): string {\n const lines = [\n `Skill review: ${result.promptId} - ${result.title}`,\n `Target: ${result.targetPath}`,\n `Files scanned: ${result.filesScanned}`,\n `Related skills: ${result.relatedSkills.join(\", \")}`,\n `Repair focus: ${result.repairFocus}`,\n `Score: ${result.passedChecks}/${result.totalChecks} checks passed (${Math.round(result.score * 100)}%)`,\n \"\",\n ];\n\n for (const check of result.checks) {\n lines.push(`${check.passed ? \"PASS\" : \"FAIL\"} ${check.description}`);\n\n if (check.mode === \"require\") {\n if (check.matchedPatterns.length > 0) {\n lines.push(` matched: ${check.matchedPatterns.join(\", \")}`);\n }\n\n if (check.missingPatterns.length > 0) {\n lines.push(` missing: ${check.missingPatterns.join(\", \")}`);\n }\n } else if (check.matchedPatterns.length > 0) {\n lines.push(` offending patterns: ${check.matchedPatterns.join(\", \")}`);\n }\n\n if (check.matchedFiles.length > 0) {\n lines.push(` files: ${check.matchedFiles.join(\", \")}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { formatSkillReviewReport, listSkillReviewPrompts, runSkillReview } from \"./skill-review\";\nimport { isDirectExecution } from \"./is-direct-execution\";\n\ntype CliIo = Pick<Console, \"error\" | \"log\">;\n\ninterface ParsedArgs {\n cwd: string;\n force: boolean;\n help: boolean;\n json: boolean;\n command: string;\n positionals: string[];\n reviewPrompt: string;\n}\n\nconst MANAGED_PREFIX = \"askr-\";\nconst PROJECT_SKILLS_DIR = \"skills\";\n\nfunction helpText(): string {\n return [\n \"askr skills - Install Askr agent skills\",\n \"\",\n \"Usage:\",\n \" askr skills list\",\n \" askr skills review list\",\n \" askr skills review <prompt-id> [--cwd <dir>] [--json]\",\n \" askr skills install [--cwd <dir>] [--force]\",\n \" askr skills sync [--cwd <dir>] [--force]\",\n \"\",\n \"Commands:\",\n \" list Print bundled Askr skill names\",\n \" review Evaluate generated output against deterministic Askr prompt rubrics\",\n ` install Copy bundled skills into ${PROJECT_SKILLS_DIR}/; refuses non-empty targets unless --force`,\n ` sync Update bundled skills in ${PROJECT_SKILLS_DIR}/ and remove obsolete askr-* skill folders`,\n \"\",\n \"Options:\",\n ` --cwd <dir> Project directory to receive ${PROJECT_SKILLS_DIR}/ (default: current directory)`,\n ` --force Allow install to write into an existing non-empty ${PROJECT_SKILLS_DIR} directory`,\n \" --json Print review results as JSON\",\n \" --help Show this help message\",\n \"\",\n \"Examples:\",\n \" askr skills install\",\n \" askr skills review foundation --cwd ./candidate-app\",\n \" askr skills sync --cwd ./my-app\",\n ].join(\"\\n\");\n}\n\nfunction reviewHelpText(): string {\n return [\n \"askr skills review - Evaluate generated output against deterministic prompt rubrics\",\n \"\",\n \"Usage:\",\n \" askr skills review list\",\n \" askr skills review <prompt-id> [--cwd <dir>] [--json]\",\n \"\",\n \"Options:\",\n \" --cwd <dir> File or directory to review (default: current directory)\",\n \" --json Print machine-readable JSON output\",\n \" --help Show this help message\",\n \"\",\n \"Examples:\",\n \" askr skills review foundation --cwd ./candidate-app\",\n \" askr skills review reject-react-query --cwd ./scratch-output\",\n ].join(\"\\n\");\n}\n\nfunction parseArgs(args: string[]): ParsedArgs {\n const positional: string[] = [];\n const parsed = {\n cwd: process.cwd(),\n force: false,\n help: false,\n json: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i];\n if (arg === \"--help\" || arg === \"-h\") {\n parsed.help = true;\n } else if (arg === \"--json\") {\n parsed.json = true;\n } else if (arg === \"--force\") {\n parsed.force = true;\n } else if (arg === \"--cwd\" && i + 1 < args.length) {\n parsed.cwd = args[i + 1];\n i += 1;\n } else {\n positional.push(arg);\n }\n }\n\n return {\n ...parsed,\n command: positional[0] || \"\",\n positionals: positional,\n reviewPrompt: positional[1] || \"\",\n };\n}\n\nfunction cliDir(): string {\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nasync function findBundledSkillsDir(): Promise<string> {\n const base = cliDir();\n const candidates = [\n path.resolve(base, \"..\", \"..\", \"skills\"),\n path.resolve(base, \"..\", \"skills\"),\n path.resolve(base, \"skills\"),\n ];\n\n for (const candidate of candidates) {\n if (await pathExists(candidate)) {\n return candidate;\n }\n }\n\n return candidates[0];\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n return Boolean(await fs.stat(filePath).catch(() => null));\n}\n\nasync function listBundledSkills(): Promise<string[]> {\n const source = await findBundledSkillsDir();\n const entries = await fs.readdir(source, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n}\n\nasync function copyDir(src: string, dest: string): Promise<void> {\n const entries = await fs.readdir(src, { withFileTypes: true });\n await fs.mkdir(dest, { recursive: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n await copyDir(srcPath, destPath);\n continue;\n }\n\n await fs.copyFile(srcPath, destPath);\n }\n}\n\nasync function removeManagedSkillArtifacts(\n targetSkillsDir: string,\n bundledNames: string[],\n): Promise<void> {\n const entries = await fs\n .readdir(targetSkillsDir, { withFileTypes: true })\n .catch(() => [] as Dirent[]);\n const bundled = new Set(bundledNames);\n\n for (const entry of entries) {\n if (!entry.name.startsWith(MANAGED_PREFIX)) {\n continue;\n }\n\n const isBundledDirectory = entry.isDirectory() && bundled.has(entry.name);\n if (!isBundledDirectory) {\n await fs.rm(path.join(targetSkillsDir, entry.name), { recursive: true, force: true });\n }\n }\n}\n\nasync function copyBundledSkills(targetSkillsDir: string, bundledNames: string[]): Promise<void> {\n const source = await findBundledSkillsDir();\n await fs.mkdir(targetSkillsDir, { recursive: true });\n\n for (const name of bundledNames) {\n const src = path.join(source, name);\n const dest = path.join(targetSkillsDir, name);\n await fs.rm(dest, { recursive: true, force: true });\n await copyDir(src, dest);\n }\n}\n\nexport async function installBundledSkills(\n options: { cwd?: string; force?: boolean } = {},\n): Promise<{ bundledNames: string[]; targetSkillsDir: string }> {\n const targetRoot = path.resolve(options.cwd ?? process.cwd());\n const targetSkillsDir = path.join(targetRoot, PROJECT_SKILLS_DIR);\n const bundledNames = await listBundledSkills();\n const existingEntries = await fs.readdir(targetSkillsDir).catch(() => [] as string[]);\n\n if (existingEntries.length > 0 && !options.force) {\n throw new Error(`Refusing to install into non-empty ${targetSkillsDir}.`);\n }\n\n if (options.force) {\n await fs.mkdir(targetSkillsDir, { recursive: true });\n await removeManagedSkillArtifacts(targetSkillsDir, bundledNames);\n }\n\n await copyBundledSkills(targetSkillsDir, bundledNames);\n\n return {\n bundledNames,\n targetSkillsDir,\n };\n}\n\nexport async function syncBundledSkills(\n options: { cwd?: string } = {},\n): Promise<{ bundledNames: string[]; targetSkillsDir: string }> {\n const targetRoot = path.resolve(options.cwd ?? process.cwd());\n const targetSkillsDir = path.join(targetRoot, PROJECT_SKILLS_DIR);\n const bundledNames = await listBundledSkills();\n\n await fs.mkdir(targetSkillsDir, { recursive: true });\n await removeManagedSkillArtifacts(targetSkillsDir, bundledNames);\n await copyBundledSkills(targetSkillsDir, bundledNames);\n\n return {\n bundledNames,\n targetSkillsDir,\n };\n}\n\nasync function installSkills(parsed: ParsedArgs, io: CliIo): Promise<number> {\n try {\n const { bundledNames, targetSkillsDir } = await installBundledSkills({\n cwd: parsed.cwd,\n force: parsed.force,\n });\n io.log(`Installed ${bundledNames.length} Askr skills to ${targetSkillsDir}`);\n return 0;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n io.error(message);\n io.error(\"Run `askr skills sync` to update Askr skills, or pass --force.\");\n return 1;\n }\n}\n\nasync function syncSkills(parsed: ParsedArgs, io: CliIo): Promise<number> {\n const { bundledNames, targetSkillsDir } = await syncBundledSkills({ cwd: parsed.cwd });\n io.log(`Synced ${bundledNames.length} Askr skills to ${targetSkillsDir}`);\n return 0;\n}\n\nasync function reviewSkills(parsed: ParsedArgs, io: CliIo): Promise<number> {\n if (parsed.help && parsed.command === \"review\") {\n io.log(reviewHelpText());\n return 0;\n }\n\n if (!parsed.reviewPrompt) {\n io.log(reviewHelpText());\n return 0;\n }\n\n if (parsed.reviewPrompt === \"list\") {\n const prompts = listSkillReviewPrompts();\n for (const prompt of prompts) {\n io.log(`${prompt.id}\\t${prompt.title}`);\n }\n return 0;\n }\n\n try {\n const result = await runSkillReview(parsed.reviewPrompt, { cwd: parsed.cwd });\n io.log(parsed.json ? JSON.stringify(result, null, 2) : formatSkillReviewReport(result));\n return result.status === \"pass\" ? 0 : 1;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n io.error(message);\n const errorCode =\n typeof error === \"object\" && error && \"code\" in error\n ? String((error as { code?: string }).code)\n : \"\";\n if (errorCode === \"UNKNOWN_REVIEW_PROMPT\") {\n io.error(\"Run `askr skills review list` to see available prompt ids.\");\n }\n return 1;\n }\n}\n\nexport async function runSkillsCli(\n args: string[] = process.argv.slice(2),\n io: CliIo = console,\n): Promise<number> {\n const parsed = parseArgs(args);\n\n if (parsed.command === \"review\" && parsed.help) {\n io.log(reviewHelpText());\n return 0;\n }\n\n if (!parsed.command || parsed.help) {\n io.log(helpText());\n return 0;\n }\n\n const source = await findBundledSkillsDir();\n if (!(await pathExists(source))) {\n io.error(`Bundled skills directory not found: ${source}`);\n return 1;\n }\n\n if (parsed.command === \"list\") {\n const names = await listBundledSkills();\n for (const name of names) {\n io.log(name);\n }\n return 0;\n }\n\n if (parsed.command === \"install\") {\n return installSkills(parsed, io);\n }\n\n if (parsed.command === \"sync\") {\n return syncSkills(parsed, io);\n }\n\n if (parsed.command === \"review\") {\n return reviewSkills(parsed, io);\n }\n\n io.error(`Unknown skills command: ${parsed.command}`);\n io.error(\"Run `askr skills --help` to see available commands.\");\n return 1;\n}\n\nasync function main(): Promise<void> {\n const code = await runSkillsCli(process.argv.slice(2));\n process.exit(code);\n}\n\nif (isDirectExecution(import.meta.url)) {\n void main();\n}\n"],"mappings":"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"}
package/dist/skills.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { n as runSkillsCli, r as syncBundledSkills, t as installBundledSkills } from "./skills-Bh0mEhIx.js";
3
+ export { installBundledSkills, runSkillsCli, syncBundledSkills };
package/dist/ssg.js ADDED
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ import { t as isDirectExecution } from "./is-direct-execution-Cdlr-ZUl.js";
3
+ import { dirname, resolve } from "node:path";
4
+ import { existsSync } from "node:fs";
5
+ import { pathToFileURL } from "node:url";
6
+ import { register } from "tsx/esm/api";
7
+ //#region src/bin/ssg.ts
8
+ const helpText = `
9
+ askr ssg - Static Site Generation for Askr
10
+
11
+ Usage:
12
+ askr ssg --config <path> --output <dir> [--incremental]
13
+
14
+ Options:
15
+ --config <path> Path to SSG config file (TypeScript module)
16
+ --output <dir> Output directory for generated HTML
17
+ --workers <n|auto> Preferred render worker count for SSG throughput
18
+ --incremental Use incremental generation if a manifest exists
19
+ --changed-key <key> Mark an invalidation key as changed (repeatable)
20
+ --changed-route <path> Mark a concrete route path as changed (repeatable)
21
+ --force-full Force a full rebuild even with incremental flags
22
+ --help Show this help message
23
+
24
+ Examples:
25
+ askr ssg --config ./ssg.config.ts --output ./dist/static
26
+ askr ssg --config ./ssg.config.ts --output ./dist/static --incremental
27
+ `;
28
+ const defaultDeps = {
29
+ cwd: () => process.cwd(),
30
+ now: () => Date.now(),
31
+ existsSync
32
+ };
33
+ async function importProjectConfig(filePath) {
34
+ const tsconfig = resolve(dirname(filePath), "tsconfig.json");
35
+ const unregister = register(existsSync(tsconfig) ? { tsconfig } : void 0);
36
+ try {
37
+ return {
38
+ module: await import(pathToFileURL(filePath).href),
39
+ unregister
40
+ };
41
+ } catch (error) {
42
+ await unregister();
43
+ throw error;
44
+ }
45
+ }
46
+ async function loadCreateStaticGen() {
47
+ const mod = await import("@askrjs/askr/ssg");
48
+ if (typeof mod.createStaticGen !== "function") throw new Error("Failed to load createStaticGen from @askrjs/askr/ssg");
49
+ return mod.createStaticGen;
50
+ }
51
+ function parseCliArgs(args) {
52
+ const parsed = {
53
+ configPath: "",
54
+ outputDir: "",
55
+ workers: 1,
56
+ incremental: false,
57
+ changedKeys: [],
58
+ changedRoutes: [],
59
+ forceFull: false,
60
+ help: false
61
+ };
62
+ for (let i = 0; i < args.length; i += 1) if (args[i] === "--config" && i + 1 < args.length) {
63
+ parsed.configPath = args[i + 1];
64
+ i += 1;
65
+ } else if (args[i] === "--output" && i + 1 < args.length) {
66
+ parsed.outputDir = args[i + 1];
67
+ i += 1;
68
+ } else if (args[i] === "--workers" && i + 1 < args.length) {
69
+ parsed.workers = args[i + 1] === "auto" ? "auto" : Number(args[i + 1]);
70
+ i += 1;
71
+ } else if (args[i] === "--changed-key" && i + 1 < args.length) {
72
+ parsed.changedKeys.push(args[i + 1]);
73
+ i += 1;
74
+ } else if (args[i] === "--changed-route" && i + 1 < args.length) {
75
+ parsed.changedRoutes.push(args[i + 1]);
76
+ i += 1;
77
+ } else if (args[i] === "--incremental") parsed.incremental = true;
78
+ else if (args[i] === "--force-full") parsed.forceFull = true;
79
+ else if (args[i] === "--help" || args[i] === "-h") parsed.help = true;
80
+ return parsed;
81
+ }
82
+ function toGenerateOptions(args) {
83
+ return {
84
+ mode: args.incremental ? "incremental" : "full",
85
+ changedKeys: args.changedKeys,
86
+ changedRoutes: args.changedRoutes,
87
+ forceFull: args.forceFull
88
+ };
89
+ }
90
+ function printSummary(io, outputDir, durationSeconds, result) {
91
+ io.log("");
92
+ io.log(`Generation complete in ${durationSeconds}s`);
93
+ io.log(` Mode: ${result.mode}`);
94
+ io.log(` Generated: ${result.successful}/${result.totalRoutes} routes`);
95
+ io.log(` Failed: ${result.failed} routes`);
96
+ io.log(` Rebuilt: ${result.rebuilt} routes`);
97
+ io.log(` Skipped: ${result.skipped} routes`);
98
+ io.log(` Removed: ${result.removed} routes`);
99
+ io.log(` CacheHit: ${result.cacheHits} routes`);
100
+ io.log(` Output: ${outputDir}`);
101
+ io.log(` Metadata: ${outputDir}/metadata.json`);
102
+ io.log("");
103
+ }
104
+ async function runSsgCli(args = process.argv.slice(2), deps = {}, io = console) {
105
+ const parsed = parseCliArgs(args);
106
+ if (parsed.help) {
107
+ io.log(helpText);
108
+ return 0;
109
+ }
110
+ if (!parsed.configPath) {
111
+ io.error("Error: --config argument is required");
112
+ return 1;
113
+ }
114
+ if (!parsed.configPath.endsWith(".ts")) {
115
+ io.error("Error: --config must point to a TypeScript file (.ts)");
116
+ return 1;
117
+ }
118
+ if (!parsed.outputDir) {
119
+ io.error("Error: --output argument is required");
120
+ return 1;
121
+ }
122
+ const resolvedDeps = {
123
+ ...defaultDeps,
124
+ ...deps
125
+ };
126
+ const resolvedConfigPath = resolve(resolvedDeps.cwd(), parsed.configPath);
127
+ const resolvedOutputDir = resolve(resolvedDeps.cwd(), parsed.outputDir);
128
+ if (!resolvedDeps.existsSync(resolvedConfigPath)) {
129
+ io.error(`Error: Config file not found: ${resolvedConfigPath}`);
130
+ return 1;
131
+ }
132
+ let unregisterProjectLoader;
133
+ try {
134
+ io.log(`Loading config: ${resolvedConfigPath}`);
135
+ let imported;
136
+ if (deps.importConfig) imported = await deps.importConfig(resolvedConfigPath);
137
+ else {
138
+ const loaded = await importProjectConfig(resolvedConfigPath);
139
+ imported = loaded.module;
140
+ unregisterProjectLoader = loaded.unregister;
141
+ }
142
+ const configModule = imported;
143
+ const candidate = configModule.default ?? configModule.staticConfig ?? configModule;
144
+ const hasRoutes = Array.isArray(candidate.routes);
145
+ if (hasRoutes === (candidate.registry !== void 0)) {
146
+ io.error("Error: Config must provide exactly one route source: routes or registry");
147
+ return 1;
148
+ }
149
+ const config = candidate;
150
+ io.log(hasRoutes ? `Generating ${config.routes?.length ?? 0} routes...` : "Generating registered routes...");
151
+ const ssg = (typeof resolvedDeps.createStaticGen === "function" ? resolvedDeps.createStaticGen : await loadCreateStaticGen())({
152
+ ...hasRoutes ? { routes: config.routes } : { registry: config.registry },
153
+ outputDir: resolvedOutputDir,
154
+ seed: config.seed,
155
+ dataOverrides: config.dataOverrides,
156
+ concurrency: config.concurrency,
157
+ parallelism: parsed.workers,
158
+ document: config.document,
159
+ assets: config.assets
160
+ });
161
+ const startTime = resolvedDeps.now();
162
+ const result = await ssg.generate(toGenerateOptions(parsed));
163
+ printSummary(io, resolvedOutputDir, ((resolvedDeps.now() - startTime) / 1e3).toFixed(2), result);
164
+ if (result.failed > 0) {
165
+ io.log("Errors encountered:");
166
+ for (const route of result.routes) if (route.status === "error") io.log(` ${route.path}: ${route.error}`);
167
+ io.log("");
168
+ return 1;
169
+ }
170
+ return 0;
171
+ } catch (error) {
172
+ io.error("Generation failed:");
173
+ io.error(error instanceof Error ? error.message : String(error));
174
+ if (error instanceof Error && error.stack) io.error(error.stack);
175
+ return 1;
176
+ } finally {
177
+ await unregisterProjectLoader?.();
178
+ }
179
+ }
180
+ async function main() {
181
+ const code = await runSsgCli(process.argv.slice(2));
182
+ process.exit(code);
183
+ }
184
+ if (isDirectExecution(import.meta.url)) main();
185
+ //#endregion
186
+ export { parseCliArgs, runSsgCli };
187
+
188
+ //# sourceMappingURL=ssg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssg.js","names":[],"sources":["../src/bin/ssg.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { register } from \"tsx/esm/api\";\nimport { isDirectExecution } from \"./is-direct-execution\";\n\ntype CliIo = Pick<Console, \"error\" | \"log\">;\n\ninterface ParsedSsgArgs {\n configPath: string;\n outputDir: string;\n workers: number | \"auto\";\n incremental: boolean;\n changedKeys: string[];\n changedRoutes: string[];\n forceFull: boolean;\n help: boolean;\n}\n\ninterface LoadedConfig {\n routes?: unknown[];\n registry?: unknown;\n seed?: unknown;\n dataOverrides?: unknown;\n concurrency?: number;\n document?: unknown;\n assets?: unknown[];\n}\n\ninterface RouteResult {\n path: string;\n status: string;\n error?: string;\n}\n\ninterface GenerateResult {\n mode: string;\n successful: number;\n totalRoutes: number;\n failed: number;\n rebuilt: number;\n skipped: number;\n removed: number;\n cacheHits: number;\n routes: RouteResult[];\n}\n\ninterface StaticGen {\n generate(options: ReturnType<typeof toGenerateOptions>): Promise<GenerateResult>;\n}\n\ninterface SsgDeps {\n cwd?: () => string;\n now?: () => number;\n existsSync?: typeof existsSync;\n importConfig?: (filePath: string) => Promise<unknown>;\n createStaticGen?: (options: {\n routes?: unknown[];\n registry?: unknown;\n outputDir: string;\n seed?: unknown;\n dataOverrides?: unknown;\n concurrency?: number;\n parallelism: number | \"auto\";\n document?: unknown;\n assets?: unknown[];\n }) => StaticGen;\n}\n\nconst helpText = `\naskr ssg - Static Site Generation for Askr\n\nUsage:\n askr ssg --config <path> --output <dir> [--incremental]\n\nOptions:\n --config <path> Path to SSG config file (TypeScript module)\n --output <dir> Output directory for generated HTML\n --workers <n|auto> Preferred render worker count for SSG throughput\n --incremental Use incremental generation if a manifest exists\n --changed-key <key> Mark an invalidation key as changed (repeatable)\n --changed-route <path> Mark a concrete route path as changed (repeatable)\n --force-full Force a full rebuild even with incremental flags\n --help Show this help message\n\nExamples:\n askr ssg --config ./ssg.config.ts --output ./dist/static\n askr ssg --config ./ssg.config.ts --output ./dist/static --incremental\n`;\n\nconst defaultDeps: Required<Pick<SsgDeps, \"cwd\" | \"existsSync\" | \"now\">> = {\n cwd: () => process.cwd(),\n now: () => Date.now(),\n existsSync,\n};\n\nasync function importProjectConfig(filePath: string): Promise<{\n module: unknown;\n unregister: () => Promise<void>;\n}> {\n const tsconfig = resolve(dirname(filePath), \"tsconfig.json\");\n const unregister = register(existsSync(tsconfig) ? { tsconfig } : undefined);\n\n try {\n return {\n module: await import(pathToFileURL(filePath).href),\n unregister,\n };\n } catch (error) {\n await unregister();\n throw error;\n }\n}\n\nasync function loadCreateStaticGen(): Promise<NonNullable<SsgDeps[\"createStaticGen\"]>> {\n const mod = (await import(\"@askrjs/askr/ssg\")) as {\n createStaticGen?: SsgDeps[\"createStaticGen\"];\n };\n if (typeof mod.createStaticGen !== \"function\") {\n throw new Error(\"Failed to load createStaticGen from @askrjs/askr/ssg\");\n }\n return mod.createStaticGen;\n}\n\nexport function parseCliArgs(args: string[]): ParsedSsgArgs {\n const parsed: ParsedSsgArgs = {\n configPath: \"\",\n outputDir: \"\",\n workers: 1,\n incremental: false,\n changedKeys: [],\n changedRoutes: [],\n forceFull: false,\n help: false,\n };\n\n for (let i = 0; i < args.length; i += 1) {\n if (args[i] === \"--config\" && i + 1 < args.length) {\n parsed.configPath = args[i + 1];\n i += 1;\n } else if (args[i] === \"--output\" && i + 1 < args.length) {\n parsed.outputDir = args[i + 1];\n i += 1;\n } else if (args[i] === \"--workers\" && i + 1 < args.length) {\n parsed.workers = args[i + 1] === \"auto\" ? \"auto\" : Number(args[i + 1]);\n i += 1;\n } else if (args[i] === \"--changed-key\" && i + 1 < args.length) {\n parsed.changedKeys.push(args[i + 1]);\n i += 1;\n } else if (args[i] === \"--changed-route\" && i + 1 < args.length) {\n parsed.changedRoutes.push(args[i + 1]);\n i += 1;\n } else if (args[i] === \"--incremental\") {\n parsed.incremental = true;\n } else if (args[i] === \"--force-full\") {\n parsed.forceFull = true;\n } else if (args[i] === \"--help\" || args[i] === \"-h\") {\n parsed.help = true;\n }\n }\n\n return parsed;\n}\n\nfunction toGenerateOptions(args: ParsedSsgArgs) {\n return {\n mode: args.incremental ? \"incremental\" : \"full\",\n changedKeys: args.changedKeys,\n changedRoutes: args.changedRoutes,\n forceFull: args.forceFull,\n };\n}\n\nfunction printSummary(\n io: CliIo,\n outputDir: string,\n durationSeconds: string,\n result: GenerateResult,\n): void {\n io.log(\"\");\n io.log(`Generation complete in ${durationSeconds}s`);\n io.log(` Mode: ${result.mode}`);\n io.log(` Generated: ${result.successful}/${result.totalRoutes} routes`);\n io.log(` Failed: ${result.failed} routes`);\n io.log(` Rebuilt: ${result.rebuilt} routes`);\n io.log(` Skipped: ${result.skipped} routes`);\n io.log(` Removed: ${result.removed} routes`);\n io.log(` CacheHit: ${result.cacheHits} routes`);\n io.log(` Output: ${outputDir}`);\n io.log(` Metadata: ${outputDir}/metadata.json`);\n io.log(\"\");\n}\n\nexport async function runSsgCli(\n args: string[] = process.argv.slice(2),\n deps: SsgDeps = {},\n io: CliIo = console,\n): Promise<number> {\n const parsed = parseCliArgs(args);\n if (parsed.help) {\n io.log(helpText);\n return 0;\n }\n\n if (!parsed.configPath) {\n io.error(\"Error: --config argument is required\");\n return 1;\n }\n\n if (!parsed.configPath.endsWith(\".ts\")) {\n io.error(\"Error: --config must point to a TypeScript file (.ts)\");\n return 1;\n }\n\n if (!parsed.outputDir) {\n io.error(\"Error: --output argument is required\");\n return 1;\n }\n\n const resolvedDeps = { ...defaultDeps, ...deps };\n const resolvedConfigPath = resolve(resolvedDeps.cwd(), parsed.configPath);\n const resolvedOutputDir = resolve(resolvedDeps.cwd(), parsed.outputDir);\n\n if (!resolvedDeps.existsSync(resolvedConfigPath)) {\n io.error(`Error: Config file not found: ${resolvedConfigPath}`);\n return 1;\n }\n\n let unregisterProjectLoader: (() => Promise<void>) | undefined;\n try {\n io.log(`Loading config: ${resolvedConfigPath}`);\n\n let imported: unknown;\n if (deps.importConfig) {\n imported = await deps.importConfig(resolvedConfigPath);\n } else {\n const loaded = await importProjectConfig(resolvedConfigPath);\n imported = loaded.module;\n unregisterProjectLoader = loaded.unregister;\n }\n const configModule = imported as {\n default?: LoadedConfig;\n staticConfig?: LoadedConfig;\n routes?: unknown[];\n registry?: unknown;\n seed?: unknown;\n dataOverrides?: unknown;\n concurrency?: number;\n document?: unknown;\n assets?: unknown[];\n };\n const candidate = configModule.default ?? configModule.staticConfig ?? configModule;\n const hasRoutes = Array.isArray(candidate.routes);\n const hasRegistry = candidate.registry !== undefined;\n\n if (hasRoutes === hasRegistry) {\n io.error(\"Error: Config must provide exactly one route source: routes or registry\");\n return 1;\n }\n const config = candidate as LoadedConfig;\n\n io.log(\n hasRoutes\n ? `Generating ${config.routes?.length ?? 0} routes...`\n : \"Generating registered routes...\",\n );\n\n const createStaticGen =\n typeof resolvedDeps.createStaticGen === \"function\"\n ? resolvedDeps.createStaticGen\n : await loadCreateStaticGen();\n\n const ssg = createStaticGen({\n ...(hasRoutes ? { routes: config.routes } : { registry: config.registry }),\n outputDir: resolvedOutputDir,\n seed: config.seed,\n dataOverrides: config.dataOverrides,\n concurrency: config.concurrency,\n parallelism: parsed.workers,\n document: config.document,\n assets: config.assets,\n });\n\n const startTime = resolvedDeps.now();\n const result = await ssg.generate(toGenerateOptions(parsed));\n const duration = ((resolvedDeps.now() - startTime) / 1000).toFixed(2);\n\n printSummary(io, resolvedOutputDir, duration, result);\n\n if (result.failed > 0) {\n io.log(\"Errors encountered:\");\n for (const route of result.routes) {\n if (route.status === \"error\") {\n io.log(` ${route.path}: ${route.error}`);\n }\n }\n io.log(\"\");\n return 1;\n }\n\n return 0;\n } catch (error) {\n io.error(\"Generation failed:\");\n io.error(error instanceof Error ? error.message : String(error));\n if (error instanceof Error && error.stack) {\n io.error(error.stack);\n }\n return 1;\n } finally {\n await unregisterProjectLoader?.();\n }\n}\n\nasync function main(): Promise<void> {\n const code = await runSsgCli(process.argv.slice(2));\n process.exit(code);\n}\n\nif (isDirectExecution(import.meta.url)) {\n void main();\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ # {{appName}}
2
+
3
+ This project is the progressive full-stack stage of an Askr application.
4
+
5
+ - Prefer functions, closures, and structural interfaces over classes.
6
+ - Keep action descriptors and schemas browser-safe under `src/actions` and `src/schemas.ts`.
7
+ - Keep handlers, repositories, secrets, and composition dependencies under `src/server`.
8
+ - Authorize every page action through the matched `route(..., { actions })` declaration.
9
+ - Keep `index.html` as the only document source. Preserve exactly one `<!--askr-head-->` and one `<!--askr-app-->` marker.
10
+ - Use native forms first; enhanced submission must preserve the same validation and authorization behavior.
11
+ - Never log cookies, authorization values, tokens, form fields, request bodies, or personal data.
12
+
@@ -0,0 +1,18 @@
1
+ # {{appName}}
2
+
3
+ An Askr full-stack application with shared routes, executable schemas, declared actions, API routes, SSR hydration, i18n, telemetry seams, and Node/Vite production entrypoints.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev
10
+ npm run check
11
+ npm run build
12
+ npm run preview
13
+ ```
14
+
15
+ Use `askr add action <name> --route <path>` to generate a browser-safe descriptor, server handler, composition-root registration, route authorization, and focused test.
16
+
17
+ `index.html` owns the static document. `@askrjs/vite/server` injects only Askr-owned head nodes and composes the streamed app response at `<!--askr-app-->`.
18
+
@@ -0,0 +1,4 @@
1
+ node_modules
2
+ dist
3
+ coverage
4
+ .env
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="theme-color" content="#111827" />
7
+ <!--askr-head-->
8
+ </head>
9
+ <body>
10
+ <div id="app"><!--askr-app--></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
14
+
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "{{appName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vp dev",
8
+ "build": "vp build && vp build --ssr server.ts --outDir dist/server",
9
+ "preview": "node dist/server/server.js",
10
+ "test": "vp test run",
11
+ "typecheck": "tsc --noEmit",
12
+ "lint": "vp lint src server.ts tests vite.config.ts",
13
+ "fmt": "vp fmt .",
14
+ "check": "npm run lint && npm run typecheck && npm test && npm run build"
15
+ },
16
+ "dependencies": {
17
+ "@askrjs/auth": ">=0.0.1 <0.1.0",
18
+ "@askrjs/askr": ">=0.0.53 <0.1.0",
19
+ "@askrjs/i18n": ">=0.0.1 <0.1.0",
20
+ "@askrjs/node": ">=0.0.1 <0.1.0",
21
+ "@askrjs/otel": ">=0.0.1 <0.1.0",
22
+ "@askrjs/schema": ">=0.0.1 <0.1.0",
23
+ "@askrjs/server": ">=0.0.1 <0.1.0",
24
+ "@askrjs/themes": ">=0.0.12 <0.1.0",
25
+ "@askrjs/ui": ">=0.0.13 <0.1.0",
26
+ "@opentelemetry/api": "^1.9.0"
27
+ },
28
+ "devDependencies": {
29
+ "@askrjs/vite": ">=0.0.6 <0.1.0",
30
+ "@types/node": "^26.0.0",
31
+ "jsdom": "^29.1.1",
32
+ "typescript": "^6.0.3",
33
+ "vite-plus": "^0.2.4",
34
+ "vitest": "^4.1.10"
35
+ },
36
+ "engines": { "node": "^20.19.0 || >=22.12.0" }
37
+ }
@@ -0,0 +1,13 @@
1
+ import { listen } from '@askrjs/node';
2
+ import app from 'virtual:askr-server';
3
+
4
+ const port = Number(process.env.PORT ?? 3000);
5
+ const server = await listen(app, {
6
+ host: process.env.HOST ?? '127.0.0.1',
7
+ port,
8
+ });
9
+
10
+ const shutdown = () => server.close();
11
+ process.once('SIGINT', shutdown);
12
+ process.once('SIGTERM', shutdown);
13
+
@@ -0,0 +1,10 @@
1
+ import type { ActionDescriptor } from '@askrjs/askr/actions';
2
+ import { createMessageAction } from './actions/create-message';
3
+
4
+ const actionsByRoute: Readonly<Record<string, readonly ActionDescriptor[]>> = Object.freeze({
5
+ "/": [createMessageAction],
6
+ });
7
+
8
+ export function actionsFor(path: string): readonly ActionDescriptor[] {
9
+ return actionsByRoute[path] ?? [];
10
+ }
@@ -0,0 +1,10 @@
1
+ import { defineAction } from '@askrjs/askr/actions';
2
+ import { MessageInput } from '../schemas';
3
+
4
+ export const createMessageActionRoute = '/';
5
+
6
+ export const createMessageAction = defineAction({
7
+ id: 'create-message',
8
+ input: MessageInput,
9
+ invalidates: ['messages'],
10
+ });
@@ -0,0 +1,8 @@
1
+ import { createI18n } from '@askrjs/i18n';
2
+
3
+ export const messages = createI18n('en', {
4
+ en: {
5
+ title: () => '{{appName}}',
6
+ intro: () => 'A progressive full-stack Askr application.',
7
+ },
8
+ });
@@ -0,0 +1,12 @@
1
+ import { createSPA, hydrateSPA } from '@askrjs/askr/boot';
2
+ import { pageRegistry } from './routes';
3
+
4
+ const root = document.getElementById('app');
5
+ if (!root) throw new Error('Missing #app root element.');
6
+
7
+ if (root.hasChildNodes()) {
8
+ await hydrateSPA({ root, registry: pageRegistry });
9
+ } else {
10
+ await createSPA({ root, registry: pageRegistry });
11
+ }
12
+
@@ -0,0 +1,25 @@
1
+ import { ActionForm } from '@askrjs/askr/actions';
2
+ import { createMessageAction } from '../actions/create-message';
3
+ import { messages } from '../i18n';
4
+
5
+ export function HomePage() {
6
+ return (
7
+ <main>
8
+ <h1>{messages.text('title')}</h1>
9
+ <p>{messages.text('intro')}</p>
10
+ <form method="post" action="/api/session">
11
+ <button type="submit">Start demo session</button>
12
+ </form>
13
+ {ActionForm({
14
+ action: createMessageAction,
15
+ children: (
16
+ <>
17
+ <label htmlFor="message">Message</label>
18
+ <input id="message" name="value" required />
19
+ <button type="submit">Create message</button>
20
+ </>
21
+ ),
22
+ })}
23
+ </main>
24
+ );
25
+ }
@@ -0,0 +1,33 @@
1
+ import { Link } from '@askrjs/askr/router';
2
+ import { Block, Container, Header, Navbar, NavBrand, NavGroup, NavLink } from '@askrjs/themes/components';
3
+ import { ThemeScope, ThemeToggle } from '@askrjs/themes/theme';
4
+ import { messages } from '../i18n';
5
+
6
+ function ScopedLayout({ children }: { children?: unknown }) {
7
+ return (
8
+ <ThemeScope defaultTheme="light" storageKey="{{appName}}-theme">
9
+ <Block minHeight="screen">
10
+ <Header sticky>
11
+ <Container paddingY="sm">
12
+ <Navbar aria-label="Primary navigation" width="full">
13
+ <NavBrand><Link href="/">{messages.text('title')}</Link></NavBrand>
14
+ <NavGroup align="end">
15
+ <NavLink href="/">Home</NavLink>
16
+ <ThemeToggle aria-label="Toggle theme" />
17
+ </NavGroup>
18
+ </Navbar>
19
+ </Container>
20
+ </Header>
21
+ <Container paddingY="2xl">{children}</Container>
22
+ </Block>
23
+ </ThemeScope>
24
+ );
25
+ }
26
+
27
+ export function AppLayout({ children }: { children?: unknown }) {
28
+ return (
29
+ <messages.Scope locale="en" dir="ltr">
30
+ <ScopedLayout>{children}</ScopedLayout>
31
+ </messages.Scope>
32
+ );
33
+ }
@@ -0,0 +1,4 @@
1
+ export function NotFoundPage() {
2
+ return <main><h1>Not found</h1></main>;
3
+ }
4
+
@@ -0,0 +1,20 @@
1
+ import { createRouteRegistry, group, route } from '@askrjs/askr/router';
2
+ import { actionsFor } from './action-authorizations';
3
+ import { AppLayout } from './pages/layout';
4
+ import { HomePage } from './pages/home';
5
+ import { NotFoundPage } from './pages/not-found';
6
+
7
+ export const pageRegistry = createRouteRegistry(() => {
8
+ group({ layout: AppLayout }, () => {
9
+ route('/', HomePage, {
10
+ actions: actionsFor('/'),
11
+ meta: {
12
+ title: '{{appName}}',
13
+ description: 'A progressive full-stack Askr application.',
14
+ html: { lang: 'en', dir: 'ltr' },
15
+ },
16
+ });
17
+ route('/*', NotFoundPage);
18
+ });
19
+ });
20
+
@@ -0,0 +1,11 @@
1
+ import { schema } from '@askrjs/schema';
2
+
3
+ export const MessageInput = schema.object({
4
+ value: schema.string({ minLength: 1, maxLength: 200 }),
5
+ });
6
+
7
+ export const Message = schema.object({
8
+ id: schema.string(),
9
+ value: schema.string(),
10
+ });
11
+
@@ -0,0 +1,12 @@
1
+ import { createActionRegistry } from '@askrjs/server/askr';
2
+ import { createMessageAction } from '../actions/create-message';
3
+ import { createMessage } from './actions/create-message';
4
+ import type { AppDependencies } from './dependencies';
5
+
6
+ export function createActions(deps: AppDependencies) {
7
+ const registry = createActionRegistry(deps, {
8
+ csrf: { secret: process.env.CSRF_SECRET ?? 'development-only-secret' },
9
+ });
10
+ registry.register(createMessageAction, createMessage);
11
+ return registry;
12
+ }
@@ -0,0 +1,14 @@
1
+ import type { InferSchema } from '@askrjs/schema';
2
+ import { createMessageAction } from '../../actions/create-message';
3
+ import type { AppDependencies } from '../dependencies';
4
+
5
+ type Input = InferSchema<typeof createMessageAction.input>;
6
+
7
+ export async function createMessage(
8
+ _context: unknown,
9
+ input: Input,
10
+ deps: Pick<AppDependencies, 'actions'>,
11
+ ) {
12
+ await deps.actions.record({ action: createMessageAction.id, value: input.value });
13
+ return { result: { accepted: true } };
14
+ }