@askrjs/cli 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/README.md +46 -7
  2. package/dist/add.d.ts +16 -0
  3. package/dist/add.js +558 -1
  4. package/dist/cli.d.ts +5 -0
  5. package/dist/cli.js +43 -16
  6. package/dist/create.d.ts +5 -0
  7. package/dist/create.js +104 -26
  8. package/dist/directory-swap-DWoHtx7C.js +35 -0
  9. package/dist/discovery-Difb7Y4G.js +323 -0
  10. package/dist/generate.d.ts +5 -0
  11. package/dist/generate.js +461 -0
  12. package/dist/is-direct-execution-Cdlr-ZUl.js +0 -2
  13. package/dist/openapi.d.ts +25 -0
  14. package/dist/openapi.js +49 -16
  15. package/dist/planner-VAj7qlxr.js +285 -0
  16. package/dist/range-YUs9eimn.js +125 -0
  17. package/dist/registry-CyrRHRG5.js +209 -0
  18. package/dist/skills/askr-dashboard-charts/SKILL.md +61 -44
  19. package/dist/skills/askr-dashboard-charts/agents/openai.yaml +2 -2
  20. package/dist/skills/askr-ssr-ssg/SKILL.md +3 -1
  21. package/dist/{skills-Bh0mEhIx.js → skills-B7CbWur9.js} +89 -26
  22. package/dist/skills.d.ts +18 -0
  23. package/dist/skills.js +1 -1
  24. package/dist/specification-DXnDOC-0.js +49 -0
  25. package/dist/ssg-config.d.ts +41 -0
  26. package/dist/ssg-config.js +1 -0
  27. package/dist/ssg.d.ts +61 -0
  28. package/dist/ssg.js +360 -24
  29. package/dist/templates/full-stack/AGENTS.md +0 -1
  30. package/dist/templates/full-stack/README.md +0 -1
  31. package/dist/templates/full-stack/index.html +0 -1
  32. package/dist/templates/full-stack/package.json +5 -3
  33. package/dist/templates/full-stack/server.ts +5 -9
  34. package/dist/templates/full-stack/src/action-authorizations.ts +2 -2
  35. package/dist/templates/full-stack/src/actions/create-message.ts +5 -5
  36. package/dist/templates/full-stack/src/i18n.ts +4 -4
  37. package/dist/templates/full-stack/src/main.tsx +4 -5
  38. package/dist/templates/full-stack/src/pages/home.tsx +5 -5
  39. package/dist/templates/full-stack/src/pages/layout.tsx +15 -5
  40. package/dist/templates/full-stack/src/pages/not-found.tsx +5 -2
  41. package/dist/templates/full-stack/src/routes.tsx +11 -12
  42. package/dist/templates/full-stack/src/schemas.ts +1 -2
  43. package/dist/templates/full-stack/src/server/action-registry.ts +5 -10
  44. package/dist/templates/full-stack/src/server/actions/create-message.ts +4 -4
  45. package/dist/templates/full-stack/src/server/app.ts +67 -57
  46. package/dist/templates/full-stack/src/server/dependencies.ts +10 -10
  47. package/dist/templates/full-stack/src/server/entry-server.ts +3 -3
  48. package/dist/templates/full-stack/src/telemetry.ts +1 -2
  49. package/dist/templates/full-stack/tests/actions/create-message.test.ts +7 -8
  50. package/dist/templates/full-stack/tsconfig.json +1 -2
  51. package/dist/templates/full-stack/vite.config.ts +5 -6
  52. package/dist/templates/spa/AGENTS.md +1 -1
  53. package/dist/templates/spa/package.json +3 -4
  54. package/dist/templates/spa/src/adapters/operations-client.ts +7 -2
  55. package/dist/templates/spa/src/pages/app/_routes.tsx +2 -0
  56. package/dist/templates/spa/src/pages/app/admin-home.tsx +21 -3
  57. package/dist/templates/spa/src/pages/public/_routes.tsx +2 -0
  58. package/dist/templates/spa/src/styles.css +1 -1
  59. package/dist/templates/spa/tsconfig.json +2 -1
  60. package/dist/templates/spa/vitest.config.ts +0 -4
  61. package/dist/templates/ssg/README.md +1 -1
  62. package/dist/templates/ssg/package.json +1 -1
  63. package/dist/templates/ssg/ssg.config.ts +7 -0
  64. package/dist/templates/ssg/tests/ssg-config.test.ts +5 -3
  65. package/dist/templates/ssg/tsconfig.json +2 -1
  66. package/dist/templates/ssg/vitest.config.ts +0 -4
  67. package/dist/templates/ssr/package.json +2 -2
  68. package/dist/templates/ssr/server.ts +4 -10
  69. package/dist/templates/ssr/src/entry-server.tsx +6 -4
  70. package/dist/templates/startkit/package.json +2 -2
  71. package/dist/templates/startkit/src/lib/mock-data.ts +17 -39
  72. package/dist/templates/startkit/tsconfig.json +2 -1
  73. package/dist/update.d.ts +41 -0
  74. package/dist/update.js +282 -2
  75. package/dist/writer-D8qe_7ud.js +226 -0
  76. package/package.json +23 -22
  77. package/dist/add-DqhqRzBQ.js +0 -555
  78. package/dist/add-DqhqRzBQ.js.map +0 -1
  79. package/dist/cli.js.map +0 -1
  80. package/dist/create.js.map +0 -1
  81. package/dist/is-direct-execution-Cdlr-ZUl.js.map +0 -1
  82. package/dist/openapi.js.map +0 -1
  83. package/dist/skills-Bh0mEhIx.js.map +0 -1
  84. package/dist/ssg.js.map +0 -1
  85. package/dist/templates/full-stack/src/vite-server.d.ts +0 -6
  86. package/dist/templates/spa/src/styles.d.ts +0 -1
  87. package/dist/templates/ssg/src/vite-env.d.ts +0 -5
  88. package/dist/templates/ssr/src/vite-server.d.ts +0 -7
  89. package/dist/templates/startkit/src/vite-env.d.ts +0 -5
  90. package/dist/update-DyW1na5V.js +0 -1140
  91. package/dist/update-DyW1na5V.js.map +0 -1
  92. package/skills/askr-accessibility/SKILL.md +0 -68
  93. package/skills/askr-accessibility/agents/openai.yaml +0 -4
  94. package/skills/askr-agent-execution/SKILL.md +0 -85
  95. package/skills/askr-agent-execution/agents/openai.yaml +0 -4
  96. package/skills/askr-agent-workflows/SKILL.md +0 -57
  97. package/skills/askr-agent-workflows/agents/openai.yaml +0 -4
  98. package/skills/askr-api-integration/SKILL.md +0 -79
  99. package/skills/askr-api-integration/agents/openai.yaml +0 -4
  100. package/skills/askr-app-builder/SKILL.md +0 -99
  101. package/skills/askr-app-builder/agents/openai.yaml +0 -4
  102. package/skills/askr-auth-access/SKILL.md +0 -74
  103. package/skills/askr-auth-access/agents/openai.yaml +0 -4
  104. package/skills/askr-cli-vite/SKILL.md +0 -76
  105. package/skills/askr-cli-vite/agents/openai.yaml +0 -4
  106. package/skills/askr-dashboard-charts/SKILL.md +0 -82
  107. package/skills/askr-dashboard-charts/agents/openai.yaml +0 -4
  108. package/skills/askr-design-system/SKILL.md +0 -86
  109. package/skills/askr-design-system/agents/openai.yaml +0 -4
  110. package/skills/askr-env-config/SKILL.md +0 -74
  111. package/skills/askr-env-config/agents/openai.yaml +0 -4
  112. package/skills/askr-error-loading-empty/SKILL.md +0 -89
  113. package/skills/askr-error-loading-empty/agents/openai.yaml +0 -4
  114. package/skills/askr-file-upload-artifacts/SKILL.md +0 -77
  115. package/skills/askr-file-upload-artifacts/agents/openai.yaml +0 -4
  116. package/skills/askr-forms-tables-crud/SKILL.md +0 -98
  117. package/skills/askr-forms-tables-crud/agents/openai.yaml +0 -4
  118. package/skills/askr-mental-model/SKILL.md +0 -109
  119. package/skills/askr-mental-model/agents/openai.yaml +0 -4
  120. package/skills/askr-migration-react/SKILL.md +0 -81
  121. package/skills/askr-migration-react/agents/openai.yaml +0 -4
  122. package/skills/askr-observability-debugging/SKILL.md +0 -83
  123. package/skills/askr-observability-debugging/agents/openai.yaml +0 -4
  124. package/skills/askr-project-structure/SKILL.md +0 -79
  125. package/skills/askr-project-structure/agents/openai.yaml +0 -4
  126. package/skills/askr-query-mutation/SKILL.md +0 -115
  127. package/skills/askr-query-mutation/agents/openai.yaml +0 -4
  128. package/skills/askr-realtime-streaming/SKILL.md +0 -76
  129. package/skills/askr-realtime-streaming/agents/openai.yaml +0 -4
  130. package/skills/askr-resources-data/SKILL.md +0 -100
  131. package/skills/askr-resources-data/agents/openai.yaml +0 -4
  132. package/skills/askr-routing-layouts/SKILL.md +0 -107
  133. package/skills/askr-routing-layouts/agents/openai.yaml +0 -4
  134. package/skills/askr-runtime-reactivity/SKILL.md +0 -92
  135. package/skills/askr-runtime-reactivity/agents/openai.yaml +0 -4
  136. package/skills/askr-ssr-ssg/SKILL.md +0 -76
  137. package/skills/askr-ssr-ssg/agents/openai.yaml +0 -4
  138. package/skills/askr-testing-determinism/SKILL.md +0 -75
  139. package/skills/askr-testing-determinism/agents/openai.yaml +0 -4
  140. package/skills/askr-theming/SKILL.md +0 -86
  141. package/skills/askr-theming/agents/openai.yaml +0 -4
  142. package/skills/askr-ui-composition/SKILL.md +0 -92
  143. package/skills/askr-ui-composition/agents/openai.yaml +0 -4
  144. package/templates/full-stack/AGENTS.md +0 -12
  145. package/templates/full-stack/README.md +0 -18
  146. package/templates/full-stack/gitignore.template +0 -4
  147. package/templates/full-stack/index.html +0 -14
  148. package/templates/full-stack/package.json +0 -37
  149. package/templates/full-stack/server.ts +0 -13
  150. package/templates/full-stack/src/action-authorizations.ts +0 -10
  151. package/templates/full-stack/src/actions/create-message.ts +0 -10
  152. package/templates/full-stack/src/i18n.ts +0 -8
  153. package/templates/full-stack/src/main.tsx +0 -12
  154. package/templates/full-stack/src/pages/home.tsx +0 -25
  155. package/templates/full-stack/src/pages/layout.tsx +0 -33
  156. package/templates/full-stack/src/pages/not-found.tsx +0 -4
  157. package/templates/full-stack/src/routes.tsx +0 -20
  158. package/templates/full-stack/src/schemas.ts +0 -11
  159. package/templates/full-stack/src/server/action-registry.ts +0 -12
  160. package/templates/full-stack/src/server/actions/create-message.ts +0 -14
  161. package/templates/full-stack/src/server/app.ts +0 -66
  162. package/templates/full-stack/src/server/dependencies.ts +0 -55
  163. package/templates/full-stack/src/server/entry-server.ts +0 -8
  164. package/templates/full-stack/src/telemetry.ts +0 -4
  165. package/templates/full-stack/src/vite-server.d.ts +0 -6
  166. package/templates/full-stack/tests/actions/create-message.test.ts +0 -13
  167. package/templates/full-stack/tsconfig.json +0 -16
  168. package/templates/full-stack/vite.config.ts +0 -11
  169. package/templates/spa/AGENTS.md +0 -60
  170. package/templates/spa/README.md +0 -96
  171. package/templates/spa/gitignore.template +0 -16
  172. package/templates/spa/index.html +0 -13
  173. package/templates/spa/package.json +0 -35
  174. package/templates/spa/src/adapters/operations-client.ts +0 -90
  175. package/templates/spa/src/components/shared/metric-card.tsx +0 -27
  176. package/templates/spa/src/components/shared/status-badge.tsx +0 -24
  177. package/templates/spa/src/features/operations/operations.query.ts +0 -9
  178. package/templates/spa/src/main.tsx +0 -10
  179. package/templates/spa/src/pages/_layout.tsx +0 -9
  180. package/templates/spa/src/pages/_routes.tsx +0 -27
  181. package/templates/spa/src/pages/app/_layout.tsx +0 -94
  182. package/templates/spa/src/pages/app/_routes.tsx +0 -10
  183. package/templates/spa/src/pages/app/admin-home.tsx +0 -152
  184. package/templates/spa/src/pages/app/agent-runs.tsx +0 -93
  185. package/templates/spa/src/pages/app/settings.tsx +0 -91
  186. package/templates/spa/src/pages/auth/_layout.tsx +0 -38
  187. package/templates/spa/src/pages/auth/_routes.tsx +0 -6
  188. package/templates/spa/src/pages/auth/login.tsx +0 -63
  189. package/templates/spa/src/pages/not-found.tsx +0 -22
  190. package/templates/spa/src/pages/public/_layout.tsx +0 -47
  191. package/templates/spa/src/pages/public/_routes.tsx +0 -6
  192. package/templates/spa/src/pages/public/home.tsx +0 -143
  193. package/templates/spa/src/shared/format.ts +0 -12
  194. package/templates/spa/src/shared/navigation.ts +0 -15
  195. package/templates/spa/src/styles/components.css +0 -49
  196. package/templates/spa/src/styles/layout.css +0 -192
  197. package/templates/spa/src/styles/reset.css +0 -44
  198. package/templates/spa/src/styles/theme.css +0 -57
  199. package/templates/spa/src/styles/tokens.css +0 -20
  200. package/templates/spa/src/styles.css +0 -7
  201. package/templates/spa/src/styles.d.ts +0 -1
  202. package/templates/spa/tests/app.test.tsx +0 -37
  203. package/templates/spa/tests/components/shared.test.tsx +0 -12
  204. package/templates/spa/tests/resources.test.ts +0 -22
  205. package/templates/spa/tsconfig.json +0 -20
  206. package/templates/spa/tsconfig.node.json +0 -10
  207. package/templates/spa/vite.config.ts +0 -24
  208. package/templates/spa/vitest.config.ts +0 -17
  209. package/templates/ssg/AGENTS.md +0 -55
  210. package/templates/ssg/README.md +0 -39
  211. package/templates/ssg/gitignore.template +0 -17
  212. package/templates/ssg/index.html +0 -13
  213. package/templates/ssg/package.json +0 -35
  214. package/templates/ssg/src/app.tsx +0 -14
  215. package/templates/ssg/src/components/badge.tsx +0 -3
  216. package/templates/ssg/src/components/counter.tsx +0 -30
  217. package/templates/ssg/src/components/site-shell.tsx +0 -111
  218. package/templates/ssg/src/jsx.d.ts +0 -23
  219. package/templates/ssg/src/main.tsx +0 -8
  220. package/templates/ssg/src/pages/about.tsx +0 -82
  221. package/templates/ssg/src/pages/content.tsx +0 -63
  222. package/templates/ssg/src/pages/example.tsx +0 -97
  223. package/templates/ssg/src/pages/home.tsx +0 -51
  224. package/templates/ssg/src/resources/user.ts +0 -15
  225. package/templates/ssg/src/routes.tsx +0 -15
  226. package/templates/ssg/src/styles.css +0 -89
  227. package/templates/ssg/src/vite-env.d.ts +0 -5
  228. package/templates/ssg/ssg.config.ts +0 -34
  229. package/templates/ssg/tests/app.test.tsx +0 -19
  230. package/templates/ssg/tests/components/counter.test.tsx +0 -18
  231. package/templates/ssg/tests/resources.test.ts +0 -11
  232. package/templates/ssg/tests/ssg-config.test.ts +0 -11
  233. package/templates/ssg/tsconfig.json +0 -20
  234. package/templates/ssg/tsconfig.node.json +0 -10
  235. package/templates/ssg/vite.config.ts +0 -24
  236. package/templates/ssg/vitest.config.ts +0 -17
  237. package/templates/ssr/AGENTS.md +0 -28
  238. package/templates/ssr/README.md +0 -38
  239. package/templates/ssr/gitignore.template +0 -16
  240. package/templates/ssr/index.html +0 -13
  241. package/templates/ssr/package.json +0 -34
  242. package/templates/ssr/server.ts +0 -16
  243. package/templates/ssr/src/app.tsx +0 -21
  244. package/templates/ssr/src/components/counter.tsx +0 -26
  245. package/templates/ssr/src/entry-server.tsx +0 -10
  246. package/templates/ssr/src/main.tsx +0 -11
  247. package/templates/ssr/src/pages/about.tsx +0 -75
  248. package/templates/ssr/src/pages/example.tsx +0 -113
  249. package/templates/ssr/src/pages/home.tsx +0 -56
  250. package/templates/ssr/src/resources/user.ts +0 -15
  251. package/templates/ssr/src/routes.tsx +0 -13
  252. package/templates/ssr/src/styles.css +0 -148
  253. package/templates/ssr/src/vite-server.d.ts +0 -7
  254. package/templates/ssr/tests/app.test.tsx +0 -24
  255. package/templates/ssr/tests/components/counter.test.tsx +0 -13
  256. package/templates/ssr/tests/resources.test.ts +0 -11
  257. package/templates/ssr/tsconfig.json +0 -22
  258. package/templates/ssr/tsconfig.node.json +0 -10
  259. package/templates/ssr/tsconfig.server.json +0 -15
  260. package/templates/ssr/vite.config.ts +0 -25
  261. package/templates/ssr/vitest.config.ts +0 -13
  262. package/templates/startkit/AGENTS.md +0 -77
  263. package/templates/startkit/README.md +0 -192
  264. package/templates/startkit/gitignore.template +0 -16
  265. package/templates/startkit/index.html +0 -13
  266. package/templates/startkit/package.json +0 -35
  267. package/templates/startkit/src/components/app-header.tsx +0 -93
  268. package/templates/startkit/src/components/app-sidebar.tsx +0 -95
  269. package/templates/startkit/src/components/data-table.tsx +0 -80
  270. package/templates/startkit/src/components/empty-state.tsx +0 -13
  271. package/templates/startkit/src/components/page-header.tsx +0 -23
  272. package/templates/startkit/src/components/stat-card.tsx +0 -24
  273. package/templates/startkit/src/features/accounts/account-filters.tsx +0 -61
  274. package/templates/startkit/src/features/accounts/account-table.tsx +0 -79
  275. package/templates/startkit/src/lib/format.ts +0 -31
  276. package/templates/startkit/src/lib/mock-data.ts +0 -441
  277. package/templates/startkit/src/lib/routes.ts +0 -116
  278. package/templates/startkit/src/main.tsx +0 -12
  279. package/templates/startkit/src/pages/_layout.tsx +0 -56
  280. package/templates/startkit/src/pages/auth/_layout.tsx +0 -7
  281. package/templates/startkit/src/pages/auth/login.tsx +0 -129
  282. package/templates/startkit/src/pages/home.tsx +0 -83
  283. package/templates/startkit/src/pages/not-found.tsx +0 -24
  284. package/templates/startkit/src/pages/workspace/_layout.tsx +0 -17
  285. package/templates/startkit/src/pages/workspace/accounts/index.tsx +0 -217
  286. package/templates/startkit/src/pages/workspace/dashboard.tsx +0 -118
  287. package/templates/startkit/src/pages/workspace/settings.tsx +0 -218
  288. package/templates/startkit/src/router.tsx +0 -7
  289. package/templates/startkit/src/routes/auth-config.ts +0 -38
  290. package/templates/startkit/src/routes/auth.ts +0 -8
  291. package/templates/startkit/src/routes/index.ts +0 -28
  292. package/templates/startkit/src/routes/public.ts +0 -8
  293. package/templates/startkit/src/routes/workspace/accounts.ts +0 -8
  294. package/templates/startkit/src/routes/workspace/index.ts +0 -14
  295. package/templates/startkit/src/styles/components.css +0 -396
  296. package/templates/startkit/src/styles/layout.css +0 -192
  297. package/templates/startkit/src/styles/reset.css +0 -38
  298. package/templates/startkit/src/styles/theme.css +0 -76
  299. package/templates/startkit/src/styles/tokens.css +0 -67
  300. package/templates/startkit/src/styles.css +0 -7
  301. package/templates/startkit/src/toast.ts +0 -55
  302. package/templates/startkit/src/utils/join-classes.ts +0 -4
  303. package/templates/startkit/src/vite-env.d.ts +0 -5
  304. package/templates/startkit/tests/app.test.tsx +0 -32
  305. package/templates/startkit/tests/preferences.test.ts +0 -43
  306. package/templates/startkit/tests/resources.test.ts +0 -82
  307. package/templates/startkit/tsconfig.json +0 -20
  308. package/templates/startkit/tsconfig.node.json +0 -10
  309. package/templates/startkit/vite.config.ts +0 -32
  310. package/templates/startkit/vitest.config.ts +0 -13
