@stacksjs/defaults 0.70.207 → 0.70.208
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/TODO.md +21 -0
- package/ai/AGENTS.md +79 -0
- package/ai/README.md +45 -0
- package/ai/claude/launch.json +12 -0
- package/ai/skills/stacks-actions/SKILL.md +128 -0
- package/ai/skills/stacks-ai/SKILL.md +276 -0
- package/ai/skills/stacks-alias/SKILL.md +94 -0
- package/ai/skills/stacks-analytics/SKILL.md +91 -0
- package/ai/skills/stacks-api/SKILL.md +738 -0
- package/ai/skills/stacks-arrays/SKILL.md +277 -0
- package/ai/skills/stacks-auth/SKILL.md +422 -0
- package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
- package/ai/skills/stacks-brandkit/SKILL.md +811 -0
- package/ai/skills/stacks-browse/SKILL.md +127 -0
- package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
- package/ai/skills/stacks-browser/SKILL.md +145 -0
- package/ai/skills/stacks-buddy/SKILL.md +676 -0
- package/ai/skills/stacks-build/SKILL.md +163 -0
- package/ai/skills/stacks-cache/SKILL.md +125 -0
- package/ai/skills/stacks-calendar/SKILL.md +113 -0
- package/ai/skills/stacks-chat/SKILL.md +371 -0
- package/ai/skills/stacks-cli/SKILL.md +112 -0
- package/ai/skills/stacks-cloud/SKILL.md +192 -0
- package/ai/skills/stacks-cms/SKILL.md +217 -0
- package/ai/skills/stacks-collections/SKILL.md +82 -0
- package/ai/skills/stacks-commerce/SKILL.md +114 -0
- package/ai/skills/stacks-composables/SKILL.md +161 -0
- package/ai/skills/stacks-config/SKILL.md +144 -0
- package/ai/skills/stacks-configuration/SKILL.md +154 -0
- package/ai/skills/stacks-cron/SKILL.md +123 -0
- package/ai/skills/stacks-crosswind/SKILL.md +190 -0
- package/ai/skills/stacks-dashboard/SKILL.md +173 -0
- package/ai/skills/stacks-database/SKILL.md +286 -0
- package/ai/skills/stacks-datetime/SKILL.md +269 -0
- package/ai/skills/stacks-dependencies/SKILL.md +111 -0
- package/ai/skills/stacks-deploy/SKILL.md +102 -0
- package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
- package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
- package/ai/skills/stacks-design-output/SKILL.md +55 -0
- package/ai/skills/stacks-design-soft/SKILL.md +156 -0
- package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
- package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
- package/ai/skills/stacks-desktop/SKILL.md +78 -0
- package/ai/skills/stacks-development/SKILL.md +298 -0
- package/ai/skills/stacks-dns/SKILL.md +149 -0
- package/ai/skills/stacks-docs/SKILL.md +109 -0
- package/ai/skills/stacks-email/SKILL.md +236 -0
- package/ai/skills/stacks-enums/SKILL.md +100 -0
- package/ai/skills/stacks-env/SKILL.md +181 -0
- package/ai/skills/stacks-error-handling/SKILL.md +137 -0
- package/ai/skills/stacks-events/SKILL.md +228 -0
- package/ai/skills/stacks-faker/SKILL.md +158 -0
- package/ai/skills/stacks-git/SKILL.md +158 -0
- package/ai/skills/stacks-guard/SKILL.md +98 -0
- package/ai/skills/stacks-health/SKILL.md +75 -0
- package/ai/skills/stacks-http/SKILL.md +316 -0
- package/ai/skills/stacks-i18n/SKILL.md +198 -0
- package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
- package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
- package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
- package/ai/skills/stacks-investigate/SKILL.md +119 -0
- package/ai/skills/stacks-jobs/SKILL.md +136 -0
- package/ai/skills/stacks-lint/SKILL.md +184 -0
- package/ai/skills/stacks-listeners/SKILL.md +99 -0
- package/ai/skills/stacks-logging/SKILL.md +78 -0
- package/ai/skills/stacks-mail/SKILL.md +120 -0
- package/ai/skills/stacks-middleware/SKILL.md +249 -0
- package/ai/skills/stacks-migrations/SKILL.md +105 -0
- package/ai/skills/stacks-models/SKILL.md +267 -0
- package/ai/skills/stacks-new-feature/SKILL.md +206 -0
- package/ai/skills/stacks-notifications/SKILL.md +210 -0
- package/ai/skills/stacks-objects/SKILL.md +205 -0
- package/ai/skills/stacks-office-hours/SKILL.md +134 -0
- package/ai/skills/stacks-orm/SKILL.md +342 -0
- package/ai/skills/stacks-path/SKILL.md +118 -0
- package/ai/skills/stacks-payments/SKILL.md +373 -0
- package/ai/skills/stacks-plan-review/SKILL.md +152 -0
- package/ai/skills/stacks-plugins/SKILL.md +149 -0
- package/ai/skills/stacks-push/SKILL.md +376 -0
- package/ai/skills/stacks-query-builder/SKILL.md +128 -0
- package/ai/skills/stacks-queue/SKILL.md +559 -0
- package/ai/skills/stacks-realtime/SKILL.md +442 -0
- package/ai/skills/stacks-redesign/SKILL.md +182 -0
- package/ai/skills/stacks-registry/SKILL.md +58 -0
- package/ai/skills/stacks-repl/SKILL.md +80 -0
- package/ai/skills/stacks-retro/SKILL.md +122 -0
- package/ai/skills/stacks-review/SKILL.md +135 -0
- package/ai/skills/stacks-router/SKILL.md +231 -0
- package/ai/skills/stacks-routes/SKILL.md +105 -0
- package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
- package/ai/skills/stacks-scheduler/SKILL.md +363 -0
- package/ai/skills/stacks-search-engine/SKILL.md +112 -0
- package/ai/skills/stacks-security/SKILL.md +129 -0
- package/ai/skills/stacks-security-audit/SKILL.md +128 -0
- package/ai/skills/stacks-server/SKILL.md +458 -0
- package/ai/skills/stacks-shell/SKILL.md +62 -0
- package/ai/skills/stacks-slug/SKILL.md +87 -0
- package/ai/skills/stacks-sms/SKILL.md +385 -0
- package/ai/skills/stacks-socials/SKILL.md +303 -0
- package/ai/skills/stacks-storage/SKILL.md +576 -0
- package/ai/skills/stacks-strings/SKILL.md +416 -0
- package/ai/skills/stacks-stx/SKILL.md +176 -0
- package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
- package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
- package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
- package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
- package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
- package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
- package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
- package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
- package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
- package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
- package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
- package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
- package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
- package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
- package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
- package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
- package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
- package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
- package/ai/skills/stacks-testing/SKILL.md +129 -0
- package/ai/skills/stacks-tunnel/SKILL.md +125 -0
- package/ai/skills/stacks-types/SKILL.md +178 -0
- package/ai/skills/stacks-ui/SKILL.md +246 -0
- package/ai/skills/stacks-utils/SKILL.md +444 -0
- package/ai/skills/stacks-validation/SKILL.md +371 -0
- package/ai/skills/stacks-whois/SKILL.md +315 -0
- package/assets/world-map-data.ts +121 -0
- package/bootstrap.ts +114 -0
- package/docs/api-examples.md +46 -0
- package/docs/index.md +24 -0
- package/docs/markdown-examples.md +87 -0
- package/functions/analytics.ts +97 -0
- package/functions/api.ts +143 -0
- package/functions/auth.ts +208 -0
- package/functions/billing/payments.ts +149 -0
- package/functions/blog.ts +120 -0
- package/functions/cms/categorizables.ts +107 -0
- package/functions/cms/pages.ts +108 -0
- package/functions/cms/posts.ts +100 -0
- package/functions/cms/taggables.ts +102 -0
- package/functions/commerce/coupons.ts +128 -0
- package/functions/commerce/customers.ts +128 -0
- package/functions/commerce/gift-cards.ts +119 -0
- package/functions/commerce/orders.ts +112 -0
- package/functions/commerce/payments.ts +119 -0
- package/functions/commerce/products/categories.ts +123 -0
- package/functions/commerce/products/manufacturers.ts +123 -0
- package/functions/commerce/products/products.ts +123 -0
- package/functions/commerce/products/reviews.ts +123 -0
- package/functions/commerce/products/units.ts +123 -0
- package/functions/commerce/products/variants.ts +123 -0
- package/functions/commerce/shippings/delivery-routes.ts +123 -0
- package/functions/commerce/shippings/digital-deliveries.ts +119 -0
- package/functions/commerce/shippings/drivers.ts +123 -0
- package/functions/commerce/shippings/license-keys.ts +123 -0
- package/functions/commerce/shippings/shipping-methods.ts +123 -0
- package/functions/commerce/shippings/shipping-rates.ts +119 -0
- package/functions/commerce/shippings/shipping-zones.ts +119 -0
- package/functions/commerce/taxes.ts +119 -0
- package/functions/commerce/waitlist/products.ts +123 -0
- package/functions/commerce/waitlist/restaurants.ts +123 -0
- package/functions/craft.ts +107 -0
- package/functions/dashboard.ts +153 -0
- package/functions/inbox.ts +95 -0
- package/functions/jobs.ts +86 -0
- package/functions/monitoring/errors.ts +295 -0
- package/functions/queue.ts +111 -0
- package/functions/realtime/websockets.ts +96 -0
- package/functions/realtime.ts +52 -0
- package/functions/releases.ts +49 -0
- package/functions/search.ts +126 -0
- package/functions/toasts.ts +95 -0
- package/functions/uploads.ts +216 -0
- package/ide/.gitignore +4 -0
- package/ide/cursor/rules/auto-imports.mdc +574 -0
- package/ide/cursor/rules/code-style.mdc +12 -0
- package/ide/cursor/rules/documentation.mdc +9 -0
- package/ide/cursor/rules/error-handling-validation.mdc +11 -0
- package/ide/cursor/rules/key-conventions.mdc +11 -0
- package/ide/cursor/rules/project-structure.mdc +169 -0
- package/ide/cursor/rules/readme.mdc +318 -0
- package/ide/cursor/rules/syntax-formatting.mdc +9 -0
- package/ide/cursor/rules/testing.mdc +10 -0
- package/ide/cursor/rules/typescript.mdc +9 -0
- package/ide/cursor/rules/ui-styling.mdc +0 -0
- package/ide/dictionary.txt +397 -0
- package/ide/jetbrains/.fleet/settings.json +4 -0
- package/ide/jetbrains/.idea/.gitignore +5 -0
- package/ide/jetbrains/.idea/.name +1 -0
- package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
- package/ide/jetbrains/.idea/modules.xml +8 -0
- package/ide/jetbrains/.idea/stacks.iml +22 -0
- package/ide/jetbrains/.idea/vcs.xml +6 -0
- package/ide/jetbrains/.idea/webResources.xml +14 -0
- package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
- package/ide/jetbrains/installed.txt +4 -0
- package/ide/jetbrains/options/github-copilot.xml +5 -0
- package/ide/jetbrains/options/nodejs.xml +7 -0
- package/ide/jetbrains/options/templates.xml +124 -0
- package/ide/jetbrains/templates/JavaScript.xml +6 -0
- package/ide/jetbrains/templates/Stacks.xml +8 -0
- package/ide/vscode/.vscode/README.md +23 -0
- package/ide/vscode/.vscode/extensions.json +5 -0
- package/ide/vscode/.vscode/settings.json +176 -0
- package/ide/vscode/.vscode/stacks.code-snippets +181 -0
- package/ide/vscode/LICENSE.md +21 -0
- package/ide/vscode/README.md +36 -0
- package/ide/vscode/logo.png +0 -0
- package/ide/vscode/package.json +79 -0
- package/ide/zed/.zed/settings.json +139 -0
- package/lang/README.md +28 -0
- package/lang/de.yml +14 -0
- package/lang/en.yml +15 -0
- package/package.json +19 -3
- package/project/bootstrap +161 -0
- package/project/buddy +175 -0
- package/project/storage/framework/tsconfig.app.json +50 -0
- package/project/storage/framework/tsconfig.base.json +58 -0
- package/routes/core.ts +78 -0
- package/routes/dashboard-api.ts +233 -0
- package/routes/dashboard.ts +739 -0
- package/routes/email.ts +129 -0
- package/stores/[name].stx +16 -0
- package/stores/git.ts +71 -0
- package/stores/payment.ts +474 -0
- package/stores/queue.ts +43 -0
- package/stores/user.ts +29 -0
- package/stx-components-plugin.ts +25 -0
- package/styles/design-tokens.css +597 -0
- package/types/dashboard.ts +70 -0
- package/types/defaults.ts +438 -0
- package/vcs/github/CODE_OF_CONDUCT.md +83 -0
- package/vcs/github/CONTRIBUTING.md +187 -0
- package/vcs/github/EXPLANATIONS.md +41 -0
- package/vcs/github/FUNDING.yml +1 -0
- package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
- package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
- package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
- package/vcs/github/SECURITY.md +70 -0
- package/vcs/github/renovate.json +5 -0
- package/vcs/github/stale.yml +14 -0
- package/vcs/github/workflows/README.md +16 -0
- package/vcs/github/workflows/ci.yml +114 -0
- package/vcs/github/workflows/export-size.yml +25 -0
- package/vcs/github/workflows/labeler.yml +13 -0
- package/vcs/github/workflows/release.yml +219 -0
- package/views/[...all].stx +8 -0
- package/views/about.md +3 -0
- package/views/auth/login.stx +1 -0
- package/views/auth/signup.stx +85 -0
- package/views/dashboard/.discovered-models.json +542 -0
- package/views/dashboard/AUDIT.md +904 -0
- package/views/dashboard/[...all].stx +89 -0
- package/views/dashboard/access-tokens/index.stx +177 -0
- package/views/dashboard/actions/index.stx +129 -0
- package/views/dashboard/analytics/blog/index.stx +356 -0
- package/views/dashboard/analytics/browsers/index.stx +263 -0
- package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
- package/views/dashboard/analytics/commerce/web/index.stx +379 -0
- package/views/dashboard/analytics/countries/index.stx +289 -0
- package/views/dashboard/analytics/devices/index.stx +305 -0
- package/views/dashboard/analytics/events/index.stx +536 -0
- package/views/dashboard/analytics/index.stx +88 -0
- package/views/dashboard/analytics/marketing/index.stx +315 -0
- package/views/dashboard/analytics/pages/index.stx +271 -0
- package/views/dashboard/analytics/referrers/index.stx +319 -0
- package/views/dashboard/analytics/web/index.stx +356 -0
- package/views/dashboard/buddy/index.stx +198 -0
- package/views/dashboard/ci/index.stx +462 -0
- package/views/dashboard/cloud/index.stx +452 -0
- package/views/dashboard/commands/index.stx +295 -0
- package/views/dashboard/commerce/categories/index.stx +406 -0
- package/views/dashboard/commerce/coupons/index.stx +485 -0
- package/views/dashboard/commerce/customers/index.stx +410 -0
- package/views/dashboard/commerce/dashboard/index.stx +287 -0
- package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
- package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
- package/views/dashboard/commerce/delivery/drivers.stx +397 -0
- package/views/dashboard/commerce/delivery/index.stx +18 -0
- package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
- package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
- package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
- package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
- package/views/dashboard/commerce/delivery/tabs.ts +25 -0
- package/views/dashboard/commerce/gift-cards/index.stx +561 -0
- package/views/dashboard/commerce/manufacturers/index.stx +308 -0
- package/views/dashboard/commerce/orders/index.stx +247 -0
- package/views/dashboard/commerce/payments/index.stx +535 -0
- package/views/dashboard/commerce/pos/index.stx +653 -0
- package/views/dashboard/commerce/printers/devices/index.stx +273 -0
- package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
- package/views/dashboard/commerce/products/detail.stx +563 -0
- package/views/dashboard/commerce/products/index.stx +370 -0
- package/views/dashboard/commerce/reviews/index.stx +656 -0
- package/views/dashboard/commerce/reviews/index.ts +0 -0
- package/views/dashboard/commerce/taxes/index.stx +377 -0
- package/views/dashboard/commerce/units/index.stx +317 -0
- package/views/dashboard/commerce/variants/index.stx +319 -0
- package/views/dashboard/commerce/waitlist/products.stx +942 -0
- package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
- package/views/dashboard/components/index.stx +330 -0
- package/views/dashboard/composables/index.ts +19 -0
- package/views/dashboard/composables/useChart.ts +77 -0
- package/views/dashboard/composables/useNavigation.ts +99 -0
- package/views/dashboard/composables/useRole.ts +58 -0
- package/views/dashboard/composables/useTheme.ts +74 -0
- package/views/dashboard/content/authors/index.stx +171 -0
- package/views/dashboard/content/blog/index.stx +493 -0
- package/views/dashboard/content/categories/index.stx +169 -0
- package/views/dashboard/content/comments/index.stx +189 -0
- package/views/dashboard/content/dashboard.stx +383 -0
- package/views/dashboard/content/files/index.stx +706 -0
- package/views/dashboard/content/pages/index.stx +174 -0
- package/views/dashboard/content/posts/index.stx +269 -0
- package/views/dashboard/content/seo/index.stx +240 -0
- package/views/dashboard/content/tags/index.stx +167 -0
- package/views/dashboard/data/activity/index.stx +261 -0
- package/views/dashboard/data/dashboard/index.stx +116 -0
- package/views/dashboard/data/subscribers.stx +270 -0
- package/views/dashboard/data/teams.stx +275 -0
- package/views/dashboard/data/users.stx +279 -0
- package/views/dashboard/dependencies/index.stx +178 -0
- package/views/dashboard/deployments/[id].stx +234 -0
- package/views/dashboard/deployments/index.stx +9 -0
- package/views/dashboard/dns/index.stx +163 -0
- package/views/dashboard/environment/index.stx +283 -0
- package/views/dashboard/errors/index.stx +274 -0
- package/views/dashboard/forgot-password.stx +57 -0
- package/views/dashboard/functions/index.stx +159 -0
- package/views/dashboard/health/index.stx +248 -0
- package/views/dashboard/inbox/activity.stx +350 -0
- package/views/dashboard/inbox/index.stx +452 -0
- package/views/dashboard/inbox/settings.stx +290 -0
- package/views/dashboard/index.stx +252 -0
- package/views/dashboard/insights/index.stx +529 -0
- package/views/dashboard/jobs/[id].stx +430 -0
- package/views/dashboard/jobs/history.stx +222 -0
- package/views/dashboard/jobs/index.stx +214 -0
- package/views/dashboard/kanban/[id].stx +899 -0
- package/views/dashboard/kanban/index.stx +260 -0
- package/views/dashboard/layouts/default.stx +565 -0
- package/views/dashboard/layouts/guest.stx +10 -0
- package/views/dashboard/login.stx +48 -0
- package/views/dashboard/logs/index.stx +540 -0
- package/views/dashboard/mailboxes/index.stx +149 -0
- package/views/dashboard/management/permissions/index.stx +490 -0
- package/views/dashboard/marketing/campaigns/index.stx +604 -0
- package/views/dashboard/marketing/lists/index.stx +514 -0
- package/views/dashboard/marketing/reviews/index.stx +475 -0
- package/views/dashboard/marketing/social-posts/index.stx +560 -0
- package/views/dashboard/models/[model].stx +195 -0
- package/views/dashboard/models/index.stx +159 -0
- package/views/dashboard/monitoring/errors/index.stx +415 -0
- package/views/dashboard/notifications/dashboard.stx +383 -0
- package/views/dashboard/notifications/email.stx +336 -0
- package/views/dashboard/notifications/history.stx +373 -0
- package/views/dashboard/notifications/sms.stx +332 -0
- package/views/dashboard/packages/index.stx +195 -0
- package/views/dashboard/queries/[id].stx +381 -0
- package/views/dashboard/queries/history.stx +227 -0
- package/views/dashboard/queries/index.stx +335 -0
- package/views/dashboard/queries/slow.stx +318 -0
- package/views/dashboard/queue/index.stx +427 -0
- package/views/dashboard/realtime/index.stx +429 -0
- package/views/dashboard/register.stx +46 -0
- package/views/dashboard/releases/index.stx +389 -0
- package/views/dashboard/requests/index.stx +462 -0
- package/views/dashboard/serverless/index.stx +475 -0
- package/views/dashboard/servers/[id].stx +299 -0
- package/views/dashboard/servers/index.stx +483 -0
- package/views/dashboard/settings/billing.stx +50 -0
- package/views/dashboard/settings/index.stx +256 -0
- package/views/dashboard/settings/mail.stx +252 -0
- package/views/dashboard/stores/auth.ts +123 -0
- package/views/dashboard/stores/ci.ts +342 -0
- package/views/dashboard/stores/index.ts +129 -0
- package/views/dashboard/stores/kanban.ts +723 -0
- package/views/dashboard/stores/rbac.ts +350 -0
- package/views/dashboard/stx.config.ts +34 -0
- package/views/dashboard/teams/[id].stx +170 -0
- package/views/forum/category.stx +92 -0
- package/views/forum/index.stx +209 -0
- package/views/forum/new-topic.stx +113 -0
- package/views/forum/profile.stx +1 -0
- package/views/forum/topic.stx +143 -0
- package/views/hello-world/[name].stx +47 -0
- package/views/index.stx +21 -0
- package/views/system-tray/index.stx +147 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { WaitlistProduct } from '../../../types/defaults'
|
|
2
|
+
import { useStorage } from '@stacksjs/browser'
|
|
3
|
+
import { pushToast } from '../../toasts'
|
|
4
|
+
|
|
5
|
+
// Create a persistent waitlist products array using STX useStorage
|
|
6
|
+
const waitlistProducts = useStorage<WaitlistProduct[]>('waitlist_products', [])
|
|
7
|
+
|
|
8
|
+
const baseURL = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
9
|
+
|
|
10
|
+
// Basic fetch function to get all waitlist products
|
|
11
|
+
async function fetchWaitlistProducts() {
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/products`)
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
16
|
+
}
|
|
17
|
+
const data = await response.json() as WaitlistProduct[]
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(data)) {
|
|
20
|
+
waitlistProducts.value = data
|
|
21
|
+
return data
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
pushToast('error', 'Couldn\'t load waitlist products', { detail: 'Server returned a non-array response' })
|
|
25
|
+
return []
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
pushToast('error', 'Error fetching waitlist products', { detail: String(error) })
|
|
30
|
+
return []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function createWaitlistProduct(waitlistProduct: WaitlistProduct) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/products`, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify(waitlistProduct),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const data = await response.json() as WaitlistProduct
|
|
49
|
+
if (data) {
|
|
50
|
+
waitlistProducts.value.push(data)
|
|
51
|
+
return data
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
pushToast('error', 'Error creating waitlist product', { detail: String(error) })
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function updateWaitlistProduct(waitlistProduct: WaitlistProduct) {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/products/${waitlistProduct.id}`, {
|
|
64
|
+
method: 'PATCH',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify(waitlistProduct),
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const data = await response.json() as WaitlistProduct
|
|
76
|
+
if (data) {
|
|
77
|
+
const index = waitlistProducts.value.findIndex(wp => wp.id === waitlistProduct.id)
|
|
78
|
+
if (index !== -1) {
|
|
79
|
+
waitlistProducts.value[index] = data
|
|
80
|
+
}
|
|
81
|
+
return data
|
|
82
|
+
}
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
pushToast('error', 'Error updating waitlist product', { detail: String(error) })
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function deleteWaitlistProduct(id: number) {
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/products/${id}`, {
|
|
94
|
+
method: 'DELETE',
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const index = waitlistProducts.value.findIndex(wp => wp.id === id)
|
|
102
|
+
if (index !== -1) {
|
|
103
|
+
waitlistProducts.value.splice(index, 1)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
pushToast('error', 'Error deleting waitlist product', { detail: String(error) })
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Export the composable
|
|
115
|
+
export function useWaitlistProducts() {
|
|
116
|
+
return {
|
|
117
|
+
waitlistProducts,
|
|
118
|
+
fetchWaitlistProducts,
|
|
119
|
+
createWaitlistProduct,
|
|
120
|
+
updateWaitlistProduct,
|
|
121
|
+
deleteWaitlistProduct,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { WaitlistRestaurant } from '../../../types/defaults'
|
|
2
|
+
import { useStorage } from '@stacksjs/browser'
|
|
3
|
+
import { pushToast } from '../../toasts'
|
|
4
|
+
|
|
5
|
+
// Create a persistent waitlist restaurants array using STX useStorage
|
|
6
|
+
const waitlistRestaurants = useStorage<WaitlistRestaurant[]>('waitlist_restaurants', [])
|
|
7
|
+
|
|
8
|
+
const baseURL = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
9
|
+
|
|
10
|
+
// Basic fetch function to get all waitlist restaurants
|
|
11
|
+
async function fetchWaitlistRestaurants() {
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/restaurants`)
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
16
|
+
}
|
|
17
|
+
const data = await response.json() as WaitlistRestaurant[]
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(data)) {
|
|
20
|
+
waitlistRestaurants.value = data
|
|
21
|
+
return data
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
pushToast('error', 'Couldn\'t load waitlist restaurants', { detail: 'Server returned a non-array response' })
|
|
25
|
+
return []
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
pushToast('error', 'Error fetching waitlist restaurants', { detail: String(error) })
|
|
30
|
+
return []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function createWaitlistRestaurant(waitlistRestaurant: WaitlistRestaurant) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/restaurants`, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify(waitlistRestaurant),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const data = await response.json() as WaitlistRestaurant
|
|
49
|
+
if (data) {
|
|
50
|
+
waitlistRestaurants.value.push(data)
|
|
51
|
+
return data
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
pushToast('error', 'Error creating waitlist restaurant', { detail: String(error) })
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function updateWaitlistRestaurant(waitlistRestaurant: WaitlistRestaurant) {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/restaurants/${waitlistRestaurant.id}`, {
|
|
64
|
+
method: 'PATCH',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify(waitlistRestaurant),
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const data = await response.json() as WaitlistRestaurant
|
|
76
|
+
if (data) {
|
|
77
|
+
const index = waitlistRestaurants.value.findIndex(wr => wr.id === waitlistRestaurant.id)
|
|
78
|
+
if (index !== -1) {
|
|
79
|
+
waitlistRestaurants.value[index] = data
|
|
80
|
+
}
|
|
81
|
+
return data
|
|
82
|
+
}
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
pushToast('error', 'Error updating waitlist restaurant', { detail: String(error) })
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function deleteWaitlistRestaurant(id: number) {
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(`${baseURL}/commerce/waitlist/restaurants/${id}`, {
|
|
94
|
+
method: 'DELETE',
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const index = waitlistRestaurants.value.findIndex(wr => wr.id === id)
|
|
102
|
+
if (index !== -1) {
|
|
103
|
+
waitlistRestaurants.value.splice(index, 1)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
pushToast('error', 'Error deleting waitlist restaurant', { detail: String(error) })
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Export the composable
|
|
115
|
+
export function useWaitlistRestaurants() {
|
|
116
|
+
return {
|
|
117
|
+
waitlistRestaurants,
|
|
118
|
+
fetchWaitlistRestaurants,
|
|
119
|
+
createWaitlistRestaurant,
|
|
120
|
+
updateWaitlistRestaurant,
|
|
121
|
+
deleteWaitlistRestaurant,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Craft Native App Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for interacting with the Craft native app environment.
|
|
5
|
+
* These functions are safe to call in both web and native environments.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Check if running in Craft native environment
|
|
10
|
+
*/
|
|
11
|
+
export function isCraftNative(): boolean {
|
|
12
|
+
return typeof window !== 'undefined' && window.craft?.window !== undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the Craft bridge API (returns undefined in web environment)
|
|
17
|
+
*/
|
|
18
|
+
export function useCraft() {
|
|
19
|
+
if (!isCraftNative()) {
|
|
20
|
+
return {
|
|
21
|
+
isNative: false,
|
|
22
|
+
window: undefined,
|
|
23
|
+
app: undefined,
|
|
24
|
+
tray: undefined,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
isNative: true,
|
|
30
|
+
window: window.craft?.window,
|
|
31
|
+
app: window.craft?.app,
|
|
32
|
+
tray: window.craft?.tray,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Window control functions that work in both web and native environments
|
|
38
|
+
*/
|
|
39
|
+
export function useWindowControls() {
|
|
40
|
+
const { isNative, window: craftWindow } = useCraft()
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
isNative,
|
|
44
|
+
|
|
45
|
+
minimize: async () => {
|
|
46
|
+
if (isNative && craftWindow) {
|
|
47
|
+
await craftWindow.minimize()
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
close: async () => {
|
|
52
|
+
if (isNative && craftWindow) {
|
|
53
|
+
await craftWindow.close()
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
toggle: async () => {
|
|
58
|
+
if (isNative && craftWindow) {
|
|
59
|
+
await craftWindow.toggle()
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
show: async () => {
|
|
64
|
+
if (isNative && craftWindow) {
|
|
65
|
+
await craftWindow.show()
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
hide: async () => {
|
|
70
|
+
if (isNative && craftWindow) {
|
|
71
|
+
await craftWindow.hide()
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* App control functions
|
|
79
|
+
*/
|
|
80
|
+
export function useAppControls() {
|
|
81
|
+
const { isNative, app } = useCraft()
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
isNative,
|
|
85
|
+
|
|
86
|
+
quit: async () => {
|
|
87
|
+
if (isNative && app) {
|
|
88
|
+
await app.quit()
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
notify: async (title: string, body?: string) => {
|
|
93
|
+
if (isNative && app) {
|
|
94
|
+
await app.notify({ title, body })
|
|
95
|
+
} else if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
|
|
96
|
+
new Notification(title, { body })
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
getInfo: async () => {
|
|
101
|
+
if (isNative && app) {
|
|
102
|
+
return app.getInfo()
|
|
103
|
+
}
|
|
104
|
+
return { name: 'Stacks Dashboard', version: '0.0.0', platform: 'web' }
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides data fetching for the main dashboard overview.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ref } from '@stacksjs/stx'
|
|
8
|
+
|
|
9
|
+
const baseUrl = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
10
|
+
|
|
11
|
+
export interface DashboardStats {
|
|
12
|
+
title: string
|
|
13
|
+
value: string
|
|
14
|
+
trend: number
|
|
15
|
+
trendLabel: string
|
|
16
|
+
icon: string
|
|
17
|
+
iconBg: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ActivityItem {
|
|
21
|
+
id: number
|
|
22
|
+
type: string
|
|
23
|
+
title: string
|
|
24
|
+
time: string
|
|
25
|
+
status: 'success' | 'error' | 'warning'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SystemHealthItem {
|
|
29
|
+
name: string
|
|
30
|
+
status: 'healthy' | 'degraded' | 'critical'
|
|
31
|
+
latency: string
|
|
32
|
+
uptime: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Default fallback data
|
|
36
|
+
const defaultStats: DashboardStats[] = [
|
|
37
|
+
{ title: 'Total Users', value: '0', trend: 0, trendLabel: 'vs last period', icon: 'i-hugeicons-user-group', iconBg: 'primary' },
|
|
38
|
+
{ title: 'Active Projects', value: '0', trend: 0, trendLabel: 'vs last period', icon: 'i-hugeicons-folder-02', iconBg: 'success' },
|
|
39
|
+
{ title: 'Cloud Uptime', value: '0%', trend: 0, trendLabel: 'vs last period', icon: 'i-hugeicons-cloud', iconBg: 'info' },
|
|
40
|
+
{ title: 'Response Time', value: '0ms', trend: 0, trendLabel: 'vs last period', icon: 'i-hugeicons-time-02', iconBg: 'warning' },
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
const defaultActivity: ActivityItem[] = []
|
|
44
|
+
|
|
45
|
+
const defaultHealth: SystemHealthItem[] = [
|
|
46
|
+
{ name: 'API', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
47
|
+
{ name: 'Database', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
48
|
+
{ name: 'Storage', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
49
|
+
{ name: 'Cache', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
50
|
+
{ name: 'Queue', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
51
|
+
{ name: 'Notifications', status: 'healthy', latency: '0ms', uptime: '0%' },
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
export function useDashboard() {
|
|
55
|
+
const stats = ref<DashboardStats[]>(defaultStats)
|
|
56
|
+
const recentActivity = ref<ActivityItem[]>(defaultActivity)
|
|
57
|
+
const systemHealth = ref<SystemHealthItem[]>(defaultHealth)
|
|
58
|
+
const isLoading = ref(false)
|
|
59
|
+
const error = ref<string | null>(null)
|
|
60
|
+
|
|
61
|
+
async function fetchDashboardStats(timeRange = '7d') {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`${baseUrl}/dashboard/stats?range=${timeRange}`, {
|
|
64
|
+
headers: {
|
|
65
|
+
'Accept': 'application/json',
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
if (response.ok) {
|
|
70
|
+
const data = await response.json()
|
|
71
|
+
stats.value = data.stats || defaultStats
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.error('Failed to fetch dashboard stats:', e)
|
|
76
|
+
throw e
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function fetchRecentActivity() {
|
|
81
|
+
try {
|
|
82
|
+
const response = await fetch(`${baseUrl}/dashboard/activity`, {
|
|
83
|
+
headers: {
|
|
84
|
+
'Accept': 'application/json',
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
if (response.ok) {
|
|
89
|
+
const data = await response.json()
|
|
90
|
+
recentActivity.value = data.activity || defaultActivity
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
console.error('Failed to fetch recent activity:', e)
|
|
95
|
+
throw e
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function fetchSystemHealth() {
|
|
100
|
+
try {
|
|
101
|
+
const response = await fetch(`${baseUrl}/health`, {
|
|
102
|
+
headers: {
|
|
103
|
+
'Accept': 'application/json',
|
|
104
|
+
},
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (response.ok) {
|
|
108
|
+
const data = await response.json()
|
|
109
|
+
systemHealth.value = data.services || defaultHealth
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
console.error('Failed to fetch system health:', e)
|
|
114
|
+
throw e
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function fetchAll(timeRange = '7d') {
|
|
119
|
+
isLoading.value = true
|
|
120
|
+
error.value = null
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await Promise.all([
|
|
124
|
+
fetchDashboardStats(timeRange),
|
|
125
|
+
fetchRecentActivity(),
|
|
126
|
+
fetchSystemHealth(),
|
|
127
|
+
])
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
error.value = 'Failed to load dashboard data. Please try again.'
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
isLoading.value = false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function retry(timeRange = '7d') {
|
|
138
|
+
return fetchAll(timeRange)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
stats,
|
|
143
|
+
recentActivity,
|
|
144
|
+
systemHealth,
|
|
145
|
+
isLoading,
|
|
146
|
+
error,
|
|
147
|
+
fetchDashboardStats,
|
|
148
|
+
fetchRecentActivity,
|
|
149
|
+
fetchSystemHealth,
|
|
150
|
+
fetchAll,
|
|
151
|
+
retry,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbox Composable
|
|
3
|
+
*
|
|
4
|
+
* Reads captured transactional emails from the framework's mail log driver
|
|
5
|
+
* (in-memory + storage/logs/mail/*.html) for the dashboard inbox view.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ref } from '@stacksjs/stx'
|
|
9
|
+
import { get } from './api'
|
|
10
|
+
|
|
11
|
+
export interface InboxEntry {
|
|
12
|
+
id: string
|
|
13
|
+
source: 'memory' | 'disk'
|
|
14
|
+
from: string
|
|
15
|
+
to: string
|
|
16
|
+
subject: string
|
|
17
|
+
preview: string
|
|
18
|
+
sent_at: string
|
|
19
|
+
has_html: boolean
|
|
20
|
+
has_text: boolean
|
|
21
|
+
size: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InboxBody {
|
|
25
|
+
id: string
|
|
26
|
+
from: string
|
|
27
|
+
to: string
|
|
28
|
+
cc?: string
|
|
29
|
+
bcc?: string
|
|
30
|
+
subject: string
|
|
31
|
+
sent_at: string
|
|
32
|
+
html: string
|
|
33
|
+
text: string
|
|
34
|
+
error?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useInbox() {
|
|
38
|
+
const emails = ref<InboxEntry[]>([])
|
|
39
|
+
const driver = ref<string>('log')
|
|
40
|
+
const total = ref(0)
|
|
41
|
+
const isLoading = ref(false)
|
|
42
|
+
const error = ref<string | null>(null)
|
|
43
|
+
const selected = ref<InboxBody | null>(null)
|
|
44
|
+
|
|
45
|
+
async function fetchEmails() {
|
|
46
|
+
isLoading.value = true
|
|
47
|
+
error.value = null
|
|
48
|
+
try {
|
|
49
|
+
const data = await get<{ data: InboxEntry[], total: number, driver: string }>('/inbox')
|
|
50
|
+
emails.value = data.data || []
|
|
51
|
+
total.value = data.total || 0
|
|
52
|
+
driver.value = data.driver || 'log'
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
error.value = 'Failed to load inbox.'
|
|
56
|
+
console.error('Failed to fetch inbox:', e)
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
isLoading.value = false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function openEmail(id: string) {
|
|
64
|
+
error.value = null
|
|
65
|
+
try {
|
|
66
|
+
const data = await get<InboxBody>(`/inbox/${encodeURIComponent(id)}`)
|
|
67
|
+
if (data.error) {
|
|
68
|
+
error.value = data.error
|
|
69
|
+
selected.value = null
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
selected.value = data
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
error.value = 'Failed to open email.'
|
|
76
|
+
console.error('Failed to fetch email:', e)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function closeEmail() {
|
|
81
|
+
selected.value = null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
emails,
|
|
86
|
+
driver,
|
|
87
|
+
total,
|
|
88
|
+
isLoading,
|
|
89
|
+
error,
|
|
90
|
+
selected,
|
|
91
|
+
fetchEmails,
|
|
92
|
+
openEmail,
|
|
93
|
+
closeEmail,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jobs Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides data fetching for job history and queue management.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ref } from '@stacksjs/stx'
|
|
8
|
+
import { get, post } from './api'
|
|
9
|
+
|
|
10
|
+
export interface JobHistoryEntry {
|
|
11
|
+
id: string
|
|
12
|
+
name: string
|
|
13
|
+
queue: string
|
|
14
|
+
status: 'queued' | 'processing' | 'failed' | 'completed'
|
|
15
|
+
attempts: number
|
|
16
|
+
runtime?: number
|
|
17
|
+
started_at?: string
|
|
18
|
+
finished_at?: string
|
|
19
|
+
error?: string
|
|
20
|
+
payload: any
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useJobs() {
|
|
24
|
+
const jobs = ref<JobHistoryEntry[]>([])
|
|
25
|
+
const totalJobs = ref(0)
|
|
26
|
+
const isLoading = ref(false)
|
|
27
|
+
const error = ref<string | null>(null)
|
|
28
|
+
|
|
29
|
+
async function fetchJobs(params?: { page?: number, perPage?: number, queue?: string, status?: string, search?: string }) {
|
|
30
|
+
isLoading.value = true
|
|
31
|
+
error.value = null
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const query = new URLSearchParams()
|
|
35
|
+
if (params?.page) query.set('page', String(params.page))
|
|
36
|
+
if (params?.perPage) query.set('per_page', String(params.perPage))
|
|
37
|
+
if (params?.queue && params.queue !== 'all') query.set('queue', params.queue)
|
|
38
|
+
if (params?.status && params.status !== 'all') query.set('status', params.status)
|
|
39
|
+
if (params?.search) query.set('search', params.search)
|
|
40
|
+
|
|
41
|
+
const data = await get<{ data: JobHistoryEntry[], total: number }>(`/jobs?${query.toString()}`)
|
|
42
|
+
jobs.value = data.data || []
|
|
43
|
+
totalJobs.value = data.total || 0
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
error.value = 'Failed to load job history.'
|
|
47
|
+
console.error('Failed to fetch jobs:', e)
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
isLoading.value = false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function retryJob(jobId: string) {
|
|
55
|
+
try {
|
|
56
|
+
await post(`/jobs/${jobId}/retry`)
|
|
57
|
+
// Refresh the job list after retry
|
|
58
|
+
await fetchJobs()
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
error.value = `Failed to retry job ${jobId}.`
|
|
62
|
+
console.error('Failed to retry job:', e)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function retryFailedJobs() {
|
|
67
|
+
try {
|
|
68
|
+
await post('/queue/retry-failed')
|
|
69
|
+
await fetchJobs()
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
error.value = 'Failed to retry failed jobs.'
|
|
73
|
+
console.error('Failed to retry failed jobs:', e)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
jobs,
|
|
79
|
+
totalJobs,
|
|
80
|
+
isLoading,
|
|
81
|
+
error,
|
|
82
|
+
fetchJobs,
|
|
83
|
+
retryJob,
|
|
84
|
+
retryFailedJobs,
|
|
85
|
+
}
|
|
86
|
+
}
|