@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,157 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const loadProvider = require('../../../libraries/load-provider.js');
|
|
3
|
+
const powertools = require('node-powertools');
|
|
4
|
+
const safeCompare = require('../../../helpers/safe-compare.js');
|
|
5
|
+
const env = require('../../../libraries/env.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* POST /payments/webhook?provider=stripe&key=XXX
|
|
9
|
+
* Receives payment provider webhooks, validates them, and saves to Firestore
|
|
10
|
+
* The Firestore onWrite trigger handles async processing
|
|
11
|
+
*
|
|
12
|
+
* This handler is provider-agnostic. Each provider module defines:
|
|
13
|
+
* - parseWebhook(req) — extracts { eventId, eventType, category, resourceType, resourceId, chargeId, refundId, raw, uid }
|
|
14
|
+
* - isSupported(eventType) — returns true for events we should process
|
|
15
|
+
*/
|
|
16
|
+
module.exports = async ({ ctx, Manager, libraries }) => {
|
|
17
|
+
const { admin } = libraries;
|
|
18
|
+
const data = ctx.request.data;
|
|
19
|
+
const query = ctx.request.query;
|
|
20
|
+
|
|
21
|
+
// Get provider and key from query params
|
|
22
|
+
const provider = query.provider;
|
|
23
|
+
const key = query.key;
|
|
24
|
+
|
|
25
|
+
// Validate provider
|
|
26
|
+
if (!provider) {
|
|
27
|
+
return ctx.respond('Missing provider parameter', { code: 400 });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Validate key
|
|
31
|
+
if (!safeCompare(key, env.get('OMEGA_WEBHOOK_KEY'))) {
|
|
32
|
+
return ctx.respond('Invalid key', { code: 401 });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Guard: test provider is not available in production
|
|
36
|
+
// (mirrors the intent side's guard — the webhook providers receive only the raw
|
|
37
|
+
// req, so the dispatch layer is where this side has a ctx to ask)
|
|
38
|
+
if (provider === 'test' && ctx.isProduction()) {
|
|
39
|
+
return ctx.respond('Test provider is not available in production', { code: 403 });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Validate brand — quit if a brand is specified and doesn't match ours
|
|
43
|
+
const brand = query.brand;
|
|
44
|
+
const ourBrand = Manager.config.brand?.id;
|
|
45
|
+
if (brand && ourBrand && brand !== ourBrand) {
|
|
46
|
+
ctx.log(`Ignoring webhook: explicit brand mismatch (received=${brand}, expected=${ourBrand})`);
|
|
47
|
+
return ctx.respond({ received: true, ignored: true });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Load the provider module
|
|
51
|
+
let providerModule;
|
|
52
|
+
try {
|
|
53
|
+
providerModule = loadProvider(path.join(__dirname, 'providers'), provider);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
return ctx.respond(`Unknown provider: ${provider}`, { code: 400 });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Parse the webhook using the provider
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = providerModule.parseWebhook(ctx.ref.req);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return ctx.respond(`Failed to parse webhook: ${e.message}`, { code: 400 });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const { eventId, eventType, category, resourceType, resourceId, chargeId, refundId, raw, uid } = parsed;
|
|
67
|
+
|
|
68
|
+
ctx.log(`Parsed webhook: eventId=${eventId}, eventType=${eventType}, category=${category || 'null'}, resourceType=${resourceType || 'null'}, uid=${uid || 'null'}, api_version=${raw?.api_version || 'unknown'}`);
|
|
69
|
+
|
|
70
|
+
// Let the provider decide if this event type is relevant
|
|
71
|
+
if (providerModule.isSupported && !providerModule.isSupported(eventType)) {
|
|
72
|
+
ctx.log(`Ignoring unsupported event type: ${eventType}`);
|
|
73
|
+
return ctx.respond({ received: true, ignored: true });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Skip events with no category (e.g., checkout.session.completed for subscription mode)
|
|
77
|
+
if (!category) {
|
|
78
|
+
ctx.log(`Ignoring event with no category: ${eventType}`);
|
|
79
|
+
return ctx.respond({ received: true, ignored: true });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Build timestamps
|
|
83
|
+
const now = powertools.timestamp(new Date(), { output: 'string' });
|
|
84
|
+
const nowUNIX = powertools.timestamp(now, { output: 'unix' });
|
|
85
|
+
|
|
86
|
+
// Claim the event, then save — in ONE transaction. Providers retry, and a
|
|
87
|
+
// retry can arrive while the first delivery is still in flight: a read
|
|
88
|
+
// followed by a separate write leaves a window where both deliveries see no
|
|
89
|
+
// doc and both write, so the pipeline runs the same event twice. The
|
|
90
|
+
// transaction's read locks the document, so exactly one delivery claims it
|
|
91
|
+
// and the other is told it is a duplicate ([#212]).
|
|
92
|
+
const docRef = admin.firestore().doc(`payments-webhooks/${eventId}`);
|
|
93
|
+
const claimed = await admin.firestore().runTransaction(async (transaction) => {
|
|
94
|
+
const existingDoc = await transaction.get(docRef);
|
|
95
|
+
|
|
96
|
+
if (existingDoc.exists) {
|
|
97
|
+
const existingStatus = existingDoc.data()?.status;
|
|
98
|
+
|
|
99
|
+
// A failed webhook is the one state that may be reclaimed — that IS the retry path
|
|
100
|
+
if (existingStatus !== 'failed') {
|
|
101
|
+
return { claimed: false, status: existingStatus };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Save with status=pending (trigger handles the rest)
|
|
106
|
+
transaction.set(docRef, {
|
|
107
|
+
id: eventId,
|
|
108
|
+
provider: provider,
|
|
109
|
+
status: 'pending',
|
|
110
|
+
raw: raw,
|
|
111
|
+
owner: uid,
|
|
112
|
+
event: {
|
|
113
|
+
type: eventType,
|
|
114
|
+
category: category,
|
|
115
|
+
resourceType: resourceType,
|
|
116
|
+
resourceId: resourceId,
|
|
117
|
+
// THIS charge's own id (Stripe/Chargebee invoice, PayPal sale), where a
|
|
118
|
+
// subscription event names one. The resourceId is the subscription, which
|
|
119
|
+
// never changes, so only this can key a single charge — and GA4
|
|
120
|
+
// deduplicates `purchase` on the id it is sent
|
|
121
|
+
// ([#656](https://github.com/Omega-JS-Stack/omega/issues/656))
|
|
122
|
+
chargeId: chargeId || null,
|
|
123
|
+
// The refund's own id, where the parser separates it from the resource the
|
|
124
|
+
// refund reversed — the key the trigger looks its amounts up by
|
|
125
|
+
// ([#510](https://github.com/Omega-JS-Stack/omega/issues/510))
|
|
126
|
+
refundId: refundId || null,
|
|
127
|
+
},
|
|
128
|
+
error: null,
|
|
129
|
+
metadata: {
|
|
130
|
+
created: {
|
|
131
|
+
timestamp: now,
|
|
132
|
+
timestampUNIX: nowUNIX,
|
|
133
|
+
},
|
|
134
|
+
completed: {
|
|
135
|
+
timestamp: null,
|
|
136
|
+
timestampUNIX: null,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return { claimed: true, retried: existingDoc.exists };
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!claimed.claimed) {
|
|
145
|
+
ctx.log(`Duplicate webhook ${eventId}, existing status=${claimed.status}, skipping`);
|
|
146
|
+
return ctx.respond({ received: true, duplicate: true });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (claimed.retried) {
|
|
150
|
+
ctx.log(`Retrying previously failed webhook ${eventId}`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
ctx.log(`Saved payments-webhooks/${eventId}: eventType=${eventType}, category=${category}, provider=${provider}, uid=${uid}`);
|
|
154
|
+
|
|
155
|
+
// Return 200 immediately
|
|
156
|
+
return ctx.respond({ received: true });
|
|
157
|
+
};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chargebee webhook provider
|
|
3
|
+
* Extracts, validates, and categorizes webhook event data from Chargebee
|
|
4
|
+
*
|
|
5
|
+
* Chargebee webhook payload structure:
|
|
6
|
+
* {
|
|
7
|
+
* id: "ev_xxx",
|
|
8
|
+
* occurred_at: 1234567890,
|
|
9
|
+
* event_type: "subscription_created",
|
|
10
|
+
* content: { subscription: {...}, customer: {...}, invoice: {...} }
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const ChargebeeLib = require('../../../../libraries/payment/providers/chargebee.js');
|
|
15
|
+
|
|
16
|
+
// Events we process — mapped to their category
|
|
17
|
+
const SUPPORTED_EVENTS = new Set([
|
|
18
|
+
// Subscription lifecycle
|
|
19
|
+
'subscription_created',
|
|
20
|
+
'subscription_activated',
|
|
21
|
+
'subscription_changed',
|
|
22
|
+
'subscription_cancelled',
|
|
23
|
+
'subscription_reactivated',
|
|
24
|
+
'subscription_renewed',
|
|
25
|
+
'subscription_cancellation_scheduled',
|
|
26
|
+
'subscription_scheduled_cancellation_removed',
|
|
27
|
+
'subscription_paused',
|
|
28
|
+
'subscription_resumed',
|
|
29
|
+
|
|
30
|
+
// Payment events
|
|
31
|
+
'payment_succeeded',
|
|
32
|
+
'payment_failed',
|
|
33
|
+
'payment_refunded',
|
|
34
|
+
|
|
35
|
+
// One-time (non-recurring invoice)
|
|
36
|
+
'invoice_generated',
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
// Events that are always subscription-related
|
|
40
|
+
const SUBSCRIPTION_EVENTS = new Set([
|
|
41
|
+
'subscription_created',
|
|
42
|
+
'subscription_activated',
|
|
43
|
+
'subscription_changed',
|
|
44
|
+
'subscription_cancelled',
|
|
45
|
+
'subscription_reactivated',
|
|
46
|
+
'subscription_renewed',
|
|
47
|
+
'subscription_cancellation_scheduled',
|
|
48
|
+
'subscription_scheduled_cancellation_removed',
|
|
49
|
+
'subscription_paused',
|
|
50
|
+
'subscription_resumed',
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
/**
|
|
55
|
+
* Returns true if this event type should be saved and processed
|
|
56
|
+
*/
|
|
57
|
+
isSupported(eventType) {
|
|
58
|
+
return SUPPORTED_EVENTS.has(eventType);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parse a Chargebee webhook request
|
|
63
|
+
*
|
|
64
|
+
* @param {object} req - The raw HTTP request
|
|
65
|
+
* @returns {object} { eventId, eventType, category, resourceType, resourceId, chargeId, raw, uid }
|
|
66
|
+
*/
|
|
67
|
+
parseWebhook(req) {
|
|
68
|
+
const event = req.body;
|
|
69
|
+
|
|
70
|
+
// Validate event structure
|
|
71
|
+
if (!event || !event.id || !event.event_type) {
|
|
72
|
+
throw new Error('Invalid Chargebee webhook payload');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const eventType = event.event_type;
|
|
76
|
+
const content = event.content || {};
|
|
77
|
+
const subscription = content.subscription;
|
|
78
|
+
const invoice = content.invoice;
|
|
79
|
+
const customer = content.customer;
|
|
80
|
+
|
|
81
|
+
let category = null;
|
|
82
|
+
let resourceType = null;
|
|
83
|
+
let resourceId = null;
|
|
84
|
+
let uid = null;
|
|
85
|
+
// THIS charge's own id — Chargebee's invoice id, which rides the renewal and
|
|
86
|
+
// refund payloads. The resourceId is the subscription, constant for its whole
|
|
87
|
+
// life, so it can never key a single charge
|
|
88
|
+
// ([#656](https://github.com/Omega-JS-Stack/omega/issues/656)). A one-time
|
|
89
|
+
// purchase has exactly one charge and the order names it.
|
|
90
|
+
let chargeId = null;
|
|
91
|
+
|
|
92
|
+
if (SUBSCRIPTION_EVENTS.has(eventType)) {
|
|
93
|
+
// Subscription lifecycle events
|
|
94
|
+
category = 'subscription';
|
|
95
|
+
resourceType = 'subscription';
|
|
96
|
+
resourceId = subscription?.id || null;
|
|
97
|
+
// The RENEWAL's invoice, and only that one. `subscription_created` carries
|
|
98
|
+
// an invoice too — the checkout's first one (test/fixtures/chargebee/
|
|
99
|
+
// webhook-subscription-created.json) — but that charge is reported under
|
|
100
|
+
// the ORDER id, the one id the confirmation page can compute as well
|
|
101
|
+
// ([#656](https://github.com/Omega-JS-Stack/omega/issues/656)). Naming it
|
|
102
|
+
// here would have this hand the pipeline a charge id for an event whose
|
|
103
|
+
// transaction is keyed on the order.
|
|
104
|
+
chargeId = eventType === 'subscription_renewed' ? (invoice?.id || null) : null;
|
|
105
|
+
uid = extractUid(subscription, customer);
|
|
106
|
+
|
|
107
|
+
} else if (eventType === 'payment_succeeded') {
|
|
108
|
+
// The paid signal. Note this routes the OPPOSITE way from payment_failed
|
|
109
|
+
// below on the subscription branch: there, the state diff (active →
|
|
110
|
+
// suspended) is what names the failure, so the doc has work to do. Here a
|
|
111
|
+
// renewal's charge is already carried by `subscription_renewed` — the event
|
|
112
|
+
// the analytics resolver reads as Chargebee's payment — so storing this one
|
|
113
|
+
// too would book that revenue TWICE, the same double-count Stripe's provider
|
|
114
|
+
// header documents for `invoice.paid` beside `invoice.payment_succeeded`.
|
|
115
|
+
if (subscription) {
|
|
116
|
+
category = null;
|
|
117
|
+
} else {
|
|
118
|
+
// A one-time purchase, and the only event that says it was actually PAID.
|
|
119
|
+
// `invoice_generated` fires for the same purchase but an invoice is born
|
|
120
|
+
// unpaid, so reading that as the sale would email a receipt to someone who
|
|
121
|
+
// never paid ([#729](https://github.com/Omega-JS-Stack/omega/issues/729)).
|
|
122
|
+
category = 'one-time';
|
|
123
|
+
resourceType = 'invoice';
|
|
124
|
+
resourceId = invoice?.id || null;
|
|
125
|
+
uid = extractUid(null, customer);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
} else if (eventType === 'payment_failed') {
|
|
129
|
+
// Payment failure — subscription-related if subscription is present
|
|
130
|
+
if (subscription) {
|
|
131
|
+
category = 'subscription';
|
|
132
|
+
resourceType = 'subscription';
|
|
133
|
+
resourceId = subscription.id;
|
|
134
|
+
uid = extractUid(subscription, customer);
|
|
135
|
+
} else {
|
|
136
|
+
// One-time payment failure
|
|
137
|
+
category = 'one-time';
|
|
138
|
+
resourceType = 'invoice';
|
|
139
|
+
resourceId = invoice?.id || null;
|
|
140
|
+
uid = extractUid(null, customer);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
} else if (eventType === 'payment_refunded') {
|
|
144
|
+
// Refund — subscription-related if subscription is present
|
|
145
|
+
if (subscription) {
|
|
146
|
+
category = 'subscription';
|
|
147
|
+
resourceType = 'subscription';
|
|
148
|
+
resourceId = subscription.id;
|
|
149
|
+
// The invoice the reversed charge was paid against ([#656]).
|
|
150
|
+
chargeId = invoice?.id || null;
|
|
151
|
+
uid = extractUid(subscription, customer);
|
|
152
|
+
} else if (invoice) {
|
|
153
|
+
// No subscription — the refund of a one-time purchase, resolved through
|
|
154
|
+
// the invoice it refunded, the same one the one-time payment_failed branch
|
|
155
|
+
// above names. Skipping it meant that refund never entered the pipeline at
|
|
156
|
+
// all ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
157
|
+
category = 'one-time';
|
|
158
|
+
resourceType = 'invoice';
|
|
159
|
+
resourceId = invoice.id;
|
|
160
|
+
uid = extractUid(null, customer);
|
|
161
|
+
} else {
|
|
162
|
+
// Neither a subscription nor an invoice — nothing names the purchase
|
|
163
|
+
category = null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
} else if (eventType === 'invoice_generated') {
|
|
167
|
+
// Check if it's a non-recurring invoice (one-time purchase)
|
|
168
|
+
if (invoice && !invoice.subscription_id) {
|
|
169
|
+
category = 'one-time';
|
|
170
|
+
resourceType = 'invoice';
|
|
171
|
+
resourceId = invoice.id;
|
|
172
|
+
uid = extractUid(null, customer);
|
|
173
|
+
} else {
|
|
174
|
+
// Recurring invoice — skip (subscription events handle this)
|
|
175
|
+
category = null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
eventId: event.id,
|
|
181
|
+
eventType: eventType,
|
|
182
|
+
category: category,
|
|
183
|
+
resourceType: resourceType,
|
|
184
|
+
resourceId: resourceId,
|
|
185
|
+
chargeId: chargeId,
|
|
186
|
+
raw: event,
|
|
187
|
+
uid: uid,
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Extract UID from Chargebee subscription meta_data or customer
|
|
194
|
+
* Tries subscription meta_data first, then customer meta_data, then cf_ fields
|
|
195
|
+
*
|
|
196
|
+
* @param {object|null} subscription - Chargebee subscription object
|
|
197
|
+
* @param {object|null} customer - Chargebee customer object
|
|
198
|
+
* @returns {string|null}
|
|
199
|
+
*/
|
|
200
|
+
function extractUid(subscription, customer) {
|
|
201
|
+
// Try subscription meta_data
|
|
202
|
+
if (subscription) {
|
|
203
|
+
const uid = ChargebeeLib.getUid(subscription);
|
|
204
|
+
if (uid) {
|
|
205
|
+
return uid;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Try customer meta_data
|
|
210
|
+
if (customer) {
|
|
211
|
+
const uid = ChargebeeLib.getUid(customer);
|
|
212
|
+
if (uid) {
|
|
213
|
+
return uid;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coinbase Commerce webhook provider
|
|
3
|
+
* Extracts and categorizes webhook event data from Coinbase Commerce
|
|
4
|
+
*
|
|
5
|
+
* Coinbase Commerce events: https://docs.cdp.coinbase.com/commerce-onchain/docs/webhooks
|
|
6
|
+
*
|
|
7
|
+
* The delivery is authenticated by the ONE `?key=` check every payment webhook
|
|
8
|
+
* rides (Ian 2026-08-27, with [#634](https://github.com/Omega-JS-Stack/omega/issues/634)).
|
|
9
|
+
* Coinbase signs its deliveries with an `X-CC-Webhook-Signature` header and this
|
|
10
|
+
* framework does NOT verify it — there is no per-provider signature layer left
|
|
11
|
+
* anywhere in the payment system, and the body is trusted for identifiers only:
|
|
12
|
+
* every value that drives state comes from the charge the pipeline looks up.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// Events we process, mapped to their category. Every Coinbase Commerce event is
|
|
16
|
+
// about a CHARGE, and a charge is a single payment — there is no subscription,
|
|
17
|
+
// plan or billing agreement in this API at all, so nothing here can ever reach
|
|
18
|
+
// the pipeline's subscription half ([#642](https://github.com/Omega-JS-Stack/omega/issues/642)).
|
|
19
|
+
//
|
|
20
|
+
// The siblings stay OUT, and each for its own reason: `charge:created` is our
|
|
21
|
+
// OWN intent call answering, not a payment, and processing it would write an
|
|
22
|
+
// order for a checkout nobody has paid for; `charge:delayed` and
|
|
23
|
+
// `charge:resolved` are the two halves of the underpaid/overpaid lane, where
|
|
24
|
+
// what the customer gets is a MERCHANT decision — they need that decision
|
|
25
|
+
// specified before an event can act on one, the same rule that keeps PayPal's
|
|
26
|
+
// CAPTURE.REVERSED out of its list.
|
|
27
|
+
const SUPPORTED_EVENTS = new Set([
|
|
28
|
+
'charge:confirmed',
|
|
29
|
+
'charge:pending',
|
|
30
|
+
'charge:failed',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
/**
|
|
35
|
+
* Returns true if this event type should be saved and processed
|
|
36
|
+
*/
|
|
37
|
+
isSupported(eventType) {
|
|
38
|
+
return SUPPORTED_EVENTS.has(eventType);
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Parse a Coinbase Commerce webhook request
|
|
43
|
+
* Extracts event data and determines category, resource type, resource ID, and UID
|
|
44
|
+
*
|
|
45
|
+
* @param {object} req - The raw HTTP request
|
|
46
|
+
* @returns {object} { eventId, eventType, category, resourceType, resourceId, chargeId, refundId, raw, uid }
|
|
47
|
+
*/
|
|
48
|
+
parseWebhook(req) {
|
|
49
|
+
const body = req.body;
|
|
50
|
+
const event = body?.event;
|
|
51
|
+
|
|
52
|
+
// Validate event structure
|
|
53
|
+
if (!event || !event.id || !event.type) {
|
|
54
|
+
throw new Error('Invalid Coinbase Commerce webhook payload');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const charge = event.data || {};
|
|
58
|
+
const eventType = event.type;
|
|
59
|
+
|
|
60
|
+
let category = null;
|
|
61
|
+
let resourceType = null;
|
|
62
|
+
let resourceId = null;
|
|
63
|
+
let chargeId = null;
|
|
64
|
+
|
|
65
|
+
if (SUPPORTED_EVENTS.has(eventType)) {
|
|
66
|
+
// Every supported event is a charge event, and a charge is one purchase
|
|
67
|
+
category = 'one-time';
|
|
68
|
+
resourceType = 'charge';
|
|
69
|
+
// The endpoint reads either identifier, and the id is the stable one — a
|
|
70
|
+
// code is the short human-facing handle on the hosted page
|
|
71
|
+
resourceId = charge.id || charge.code || null;
|
|
72
|
+
// A one-time purchase has exactly ONE charge, and this is it: the same id
|
|
73
|
+
// the money event is deduplicated on ([#656](https://github.com/Omega-JS-Stack/omega/issues/656))
|
|
74
|
+
chargeId = resourceId;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
eventId: event.id,
|
|
79
|
+
eventType: eventType,
|
|
80
|
+
category: category,
|
|
81
|
+
resourceType: resourceType,
|
|
82
|
+
resourceId: resourceId,
|
|
83
|
+
chargeId: chargeId,
|
|
84
|
+
// Coinbase Commerce has no refund API and publishes no refund event, so no
|
|
85
|
+
// coinbase delivery is ever about money going back
|
|
86
|
+
refundId: null,
|
|
87
|
+
raw: body,
|
|
88
|
+
uid: charge.metadata?.uid || null,
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPal webhook provider
|
|
3
|
+
* Extracts, validates, and categorizes webhook event data from PayPal
|
|
4
|
+
*
|
|
5
|
+
* PayPal webhook events: https://developer.paypal.com/api/rest/webhooks/event-names/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Events we process, mapped to their category
|
|
9
|
+
const SUPPORTED_EVENTS = new Set([
|
|
10
|
+
// Subscription lifecycle
|
|
11
|
+
'BILLING.SUBSCRIPTION.ACTIVATED',
|
|
12
|
+
'BILLING.SUBSCRIPTION.UPDATED',
|
|
13
|
+
'BILLING.SUBSCRIPTION.CANCELLED',
|
|
14
|
+
'BILLING.SUBSCRIPTION.SUSPENDED',
|
|
15
|
+
'BILLING.SUBSCRIPTION.EXPIRED',
|
|
16
|
+
'BILLING.SUBSCRIPTION.RE-ACTIVATED',
|
|
17
|
+
|
|
18
|
+
// Payment events (subscription billing)
|
|
19
|
+
'PAYMENT.SALE.COMPLETED',
|
|
20
|
+
'PAYMENT.SALE.DENIED',
|
|
21
|
+
'PAYMENT.SALE.REFUNDED',
|
|
22
|
+
|
|
23
|
+
// One-time order events
|
|
24
|
+
'CHECKOUT.ORDER.APPROVED',
|
|
25
|
+
|
|
26
|
+
// v2 capture refunds. One-time purchases this framework creates go through
|
|
27
|
+
// v2 Orders, and a v2 capture refunds as PAYMENT.CAPTURE.REFUNDED — never the
|
|
28
|
+
// v1 PAYMENT.SALE.REFUNDED above, so this list used to drop every refund of a
|
|
29
|
+
// modern PayPal purchase ([#240](https://github.com/Omega-JS-Stack/omega/issues/240)).
|
|
30
|
+
//
|
|
31
|
+
// The siblings stay OUT, reviewed with the same issue: CAPTURE.COMPLETED /
|
|
32
|
+
// PENDING / DENIED describe the capture this framework performs itself inside
|
|
33
|
+
// fetchResource('order'), so accepting them would process one purchase twice.
|
|
34
|
+
// CAPTURE.REVERSED is a money-out event like a refund, but nothing here has
|
|
35
|
+
// ever exercised it — it needs its own payload before it is accepted.
|
|
36
|
+
'PAYMENT.CAPTURE.REFUNDED',
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
/**
|
|
41
|
+
* Returns true if this event type should be saved and processed
|
|
42
|
+
*/
|
|
43
|
+
isSupported(eventType) {
|
|
44
|
+
return SUPPORTED_EVENTS.has(eventType);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parse a PayPal webhook request
|
|
49
|
+
* Extracts event data and determines category, resource type, resource ID, and UID
|
|
50
|
+
*
|
|
51
|
+
* @param {object} req - The raw HTTP request
|
|
52
|
+
* @returns {object} { eventId, eventType, category, resourceType, resourceId, chargeId, refundId, raw, uid }
|
|
53
|
+
*/
|
|
54
|
+
parseWebhook(req) {
|
|
55
|
+
const event = req.body;
|
|
56
|
+
|
|
57
|
+
// Validate event structure
|
|
58
|
+
if (!event || !event.id || !event.event_type) {
|
|
59
|
+
throw new Error('Invalid PayPal webhook payload');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const resource = event.resource || {};
|
|
63
|
+
const eventType = event.event_type;
|
|
64
|
+
|
|
65
|
+
let category = null;
|
|
66
|
+
let resourceType = null;
|
|
67
|
+
let resourceId = null;
|
|
68
|
+
let uid = null;
|
|
69
|
+
// A refund event's resourceId is reassigned to the sale/capture the refund
|
|
70
|
+
// reversed, which used to be the last anything saw of the REFUND's own id —
|
|
71
|
+
// the key its amounts are looked up by
|
|
72
|
+
// ([#510](https://github.com/Omega-JS-Stack/omega/issues/510)).
|
|
73
|
+
let refundId = null;
|
|
74
|
+
// THIS charge's own id — PayPal's sale id, where a subscription event names
|
|
75
|
+
// one. The resourceId is the billing agreement, constant for the whole
|
|
76
|
+
// subscription, so it can never key a single charge
|
|
77
|
+
// ([#656](https://github.com/Omega-JS-Stack/omega/issues/656)). A one-time
|
|
78
|
+
// purchase has exactly one charge and the order names it.
|
|
79
|
+
let chargeId = null;
|
|
80
|
+
|
|
81
|
+
if (eventType.startsWith('BILLING.SUBSCRIPTION.')) {
|
|
82
|
+
// Subscription lifecycle events
|
|
83
|
+
category = 'subscription';
|
|
84
|
+
resourceType = 'subscription';
|
|
85
|
+
resourceId = resource.id; // PayPal subscription ID (I-xxx)
|
|
86
|
+
|
|
87
|
+
// Parse uid from custom_id
|
|
88
|
+
uid = parseUidFromCustomId(resource.custom_id);
|
|
89
|
+
|
|
90
|
+
} else if (eventType === 'PAYMENT.SALE.COMPLETED' || eventType === 'PAYMENT.SALE.DENIED') {
|
|
91
|
+
// Payment sale — determine if it's for a subscription
|
|
92
|
+
const billingAgreementId = resource.billing_agreement_id;
|
|
93
|
+
|
|
94
|
+
if (billingAgreementId) {
|
|
95
|
+
// Subscription payment
|
|
96
|
+
category = 'subscription';
|
|
97
|
+
resourceType = 'subscription';
|
|
98
|
+
resourceId = billingAgreementId; // This is the subscription ID
|
|
99
|
+
chargeId = resource.id || null; // The sale — one per recurring charge
|
|
100
|
+
|
|
101
|
+
uid = parseUidFromCustomId(resource.custom_id);
|
|
102
|
+
} else {
|
|
103
|
+
// One-time payment — skip for now (not yet supported)
|
|
104
|
+
category = null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
} else if (eventType === 'CHECKOUT.ORDER.APPROVED') {
|
|
108
|
+
// One-time order approved by buyer — will be captured in fetchResource
|
|
109
|
+
category = 'one-time';
|
|
110
|
+
resourceType = 'order';
|
|
111
|
+
resourceId = resource.id; // PayPal order ID
|
|
112
|
+
|
|
113
|
+
// Parse uid from purchase_units custom_id
|
|
114
|
+
uid = parseUidFromCustomId(resource.purchase_units?.[0]?.custom_id);
|
|
115
|
+
|
|
116
|
+
} else if (eventType === 'PAYMENT.SALE.REFUNDED') {
|
|
117
|
+
// Refund — linked to a subscription via billing_agreement_id
|
|
118
|
+
const billingAgreementId = resource.billing_agreement_id;
|
|
119
|
+
|
|
120
|
+
if (billingAgreementId) {
|
|
121
|
+
category = 'subscription';
|
|
122
|
+
resourceType = 'subscription';
|
|
123
|
+
resourceId = billingAgreementId;
|
|
124
|
+
// The sale this refund reversed, so the refund names the same id that
|
|
125
|
+
// charge was recorded under ([#656]).
|
|
126
|
+
chargeId = resource.sale_id || null;
|
|
127
|
+
} else {
|
|
128
|
+
// No billing agreement behind it — this is the refund of a one-time
|
|
129
|
+
// purchase, and the sale it reversed is the resource the event carries.
|
|
130
|
+
// Dropping it (category = null) meant that refund never entered the
|
|
131
|
+
// pipeline at all — the Stripe twin of this gap
|
|
132
|
+
// ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
133
|
+
category = 'one-time';
|
|
134
|
+
resourceType = 'sale';
|
|
135
|
+
resourceId = resource.sale_id || resource.id;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// The v1 refund resource IS the event's own resource — its id is the refund's
|
|
139
|
+
refundId = resource.id || null;
|
|
140
|
+
|
|
141
|
+
uid = parseUidFromCustomId(resource.custom_id);
|
|
142
|
+
|
|
143
|
+
} else if (eventType === 'PAYMENT.CAPTURE.REFUNDED') {
|
|
144
|
+
// The v2 twin of the branch above: a one-time purchase made through v2
|
|
145
|
+
// Orders refunds as a capture refund. The resource is a v2 Refund, which
|
|
146
|
+
// names the CAPTURE it reversed through its HATEOAS `up` link — there is
|
|
147
|
+
// no parent_payment to walk, and the capture reads back at
|
|
148
|
+
// /v2/payments/captures/{id} carrying our custom_id directly
|
|
149
|
+
// ([#240](https://github.com/Omega-JS-Stack/omega/issues/240)).
|
|
150
|
+
category = 'one-time';
|
|
151
|
+
resourceType = 'capture';
|
|
152
|
+
resourceId = resource.capture_id || parseCaptureIdFromLinks(resource.links) || resource.id;
|
|
153
|
+
|
|
154
|
+
// The v2 Refund resource IS the event's own resource — its id is the refund's
|
|
155
|
+
refundId = resource.id || null;
|
|
156
|
+
|
|
157
|
+
uid = parseUidFromCustomId(resource.custom_id);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
eventId: event.id,
|
|
162
|
+
eventType: eventType,
|
|
163
|
+
category: category,
|
|
164
|
+
resourceType: resourceType,
|
|
165
|
+
resourceId: resourceId,
|
|
166
|
+
chargeId: chargeId,
|
|
167
|
+
refundId: refundId,
|
|
168
|
+
raw: event,
|
|
169
|
+
uid: uid,
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The capture id a v2 Refund's HATEOAS links name.
|
|
176
|
+
*
|
|
177
|
+
* PayPal v2 resources point UP at what they came from: a refund's `up` link is
|
|
178
|
+
* the capture it reversed. Only a link that is actually a captures endpoint
|
|
179
|
+
* counts — the same `up` rel names the ORDER on other resources.
|
|
180
|
+
* @param {Array} links - The resource's `links` array
|
|
181
|
+
* @returns {string|null} The capture id, or null when no link names one
|
|
182
|
+
*/
|
|
183
|
+
function parseCaptureIdFromLinks(links) {
|
|
184
|
+
for (const link of links || []) {
|
|
185
|
+
const match = String(link?.href || '').match(/\/v2\/payments\/captures\/([^/?#]+)/);
|
|
186
|
+
|
|
187
|
+
if (match) {
|
|
188
|
+
return match[1];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Parse uid from PayPal custom_id format: uid:{uid},orderId:{orderId}
|
|
197
|
+
* @param {string} customId
|
|
198
|
+
* @returns {string|null}
|
|
199
|
+
*/
|
|
200
|
+
function parseUidFromCustomId(customId) {
|
|
201
|
+
if (!customId) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (const part of customId.split(',')) {
|
|
206
|
+
const [key, ...valueParts] = part.split(':');
|
|
207
|
+
|
|
208
|
+
if (key === 'uid') {
|
|
209
|
+
return valueParts.join(':') || null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return null;
|
|
214
|
+
}
|