@@ -1,20 +1,19 @@
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';
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
6
 
7
7
  export const pageRegistry = createRouteRegistry(() => {
8
8
  group({ layout: AppLayout }, () => {
9
- route('/', HomePage, {
10
- actions: actionsFor('/'),
9
+ route("/", HomePage, {
10
+ actions: actionsFor("/"),
11
11
  meta: {
12
- title: '{{appName}}',
13
- description: 'A progressive full-stack Askr application.',
14
- html: { lang: 'en', dir: 'ltr' },
12
+ title: "{{appName}}",
13
+ description: "A progressive full-stack Askr application.",
14
+ html: { lang: "en", dir: "ltr" },
15
15
  },
16
16
  });
17
- route('/*', NotFoundPage);
17
+ route("/*", NotFoundPage);
18
18
  });
19
19
  });
20
-
@@ -1,4 +1,4 @@
1
- import { schema } from '@askrjs/schema';
1
+ import { schema } from "@askrjs/schema";
2
2
 
3
3
  export const MessageInput = schema.object({
4
4
  value: schema.string({ minLength: 1, maxLength: 200 }),
@@ -8,4 +8,3 @@ export const Message = schema.object({
8
8
  id: schema.string(),
9
9
  value: schema.string(),
10
10
  });
11
-
@@ -1,12 +1,7 @@
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';
1
+ import { handleAction } from "@askrjs/server/askr";
2
+ import { createMessageAction } from "../actions/create-message";
3
+ import { createMessage } from "./actions/create-message";
5
4
 
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;
5
+ export function createActionHandlers() {
6
+ return [handleAction(createMessageAction, createMessage)] as const;
12
7
  }
@@ -1,13 +1,13 @@
1
- import type { InferSchema } from '@askrjs/schema';
2
- import { createMessageAction } from '../../actions/create-message';
3
- import type { AppDependencies } from '../dependencies';
1
+ import type { InferSchema } from "@askrjs/schema";
2
+ import { createMessageAction } from "../../actions/create-message";
3
+ import type { AppDependencies } from "../dependencies";
4
4
 
5
5
  type Input = InferSchema<typeof createMessageAction.input>;
6
6
 
7
7
  export async function createMessage(
8
8
  _context: unknown,
9
9
  input: Input,
10
- deps: Pick<AppDependencies, 'actions'>,
10
+ deps: Pick<AppDependencies, "actions">,
11
11
  ) {
12
12
  await deps.actions.record({ action: createMessageAction.id, value: input.value });
13
13
  return { result: { accepted: true } };
@@ -1,66 +1,76 @@
1
- import { createAuth } from '@askrjs/auth';
2
- import { createServerApp } from '@askrjs/server';
3
- import { createAskrPageHandler } from '@askrjs/server/askr';
4
- import { csrf, rateLimit, requestId, securityHeaders } from '@askrjs/server/middleware';
5
- import { createApi } from '@askrjs/server/openapi';
6
- import { pageRegistry } from '../routes';
7
- import { Message, MessageInput } from '../schemas';
8
- import { telemetry } from '../telemetry';
9
- import { createActions } from './action-registry';
10
- import type { AppDependencies } from './dependencies';
1
+ import { createAuth } from "@askrjs/auth";
2
+ import { createAskrApp } from "@askrjs/server/askr";
3
+ import { csrf, rateLimit, requestId, securityHeaders } from "@askrjs/server/middleware";
4
+ import { pageRegistry } from "../routes";
5
+ import { Message, MessageInput } from "../schemas";
6
+ import { telemetry } from "../telemetry";
7
+ import { createActionHandlers } from "./action-registry";
8
+ import type { AppDependencies } from "./dependencies";
11
9
 
12
10
  export function createApp(deps: AppDependencies) {
13
- const api = createApi<AppDependencies>({
14
- info: { title: '{{appName}} API', version: '1.0.0' },
15
- });
16
- api.post('/api/messages', {
17
- input: {
18
- body: {
19
- schema: MessageInput,
20
- mediaTypes: ['application/json'],
11
+ return createAskrApp({
12
+ name: "{{appName}}",
13
+ version: "1.0.0",
14
+ dependencies: deps,
15
+ pages: pageRegistry,
16
+ api: {
17
+ define(api) {
18
+ api
19
+ .post("/messages", {
20
+ input: {
21
+ body: {
22
+ schema: MessageInput,
23
+ mediaTypes: ["application/json"],
24
+ },
25
+ },
26
+ documentation: { body: { required: true } },
27
+ async handler(ctx, input, dependencies) {
28
+ const message = { id: crypto.randomUUID(), value: input.body.value };
29
+ await dependencies.actions.record({
30
+ action: "api.create-message",
31
+ value: message.value,
32
+ });
33
+ return ctx.created(message);
34
+ },
35
+ })
36
+ .operationId("createMessage")
37
+ .summary("Create a message")
38
+ .tags("Messages")
39
+ .use(
40
+ csrf({ secret: process.env.CSRF_SECRET ?? "development-only-secret" }),
41
+ rateLimit({ store: deps.rateLimits, limit: 30, windowMs: 60_000 }),
42
+ )
43
+ .created(Message)
44
+ .badRequest()
45
+ .unprocessableEntity()
46
+ .tooManyRequests();
47
+ api
48
+ .post("/session", (ctx) => {
49
+ const response = ctx.redirect("/", 303);
50
+ return ctx.setCookie(response, "askr-session", "demo-session", {
51
+ httpOnly: true,
52
+ sameSite: "lax",
53
+ secure: ctx.url.protocol === "https:",
54
+ path: "/",
55
+ });
56
+ })
57
+ .operationId("createSession")
58
+ .summary("Create a demo session")
59
+ .seeOther();
21
60
  },
22
61
  },
23
- documentation: { body: { required: true } },
24
- async handler(ctx, input, dependencies) {
25
- const message = { id: crypto.randomUUID(), value: input.body.value };
26
- await dependencies.actions.record({ action: 'api.create-message', value: message.value });
27
- return ctx.created(message);
62
+ auth: {
63
+ resolver: createAuth({
64
+ sessions: deps.sessions,
65
+ principals: deps.principals,
66
+ sessionCookie: "askr-session",
67
+ }),
68
+ },
69
+ actions: {
70
+ handlers: createActionHandlers(),
71
+ csrf: { secret: process.env.CSRF_SECRET ?? "development-only-secret" },
28
72
  },
29
- })
30
- .operationId('createMessage')
31
- .summary('Create a message')
32
- .tags('Messages')
33
- .use(
34
- csrf({ secret: process.env.CSRF_SECRET ?? 'development-only-secret' }),
35
- rateLimit({ store: deps.rateLimits, limit: 30, windowMs: 60_000 }),
36
- )
37
- .created(Message)
38
- .badRequest()
39
- .unprocessableEntity()
40
- .tooManyRequests();
41
-
42
- const router = api.createRouter(deps);
43
- router.post('/api/session', (ctx) => {
44
- const response = ctx.redirect('/', 303);
45
- return ctx.setCookie(response, 'askr-session', 'demo-session', {
46
- httpOnly: true,
47
- sameSite: 'lax',
48
- secure: ctx.url.protocol === 'https:',
49
- path: '/',
50
- });
51
- });
52
- return createServerApp({
53
- router,
54
- auth: createAuth({
55
- sessions: deps.sessions,
56
- principals: deps.principals,
57
- sessionCookie: 'askr-session',
58
- }),
59
73
  middleware: [requestId(), securityHeaders()],
60
74
  telemetry,
61
- fallback: createAskrPageHandler({
62
- registry: pageRegistry,
63
- actions: createActions(deps),
64
- }),
65
75
  });
66
76
  }
@@ -13,7 +13,11 @@ export interface AppDependencies {
13
13
  record(entry: { action: string; value: string }): Promise<void>;
14
14
  };
15
15
  readonly rateLimits: {
16
- consume(key: string, limit: number, windowMs: number): Promise<{
16
+ consume(
17
+ key: string,
18
+ limit: number,
19
+ windowMs: number,
20
+ ): Promise<{
17
21
  allowed: boolean;
18
22
  remaining: number;
19
23
  reset: number;
@@ -25,23 +29,19 @@ export function createDependencies(): AppDependencies {
25
29
  const counters = new Map<string, { count: number; reset: number }>();
26
30
  return {
27
31
  sessions: {
28
- get: async (id) => id === 'demo-session'
29
- ? { id, subject: 'demo-user' }
30
- : null,
32
+ get: async (id) => (id === "demo-session" ? { id, subject: "demo-user" } : null),
31
33
  },
32
34
  principals: {
33
- get: async (subject) => subject === 'demo-user'
34
- ? { id: subject, subject, permissions: ['messages:create'] }
35
- : null,
35
+ get: async (subject) =>
36
+ subject === "demo-user" ? { id: subject, subject, permissions: ["messages:create"] } : null,
36
37
  },
37
38
  actions: { record: async () => undefined },
38
39
  rateLimits: {
39
40
  async consume(key, limit, windowMs) {
40
41
  const now = Date.now();
41
42
  const current = counters.get(key);
42
- const window = !current || current.reset <= now
43
- ? { count: 0, reset: now + windowMs }
44
- : current;
43
+ const window =
44
+ !current || current.reset <= now ? { count: 0, reset: now + windowMs } : current;
45
45
  window.count += 1;
46
46
  counters.set(key, window);
47
47
  return {
@@ -1,8 +1,8 @@
1
- import { createApp } from './app';
2
- import { createDependencies } from './dependencies';
1
+ import { createApp } from "./app";
2
+ import { createDependencies } from "./dependencies";
3
3
 
4
4
  const app = createApp(createDependencies());
5
5
 
6
6
  export { app };
7
- export { telemetry } from '../telemetry';
7
+ export { telemetry } from "../telemetry";
8
8
  export default app;
@@ -1,4 +1,3 @@
1
- import { createTelemetry } from '@askrjs/otel';
1
+ import { createTelemetry } from "@askrjs/otel";
2
2
 
3
3
  export const telemetry = createTelemetry();
4
-
@@ -1,13 +1,12 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { createMessageAction } from '../../src/actions/create-message';
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMessageAction } from "../../src/actions/create-message";
3
3
 
4
- describe('create message action', () => {
5
- it('should reject an empty message given declared input validation', () => {
6
- expect(createMessageAction.input.safeParse({ value: '' }).success).toBe(false);
4
+ describe("create message action", () => {
5
+ it("should reject an empty message given declared input validation", () => {
6
+ expect(createMessageAction.input.safeParse({ value: "" }).success).toBe(false);
7
7
  });
8
8
 
9
- it('should accept a message given valid input', () => {
10
- expect(createMessageAction.input.safeParse({ value: 'hello' }).success).toBe(true);
9
+ it("should accept a message given valid input", () => {
10
+ expect(createMessageAction.input.safeParse({ value: "hello" }).success).toBe(true);
11
11
  });
12
12
  });
13
-
@@ -9,8 +9,7 @@
9
9
  "noEmit": true,
10
10
  "jsx": "preserve",
11
11
  "jsxImportSource": "@askrjs/askr",
12
- "types": ["vite/client", "node"]
12
+ "types": ["vite/client", "node", "@askrjs/themes"]
13
13
  },
14
14
  "include": ["src", "tests", "server.ts", "vite.config.ts"]
15
15
  }
16
-
@@ -1,11 +1,10 @@
1
- import { defineConfig } from 'vite-plus';
2
- import { askr } from '@askrjs/vite';
3
- import { askrServer } from '@askrjs/vite/server';
1
+ import { defineConfig } from "vite-plus";
2
+ import { askr } from "@askrjs/vite";
3
+ import { askrServer } from "@askrjs/vite/server";
4
4
 
5
5
  export default defineConfig({
6
- plugins: [askr(), askrServer({ entry: './src/server/entry-server.ts' })],
7
- lint: { ignorePatterns: ['dist/**', 'node_modules/**', 'coverage/**'] },
6
+ plugins: [askr(), askrServer({ entry: "./src/server/entry-server.ts" })],
7
+ lint: { ignorePatterns: ["dist/**", "node_modules/**", "coverage/**"] },
8
8
  server: { port: 5173, open: true },
9
9
  build: { manifest: true, sourcemap: true },
10
10
  });
11
-
@@ -23,7 +23,7 @@ npm run fmt # Prettier
23
23
  - **Data:** Route/container components own resources; `src/features` owns product workflows; `src/adapters` owns API clients, transports, abort handling, and generated clients.
24
24
  - **Consistency:** Event-sourced screens should expose pending writes, projection lag, stale data, retries, and manual refresh instead of hiding everything behind one loading state.
25
25
  - **Styling:** Keep `src/styles.css` thin. Customize theme values in `src/styles/tokens.css`, global defaults in `src/styles/theme.css`, shell structure in `src/styles/layout.css`, and component classes in `src/styles/components.css`.
26
- - **Charts:** Import chart components from `@askrjs/charts/components`; chart CSS is loaded from `@askrjs/charts/default`.
26
+ - **Charts:** Create typed plot namespaces from `@askrjs/charts` at module scope and compose marks inside `Plot.Root`; chart CSS is loaded from `@askrjs/charts/styles`.
27
27
  - **Vite plugin:** `askr()` from `@askrjs/vite` handles JSX transform. Do not add manual esbuild JSX config.
28
28
 
29
29
  ## File Structure
@@ -7,7 +7,7 @@
7
7
  "dev": "vp dev",
8
8
  "build": "vp build",
9
9
  "preview": "vp preview",
10
- "test": "vp test run",
10
+ "test": "vp test run -c ./vitest.config.ts",
11
11
  "typecheck": "tsc --noEmit",
12
12
  "lint": "vp lint .",
13
13
  "lint:fix": "npm run lint -- --fix",
@@ -16,15 +16,14 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@askrjs/askr": ">=0.0.53 <0.1.0",
19
- "@askrjs/charts": ">=0.0.3 <0.1.0",
20
- "@askrjs/logos": ">=0.0.3 <0.1.0",
19
+ "@askrjs/charts": ">=0.1.0 <0.2.0",
21
20
  "@askrjs/lucide": ">=0.0.3 <0.1.0",
22
21
  "@askrjs/themes": ">=0.0.12 <0.1.0",
23
22
  "@askrjs/ui": ">=0.0.13 <0.1.0"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@askrjs/vite": ">=0.0.6 <0.1.0",
27
- "@types/node": "^26.0.0",
26
+ "@types/node": "^20.19.0",
28
27
  "jsdom": "^29.1.1",
29
28
  "typescript": "^6.0.3",
30
29
  "vite-plus": "^0.2.4"
@@ -8,13 +8,18 @@ export type OperationRun = {
8
8
  updatedAt: string;
9
9
  };
10
10
 
11
+ export type OperationsChartRow = {
12
+ label: string;
13
+ value: number;
14
+ };
15
+
11
16
  export type OperationsSnapshot = {
12
17
  version: number;
13
18
  consistency: 'fresh' | 'pending-write' | 'stale';
14
19
  lastEventId: string;
15
20
  metrics: Array<{ label: string; value: string; trend: string }>;
16
- throughput: Array<{ label: string; value: number }>;
17
- lag: Array<{ label: string; value: number }>;
21
+ throughput: OperationsChartRow[];
22
+ lag: OperationsChartRow[];
18
23
  runs: OperationRun[];
19
24
  };
20
25
 
@@ -2,8 +2,10 @@ import { route } from '@askrjs/askr/router';
2
2
  import AgentRunsPage from './agent-runs';
3
3
  import AdminHomePage from './admin-home';
4
4
  import SettingsPage from './settings';
5
+ // askr:imports
5
6
 
6
7
  export function registerAppRoutes(): void {
8
+ // askr:routes
7
9
  route('/app', AdminHomePage);
8
10
  route('/app/agents', AgentRunsPage);
9
11
  route('/app/settings', SettingsPage);
@@ -1,5 +1,5 @@
1
1
  import { resource } from '@askrjs/askr/resources';
2
- import { BarChart, Sparkline } from '@askrjs/charts/components';
2
+ import { createPlot } from '@askrjs/charts';
3
3
  import { AlertCircleIcon, RefreshCwIcon } from '@askrjs/lucide';
4
4
  import { Button } from '@askrjs/themes/components';
5
5
  import {
@@ -16,9 +16,12 @@ import { Block, Inline, Section, Stack } from '@askrjs/themes/components';
16
16
  import { EmptyState } from '@askrjs/themes/components';
17
17
  import MetricCard from '../../components/shared/metric-card';
18
18
  import StatusBadge from '../../components/shared/status-badge';
19
+ import type { OperationsChartRow } from '../../adapters/operations-client';
19
20
  import { loadOperations } from '../../features/operations/operations.query';
20
21
  import { formatRelativeTime } from '../../shared/format';
21
22
 
23
+ const OperationsPlot = createPlot<OperationsChartRow>();
24
+
22
25
  export default function AdminHomePage() {
23
26
  const operations = resource(({ signal }) => loadOperations({ signal }), []);
24
27
  const snapshot = operations.value;
@@ -84,7 +87,14 @@ export default function AdminHomePage() {
84
87
  </CardDescription>
85
88
  </CardHeader>
86
89
  <CardContent>
87
- <BarChart label="Run throughput" data={snapshot.throughput} />
90
+ <OperationsPlot.Root
91
+ data={snapshot.throughput}
92
+ rowKey="label"
93
+ label="Run throughput"
94
+ description="Accepted commands by work type."
95
+ >
96
+ <OperationsPlot.Bar x="label" y="value" />
97
+ </OperationsPlot.Root>
88
98
  </CardContent>
89
99
  </Card>
90
100
  <Card>
@@ -95,7 +105,15 @@ export default function AdminHomePage() {
95
105
  </CardDescription>
96
106
  </CardHeader>
97
107
  <CardContent>
98
- <Sparkline label="Projection lag" data={snapshot.lag} />
108
+ <OperationsPlot.Root
109
+ data={snapshot.lag}
110
+ rowKey="label"
111
+ label="Projection lag"
112
+ description="Projection lag over the last hour."
113
+ >
114
+ <OperationsPlot.Line x="label" y="value" />
115
+ <OperationsPlot.Point x="label" y="value" />
116
+ </OperationsPlot.Root>
99
117
  </CardContent>
100
118
  </Card>
101
119
  </Block>
@@ -1,6 +1,8 @@
1
1
  import { route } from '@askrjs/askr/router';
2
2
  import HomePage from './home';
3
+ // askr:imports
3
4
 
4
5
  export function registerPublicRoutes(): void {
6
+ // askr:routes
5
7
  route('/', HomePage);
6
8
  }
@@ -1,5 +1,5 @@
1
1
  @import '@askrjs/themes/default';
2
- @import '@askrjs/charts/default';
2
+ @import '@askrjs/charts/styles';
3
3
  @import './styles/reset.css';
4
4
  @import './styles/tokens.css';
5
5
  @import './styles/theme.css';
@@ -13,7 +13,8 @@
13
13
  "isolatedModules": true,
14
14
  "noEmit": true,
15
15
  "jsx": "preserve",
16
- "jsxImportSource": "@askrjs/askr"
16
+ "jsxImportSource": "@askrjs/askr",
17
+ "types": ["@askrjs/themes"]
17
18
  },
18
19
  "include": ["src", "tests"],
19
20
  "references": [{ "path": "./tsconfig.node.json" }]
@@ -3,10 +3,6 @@ import { askr } from '@askrjs/vite';
3
3
 
4
4
  export default defineConfig({
5
5
  plugins: [askr()],
6
- esbuild: {
7
- jsx: 'automatic',
8
- jsxImportSource: '@askrjs/askr',
9
- },
10
6
  test: {
11
7
  environment: 'jsdom',
12
8
  globals: true,
@@ -34,6 +34,6 @@ npm run typecheck # Type check
34
34
 
35
35
  ## Static generation
36
36
 
37
- Run `npm run build` to compile browser assets and pre-render every route into `dist/`. The `askr ssg` command owns both full and incremental generation, and publishes routes, metadata, the incremental manifest, and browser assets together.
37
+ Run `npm run build` to compile browser assets and pre-render every route into `dist/`. The `askr ssg` command owns both full and incremental generation, and publishes routes, metadata, the incremental manifest, browser assets, `sitemap.xml`, and the managed `robots.txt` sitemap directive together.
38
38
 
39
39
  `ssg.config.ts` passes the same immutable route registry used in dev mode, so the shell and leaf pages stay in sync.
@@ -24,7 +24,7 @@
24
24
  "devDependencies": {
25
25
  "@askrjs/cli": ">=0.0.2 <0.1.0",
26
26
  "@askrjs/vite": ">=0.0.6 <0.1.0",
27
- "@types/node": "^26.0.0",
27
+ "@types/node": "^20.19.0",
28
28
  "jsdom": "^29.1.1",
29
29
  "typescript": "^6.0.3",
30
30
  "vite-plus": "^0.2.4"
@@ -4,6 +4,7 @@ import type { DocumentRenderArgs } from '@askrjs/askr/ssg';
4
4
  import { pageRegistry } from './src/routes';
5
5
 
6
6
  export const outputDir = './dist';
7
+ export const siteUrl = 'https://example.com';
7
8
 
8
9
  let clientTemplate: string | undefined;
9
10
 
@@ -24,6 +25,12 @@ function renderDocument({ appHtml }: DocumentRenderArgs) {
24
25
  export const staticConfig = {
25
26
  registry: pageRegistry,
26
27
  outputDir,
28
+ siteUrl,
29
+ sitemap: {
30
+ routes: {
31
+ '/preview': false,
32
+ },
33
+ },
27
34
  document: renderDocument,
28
35
  assets: [
29
36
  {
@@ -3,9 +3,11 @@ import { staticConfig } from '../ssg.config';
3
3
 
4
4
  describe('SSG config', () => {
5
5
  it('keeps the sample route tree explicit', () => {
6
- expect(staticConfig.registry.manifest.records.map((route) => route.path).sort()).toEqual(
7
- ['/', '/content', '/preview', '/workflow'].sort()
8
- );
6
+ expect(
7
+ staticConfig.registry.manifest.records.map((route) => route.path).sort()
8
+ ).toEqual(['/', '/content', '/preview', '/workflow'].sort());
9
9
  expect(staticConfig.registry.routes).toHaveLength(4);
10
+ expect(staticConfig.siteUrl).toBe('https://example.com');
11
+ expect(staticConfig.sitemap.routes['/preview']).toBe(false);
10
12
  });
11
13
  });
@@ -13,7 +13,8 @@
13
13
  "isolatedModules": true,
14
14
  "noEmit": true,
15
15
  "jsx": "react-jsx",
16
- "jsxImportSource": "@askrjs/askr"
16
+ "jsxImportSource": "@askrjs/askr",
17
+ "types": ["@askrjs/themes"]
17
18
  },
18
19
  "include": ["src"],
19
20
  "references": [{ "path": "./tsconfig.node.json" }]
@@ -3,10 +3,6 @@ import { askr } from '@askrjs/vite';
3
3
 
4
4
  export default defineConfig({
5
5
  plugins: [askr()],
6
- esbuild: {
7
- jsx: 'automatic',
8
- jsxImportSource: '@askrjs/askr',
9
- },
10
6
  test: {
11
7
  environment: 'jsdom',
12
8
  globals: true,
@@ -6,7 +6,7 @@
6
6
  "dev": "vp dev",
7
7
  "build": "vp build && vp build --ssr server.ts --outDir dist/server",
8
8
  "preview": "node dist/server/server.js",
9
- "test": "vp test run",
9
+ "test": "vp test run -c ./vitest.config.ts",
10
10
  "typecheck": "tsc --noEmit",
11
11
  "lint": "vp lint src server.ts tests vite.config.ts",
12
12
  "lint:fix": "npm run lint -- --fix",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@askrjs/vite": ">=0.0.6 <0.1.0",
25
- "@types/node": "^26.0.0",
25
+ "@types/node": "^20.19.0",
26
26
  "jsdom": "^29.1.1",
27
27
  "tsx": "^4.23.1",
28
28
  "typescript": "^6.0.3",
@@ -1,16 +1,10 @@
1
- import { listen } from '@askrjs/node';
1
+ import { serve } from '@askrjs/node';
2
2
  import app from 'virtual:askr-server';
3
3
 
4
4
  const port = Number(process.env.PORT ?? 3000);
5
- const server = await listen(app, {
5
+ const running = await serve(app, {
6
6
  host: process.env.HOST ?? '127.0.0.1',
7
7
  port,
8
+ assets: { root: new URL('./dist', import.meta.url).pathname },
8
9
  });
9
- const address = server.address();
10
- const boundPort = typeof address === 'object' && address ? address.port : port;
11
-
12
- console.log(`Server started at http://127.0.0.1:${boundPort}`);
13
-
14
- const shutdown = () => server.close();
15
- process.once('SIGINT', shutdown);
16
- process.once('SIGTERM', shutdown);
10
+ console.log(`Server started at ${running.url}`);
@@ -1,9 +1,11 @@
1
- import { createServerApp } from '@askrjs/server';
2
- import { createAskrPageHandler } from '@askrjs/server/askr';
1
+ import { createAskrApp } from '@askrjs/server/askr';
3
2
  import { pageRegistry } from './routes';
4
3
 
5
- const app = createServerApp({
6
- fallback: createAskrPageHandler({ registry: pageRegistry }),
4
+ const app = createAskrApp({
5
+ name: '{{appName}}',
6
+ version: '0.1.0',
7
+ dependencies: undefined,
8
+ pages: pageRegistry,
7
9
  });
8
10
 
9
11
  export { app };