@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.
- package/LICENSE +201 -0
- package/README.md +140 -0
- package/dist/add-DqhqRzBQ.js +555 -0
- package/dist/add-DqhqRzBQ.js.map +1 -0
- package/dist/add.js +3 -0
- package/dist/cli.js +91 -0
- package/dist/cli.js.map +1 -0
- package/dist/create.js +923 -0
- package/dist/create.js.map +1 -0
- package/dist/is-direct-execution-Cdlr-ZUl.js +20 -0
- package/dist/is-direct-execution-Cdlr-ZUl.js.map +1 -0
- package/dist/openapi.js +127 -0
- package/dist/openapi.js.map +1 -0
- package/dist/skills/askr-accessibility/SKILL.md +68 -0
- package/dist/skills/askr-accessibility/agents/openai.yaml +4 -0
- package/dist/skills/askr-agent-execution/SKILL.md +85 -0
- package/dist/skills/askr-agent-execution/agents/openai.yaml +4 -0
- package/dist/skills/askr-agent-workflows/SKILL.md +57 -0
- package/dist/skills/askr-agent-workflows/agents/openai.yaml +4 -0
- package/dist/skills/askr-api-integration/SKILL.md +79 -0
- package/dist/skills/askr-api-integration/agents/openai.yaml +4 -0
- package/dist/skills/askr-app-builder/SKILL.md +99 -0
- package/dist/skills/askr-app-builder/agents/openai.yaml +4 -0
- package/dist/skills/askr-auth-access/SKILL.md +74 -0
- package/dist/skills/askr-auth-access/agents/openai.yaml +4 -0
- package/dist/skills/askr-cli-vite/SKILL.md +76 -0
- package/dist/skills/askr-cli-vite/agents/openai.yaml +4 -0
- package/dist/skills/askr-dashboard-charts/SKILL.md +82 -0
- package/dist/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
- package/dist/skills/askr-design-system/SKILL.md +86 -0
- package/dist/skills/askr-design-system/agents/openai.yaml +4 -0
- package/dist/skills/askr-env-config/SKILL.md +74 -0
- package/dist/skills/askr-env-config/agents/openai.yaml +4 -0
- package/dist/skills/askr-error-loading-empty/SKILL.md +89 -0
- package/dist/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
- package/dist/skills/askr-file-upload-artifacts/SKILL.md +77 -0
- package/dist/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
- package/dist/skills/askr-forms-tables-crud/SKILL.md +98 -0
- package/dist/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
- package/dist/skills/askr-mental-model/SKILL.md +109 -0
- package/dist/skills/askr-mental-model/agents/openai.yaml +4 -0
- package/dist/skills/askr-migration-react/SKILL.md +81 -0
- package/dist/skills/askr-migration-react/agents/openai.yaml +4 -0
- package/dist/skills/askr-observability-debugging/SKILL.md +83 -0
- package/dist/skills/askr-observability-debugging/agents/openai.yaml +4 -0
- package/dist/skills/askr-project-structure/SKILL.md +79 -0
- package/dist/skills/askr-project-structure/agents/openai.yaml +4 -0
- package/dist/skills/askr-query-mutation/SKILL.md +115 -0
- package/dist/skills/askr-query-mutation/agents/openai.yaml +4 -0
- package/dist/skills/askr-realtime-streaming/SKILL.md +76 -0
- package/dist/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
- package/dist/skills/askr-resources-data/SKILL.md +100 -0
- package/dist/skills/askr-resources-data/agents/openai.yaml +4 -0
- package/dist/skills/askr-routing-layouts/SKILL.md +107 -0
- package/dist/skills/askr-routing-layouts/agents/openai.yaml +4 -0
- package/dist/skills/askr-runtime-reactivity/SKILL.md +92 -0
- package/dist/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
- package/dist/skills/askr-ssr-ssg/SKILL.md +76 -0
- package/dist/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
- package/dist/skills/askr-testing-determinism/SKILL.md +75 -0
- package/dist/skills/askr-testing-determinism/agents/openai.yaml +4 -0
- package/dist/skills/askr-theming/SKILL.md +86 -0
- package/dist/skills/askr-theming/agents/openai.yaml +4 -0
- package/dist/skills/askr-ui-composition/SKILL.md +92 -0
- package/dist/skills/askr-ui-composition/agents/openai.yaml +4 -0
- package/dist/skills-Bh0mEhIx.js +682 -0
- package/dist/skills-Bh0mEhIx.js.map +1 -0
- package/dist/skills.js +3 -0
- package/dist/ssg.js +188 -0
- package/dist/ssg.js.map +1 -0
- package/dist/templates/full-stack/AGENTS.md +12 -0
- package/dist/templates/full-stack/README.md +18 -0
- package/dist/templates/full-stack/gitignore.template +4 -0
- package/dist/templates/full-stack/index.html +14 -0
- package/dist/templates/full-stack/package.json +37 -0
- package/dist/templates/full-stack/server.ts +13 -0
- package/dist/templates/full-stack/src/action-authorizations.ts +10 -0
- package/dist/templates/full-stack/src/actions/create-message.ts +10 -0
- package/dist/templates/full-stack/src/i18n.ts +8 -0
- package/dist/templates/full-stack/src/main.tsx +12 -0
- package/dist/templates/full-stack/src/pages/home.tsx +25 -0
- package/dist/templates/full-stack/src/pages/layout.tsx +33 -0
- package/dist/templates/full-stack/src/pages/not-found.tsx +4 -0
- package/dist/templates/full-stack/src/routes.tsx +20 -0
- package/dist/templates/full-stack/src/schemas.ts +11 -0
- package/dist/templates/full-stack/src/server/action-registry.ts +12 -0
- package/dist/templates/full-stack/src/server/actions/create-message.ts +14 -0
- package/dist/templates/full-stack/src/server/app.ts +66 -0
- package/dist/templates/full-stack/src/server/dependencies.ts +55 -0
- package/dist/templates/full-stack/src/server/entry-server.ts +8 -0
- package/dist/templates/full-stack/src/telemetry.ts +4 -0
- package/dist/templates/full-stack/src/vite-server.d.ts +6 -0
- package/dist/templates/full-stack/tests/actions/create-message.test.ts +13 -0
- package/dist/templates/full-stack/tsconfig.json +16 -0
- package/dist/templates/full-stack/vite.config.ts +11 -0
- package/dist/templates/spa/AGENTS.md +60 -0
- package/dist/templates/spa/README.md +96 -0
- package/dist/templates/spa/gitignore.template +16 -0
- package/dist/templates/spa/index.html +13 -0
- package/dist/templates/spa/package.json +35 -0
- package/dist/templates/spa/src/adapters/operations-client.ts +90 -0
- package/dist/templates/spa/src/components/shared/metric-card.tsx +27 -0
- package/dist/templates/spa/src/components/shared/status-badge.tsx +24 -0
- package/dist/templates/spa/src/features/operations/operations.query.ts +9 -0
- package/dist/templates/spa/src/main.tsx +10 -0
- package/dist/templates/spa/src/pages/_layout.tsx +9 -0
- package/dist/templates/spa/src/pages/_routes.tsx +27 -0
- package/dist/templates/spa/src/pages/app/_layout.tsx +94 -0
- package/dist/templates/spa/src/pages/app/_routes.tsx +10 -0
- package/dist/templates/spa/src/pages/app/admin-home.tsx +152 -0
- package/dist/templates/spa/src/pages/app/agent-runs.tsx +93 -0
- package/dist/templates/spa/src/pages/app/settings.tsx +91 -0
- package/dist/templates/spa/src/pages/auth/_layout.tsx +38 -0
- package/dist/templates/spa/src/pages/auth/_routes.tsx +6 -0
- package/dist/templates/spa/src/pages/auth/login.tsx +63 -0
- package/dist/templates/spa/src/pages/not-found.tsx +22 -0
- package/dist/templates/spa/src/pages/public/_layout.tsx +47 -0
- package/dist/templates/spa/src/pages/public/_routes.tsx +6 -0
- package/dist/templates/spa/src/pages/public/home.tsx +143 -0
- package/dist/templates/spa/src/shared/format.ts +12 -0
- package/dist/templates/spa/src/shared/navigation.ts +15 -0
- package/dist/templates/spa/src/styles/components.css +49 -0
- package/dist/templates/spa/src/styles/layout.css +192 -0
- package/dist/templates/spa/src/styles/reset.css +44 -0
- package/dist/templates/spa/src/styles/theme.css +57 -0
- package/dist/templates/spa/src/styles/tokens.css +20 -0
- package/dist/templates/spa/src/styles.css +7 -0
- package/dist/templates/spa/src/styles.d.ts +1 -0
- package/dist/templates/spa/tests/app.test.tsx +37 -0
- package/dist/templates/spa/tests/components/shared.test.tsx +12 -0
- package/dist/templates/spa/tests/resources.test.ts +22 -0
- package/dist/templates/spa/tsconfig.json +20 -0
- package/dist/templates/spa/tsconfig.node.json +10 -0
- package/dist/templates/spa/vite.config.ts +24 -0
- package/dist/templates/spa/vitest.config.ts +17 -0
- package/dist/templates/ssg/AGENTS.md +55 -0
- package/dist/templates/ssg/README.md +39 -0
- package/dist/templates/ssg/gitignore.template +17 -0
- package/dist/templates/ssg/index.html +13 -0
- package/dist/templates/ssg/package.json +35 -0
- package/dist/templates/ssg/src/app.tsx +14 -0
- package/dist/templates/ssg/src/components/badge.tsx +3 -0
- package/dist/templates/ssg/src/components/counter.tsx +30 -0
- package/dist/templates/ssg/src/components/site-shell.tsx +111 -0
- package/dist/templates/ssg/src/jsx.d.ts +23 -0
- package/dist/templates/ssg/src/main.tsx +8 -0
- package/dist/templates/ssg/src/pages/about.tsx +82 -0
- package/dist/templates/ssg/src/pages/content.tsx +63 -0
- package/dist/templates/ssg/src/pages/example.tsx +97 -0
- package/dist/templates/ssg/src/pages/home.tsx +51 -0
- package/dist/templates/ssg/src/resources/user.ts +15 -0
- package/dist/templates/ssg/src/routes.tsx +15 -0
- package/dist/templates/ssg/src/styles.css +89 -0
- package/dist/templates/ssg/src/vite-env.d.ts +5 -0
- package/dist/templates/ssg/ssg.config.ts +34 -0
- package/dist/templates/ssg/tests/app.test.tsx +19 -0
- package/dist/templates/ssg/tests/components/counter.test.tsx +18 -0
- package/dist/templates/ssg/tests/resources.test.ts +11 -0
- package/dist/templates/ssg/tests/ssg-config.test.ts +11 -0
- package/dist/templates/ssg/tsconfig.json +20 -0
- package/dist/templates/ssg/tsconfig.node.json +10 -0
- package/dist/templates/ssg/vite.config.ts +24 -0
- package/dist/templates/ssg/vitest.config.ts +17 -0
- package/dist/templates/ssr/AGENTS.md +28 -0
- package/dist/templates/ssr/README.md +38 -0
- package/dist/templates/ssr/gitignore.template +16 -0
- package/dist/templates/ssr/index.html +13 -0
- package/dist/templates/ssr/package.json +34 -0
- package/dist/templates/ssr/server.ts +16 -0
- package/dist/templates/ssr/src/app.tsx +21 -0
- package/dist/templates/ssr/src/components/counter.tsx +26 -0
- package/dist/templates/ssr/src/entry-server.tsx +10 -0
- package/dist/templates/ssr/src/main.tsx +11 -0
- package/dist/templates/ssr/src/pages/about.tsx +75 -0
- package/dist/templates/ssr/src/pages/example.tsx +113 -0
- package/dist/templates/ssr/src/pages/home.tsx +56 -0
- package/dist/templates/ssr/src/resources/user.ts +15 -0
- package/dist/templates/ssr/src/routes.tsx +13 -0
- package/dist/templates/ssr/src/styles.css +148 -0
- package/dist/templates/ssr/src/vite-server.d.ts +7 -0
- package/dist/templates/ssr/tests/app.test.tsx +24 -0
- package/dist/templates/ssr/tests/components/counter.test.tsx +13 -0
- package/dist/templates/ssr/tests/resources.test.ts +11 -0
- package/dist/templates/ssr/tsconfig.json +22 -0
- package/dist/templates/ssr/tsconfig.node.json +10 -0
- package/dist/templates/ssr/tsconfig.server.json +15 -0
- package/dist/templates/ssr/vite.config.ts +25 -0
- package/dist/templates/ssr/vitest.config.ts +13 -0
- package/dist/templates/startkit/AGENTS.md +77 -0
- package/dist/templates/startkit/README.md +192 -0
- package/dist/templates/startkit/gitignore.template +16 -0
- package/dist/templates/startkit/index.html +13 -0
- package/dist/templates/startkit/package.json +35 -0
- package/dist/templates/startkit/src/components/app-header.tsx +93 -0
- package/dist/templates/startkit/src/components/app-sidebar.tsx +95 -0
- package/dist/templates/startkit/src/components/data-table.tsx +80 -0
- package/dist/templates/startkit/src/components/empty-state.tsx +13 -0
- package/dist/templates/startkit/src/components/page-header.tsx +23 -0
- package/dist/templates/startkit/src/components/stat-card.tsx +24 -0
- package/dist/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
- package/dist/templates/startkit/src/features/accounts/account-table.tsx +79 -0
- package/dist/templates/startkit/src/lib/format.ts +31 -0
- package/dist/templates/startkit/src/lib/mock-data.ts +441 -0
- package/dist/templates/startkit/src/lib/routes.ts +116 -0
- package/dist/templates/startkit/src/main.tsx +12 -0
- package/dist/templates/startkit/src/pages/_layout.tsx +56 -0
- package/dist/templates/startkit/src/pages/auth/_layout.tsx +7 -0
- package/dist/templates/startkit/src/pages/auth/login.tsx +129 -0
- package/dist/templates/startkit/src/pages/home.tsx +83 -0
- package/dist/templates/startkit/src/pages/not-found.tsx +24 -0
- package/dist/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
- package/dist/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
- package/dist/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
- package/dist/templates/startkit/src/pages/workspace/settings.tsx +218 -0
- package/dist/templates/startkit/src/router.tsx +7 -0
- package/dist/templates/startkit/src/routes/auth-config.ts +38 -0
- package/dist/templates/startkit/src/routes/auth.ts +8 -0
- package/dist/templates/startkit/src/routes/index.ts +28 -0
- package/dist/templates/startkit/src/routes/public.ts +8 -0
- package/dist/templates/startkit/src/routes/workspace/accounts.ts +8 -0
- package/dist/templates/startkit/src/routes/workspace/index.ts +14 -0
- package/dist/templates/startkit/src/styles/components.css +396 -0
- package/dist/templates/startkit/src/styles/layout.css +192 -0
- package/dist/templates/startkit/src/styles/reset.css +38 -0
- package/dist/templates/startkit/src/styles/theme.css +76 -0
- package/dist/templates/startkit/src/styles/tokens.css +67 -0
- package/dist/templates/startkit/src/styles.css +7 -0
- package/dist/templates/startkit/src/toast.ts +55 -0
- package/dist/templates/startkit/src/utils/join-classes.ts +4 -0
- package/dist/templates/startkit/src/vite-env.d.ts +5 -0
- package/dist/templates/startkit/tests/app.test.tsx +32 -0
- package/dist/templates/startkit/tests/preferences.test.ts +43 -0
- package/dist/templates/startkit/tests/resources.test.ts +82 -0
- package/dist/templates/startkit/tsconfig.json +20 -0
- package/dist/templates/startkit/tsconfig.node.json +10 -0
- package/dist/templates/startkit/vite.config.ts +32 -0
- package/dist/templates/startkit/vitest.config.ts +13 -0
- package/dist/update-DyW1na5V.js +1140 -0
- package/dist/update-DyW1na5V.js.map +1 -0
- package/dist/update.js +3 -0
- package/package.json +84 -0
- package/skills/askr-accessibility/SKILL.md +68 -0
- package/skills/askr-accessibility/agents/openai.yaml +4 -0
- package/skills/askr-agent-execution/SKILL.md +85 -0
- package/skills/askr-agent-execution/agents/openai.yaml +4 -0
- package/skills/askr-agent-workflows/SKILL.md +57 -0
- package/skills/askr-agent-workflows/agents/openai.yaml +4 -0
- package/skills/askr-api-integration/SKILL.md +79 -0
- package/skills/askr-api-integration/agents/openai.yaml +4 -0
- package/skills/askr-app-builder/SKILL.md +99 -0
- package/skills/askr-app-builder/agents/openai.yaml +4 -0
- package/skills/askr-auth-access/SKILL.md +74 -0
- package/skills/askr-auth-access/agents/openai.yaml +4 -0
- package/skills/askr-cli-vite/SKILL.md +76 -0
- package/skills/askr-cli-vite/agents/openai.yaml +4 -0
- package/skills/askr-dashboard-charts/SKILL.md +82 -0
- package/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
- package/skills/askr-design-system/SKILL.md +86 -0
- package/skills/askr-design-system/agents/openai.yaml +4 -0
- package/skills/askr-env-config/SKILL.md +74 -0
- package/skills/askr-env-config/agents/openai.yaml +4 -0
- package/skills/askr-error-loading-empty/SKILL.md +89 -0
- package/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
- package/skills/askr-file-upload-artifacts/SKILL.md +77 -0
- package/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
- package/skills/askr-forms-tables-crud/SKILL.md +98 -0
- package/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
- package/skills/askr-mental-model/SKILL.md +109 -0
- package/skills/askr-mental-model/agents/openai.yaml +4 -0
- package/skills/askr-migration-react/SKILL.md +81 -0
- package/skills/askr-migration-react/agents/openai.yaml +4 -0
- package/skills/askr-observability-debugging/SKILL.md +83 -0
- package/skills/askr-observability-debugging/agents/openai.yaml +4 -0
- package/skills/askr-project-structure/SKILL.md +79 -0
- package/skills/askr-project-structure/agents/openai.yaml +4 -0
- package/skills/askr-query-mutation/SKILL.md +115 -0
- package/skills/askr-query-mutation/agents/openai.yaml +4 -0
- package/skills/askr-realtime-streaming/SKILL.md +76 -0
- package/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
- package/skills/askr-resources-data/SKILL.md +100 -0
- package/skills/askr-resources-data/agents/openai.yaml +4 -0
- package/skills/askr-routing-layouts/SKILL.md +107 -0
- package/skills/askr-routing-layouts/agents/openai.yaml +4 -0
- package/skills/askr-runtime-reactivity/SKILL.md +92 -0
- package/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
- package/skills/askr-ssr-ssg/SKILL.md +76 -0
- package/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
- package/skills/askr-testing-determinism/SKILL.md +75 -0
- package/skills/askr-testing-determinism/agents/openai.yaml +4 -0
- package/skills/askr-theming/SKILL.md +86 -0
- package/skills/askr-theming/agents/openai.yaml +4 -0
- package/skills/askr-ui-composition/SKILL.md +92 -0
- package/skills/askr-ui-composition/agents/openai.yaml +4 -0
- package/templates/full-stack/AGENTS.md +12 -0
- package/templates/full-stack/README.md +18 -0
- package/templates/full-stack/gitignore.template +4 -0
- package/templates/full-stack/index.html +14 -0
- package/templates/full-stack/package.json +37 -0
- package/templates/full-stack/server.ts +13 -0
- package/templates/full-stack/src/action-authorizations.ts +10 -0
- package/templates/full-stack/src/actions/create-message.ts +10 -0
- package/templates/full-stack/src/i18n.ts +8 -0
- package/templates/full-stack/src/main.tsx +12 -0
- package/templates/full-stack/src/pages/home.tsx +25 -0
- package/templates/full-stack/src/pages/layout.tsx +33 -0
- package/templates/full-stack/src/pages/not-found.tsx +4 -0
- package/templates/full-stack/src/routes.tsx +20 -0
- package/templates/full-stack/src/schemas.ts +11 -0
- package/templates/full-stack/src/server/action-registry.ts +12 -0
- package/templates/full-stack/src/server/actions/create-message.ts +14 -0
- package/templates/full-stack/src/server/app.ts +66 -0
- package/templates/full-stack/src/server/dependencies.ts +55 -0
- package/templates/full-stack/src/server/entry-server.ts +8 -0
- package/templates/full-stack/src/telemetry.ts +4 -0
- package/templates/full-stack/src/vite-server.d.ts +6 -0
- package/templates/full-stack/tests/actions/create-message.test.ts +13 -0
- package/templates/full-stack/tsconfig.json +16 -0
- package/templates/full-stack/vite.config.ts +11 -0
- package/templates/spa/AGENTS.md +60 -0
- package/templates/spa/README.md +96 -0
- package/templates/spa/gitignore.template +16 -0
- package/templates/spa/index.html +13 -0
- package/templates/spa/package.json +35 -0
- package/templates/spa/src/adapters/operations-client.ts +90 -0
- package/templates/spa/src/components/shared/metric-card.tsx +27 -0
- package/templates/spa/src/components/shared/status-badge.tsx +24 -0
- package/templates/spa/src/features/operations/operations.query.ts +9 -0
- package/templates/spa/src/main.tsx +10 -0
- package/templates/spa/src/pages/_layout.tsx +9 -0
- package/templates/spa/src/pages/_routes.tsx +27 -0
- package/templates/spa/src/pages/app/_layout.tsx +94 -0
- package/templates/spa/src/pages/app/_routes.tsx +10 -0
- package/templates/spa/src/pages/app/admin-home.tsx +152 -0
- package/templates/spa/src/pages/app/agent-runs.tsx +93 -0
- package/templates/spa/src/pages/app/settings.tsx +91 -0
- package/templates/spa/src/pages/auth/_layout.tsx +38 -0
- package/templates/spa/src/pages/auth/_routes.tsx +6 -0
- package/templates/spa/src/pages/auth/login.tsx +63 -0
- package/templates/spa/src/pages/not-found.tsx +22 -0
- package/templates/spa/src/pages/public/_layout.tsx +47 -0
- package/templates/spa/src/pages/public/_routes.tsx +6 -0
- package/templates/spa/src/pages/public/home.tsx +143 -0
- package/templates/spa/src/shared/format.ts +12 -0
- package/templates/spa/src/shared/navigation.ts +15 -0
- package/templates/spa/src/styles/components.css +49 -0
- package/templates/spa/src/styles/layout.css +192 -0
- package/templates/spa/src/styles/reset.css +44 -0
- package/templates/spa/src/styles/theme.css +57 -0
- package/templates/spa/src/styles/tokens.css +20 -0
- package/templates/spa/src/styles.css +7 -0
- package/templates/spa/src/styles.d.ts +1 -0
- package/templates/spa/tests/app.test.tsx +37 -0
- package/templates/spa/tests/components/shared.test.tsx +12 -0
- package/templates/spa/tests/resources.test.ts +22 -0
- package/templates/spa/tsconfig.json +20 -0
- package/templates/spa/tsconfig.node.json +10 -0
- package/templates/spa/vite.config.ts +24 -0
- package/templates/spa/vitest.config.ts +17 -0
- package/templates/ssg/AGENTS.md +55 -0
- package/templates/ssg/README.md +39 -0
- package/templates/ssg/gitignore.template +17 -0
- package/templates/ssg/index.html +13 -0
- package/templates/ssg/package.json +35 -0
- package/templates/ssg/src/app.tsx +14 -0
- package/templates/ssg/src/components/badge.tsx +3 -0
- package/templates/ssg/src/components/counter.tsx +30 -0
- package/templates/ssg/src/components/site-shell.tsx +111 -0
- package/templates/ssg/src/jsx.d.ts +23 -0
- package/templates/ssg/src/main.tsx +8 -0
- package/templates/ssg/src/pages/about.tsx +82 -0
- package/templates/ssg/src/pages/content.tsx +63 -0
- package/templates/ssg/src/pages/example.tsx +97 -0
- package/templates/ssg/src/pages/home.tsx +51 -0
- package/templates/ssg/src/resources/user.ts +15 -0
- package/templates/ssg/src/routes.tsx +15 -0
- package/templates/ssg/src/styles.css +89 -0
- package/templates/ssg/src/vite-env.d.ts +5 -0
- package/templates/ssg/ssg.config.ts +34 -0
- package/templates/ssg/tests/app.test.tsx +19 -0
- package/templates/ssg/tests/components/counter.test.tsx +18 -0
- package/templates/ssg/tests/resources.test.ts +11 -0
- package/templates/ssg/tests/ssg-config.test.ts +11 -0
- package/templates/ssg/tsconfig.json +20 -0
- package/templates/ssg/tsconfig.node.json +10 -0
- package/templates/ssg/vite.config.ts +24 -0
- package/templates/ssg/vitest.config.ts +17 -0
- package/templates/ssr/AGENTS.md +28 -0
- package/templates/ssr/README.md +38 -0
- package/templates/ssr/gitignore.template +16 -0
- package/templates/ssr/index.html +13 -0
- package/templates/ssr/package.json +34 -0
- package/templates/ssr/server.ts +16 -0
- package/templates/ssr/src/app.tsx +21 -0
- package/templates/ssr/src/components/counter.tsx +26 -0
- package/templates/ssr/src/entry-server.tsx +10 -0
- package/templates/ssr/src/main.tsx +11 -0
- package/templates/ssr/src/pages/about.tsx +75 -0
- package/templates/ssr/src/pages/example.tsx +113 -0
- package/templates/ssr/src/pages/home.tsx +56 -0
- package/templates/ssr/src/resources/user.ts +15 -0
- package/templates/ssr/src/routes.tsx +13 -0
- package/templates/ssr/src/styles.css +148 -0
- package/templates/ssr/src/vite-server.d.ts +7 -0
- package/templates/ssr/tests/app.test.tsx +24 -0
- package/templates/ssr/tests/components/counter.test.tsx +13 -0
- package/templates/ssr/tests/resources.test.ts +11 -0
- package/templates/ssr/tsconfig.json +22 -0
- package/templates/ssr/tsconfig.node.json +10 -0
- package/templates/ssr/tsconfig.server.json +15 -0
- package/templates/ssr/vite.config.ts +25 -0
- package/templates/ssr/vitest.config.ts +13 -0
- package/templates/startkit/AGENTS.md +77 -0
- package/templates/startkit/README.md +192 -0
- package/templates/startkit/gitignore.template +16 -0
- package/templates/startkit/index.html +13 -0
- package/templates/startkit/package.json +35 -0
- package/templates/startkit/src/components/app-header.tsx +93 -0
- package/templates/startkit/src/components/app-sidebar.tsx +95 -0
- package/templates/startkit/src/components/data-table.tsx +80 -0
- package/templates/startkit/src/components/empty-state.tsx +13 -0
- package/templates/startkit/src/components/page-header.tsx +23 -0
- package/templates/startkit/src/components/stat-card.tsx +24 -0
- package/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
- package/templates/startkit/src/features/accounts/account-table.tsx +79 -0
- package/templates/startkit/src/lib/format.ts +31 -0
- package/templates/startkit/src/lib/mock-data.ts +441 -0
- package/templates/startkit/src/lib/routes.ts +116 -0
- package/templates/startkit/src/main.tsx +12 -0
- package/templates/startkit/src/pages/_layout.tsx +56 -0
- package/templates/startkit/src/pages/auth/_layout.tsx +7 -0
- package/templates/startkit/src/pages/auth/login.tsx +129 -0
- package/templates/startkit/src/pages/home.tsx +83 -0
- package/templates/startkit/src/pages/not-found.tsx +24 -0
- package/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
- package/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
- package/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
- package/templates/startkit/src/pages/workspace/settings.tsx +218 -0
- package/templates/startkit/src/router.tsx +7 -0
- package/templates/startkit/src/routes/auth-config.ts +38 -0
- package/templates/startkit/src/routes/auth.ts +8 -0
- package/templates/startkit/src/routes/index.ts +28 -0
- package/templates/startkit/src/routes/public.ts +8 -0
- package/templates/startkit/src/routes/workspace/accounts.ts +8 -0
- package/templates/startkit/src/routes/workspace/index.ts +14 -0
- package/templates/startkit/src/styles/components.css +396 -0
- package/templates/startkit/src/styles/layout.css +192 -0
- package/templates/startkit/src/styles/reset.css +38 -0
- package/templates/startkit/src/styles/theme.css +76 -0
- package/templates/startkit/src/styles/tokens.css +67 -0
- package/templates/startkit/src/styles.css +7 -0
- package/templates/startkit/src/toast.ts +55 -0
- package/templates/startkit/src/utils/join-classes.ts +4 -0
- package/templates/startkit/src/vite-env.d.ts +5 -0
- package/templates/startkit/tests/app.test.tsx +32 -0
- package/templates/startkit/tests/preferences.test.ts +43 -0
- package/templates/startkit/tests/resources.test.ts +82 -0
- package/templates/startkit/tsconfig.json +20 -0
- package/templates/startkit/tsconfig.node.json +10 -0
- package/templates/startkit/vite.config.ts +32 -0
- package/templates/startkit/vitest.config.ts +13 -0
|
@@ -0,0 +1,66 @@
|
|
|
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';
|
|
11
|
+
|
|
12
|
+
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'],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
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);
|
|
28
|
+
},
|
|
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
|
+
middleware: [requestId(), securityHeaders()],
|
|
60
|
+
telemetry,
|
|
61
|
+
fallback: createAskrPageHandler({
|
|
62
|
+
registry: pageRegistry,
|
|
63
|
+
actions: createActions(deps),
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface AppDependencies {
|
|
2
|
+
readonly sessions: {
|
|
3
|
+
get(id: string): Promise<{ id: string; subject: string } | null>;
|
|
4
|
+
};
|
|
5
|
+
readonly principals: {
|
|
6
|
+
get(subject: string): Promise<{
|
|
7
|
+
id: string;
|
|
8
|
+
subject: string;
|
|
9
|
+
permissions: readonly string[];
|
|
10
|
+
} | null>;
|
|
11
|
+
};
|
|
12
|
+
readonly actions: {
|
|
13
|
+
record(entry: { action: string; value: string }): Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
readonly rateLimits: {
|
|
16
|
+
consume(key: string, limit: number, windowMs: number): Promise<{
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
remaining: number;
|
|
19
|
+
reset: number;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createDependencies(): AppDependencies {
|
|
25
|
+
const counters = new Map<string, { count: number; reset: number }>();
|
|
26
|
+
return {
|
|
27
|
+
sessions: {
|
|
28
|
+
get: async (id) => id === 'demo-session'
|
|
29
|
+
? { id, subject: 'demo-user' }
|
|
30
|
+
: null,
|
|
31
|
+
},
|
|
32
|
+
principals: {
|
|
33
|
+
get: async (subject) => subject === 'demo-user'
|
|
34
|
+
? { id: subject, subject, permissions: ['messages:create'] }
|
|
35
|
+
: null,
|
|
36
|
+
},
|
|
37
|
+
actions: { record: async () => undefined },
|
|
38
|
+
rateLimits: {
|
|
39
|
+
async consume(key, limit, windowMs) {
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
const current = counters.get(key);
|
|
42
|
+
const window = !current || current.reset <= now
|
|
43
|
+
? { count: 0, reset: now + windowMs }
|
|
44
|
+
: current;
|
|
45
|
+
window.count += 1;
|
|
46
|
+
counters.set(key, window);
|
|
47
|
+
return {
|
|
48
|
+
allowed: window.count <= limit,
|
|
49
|
+
remaining: Math.max(0, limit - window.count),
|
|
50
|
+
reset: window.reset,
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createMessageAction } from '../../src/actions/create-message';
|
|
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);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('should accept a message given valid input', () => {
|
|
10
|
+
expect(createMessageAction.input.safeParse({ value: 'hello' }).success).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"jsx": "preserve",
|
|
11
|
+
"jsxImportSource": "@askrjs/askr",
|
|
12
|
+
"types": ["vite/client", "node"]
|
|
13
|
+
},
|
|
14
|
+
"include": ["src", "tests", "server.ts", "vite.config.ts"]
|
|
15
|
+
}
|
|
16
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineConfig } from 'vite-plus';
|
|
2
|
+
import { askr } from '@askrjs/vite';
|
|
3
|
+
import { askrServer } from '@askrjs/vite/server';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [askr(), askrServer({ entry: './src/server/entry-server.ts' })],
|
|
7
|
+
lint: { ignorePatterns: ['dist/**', 'node_modules/**', 'coverage/**'] },
|
|
8
|
+
server: { port: 5173, open: true },
|
|
9
|
+
build: { manifest: true, sourcemap: true },
|
|
10
|
+
});
|
|
11
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# {{appName}}
|
|
2
|
+
|
|
3
|
+
Client-side SPA built with Askr, askr-ui, askr-themes, and askr-charts.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev # Vite dev server with HMR (port 5173)
|
|
9
|
+
npm run build # Production build to dist/
|
|
10
|
+
npm run preview # Serve production build locally
|
|
11
|
+
npm test # Vitest (jsdom)
|
|
12
|
+
npm run typecheck # tsc --noEmit
|
|
13
|
+
npm run lint # ESLint
|
|
14
|
+
npm run fmt # Prettier
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
- **Routing:** `src/main.tsx` imports `src/pages/_routes.tsx`, then boots `createSPA()` with the route manifest. Route branches live under `src/pages/public`, `src/pages/auth`, and `src/pages/app`.
|
|
20
|
+
- **Layouts:** `_layout.tsx` files own shells. The root layout owns `ThemeScope`; public layouts own landing chrome, auth layouts own sign-in chrome, and app layouts own authenticated sidebar chrome.
|
|
21
|
+
- **UI:** Prefer the `@askrjs/themes/components` catalog before writing local components. Use app-local components only for product concepts such as `MetricCard` and `StatusBadge`; keep charts in `@askrjs/charts`.
|
|
22
|
+
- **State:** `const [value, setValue] = state(initial)`. Read with `value()`, update with `setValue(...)`. Use `derive()` for computed values and `resource()` for async data.
|
|
23
|
+
- **Data:** Route/container components own resources; `src/features` owns product workflows; `src/adapters` owns API clients, transports, abort handling, and generated clients.
|
|
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
|
+
- **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`.
|
|
27
|
+
- **Vite plugin:** `askr()` from `@askrjs/vite` handles JSX transform. Do not add manual esbuild JSX config.
|
|
28
|
+
|
|
29
|
+
## File Structure
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
src/
|
|
33
|
+
main.tsx
|
|
34
|
+
pages/
|
|
35
|
+
_routes.tsx
|
|
36
|
+
_layout.tsx
|
|
37
|
+
public/
|
|
38
|
+
auth/
|
|
39
|
+
app/
|
|
40
|
+
components/shared/
|
|
41
|
+
features/
|
|
42
|
+
adapters/
|
|
43
|
+
shared/
|
|
44
|
+
styles/
|
|
45
|
+
reset.css
|
|
46
|
+
tokens.css
|
|
47
|
+
theme.css
|
|
48
|
+
layout.css
|
|
49
|
+
components.css
|
|
50
|
+
tests/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Conventions
|
|
54
|
+
|
|
55
|
+
- Keep routes thin and route-first.
|
|
56
|
+
- Keep shell chrome in layouts, not leaf pages.
|
|
57
|
+
- Keep business logic out of `src/pages`.
|
|
58
|
+
- Use `Link` and `navigate` from `@askrjs/askr/router`.
|
|
59
|
+
- Use headless `@askrjs/ui/*` for behavior primitives and `@askrjs/themes/*` for composed visual surfaces.
|
|
60
|
+
- Avoid hardcoded color systems, custom component catalogs, and React habits like effect-driven data loading.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# {{appName}} - SPA Template
|
|
2
|
+
|
|
3
|
+
A route-first Askr SPA built with `@askrjs/askr`, `@askrjs/ui`, `@askrjs/themes`, and `@askrjs/charts`.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev # Start dev server at http://localhost:5173
|
|
10
|
+
npm run build # Build for production
|
|
11
|
+
npm run preview # Preview production build
|
|
12
|
+
npm test # Run tests with Vitest
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Project Structure
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
src/
|
|
19
|
+
|-- main.tsx # SPA boot and route manifest
|
|
20
|
+
|-- pages/
|
|
21
|
+
| |-- _routes.tsx # Top-level route branches
|
|
22
|
+
| |-- _layout.tsx # Theme provider and app root
|
|
23
|
+
| |-- public/ # Guest-facing landing pages and shell
|
|
24
|
+
| |-- auth/ # Sign-in routes and shell
|
|
25
|
+
| `-- app/ # Authenticated branch routes and shell
|
|
26
|
+
|-- components/shared/ # App-local wrappers around theme primitives
|
|
27
|
+
|-- features/operations/ # Product workflow queries and mutations
|
|
28
|
+
|-- adapters/ # API clients and transport adapters
|
|
29
|
+
|-- shared/ # Cross-cutting helpers and navigation data
|
|
30
|
+
`-- styles/ # reset.css, tokens.css, theme.css, layout.css, components.css
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Core Patterns
|
|
34
|
+
|
|
35
|
+
Routes live in `src/pages`, shells live in `_layout.tsx`, reusable UI lives in
|
|
36
|
+
`src/components/shared`, business workflows live in `src/features`, and adapter
|
|
37
|
+
code lives in `src/adapters`.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// src/pages/_routes.tsx
|
|
41
|
+
import { fallback, group, registerRoutes } from '@askrjs/askr/router';
|
|
42
|
+
import RootLayout from './_layout';
|
|
43
|
+
import NotFoundPage from './not-found';
|
|
44
|
+
import AuthLayout from './auth/_layout';
|
|
45
|
+
import { registerAuthRoutes } from './auth/_routes';
|
|
46
|
+
import AppLayout from './app/_layout';
|
|
47
|
+
import { registerAppRoutes } from './app/_routes';
|
|
48
|
+
import PublicLayout from './public/_layout';
|
|
49
|
+
import { registerPublicRoutes } from './public/_routes';
|
|
50
|
+
|
|
51
|
+
registerRoutes(() => {
|
|
52
|
+
group({ layout: RootLayout }, () => {
|
|
53
|
+
group({ layout: PublicLayout }, () => {
|
|
54
|
+
registerPublicRoutes();
|
|
55
|
+
});
|
|
56
|
+
group({ layout: AuthLayout }, () => {
|
|
57
|
+
registerAuthRoutes();
|
|
58
|
+
});
|
|
59
|
+
group({ layout: AppLayout }, () => {
|
|
60
|
+
registerAppRoutes();
|
|
61
|
+
});
|
|
62
|
+
fallback(NotFoundPage);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The template uses the `@askrjs/themes/components` catalog for styled UI
|
|
68
|
+
composition and keeps charts in `@askrjs/charts`. Add app-local components only
|
|
69
|
+
when they compose those primitives into a product concept. Start with
|
|
70
|
+
`src/styles/tokens.css` for theme knobs, then tune `theme.css`, `layout.css`,
|
|
71
|
+
and `components.css`.
|
|
72
|
+
|
|
73
|
+
Async reads are owned by route or container components with `resource()` and
|
|
74
|
+
delegated through feature/adapters:
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
const operations = resource(({ signal }) => loadOperations({ signal }), []);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Cancellation belongs in adapters, loading/error/value states stay visible in the
|
|
81
|
+
route, and event-sourced consistency states should be modeled explicitly.
|
|
82
|
+
|
|
83
|
+
## What This Template Includes
|
|
84
|
+
|
|
85
|
+
- Public, auth, and authenticated app branches with separate layout shells
|
|
86
|
+
- Theme provider, header/nav/sidebar, cards, badges, buttons, empty states, and layout primitives
|
|
87
|
+
- A dashboard with async loading, charts, projection lag, and explicit refresh
|
|
88
|
+
- Feature and adapter boundaries for data ownership
|
|
89
|
+
- Tests that protect the route-first structure and cancellation behavior
|
|
90
|
+
|
|
91
|
+
## Next Steps
|
|
92
|
+
|
|
93
|
+
1. Replace the mock operations adapter with your generated API client.
|
|
94
|
+
2. Tune `src/styles/tokens.css` and `src/styles/theme.css` to match your brand.
|
|
95
|
+
3. Add route metadata for real auth and loader policies.
|
|
96
|
+
4. Keep new screens route-first and compose solved UI through `@askrjs/themes`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>{{appName}}</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{appName}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"clean": "npx rimraf node_modules dist",
|
|
7
|
+
"dev": "vp dev",
|
|
8
|
+
"build": "vp build",
|
|
9
|
+
"preview": "vp preview",
|
|
10
|
+
"test": "vp test run",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"lint": "vp lint .",
|
|
13
|
+
"lint:fix": "npm run lint -- --fix",
|
|
14
|
+
"fmt": "vp fmt .",
|
|
15
|
+
"check": "npm run lint && npm run typecheck && npm test && npm run build"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
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",
|
|
21
|
+
"@askrjs/lucide": ">=0.0.3 <0.1.0",
|
|
22
|
+
"@askrjs/themes": ">=0.0.12 <0.1.0",
|
|
23
|
+
"@askrjs/ui": ">=0.0.13 <0.1.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@askrjs/vite": ">=0.0.6 <0.1.0",
|
|
27
|
+
"@types/node": "^26.0.0",
|
|
28
|
+
"jsdom": "^29.1.1",
|
|
29
|
+
"typescript": "^6.0.3",
|
|
30
|
+
"vite-plus": "^0.2.4"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { RunStatus } from '../components/shared/status-badge';
|
|
2
|
+
|
|
3
|
+
export type OperationRun = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: RunStatus;
|
|
7
|
+
owner: string;
|
|
8
|
+
updatedAt: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type OperationsSnapshot = {
|
|
12
|
+
version: number;
|
|
13
|
+
consistency: 'fresh' | 'pending-write' | 'stale';
|
|
14
|
+
lastEventId: string;
|
|
15
|
+
metrics: Array<{ label: string; value: string; trend: string }>;
|
|
16
|
+
throughput: Array<{ label: string; value: number }>;
|
|
17
|
+
lag: Array<{ label: string; value: number }>;
|
|
18
|
+
runs: OperationRun[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export async function getOperationsSnapshot({
|
|
22
|
+
signal,
|
|
23
|
+
}: {
|
|
24
|
+
signal: AbortSignal;
|
|
25
|
+
}): Promise<OperationsSnapshot> {
|
|
26
|
+
await delay(220, signal);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
version: 42,
|
|
30
|
+
consistency: 'fresh',
|
|
31
|
+
lastEventId: 'evt_18442',
|
|
32
|
+
metrics: [
|
|
33
|
+
{ label: 'Active runs', value: '12', trend: '+3 today' },
|
|
34
|
+
{ label: 'Pending approvals', value: '3', trend: '2 urgent' },
|
|
35
|
+
{ label: 'Projection lag', value: '1.2s', trend: 'healthy' },
|
|
36
|
+
],
|
|
37
|
+
throughput: [
|
|
38
|
+
{ label: 'Research', value: 18 },
|
|
39
|
+
{ label: 'Review', value: 11 },
|
|
40
|
+
{ label: 'Deploy', value: 7 },
|
|
41
|
+
{ label: 'Audit', value: 9 },
|
|
42
|
+
],
|
|
43
|
+
lag: [
|
|
44
|
+
{ label: '10:00', value: 4 },
|
|
45
|
+
{ label: '10:10', value: 3 },
|
|
46
|
+
{ label: '10:20', value: 2 },
|
|
47
|
+
{ label: '10:30', value: 1 },
|
|
48
|
+
{ label: '10:40', value: 2 },
|
|
49
|
+
{ label: '10:50', value: 1 },
|
|
50
|
+
],
|
|
51
|
+
runs: [
|
|
52
|
+
{
|
|
53
|
+
id: 'run_4812',
|
|
54
|
+
title: 'Summarize renewal risk',
|
|
55
|
+
status: 'running',
|
|
56
|
+
owner: 'Revenue ops',
|
|
57
|
+
updatedAt: '2026-05-22T09:52:00.000Z',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'run_4811',
|
|
61
|
+
title: 'Approve workspace migration',
|
|
62
|
+
status: 'requires-action',
|
|
63
|
+
owner: 'Platform',
|
|
64
|
+
updatedAt: '2026-05-22T09:40:00.000Z',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'run_4810',
|
|
68
|
+
title: 'Reconcile audit events',
|
|
69
|
+
status: 'succeeded',
|
|
70
|
+
owner: 'Security',
|
|
71
|
+
updatedAt: '2026-05-22T09:25:00.000Z',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function delay(ms: number, signal: AbortSignal): Promise<void> {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const timeout = globalThis.setTimeout(resolve, ms);
|
|
80
|
+
|
|
81
|
+
signal.addEventListener(
|
|
82
|
+
'abort',
|
|
83
|
+
() => {
|
|
84
|
+
globalThis.clearTimeout(timeout);
|
|
85
|
+
reject(new DOMException('Operation aborted', 'AbortError'));
|
|
86
|
+
},
|
|
87
|
+
{ once: true }
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardDescription,
|
|
4
|
+
CardHeader,
|
|
5
|
+
CardTitle,
|
|
6
|
+
} from '@askrjs/themes/components';
|
|
7
|
+
import { Inline } from '@askrjs/themes/components';
|
|
8
|
+
|
|
9
|
+
export type MetricCardProps = {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
trend: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default function MetricCard({ label, value, trend }: MetricCardProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Card class="metric-card">
|
|
18
|
+
<CardHeader>
|
|
19
|
+
<Inline justify="between" align="center" gap="3">
|
|
20
|
+
<CardDescription>{label}</CardDescription>
|
|
21
|
+
<span class="metric-trend">{trend}</span>
|
|
22
|
+
</Inline>
|
|
23
|
+
<CardTitle>{value}</CardTitle>
|
|
24
|
+
</CardHeader>
|
|
25
|
+
</Card>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Badge } from '@askrjs/themes/components';
|
|
2
|
+
|
|
3
|
+
export type RunStatus =
|
|
4
|
+
| 'queued'
|
|
5
|
+
| 'running'
|
|
6
|
+
| 'requires-action'
|
|
7
|
+
| 'succeeded'
|
|
8
|
+
| 'failed';
|
|
9
|
+
|
|
10
|
+
export type StatusBadgeProps = {
|
|
11
|
+
status: RunStatus;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const labels: Record<RunStatus, string> = {
|
|
15
|
+
queued: 'queued',
|
|
16
|
+
running: 'running',
|
|
17
|
+
'requires-action': 'needs review',
|
|
18
|
+
succeeded: 'succeeded',
|
|
19
|
+
failed: 'failed',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function StatusBadge({ status }: StatusBadgeProps) {
|
|
23
|
+
return <Badge data-status={status}>{labels[status]}</Badge>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { fallback, group, registerRoutes } from '@askrjs/askr/router';
|
|
2
|
+
import RootLayout from './_layout';
|
|
3
|
+
import AuthLayout from './auth/_layout';
|
|
4
|
+
import { registerAuthRoutes } from './auth/_routes';
|
|
5
|
+
import { registerAppRoutes } from './app/_routes';
|
|
6
|
+
import AppLayout from './app/_layout';
|
|
7
|
+
import NotFoundPage from './not-found';
|
|
8
|
+
import { registerPublicRoutes } from './public/_routes';
|
|
9
|
+
import PublicLayout from './public/_layout';
|
|
10
|
+
|
|
11
|
+
registerRoutes(() => {
|
|
12
|
+
group({ layout: RootLayout }, () => {
|
|
13
|
+
group({ layout: PublicLayout }, () => {
|
|
14
|
+
registerPublicRoutes();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
group({ layout: AuthLayout }, () => {
|
|
18
|
+
registerAuthRoutes();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
group({ layout: AppLayout }, () => {
|
|
22
|
+
registerAppRoutes();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
fallback(NotFoundPage);
|
|
26
|
+
});
|
|
27
|
+
});
|