@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
package/routes/email.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default framework email routes (stacksjs/stacks#1880, #1881).
|
|
3
|
+
*
|
|
4
|
+
* Mounts:
|
|
5
|
+
* - GET /_stacks/email/unsubscribe/:token — opt-out via signed link
|
|
6
|
+
* - POST /webhooks/email/mailgun — bounce/complaint events
|
|
7
|
+
* - POST /webhooks/email/postmark — bounce/complaint events
|
|
8
|
+
* - POST /webhooks/email/ses — SES via SNS
|
|
9
|
+
* - POST /webhooks/email/sendgrid — event webhook
|
|
10
|
+
*
|
|
11
|
+
* All routes are CSRF-exempt (they're called by external providers
|
|
12
|
+
* or anonymous users clicking unsubscribe links). User routes
|
|
13
|
+
* registered first win, so apps that need to mount their own
|
|
14
|
+
* handlers at the same path can override.
|
|
15
|
+
*
|
|
16
|
+
* Each webhook handler self-disables if its provider credentials
|
|
17
|
+
* aren't configured — returns 401 with `missing-config` rather
|
|
18
|
+
* than processing unauthenticated requests.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { route } from '@stacksjs/router'
|
|
22
|
+
import {
|
|
23
|
+
buildUnsubscribeUrl as _ignored, // import-side dep to ensure tree-shake doesn't drop the module
|
|
24
|
+
handleMailgunWebhook,
|
|
25
|
+
handlePostmarkWebhook,
|
|
26
|
+
handleSendgridWebhook,
|
|
27
|
+
handleSesWebhook,
|
|
28
|
+
suppress,
|
|
29
|
+
verifyUnsubscribeToken,
|
|
30
|
+
} from '@stacksjs/email'
|
|
31
|
+
import { config } from '@stacksjs/config'
|
|
32
|
+
import process from 'node:process'
|
|
33
|
+
|
|
34
|
+
// Touch the import so the bundler keeps it referenced (the helper
|
|
35
|
+
// is used by app code; this file ensures the module loads when
|
|
36
|
+
// the framework routes register).
|
|
37
|
+
void _ignored
|
|
38
|
+
|
|
39
|
+
interface EmailConfigShape {
|
|
40
|
+
webhooks?: {
|
|
41
|
+
mailgun?: { signingKey?: string }
|
|
42
|
+
postmark?: { username?: string, password?: string, ipAllowlist?: ReadonlyArray<string> }
|
|
43
|
+
ses?: { autoConfirmSubscriptions?: boolean }
|
|
44
|
+
sendgrid?: { publicKeyPem?: string }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function emailConfig(): EmailConfigShape {
|
|
49
|
+
return ((config as { email?: EmailConfigShape } | undefined)?.email ?? {}) as EmailConfigShape
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Unsubscribe — signed-link opt-out (stacksjs/stacks#1880)
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
route.get('/_stacks/email/unsubscribe/{token}', async (req) => {
|
|
57
|
+
const params = (req as unknown as { params?: { token?: string } }).params
|
|
58
|
+
const token = params?.token ?? ''
|
|
59
|
+
const result = verifyUnsubscribeToken(token)
|
|
60
|
+
if (!result.valid || !result.email) {
|
|
61
|
+
return new Response(
|
|
62
|
+
`Unsubscribe link invalid or expired (${result.reason ?? 'unknown'}).`,
|
|
63
|
+
{ status: 410, headers: { 'Content-Type': 'text/plain; charset=utf-8' } },
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
await suppress(result.email, 'unsubscribe', 'user-initiated via signed URL')
|
|
67
|
+
return new Response(
|
|
68
|
+
`You've been unsubscribed. We won't email ${result.email} again.`,
|
|
69
|
+
{ status: 200, headers: { 'Content-Type': 'text/plain; charset=utf-8' } },
|
|
70
|
+
)
|
|
71
|
+
}).skipCsrf()
|
|
72
|
+
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Provider webhooks (stacksjs/stacks#1881)
|
|
75
|
+
// ============================================================================
|
|
76
|
+
|
|
77
|
+
route.post('/webhooks/email/mailgun', async (req) => {
|
|
78
|
+
const cfg = emailConfig().webhooks?.mailgun
|
|
79
|
+
const signingKey = cfg?.signingKey ?? process.env.MAILGUN_WEBHOOK_SIGNING_KEY ?? ''
|
|
80
|
+
if (!signingKey) {
|
|
81
|
+
return Response.json({ ok: false, reason: 'missing-config' }, { status: 401 })
|
|
82
|
+
}
|
|
83
|
+
const rawBody = await req.text()
|
|
84
|
+
const result = await handleMailgunWebhook(rawBody, { signingKey })
|
|
85
|
+
return Response.json(result.body, { status: result.status })
|
|
86
|
+
}).skipCsrf()
|
|
87
|
+
|
|
88
|
+
route.post('/webhooks/email/postmark', async (req) => {
|
|
89
|
+
const cfg = emailConfig().webhooks?.postmark
|
|
90
|
+
const username = cfg?.username ?? process.env.POSTMARK_WEBHOOK_USERNAME ?? ''
|
|
91
|
+
const password = cfg?.password ?? process.env.POSTMARK_WEBHOOK_PASSWORD ?? ''
|
|
92
|
+
if (!username || !password) {
|
|
93
|
+
return Response.json({ ok: false, reason: 'missing-config' }, { status: 401 })
|
|
94
|
+
}
|
|
95
|
+
const rawBody = await req.text()
|
|
96
|
+
const auth = req.headers.get('authorization')
|
|
97
|
+
// Bun's Request exposes the client IP via the server's `requestIP` API,
|
|
98
|
+
// not directly on the request. The framework's enhanced-request layer
|
|
99
|
+
// surfaces it via _clientIp when available; fall back gracefully.
|
|
100
|
+
const sourceIp = (req as unknown as { _clientIp?: string })._clientIp
|
|
101
|
+
const result = await handlePostmarkWebhook(rawBody, auth, sourceIp, {
|
|
102
|
+
username,
|
|
103
|
+
password,
|
|
104
|
+
ipAllowlist: cfg?.ipAllowlist,
|
|
105
|
+
})
|
|
106
|
+
return Response.json(result.body, { status: result.status })
|
|
107
|
+
}).skipCsrf()
|
|
108
|
+
|
|
109
|
+
route.post('/webhooks/email/ses', async (req) => {
|
|
110
|
+
const cfg = emailConfig().webhooks?.ses ?? {}
|
|
111
|
+
const rawBody = await req.text()
|
|
112
|
+
const result = await handleSesWebhook(rawBody, {
|
|
113
|
+
autoConfirmSubscriptions: cfg.autoConfirmSubscriptions,
|
|
114
|
+
})
|
|
115
|
+
return Response.json(result.body, { status: result.status })
|
|
116
|
+
}).skipCsrf()
|
|
117
|
+
|
|
118
|
+
route.post('/webhooks/email/sendgrid', async (req) => {
|
|
119
|
+
const cfg = emailConfig().webhooks?.sendgrid
|
|
120
|
+
const publicKeyPem = cfg?.publicKeyPem ?? process.env.SENDGRID_WEBHOOK_PUBLIC_KEY ?? ''
|
|
121
|
+
if (!publicKeyPem) {
|
|
122
|
+
return Response.json({ ok: false, reason: 'missing-config' }, { status: 401 })
|
|
123
|
+
}
|
|
124
|
+
const rawBody = await req.text()
|
|
125
|
+
const sig = req.headers.get('x-twilio-email-event-webhook-signature')
|
|
126
|
+
const ts = req.headers.get('x-twilio-email-event-webhook-timestamp')
|
|
127
|
+
const result = await handleSendgridWebhook(rawBody, sig, ts, { publicKeyPem })
|
|
128
|
+
return Response.json(result.body, { status: result.status })
|
|
129
|
+
}).skipCsrf()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
const route = useRoute()
|
|
3
|
+
function name() { return String(route.params.name || '') }
|
|
4
|
+
|
|
5
|
+
// set the title of the page
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<main>
|
|
9
|
+
<div class="flex gap-x-4">
|
|
10
|
+
<SettingsSidebar />
|
|
11
|
+
|
|
12
|
+
<div class="container mx-auto p-4 sm:p-6 lg:p-8">
|
|
13
|
+
<SettingsFormManager :name="name()" />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</main>
|
package/stores/git.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const owner = 'stacksjs'
|
|
2
|
+
const repo = 'stacks'
|
|
3
|
+
const numberOfCommits = 10
|
|
4
|
+
|
|
5
|
+
// Assuming you are using a library like Axios for HTTP requests
|
|
6
|
+
const apiUrl = `https://api.github.com/repos/${owner}/${repo}`
|
|
7
|
+
|
|
8
|
+
const token = ''
|
|
9
|
+
|
|
10
|
+
declare const defineStore: any
|
|
11
|
+
declare const useHttpFetch: any
|
|
12
|
+
|
|
13
|
+
export const useGitStore = defineStore('git', {
|
|
14
|
+
state: (): any => {
|
|
15
|
+
return {
|
|
16
|
+
commitLists: [] as any[],
|
|
17
|
+
workflowRuns: [] as any[],
|
|
18
|
+
workflowRun: {} as any,
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
actions: {
|
|
23
|
+
async fetchCommits(this: any): Promise<void> {
|
|
24
|
+
const fetch = await useHttpFetch(apiUrl)
|
|
25
|
+
|
|
26
|
+
fetch.setToken(token)
|
|
27
|
+
|
|
28
|
+
const response = await fetch.get(`/commits?per_page=${numberOfCommits}`)
|
|
29
|
+
|
|
30
|
+
this.commitLists = response
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async fetchWorkflowActions(this: any): Promise<void> {
|
|
34
|
+
const fetch = await useHttpFetch(apiUrl)
|
|
35
|
+
|
|
36
|
+
fetch.setToken(token)
|
|
37
|
+
|
|
38
|
+
const response = await fetch.get(`/actions/runs?per_page=${numberOfCommits}`)
|
|
39
|
+
|
|
40
|
+
this.workflowRuns = response.workflow_runs
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async fetchWorkflowAction(this: any, id: number): Promise<void> {
|
|
44
|
+
const fetch = await useHttpFetch(apiUrl)
|
|
45
|
+
|
|
46
|
+
fetch.setToken(token)
|
|
47
|
+
|
|
48
|
+
const response = await fetch.get(`/actions/runs/${id}`)
|
|
49
|
+
|
|
50
|
+
this.workflowRun = response
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
getters: {
|
|
55
|
+
getCommits(state: any): any[] {
|
|
56
|
+
return state.commitLists
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
hasCommits(state: any) {
|
|
60
|
+
return state.commitLists.length
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
hasWorkflowRuns(state: any) {
|
|
64
|
+
return state.workflowRuns.length
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
getWorkflowRuns(state: any): any[] {
|
|
68
|
+
return state.workflowRuns
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
})
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
type PaymentMethod = any
|
|
2
|
+
type Product = any
|
|
3
|
+
type Subscription = any
|
|
4
|
+
type TransactionHistory = any
|
|
5
|
+
|
|
6
|
+
const apiUrl = `http://localhost:3008`
|
|
7
|
+
|
|
8
|
+
export const usePaymentStore = defineStore('payment', () => {
|
|
9
|
+
// TODO: update the any types
|
|
10
|
+
const loadingStates = ref<Record<string, boolean>>({})
|
|
11
|
+
const paymentMethods = ref<PaymentMethod[]>([])
|
|
12
|
+
const transactionHistory = ref<TransactionHistory[]>([])
|
|
13
|
+
const defaultPaymentMethod = ref<PaymentMethod>({} as PaymentMethod)
|
|
14
|
+
const product = ref<Product>({} as Product)
|
|
15
|
+
const activeSubscription = ref<Subscription>({} as Subscription)
|
|
16
|
+
const subscriptions = ref<Subscription[]>([])
|
|
17
|
+
const stripeCustomer = ref<any>({} as any)
|
|
18
|
+
const planState = ref<boolean>(false)
|
|
19
|
+
|
|
20
|
+
const getPaymentMethods = computed(() => paymentMethods.value)
|
|
21
|
+
const getProduct = computed(() => product.value)
|
|
22
|
+
const getCurrentPlan = computed(() => activeSubscription.value)
|
|
23
|
+
const getTransactionHistory = computed(() => transactionHistory.value)
|
|
24
|
+
|
|
25
|
+
const isLoading = computed(() => loadingStates.value.size)
|
|
26
|
+
|
|
27
|
+
const hasPaymentMethods = computed(() =>
|
|
28
|
+
paymentMethods.value.length > 0
|
|
29
|
+
|| !(defaultPaymentMethod.value == null
|
|
30
|
+
|| (typeof defaultPaymentMethod.value === 'object' && Object.keys(defaultPaymentMethod.value).length === 0)),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const getDefaultPaymentMethod = computed(() => defaultPaymentMethod.value)
|
|
34
|
+
const getStripeCustomer = computed(() => stripeCustomer.value)
|
|
35
|
+
const getPlanState = computed(() => planState.value)
|
|
36
|
+
|
|
37
|
+
async function fetchSetupIntent(id: number): Promise<string> {
|
|
38
|
+
const url = `http://localhost:3008/payments/create-setup-intent/${id}`
|
|
39
|
+
|
|
40
|
+
const response = await fetch(url, {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json',
|
|
44
|
+
'Accept': 'application/json',
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`Failed to fetch setup intent: ${response.status}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const client: any = await response.json()
|
|
53
|
+
const clientSecret = client.client_secret
|
|
54
|
+
|
|
55
|
+
return clientSecret
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function fetchPaymentIntent(id: number, productId: number): Promise<string> {
|
|
59
|
+
const body = { productId }
|
|
60
|
+
|
|
61
|
+
const url = `http://localhost:3008/payments/create-payment-intent/${id}`
|
|
62
|
+
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
'Accept': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify(body),
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`Failed to create payment intent: ${response.status}`)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const client: any = await response.json()
|
|
77
|
+
const clientSecret = client.client_secret
|
|
78
|
+
|
|
79
|
+
return clientSecret
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function storeTransaction(id: number, productId: number): Promise<string> {
|
|
83
|
+
const body = { productId }
|
|
84
|
+
|
|
85
|
+
const url = `http://localhost:3008/payments/store-transaction/${id}`
|
|
86
|
+
|
|
87
|
+
const response = await fetch(url, {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'application/json',
|
|
91
|
+
'Accept': 'application/json',
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify(body),
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
throw new Error(`Failed to store transaction: ${response.status}`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const client: any = await response.json()
|
|
101
|
+
const clientSecret = client.client_secret
|
|
102
|
+
|
|
103
|
+
return clientSecret
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function subscribeToPlan(body: { type: string, plan: string, description: string }): Promise<string> {
|
|
107
|
+
const url = 'http://localhost:3008/payments/create-subscription'
|
|
108
|
+
|
|
109
|
+
const response = await fetch(url, {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers: {
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
'Accept': 'application/json',
|
|
114
|
+
},
|
|
115
|
+
body: JSON.stringify(body),
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const client: any = await response.json()
|
|
119
|
+
|
|
120
|
+
;(globalThis as any).dispatch('subscription:created')
|
|
121
|
+
|
|
122
|
+
return client
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function updatePlan(body: { type: string, plan: string, description: string }): Promise<string> {
|
|
126
|
+
const url = 'http://localhost:3008/payments/update-subscription'
|
|
127
|
+
|
|
128
|
+
const response = await fetch(url, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
headers: {
|
|
131
|
+
'Content-Type': 'application/json',
|
|
132
|
+
'Accept': 'application/json',
|
|
133
|
+
},
|
|
134
|
+
body: JSON.stringify(body),
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const client: any = await response.json()
|
|
138
|
+
|
|
139
|
+
return client
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function setDefaultPaymentMethod(paymentId: string): Promise<string> {
|
|
143
|
+
const url = 'http://localhost:3008/payments/set-default-payment-method/1'
|
|
144
|
+
|
|
145
|
+
const body = { paymentId }
|
|
146
|
+
|
|
147
|
+
const response = await fetch(url, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: {
|
|
150
|
+
'Content-Type': 'application/json',
|
|
151
|
+
'Accept': 'application/json',
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify(body),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const res: any = await response.json()
|
|
157
|
+
|
|
158
|
+
return res
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function setUserDefaultPaymentMethod(setupIntent: string): Promise<string> {
|
|
162
|
+
const url = 'http://localhost:3008/payments/user-default-payment-method/1'
|
|
163
|
+
|
|
164
|
+
const body = { setupIntent }
|
|
165
|
+
|
|
166
|
+
const response = await fetch(url, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
headers: {
|
|
169
|
+
'Content-Type': 'application/json',
|
|
170
|
+
'Accept': 'application/json',
|
|
171
|
+
},
|
|
172
|
+
body: JSON.stringify(body),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
const res: any = await response.json()
|
|
176
|
+
|
|
177
|
+
return res
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function storePaymentMethod(setupIntent: string): Promise<string> {
|
|
181
|
+
const url = 'http://localhost:3008/payments/payment-method/1'
|
|
182
|
+
|
|
183
|
+
const body = { setupIntent }
|
|
184
|
+
|
|
185
|
+
const response = await fetch(url, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: {
|
|
188
|
+
'Content-Type': 'application/json',
|
|
189
|
+
'Accept': 'application/json',
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify(body),
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
const res: any = await response.json()
|
|
195
|
+
|
|
196
|
+
return res
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function openPlans() {
|
|
200
|
+
planState.value = true
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function closePlans() {
|
|
204
|
+
planState.value = false
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function fetchSubscriptions(): Promise<void> {
|
|
208
|
+
setLoadingState('fetchSubscriptions')
|
|
209
|
+
|
|
210
|
+
const url = 'http://localhost:3008/payments/fetch-user-subscriptions'
|
|
211
|
+
|
|
212
|
+
const response = await fetch(url, {
|
|
213
|
+
method: 'GET',
|
|
214
|
+
headers: {
|
|
215
|
+
'Content-Type': 'application/json',
|
|
216
|
+
'Accept': 'application/json',
|
|
217
|
+
},
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
if (response.status !== 204) {
|
|
221
|
+
const res = await response.json() as any[]
|
|
222
|
+
|
|
223
|
+
subscriptions.value = res
|
|
224
|
+
}
|
|
225
|
+
await response.json()
|
|
226
|
+
|
|
227
|
+
removeLoadingState('fetchSubscriptions')
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function cancelPlan(): Promise<void> {
|
|
231
|
+
const url = 'http://localhost:3008/payments/cancel-subscription'
|
|
232
|
+
|
|
233
|
+
const providerId = getCurrentPlan.value.subscription.provider_id
|
|
234
|
+
const subscriptionId = getCurrentPlan.value.subscription.id
|
|
235
|
+
const body = { providerId, subscriptionId }
|
|
236
|
+
const response = await fetch(url, {
|
|
237
|
+
method: 'POST',
|
|
238
|
+
headers: {
|
|
239
|
+
'Content-Type': 'application/json',
|
|
240
|
+
'Accept': 'application/json',
|
|
241
|
+
},
|
|
242
|
+
body: JSON.stringify(body),
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
if (response.status !== 204)
|
|
246
|
+
await response.json()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async function fetchUserPaymentMethods(id: number): Promise<void> {
|
|
250
|
+
setLoadingState('fetchUserPaymentMethods')
|
|
251
|
+
|
|
252
|
+
const response: any = await fetch(`${apiUrl}/payments/payment-methods/${id}`, {
|
|
253
|
+
method: 'GET',
|
|
254
|
+
headers: {
|
|
255
|
+
'Content-Type': 'application/json',
|
|
256
|
+
'Accept': 'application/json',
|
|
257
|
+
},
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
if (response.status !== 204) {
|
|
261
|
+
const res = await response.json()
|
|
262
|
+
|
|
263
|
+
paymentMethods.value = res
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
removeLoadingState('fetchUserPaymentMethods')
|
|
267
|
+
|
|
268
|
+
;(globalThis as any).dispatch('paymentMethods:fetched')
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function fetchTransactionHistory(id: number): Promise<void> {
|
|
272
|
+
setLoadingState('fetchTransactionHistory')
|
|
273
|
+
|
|
274
|
+
const response: any = await fetch(`${apiUrl}/payments/fetch-transaction-history/${id}`, {
|
|
275
|
+
method: 'GET',
|
|
276
|
+
headers: {
|
|
277
|
+
'Content-Type': 'application/json',
|
|
278
|
+
'Accept': 'application/json',
|
|
279
|
+
},
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
if (response.status !== 204) {
|
|
283
|
+
const res = await response.json()
|
|
284
|
+
|
|
285
|
+
transactionHistory.value = res.data
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
removeLoadingState('fetchTransactionHistory')
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function deletePaymentMethod(paymentMethod: number): Promise<void> {
|
|
292
|
+
setLoadingState('deletePaymentMethod')
|
|
293
|
+
const url = 'http://localhost:3008/payments/delete-payment-method/1'
|
|
294
|
+
|
|
295
|
+
const body = { paymentMethod }
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
await fetch(url, {
|
|
299
|
+
method: 'DELETE',
|
|
300
|
+
headers: {
|
|
301
|
+
'Content-Type': 'application/json',
|
|
302
|
+
'Accept': 'application/json',
|
|
303
|
+
},
|
|
304
|
+
body: JSON.stringify(body),
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
catch (err: any) {
|
|
308
|
+
// eslint-disable-next-line no-console
|
|
309
|
+
console.log(err)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
removeLoadingState('deletePaymentMethod')
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async function updateDefaultPaymentMethod(paymentMethod: string): Promise<void> {
|
|
316
|
+
setLoadingState('updateDefaultPaymentMethod')
|
|
317
|
+
|
|
318
|
+
const url = 'http://localhost:3008/payments/update-default-payment-method/1'
|
|
319
|
+
|
|
320
|
+
const body = { paymentMethod }
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
await fetch(url, {
|
|
324
|
+
method: 'PUT',
|
|
325
|
+
headers: {
|
|
326
|
+
'Content-Type': 'application/json',
|
|
327
|
+
'Accept': 'application/json',
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify(body),
|
|
330
|
+
})
|
|
331
|
+
}
|
|
332
|
+
catch (err: any) {
|
|
333
|
+
// eslint-disable-next-line no-console
|
|
334
|
+
console.log(err)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
removeLoadingState('updateDefaultPaymentMethod')
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async function fetchStripeCustomer(id: number): Promise<void> {
|
|
341
|
+
setLoadingState('fetchStripeCustomer')
|
|
342
|
+
|
|
343
|
+
const response: any = await fetch(`${apiUrl}/payments/fetch-customer/${id}`, {
|
|
344
|
+
method: 'GET',
|
|
345
|
+
headers: {
|
|
346
|
+
'Content-Type': 'application/json',
|
|
347
|
+
'Accept': 'application/json',
|
|
348
|
+
},
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
if (response.status !== 204) {
|
|
352
|
+
const res = await response.json()
|
|
353
|
+
stripeCustomer.value = res
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
removeLoadingState('fetchStripeCustomer')
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function fetchDefaultPaymentMethod(id: number): Promise<void> {
|
|
360
|
+
setLoadingState('fetchDefaultPaymentMethod')
|
|
361
|
+
|
|
362
|
+
const response: any = await fetch(`${apiUrl}/payments/default-payment-method/${id}`, {
|
|
363
|
+
method: 'GET',
|
|
364
|
+
headers: {
|
|
365
|
+
'Content-Type': 'application/json',
|
|
366
|
+
'Accept': 'application/json',
|
|
367
|
+
},
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
if (response.status !== 204) {
|
|
371
|
+
const res = await response.json()
|
|
372
|
+
|
|
373
|
+
defaultPaymentMethod.value = res
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
removeLoadingState('fetchDefaultPaymentMethod')
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async function fetchProduct(id: number): Promise<void> {
|
|
380
|
+
setLoadingState('fetchProduct')
|
|
381
|
+
|
|
382
|
+
const response: any = await fetch(`${apiUrl}/payments/fetch-product/${id}`, {
|
|
383
|
+
method: 'GET',
|
|
384
|
+
headers: {
|
|
385
|
+
'Content-Type': 'application/json',
|
|
386
|
+
'Accept': 'application/json',
|
|
387
|
+
},
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
if (response.status !== 204) {
|
|
391
|
+
const res = await response.json()
|
|
392
|
+
|
|
393
|
+
product.value = res
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
removeLoadingState('fetchProduct')
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
async function fetchUserActivePlan(id: number): Promise<void> {
|
|
400
|
+
setLoadingState('fetchActivePlan')
|
|
401
|
+
const response: any = await fetch(`${apiUrl}/payments/fetch-active-subscription/${id}`, {
|
|
402
|
+
method: 'GET',
|
|
403
|
+
headers: {
|
|
404
|
+
'Content-Type': 'application/json',
|
|
405
|
+
'Accept': 'application/json',
|
|
406
|
+
},
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
if (response.status !== 204) {
|
|
410
|
+
const res = await response.json()
|
|
411
|
+
|
|
412
|
+
activeSubscription.value = res
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
activeSubscription.value = {}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
removeLoadingState('fetchActivePlan')
|
|
419
|
+
|
|
420
|
+
;(globalThis as any).dispatch('subscription:fetched')
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function setLoadingState(statusKey: string): void {
|
|
424
|
+
loadingStates.value[statusKey] = true
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function removeLoadingState(statusKey: string): void {
|
|
428
|
+
loadingStates.value[statusKey] = false
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function isStateLoading(statusKey: string): boolean {
|
|
432
|
+
return loadingStates.value[statusKey] === undefined ? true : loadingStates.value[statusKey]
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
paymentMethods,
|
|
437
|
+
defaultPaymentMethod,
|
|
438
|
+
stripeCustomer,
|
|
439
|
+
product,
|
|
440
|
+
activeSubscription,
|
|
441
|
+
transactionHistory,
|
|
442
|
+
isLoading,
|
|
443
|
+
getPaymentMethods,
|
|
444
|
+
getProduct,
|
|
445
|
+
getCurrentPlan,
|
|
446
|
+
getTransactionHistory,
|
|
447
|
+
hasPaymentMethods,
|
|
448
|
+
getDefaultPaymentMethod,
|
|
449
|
+
getStripeCustomer,
|
|
450
|
+
getPlanState,
|
|
451
|
+
fetchSetupIntent,
|
|
452
|
+
fetchPaymentIntent,
|
|
453
|
+
storeTransaction,
|
|
454
|
+
subscribeToPlan,
|
|
455
|
+
updatePlan,
|
|
456
|
+
setDefaultPaymentMethod,
|
|
457
|
+
setUserDefaultPaymentMethod,
|
|
458
|
+
storePaymentMethod,
|
|
459
|
+
openPlans,
|
|
460
|
+
closePlans,
|
|
461
|
+
fetchSubscriptions,
|
|
462
|
+
cancelPlan,
|
|
463
|
+
fetchUserPaymentMethods,
|
|
464
|
+
fetchTransactionHistory,
|
|
465
|
+
deletePaymentMethod,
|
|
466
|
+
updateDefaultPaymentMethod,
|
|
467
|
+
fetchStripeCustomer,
|
|
468
|
+
fetchDefaultPaymentMethod,
|
|
469
|
+
fetchProduct,
|
|
470
|
+
isStateLoading,
|
|
471
|
+
fetchUserActivePlan,
|
|
472
|
+
|
|
473
|
+
}
|
|
474
|
+
})
|