@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,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stacks-path
|
|
3
|
+
description: Use when working with file paths in Stacks — 100+ framework-aware path builder functions for every directory in the project (actions, app, config, database, models, routes, storage, etc.), plus Node.js path utilities (join, resolve, basename, dirname, etc.). Covers @stacksjs/path.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
|
+
allowed-tools: Read Edit Write Bash Grep Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Stacks Path
|
|
10
|
+
|
|
11
|
+
100+ path builder functions for every framework directory.
|
|
12
|
+
|
|
13
|
+
## Key Path
|
|
14
|
+
- Core package: `storage/framework/core/path/src/`
|
|
15
|
+
|
|
16
|
+
## Node.js Path Re-exports
|
|
17
|
+
`basename`, `delimiter`, `dirname`, `extname`, `isAbsolute`, `join`, `normalize`, `parse`, `relative`, `resolve`, `sep`, `toNamespacedPath`
|
|
18
|
+
|
|
19
|
+
## Framework Path Builders
|
|
20
|
+
|
|
21
|
+
All accept an optional relative path suffix and return absolute paths.
|
|
22
|
+
|
|
23
|
+
### Application Paths
|
|
24
|
+
```typescript
|
|
25
|
+
appPath('Models') // ~/app/Models
|
|
26
|
+
userActionsPath() // ~/app/Actions
|
|
27
|
+
userComponentsPath() // ~/app/Components
|
|
28
|
+
userViewsPath() // ~/app/Views
|
|
29
|
+
userFunctionsPath() // ~/app/Functions
|
|
30
|
+
userJobsPath() // ~/app/Jobs
|
|
31
|
+
userControllersPath() // ~/app/Controllers
|
|
32
|
+
userListenersPath() // ~/app/Listeners
|
|
33
|
+
userMiddlewarePath() // ~/app/Middleware
|
|
34
|
+
userModelsPath() // ~/app/Models
|
|
35
|
+
userNotificationsPath() // ~/app/Notifications
|
|
36
|
+
userDatabasePath() // ~/database
|
|
37
|
+
userMigrationsPath() // ~/database/migrations
|
|
38
|
+
userEventsPath() // ~/app/Events.ts
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Framework Paths
|
|
42
|
+
```typescript
|
|
43
|
+
actionsPath() // ~/storage/framework/core/actions
|
|
44
|
+
buddyPath() // ~/storage/framework/core/buddy
|
|
45
|
+
runtimePath() // ~/storage/framework/core/buddy
|
|
46
|
+
buildPath() // ~/storage/framework/core/build
|
|
47
|
+
cachePath() // ~/storage/framework/cache
|
|
48
|
+
cloudPath() // ~/cloud
|
|
49
|
+
frameworkCloudPath() // ~/storage/framework/cloud
|
|
50
|
+
libsPath() // ~/storage/framework/libs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Package Paths (one per core package)
|
|
54
|
+
```typescript
|
|
55
|
+
aiPath() analyticsPath() aliasPath()
|
|
56
|
+
arraysPath() authPath() browserPath()
|
|
57
|
+
cliPath() chatPath() collectionsPath()
|
|
58
|
+
configPath() databasePath() datetimePath()
|
|
59
|
+
dnsPath() docsPath() emailPath()
|
|
60
|
+
enumsPath() envPath() errorHandlingPath()
|
|
61
|
+
eventsPath() fakerPath() gitPath()
|
|
62
|
+
healthPath() httpPath() i18nPath()
|
|
63
|
+
lintPath() loggingPath() notificationsPath()
|
|
64
|
+
objectsPath() ormPath() pathPath()
|
|
65
|
+
paymentsPath() pluginsPath() pushPath()
|
|
66
|
+
queuePath() realtimePath() routerPath()
|
|
67
|
+
schedulerPath() searchEnginePath() securityPath()
|
|
68
|
+
serverPath() shellPath() slugPath()
|
|
69
|
+
smsPath() socialsPath() storagePath()
|
|
70
|
+
stringsPath() testingPath() tinkerPath()
|
|
71
|
+
tunnelPath() typesPath() uiPath()
|
|
72
|
+
utilsPath() validationPath() whoisPath()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Resource Paths
|
|
76
|
+
```typescript
|
|
77
|
+
assetsPath() // ~/resources/assets
|
|
78
|
+
resourcesPath() // ~/resources
|
|
79
|
+
publicPath() // ~/public
|
|
80
|
+
localesPath() // ~/locales
|
|
81
|
+
routesPath() // ~/routes
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Build & Output Paths
|
|
85
|
+
```typescript
|
|
86
|
+
buildEnginePath()
|
|
87
|
+
libsEntriesPath()
|
|
88
|
+
frameworkPath() // ~/storage/framework
|
|
89
|
+
corePath() // ~/storage/framework/core
|
|
90
|
+
defaultsPath() // ~/storage/framework/defaults
|
|
91
|
+
defaultsAppPath()
|
|
92
|
+
defaultsResourcesPath()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Relative Path Variants
|
|
96
|
+
Most paths have `relative*` variants:
|
|
97
|
+
```typescript
|
|
98
|
+
relativeActionsPath()
|
|
99
|
+
relativeAppPath()
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Path with Suffix
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
appPath('Models/User.ts') // ~/app/Models/User.ts
|
|
106
|
+
databasePath('migrations') // ~/storage/framework/core/database/migrations
|
|
107
|
+
configPath('app.ts') // ~/config/app.ts
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Gotchas
|
|
111
|
+
- Always use `@stacksjs/path` instead of Node's `path` for framework paths
|
|
112
|
+
- All paths resolve to absolute paths by default
|
|
113
|
+
- Most functions accept an optional relative path suffix
|
|
114
|
+
- `relative*` variants return paths relative to project root
|
|
115
|
+
- `user*Path()` functions point to application-level directories (app/)
|
|
116
|
+
- `built*Path()` functions point to compiled output directories
|
|
117
|
+
- Path is a dependency of almost every framework package
|
|
118
|
+
- Some paths accept `options` with `relative` flag
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stacks-payments
|
|
3
|
+
description: Use when implementing payment processing in Stacks — Stripe charges, subscriptions, checkout sessions, customer management, payment methods, invoices, coupons, promo codes, products, prices, webhooks, or the Payment facade. Covers @stacksjs/payments and config/payment.ts.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
|
+
allowed-tools: Read Edit Write Bash Grep Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Stacks Payments
|
|
10
|
+
|
|
11
|
+
Full Stripe integration via the Payment facade. Uses Stripe API version `2026-01-28.clover`. The Stripe SDK is initialized from `services.stripe.secretKey` (sourced from `config/payment.ts`).
|
|
12
|
+
|
|
13
|
+
## Key Paths
|
|
14
|
+
- Core package: `storage/framework/core/payments/src/`
|
|
15
|
+
- Payment facade: `storage/framework/core/payments/src/payment.ts`
|
|
16
|
+
- Stripe driver: `storage/framework/core/payments/src/drivers/stripe.ts`
|
|
17
|
+
- Billable modules: `storage/framework/core/payments/src/billable/`
|
|
18
|
+
- Configuration: `config/payment.ts`
|
|
19
|
+
- SaaS config: `config/saas.ts`
|
|
20
|
+
- Default billing functions: `storage/framework/defaults/functions/billing/payments.ts`
|
|
21
|
+
|
|
22
|
+
## Package Exports
|
|
23
|
+
- `Payment` (default) -- facade object with all payment methods
|
|
24
|
+
- All individual functions (`charge`, `subscribe`, `checkout`, etc.)
|
|
25
|
+
- All billable modules (`manageCharge`, `manageCustomer`, `manageSubscription`, etc.)
|
|
26
|
+
- `stripe` -- raw Stripe SDK instance
|
|
27
|
+
- `Stripe` -- re-exported Stripe types namespace
|
|
28
|
+
|
|
29
|
+
## Payment Facade
|
|
30
|
+
|
|
31
|
+
The `Payment` object aggregates all payment operations. Every method is also available as a standalone export.
|
|
32
|
+
|
|
33
|
+
### Charges
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Payment } from '@stacksjs/payments'
|
|
37
|
+
|
|
38
|
+
// Create and confirm a charge (creates PaymentIntent with confirm: true)
|
|
39
|
+
const intent = await Payment.charge(user, 2999, 'pm_xxx', { currency: 'usd' })
|
|
40
|
+
|
|
41
|
+
// Create PaymentIntent without confirming (for client-side confirmation)
|
|
42
|
+
const intent = await Payment.createPayment(user, 2999, { currency: 'usd' })
|
|
43
|
+
|
|
44
|
+
// Refund -- partial
|
|
45
|
+
const refund = await Payment.refund('pi_xxx', 1000)
|
|
46
|
+
|
|
47
|
+
// Refund -- full (omit amount)
|
|
48
|
+
const refund = await Payment.refund('pi_xxx')
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`charge()` sets `confirmation_method: 'automatic'`, `confirm: true`, attaches the payment method, and delegates to `createPayment()`. If the user has a `stripe_id`, it is set as the customer on the PaymentIntent. Default currency is `'usd'`.
|
|
52
|
+
|
|
53
|
+
The `manageCharge` module also exposes `findPayment(id)` which retrieves a PaymentIntent by ID, returning `null` on failure.
|
|
54
|
+
|
|
55
|
+
### Checkout Sessions
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// One-time payment checkout
|
|
59
|
+
const session = await Payment.checkout(user, [
|
|
60
|
+
{ price: 'price_xxx', quantity: 1 }
|
|
61
|
+
], { success_url: '/success', cancel_url: '/cancel' })
|
|
62
|
+
|
|
63
|
+
// Subscription checkout
|
|
64
|
+
const subSession = await Payment.subscriptionCheckout(user, 'price_xxx', {
|
|
65
|
+
success_url: '/success', cancel_url: '/cancel'
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Both methods require the user to have a `stripe_id` (throws if missing). `checkout()` sets `mode: 'payment'`, `subscriptionCheckout()` sets `mode: 'subscription'`.
|
|
70
|
+
|
|
71
|
+
### Subscriptions
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// Create -- uses lookup_key to resolve the Stripe Price
|
|
75
|
+
const sub = await Payment.subscribe(user, 'premium-monthly')
|
|
76
|
+
|
|
77
|
+
// Cancel at period end (prorate: true)
|
|
78
|
+
const cancelled = await Payment.cancelSubscription('sub_xxx')
|
|
79
|
+
|
|
80
|
+
// Cancel immediately (invoice_now: true, prorate: false)
|
|
81
|
+
const cancelled = await Payment.cancelSubscription('sub_xxx', true)
|
|
82
|
+
|
|
83
|
+
// Check active subscription
|
|
84
|
+
const hasActive = await Payment.hasActiveSubscription(user, 'default')
|
|
85
|
+
|
|
86
|
+
// Change plan -- swaps the subscription item's price
|
|
87
|
+
const changed = await Payment.changeSubscription(user, 'enterprise-monthly')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`subscribe()` calls `managePrice.retrieveByLookupKey(lookupKey)` to find the price, then creates the subscription with `payment_behavior: 'allow_incomplete'` and `expand: ['latest_invoice.payment_intent']`. It stores the subscription in the `subscriptions` database table.
|
|
91
|
+
|
|
92
|
+
`isValid()` returns `true` if the subscription status is `'active'` or `'trialing'`. `isIncomplete()` checks for `'incomplete'` status.
|
|
93
|
+
|
|
94
|
+
`cancel()` calls `stripe.subscriptions.cancel()` and updates `provider_status` to `'canceled'` in the database.
|
|
95
|
+
|
|
96
|
+
`update()` retrieves the active subscription via `user.activeSubscription()`, finds the new price by lookup key, updates the subscription item, and stores the updated price in the database.
|
|
97
|
+
|
|
98
|
+
### Customers
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// Get existing or create new Stripe customer
|
|
102
|
+
const customer = await Payment.getOrCreateCustomer(user, { name: 'John' })
|
|
103
|
+
|
|
104
|
+
// Update customer details in Stripe
|
|
105
|
+
const updated = await Payment.updateCustomer(user, { name: 'Jane' })
|
|
106
|
+
|
|
107
|
+
// Delete from Stripe and clear stripe_id on user model
|
|
108
|
+
const deleted = await Payment.deleteCustomer(user)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`createOrGetStripeUser()` checks `user.stripe_id` first. If the user has one, it retrieves the customer from Stripe. If the customer was deleted (404 or `deleted: true`), it creates a new one. On creation, it auto-fills `name` and `email` from the user model and calls `user.update({ stripe_id: customer.id })`.
|
|
112
|
+
|
|
113
|
+
Additional methods on `manageCustomer`:
|
|
114
|
+
- `stripeId(user)` -- returns `user.stripe_id`
|
|
115
|
+
- `hasStripeId(user)` -- boolean check
|
|
116
|
+
- `createStripeCustomer(user, options)` -- throws if user already has a stripe_id
|
|
117
|
+
- `createOrUpdateStripeUser(user, options)` -- creates or updates
|
|
118
|
+
- `retrieveStripeUser(user)` -- returns customer or undefined
|
|
119
|
+
- `syncStripeCustomerDetails(user, options)` -- updates Stripe with user's name, email, address, locales, metadata
|
|
120
|
+
|
|
121
|
+
### Payment Methods
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Add a payment method to the customer
|
|
125
|
+
const pm = await Payment.addPaymentMethod(user, 'pm_xxx')
|
|
126
|
+
|
|
127
|
+
// Set as default (by Stripe payment method ID string)
|
|
128
|
+
const customer = await Payment.setDefaultPaymentMethod(user, 'pm_xxx')
|
|
129
|
+
|
|
130
|
+
// Remove a payment method (by database record ID number)
|
|
131
|
+
const removed = await Payment.removePaymentMethod(user, paymentMethodDbId)
|
|
132
|
+
|
|
133
|
+
// Create a setup intent for collecting payment methods
|
|
134
|
+
const intent = await Payment.createSetupIntent(user, { payment_method_types: ['card'] })
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`addPaymentMethod()` accepts a string (Stripe PM ID) or Stripe.PaymentMethod object. It attaches the PM to the customer if not already attached, then stores it in the `payment_methods` table with `type`, `last_four`, `brand`, `exp_year`, `exp_month`, `user_id`, `provider_id`.
|
|
138
|
+
|
|
139
|
+
`setUserDefaultPayment()` accepts a Stripe PM ID string, clears existing `is_default` flags, sets the new default in the database, and updates `invoice_settings.default_payment_method` on the Stripe customer.
|
|
140
|
+
|
|
141
|
+
`setDefaultPaymentMethod()` accepts a database record ID number.
|
|
142
|
+
|
|
143
|
+
Additional methods on `managePaymentMethod`:
|
|
144
|
+
- `updatePaymentMethod(user, pmId, params)` -- updates PM in Stripe
|
|
145
|
+
- `listPaymentMethods(user)` -- queries `payment_methods` table by `user_id`
|
|
146
|
+
- `retrievePaymentMethod(user, pmId)` -- by database ID
|
|
147
|
+
- `retrieveDefaultPaymentMethod(user)` -- finds where `is_default: true`
|
|
148
|
+
|
|
149
|
+
### Invoices
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const invoices = await Payment.getInvoices(user) // lists with expanded payment_intent.payment_method
|
|
153
|
+
const invoice = await Payment.createInvoice('cus_xxx', { description: 'Custom invoice' })
|
|
154
|
+
const paid = await Payment.payInvoice('inv_xxx')
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`getInvoices()` requires the user to have a `stripe_id` and expands `data.payment_intent.payment_method`.
|
|
158
|
+
|
|
159
|
+
### Products & Prices
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Create a product with its price
|
|
163
|
+
const { product, price } = await Payment.createProduct('Pro Plan', 2999, {
|
|
164
|
+
currency: 'usd', interval: 'month', description: 'Pro features'
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Get a price by Stripe lookup_key
|
|
168
|
+
const price = await Payment.getPrice('premium-monthly')
|
|
169
|
+
|
|
170
|
+
// List active products
|
|
171
|
+
const products = await Payment.listProducts({ limit: 10 })
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`createProduct()` creates the Stripe product, then creates a price linked to it. If `interval` is provided, the price gets `recurring: { interval }`.
|
|
175
|
+
|
|
176
|
+
Additional methods on `manageProduct`:
|
|
177
|
+
- `create(params)`, `retrieve(productId)`, `update(productId, params)`
|
|
178
|
+
- `archive(productId)` -- sets `active: false`
|
|
179
|
+
- `search(query, params)` -- Stripe product search
|
|
180
|
+
- `list(params)` -- defaults to `active: true`
|
|
181
|
+
|
|
182
|
+
Additional methods on `managePriceExtended`:
|
|
183
|
+
- `create(params)`, `retrieve(priceId)`, `update(priceId, params)`
|
|
184
|
+
- `list(params)` -- defaults to `active: true`
|
|
185
|
+
- `listByProduct(productId, params)` -- prices for a specific product
|
|
186
|
+
- `search(query, params)` -- Stripe price search
|
|
187
|
+
- `archive(priceId)` -- sets `active: false`
|
|
188
|
+
|
|
189
|
+
### Coupons & Promo Codes
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const coupon = await Payment.createCoupon({
|
|
193
|
+
percentOff: 20, duration: 'once', name: 'Holiday Sale', maxRedemptions: 100
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// Or amount-based: { amountOff: 500, currency: 'usd', duration: 'forever' }
|
|
197
|
+
|
|
198
|
+
const promo = await Payment.createPromoCode('coupon_xxx', 'SAVE20')
|
|
199
|
+
const valid = await Payment.validatePromoCode('SAVE20') // returns PromotionCode | null
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`createCoupon()` supports `percentOff`, `amountOff`, `currency`, `duration` ('forever' | 'once' | 'repeating'), `durationInMonths`, `name`, `maxRedemptions`.
|
|
203
|
+
|
|
204
|
+
Additional methods on `manageCoupon`:
|
|
205
|
+
- `retrieve(couponId)`, `update(couponId, params)`, `delete(couponId)`, `list(params)`
|
|
206
|
+
- `createPromotionCode(params)` -- wraps `stripe.promotionCodes.create()`
|
|
207
|
+
- `retrievePromotionCode(code)` -- lists active promotion codes matching the code string
|
|
208
|
+
|
|
209
|
+
### Transactions
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { manageTransaction } from '@stacksjs/payments'
|
|
213
|
+
|
|
214
|
+
const tx = await manageTransaction.store(user, productId, {
|
|
215
|
+
brand: 'visa', provider_id: 'pi_xxx', description: 'Purchase', type: 'one-time'
|
|
216
|
+
})
|
|
217
|
+
const txList = await manageTransaction.list(user)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Transactions are stored in the `payment_transactions` table with `name` (from product), `amount` (from product `unit_price`), `brand`, `type`, `provider_id`, `user_id`.
|
|
221
|
+
|
|
222
|
+
### Webhooks
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { Payment } from '@stacksjs/payments'
|
|
226
|
+
|
|
227
|
+
// Register handlers
|
|
228
|
+
Payment.onPaymentIntent({
|
|
229
|
+
succeeded: async (event) => { /* ... */ },
|
|
230
|
+
failed: async (event) => { /* ... */ },
|
|
231
|
+
created: async (event) => { /* ... */ },
|
|
232
|
+
canceled: async (event) => { /* ... */ },
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
Payment.onSubscription({
|
|
236
|
+
created: async (event) => { /* ... */ },
|
|
237
|
+
updated: async (event) => { /* ... */ },
|
|
238
|
+
deleted: async (event) => { /* ... */ },
|
|
239
|
+
trialWillEnd: async (event) => { /* ... */ },
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
Payment.onInvoice({
|
|
243
|
+
paid: async (event) => { /* ... */ },
|
|
244
|
+
paymentFailed: async (event) => { /* ... */ },
|
|
245
|
+
created: async (event) => { /* ... */ },
|
|
246
|
+
finalized: async (event) => { /* ... */ },
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
Payment.onCheckout({
|
|
250
|
+
completed: async (event) => { /* ... */ },
|
|
251
|
+
expired: async (event) => { /* ... */ },
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
Payment.onCharge({
|
|
255
|
+
succeeded: async (event) => { /* ... */ },
|
|
256
|
+
failed: async (event) => { /* ... */ },
|
|
257
|
+
refunded: async (event) => { /* ... */ },
|
|
258
|
+
disputed: async (event) => { /* ... */ },
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
// Process incoming webhook request
|
|
262
|
+
const result = await Payment.processWebhook(rawPayload, signatureHeader, {
|
|
263
|
+
secret: 'whsec_xxx', tolerance: 300
|
|
264
|
+
})
|
|
265
|
+
// Returns: { success: boolean, eventType?: string, error?: string }
|
|
266
|
+
|
|
267
|
+
// Low-level: register any event type
|
|
268
|
+
Payment.webhook.onWebhookEvent('payment_method.attached', handler)
|
|
269
|
+
Payment.webhook.registerWebhookHandlers({ 'payment_intent.succeeded': handler })
|
|
270
|
+
|
|
271
|
+
// Event data extractors
|
|
272
|
+
import { getPaymentIntent, getSubscription, getInvoice, getCheckoutSession, getCharge, getCustomer } from '@stacksjs/payments'
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Supported webhook event types: `payment_intent.succeeded`, `payment_intent.payment_failed`, `payment_intent.created`, `payment_intent.canceled`, `customer.subscription.created/updated/deleted`, `customer.subscription.trial_will_end`, `customer.created/updated/deleted`, `invoice.paid/payment_failed/finalized/created`, `checkout.session.completed/expired`, `charge.succeeded/failed/refunded`, `charge.dispute.created/closed`, `payment_method.attached/detached`, `setup_intent.succeeded/setup_failed`, plus any string.
|
|
276
|
+
|
|
277
|
+
### Setup Products from SaaS Config
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { createStripeProduct } from '@stacksjs/payments'
|
|
281
|
+
|
|
282
|
+
const result = await createStripeProduct()
|
|
283
|
+
// Creates Stripe products and prices from config/saas.ts plans
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
This iterates `saas.plans`, creates a Stripe product per plan, then creates prices for each pricing option using `lookup_key` from the `key` field.
|
|
287
|
+
|
|
288
|
+
### Utility Functions
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
Payment.formatAmount(2999, 'usd') // '$29.99' (uses Intl.NumberFormat)
|
|
292
|
+
Payment.toCents(29.99) // 2999
|
|
293
|
+
Payment.toDollars(2999) // 29.99
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Client-Side Billing (useBillable)
|
|
297
|
+
|
|
298
|
+
The `storage/framework/defaults/functions/billing/payments.ts` file provides a `useBillable()` composable for frontend billing UI:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
const { loadCardForm, loadPaymentForm, handleAddPaymentMethod, handlePayment } = useBillable()
|
|
302
|
+
|
|
303
|
+
await loadCardForm(clientSecret) // loads Stripe Card Element
|
|
304
|
+
await loadPaymentForm(clientSecret) // loads Stripe Payment Element
|
|
305
|
+
await handleAddPaymentMethod(clientSecret, elements) // confirms card setup
|
|
306
|
+
await handlePayment(elements) // confirms payment
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## config/payment.ts
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
{
|
|
313
|
+
driver: 'stripe',
|
|
314
|
+
stripe: {
|
|
315
|
+
publishableKey: env.STRIPE_PUBLISHABLE_KEY || '',
|
|
316
|
+
secretKey: env.STRIPE_SECRET_KEY || '',
|
|
317
|
+
},
|
|
318
|
+
} satisfies PaymentConfig
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## config/saas.ts
|
|
322
|
+
|
|
323
|
+
Plans use `productName`, `description`, `metadata`, and a `pricing` array where each entry has `key` (lookup_key), `price` (in cents), `interval` (optional: 'month' | 'year'), `currency`:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
{
|
|
327
|
+
plans: [
|
|
328
|
+
{
|
|
329
|
+
productName: 'Stacks Hobby',
|
|
330
|
+
description: 'All the Stacks features.',
|
|
331
|
+
pricing: [
|
|
332
|
+
{ key: 'stacks_hobby_early_monthly', price: 1900, interval: 'month', currency: 'usd' },
|
|
333
|
+
{ key: 'stacks_hobby_yearly', price: 37900, interval: 'year', currency: 'usd' },
|
|
334
|
+
],
|
|
335
|
+
metadata: { createdBy: 'admin', version: '1.0.0' },
|
|
336
|
+
},
|
|
337
|
+
// ... more plans
|
|
338
|
+
],
|
|
339
|
+
webhook: { endpoint: 'your-webhook-endpoint', secret: 'your-webhook-secret' },
|
|
340
|
+
currencies: ['usd'],
|
|
341
|
+
coupons: [],
|
|
342
|
+
products: [
|
|
343
|
+
{ name: 'Stacks Hobby', description: '...', images: ['image-url'] },
|
|
344
|
+
],
|
|
345
|
+
} satisfies SaasConfig
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Database Tables Used
|
|
349
|
+
- `subscriptions` -- columns: `user_id`, `type`, `unit_price`, `provider_id`, `provider_status`, `provider_price_id`, `quantity`, `trial_ends_at`, `ends_at`, `provider_type`, `last_used_at`
|
|
350
|
+
- `payment_methods` -- columns: `id`, `type`, `last_four`, `brand`, `exp_year`, `exp_month`, `user_id`, `provider_id`, `is_default`
|
|
351
|
+
- `payment_products` -- columns: `id`, `name`, `unit_price`
|
|
352
|
+
- `payment_transactions` -- columns: `id`, `name`, `description`, `amount`, `brand`, `type`, `provider_id`, `user_id`
|
|
353
|
+
|
|
354
|
+
## User Model Requirements
|
|
355
|
+
The `UserModel` must have:
|
|
356
|
+
- `id`, `name`, `email`, `stripe_id` fields
|
|
357
|
+
- `hasStripeId()` method -- returns boolean
|
|
358
|
+
- `update(data)` method -- for persisting `stripe_id`
|
|
359
|
+
- `activeSubscription()` method -- for subscription updates
|
|
360
|
+
|
|
361
|
+
## Gotchas
|
|
362
|
+
- Stripe API keys MUST be in `.env` as `STRIPE_SECRET_KEY` and `STRIPE_PUBLISHABLE_KEY` -- never hardcode them in config files
|
|
363
|
+
- The Stripe SDK is initialized eagerly -- if `STRIPE_SECRET_KEY` is missing, the module throws on import
|
|
364
|
+
- All amounts are in cents -- use `toCents()` and `toDollars()` for conversion
|
|
365
|
+
- `charge()` creates AND confirms the PaymentIntent in one step
|
|
366
|
+
- `subscribe()` resolves the price via `lookup_key`, not a direct Stripe price ID
|
|
367
|
+
- `removePaymentMethod()` takes a database record ID (number), not a Stripe PM ID (string)
|
|
368
|
+
- `setDefaultPaymentMethod` has two variants: one takes a Stripe PM ID string (`setUserDefaultPayment`), the other takes a database ID number
|
|
369
|
+
- `getOrCreateCustomer()` handles deleted Stripe customers by recreating them
|
|
370
|
+
- Subscription status checks query the local database, not Stripe directly
|
|
371
|
+
- `list()` on products defaults to `active: true` only
|
|
372
|
+
- Webhook handlers are stored in an in-memory Map -- register them on application startup
|
|
373
|
+
- `processWebhook()` uses `stripe.webhooks.constructEvent()` for signature verification
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stacks-plan-review
|
|
3
|
+
description: Use for architecture review of Stacks changes — scope review (CEO-level), data flow analysis, dependency analysis, test matrices, and implementation plans. Invoke with /stacks-plan-review.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
|
+
allowed-tools: Read Edit Write Bash Grep Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /stacks-plan-review — Architecture Review & Planning
|
|
10
|
+
|
|
11
|
+
You analyze proposed changes at two levels: scope review (are we building the right thing?) and engineering review (are we building it right?).
|
|
12
|
+
|
|
13
|
+
## Upstream Context
|
|
14
|
+
|
|
15
|
+
If `/stacks-office-hours` produced a design document, read it. Don't ask the user to re-explain.
|
|
16
|
+
|
|
17
|
+
## Step 1: Scope Review
|
|
18
|
+
|
|
19
|
+
### Expansion Analysis — Is this doing too much
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
| Addition | Core to goal? | Can ship separately? | Risk if included |
|
|
23
|
+
|----------|--------------|---------------------|-----------------|
|
|
24
|
+
| [item] | [yes/no] | [yes/no] | [risk] |
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Reduction Analysis — Is this doing too little
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
| Missing piece | Needed for v1? | Cost of deferring |
|
|
31
|
+
|---------------|---------------|-------------------|
|
|
32
|
+
| [item] | [yes/no] | [consequence] |
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
📊 Scope: [RIGHT-SIZED / TOO BROAD / TOO NARROW]
|
|
37
|
+
Recommended scope: [what should be in vs. out]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Step 2: Data Flow Analysis
|
|
41
|
+
|
|
42
|
+
Trace data through the Stacks system:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
[entry point] → [transformation] (file:function) → [exit point]
|
|
46
|
+
Error paths: [what happens when each step fails]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
For Stacks projects, pay attention to:
|
|
50
|
+
- Cross-package data flow in the monorepo (`storage/framework/core/*/`)
|
|
51
|
+
- Build pipeline flow (source → `bun build` → `dist/`)
|
|
52
|
+
- Request flow: route → middleware → action → ORM → database
|
|
53
|
+
- CLI flow: `buddy` command → action → core package
|
|
54
|
+
|
|
55
|
+
## Step 3: Architecture Review
|
|
56
|
+
|
|
57
|
+
### Dependency Analysis
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
### This change depends on:
|
|
61
|
+
| Dependency | Type | Stability | Risk |
|
|
62
|
+
|-----------|------|-----------|------|
|
|
63
|
+
| [@stacksjs/package] | [internal] | [stable/changing] | [what could break] |
|
|
64
|
+
|
|
65
|
+
### Depends on this change:
|
|
66
|
+
| Consumer | Impact | Migration needed? |
|
|
67
|
+
|----------|--------|-------------------|
|
|
68
|
+
| [package] | [what changes] | [yes/no] |
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Interface Review
|
|
72
|
+
|
|
73
|
+
For new/changed public interfaces:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
### [Interface] (file:line)
|
|
77
|
+
**Before**: [existing signature]
|
|
78
|
+
**After**: [proposed signature]
|
|
79
|
+
**Breaking?**: [yes/no]
|
|
80
|
+
**Migration path**: [how consumers update]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Consistency Check
|
|
84
|
+
|
|
85
|
+
- Naming: match existing patterns in the codebase
|
|
86
|
+
- Error handling: does this project throw, return Result types, or use error codes?
|
|
87
|
+
- Config: does it follow `defineX()` pattern from `@stacksjs/config`?
|
|
88
|
+
- Testing: does it follow `bun test` patterns?
|
|
89
|
+
|
|
90
|
+
## Step 4: Test Matrix
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
### Unit Tests
|
|
94
|
+
| Function | Test Case | Input | Expected | Priority |
|
|
95
|
+
|----------|-----------|-------|----------|----------|
|
|
96
|
+
|
|
97
|
+
### Integration Tests
|
|
98
|
+
| Flow | Components | Scenario | Priority |
|
|
99
|
+
|------|-----------|----------|----------|
|
|
100
|
+
|
|
101
|
+
### Edge Cases
|
|
102
|
+
| Case | Why it matters | Test approach |
|
|
103
|
+
|------|---------------|---------------|
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
P0: Must have before merge. P1: Should have. P2: Nice to have.
|
|
107
|
+
|
|
108
|
+
## Step 5: Implementation Plan
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
### Phase 1: [name]
|
|
112
|
+
- [ ] [task with file references]
|
|
113
|
+
**Checkpoint**: [what should be true]
|
|
114
|
+
|
|
115
|
+
### Phase 2: [name]
|
|
116
|
+
- [ ] [task]
|
|
117
|
+
**Checkpoint**: [what should be true]
|
|
118
|
+
|
|
119
|
+
### Rollback Plan
|
|
120
|
+
1. [specific rollback step]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Each phase should be independently mergeable. Run `bun test` at each checkpoint.
|
|
124
|
+
|
|
125
|
+
## Output
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
# Plan: [feature/change]
|
|
129
|
+
|
|
130
|
+
## Scope Assessment
|
|
131
|
+
## Data Flow
|
|
132
|
+
## Architecture Review
|
|
133
|
+
## Test Matrix
|
|
134
|
+
## Implementation Plan
|
|
135
|
+
|
|
136
|
+
## Summary
|
|
137
|
+
- Scope: [assessment]
|
|
138
|
+
- Breaking changes: [yes/no]
|
|
139
|
+
- New dependencies: [list]
|
|
140
|
+
- Key risk: [biggest risk + mitigation]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Rules
|
|
144
|
+
|
|
145
|
+
- **Scope review is not optional.** Even for "just a technical plan."
|
|
146
|
+
- **Be specific about files.** "Update auth" → "Add token validation in `storage/framework/core/auth/src/middleware.ts`"
|
|
147
|
+
- **Test matrix before implementation.** Knowing what to test shapes how you build.
|
|
148
|
+
- **For Stacks monorepo**: always check cross-package impacts.
|
|
149
|
+
|
|
150
|
+
## Downstream
|
|
151
|
+
|
|
152
|
+
> **Plan complete.** After implementation, run `/stacks-review` for code review, `/stacks-security-audit` for security, or `/stacks-browse` for QA.
|