@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,295 @@
|
|
|
1
|
+
import { useStorage } from '@stacksjs/browser'
|
|
2
|
+
|
|
3
|
+
export interface GroupedError {
|
|
4
|
+
id: number
|
|
5
|
+
type: string
|
|
6
|
+
message: string
|
|
7
|
+
stack: string | null
|
|
8
|
+
status: string
|
|
9
|
+
count: number
|
|
10
|
+
first_seen: string
|
|
11
|
+
last_seen: string
|
|
12
|
+
error_ids: number[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ErrorRecord {
|
|
16
|
+
id: number
|
|
17
|
+
type: string
|
|
18
|
+
message: string
|
|
19
|
+
stack: string | null
|
|
20
|
+
status: number | null
|
|
21
|
+
additional_info: string | null
|
|
22
|
+
created_at: string
|
|
23
|
+
updated_at: string | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ErrorStats {
|
|
27
|
+
total: number
|
|
28
|
+
unresolved: number
|
|
29
|
+
resolved: number
|
|
30
|
+
ignored: number
|
|
31
|
+
last_24h: number
|
|
32
|
+
trend: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ErrorTimelinePoint {
|
|
36
|
+
hour: string
|
|
37
|
+
count: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Create persistent storage for errors data
|
|
41
|
+
const groupedErrors = useStorage<GroupedError[]>('grouped-errors', [])
|
|
42
|
+
const errorStats = useStorage<ErrorStats | null>('error-stats', null)
|
|
43
|
+
const errorTimeline = useStorage<ErrorTimelinePoint[]>('error-timeline', [])
|
|
44
|
+
|
|
45
|
+
const baseURL = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Fetch all grouped errors
|
|
49
|
+
*/
|
|
50
|
+
async function fetchGroupedErrors(): Promise<GroupedError[]> {
|
|
51
|
+
try {
|
|
52
|
+
const response = await fetch(`${baseURL}/monitoring/errors`)
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
55
|
+
}
|
|
56
|
+
const { data } = await response.json() as { data: GroupedError[] }
|
|
57
|
+
|
|
58
|
+
if (Array.isArray(data)) {
|
|
59
|
+
groupedErrors.value = data
|
|
60
|
+
return data
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.error('Expected array of errors but received:', typeof data)
|
|
64
|
+
return []
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('Error fetching grouped errors:', error)
|
|
69
|
+
return groupedErrors.value
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Fetch a single error by ID
|
|
75
|
+
*/
|
|
76
|
+
async function fetchErrorById(id: number): Promise<ErrorRecord | null> {
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(`${baseURL}/monitoring/errors/${id}`)
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
81
|
+
}
|
|
82
|
+
const { data } = await response.json() as { data: ErrorRecord }
|
|
83
|
+
return data
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error('Error fetching error by ID:', error)
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Fetch all errors in a specific group
|
|
93
|
+
*/
|
|
94
|
+
async function fetchErrorGroup(type: string, message: string): Promise<ErrorRecord[]> {
|
|
95
|
+
try {
|
|
96
|
+
const params = new URLSearchParams({
|
|
97
|
+
type: encodeURIComponent(type),
|
|
98
|
+
message: encodeURIComponent(message),
|
|
99
|
+
})
|
|
100
|
+
const response = await fetch(`${baseURL}/monitoring/errors/group?${params}`)
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
103
|
+
}
|
|
104
|
+
const { data } = await response.json() as { data: ErrorRecord[] }
|
|
105
|
+
return data || []
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
console.error('Error fetching error group:', error)
|
|
109
|
+
return []
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Fetch error statistics
|
|
115
|
+
*/
|
|
116
|
+
async function fetchErrorStats(): Promise<ErrorStats | null> {
|
|
117
|
+
try {
|
|
118
|
+
const response = await fetch(`${baseURL}/monitoring/errors/stats`)
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
121
|
+
}
|
|
122
|
+
const { data } = await response.json() as { data: ErrorStats }
|
|
123
|
+
errorStats.value = data
|
|
124
|
+
return data
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.error('Error fetching error stats:', error)
|
|
128
|
+
return errorStats.value
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Fetch error timeline
|
|
134
|
+
*/
|
|
135
|
+
async function fetchErrorTimeline(): Promise<ErrorTimelinePoint[]> {
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(`${baseURL}/monitoring/errors/timeline`)
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
140
|
+
}
|
|
141
|
+
const { data } = await response.json() as { data: ErrorTimelinePoint[] }
|
|
142
|
+
errorTimeline.value = data
|
|
143
|
+
return data
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error('Error fetching error timeline:', error)
|
|
147
|
+
return errorTimeline.value
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Resolve all errors in a group
|
|
153
|
+
*/
|
|
154
|
+
async function resolveErrorGroup(type: string, message: string): Promise<boolean> {
|
|
155
|
+
try {
|
|
156
|
+
const response = await fetch(`${baseURL}/monitoring/errors/resolve`, {
|
|
157
|
+
method: 'PATCH',
|
|
158
|
+
headers: {
|
|
159
|
+
'Content-Type': 'application/json',
|
|
160
|
+
},
|
|
161
|
+
body: JSON.stringify({ type, message }),
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Update local state
|
|
169
|
+
const index = groupedErrors.value.findIndex(
|
|
170
|
+
e => e.type === type && e.message === message,
|
|
171
|
+
)
|
|
172
|
+
if (index !== -1) {
|
|
173
|
+
groupedErrors.value[index].status = 'resolved'
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return true
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
console.error('Error resolving error group:', error)
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Ignore all errors in a group
|
|
186
|
+
*/
|
|
187
|
+
async function ignoreErrorGroup(type: string, message: string): Promise<boolean> {
|
|
188
|
+
try {
|
|
189
|
+
const response = await fetch(`${baseURL}/monitoring/errors/ignore`, {
|
|
190
|
+
method: 'PATCH',
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': 'application/json',
|
|
193
|
+
},
|
|
194
|
+
body: JSON.stringify({ type, message }),
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
if (!response.ok) {
|
|
198
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Update local state
|
|
202
|
+
const index = groupedErrors.value.findIndex(
|
|
203
|
+
e => e.type === type && e.message === message,
|
|
204
|
+
)
|
|
205
|
+
if (index !== -1) {
|
|
206
|
+
groupedErrors.value[index].status = 'ignored'
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return true
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error('Error ignoring error group:', error)
|
|
213
|
+
return false
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Unresolve (reopen) all errors in a group
|
|
219
|
+
*/
|
|
220
|
+
async function unresolveErrorGroup(type: string, message: string): Promise<boolean> {
|
|
221
|
+
try {
|
|
222
|
+
const response = await fetch(`${baseURL}/monitoring/errors/unresolve`, {
|
|
223
|
+
method: 'PATCH',
|
|
224
|
+
headers: {
|
|
225
|
+
'Content-Type': 'application/json',
|
|
226
|
+
},
|
|
227
|
+
body: JSON.stringify({ type, message }),
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Update local state
|
|
235
|
+
const index = groupedErrors.value.findIndex(
|
|
236
|
+
e => e.type === type && e.message === message,
|
|
237
|
+
)
|
|
238
|
+
if (index !== -1) {
|
|
239
|
+
groupedErrors.value[index].status = 'unresolved'
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error('Error unresolving error group:', error)
|
|
246
|
+
return false
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Delete all errors in a group
|
|
252
|
+
*/
|
|
253
|
+
async function deleteErrorGroup(type: string, message: string): Promise<boolean> {
|
|
254
|
+
try {
|
|
255
|
+
const params = new URLSearchParams({
|
|
256
|
+
type: encodeURIComponent(type),
|
|
257
|
+
message: encodeURIComponent(message),
|
|
258
|
+
})
|
|
259
|
+
const response = await fetch(`${baseURL}/monitoring/errors?${params}`, {
|
|
260
|
+
method: 'DELETE',
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
if (!response.ok) {
|
|
264
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Update local state
|
|
268
|
+
groupedErrors.value = groupedErrors.value.filter(
|
|
269
|
+
e => !(e.type === type && e.message === message),
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
return true
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
console.error('Error deleting error group:', error)
|
|
276
|
+
return false
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function useErrors() {
|
|
281
|
+
return {
|
|
282
|
+
groupedErrors,
|
|
283
|
+
errorStats,
|
|
284
|
+
errorTimeline,
|
|
285
|
+
fetchGroupedErrors,
|
|
286
|
+
fetchErrorById,
|
|
287
|
+
fetchErrorGroup,
|
|
288
|
+
fetchErrorStats,
|
|
289
|
+
fetchErrorTimeline,
|
|
290
|
+
resolveErrorGroup,
|
|
291
|
+
ignoreErrorGroup,
|
|
292
|
+
unresolveErrorGroup,
|
|
293
|
+
deleteErrorGroup,
|
|
294
|
+
}
|
|
295
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides data fetching for the queue dashboard. The shape mirrors what
|
|
5
|
+
* `/queue/stats` and `/queue/workers` return, which in turn pull from the
|
|
6
|
+
* framework's Job ORM and `@stacksjs/queue` metrics tracker.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ref } from '@stacksjs/stx'
|
|
10
|
+
import { get, post } from './api'
|
|
11
|
+
|
|
12
|
+
export interface QueueBucket {
|
|
13
|
+
name: string
|
|
14
|
+
status: 'active' | 'idle'
|
|
15
|
+
pending: number
|
|
16
|
+
active: number
|
|
17
|
+
completed: number
|
|
18
|
+
failed: number
|
|
19
|
+
total: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface QueueAggregateStats {
|
|
23
|
+
totalQueues: number
|
|
24
|
+
totalJobs: number
|
|
25
|
+
activeJobs: number
|
|
26
|
+
completedJobs: number
|
|
27
|
+
failedJobs: number
|
|
28
|
+
throughputPerMinute: number
|
|
29
|
+
averageProcessingTimeMs: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface QueueWorker {
|
|
33
|
+
id: string
|
|
34
|
+
name: string
|
|
35
|
+
status: 'running' | 'paused' | 'stopped'
|
|
36
|
+
queues: string[]
|
|
37
|
+
jobs_processed: number
|
|
38
|
+
failed_jobs: number
|
|
39
|
+
uptime: string
|
|
40
|
+
last_heartbeat: string
|
|
41
|
+
memory: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function useQueue() {
|
|
45
|
+
const queues = ref<QueueBucket[]>([])
|
|
46
|
+
const stats = ref<QueueAggregateStats>({
|
|
47
|
+
totalQueues: 0,
|
|
48
|
+
totalJobs: 0,
|
|
49
|
+
activeJobs: 0,
|
|
50
|
+
completedJobs: 0,
|
|
51
|
+
failedJobs: 0,
|
|
52
|
+
throughputPerMinute: 0,
|
|
53
|
+
averageProcessingTimeMs: 0,
|
|
54
|
+
})
|
|
55
|
+
const workers = ref<QueueWorker[]>([])
|
|
56
|
+
const queueConnected = ref(false)
|
|
57
|
+
const isLoading = ref(false)
|
|
58
|
+
const error = ref<string | null>(null)
|
|
59
|
+
|
|
60
|
+
async function fetchStats() {
|
|
61
|
+
const data = await get<{ queues: QueueBucket[], stats: QueueAggregateStats, queueConnected: boolean }>('/queue/stats')
|
|
62
|
+
queues.value = data.queues || []
|
|
63
|
+
stats.value = data.stats || stats.value
|
|
64
|
+
queueConnected.value = Boolean(data.queueConnected)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function fetchWorkers() {
|
|
68
|
+
const data = await get<{ data: QueueWorker[] }>('/queue/workers')
|
|
69
|
+
workers.value = data.data || []
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function fetchAll() {
|
|
73
|
+
isLoading.value = true
|
|
74
|
+
error.value = null
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await Promise.all([fetchStats(), fetchWorkers()])
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
error.value = 'Failed to load queue data.'
|
|
81
|
+
console.error('Failed to fetch queue data:', e)
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
isLoading.value = false
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function retryFailedJobs() {
|
|
89
|
+
try {
|
|
90
|
+
await post<{ success: boolean, count: number, message: string }>('/queue/retry-failed')
|
|
91
|
+
await fetchAll()
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
error.value = 'Failed to retry failed jobs.'
|
|
95
|
+
console.error('Failed to retry failed jobs:', e)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
queues,
|
|
101
|
+
stats,
|
|
102
|
+
workers,
|
|
103
|
+
queueConnected,
|
|
104
|
+
isLoading,
|
|
105
|
+
error,
|
|
106
|
+
fetchStats,
|
|
107
|
+
fetchWorkers,
|
|
108
|
+
fetchAll,
|
|
109
|
+
retryFailedJobs,
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { StoreWebsocket, Websockets } from '../../types/defaults'
|
|
2
|
+
import { useFetch, useStorage } from '@stacksjs/browser'
|
|
3
|
+
|
|
4
|
+
const baseURL = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
5
|
+
|
|
6
|
+
// Create a persistent websockets array using STX useStorage
|
|
7
|
+
const websockets = useStorage<Websockets[]>('websockets', [])
|
|
8
|
+
|
|
9
|
+
// Basic fetch function to get all websocket events
|
|
10
|
+
async function fetchWebsockets() {
|
|
11
|
+
const { error, data } = await useFetch(`${baseURL}/realtime/websockets`).get().json()
|
|
12
|
+
|
|
13
|
+
const websocketsJson = data.value as Websockets[]
|
|
14
|
+
if (error.value) {
|
|
15
|
+
console.error('Error fetching websocket events:', error.value)
|
|
16
|
+
return []
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ensure data is an array before assigning
|
|
20
|
+
if (Array.isArray(data.value)) {
|
|
21
|
+
websockets.value = websocketsJson
|
|
22
|
+
return data.value
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.error('Expected array of websocket events but received:', typeof data.value)
|
|
26
|
+
return []
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function createWebsocket(websocket: Partial<StoreWebsocket>): Promise<Websockets | null> {
|
|
31
|
+
const { error, data } = await useFetch(`${baseURL}/realtime/websockets`)
|
|
32
|
+
.post(JSON.stringify(websocket))
|
|
33
|
+
.json()
|
|
34
|
+
|
|
35
|
+
if (error.value) {
|
|
36
|
+
console.error('Error creating websocket event:', error.value)
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const newWebsocket = data.value as Websockets
|
|
41
|
+
if (newWebsocket) {
|
|
42
|
+
websockets.value.unshift(newWebsocket)
|
|
43
|
+
return newWebsocket
|
|
44
|
+
}
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function updateWebsocket(id: number, websocket: Partial<Websockets>) {
|
|
49
|
+
const { error, data } = await useFetch(`${baseURL}/realtime/websockets/${id}`)
|
|
50
|
+
.patch(JSON.stringify(websocket))
|
|
51
|
+
.json()
|
|
52
|
+
|
|
53
|
+
if (error.value) {
|
|
54
|
+
console.error('Error updating websocket event:', error.value)
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const updatedWebsocket = data.value as Websockets
|
|
59
|
+
if (updatedWebsocket) {
|
|
60
|
+
const index = websockets.value.findIndex(w => w.id === id)
|
|
61
|
+
if (index !== -1) {
|
|
62
|
+
websockets.value[index] = updatedWebsocket
|
|
63
|
+
}
|
|
64
|
+
return updatedWebsocket
|
|
65
|
+
}
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function deleteWebsocket(id: number) {
|
|
70
|
+
const { error } = await useFetch(`${baseURL}/realtime/websockets/${id}`)
|
|
71
|
+
.delete()
|
|
72
|
+
.json()
|
|
73
|
+
|
|
74
|
+
if (error.value) {
|
|
75
|
+
console.error('Error deleting websocket event:', error.value)
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const index = websockets.value.findIndex(w => w.id === id)
|
|
80
|
+
if (index !== -1) {
|
|
81
|
+
websockets.value.splice(index, 1)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Export the composable
|
|
88
|
+
export function useWebsockets() {
|
|
89
|
+
return {
|
|
90
|
+
websockets,
|
|
91
|
+
fetchWebsockets,
|
|
92
|
+
createWebsocket,
|
|
93
|
+
updateWebsocket,
|
|
94
|
+
deleteWebsocket,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime Composable
|
|
3
|
+
*/
|
|
4
|
+
import { ref } from '@stacksjs/stx'
|
|
5
|
+
|
|
6
|
+
const baseUrl = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
7
|
+
|
|
8
|
+
export interface RealtimeStats {
|
|
9
|
+
connectionsTriggered: number
|
|
10
|
+
connectionsChange: number
|
|
11
|
+
avgLatency: string
|
|
12
|
+
latencyChange: number
|
|
13
|
+
successRate: string
|
|
14
|
+
successChange: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ActiveConnection {
|
|
18
|
+
id: string
|
|
19
|
+
client: string
|
|
20
|
+
status: string
|
|
21
|
+
uptime: string
|
|
22
|
+
messages: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useRealtimeStats() {
|
|
26
|
+
const stats = ref<RealtimeStats>({ connectionsTriggered: 0, connectionsChange: 0, avgLatency: '0ms', latencyChange: 0, successRate: '0%', successChange: 0 })
|
|
27
|
+
const activeConnections = ref<ActiveConnection[]>([])
|
|
28
|
+
const isLoading = ref(false)
|
|
29
|
+
const error = ref<string | null>(null)
|
|
30
|
+
|
|
31
|
+
async function fetchStats() {
|
|
32
|
+
isLoading.value = true
|
|
33
|
+
error.value = null
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(`${baseUrl}/realtime/stats`, {
|
|
36
|
+
headers: { 'Accept': 'application/json' },
|
|
37
|
+
})
|
|
38
|
+
if (response.ok) {
|
|
39
|
+
const data = await response.json()
|
|
40
|
+
stats.value = data.stats || stats.value
|
|
41
|
+
activeConnections.value = data.activeConnections || []
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
error.value = 'Failed to load realtime stats.'
|
|
45
|
+
console.error('Failed to fetch realtime stats:', e)
|
|
46
|
+
} finally {
|
|
47
|
+
isLoading.value = false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { stats, activeConnections, isLoading, error, fetchStats }
|
|
52
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Releases Composable
|
|
3
|
+
*/
|
|
4
|
+
import { ref } from '@stacksjs/stx'
|
|
5
|
+
|
|
6
|
+
const baseUrl = process.env.VITE_API_URL || `http://localhost:${process.env.PORT_API || '3008'}`
|
|
7
|
+
|
|
8
|
+
export interface Release {
|
|
9
|
+
version: string
|
|
10
|
+
codename: string
|
|
11
|
+
size: string
|
|
12
|
+
path: string
|
|
13
|
+
createdAt: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ReleaseStats {
|
|
17
|
+
labels: string[]
|
|
18
|
+
downloads: number[]
|
|
19
|
+
releaseTimes: number[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function useReleases() {
|
|
23
|
+
const releases = ref<Release[]>([])
|
|
24
|
+
const stats = ref<ReleaseStats>({ labels: [], downloads: [], releaseTimes: [] })
|
|
25
|
+
const isLoading = ref(false)
|
|
26
|
+
const error = ref<string | null>(null)
|
|
27
|
+
|
|
28
|
+
async function fetchAll() {
|
|
29
|
+
isLoading.value = true
|
|
30
|
+
error.value = null
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(`${baseUrl}/releases`, {
|
|
33
|
+
headers: { 'Accept': 'application/json' },
|
|
34
|
+
})
|
|
35
|
+
if (response.ok) {
|
|
36
|
+
const data = await response.json()
|
|
37
|
+
releases.value = data.data || []
|
|
38
|
+
stats.value = data.stats || stats.value
|
|
39
|
+
}
|
|
40
|
+
} catch (e) {
|
|
41
|
+
error.value = 'Failed to load releases.'
|
|
42
|
+
console.error('Failed to fetch releases:', e)
|
|
43
|
+
} finally {
|
|
44
|
+
isLoading.value = false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { releases, stats, isLoading, error, fetchAll }
|
|
49
|
+
}
|