@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,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chargebee refund provider
|
|
3
|
+
* Issues a refund for the latest invoice and cancels the subscription immediately.
|
|
4
|
+
*
|
|
5
|
+
* Refund amount:
|
|
6
|
+
* - Full refund if the last payment was ≤7 days ago
|
|
7
|
+
* - Prorated refund (based on days remaining in billing period) if >7 days ago
|
|
8
|
+
*
|
|
9
|
+
* Chargebee refunds are issued on invoices via POST /invoices/{id}/refund.
|
|
10
|
+
* After refunding, the subscription is cancelled immediately.
|
|
11
|
+
*
|
|
12
|
+
* A one-time purchase is its own non-recurring invoice, refunded in full.
|
|
13
|
+
*/
|
|
14
|
+
const { FULL_REFUND_DAYS } = require('../../../../libraries/payment/refund-policy.js');
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
/**
|
|
18
|
+
* Process a refund for a Chargebee subscription
|
|
19
|
+
*
|
|
20
|
+
* @param {object} options
|
|
21
|
+
* @param {string} options.resourceId - Chargebee subscription ID
|
|
22
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
23
|
+
* @param {object} options.subscription - User's subscription object from Firestore
|
|
24
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
25
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
26
|
+
*/
|
|
27
|
+
async processRefund({ resourceId, uid, ctx }) {
|
|
28
|
+
const ChargebeeLib = require('../../../../libraries/payment/providers/chargebee.js');
|
|
29
|
+
ChargebeeLib.init();
|
|
30
|
+
|
|
31
|
+
// 1. Retrieve subscription
|
|
32
|
+
const subResult = await ChargebeeLib.request(`/subscriptions/${resourceId}`);
|
|
33
|
+
const sub = subResult.subscription;
|
|
34
|
+
|
|
35
|
+
// 2. Find the latest paid invoice for this subscription
|
|
36
|
+
const invoiceResult = await ChargebeeLib.request(
|
|
37
|
+
`/invoices?subscription_id[is]=${encodeURIComponent(resourceId)}&status[is]=paid&sort_by[desc]=date&limit=1`,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const invoices = invoiceResult.list || [];
|
|
41
|
+
|
|
42
|
+
if (invoices.length === 0) {
|
|
43
|
+
throw new Error('No paid invoice found for this subscription');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const invoice = invoices[0].invoice;
|
|
47
|
+
const invoiceAmountCents = invoice.amount_paid || invoice.total || 0;
|
|
48
|
+
|
|
49
|
+
if (invoiceAmountCents <= 0) {
|
|
50
|
+
throw new Error('No refundable amount on the latest invoice');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 3. Calculate refund amount
|
|
54
|
+
const invoicePaidAt = invoice.paid_at || invoice.date;
|
|
55
|
+
const daysSincePayment = (Date.now() / 1000 - invoicePaidAt) / 86400;
|
|
56
|
+
|
|
57
|
+
let refundAmountCents;
|
|
58
|
+
let isFullRefund;
|
|
59
|
+
|
|
60
|
+
if (daysSincePayment <= FULL_REFUND_DAYS) {
|
|
61
|
+
refundAmountCents = invoiceAmountCents;
|
|
62
|
+
isFullRefund = true;
|
|
63
|
+
} else {
|
|
64
|
+
// Prorated: remaining days / total days * amount
|
|
65
|
+
const periodStart = sub.current_term_start || invoice.date;
|
|
66
|
+
const periodEnd = sub.current_term_end || (invoice.date + 86400 * 30);
|
|
67
|
+
const totalDays = (periodEnd - periodStart) / 86400;
|
|
68
|
+
const daysRemaining = Math.max(0, (periodEnd - Date.now() / 1000) / 86400);
|
|
69
|
+
|
|
70
|
+
refundAmountCents = Math.round((daysRemaining / totalDays) * invoiceAmountCents);
|
|
71
|
+
isFullRefund = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (refundAmountCents <= 0) {
|
|
75
|
+
throw new Error('No refundable amount remaining');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 4. Issue refund on the invoice
|
|
79
|
+
await ChargebeeLib.request(`/invoices/${invoice.id}/refund`, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
body: { refund_amount: refundAmountCents },
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const currency = invoice.currency_code || 'USD';
|
|
85
|
+
|
|
86
|
+
ctx.log(`Chargebee refund issued: invoiceId=${invoice.id}, amount=${refundAmountCents}, full=${isFullRefund}, uid=${uid}`);
|
|
87
|
+
|
|
88
|
+
// 5. Cancel subscription immediately (if not already cancelled)
|
|
89
|
+
if (sub.status !== 'cancelled') {
|
|
90
|
+
await ChargebeeLib.request(`/subscriptions/${resourceId}/cancel_for_items`, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
body: { cancel_option: 'immediately' },
|
|
93
|
+
});
|
|
94
|
+
ctx.log(`Chargebee subscription cancelled immediately: sub=${resourceId}, uid=${uid}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
amount: refundAmountCents / 100,
|
|
99
|
+
currency: currency.toLowerCase(),
|
|
100
|
+
full: isFullRefund,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Process a refund for a Chargebee ONE-TIME purchase
|
|
106
|
+
*
|
|
107
|
+
* A one-time purchase is a non-recurring INVOICE, and Chargebee issues refunds
|
|
108
|
+
* on invoices — the same call the subscription path makes, against the order's
|
|
109
|
+
* own invoice. Always FULL: a one-time purchase buys no billing period, so
|
|
110
|
+
* there is nothing to prorate over
|
|
111
|
+
* ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
112
|
+
*
|
|
113
|
+
* @param {object} options
|
|
114
|
+
* @param {string} options.resourceId - Chargebee invoice ID
|
|
115
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
116
|
+
* @param {object} options.order - The payments-orders doc being refunded
|
|
117
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
118
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
119
|
+
*/
|
|
120
|
+
async processOneTimeRefund({ resourceId, uid, order, ctx }) {
|
|
121
|
+
const ChargebeeLib = require('../../../../libraries/payment/providers/chargebee.js');
|
|
122
|
+
ChargebeeLib.init();
|
|
123
|
+
|
|
124
|
+
const invoiceResult = await ChargebeeLib.request(`/invoices/${resourceId}`);
|
|
125
|
+
const invoice = invoiceResult.invoice;
|
|
126
|
+
const amountCents = invoice?.amount_paid || 0;
|
|
127
|
+
|
|
128
|
+
if (amountCents <= 0) {
|
|
129
|
+
throw new Error('No refundable amount on this purchase');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await ChargebeeLib.request(`/invoices/${resourceId}/refund`, {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
body: { refund_amount: amountCents },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const currency = invoice.currency_code || 'USD';
|
|
138
|
+
|
|
139
|
+
ctx.log(`Chargebee one-time refund issued: invoiceId=${resourceId}, amount=${amountCents}, orderId=${order?.id}, uid=${uid}`);
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
amount: amountCents / 100,
|
|
143
|
+
currency: currency.toLowerCase(),
|
|
144
|
+
full: true,
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coinbase Commerce refund provider — the explicit UNSUPPORTED one.
|
|
3
|
+
*
|
|
4
|
+
* Coinbase Commerce has no refund API. Returning crypto is a transfer the
|
|
5
|
+
* merchant makes by hand from the dashboard, at whatever the coin is worth that
|
|
6
|
+
* day, and nothing about it is ever attached to the charge — so there is no call
|
|
7
|
+
* this file could make and no amount it could report
|
|
8
|
+
* ([#642](https://github.com/Omega-JS-Stack/omega/issues/642)).
|
|
9
|
+
*
|
|
10
|
+
* The file still EXISTS, because a missing one makes the route answer "Unknown
|
|
11
|
+
* provider" — a different and wrong statement about a provider this backend
|
|
12
|
+
* plainly knows ([Capability gating](../../../../../../docs/payment-system.md)).
|
|
13
|
+
*
|
|
14
|
+
* Nothing reaches these functions in practice: the refund route refuses a crypto
|
|
15
|
+
* order before it loads a provider, through the ONE predicate the account page's
|
|
16
|
+
* refund button reads too (`libraries/payment/refund-policy.js`), so a button the
|
|
17
|
+
* page offers is still a refund the route accepts. They throw rather than
|
|
18
|
+
* silently answering, so a caller that ever bypasses that refusal fails at the
|
|
19
|
+
* bypass instead of recording a refund that never happened.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const UNSUPPORTED = 'Coinbase Commerce has no refund API — a crypto refund is a manual transfer from the Coinbase Commerce dashboard';
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
/**
|
|
26
|
+
* Refund a Coinbase subscription — there is no such thing to refund
|
|
27
|
+
* @throws {Error} always
|
|
28
|
+
*/
|
|
29
|
+
async processRefund() {
|
|
30
|
+
throw new Error(`${UNSUPPORTED} (and Coinbase Commerce has no subscriptions at all)`);
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Refund a Coinbase ONE-TIME purchase — unsupported, by the provider
|
|
35
|
+
* @throws {Error} always
|
|
36
|
+
*/
|
|
37
|
+
async processOneTimeRefund() {
|
|
38
|
+
throw new Error(UNSUPPORTED);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPal refund provider
|
|
3
|
+
* Refunds the most recent payment on a PayPal subscription and cancels it.
|
|
4
|
+
* A one-time purchase is refunded against its order's capture instead.
|
|
5
|
+
*
|
|
6
|
+
* PayPal refunds are issued against individual sale/capture transactions,
|
|
7
|
+
* not against the subscription itself. We find the most recent completed
|
|
8
|
+
* transaction and refund it.
|
|
9
|
+
*
|
|
10
|
+
* Proration is the same day-based compute Stripe and Chargebee run — PayPal
|
|
11
|
+
* just makes us assemble the period ourselves: it exposes no period_start /
|
|
12
|
+
* period_end on a transaction, so the period the refunded payment bought runs
|
|
13
|
+
* from that payment forward one billing interval. The interval comes from the
|
|
14
|
+
* subscription's own plan; when neither the plan nor `next_billing_time` can
|
|
15
|
+
* supply it the refund REFUSES rather than guessing at somebody's money
|
|
16
|
+
* ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
17
|
+
*/
|
|
18
|
+
const { FULL_REFUND_DAYS } = require('../../../../libraries/payment/refund-policy.js');
|
|
19
|
+
|
|
20
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
/**
|
|
24
|
+
* Process a refund for a PayPal subscription
|
|
25
|
+
*
|
|
26
|
+
* @param {object} options
|
|
27
|
+
* @param {string} options.resourceId - PayPal subscription ID (e.g., 'I-xxx')
|
|
28
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
29
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
30
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
31
|
+
*/
|
|
32
|
+
async processRefund({ resourceId, uid, ctx }) {
|
|
33
|
+
const PayPalLib = require('../../../../libraries/payment/providers/paypal.js');
|
|
34
|
+
|
|
35
|
+
// 1. Get subscription transactions to find the latest payment
|
|
36
|
+
const now = new Date();
|
|
37
|
+
const oneYearAgo = new Date(now);
|
|
38
|
+
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
|
|
39
|
+
|
|
40
|
+
const transactions = await PayPalLib.request(
|
|
41
|
+
`/v1/billing/subscriptions/${resourceId}/transactions?start_time=${oneYearAgo.toISOString()}&end_time=${now.toISOString()}`
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const completedTransactions = (transactions.transactions || [])
|
|
45
|
+
.filter(t => t.status === 'COMPLETED')
|
|
46
|
+
.sort((a, b) => new Date(b.time) - new Date(a.time));
|
|
47
|
+
|
|
48
|
+
if (completedTransactions.length === 0) {
|
|
49
|
+
throw new Error('No completed transactions found for this subscription');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const latestTransaction = completedTransactions[0];
|
|
53
|
+
const saleId = latestTransaction.id;
|
|
54
|
+
const transactionAmount = parseFloat(latestTransaction.amount_with_breakdown?.gross_amount?.value || '0');
|
|
55
|
+
const currency = latestTransaction.amount_with_breakdown?.gross_amount?.currency_code || 'USD';
|
|
56
|
+
|
|
57
|
+
if (transactionAmount <= 0) {
|
|
58
|
+
throw new Error('No refundable amount on the latest transaction');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 2. Calculate refund amount
|
|
62
|
+
const transactionDate = new Date(latestTransaction.time);
|
|
63
|
+
const daysSincePayment = (now - transactionDate) / (1000 * 60 * 60 * 24);
|
|
64
|
+
|
|
65
|
+
let refundAmount;
|
|
66
|
+
let isFullRefund;
|
|
67
|
+
|
|
68
|
+
if (daysSincePayment <= FULL_REFUND_DAYS) {
|
|
69
|
+
refundAmount = transactionAmount;
|
|
70
|
+
isFullRefund = true;
|
|
71
|
+
} else {
|
|
72
|
+
// Prorated: remaining days / total days * amount — the same compute the
|
|
73
|
+
// Stripe and Chargebee providers run, over a period PayPal makes us derive.
|
|
74
|
+
const sub = await PayPalLib.request(`/v1/billing/subscriptions/${resourceId}`);
|
|
75
|
+
const periodEnd = await this.resolvePeriodEnd({ sub, resourceId, periodStart: transactionDate, PayPalLib, ctx });
|
|
76
|
+
|
|
77
|
+
const totalDays = (periodEnd - transactionDate) / DAY_MS;
|
|
78
|
+
|
|
79
|
+
if (totalDays <= 0) {
|
|
80
|
+
throw new Error(`PayPal billing period for subscription ${resourceId} ends at or before the payment it covers — refusing to prorate`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const daysRemaining = Math.max(0, (periodEnd - now) / DAY_MS);
|
|
84
|
+
|
|
85
|
+
refundAmount = Math.round((daysRemaining / totalDays) * transactionAmount * 100) / 100;
|
|
86
|
+
isFullRefund = false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (refundAmount <= 0) {
|
|
90
|
+
throw new Error('No refundable amount remaining');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 3. Issue the refund against the sale/capture
|
|
94
|
+
await PayPalLib.request(`/v2/payments/captures/${saleId}/refund`, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
body: JSON.stringify({
|
|
97
|
+
amount: {
|
|
98
|
+
value: refundAmount.toFixed(2),
|
|
99
|
+
currency_code: currency,
|
|
100
|
+
},
|
|
101
|
+
note_to_payer: 'Subscription refund',
|
|
102
|
+
}),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
ctx.log(`PayPal refund issued: saleId=${saleId}, amount=${refundAmount}, full=${isFullRefund}, uid=${uid}`);
|
|
106
|
+
|
|
107
|
+
// 4. Cancel the subscription
|
|
108
|
+
try {
|
|
109
|
+
await PayPalLib.request(`/v1/billing/subscriptions/${resourceId}/cancel`, {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
body: JSON.stringify({ reason: 'Refund requested' }),
|
|
112
|
+
});
|
|
113
|
+
ctx.log(`PayPal subscription cancelled after refund: sub=${resourceId}, uid=${uid}`);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
// Already cancelled — that's fine
|
|
116
|
+
ctx.log(`PayPal subscription cancel after refund failed (may already be cancelled): ${e.message}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
amount: refundAmount,
|
|
121
|
+
currency: currency.toLowerCase(),
|
|
122
|
+
full: isFullRefund,
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Process a refund for a PayPal ONE-TIME purchase
|
|
128
|
+
*
|
|
129
|
+
* A one-time purchase is a PayPal ORDER (Orders API v2) and the money sits on
|
|
130
|
+
* its capture, so the refund is issued against that capture. Always FULL: a
|
|
131
|
+
* one-time purchase buys no billing period, so there is nothing to prorate over
|
|
132
|
+
* ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
133
|
+
*
|
|
134
|
+
* @param {object} options
|
|
135
|
+
* @param {string} options.resourceId - PayPal order ID
|
|
136
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
137
|
+
* @param {object} options.order - The payments-orders doc being refunded
|
|
138
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
139
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
140
|
+
*/
|
|
141
|
+
async processOneTimeRefund({ resourceId, uid, order, ctx }) {
|
|
142
|
+
const PayPalLib = require('../../../../libraries/payment/providers/paypal.js');
|
|
143
|
+
|
|
144
|
+
const paypalOrder = await PayPalLib.request(`/v2/checkout/orders/${resourceId}`);
|
|
145
|
+
const captures = paypalOrder.purchase_units?.[0]?.payments?.captures || [];
|
|
146
|
+
const capture = captures.find(c => c.status === 'COMPLETED');
|
|
147
|
+
|
|
148
|
+
if (!capture) {
|
|
149
|
+
throw new Error(`No completed capture found for PayPal order ${resourceId}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const amount = parseFloat(capture.amount?.value || '0');
|
|
153
|
+
const currency = capture.amount?.currency_code || 'USD';
|
|
154
|
+
|
|
155
|
+
if (amount <= 0) {
|
|
156
|
+
throw new Error('No refundable amount on this purchase');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await PayPalLib.request(`/v2/payments/captures/${capture.id}/refund`, {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
body: JSON.stringify({
|
|
162
|
+
amount: {
|
|
163
|
+
value: amount.toFixed(2),
|
|
164
|
+
currency_code: currency,
|
|
165
|
+
},
|
|
166
|
+
note_to_payer: 'Purchase refund',
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
ctx.log(`PayPal one-time refund issued: captureId=${capture.id}, amount=${amount}, orderId=${order?.id}, uid=${uid}`);
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
amount: amount,
|
|
174
|
+
currency: currency.toLowerCase(),
|
|
175
|
+
full: true,
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Resolve the end of the billing period a PayPal payment bought.
|
|
181
|
+
*
|
|
182
|
+
* PayPal's own answer comes first: `billing_info.next_billing_time` IS the
|
|
183
|
+
* period end while a subscription is live. A cancelled or suspended
|
|
184
|
+
* subscription drops that field, so the period is rebuilt from the payment
|
|
185
|
+
* being refunded plus the plan's REGULAR billing interval — the same
|
|
186
|
+
* derivation the PayPal library's period-end resolution runs. When neither is
|
|
187
|
+
* available the refund refuses: an invented period is an invented amount of
|
|
188
|
+
* somebody's money.
|
|
189
|
+
*
|
|
190
|
+
* @param {object} options
|
|
191
|
+
* @param {object} options.sub - The PayPal subscription resource
|
|
192
|
+
* @param {string} options.resourceId - PayPal subscription ID (for messages)
|
|
193
|
+
* @param {Date} options.periodStart - Start of the period being refunded (the payment's own date)
|
|
194
|
+
* @param {object} options.PayPalLib - The PayPal library (plan lookup)
|
|
195
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
196
|
+
* @returns {Promise<Date>} The period end
|
|
197
|
+
* @throws {Error} When the billing period cannot be derived
|
|
198
|
+
*/
|
|
199
|
+
async resolvePeriodEnd({ sub, resourceId, periodStart, PayPalLib, ctx }) {
|
|
200
|
+
const nextBilling = sub.billing_info?.next_billing_time;
|
|
201
|
+
|
|
202
|
+
if (nextBilling) {
|
|
203
|
+
return new Date(nextBilling);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!sub.plan_id) {
|
|
207
|
+
throw new Error(`PayPal subscription ${resourceId} has no next_billing_time and no plan_id — the billing period cannot be derived`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const plan = await PayPalLib.request(`/v1/billing/plans/${sub.plan_id}`);
|
|
211
|
+
const cycle = (plan.billing_cycles || []).find(c => c.tenure_type === 'REGULAR');
|
|
212
|
+
const unit = cycle?.frequency?.interval_unit;
|
|
213
|
+
const count = cycle?.frequency?.interval_count || 1;
|
|
214
|
+
|
|
215
|
+
if (!unit) {
|
|
216
|
+
throw new Error(`PayPal plan ${sub.plan_id} exposes no REGULAR billing interval — the billing period cannot be derived`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// UTC arithmetic on purpose: the local-time setters shift the period by an
|
|
220
|
+
// hour across a DST boundary, and a billing period is not a wall clock.
|
|
221
|
+
const periodEnd = new Date(periodStart);
|
|
222
|
+
|
|
223
|
+
if (unit === 'YEAR') {
|
|
224
|
+
periodEnd.setUTCFullYear(periodEnd.getUTCFullYear() + count);
|
|
225
|
+
} else if (unit === 'MONTH') {
|
|
226
|
+
periodEnd.setUTCMonth(periodEnd.getUTCMonth() + count);
|
|
227
|
+
} else if (unit === 'WEEK') {
|
|
228
|
+
periodEnd.setUTCDate(periodEnd.getUTCDate() + (count * 7));
|
|
229
|
+
} else if (unit === 'DAY') {
|
|
230
|
+
periodEnd.setUTCDate(periodEnd.getUTCDate() + count);
|
|
231
|
+
} else {
|
|
232
|
+
throw new Error(`PayPal plan ${sub.plan_id} uses an unknown billing interval "${unit}" — the billing period cannot be derived`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
ctx.log(`PayPal period end derived from plan ${sub.plan_id}: ${count} ${unit} after ${periodStart.toISOString()} → ${periodEnd.toISOString()}`);
|
|
236
|
+
|
|
237
|
+
return periodEnd;
|
|
238
|
+
},
|
|
239
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe refund provider
|
|
3
|
+
*
|
|
4
|
+
* Subscriptions: issues a refund for the latest invoice and cancels the
|
|
5
|
+
* subscription immediately. One-time purchases: refunds the payment behind the
|
|
6
|
+
* order's checkout session, in full.
|
|
7
|
+
*
|
|
8
|
+
* Refund amount:
|
|
9
|
+
* - Full refund if the last payment was ≤7 days ago
|
|
10
|
+
* - Prorated refund (based on days remaining in billing period) if >7 days ago
|
|
11
|
+
*
|
|
12
|
+
* After refunding, if the subscription is still active, it is cancelled immediately.
|
|
13
|
+
* Stripe then sends a customer.subscription.deleted webhook which the existing
|
|
14
|
+
* pipeline processes to update Firestore.
|
|
15
|
+
*/
|
|
16
|
+
const { FULL_REFUND_DAYS } = require('../../../../libraries/payment/refund-policy.js');
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
/**
|
|
20
|
+
* Process a refund for a Stripe subscription
|
|
21
|
+
*
|
|
22
|
+
* @param {object} options
|
|
23
|
+
* @param {string} options.resourceId - Stripe subscription ID (e.g., 'sub_xxx')
|
|
24
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
25
|
+
* @param {object} options.subscription - User's subscription object from Firestore
|
|
26
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
27
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
28
|
+
*/
|
|
29
|
+
async processRefund({ resourceId, uid, ctx }) {
|
|
30
|
+
const StripeLib = require('../../../../libraries/payment/providers/stripe.js');
|
|
31
|
+
const stripe = StripeLib.init();
|
|
32
|
+
|
|
33
|
+
// 1. Retrieve subscription to get latest_invoice
|
|
34
|
+
const sub = await stripe.subscriptions.retrieve(resourceId);
|
|
35
|
+
|
|
36
|
+
if (!sub.latest_invoice) {
|
|
37
|
+
throw new Error('No invoice found for this subscription');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Retrieve the latest invoice to get payment_intent + timing
|
|
41
|
+
const invoiceId = typeof sub.latest_invoice === 'string'
|
|
42
|
+
? sub.latest_invoice
|
|
43
|
+
: sub.latest_invoice.id;
|
|
44
|
+
const invoice = await stripe.invoices.retrieve(invoiceId);
|
|
45
|
+
|
|
46
|
+
if (!invoice.payment_intent) {
|
|
47
|
+
throw new Error('No payment found for the latest invoice');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 3. Calculate refund amount
|
|
51
|
+
const invoicePaidAt = invoice.status_transitions?.paid_at || invoice.created;
|
|
52
|
+
const daysSincePayment = (Date.now() / 1000 - invoicePaidAt) / 86400;
|
|
53
|
+
const invoiceAmount = invoice.amount_paid; // in cents
|
|
54
|
+
|
|
55
|
+
if (invoiceAmount <= 0) {
|
|
56
|
+
throw new Error('No refundable amount on the latest invoice');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let refundAmount;
|
|
60
|
+
let isFullRefund;
|
|
61
|
+
|
|
62
|
+
if (daysSincePayment <= FULL_REFUND_DAYS) {
|
|
63
|
+
refundAmount = invoiceAmount;
|
|
64
|
+
isFullRefund = true;
|
|
65
|
+
} else {
|
|
66
|
+
// Prorated: remaining days / total days * amount
|
|
67
|
+
const periodStart = sub.current_period_start || invoice.period_start;
|
|
68
|
+
const periodEnd = sub.current_period_end || invoice.period_end;
|
|
69
|
+
const totalDays = (periodEnd - periodStart) / 86400;
|
|
70
|
+
const daysRemaining = Math.max(0, (periodEnd - Date.now() / 1000) / 86400);
|
|
71
|
+
|
|
72
|
+
refundAmount = Math.round((daysRemaining / totalDays) * invoiceAmount);
|
|
73
|
+
isFullRefund = false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (refundAmount <= 0) {
|
|
77
|
+
throw new Error('No refundable amount remaining');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 4. Issue the refund
|
|
81
|
+
const paymentIntentId = typeof invoice.payment_intent === 'string'
|
|
82
|
+
? invoice.payment_intent
|
|
83
|
+
: invoice.payment_intent.id;
|
|
84
|
+
|
|
85
|
+
// Idempotency key scoped to the subscription prevents double-refund from
|
|
86
|
+
// a user double-clicking the refund button. Stripe caches the response for
|
|
87
|
+
// 24 hours — any concurrent or repeated refund request for the same sub
|
|
88
|
+
// within that window returns the original refund instead of issuing a new one.
|
|
89
|
+
const refund = await stripe.refunds.create({
|
|
90
|
+
payment_intent: paymentIntentId,
|
|
91
|
+
amount: refundAmount,
|
|
92
|
+
reason: 'requested_by_customer',
|
|
93
|
+
}, {
|
|
94
|
+
idempotencyKey: `omega-refund-${resourceId}`,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
ctx.log(`Stripe refund created: refundId=${refund.id}, amount=${refundAmount}, full=${isFullRefund}, uid=${uid}`);
|
|
98
|
+
|
|
99
|
+
// 5. Cancel subscription immediately (if not already canceled)
|
|
100
|
+
// This triggers customer.subscription.deleted webhook → existing pipeline
|
|
101
|
+
if (sub.status !== 'canceled') {
|
|
102
|
+
await stripe.subscriptions.cancel(resourceId);
|
|
103
|
+
ctx.log(`Stripe subscription cancelled immediately: sub=${resourceId}, uid=${uid}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
amount: refundAmount / 100, // convert cents to dollars for response
|
|
108
|
+
currency: refund.currency,
|
|
109
|
+
full: isFullRefund,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Process a refund for a Stripe ONE-TIME purchase
|
|
115
|
+
*
|
|
116
|
+
* The order's resource is the checkout session the purchase completed with, and
|
|
117
|
+
* the payment behind it is what gets refunded. Always FULL: a one-time purchase
|
|
118
|
+
* buys no billing period, so there is nothing to prorate over
|
|
119
|
+
* ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
120
|
+
*
|
|
121
|
+
* @param {object} options
|
|
122
|
+
* @param {string} options.resourceId - Stripe checkout session ID (e.g., 'cs_xxx')
|
|
123
|
+
* @param {string} options.uid - User's UID (for logging)
|
|
124
|
+
* @param {object} options.order - The payments-orders doc being refunded
|
|
125
|
+
* @param {object} options.ctx - Assistant instance for logging
|
|
126
|
+
* @returns {{ amount: number, currency: string, full: boolean }}
|
|
127
|
+
*/
|
|
128
|
+
async processOneTimeRefund({ resourceId, uid, order, ctx }) {
|
|
129
|
+
const StripeLib = require('../../../../libraries/payment/providers/stripe.js');
|
|
130
|
+
const stripe = StripeLib.init();
|
|
131
|
+
|
|
132
|
+
const session = await stripe.checkout.sessions.retrieve(resourceId);
|
|
133
|
+
|
|
134
|
+
const paymentIntentId = typeof session.payment_intent === 'string'
|
|
135
|
+
? session.payment_intent
|
|
136
|
+
: session.payment_intent?.id;
|
|
137
|
+
|
|
138
|
+
if (!paymentIntentId) {
|
|
139
|
+
throw new Error(`No payment found for checkout session ${resourceId}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// No `amount` — the whole charge comes back. The idempotency key scoped to the
|
|
143
|
+
// session prevents a double-refund from a double-clicked button: Stripe caches
|
|
144
|
+
// the response for 24 hours and returns the original refund.
|
|
145
|
+
const refund = await stripe.refunds.create({
|
|
146
|
+
payment_intent: paymentIntentId,
|
|
147
|
+
reason: 'requested_by_customer',
|
|
148
|
+
}, {
|
|
149
|
+
idempotencyKey: `omega-refund-one-time-${resourceId}`,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
ctx.log(`Stripe one-time refund created: refundId=${refund.id}, amount=${refund.amount}, orderId=${order?.id}, uid=${uid}`);
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
amount: refund.amount / 100, // convert cents to dollars for response
|
|
156
|
+
currency: refund.currency,
|
|
157
|
+
full: true,
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
};
|