@omega.js/backend 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +98 -0
- package/README.md +1053 -0
- package/bin/omega +2 -0
- package/bin/omega-backend +2 -0
- package/bin/omg +2 -0
- package/cli.js +3 -0
- package/dist/cli/command-table.js +268 -0
- package/dist/cli/commands/auth.js +259 -0
- package/dist/cli/commands/base-command.js +451 -0
- package/dist/cli/commands/build.js +27 -0
- package/dist/cli/commands/clean.js +13 -0
- package/dist/cli/commands/clear.js +11 -0
- package/dist/cli/commands/cwd.js +9 -0
- package/dist/cli/commands/deploy.js +205 -0
- package/dist/cli/commands/emulator-orphans.js +440 -0
- package/dist/cli/commands/emulator.js +1829 -0
- package/dist/cli/commands/firebase-init.js +101 -0
- package/dist/cli/commands/firestore.js +261 -0
- package/dist/cli/commands/indexes.js +51 -0
- package/dist/cli/commands/install.js +151 -0
- package/dist/cli/commands/logs.js +358 -0
- package/dist/cli/commands/mcp.js +41 -0
- package/dist/cli/commands/migrate-markers.js +176 -0
- package/dist/cli/commands/migrate-rules.js +90 -0
- package/dist/cli/commands/migrate.js +59 -0
- package/dist/cli/commands/serve.js +208 -0
- package/dist/cli/commands/setup-tests/base-test.js +174 -0
- package/dist/cli/commands/setup-tests/emulator-config.js +109 -0
- package/dist/cli/commands/setup-tests/env-runtime-config-deprecated.js +47 -0
- package/dist/cli/commands/setup-tests/firebase-admin.js +49 -0
- package/dist/cli/commands/setup-tests/firebase-auth.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-cli.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-functions.js +49 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-file.js +72 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-required.js +108 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-synced.js +236 -0
- package/dist/cli/commands/setup-tests/firestore-rules-file.js +115 -0
- package/dist/cli/commands/setup-tests/firestore-rules-in-json.js +49 -0
- package/dist/cli/commands/setup-tests/functions-package.js +44 -0
- package/dist/cli/commands/setup-tests/gcloud-cli.js +26 -0
- package/dist/cli/commands/setup-tests/gitignore.js +122 -0
- package/dist/cli/commands/setup-tests/helpers/merge-line-files.js +28 -0
- package/dist/cli/commands/setup-tests/helpers/required-indexes.js +109 -0
- package/dist/cli/commands/setup-tests/helpers/seed-campaigns.js +246 -0
- package/dist/cli/commands/setup-tests/helpers.js +72 -0
- package/dist/cli/commands/setup-tests/hosting-folder.js +23 -0
- package/dist/cli/commands/setup-tests/hosting-rewrites.js +52 -0
- package/dist/cli/commands/setup-tests/index.js +111 -0
- package/dist/cli/commands/setup-tests/is-firebase-project.js +21 -0
- package/dist/cli/commands/setup-tests/java-installed.js +27 -0
- package/dist/cli/commands/setup-tests/legacy-tests-cleanup.js +43 -0
- package/dist/cli/commands/setup-tests/marketing-campaigns-seeded.js +230 -0
- package/dist/cli/commands/setup-tests/node-version.js +60 -0
- package/dist/cli/commands/setup-tests/npm-project-scripts.js +42 -0
- package/dist/cli/commands/setup-tests/nvmrc-version.js +36 -0
- package/dist/cli/commands/setup-tests/omega-backend.js +42 -0
- package/dist/cli/commands/setup-tests/omega-config.js +84 -0
- package/dist/cli/commands/setup-tests/project-directories.js +34 -0
- package/dist/cli/commands/setup-tests/project-id-consistency.js +201 -0
- package/dist/cli/commands/setup-tests/public-html-files.js +22 -0
- package/dist/cli/commands/setup-tests/realtime-rules-file.js +69 -0
- package/dist/cli/commands/setup-tests/realtime-rules-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-file.js +32 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-in-json.js +31 -0
- package/dist/cli/commands/setup-tests/service-account.js +86 -0
- package/dist/cli/commands/setup-tests/storage-lifecycle-policy.js +81 -0
- package/dist/cli/commands/setup-tests/storage-rules-file.js +32 -0
- package/dist/cli/commands/setup-tests/storage-rules-in-json.js +20 -0
- package/dist/cli/commands/stripe.js +14 -0
- package/dist/cli/commands/test-lanes/stripe-live.js +440 -0
- package/dist/cli/commands/test.js +976 -0
- package/dist/cli/commands/update.js +27 -0
- package/dist/cli/commands/version.js +10 -0
- package/dist/cli/commands/watch.js +196 -0
- package/dist/cli/flags.js +13 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/run.js +33 -0
- package/dist/cli/utils/attach-log-file.js +4 -0
- package/dist/cli/utils/compile-rules.js +1155 -0
- package/dist/cli/utils/ensure-target.js +314 -0
- package/dist/cli/utils/project-type.js +140 -0
- package/dist/cli/utils/public-files.js +49 -0
- package/dist/cli/utils/safe-install.js +4 -0
- package/dist/cli/utils/spawn-shell.js +94 -0
- package/dist/cli/utils/stage-functions.js +338 -0
- package/dist/cli/utils/stage-local-packages.js +210 -0
- package/dist/cli/utils/target-checks.js +161 -0
- package/dist/cli/utils/target.js +24 -0
- package/dist/cli/utils/ui.js +292 -0
- package/dist/defaults/AGENTS.md +125 -0
- package/dist/defaults/CHANGELOG.md +15 -0
- package/dist/defaults/CLAUDE.md +1 -0
- package/dist/defaults/_.gitignore +65 -0
- package/dist/defaults/docs/README.md +17 -0
- package/dist/defaults/test/README.md +65 -0
- package/dist/defaults/test/_init.js +14 -0
- package/dist/defaults/test/helpers/connect-trap.js +72 -0
- package/dist/defaults/test/unit/registration.test.js +143 -0
- package/dist/defaults/test/unit/rules-posture.test.js +101 -0
- package/dist/defaults/test/unit/socket-free.test.js +43 -0
- package/dist/manager/events/auth/before-create.js +89 -0
- package/dist/manager/events/auth/before-signin.js +76 -0
- package/dist/manager/events/auth/on-create.js +112 -0
- package/dist/manager/events/auth/on-delete.js +141 -0
- package/dist/manager/events/auth/utils.js +93 -0
- package/dist/manager/events/cron/daily/blog-auto-publisher.js +287 -0
- package/dist/manager/events/cron/daily/data-requests.js +57 -0
- package/dist/manager/events/cron/daily/expire-paypal-cancellations.js +191 -0
- package/dist/manager/events/cron/daily/marketing-prune.js +486 -0
- package/dist/manager/events/cron/daily/reset-usage.js +188 -0
- package/dist/manager/events/cron/daily/trial-lapse-sweep.js +355 -0
- package/dist/manager/events/cron/daily.js +3 -0
- package/dist/manager/events/cron/frequent/abandoned-carts.js +204 -0
- package/dist/manager/events/cron/frequent/email-queue.js +71 -0
- package/dist/manager/events/cron/frequent/marketing-campaigns.js +463 -0
- package/dist/manager/events/cron/frequent/retry-failed-webhooks.js +70 -0
- package/dist/manager/events/cron/frequent.js +3 -0
- package/dist/manager/events/cron/runner.js +64 -0
- package/dist/manager/events/firestore/notifications/on-write.js +123 -0
- package/dist/manager/events/firestore/payments-disputes/on-write.js +256 -0
- package/dist/manager/events/firestore/payments-disputes/providers/stripe.js +218 -0
- package/dist/manager/events/firestore/payments-disputes/providers/test.js +231 -0
- package/dist/manager/events/firestore/payments-webhooks/analytics.js +687 -0
- package/dist/manager/events/firestore/payments-webhooks/on-write.js +1224 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/index.js +395 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-completed.js +58 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-failed.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-refunded.js +30 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/send-email.js +74 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-removed.js +14 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-requested.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/checkout-declined.js +18 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/new-subscription.js +67 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-failed.js +25 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-recovered.js +26 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-refunded.js +34 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/plan-changed.js +42 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-cancelled.js +33 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-winback.js +17 -0
- package/dist/manager/functions/_legacy/actions/create-post-handler.js +188 -0
- package/dist/manager/functions/_legacy/actions/generate-uuid.js +63 -0
- package/dist/manager/functions/_legacy/actions/sign-up-handler.js +205 -0
- package/dist/manager/functions/_legacy/admin/create-post.js +207 -0
- package/dist/manager/functions/_legacy/admin/firestore-write.js +72 -0
- package/dist/manager/functions/_legacy/admin/get-stats.js +218 -0
- package/dist/manager/functions/_legacy/admin/query.js +198 -0
- package/dist/manager/functions/_legacy/admin/send-notification.js +206 -0
- package/dist/manager/functions/_legacy/template.js +33 -0
- package/dist/manager/functions/_legacy/test/authenticate.js +40 -0
- package/dist/manager/functions/_legacy/test/webhook.js +37 -0
- package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
- package/dist/manager/helpers/analytics.js +498 -0
- package/dist/manager/helpers/api-manager.js +313 -0
- package/dist/manager/helpers/backend-router.js +37 -0
- package/dist/manager/helpers/context/authenticate.js +215 -0
- package/dist/manager/helpers/context/client-info.js +91 -0
- package/dist/manager/helpers/context/index.js +228 -0
- package/dist/manager/helpers/context/logging.js +150 -0
- package/dist/manager/helpers/context/parse.js +160 -0
- package/dist/manager/helpers/context/respond.js +247 -0
- package/dist/manager/helpers/event-middleware.js +109 -0
- package/dist/manager/helpers/metadata.js +32 -0
- package/dist/manager/helpers/middleware.js +541 -0
- package/dist/manager/helpers/redact-secret.js +25 -0
- package/dist/manager/helpers/resolved-config.js +34 -0
- package/dist/manager/helpers/roles.js +69 -0
- package/dist/manager/helpers/safe-compare.js +31 -0
- package/dist/manager/helpers/schema-engine.js +314 -0
- package/dist/manager/helpers/schema-zod.js +203 -0
- package/dist/manager/helpers/settings.js +215 -0
- package/dist/manager/helpers/usage.js +541 -0
- package/dist/manager/helpers/user.js +57 -0
- package/dist/manager/helpers/utilities.js +565 -0
- package/dist/manager/index.js +1404 -0
- package/dist/manager/libraries/abandoned-cart-config.js +12 -0
- package/dist/manager/libraries/ai/index.js +321 -0
- package/dist/manager/libraries/ai/prompt.js +85 -0
- package/dist/manager/libraries/ai/providers/anthropic-format.js +297 -0
- package/dist/manager/libraries/ai/providers/anthropic.js +169 -0
- package/dist/manager/libraries/ai/providers/claude-code.js +183 -0
- package/dist/manager/libraries/ai/providers/openai.js +1272 -0
- package/dist/manager/libraries/ai/providers/test.js +257 -0
- package/dist/manager/libraries/ai/tokens.js +54 -0
- package/dist/manager/libraries/analytics/conversions.js +478 -0
- package/dist/manager/libraries/analytics/match-data.js +573 -0
- package/dist/manager/libraries/analytics/signup.js +120 -0
- package/dist/manager/libraries/auth-user.js +46 -0
- package/dist/manager/libraries/content/feed-parser.js +198 -0
- package/dist/manager/libraries/content/ghostii.js +191 -0
- package/dist/manager/libraries/content/source-resolver.js +629 -0
- package/dist/manager/libraries/email/constants.js +532 -0
- package/dist/manager/libraries/email/data/blocked-local-parts.json +55 -0
- package/dist/manager/libraries/email/data/blocked-local-patterns.js +14 -0
- package/dist/manager/libraries/email/data/corporate-domains.json +23 -0
- package/dist/manager/libraries/email/data/custom-disposable-domains.json +58 -0
- package/dist/manager/libraries/email/data/disposable-domains.json +8184 -0
- package/dist/manager/libraries/email/data/typo-domains.js +83 -0
- package/dist/manager/libraries/email/disposable-domains.js +92 -0
- package/dist/manager/libraries/email/generators/lib/filter.js +179 -0
- package/dist/manager/libraries/email/generators/lib/image-host.js +344 -0
- package/dist/manager/libraries/email/generators/lib/image-illustrator.js +154 -0
- package/dist/manager/libraries/email/generators/lib/markdown-renderer.js +294 -0
- package/dist/manager/libraries/email/generators/lib/mjml-template.js +120 -0
- package/dist/manager/libraries/email/generators/lib/structure.js +299 -0
- package/dist/manager/libraries/email/generators/lib/svg-illustrator.js +197 -0
- package/dist/manager/libraries/email/generators/lib/templates/base.js +229 -0
- package/dist/manager/libraries/email/generators/lib/templates/card.js +33 -0
- package/dist/manager/libraries/email/generators/lib/templates/classic-schema.js +59 -0
- package/dist/manager/libraries/email/generators/lib/templates/clean.js +82 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/helpers.js +100 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/index.js +318 -0
- package/dist/manager/libraries/email/generators/lib/templates/feedback.js +101 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/helpers.js +138 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/index.js +494 -0
- package/dist/manager/libraries/email/generators/lib/templates/index.js +47 -0
- package/dist/manager/libraries/email/generators/lib/templates/newsletter-shared.js +610 -0
- package/dist/manager/libraries/email/generators/lib/templates/order.js +461 -0
- package/dist/manager/libraries/email/generators/lib/templates/plain.js +83 -0
- package/dist/manager/libraries/email/generators/lib/templates/shared-campaign.js +64 -0
- package/dist/manager/libraries/email/generators/newsletter.js +899 -0
- package/dist/manager/libraries/email/index.js +146 -0
- package/dist/manager/libraries/email/marketing/index.js +754 -0
- package/dist/manager/libraries/email/prepare.js +365 -0
- package/dist/manager/libraries/email/providers/beehiiv.js +589 -0
- package/dist/manager/libraries/email/providers/sendgrid.js +845 -0
- package/dist/manager/libraries/email/transactional/index.js +510 -0
- package/dist/manager/libraries/email/utm.js +86 -0
- package/dist/manager/libraries/email/validation-provider-neverbounce.js +70 -0
- package/dist/manager/libraries/email/validation-provider-zerobounce.js +42 -0
- package/dist/manager/libraries/email/validation.js +255 -0
- package/dist/manager/libraries/env.js +198 -0
- package/dist/manager/libraries/infer-contact.js +101 -0
- package/dist/manager/libraries/load-provider.js +65 -0
- package/dist/manager/libraries/notification.js +256 -0
- package/dist/manager/libraries/openai.js +13 -0
- package/dist/manager/libraries/payment/discount-codes.js +204 -0
- package/dist/manager/libraries/payment/fetch-failure.js +56 -0
- package/dist/manager/libraries/payment/license.js +44 -0
- package/dist/manager/libraries/payment/order-id.js +57 -0
- package/dist/manager/libraries/payment/provider-errors.js +71 -0
- package/dist/manager/libraries/payment/providers/chargebee.js +817 -0
- package/dist/manager/libraries/payment/providers/coinbase.js +330 -0
- package/dist/manager/libraries/payment/providers/paypal.js +987 -0
- package/dist/manager/libraries/payment/providers/stripe.js +755 -0
- package/dist/manager/libraries/payment/providers/test.js +250 -0
- package/dist/manager/libraries/payment/refund-linkage.js +78 -0
- package/dist/manager/libraries/payment/refund-policy.js +113 -0
- package/dist/manager/libraries/payment/winback.js +55 -0
- package/dist/manager/libraries/prompts/infer-contact.md +78 -0
- package/dist/manager/libraries/rate-limits.js +17 -0
- package/dist/manager/libraries/recaptcha.js +58 -0
- package/dist/manager/libraries/user-doc.js +234 -0
- package/dist/manager/routes/admin/backup/post.js +106 -0
- package/dist/manager/routes/admin/cron/post.js +37 -0
- package/dist/manager/routes/admin/database/get.js +35 -0
- package/dist/manager/routes/admin/database/post.js +34 -0
- package/dist/manager/routes/admin/email/post.js +74 -0
- package/dist/manager/routes/admin/firestore/get.js +35 -0
- package/dist/manager/routes/admin/firestore/post.js +56 -0
- package/dist/manager/routes/admin/firestore/query/post.js +128 -0
- package/dist/manager/routes/admin/hook/post.js +104 -0
- package/dist/manager/routes/admin/infer-contact/post.js +35 -0
- package/dist/manager/routes/admin/notification/post.js +37 -0
- package/dist/manager/routes/admin/payment/post.js +56 -0
- package/dist/manager/routes/admin/post/deduplicate-image-alts.js +52 -0
- package/dist/manager/routes/admin/post/dispatch-deploy.js +36 -0
- package/dist/manager/routes/admin/post/post.js +487 -0
- package/dist/manager/routes/admin/post/put.js +146 -0
- package/dist/manager/routes/admin/post/templates/post.html +14 -0
- package/dist/manager/routes/admin/repo/content/post.js +106 -0
- package/dist/manager/routes/admin/stats/get.js +222 -0
- package/dist/manager/routes/admin/users/disable/post.js +50 -0
- package/dist/manager/routes/admin/users/list/get.js +110 -0
- package/dist/manager/routes/admin/users/sync/post.js +119 -0
- package/dist/manager/routes/brand/get.js +26 -0
- package/dist/manager/routes/content/post/get.js +110 -0
- package/dist/manager/routes/general/email/post.js +89 -0
- package/dist/manager/routes/general/email/templates/general/download-app-link.js +42 -0
- package/dist/manager/routes/general/uuid/post.js +31 -0
- package/dist/manager/routes/handler/post/post.js +142 -0
- package/dist/manager/routes/health/get.js +43 -0
- package/dist/manager/routes/index.js +11 -0
- package/dist/manager/routes/marketing/campaign/delete.js +45 -0
- package/dist/manager/routes/marketing/campaign/get.js +69 -0
- package/dist/manager/routes/marketing/campaign/post.js +124 -0
- package/dist/manager/routes/marketing/campaign/put.js +86 -0
- package/dist/manager/routes/marketing/campaign/utils.js +59 -0
- package/dist/manager/routes/marketing/contact/delete.js +100 -0
- package/dist/manager/routes/marketing/contact/post.js +149 -0
- package/dist/manager/routes/marketing/contact/put.js +37 -0
- package/dist/manager/routes/marketing/email-preferences/post.js +275 -0
- package/dist/manager/routes/marketing/webhook/forward/post.js +170 -0
- package/dist/manager/routes/marketing/webhook/post.js +123 -0
- package/dist/manager/routes/marketing/webhook/providers/beehiiv.js +197 -0
- package/dist/manager/routes/marketing/webhook/providers/sendgrid.js +194 -0
- package/dist/manager/routes/payments/cancel/_is-trialing.js +40 -0
- package/dist/manager/routes/payments/cancel/post.js +149 -0
- package/dist/manager/routes/payments/cancel/providers/chargebee.js +41 -0
- package/dist/manager/routes/payments/cancel/providers/paypal.js +56 -0
- package/dist/manager/routes/payments/cancel/providers/stripe.js +33 -0
- package/dist/manager/routes/payments/cancel/providers/test.js +118 -0
- package/dist/manager/routes/payments/discount/get.js +25 -0
- package/dist/manager/routes/payments/dispute-alert/post.js +117 -0
- package/dist/manager/routes/payments/dispute-alert/providers/chargeblast.js +55 -0
- package/dist/manager/routes/payments/intent/post.js +341 -0
- package/dist/manager/routes/payments/intent/providers/chargebee.js +197 -0
- package/dist/manager/routes/payments/intent/providers/coinbase.js +94 -0
- package/dist/manager/routes/payments/intent/providers/paypal.js +244 -0
- package/dist/manager/routes/payments/intent/providers/stripe.js +141 -0
- package/dist/manager/routes/payments/intent/providers/test.js +341 -0
- package/dist/manager/routes/payments/plan/post.js +147 -0
- package/dist/manager/routes/payments/plan/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/plan/providers/paypal.js +62 -0
- package/dist/manager/routes/payments/plan/providers/stripe.js +59 -0
- package/dist/manager/routes/payments/plan/providers/test.js +113 -0
- package/dist/manager/routes/payments/portal/post.js +113 -0
- package/dist/manager/routes/payments/portal/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/portal/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/portal/providers/stripe.js +62 -0
- package/dist/manager/routes/payments/portal/providers/test.js +18 -0
- package/dist/manager/routes/payments/refund/post.js +207 -0
- package/dist/manager/routes/payments/refund/providers/chargebee.js +147 -0
- package/dist/manager/routes/payments/refund/providers/coinbase.js +40 -0
- package/dist/manager/routes/payments/refund/providers/paypal.js +239 -0
- package/dist/manager/routes/payments/refund/providers/stripe.js +160 -0
- package/dist/manager/routes/payments/refund/providers/test.js +204 -0
- package/dist/manager/routes/payments/trial-eligibility/get.js +29 -0
- package/dist/manager/routes/payments/uncancel/post.js +106 -0
- package/dist/manager/routes/payments/uncancel/providers/chargebee.js +30 -0
- package/dist/manager/routes/payments/uncancel/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/uncancel/providers/stripe.js +27 -0
- package/dist/manager/routes/payments/uncancel/providers/test.js +114 -0
- package/dist/manager/routes/payments/webhook/post.js +157 -0
- package/dist/manager/routes/payments/webhook/providers/chargebee.js +218 -0
- package/dist/manager/routes/payments/webhook/providers/coinbase.js +91 -0
- package/dist/manager/routes/payments/webhook/providers/paypal.js +214 -0
- package/dist/manager/routes/payments/webhook/providers/stripe.js +182 -0
- package/dist/manager/routes/payments/webhook/providers/test.js +18 -0
- package/dist/manager/routes/payments/winback/post.js +276 -0
- package/dist/manager/routes/payments/winback/providers/chargebee.js +24 -0
- package/dist/manager/routes/payments/winback/providers/paypal.js +22 -0
- package/dist/manager/routes/payments/winback/providers/stripe.js +41 -0
- package/dist/manager/routes/payments/winback/providers/test.js +42 -0
- package/dist/manager/routes/restart/index.js +37 -0
- package/dist/manager/routes/special/electron-client/post.js +59 -0
- package/dist/manager/routes/test/authenticate/get.js +11 -0
- package/dist/manager/routes/test/health/get.js +8 -0
- package/dist/manager/routes/test/index.js +16 -0
- package/dist/manager/routes/test/lab/post.js +17 -0
- package/dist/manager/routes/test/redirect/get.js +27 -0
- package/dist/manager/routes/test/reset-account/post.js +79 -0
- package/dist/manager/routes/test/roster/get.js +40 -0
- package/dist/manager/routes/test/schema/post.js +20 -0
- package/dist/manager/routes/test/usage/post.js +44 -0
- package/dist/manager/routes/test/webhook/post.js +21 -0
- package/dist/manager/routes/user/api-keys/post.js +51 -0
- package/dist/manager/routes/user/connections/_context.js +194 -0
- package/dist/manager/routes/user/connections/_grant.js +247 -0
- package/dist/manager/routes/user/connections/_lease.js +184 -0
- package/dist/manager/routes/user/connections/_providers.js +191 -0
- package/dist/manager/routes/user/connections/_state.js +117 -0
- package/dist/manager/routes/user/connections/delete.js +55 -0
- package/dist/manager/routes/user/connections/get.js +167 -0
- package/dist/manager/routes/user/connections/post.js +370 -0
- package/dist/manager/routes/user/connections/providers/discord.js +41 -0
- package/dist/manager/routes/user/connections/providers/google.js +55 -0
- package/dist/manager/routes/user/connections/providers/kick.js +68 -0
- package/dist/manager/routes/user/connections/providers/spotify.js +40 -0
- package/dist/manager/routes/user/connections/providers/twitch.js +52 -0
- package/dist/manager/routes/user/data-request/delete.js +84 -0
- package/dist/manager/routes/user/data-request/get.js +229 -0
- package/dist/manager/routes/user/data-request/post.js +136 -0
- package/dist/manager/routes/user/delete.js +149 -0
- package/dist/manager/routes/user/feedback/post.js +81 -0
- package/dist/manager/routes/user/get.js +14 -0
- package/dist/manager/routes/user/orders/get.js +95 -0
- package/dist/manager/routes/user/sessions/delete.js +95 -0
- package/dist/manager/routes/user/sessions/get.js +40 -0
- package/dist/manager/routes/user/settings/validate/post.js +86 -0
- package/dist/manager/routes/user/signup/post.js +662 -0
- package/dist/manager/routes/user/subscription/get.js +77 -0
- package/dist/manager/routes/user/token/post.js +30 -0
- package/dist/manager/routes/verts/delete.js +43 -0
- package/dist/manager/routes/verts/get.js +49 -0
- package/dist/manager/routes/verts/post.js +61 -0
- package/dist/manager/routes/verts/put.js +75 -0
- package/dist/manager/routes/verts/redirect/get.js +36 -0
- package/dist/manager/routes/verts/serve/get.js +67 -0
- package/dist/manager/routes/verts/utils.js +436 -0
- package/dist/manager/schemas/admin/backup/post.js +8 -0
- package/dist/manager/schemas/admin/cron/post.js +8 -0
- package/dist/manager/schemas/admin/database/get.js +5 -0
- package/dist/manager/schemas/admin/database/post.js +6 -0
- package/dist/manager/schemas/admin/email/post.js +31 -0
- package/dist/manager/schemas/admin/firestore/get.js +5 -0
- package/dist/manager/schemas/admin/firestore/post.js +8 -0
- package/dist/manager/schemas/admin/firestore/query/post.js +5 -0
- package/dist/manager/schemas/admin/hook/post.js +8 -0
- package/dist/manager/schemas/admin/infer-contact/post.js +6 -0
- package/dist/manager/schemas/admin/notification/post.js +23 -0
- package/dist/manager/schemas/admin/payment/post.js +8 -0
- package/dist/manager/schemas/admin/post/post.js +23 -0
- package/dist/manager/schemas/admin/post/put.js +13 -0
- package/dist/manager/schemas/admin/repo/content/post.js +10 -0
- package/dist/manager/schemas/admin/stats/get.js +5 -0
- package/dist/manager/schemas/admin/users/disable/post.js +9 -0
- package/dist/manager/schemas/admin/users/list/get.js +10 -0
- package/dist/manager/schemas/admin/users/sync/post.js +7 -0
- package/dist/manager/schemas/brand/get.js +3 -0
- package/dist/manager/schemas/content/post/get.js +8 -0
- package/dist/manager/schemas/general/email/post.js +10 -0
- package/dist/manager/schemas/general/uuid/post.js +9 -0
- package/dist/manager/schemas/handler/post/post.js +13 -0
- package/dist/manager/schemas/health/get.js +3 -0
- package/dist/manager/schemas/marketing/campaign/delete.js +8 -0
- package/dist/manager/schemas/marketing/campaign/get.js +13 -0
- package/dist/manager/schemas/marketing/campaign/post.js +43 -0
- package/dist/manager/schemas/marketing/campaign/put.js +37 -0
- package/dist/manager/schemas/marketing/contact/delete.js +8 -0
- package/dist/manager/schemas/marketing/contact/post.js +14 -0
- package/dist/manager/schemas/marketing/contact/put.js +8 -0
- package/dist/manager/schemas/marketing/email-preferences/post.js +15 -0
- package/dist/manager/schemas/marketing/webhook/forward/post.js +8 -0
- package/dist/manager/schemas/marketing/webhook/post.js +7 -0
- package/dist/manager/schemas/payments/cancel/post.js +15 -0
- package/dist/manager/schemas/payments/discount/get.js +8 -0
- package/dist/manager/schemas/payments/dispute-alert/post.js +6 -0
- package/dist/manager/schemas/payments/intent/post.js +28 -0
- package/dist/manager/schemas/payments/plan/post.js +11 -0
- package/dist/manager/schemas/payments/portal/post.js +12 -0
- package/dist/manager/schemas/payments/refund/post.js +14 -0
- package/dist/manager/schemas/payments/trial-eligibility/get.js +7 -0
- package/dist/manager/schemas/payments/uncancel/post.js +9 -0
- package/dist/manager/schemas/payments/webhook/post.js +6 -0
- package/dist/manager/schemas/payments/winback/post.js +12 -0
- package/dist/manager/schemas/restart/index.js +5 -0
- package/dist/manager/schemas/special/electron-client/post.js +11 -0
- package/dist/manager/schemas/test/authenticate/get.js +3 -0
- package/dist/manager/schemas/test/health/get.js +3 -0
- package/dist/manager/schemas/test/index.js +5 -0
- package/dist/manager/schemas/test/lab/post.js +3 -0
- package/dist/manager/schemas/test/redirect/get.js +7 -0
- package/dist/manager/schemas/test/reset-account/post.js +3 -0
- package/dist/manager/schemas/test/roster/get.js +3 -0
- package/dist/manager/schemas/test/schema/post.js +70 -0
- package/dist/manager/schemas/test/usage/post.js +8 -0
- package/dist/manager/schemas/test/webhook/post.js +7 -0
- package/dist/manager/schemas/user/api-keys/post.js +6 -0
- package/dist/manager/schemas/user/connections/delete.js +8 -0
- package/dist/manager/schemas/user/connections/get.js +21 -0
- package/dist/manager/schemas/user/connections/post.js +12 -0
- package/dist/manager/schemas/user/data-request/delete.js +3 -0
- package/dist/manager/schemas/user/data-request/get.js +5 -0
- package/dist/manager/schemas/user/data-request/post.js +6 -0
- package/dist/manager/schemas/user/delete.js +6 -0
- package/dist/manager/schemas/user/feedback/post.js +8 -0
- package/dist/manager/schemas/user/get.js +3 -0
- package/dist/manager/schemas/user/orders/get.js +6 -0
- package/dist/manager/schemas/user/sessions/delete.js +6 -0
- package/dist/manager/schemas/user/sessions/get.js +6 -0
- package/dist/manager/schemas/user/settings/validate/post.js +8 -0
- package/dist/manager/schemas/user/signup/post.js +27 -0
- package/dist/manager/schemas/user/subscription/get.js +5 -0
- package/dist/manager/schemas/user/token/post.js +5 -0
- package/dist/manager/schemas/verts/delete.js +8 -0
- package/dist/manager/schemas/verts/get.js +9 -0
- package/dist/manager/schemas/verts/post.js +23 -0
- package/dist/manager/schemas/verts/put.js +20 -0
- package/dist/manager/schemas/verts/redirect/get.js +10 -0
- package/dist/manager/schemas/verts/serve/get.js +14 -0
- package/dist/manager/server-manager.js +69 -0
- package/dist/mcp/client.js +98 -0
- package/dist/mcp/handler.js +521 -0
- package/dist/mcp/index.js +157 -0
- package/dist/mcp/tools.js +555 -0
- package/dist/mcp/utils.js +108 -0
- package/dist/omega-bin.js +6 -0
- package/dist/require.js +3 -0
- package/dist/test/fixtures/firebase-project/.firebaserc +5 -0
- package/dist/test/fixtures/firebase-project/config/omega.json5 +131 -0
- package/dist/test/fixtures/firebase-project/database.rules.json +6 -0
- package/dist/test/fixtures/firebase-project/firebase.json +49 -0
- package/dist/test/fixtures/firebase-project/firestore.indexes.json +4 -0
- package/dist/test/fixtures/firebase-project/package.json +14 -0
- package/dist/test/fixtures/firebase-project/src/index.js +11 -0
- package/dist/test/fixtures/firebase-project/storage.rules +8 -0
- package/dist/test/parse-audit.js +25 -0
- package/dist/test/run-tests.js +90 -0
- package/dist/test/runner.js +982 -0
- package/dist/test/seed.js +242 -0
- package/dist/test/test-accounts.js +2660 -0
- package/dist/test/utils/assertions.js +189 -0
- package/dist/test/utils/email-capture.js +252 -0
- package/dist/test/utils/extended-mode-warning.js +11 -0
- package/dist/test/utils/firestore-rules-client.js +277 -0
- package/dist/test/utils/http-client.js +228 -0
- package/dist/test/utils/test-mode-file.js +192 -0
- package/dist/utils/merge-line-files.js +6 -0
- package/dist/utils/scaffold-defaults.js +71 -0
- package/dist/utils/test-lanes.js +62 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/analytics/adapters/ga4.js +26 -0
- package/dist/vendor/analytics/adapters/meta.js +26 -0
- package/dist/vendor/analytics/adapters/resolve.js +130 -0
- package/dist/vendor/analytics/adapters/tiktok.js +27 -0
- package/dist/vendor/analytics/catalog.js +908 -0
- package/dist/vendor/analytics/identity.js +136 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bare-requires.js +153 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/npm-registry.js +52 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/parse-audit.js +74 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/assert.js +120 -0
- package/dist/vendor/devkit/test/define-cases.js +104 -0
- package/dist/vendor/devkit/test/runner-core.js +554 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/monitoring/core.js +180 -0
- package/dist/vendor/monitoring/env.js +49 -0
- package/dist/vendor/monitoring/logger.js +39 -0
- package/dist/vendor/monitoring/node.js +72 -0
- package/docs/admin-post-route.md +57 -0
- package/docs/ai-library.md +171 -0
- package/docs/architecture.md +62 -0
- package/docs/audit.md +70 -0
- package/docs/auth-hooks.md +74 -0
- package/docs/build-system.md +65 -0
- package/docs/cdp-debugging.md +29 -0
- package/docs/cli-firestore-auth.md +85 -0
- package/docs/cli-logs.md +67 -0
- package/docs/cli-output.md +146 -0
- package/docs/code-patterns.md +77 -0
- package/docs/common-mistakes.md +12 -0
- package/docs/common-operations.md +60 -0
- package/docs/connections.md +212 -0
- package/docs/consent.md +362 -0
- package/docs/directory-structure.md +150 -0
- package/docs/email-system.md +459 -0
- package/docs/environment-detection.md +93 -0
- package/docs/file-naming.md +10 -0
- package/docs/firestore.md +134 -0
- package/docs/ghostii.md +240 -0
- package/docs/index.md +299 -0
- package/docs/key-files.md +37 -0
- package/docs/logging.md +60 -0
- package/docs/marketing-campaigns.md +407 -0
- package/docs/marketing-fields.md +25 -0
- package/docs/mcp.md +222 -0
- package/docs/migration.md +129 -0
- package/docs/payment-system.md +856 -0
- package/docs/paypal-sandbox-qa.md +105 -0
- package/docs/response-headers.md +9 -0
- package/docs/routes.md +211 -0
- package/docs/sanitization.md +71 -0
- package/docs/schemas.md +163 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/stripe-webhook-forwarding.md +20 -0
- package/docs/test-boot-layer.md +67 -0
- package/docs/test-framework.md +583 -0
- package/docs/usage-rate-limiting.md +121 -0
- package/docs/verts.md +29 -0
- package/package.json +143 -0
- package/templates/config/omega.json5 +322 -0
- package/templates/database.rules.json +82 -0
- package/templates/firebase.json +67 -0
- package/templates/firestore.framework.rules +191 -0
- package/templates/firestore.indexes.json +4 -0
- package/templates/firestore.rules +59 -0
- package/templates/index.js +12 -0
- package/templates/public/404.html +26 -0
- package/templates/public/index.html +24 -0
- package/templates/remoteconfig.template.json +1 -0
- package/templates/storage-lifecycle-config-1-day.json +9 -0
- package/templates/storage-lifecycle-config-30-days.json +9 -0
- package/templates/storage.rules +11 -0
- package/test/_init/accounts-validation.js +58 -0
- package/test/ai/tools-live.test.js +171 -0
- package/test/analytics/conversion-delivery.test.js +1013 -0
- package/test/analytics/match-normalization.test.js +238 -0
- package/test/analytics/signup-conversion.test.js +135 -0
- package/test/boot/cli-dispatch.test.js +142 -0
- package/test/boot/defaults-scaffold.test.js +248 -0
- package/test/boot/deploy-staging.test.js +446 -0
- package/test/boot/disposable-domains.test.js +154 -0
- package/test/boot/emulator-boots.test.js +39 -0
- package/test/boot/emulator-port-preflight.test.js +126 -0
- package/test/boot/emulator-ready-timeout.test.js +46 -0
- package/test/boot/project-id-refresh.test.js +73 -0
- package/test/boot/suite-portability.test.js +278 -0
- package/test/boot/update-command.test.js +63 -0
- package/test/cli/cross-platform.test.js +168 -0
- package/test/cli/custom-project-type.test.js +426 -0
- package/test/cli/deploy-license-env.test.js +100 -0
- package/test/cli/emulator-adoption.test.js +254 -0
- package/test/cli/emulator-orphans.test.js +658 -0
- package/test/cli/emulator-ownership.test.js +177 -0
- package/test/cli/emulator-port-retry.test.js +395 -0
- package/test/cli/emulator-shutdown.test.js +788 -0
- package/test/cli/emulator-stale-reap.test.js +574 -0
- package/test/cli/ensure-target.test.js +325 -0
- package/test/cli/flags.test.js +64 -0
- package/test/cli/https-trust.test.js +38 -0
- package/test/cli/install-update-dispatch.test.js +47 -0
- package/test/cli/lane-environments.test.js +159 -0
- package/test/cli/marketing-campaigns-seeded.test.js +194 -0
- package/test/cli/migrate-bare-requires.test.js +128 -0
- package/test/cli/migrate-markers.test.js +530 -0
- package/test/cli/required-indexes.test.js +64 -0
- package/test/cli/rules-compile.test.js +622 -0
- package/test/cli/rules-migration-deferral.test.js +259 -0
- package/test/cli/rules-version.test.js +104 -0
- package/test/cli/setup-load-files.test.js +66 -0
- package/test/cli/setup-offline-mode.test.js +276 -0
- package/test/cli/setup-retired.test.js +64 -0
- package/test/cli/setup-shared-project-indexes.test.js +262 -0
- package/test/cli/setup-tests-requires.test.js +45 -0
- package/test/cli/stage-env-compose.test.js +316 -0
- package/test/cli/stripe-live-lane.test.js +303 -0
- package/test/cli/target.test.js +182 -0
- package/test/cli/templates.test.js +66 -0
- package/test/cli/test-runner-env.test.js +115 -0
- package/test/cli/test-stack-shutdown.test.js +275 -0
- package/test/cli/test-target-no-match.test.js +128 -0
- package/test/cli/verb-logs.test.js +118 -0
- package/test/cli/version-dispatch.test.js +39 -0
- package/test/content/blog-generate.test.js +164 -0
- package/test/email/campaign-config-fault.test.js +376 -0
- package/test/email/campaign-cron-pipeline.test.js +536 -0
- package/test/email/campaign-send.test.js +47 -0
- package/test/email/consent-lifecycle.test.js +258 -0
- package/test/email/content-html-policy.test.js +270 -0
- package/test/email/feedback-and-plain-send.test.js +54 -0
- package/test/email/fixtures/clean.json +30 -0
- package/test/email/fixtures/editorial.json +30 -0
- package/test/email/fixtures/field-report.json +53 -0
- package/test/email/identity.test.js +321 -0
- package/test/email/marketing/consent-gate.test.js +265 -0
- package/test/email/marketing/custom-fields-catalog.test.js +259 -0
- package/test/email/marketing/prune-per-provider.test.js +762 -0
- package/test/email/marketing/remove-log-privacy.test.js +225 -0
- package/test/email/marketing-lifecycle.test.js +139 -0
- package/test/email/newsletter-generate.test.js +853 -0
- package/test/email/newsletter-svg-tokens.test.js +51 -0
- package/test/email/newsletter-templates.test.js +492 -0
- package/test/email/order-one-time-cta.test.js +97 -0
- package/test/email/render-content.test.js +248 -0
- package/test/email/safe-url.test.js +0 -0
- package/test/email/sanitize-images.test.js +66 -0
- package/test/email/send-log-privacy.test.js +107 -0
- package/test/email/templates.test.js +288 -0
- package/test/email/testing-capture.test.js +260 -0
- package/test/email/transactional-send.test.js +36 -0
- package/test/email/transactional.test.js +562 -0
- package/test/email/unsubscribe-groups.test.js +155 -0
- package/test/email/unsubscribe-key.test.js +91 -0
- package/test/email/validation-cases.test.js +152 -0
- package/test/email/validation.test.js +746 -0
- package/test/events/auth-delete-conversion.test.js +138 -0
- package/test/events/auth-delete-race.test.js +211 -0
- package/test/events/auth-on-create-log.test.js +164 -0
- package/test/events/auth-signup-conversion.test.js +141 -0
- package/test/events/auth-signup-limit.test.js +142 -0
- package/test/events/auth-trigger-log-privacy.test.js +256 -0
- package/test/events/cron-job-doc-shape.test.js +101 -0
- package/test/events/cron-reset-usage.test.js +116 -0
- package/test/events/notification-conversion.test.js +182 -0
- package/test/events/payments/_webhook-harness.js +307 -0
- package/test/events/payments/abandoned-cart-activity.test.js +135 -0
- package/test/events/payments/analytics-payment-events.test.js +945 -0
- package/test/events/payments/dispute-email-status.test.js +55 -0
- package/test/events/payments/journey-payments-abandoned.test.js +126 -0
- package/test/events/payments/journey-payments-cancel-endpoint.test.js +102 -0
- package/test/events/payments/journey-payments-cancel-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-cancel.test.js +184 -0
- package/test/events/payments/journey-payments-decline.test.js +225 -0
- package/test/events/payments/journey-payments-discount.test.js +91 -0
- package/test/events/payments/journey-payments-dispute.test.js +190 -0
- package/test/events/payments/journey-payments-failure.test.js +148 -0
- package/test/events/payments/journey-payments-legacy-product.test.js +151 -0
- package/test/events/payments/journey-payments-one-time-decline.test.js +127 -0
- package/test/events/payments/journey-payments-one-time-failure.test.js +113 -0
- package/test/events/payments/journey-payments-one-time-refund.test.js +186 -0
- package/test/events/payments/journey-payments-one-time.test.js +175 -0
- package/test/events/payments/journey-payments-plan-change.test.js +146 -0
- package/test/events/payments/journey-payments-plan-switch-trial.test.js +161 -0
- package/test/events/payments/journey-payments-plan-switch.test.js +182 -0
- package/test/events/payments/journey-payments-refund-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-refund-webhook.test.js +225 -0
- package/test/events/payments/journey-payments-suspend.test.js +183 -0
- package/test/events/payments/journey-payments-trial-cancel.test.js +132 -0
- package/test/events/payments/journey-payments-trial.test.js +173 -0
- package/test/events/payments/journey-payments-uid-resolution.test.js +134 -0
- package/test/events/payments/journey-payments-uncancel.test.js +157 -0
- package/test/events/payments/journey-payments-upgrade.test.js +137 -0
- package/test/events/payments/journey-payments-winback-decline.test.js +171 -0
- package/test/events/payments/journey-payments-winback.test.js +195 -0
- package/test/events/payments/paypal-expiry-cron.test.js +166 -0
- package/test/events/payments/purchase-failed-handler.test.js +80 -0
- package/test/events/payments/purchase-refunded-handler.test.js +108 -0
- package/test/events/payments/test-processor-doc-shape.test.js +162 -0
- package/test/events/payments/transition-order-emails.test.js +185 -0
- package/test/events/payments/transition-promo-lines.test.js +192 -0
- package/test/events/payments/transitions-detect.test.js +767 -0
- package/test/events/payments/trial-lapse-sweep-staleness.test.js +173 -0
- package/test/events/payments/trial-lapse-sweep.test.js +359 -0
- package/test/events/payments/webhook-atomic-writes.test.js +69 -0
- package/test/events/payments/webhook-chargebee-unreachable.test.js +106 -0
- package/test/events/payments/webhook-discount-clear.test.js +189 -0
- package/test/events/payments/webhook-failure-intent.test.js +93 -0
- package/test/events/payments/webhook-hosted-page-uid-trust.test.js +212 -0
- package/test/events/payments/webhook-ordering.test.js +326 -0
- package/test/events/payments/webhook-provider-lookup-trust.test.js +206 -0
- package/test/events/payments/webhook-refund-amount-trust.test.js +223 -0
- package/test/events/payments/webhook-refund-envelope-shape.test.js +148 -0
- package/test/events/payments/webhook-refund-linkage-trust.test.js +404 -0
- package/test/events/payments/webhook-refund-transaction-fallback.test.js +184 -0
- package/test/events/payments/webhook-refund-without-order.test.js +170 -0
- package/test/events/payments/webhook-refusal-reporting.test.js +194 -0
- package/test/events/payments/webhook-refused-intent.test.js +142 -0
- package/test/events/payments/webhook-retry-sweep.test.js +252 -0
- package/test/events/payments/webhook-transition-claim.test.js +389 -0
- package/test/events/payments/webhook-uid-trust.test.js +203 -0
- package/test/events/payments/webhook-user-without-auth.test.js +161 -0
- package/test/fixtures/chargebee/invoice-one-time.json +27 -0
- package/test/fixtures/chargebee/subscription-active.json +44 -0
- package/test/fixtures/chargebee/subscription-cancelled.json +42 -0
- package/test/fixtures/chargebee/subscription-in-trial.json +41 -0
- package/test/fixtures/chargebee/subscription-legacy-plan.json +41 -0
- package/test/fixtures/chargebee/subscription-non-renewing.json +41 -0
- package/test/fixtures/chargebee/subscription-paused.json +42 -0
- package/test/fixtures/chargebee/webhook-payment-failed.json +51 -0
- package/test/fixtures/chargebee/webhook-subscription-created.json +47 -0
- package/test/fixtures/coinbase/charge-confirmed.json +50 -0
- package/test/fixtures/coinbase/charge-failed.json +34 -0
- package/test/fixtures/coinbase/charge-pending.json +34 -0
- package/test/fixtures/migrate/ported-route.js.txt +11 -0
- package/test/fixtures/paypal/capture-completed.json +51 -0
- package/test/fixtures/paypal/capture-refunded.json +43 -0
- package/test/fixtures/paypal/order-approved.json +62 -0
- package/test/fixtures/paypal/order-completed.json +110 -0
- package/test/fixtures/paypal/sale-refunded.json +38 -0
- package/test/fixtures/paypal/subscription-active.json +76 -0
- package/test/fixtures/paypal/subscription-cancelled.json +50 -0
- package/test/fixtures/paypal/subscription-suspended.json +65 -0
- package/test/fixtures/stripe/checkout-session-completed.json +130 -0
- package/test/fixtures/stripe/invoice-payment-failed.json +148 -0
- package/test/fixtures/stripe/invoice-subscription-payment-failed.json +28 -0
- package/test/fixtures/stripe/invoice-subscription-payment-succeeded.json +28 -0
- package/test/fixtures/stripe/subscription-active.json +161 -0
- package/test/fixtures/stripe/subscription-canceled.json +161 -0
- package/test/fixtures/stripe/subscription-trialing.json +161 -0
- package/test/helpers/_shared-config.js +15 -0
- package/test/helpers/ai-request-payload.test.js +619 -0
- package/test/helpers/ai-schema-resolve.test.js +125 -0
- package/test/helpers/ai-test-provider.test.js +227 -0
- package/test/helpers/ai-token-accounting.test.js +150 -0
- package/test/helpers/ai-tools-format.test.js +384 -0
- package/test/helpers/analytics-no-id-notice.test.js +146 -0
- package/test/helpers/analytics-user-data.test.js +194 -0
- package/test/helpers/api-manager.test.js +311 -0
- package/test/helpers/backend-router.test.js +136 -0
- package/test/helpers/content/blog-auto-publisher.test.js +482 -0
- package/test/helpers/content/feed-parser.test.js +529 -0
- package/test/helpers/content/ghostii-blocks.test.js +135 -0
- package/test/helpers/content/ghostii-feed-integration.test.js +405 -0
- package/test/helpers/content/ghostii-write-article.test.js +244 -0
- package/test/helpers/dev-only-routes.test.js +225 -0
- package/test/helpers/env-reader.test.js +362 -0
- package/test/helpers/environment.test.js +263 -0
- package/test/helpers/event-middleware.test.js +407 -0
- package/test/helpers/infer-contact.test.js +157 -0
- package/test/helpers/lane-url.test.js +90 -0
- package/test/helpers/merge-line-files.test.js +272 -0
- package/test/helpers/metadata.test.js +122 -0
- package/test/helpers/middleware-request-log.test.js +134 -0
- package/test/helpers/middleware-user-log.test.js +124 -0
- package/test/helpers/payment/chargebee/parse-webhook.test.js +490 -0
- package/test/helpers/payment/chargebee/refund-details.test.js +198 -0
- package/test/helpers/payment/chargebee/to-unified-one-time.test.js +148 -0
- package/test/helpers/payment/chargebee/to-unified-subscription.test.js +649 -0
- package/test/helpers/payment/coinbase/create-intent.test.js +247 -0
- package/test/helpers/payment/coinbase/parse-webhook.test.js +195 -0
- package/test/helpers/payment/coinbase/refund-unsupported.test.js +141 -0
- package/test/helpers/payment/coinbase/to-unified-one-time.test.js +201 -0
- package/test/helpers/payment/discount-codes.test.js +141 -0
- package/test/helpers/payment/extract-resource.test.js +113 -0
- package/test/helpers/payment/fetch-failure.test.js +215 -0
- package/test/helpers/payment/license-gate.test.js +108 -0
- package/test/helpers/payment/order-id.test.js +99 -0
- package/test/helpers/payment/paypal/create-intent.test.js +382 -0
- package/test/helpers/payment/paypal/fetch-capture.test.js +123 -0
- package/test/helpers/payment/paypal/fetch-sale.test.js +183 -0
- package/test/helpers/payment/paypal/parse-webhook.test.js +678 -0
- package/test/helpers/payment/paypal/refund-details.test.js +202 -0
- package/test/helpers/payment/paypal/resolve-plan-id.test.js +108 -0
- package/test/helpers/payment/paypal/switch-plan.test.js +92 -0
- package/test/helpers/payment/paypal/to-unified-one-time.test.js +383 -0
- package/test/helpers/payment/paypal/to-unified-subscription.test.js +884 -0
- package/test/helpers/payment/stripe/fetch-charge.test.js +147 -0
- package/test/helpers/payment/stripe/parse-webhook.test.js +448 -0
- package/test/helpers/payment/stripe/refund-details.test.js +147 -0
- package/test/helpers/payment/stripe/to-unified-one-time.test.js +307 -0
- package/test/helpers/payment/stripe/to-unified-subscription.test.js +709 -0
- package/test/helpers/persona-domain.test.js +87 -0
- package/test/helpers/recaptcha.test.js +166 -0
- package/test/helpers/resolved-config.test.js +106 -0
- package/test/helpers/response-log-redaction.test.js +262 -0
- package/test/helpers/roles.test.js +155 -0
- package/test/helpers/route-context-debug-gate.test.js +118 -0
- package/test/helpers/route-context-logging.test.js +214 -0
- package/test/helpers/route-context.test.js +129 -0
- package/test/helpers/safe-compare.test.js +114 -0
- package/test/helpers/sanitize.test.js +223 -0
- package/test/helpers/schema-engine.test.js +537 -0
- package/test/helpers/schema-zod.test.js +554 -0
- package/test/helpers/seed-accounts-load.test.js +163 -0
- package/test/helpers/seed-google-personas.test.js +114 -0
- package/test/helpers/seeded-personas.test.js +823 -0
- package/test/helpers/settings.test.js +292 -0
- package/test/helpers/setup-engines-pin.test.js +68 -0
- package/test/helpers/setup-manifest-sync.test.js +116 -0
- package/test/helpers/slugify.test.js +395 -0
- package/test/helpers/storage.test.js +195 -0
- package/test/helpers/test-banner-latch.test.js +139 -0
- package/test/helpers/usage-consume.test.js +460 -0
- package/test/helpers/usage-log-privacy.test.js +121 -0
- package/test/helpers/user-doc-heal.test.js +540 -0
- package/test/helpers/user.test.js +771 -0
- package/test/helpers/webhook-forward.test.js +419 -0
- package/test/helpers/wipe-auth-project.test.js +143 -0
- package/test/mcp/discovery.test.js +52 -0
- package/test/mcp/oauth.test.js +160 -0
- package/test/mcp/protocol.test.js +278 -0
- package/test/mcp/roles.test.js +203 -0
- package/test/mcp/utils.test.js +245 -0
- package/test/notification/identity.test.js +155 -0
- package/test/routes/admin/create-post.test.js +362 -0
- package/test/routes/admin/database.test.js +133 -0
- package/test/routes/admin/deduplicate-image-alts.test.js +191 -0
- package/test/routes/admin/email-content-html.test.js +58 -0
- package/test/routes/admin/email-request-log.test.js +86 -0
- package/test/routes/admin/email.test.js +116 -0
- package/test/routes/admin/firestore-query.test.js +206 -0
- package/test/routes/admin/firestore.test.js +129 -0
- package/test/routes/admin/infer-contact.test.js +220 -0
- package/test/routes/admin/notification.test.js +199 -0
- package/test/routes/admin/post-convert-image.test.js +159 -0
- package/test/routes/admin/post-deploy-flag.test.js +81 -0
- package/test/routes/admin/post-download-error.test.js +90 -0
- package/test/routes/admin/post-resize-image.test.js +185 -0
- package/test/routes/admin/post.test.js +369 -0
- package/test/routes/admin/repo-content.test.js +223 -0
- package/test/routes/admin/stats.test.js +114 -0
- package/test/routes/admin/users-disable.test.js +63 -0
- package/test/routes/admin/users-list.test.js +71 -0
- package/test/routes/content/post.test.js +60 -0
- package/test/routes/general/uuid.test.js +133 -0
- package/test/routes/health.test.js +110 -0
- package/test/routes/marketing/campaign.test.js +184 -0
- package/test/routes/marketing/contact.test.js +416 -0
- package/test/routes/marketing/email-preferences.test.js +293 -0
- package/test/routes/marketing/push-send.test.js +34 -0
- package/test/routes/marketing/webhook-forward.test.js +63 -0
- package/test/routes/marketing/webhook.test.js +641 -0
- package/test/routes/payments/_route-harness.js +145 -0
- package/test/routes/payments/cancel-provider-errors.test.js +227 -0
- package/test/routes/payments/cancel-skip-guards.test.js +126 -0
- package/test/routes/payments/cancel-trialing.test.js +428 -0
- package/test/routes/payments/cancel.test.js +165 -0
- package/test/routes/payments/dedup-race.test.js +186 -0
- package/test/routes/payments/discount.test.js +82 -0
- package/test/routes/payments/dispute-alert.test.js +324 -0
- package/test/routes/payments/intent-discount-amounts.test.js +550 -0
- package/test/routes/payments/intent-discount-coupons.test.js +293 -0
- package/test/routes/payments/intent-one-time-metadata.test.js +122 -0
- package/test/routes/payments/intent-purchaser-guard.test.js +139 -0
- package/test/routes/payments/intent-zero-total.test.js +260 -0
- package/test/routes/payments/intent.test.js +413 -0
- package/test/routes/payments/plan.test.js +367 -0
- package/test/routes/payments/portal-return-url.test.js +107 -0
- package/test/routes/payments/portal.test.js +94 -0
- package/test/routes/payments/refund-one-time.test.js +254 -0
- package/test/routes/payments/refund-paypal-proration.test.js +190 -0
- package/test/routes/payments/refund.test.js +181 -0
- package/test/routes/payments/trial-eligibility.test.js +73 -0
- package/test/routes/payments/uncancel.test.js +270 -0
- package/test/routes/payments/webhook-stripe-invoice.test.js +129 -0
- package/test/routes/payments/webhook-stripe-refund-one-time.test.js +130 -0
- package/test/routes/payments/webhook-test-provider.test.js +156 -0
- package/test/routes/payments/webhook.test.js +115 -0
- package/test/routes/payments/winback-stripe-coupon.test.js +126 -0
- package/test/routes/payments/winback.test.js +597 -0
- package/test/routes/test/authenticate.test.js +79 -0
- package/test/routes/test/redirect.test.js +66 -0
- package/test/routes/test/reset-account.test.js +126 -0
- package/test/routes/test/roster.test.js +101 -0
- package/test/routes/test/schema.test.js +556 -0
- package/test/routes/test/usage.test.js +374 -0
- package/test/routes/user/api-keys.test.js +158 -0
- package/test/routes/user/connections-grant.test.js +759 -0
- package/test/routes/user/connections-identity.test.js +260 -0
- package/test/routes/user/connections-log-privacy.test.js +206 -0
- package/test/routes/user/connections-refresh-lease.test.js +696 -0
- package/test/routes/user/connections-return.test.js +261 -0
- package/test/routes/user/connections-uid.test.js +516 -0
- package/test/routes/user/delete.test.js +138 -0
- package/test/routes/user/feedback.test.js +106 -0
- package/test/routes/user/orders.test.js +233 -0
- package/test/routes/user/sessions.test.js +231 -0
- package/test/routes/user/settings-validate.test.js +84 -0
- package/test/routes/user/signup-emails.test.js +113 -0
- package/test/routes/user/signup-location.test.js +84 -0
- package/test/routes/user/signup-log-privacy.test.js +112 -0
- package/test/routes/user/signup.test.js +579 -0
- package/test/routes/user/subscription.test.js +101 -0
- package/test/routes/user/token.test.js +111 -0
- package/test/routes/user/user.test.js +158 -0
- package/test/routes/verts/cache.test.js +78 -0
- package/test/routes/verts/click-destination.test.js +76 -0
- package/test/routes/verts/crud.test.js +194 -0
- package/test/routes/verts/redirect.test.js +147 -0
- package/test/routes/verts/selection.test.js +237 -0
- package/test/routes/verts/serve.test.js +185 -0
- package/test/routes/verts/unit-document.test.js +117 -0
- package/test/rules/_environment.js +66 -0
- package/test/rules/brand-merge.test.js +195 -0
- package/test/rules/field-helpers.test.js +309 -0
- package/test/rules/notifications.test.js +577 -0
- package/test/rules/payments-carts.test.js +406 -0
- package/test/rules/sessions.test.js +170 -0
- package/test/rules/user.test.js +517 -0
- package/test/rules/verts.test.js +101 -0
- package/test/security/fetch-log-secrets.test.js +124 -0
- package/test/security/primitives.test.js +105 -0
- package/test/security/repo-pinning.test.js +77 -0
- package/test/stripe-live/subscription-lifecycle.test.js +141 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: POST /payments/cancel — a TRIAL cancel ends access immediately
|
|
3
|
+
* ([#267](https://github.com/Omega-JS-Stack/omega/issues/267)).
|
|
4
|
+
*
|
|
5
|
+
* Ian's ruling (2026-08-15): we do not keep serving a trial we know will not
|
|
6
|
+
* convert. Two things follow, and this file proves both:
|
|
7
|
+
*
|
|
8
|
+
* - the 24-hour young-subscription guard does not apply to a trial. That guard
|
|
9
|
+
* exists to stop a cancellation racing a PAID checkout that is still
|
|
10
|
+
* settling; a trial has no payment to settle, and cancelling the same day you
|
|
11
|
+
* started is the most common trial behavior there is. It used to answer
|
|
12
|
+
* "your subscription is still being set up" — the journey suite only got past
|
|
13
|
+
* it by sending `skipGuards`, which is a privileged request, not something a
|
|
14
|
+
* real trialer can send.
|
|
15
|
+
* - `_is-trialing.js` is the ONE definition of "still inside the trial", shared
|
|
16
|
+
* by the route and all four cancel providers. It was three copies before,
|
|
17
|
+
* which is how the route came to disagree with the providers it calls.
|
|
18
|
+
*
|
|
19
|
+
* Three layers, each proving what it can:
|
|
20
|
+
* - the classifier as a pure function (zero I/O — the framework's one exception
|
|
21
|
+
* to running everything for real), over the subscription shapes the pipeline
|
|
22
|
+
* actually writes;
|
|
23
|
+
* - the route against the real emulator: a trialing subscription minutes old
|
|
24
|
+
* gets PAST the guard, and a paid one exactly as young still does not;
|
|
25
|
+
* - every cancel PROVIDER, one case per provider: the branch has to reach the
|
|
26
|
+
* provider's own immediate-cancel verb, not merely log that it meant to. The
|
|
27
|
+
* provider SDK/HTTP seam is the one thing stood in for (creating and
|
|
28
|
+
* cancelling a live subscription needs a real account), exactly as
|
|
29
|
+
* intent-discount-coupons.test.js does it; the test provider writes to the
|
|
30
|
+
* real emulator instead, since its "provider" IS Firestore.
|
|
31
|
+
*
|
|
32
|
+
* The route cases carry a deliberately unknown provider, so getting past the
|
|
33
|
+
* guard lands on "Unknown provider" and nothing external is ever reached — the
|
|
34
|
+
* technique cancel-skip-guards.test.js established. Both verdicts are a 400 with
|
|
35
|
+
* DIFFERENT text, which is what separates "the guard ran" from "the guard did
|
|
36
|
+
* not".
|
|
37
|
+
*
|
|
38
|
+
* PayPal has no immediate-cancel verb to reach — one endpoint cancels, and the
|
|
39
|
+
* immediacy is enforced in the unified transform instead (a subscription inside
|
|
40
|
+
* its trial window gets no remaining period). The transform half is pinned in
|
|
41
|
+
* helpers/payment/paypal/to-unified-subscription.test.js; what belongs here is
|
|
42
|
+
* that the provider calls the cancel endpoint and says which cancel it was.
|
|
43
|
+
*
|
|
44
|
+
* Run: npx omega test backend:routes/payments/cancel-trialing
|
|
45
|
+
*/
|
|
46
|
+
const { buildUser, callHandler, withEnvironment, PRODUCTION_ENVIRONMENT } = require('./_route-harness.js');
|
|
47
|
+
|
|
48
|
+
const handler = require('../../../dist/manager/routes/payments/cancel/post.js');
|
|
49
|
+
const isTrialing = require('../../../dist/manager/routes/payments/cancel/_is-trialing.js');
|
|
50
|
+
|
|
51
|
+
const StripeLib = require('../../../dist/manager/libraries/payment/providers/stripe.js');
|
|
52
|
+
const ChargebeeLib = require('../../../dist/manager/libraries/payment/providers/chargebee.js');
|
|
53
|
+
const PayPalLib = require('../../../dist/manager/libraries/payment/providers/paypal.js');
|
|
54
|
+
|
|
55
|
+
const stripeCancel = require('../../../dist/manager/routes/payments/cancel/providers/stripe.js');
|
|
56
|
+
const chargebeeCancel = require('../../../dist/manager/routes/payments/cancel/providers/chargebee.js');
|
|
57
|
+
const paypalCancel = require('../../../dist/manager/routes/payments/cancel/providers/paypal.js');
|
|
58
|
+
const testCancel = require('../../../dist/manager/routes/payments/cancel/providers/test.js');
|
|
59
|
+
const defineCases = require('../../../dist/vendor/devkit/test/define-cases.js');
|
|
60
|
+
|
|
61
|
+
const DAY = 24 * 60 * 60;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A subscriber whose subscription started minutes ago — the age the guard
|
|
65
|
+
* exists for. A trialing one expires exactly when its trial does; a paid one
|
|
66
|
+
* carries no trial at all.
|
|
67
|
+
*/
|
|
68
|
+
function youngSubscriber(Manager, { uid, trialing }) {
|
|
69
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
70
|
+
const trialEndUNIX = nowUNIX + (14 * DAY);
|
|
71
|
+
const stamp = (unix) => ({ timestamp: new Date(unix * 1000).toISOString(), timestampUNIX: unix });
|
|
72
|
+
|
|
73
|
+
return buildUser(Manager, {
|
|
74
|
+
auth: { uid: uid, email: `${uid}@example.com` },
|
|
75
|
+
roles: {},
|
|
76
|
+
subscription: {
|
|
77
|
+
product: { id: 'premium', name: 'Premium' },
|
|
78
|
+
status: 'active',
|
|
79
|
+
cancellation: { pending: false },
|
|
80
|
+
// A live trial expires WITH its trial; a paid subscription runs to the end
|
|
81
|
+
// of the period it paid for.
|
|
82
|
+
expires: stamp(trialing ? trialEndUNIX : nowUNIX + (30 * DAY)),
|
|
83
|
+
trial: trialing
|
|
84
|
+
? { claimed: true, expires: stamp(trialEndUNIX) }
|
|
85
|
+
: { claimed: false },
|
|
86
|
+
payment: {
|
|
87
|
+
// Deliberately unknown: getting PAST the age guard must not reach a real provider
|
|
88
|
+
provider: 'unknown-provider',
|
|
89
|
+
resourceId: 'sub_test_trial_cancel',
|
|
90
|
+
startDate: stamp(nowUNIX),
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Cancel the way a real customer does — no privileged `skipGuards` anywhere.
|
|
97
|
+
function cancel(Manager, user) {
|
|
98
|
+
return callHandler({
|
|
99
|
+
Manager,
|
|
100
|
+
handler,
|
|
101
|
+
functionName: 'payments-cancel',
|
|
102
|
+
user,
|
|
103
|
+
settings: { confirmed: true, skipGuards: false, reason: 'Not for me', feedback: null },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The guards have to be driven in a PRODUCTION environment: in a testing run
|
|
108
|
+
// every caller may bypass them by design, so a testing-run assertion would
|
|
109
|
+
// prove nothing (the reasoning cancel-skip-guards.test.js sets out in full).
|
|
110
|
+
function cancelInProduction(Manager, user) {
|
|
111
|
+
return withEnvironment(PRODUCTION_ENVIRONMENT, () => cancel(Manager, user));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// The subscription shapes the pipeline writes, as the classifier sees them.
|
|
115
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
116
|
+
const at = (unix) => ({ timestamp: new Date(unix * 1000).toISOString(), timestampUNIX: unix });
|
|
117
|
+
|
|
118
|
+
// ─── the providers ──────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The subscription each provider is handed, in the two states that decide its
|
|
122
|
+
* branch. A live trial expires WITH its trial; a paid one runs to its period end.
|
|
123
|
+
*/
|
|
124
|
+
function subscriptionInState(trialing) {
|
|
125
|
+
const trialEndUNIX = nowUNIX + (7 * DAY);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
product: { id: 'premium', name: 'Premium' },
|
|
129
|
+
status: 'active',
|
|
130
|
+
cancellation: { pending: false },
|
|
131
|
+
expires: at(trialing ? trialEndUNIX : nowUNIX + (30 * DAY)),
|
|
132
|
+
trial: trialing
|
|
133
|
+
? { claimed: true, expires: at(trialEndUNIX) }
|
|
134
|
+
: { claimed: false },
|
|
135
|
+
payment: { resourceId: 'sub_test_immediacy', startDate: at(nowUNIX - (60 * DAY)) },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// A ctx that records the log line, which is how each provider names the cancel
|
|
140
|
+
// it performed. Everything else the providers touch is the REAL ctx — the
|
|
141
|
+
// recorder delegates to it (rather than copying it, which would drop every
|
|
142
|
+
// method the providers call, `isProduction()` and `Manager` among them).
|
|
143
|
+
function recordingCtx(ctx) {
|
|
144
|
+
const logs = [];
|
|
145
|
+
const recorder = Object.create(ctx);
|
|
146
|
+
|
|
147
|
+
recorder.log = (message) => logs.push(message);
|
|
148
|
+
|
|
149
|
+
return { ctx: recorder, logs };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Run fn with a library method replaced by a stand-in, restored afterwards. */
|
|
153
|
+
async function withStub(library, method, replacement, fn) {
|
|
154
|
+
const real = library[method];
|
|
155
|
+
|
|
156
|
+
library[method] = replacement;
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
return await fn();
|
|
160
|
+
} finally {
|
|
161
|
+
library[method] = real;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Cancel through a provider, in the trialing or the paid state. */
|
|
166
|
+
async function cancelVia(provider, { trialing, ctx }) {
|
|
167
|
+
const recorder = recordingCtx(ctx);
|
|
168
|
+
|
|
169
|
+
await provider.cancelAtPeriodEnd({
|
|
170
|
+
resourceId: 'sub_test_immediacy',
|
|
171
|
+
uid: '_test-cancel-immediacy',
|
|
172
|
+
subscription: subscriptionInState(trialing),
|
|
173
|
+
ctx: recorder.ctx,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return recorder.logs;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
module.exports = defineCases({
|
|
180
|
+
description: 'Payment cancel endpoint: a trial cancels immediately',
|
|
181
|
+
type: 'group',
|
|
182
|
+
timeout: 15000,
|
|
183
|
+
|
|
184
|
+
tests: [
|
|
185
|
+
// ─── the route ───
|
|
186
|
+
|
|
187
|
+
{
|
|
188
|
+
name: 'a-trial-cancel-is-not-blocked-by-the-24-hour-guard',
|
|
189
|
+
auth: 'none',
|
|
190
|
+
async run({ assert, Manager }) {
|
|
191
|
+
const user = youngSubscriber(Manager, { uid: '_test-cancel-trialing-young', trialing: true });
|
|
192
|
+
|
|
193
|
+
const sent = await cancelInProduction(Manager, user);
|
|
194
|
+
|
|
195
|
+
assert.equal(sent.code, 400, `Expected the request to reach the provider lookup, got ${sent.code}: ${sent.body}`);
|
|
196
|
+
assert.ok(
|
|
197
|
+
!/still being set up/i.test(`${sent.body}`),
|
|
198
|
+
`A trial must never be told it is still being set up, got: ${sent.body}`,
|
|
199
|
+
);
|
|
200
|
+
assert.match(`${sent.body}`, /Unknown provider/i, 'The trial cancel should get PAST the age guard');
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
name: 'a-paid-cancel-that-young-is-still-guarded',
|
|
206
|
+
auth: 'none',
|
|
207
|
+
async run({ assert, Manager }) {
|
|
208
|
+
// The other half of the ruling: paid cancels keep today's behavior
|
|
209
|
+
// exactly. Same age, same everything — only the trial differs.
|
|
210
|
+
const user = youngSubscriber(Manager, { uid: '_test-cancel-paid-young', trialing: false });
|
|
211
|
+
|
|
212
|
+
const sent = await cancelInProduction(Manager, user);
|
|
213
|
+
|
|
214
|
+
assert.equal(sent.code, 400, `A young PAID subscription must still be guarded, got ${sent.code}: ${sent.body}`);
|
|
215
|
+
assert.match(`${sent.body}`, /still being set up/i, 'The age guard should be the rejection for a paid subscription');
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// ─── the classifier ───
|
|
220
|
+
|
|
221
|
+
{
|
|
222
|
+
name: 'classifies-a-live-trial-as-trialing',
|
|
223
|
+
auth: 'none',
|
|
224
|
+
async run({ assert }) {
|
|
225
|
+
const trialEnd = nowUNIX + (14 * DAY);
|
|
226
|
+
|
|
227
|
+
assert.equal(isTrialing({
|
|
228
|
+
status: 'active',
|
|
229
|
+
trial: { claimed: true, expires: at(trialEnd) },
|
|
230
|
+
expires: at(trialEnd),
|
|
231
|
+
}), true, 'A live trial expires exactly when its trial does');
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
{
|
|
236
|
+
name: 'classifies-a-converted-trial-as-paid',
|
|
237
|
+
auth: 'none',
|
|
238
|
+
async run({ assert }) {
|
|
239
|
+
// Conversion moves `expires` out to the end of the first paid period
|
|
240
|
+
// while `trial.expires` stays put — that gap IS the conversion.
|
|
241
|
+
assert.equal(isTrialing({
|
|
242
|
+
status: 'active',
|
|
243
|
+
trial: { claimed: true, expires: at(nowUNIX - DAY) },
|
|
244
|
+
expires: at(nowUNIX + (30 * DAY)),
|
|
245
|
+
}), false, 'A converted trial is a paid subscription and cancels at period end');
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
{
|
|
250
|
+
name: 'classifies-a-subscription-that-never-trialed-as-paid',
|
|
251
|
+
auth: 'none',
|
|
252
|
+
async run({ assert }) {
|
|
253
|
+
assert.equal(isTrialing({
|
|
254
|
+
status: 'active',
|
|
255
|
+
trial: { claimed: false },
|
|
256
|
+
expires: at(nowUNIX + (30 * DAY)),
|
|
257
|
+
}), false, 'No trial claimed, no immediate cancel');
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
{
|
|
262
|
+
name: 'classifies-a-suspended-trial-as-not-trialing',
|
|
263
|
+
auth: 'none',
|
|
264
|
+
async run({ assert }) {
|
|
265
|
+
// A suspended subscription is already out of the live path; the route
|
|
266
|
+
// handles it through the force-cancel branch instead.
|
|
267
|
+
const trialEnd = nowUNIX + (14 * DAY);
|
|
268
|
+
|
|
269
|
+
assert.equal(isTrialing({
|
|
270
|
+
status: 'suspended',
|
|
271
|
+
trial: { claimed: true, expires: at(trialEnd) },
|
|
272
|
+
expires: at(trialEnd),
|
|
273
|
+
}), false, 'Only a live subscription can be in its trial');
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
{
|
|
278
|
+
name: 'classifies-an-expired-but-unswept-trial-as-trialing',
|
|
279
|
+
auth: 'none',
|
|
280
|
+
async run({ assert }) {
|
|
281
|
+
// The lapse sweep has not run yet. Nothing was ever paid, so there is
|
|
282
|
+
// no period to let ride — this still cancels now.
|
|
283
|
+
const trialEnd = nowUNIX - DAY;
|
|
284
|
+
|
|
285
|
+
assert.equal(isTrialing({
|
|
286
|
+
status: 'active',
|
|
287
|
+
trial: { claimed: true, expires: at(trialEnd) },
|
|
288
|
+
expires: at(trialEnd),
|
|
289
|
+
}), true, 'An unswept expired trial has no paid period to serve out');
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
{
|
|
294
|
+
name: 'a-missing-expiry-never-reads-as-trialing',
|
|
295
|
+
auth: 'none',
|
|
296
|
+
async run({ assert }) {
|
|
297
|
+
// The three copies this was folded out of compared the two timestamps
|
|
298
|
+
// directly, so a subscription carrying NEITHER matched itself on
|
|
299
|
+
// `undefined`. That answer now waives a guard, and a guard must never
|
|
300
|
+
// be waived by absent data.
|
|
301
|
+
assert.equal(isTrialing({
|
|
302
|
+
status: 'active',
|
|
303
|
+
trial: { claimed: true },
|
|
304
|
+
}), false, 'No expiry on either side is not a trial');
|
|
305
|
+
|
|
306
|
+
assert.equal(isTrialing({}), false, 'An empty subscription is not a trial');
|
|
307
|
+
assert.equal(isTrialing(null), false, 'No subscription at all is not a trial');
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
// ─── the providers ───
|
|
312
|
+
|
|
313
|
+
{
|
|
314
|
+
name: 'stripe-cancels-a-trial-now-and-a-paid-subscription-at-period-end',
|
|
315
|
+
auth: 'none',
|
|
316
|
+
async run({ assert, ctx }) {
|
|
317
|
+
const calls = [];
|
|
318
|
+
const sdk = {
|
|
319
|
+
subscriptions: {
|
|
320
|
+
cancel: async (id) => { calls.push({ verb: 'cancel', id }); return {}; },
|
|
321
|
+
update: async (id, params) => { calls.push({ verb: 'update', id, params }); return {}; },
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const trialLogs = await withStub(StripeLib, 'init', () => sdk, () => cancelVia(stripeCancel, { trialing: true, ctx }));
|
|
326
|
+
|
|
327
|
+
assert.deepEqual(
|
|
328
|
+
calls,
|
|
329
|
+
[{ verb: 'cancel', id: 'sub_test_immediacy' }],
|
|
330
|
+
'A trial must reach subscriptions.cancel — cancel_at_period_end would serve the trial out',
|
|
331
|
+
);
|
|
332
|
+
assert.match(trialLogs.join('\n'), /immediate \(trialing\)/, 'and the log names the cancel it performed');
|
|
333
|
+
|
|
334
|
+
calls.length = 0;
|
|
335
|
+
const paidLogs = await withStub(StripeLib, 'init', () => sdk, () => cancelVia(stripeCancel, { trialing: false, ctx }));
|
|
336
|
+
|
|
337
|
+
assert.equal(calls.length, 1, 'A paid cancel is one call too');
|
|
338
|
+
assert.equal(calls[0].verb, 'update', 'A paid subscription is scheduled, never cancelled outright');
|
|
339
|
+
assert.deepEqual(calls[0].params, { cancel_at_period_end: true }, 'with the period-end flag');
|
|
340
|
+
assert.match(paidLogs.join('\n'), /at period end/, 'and the log says so');
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
{
|
|
345
|
+
name: 'chargebee-cancels-a-trial-immediately-and-a-paid-subscription-at-end-of-term',
|
|
346
|
+
auth: 'none',
|
|
347
|
+
async run({ assert, ctx }) {
|
|
348
|
+
const calls = [];
|
|
349
|
+
const request = async (path, options) => { calls.push({ path, options }); return {}; };
|
|
350
|
+
|
|
351
|
+
const trialLogs = await withStub(ChargebeeLib, 'init', () => ({}), () => (
|
|
352
|
+
withStub(ChargebeeLib, 'request', request, () => cancelVia(chargebeeCancel, { trialing: true, ctx }))
|
|
353
|
+
));
|
|
354
|
+
|
|
355
|
+
assert.equal(calls.length, 1, 'One cancel call');
|
|
356
|
+
assert.equal(calls[0].path, '/subscriptions/sub_test_immediacy/cancel_for_items', 'Chargebee\'s cancel endpoint');
|
|
357
|
+
assert.equal(calls[0].options.body.cancel_option, 'immediately', 'A trial takes the immediate path');
|
|
358
|
+
assert.match(trialLogs.join('\n'), /immediate \(trialing\)/, 'and the log names it');
|
|
359
|
+
|
|
360
|
+
calls.length = 0;
|
|
361
|
+
const paidLogs = await withStub(ChargebeeLib, 'init', () => ({}), () => (
|
|
362
|
+
withStub(ChargebeeLib, 'request', request, () => cancelVia(chargebeeCancel, { trialing: false, ctx }))
|
|
363
|
+
));
|
|
364
|
+
|
|
365
|
+
assert.equal(calls[0].options.body.cancel_option, 'end_of_term', 'A paid subscription runs to the end of its term');
|
|
366
|
+
assert.match(paidLogs.join('\n'), /at period end/, 'and the log says so');
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
|
|
370
|
+
{
|
|
371
|
+
name: 'paypal-cancels-through-the-one-endpoint-and-names-the-trial',
|
|
372
|
+
auth: 'none',
|
|
373
|
+
async run({ assert, ctx }) {
|
|
374
|
+
// PayPal exposes no second cancel mode, so the CALL is the same one in
|
|
375
|
+
// both states — what differs is the reason it carries and the log it
|
|
376
|
+
// writes. The immediacy itself lives in the unified transform, pinned in
|
|
377
|
+
// helpers/payment/paypal/to-unified-subscription.test.js.
|
|
378
|
+
const calls = [];
|
|
379
|
+
const request = async (path, options) => { calls.push({ path, body: JSON.parse(options.body) }); return {}; };
|
|
380
|
+
|
|
381
|
+
const trialLogs = await withStub(PayPalLib, 'request', request, () => cancelVia(paypalCancel, { trialing: true, ctx }));
|
|
382
|
+
|
|
383
|
+
assert.equal(calls.length, 1, 'One cancel call');
|
|
384
|
+
assert.equal(calls[0].path, '/v1/billing/subscriptions/sub_test_immediacy/cancel', 'PayPal\'s cancel endpoint');
|
|
385
|
+
assert.match(calls[0].body.reason, /free trial/i, 'The reason PayPal records says this was a trial cancel');
|
|
386
|
+
assert.match(trialLogs.join('\n'), /immediate \(trialing\)/, 'and our log names it');
|
|
387
|
+
|
|
388
|
+
calls.length = 0;
|
|
389
|
+
const paidLogs = await withStub(PayPalLib, 'request', request, () => cancelVia(paypalCancel, { trialing: false, ctx }));
|
|
390
|
+
|
|
391
|
+
assert.equal(calls[0].path, '/v1/billing/subscriptions/sub_test_immediacy/cancel', 'The same endpoint — PayPal has only the one');
|
|
392
|
+
assert.match(calls[0].body.reason, /requested cancellation/i, 'with the ordinary reason');
|
|
393
|
+
assert.match(paidLogs.join('\n'), /at period end/, 'and the log says which cancel this was');
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
|
|
397
|
+
{
|
|
398
|
+
name: 'the-test-provider-fabricates-the-immediate-cancel-event',
|
|
399
|
+
auth: 'none',
|
|
400
|
+
async run({ assert, ctx, firestore }) {
|
|
401
|
+
// The test provider's "provider" is Firestore, so this one runs for
|
|
402
|
+
// real: the webhook doc it writes IS the cancel, and the pipeline folds
|
|
403
|
+
// it exactly as a Stripe delivery.
|
|
404
|
+
const trialLogs = await cancelVia(testCancel, { trialing: true, ctx });
|
|
405
|
+
const trialEventId = trialLogs.join('\n').match(/payments-webhooks\/([\w-]+)/)?.[1];
|
|
406
|
+
|
|
407
|
+
assert.ok(trialEventId, `The provider should name the event it wrote, got: ${trialLogs.join('\n')}`);
|
|
408
|
+
|
|
409
|
+
const trialEvent = await firestore.get(`payments-webhooks/${trialEventId}`);
|
|
410
|
+
const trialSubscription = trialEvent.raw.data.object;
|
|
411
|
+
|
|
412
|
+
assert.equal(trialEvent.raw.type, 'customer.subscription.deleted', 'A trial cancel is the DELETED event — the subscription ends now');
|
|
413
|
+
assert.equal(trialSubscription.status, 'canceled', 'with the subscription already cancelled');
|
|
414
|
+
assert.equal(trialSubscription.cancel_at_period_end, false, 'and nothing scheduled for later');
|
|
415
|
+
assert.ok(trialSubscription.current_period_end <= Math.floor(Date.now() / 1000), 'the period ends now, not in a month');
|
|
416
|
+
|
|
417
|
+
const paidLogs = await cancelVia(testCancel, { trialing: false, ctx });
|
|
418
|
+
const paidEventId = paidLogs.join('\n').match(/payments-webhooks\/([\w-]+)/)?.[1];
|
|
419
|
+
const paidEvent = await firestore.get(`payments-webhooks/${paidEventId}`);
|
|
420
|
+
const paidSubscription = paidEvent.raw.data.object;
|
|
421
|
+
|
|
422
|
+
assert.equal(paidEvent.raw.type, 'customer.subscription.updated', 'A paid cancel is the UPDATED event');
|
|
423
|
+
assert.equal(paidSubscription.status, 'active', 'the subscription is still live');
|
|
424
|
+
assert.equal(paidSubscription.cancel_at_period_end, true, 'with the cancellation scheduled at its period end');
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
});
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: POST /payments/cancel - Validation errors
|
|
3
|
+
* Tests rejection cases before any provider call is made.
|
|
4
|
+
* See test/events/payments/journey-payments-cancel-endpoint.js for the full end-to-end journey.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const defineCases = require('../../../dist/vendor/devkit/test/define-cases.js');
|
|
8
|
+
module.exports = defineCases({
|
|
9
|
+
description: 'Payment cancel endpoint: validation errors',
|
|
10
|
+
type: 'group',
|
|
11
|
+
timeout: 15000,
|
|
12
|
+
|
|
13
|
+
tests: [
|
|
14
|
+
{
|
|
15
|
+
name: 'rejects-unauthenticated',
|
|
16
|
+
async run({ http, assert }) {
|
|
17
|
+
const response = await http.as('none').post('backend-manager/payments/cancel', {
|
|
18
|
+
confirmed: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
assert.isError(response, 401, 'Should reject unauthenticated request');
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
name: 'rejects-missing-confirmed',
|
|
27
|
+
async run({ http, assert }) {
|
|
28
|
+
const response = await http.as('basic').post('backend-manager/payments/cancel', {
|
|
29
|
+
reason: 'Too expensive',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
assert.isError(response, 400, 'Should reject missing confirmed field');
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
{
|
|
37
|
+
name: 'rejects-basic-user',
|
|
38
|
+
async run({ http, assert }) {
|
|
39
|
+
const response = await http.as('basic').post('backend-manager/payments/cancel', {
|
|
40
|
+
confirmed: true,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
assert.isError(response, 400, 'Should reject basic user with no paid subscription');
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
name: 'rejects-no-provider-or-resource-id',
|
|
49
|
+
async run({ http, assert }) {
|
|
50
|
+
// cancel-no-provider starts with payment.provider=null
|
|
51
|
+
const response = await http.as('cancel-no-provider').post('backend-manager/payments/cancel', {
|
|
52
|
+
confirmed: true,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
assert.isError(response, 400, 'Should reject when no provider or resourceId is set');
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
name: 'rejects-already-pending-cancellation',
|
|
61
|
+
async run({ http, assert }) {
|
|
62
|
+
// cancel-already-pending starts with cancellation.pending=true
|
|
63
|
+
const response = await http.as('cancel-already-pending').post('backend-manager/payments/cancel', {
|
|
64
|
+
confirmed: true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
assert.isError(response, 400, 'Should reject when cancellation already pending');
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
name: 'rejects-subscription-younger-than-24-hours',
|
|
73
|
+
async run({ http, assert }) {
|
|
74
|
+
// cancel-too-young starts with startDate set to now (< 24 hours old)
|
|
75
|
+
const response = await http.as('cancel-too-young').post('backend-manager/payments/cancel', {
|
|
76
|
+
confirmed: true,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
assert.isError(response, 400, 'Should reject subscription younger than 24 hours');
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
{
|
|
84
|
+
name: 'rejects-unknown-provider',
|
|
85
|
+
async run({ http, assert }) {
|
|
86
|
+
// cancel-unknown-provider starts with provider='unknown-provider'
|
|
87
|
+
const response = await http.as('cancel-unknown-provider').post('backend-manager/payments/cancel', {
|
|
88
|
+
confirmed: true,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
assert.isError(response, 400, 'Should reject unknown provider');
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
{
|
|
96
|
+
name: 'allows-suspended-subscription',
|
|
97
|
+
async run({ http, assert, config, accounts, firestore, waitFor, skip }) {
|
|
98
|
+
const uid = accounts['cancel-suspended'].uid;
|
|
99
|
+
|
|
100
|
+
const response = await http.as('cancel-suspended').post('backend-manager/payments/cancel', {
|
|
101
|
+
confirmed: true,
|
|
102
|
+
reason: 'Subscription was suspended',
|
|
103
|
+
skipGuards: true,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
assert.isSuccess(response, 'Should allow cancelling a suspended subscription');
|
|
107
|
+
assert.equal(response.data.success, true, 'Should return success: true');
|
|
108
|
+
|
|
109
|
+
// Verify the subscription was reset to cancelled (via fallback or webhook)
|
|
110
|
+
await waitFor(async () => {
|
|
111
|
+
const userDoc = await firestore.get(`users/${uid}`);
|
|
112
|
+
return userDoc?.subscription?.status === 'cancelled'
|
|
113
|
+
|| userDoc?.subscription?.cancellation?.pending === true;
|
|
114
|
+
}, 15000, 500);
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
{
|
|
119
|
+
name: 'succeeds-with-test-provider',
|
|
120
|
+
async run({ http, assert, config, accounts, firestore, waitFor, skip }) {
|
|
121
|
+
const uid = accounts['route-cancel-success'].uid;
|
|
122
|
+
const paidProduct = config.payment.products.find(p => p.id !== 'basic' && p.prices?.monthly);
|
|
123
|
+
if (!paidProduct) {
|
|
124
|
+
skip('No paid product with monthly price configured in this brand');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Step 1: Create a test subscription intent to set up a proper paid subscription
|
|
128
|
+
const intentResponse = await http.as('route-cancel-success').post('backend-manager/payments/intent', {
|
|
129
|
+
provider: 'test',
|
|
130
|
+
productId: paidProduct.id,
|
|
131
|
+
frequency: 'monthly',
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
assert.isSuccess(intentResponse, 'Intent should succeed');
|
|
135
|
+
|
|
136
|
+
// Wait for the auto-webhook to activate the subscription
|
|
137
|
+
await waitFor(async () => {
|
|
138
|
+
const userDoc = await firestore.get(`users/${uid}`);
|
|
139
|
+
return userDoc?.subscription?.payment?.provider === 'test'
|
|
140
|
+
&& userDoc?.subscription?.payment?.resourceId
|
|
141
|
+
&& userDoc?.subscription?.status === 'active';
|
|
142
|
+
}, 15000, 500);
|
|
143
|
+
|
|
144
|
+
// Step 2: Call the cancel endpoint (skipGuards bypasses the 24-hour age guard)
|
|
145
|
+
const cancelResponse = await http.as('route-cancel-success').post('backend-manager/payments/cancel', {
|
|
146
|
+
confirmed: true,
|
|
147
|
+
reason: 'Too expensive',
|
|
148
|
+
skipGuards: true,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
assert.isSuccess(cancelResponse, 'Cancel should succeed');
|
|
152
|
+
assert.equal(cancelResponse.data.success, true, 'Should return success: true');
|
|
153
|
+
|
|
154
|
+
// Step 3: Verify cancellation.pending was set via the webhook pipeline
|
|
155
|
+
await waitFor(async () => {
|
|
156
|
+
const userDoc = await firestore.get(`users/${uid}`);
|
|
157
|
+
return userDoc?.subscription?.cancellation?.pending === true;
|
|
158
|
+
}, 15000, 500);
|
|
159
|
+
|
|
160
|
+
const userDoc = await firestore.get(`users/${uid}`);
|
|
161
|
+
assert.equal(userDoc?.subscription?.cancellation?.pending, true, 'Cancellation should be pending');
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
});
|