@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,250 @@
|
|
|
1
|
+
const Stripe = require('./stripe.js');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test provider library
|
|
5
|
+
* Delegates to Stripe's transformers since test provider generates Stripe-shaped data
|
|
6
|
+
* Stamps provider as 'test' to distinguish from real Stripe data
|
|
7
|
+
*/
|
|
8
|
+
const Test = {
|
|
9
|
+
/**
|
|
10
|
+
* No-op init — test provider doesn't need an external SDK
|
|
11
|
+
*/
|
|
12
|
+
init() {
|
|
13
|
+
return null;
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fetch resource — the test provider IS its own API
|
|
18
|
+
*
|
|
19
|
+
* The one library that may read the event body ([../fetch-failure.js](../fetch-failure.js)):
|
|
20
|
+
* there is no test provider out there to ask, so its "API records" are the
|
|
21
|
+
* emulator's own payments-orders plus the body the event carried. A REAL
|
|
22
|
+
* provider never reads it — that is the trust rule this seam enforces
|
|
23
|
+
* ([#506](https://github.com/Omega-JS-Stack/omega/issues/506)) — and the route
|
|
24
|
+
* refuses `provider=test` in production, so nothing outside a test run reaches here.
|
|
25
|
+
*
|
|
26
|
+
* When the requested resourceType doesn't match the event's own resource (e.g.,
|
|
27
|
+
* requesting a subscription but the event carries an invoice from
|
|
28
|
+
* invoice.payment_failed), look up the existing resource from Firestore instead
|
|
29
|
+
* of returning mismatched data.
|
|
30
|
+
*/
|
|
31
|
+
async fetchResource(resourceType, resourceId, context) {
|
|
32
|
+
const eventResource = this.extractResource(context?.raw) || {};
|
|
33
|
+
|
|
34
|
+
// If the event's resource matches the requested type AND has a UID, return it directly
|
|
35
|
+
// When UID is missing (e.g., PAYMENT.SALE events), fall through to Firestore lookup
|
|
36
|
+
// so we can reconstruct a resource with the UID from the order's owner field
|
|
37
|
+
if (eventResource.object === resourceType && eventResource.metadata?.uid) {
|
|
38
|
+
return eventResource;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Look up the existing resource from payments-orders in Firestore
|
|
42
|
+
// This simulates what a real API call (Stripe/PayPal) would return — a resource
|
|
43
|
+
// with the full metadata including UID
|
|
44
|
+
const admin = context?.admin;
|
|
45
|
+
if (admin && resourceId) {
|
|
46
|
+
const snapshot = await admin.firestore()
|
|
47
|
+
.collection('payments-orders')
|
|
48
|
+
.where('resourceId', '==', resourceId)
|
|
49
|
+
.limit(1)
|
|
50
|
+
.get();
|
|
51
|
+
|
|
52
|
+
if (!snapshot.empty) {
|
|
53
|
+
const data = snapshot.docs[0].data();
|
|
54
|
+
// payments-orders stores the unified subscription inside .unified
|
|
55
|
+
// Reconstruct a Stripe-shaped object from the unified data for toUnifiedSubscription()
|
|
56
|
+
if (resourceType === 'subscription' && data.unified) {
|
|
57
|
+
const reconstructed = buildStripeSubscriptionFromUnified(data.unified, resourceId, context?.eventType, context?.config, data.owner);
|
|
58
|
+
|
|
59
|
+
// If the event's resource matched the type but lacked UID, overlay its new
|
|
60
|
+
// state onto the reconstructed resource, but keep the reconstructed metadata (has uid)
|
|
61
|
+
if (eventResource.object === resourceType) {
|
|
62
|
+
return { ...eventResource, metadata: { ...eventResource.metadata, ...reconstructed.metadata } };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return reconstructed;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The same reconstruction on the one-time side: a session/invoice webhook
|
|
69
|
+
// that carries no metadata (no uid, no orderId) is answered from the order
|
|
70
|
+
// the first webhook already wrote
|
|
71
|
+
if (data.type === 'one-time' && data.unified) {
|
|
72
|
+
const reconstructed = buildStripeOneTimeFromOrder(data, resourceId);
|
|
73
|
+
|
|
74
|
+
// Keep the event's fresh state, take the metadata only the order has
|
|
75
|
+
if (Object.keys(eventResource).length > 0) {
|
|
76
|
+
return { ...eventResource, metadata: { ...eventResource.metadata, ...reconstructed.metadata } };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return reconstructed;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Last resort: the event's own resource is all this provider has
|
|
85
|
+
return eventResource;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Extract the resource the webhook envelope carries — delegates to Stripe
|
|
90
|
+
* (test provider uses Stripe-shaped data), and is where its own fetchResource
|
|
91
|
+
* reads the event body it answers from
|
|
92
|
+
*/
|
|
93
|
+
extractResource(raw) {
|
|
94
|
+
return Stripe.extractResource(raw);
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Extract orderId — delegates to Stripe (test provider uses Stripe-shaped data)
|
|
99
|
+
*/
|
|
100
|
+
getOrderId(resource) {
|
|
101
|
+
return Stripe.getOrderId(resource);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Extract UID — delegates to Stripe (test provider uses Stripe-shaped data)
|
|
106
|
+
*/
|
|
107
|
+
getUid(resource) {
|
|
108
|
+
return Stripe.getUid(resource);
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Refund details — Stripe's reader over the charge this provider has
|
|
113
|
+
*
|
|
114
|
+
* The test provider IS its own API ([../fetch-failure.js](../fetch-failure.js)),
|
|
115
|
+
* so the charge of record is whichever one it already holds: the fetched
|
|
116
|
+
* resource when the event resolved to the charge itself, otherwise the event's
|
|
117
|
+
* own body. Never a real Stripe lookup — there is no Stripe account behind a
|
|
118
|
+
* test-provider event to answer one
|
|
119
|
+
* ([#510](https://github.com/Omega-JS-Stack/omega/issues/510)).
|
|
120
|
+
*/
|
|
121
|
+
async getRefundDetails(resource, options = {}) {
|
|
122
|
+
const charge = resource?.object === 'charge'
|
|
123
|
+
? resource
|
|
124
|
+
: this.extractResource(options.raw);
|
|
125
|
+
|
|
126
|
+
return Stripe.toRefundDetails(charge);
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Transform raw subscription into unified shape
|
|
131
|
+
* Delegates to Stripe's toUnifiedSubscription (same data shape), stamps provider as 'test'
|
|
132
|
+
*/
|
|
133
|
+
toUnifiedSubscription(rawSubscription, options) {
|
|
134
|
+
const unified = Stripe.toUnifiedSubscription(rawSubscription, options);
|
|
135
|
+
unified.payment.provider = 'test';
|
|
136
|
+
return unified;
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Transform raw one-time payment into unified shape
|
|
141
|
+
* Delegates to Stripe's toUnifiedOneTime, stamps provider as 'test'
|
|
142
|
+
*/
|
|
143
|
+
toUnifiedOneTime(rawResource, options) {
|
|
144
|
+
const unified = Stripe.toUnifiedOneTime(rawResource, options);
|
|
145
|
+
unified.payment.provider = 'test';
|
|
146
|
+
return unified;
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
module.exports = Test;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Reconstruct a Stripe-shaped subscription from the unified subscription stored in Firestore
|
|
154
|
+
* This is only needed for the test provider when the webhook fallback doesn't match the resource type
|
|
155
|
+
* (e.g., invoice.payment_failed sends invoice data but we need the subscription)
|
|
156
|
+
*
|
|
157
|
+
* The unified → Stripe mapping must produce data that toUnifiedSubscription() can process correctly.
|
|
158
|
+
* For payment failure events, we override the status to past_due so it maps to 'suspended'.
|
|
159
|
+
*/
|
|
160
|
+
function buildStripeSubscriptionFromUnified(unified, resourceId, eventType, config, ownerUid) {
|
|
161
|
+
// Map unified status back to a Stripe status
|
|
162
|
+
const STATUS_MAP = {
|
|
163
|
+
active: 'active',
|
|
164
|
+
suspended: 'past_due',
|
|
165
|
+
cancelled: 'canceled',
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Map unified frequency back to Stripe interval
|
|
169
|
+
const INTERVAL_MAP = {
|
|
170
|
+
monthly: 'month',
|
|
171
|
+
annually: 'year',
|
|
172
|
+
weekly: 'week',
|
|
173
|
+
daily: 'day',
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// Determine status: for payment failure events, force past_due regardless of current state
|
|
177
|
+
// In production, Stripe would have already updated the subscription status
|
|
178
|
+
let status = STATUS_MAP[unified.status] || 'active';
|
|
179
|
+
if (eventType === 'invoice.payment_failed') {
|
|
180
|
+
status = 'past_due';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Resolve the Stripe product ID from config
|
|
184
|
+
// This is needed for resolveProduct() in toUnifiedSubscription() to match the correct product
|
|
185
|
+
const frequency = unified.payment?.frequency;
|
|
186
|
+
const productId = unified.product?.id;
|
|
187
|
+
const stripeProductId = resolveStripeProductId(productId, config);
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
id: resourceId,
|
|
191
|
+
object: 'subscription',
|
|
192
|
+
status: status,
|
|
193
|
+
metadata: { orderId: unified.payment?.orderId || null, uid: ownerUid || null },
|
|
194
|
+
plan: {
|
|
195
|
+
product: stripeProductId,
|
|
196
|
+
interval: INTERVAL_MAP[frequency] || 'month',
|
|
197
|
+
},
|
|
198
|
+
current_period_end: unified.expires?.timestampUNIX || 0,
|
|
199
|
+
current_period_start: unified.payment?.startDate?.timestampUNIX || 0,
|
|
200
|
+
start_date: unified.payment?.startDate?.timestampUNIX || 0,
|
|
201
|
+
cancel_at_period_end: unified.cancellation?.pending || false,
|
|
202
|
+
cancel_at: unified.cancellation?.pending ? unified.cancellation?.date?.timestampUNIX : null,
|
|
203
|
+
canceled_at: null,
|
|
204
|
+
trial_start: unified.trial?.claimed ? (unified.payment?.startDate?.timestampUNIX || 0) : null,
|
|
205
|
+
trial_end: unified.trial?.claimed ? (unified.trial?.expires?.timestampUNIX || 0) : null,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Reconstruct a Stripe-shaped one-time resource from the order stored in Firestore
|
|
211
|
+
*
|
|
212
|
+
* The one-time twin of buildStripeSubscriptionFromUnified(): what a real API call
|
|
213
|
+
* would return for a session/invoice — most importantly the metadata (uid, orderId,
|
|
214
|
+
* productId) that a bare webhook payload may not carry.
|
|
215
|
+
*/
|
|
216
|
+
function buildStripeOneTimeFromOrder(order, resourceId) {
|
|
217
|
+
const unified = order.unified || {};
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
id: resourceId,
|
|
221
|
+
object: 'checkout.session',
|
|
222
|
+
status: unified.status === 'completed' ? 'complete' : unified.status || 'complete',
|
|
223
|
+
metadata: {
|
|
224
|
+
orderId: unified.payment?.orderId || order.id || null,
|
|
225
|
+
uid: order.owner || null,
|
|
226
|
+
productId: unified.product?.id || order.productId || null,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Look up the Stripe product ID from config given a product ID
|
|
233
|
+
* e.g., ('plus') → 'prod_plus'
|
|
234
|
+
*/
|
|
235
|
+
function resolveStripeProductId(productId, config) {
|
|
236
|
+
if (!productId || !config?.payment?.products) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const product = config.payment.products.find(p => p.id === productId);
|
|
241
|
+
|
|
242
|
+
if (!product) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Real Stripe product ID if configured, otherwise the "_test_<id>" sentinel that the
|
|
247
|
+
// Stripe resolver recognizes and maps back to the @omega.js/backend product. Lets reconstruction
|
|
248
|
+
// work in brands without real Stripe (Somiibo uses PayPal, Chargebee, etc.).
|
|
249
|
+
return product.stripe?.productId || `_test_${product.id}`;
|
|
250
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE rule that says a refund record belongs to the event that named it.
|
|
3
|
+
*
|
|
4
|
+
* A refund's numbers come from the provider, looked up by an id the payload
|
|
5
|
+
* carried ([#510](https://github.com/Omega-JS-Stack/omega/issues/510)). That id is
|
|
6
|
+
* as trusted as the resourceId every lookup starts from — with one difference the
|
|
7
|
+
* trust argument missed: a resourceId is SELF-CONSISTENT (whatever it names is
|
|
8
|
+
* what gets fetched and what gets written), while a refund id imports numbers
|
|
9
|
+
* ACROSS records. Pair a real sale of your own with an unrelated refund id from
|
|
10
|
+
* the same merchant account and another customer's refund amount lands on your
|
|
11
|
+
* order, their email and their refund conversion
|
|
12
|
+
* ([#532](https://github.com/Omega-JS-Stack/omega/issues/532)).
|
|
13
|
+
*
|
|
14
|
+
* So every refund lookup is linked back. Each provider knows its own back-pointer
|
|
15
|
+
* — a PayPal v1 refund names its `sale_id` and a v2 refund links `up` to its
|
|
16
|
+
* capture, a Chargebee credit note names its `subscription_id` /
|
|
17
|
+
* `reference_invoice_id`, a Stripe charge carries the subscription and the uid it
|
|
18
|
+
* was made under — and hands the pair here, so the DECISION is written once:
|
|
19
|
+
*
|
|
20
|
+
* - **disagrees** — the record is about another order. Thrown as
|
|
21
|
+
* `refundNotLinked`, which the pipeline refuses and acknowledges (the #509
|
|
22
|
+
* shape): nothing is written, and the stamp on the event's own doc is what a
|
|
23
|
+
* human reconciles from.
|
|
24
|
+
* - **agrees** — proceed.
|
|
25
|
+
* - **nothing to compare** — the record carries no back-pointer for this kind of
|
|
26
|
+
* resource (a PayPal subscription refund names the sale, never the billing
|
|
27
|
+
* agreement). Unprovable is not the same as wrong, so it proceeds — and the log
|
|
28
|
+
* line saying so is the only warning a human gets that this one refund was
|
|
29
|
+
* never cross-checked, exactly like the #509 uid fallback.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Assert that a looked-up refund record points back at the event's resource
|
|
34
|
+
*
|
|
35
|
+
* @param {object} options
|
|
36
|
+
* @param {string} options.provider - Provider name (e.g. 'paypal')
|
|
37
|
+
* @param {string} options.refundType - What was looked up ('refund', 'credit_note', 'charge', 'transaction')
|
|
38
|
+
* @param {string} options.refundId - The id it was looked up by
|
|
39
|
+
* @param {string|null} options.field - The record's back-pointer field, named as the provider spells it
|
|
40
|
+
* @param {string|null} options.found - What that field says the record belongs to
|
|
41
|
+
* @param {string|null} options.expected - What the event says it should belong to
|
|
42
|
+
* @param {string} options.resourceType - The event's resource type
|
|
43
|
+
* @param {string} options.resourceId - The event's resource id
|
|
44
|
+
* @param {object} [options.ctx] - Assistant instance for logging
|
|
45
|
+
* @throws {Error} Carrying `refundNotLinked` when the record belongs to something else
|
|
46
|
+
*/
|
|
47
|
+
function assertRefundLinkage({ provider, refundType, refundId, field, found, expected, resourceType, resourceId, ctx }) {
|
|
48
|
+
if (!field || !found || !expected) {
|
|
49
|
+
const message = `REFUND LINK UNPROVEN: ${provider} ${refundType} ${refundId} carries no ${field || 'back-pointer'} to check against ${resourceType} ${resourceId}, so this refund's numbers are recorded without being linked back to the resource the event named`;
|
|
50
|
+
|
|
51
|
+
if (ctx?.warn) {
|
|
52
|
+
ctx.warn(message);
|
|
53
|
+
} else {
|
|
54
|
+
console.warn(`[@omega.js/backend:payment:refund-linkage] ${message}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (found === expected) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const failure = new Error(`${provider} ${refundType} ${refundId} names ${field} ${found}, but the ${resourceType} ${resourceId} this event is about is ${expected} — the refund belongs to another record`);
|
|
65
|
+
|
|
66
|
+
failure.refundNotLinked = true;
|
|
67
|
+
failure.provider = provider;
|
|
68
|
+
failure.refundType = refundType;
|
|
69
|
+
failure.refundId = refundId;
|
|
70
|
+
failure.field = field;
|
|
71
|
+
failure.linkedTo = found;
|
|
72
|
+
failure.resourceType = resourceType;
|
|
73
|
+
failure.resourceId = resourceId;
|
|
74
|
+
|
|
75
|
+
throw failure;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = assertRefundLinkage;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refund policy — the ONE home of the brand's refund window.
|
|
3
|
+
*
|
|
4
|
+
* Every refund provider answers the same question ("is this payment recent
|
|
5
|
+
* enough for a full refund, or is it prorated by days remaining?") and the
|
|
6
|
+
* answer must be identical across Stripe, PayPal, and Chargebee: a user who
|
|
7
|
+
* paid the same day must not get a different outcome because of which button
|
|
8
|
+
* they checked out with. Three private copies of the number would drift; this
|
|
9
|
+
* is the single definition all three import ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
10
|
+
*
|
|
11
|
+
* It is also where a ONE-TIME order's refundability is decided, for the same
|
|
12
|
+
* reason: the refund route enforces it, and the account page's orders list has
|
|
13
|
+
* to offer the button on exactly the orders that route would accept. Two
|
|
14
|
+
* spellings of "refundable" would eventually offer a button that 400s
|
|
15
|
+
* ([#672](https://github.com/Omega-JS-Stack/omega/issues/672)).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Payments this many days old or younger refund in FULL. Older ones prorate by
|
|
19
|
+
// the days remaining in the billing period the payment bought.
|
|
20
|
+
const FULL_REFUND_DAYS = 7;
|
|
21
|
+
|
|
22
|
+
// Payments older than this are not eligible for a refund, whatever was bought.
|
|
23
|
+
const REFUND_WINDOW_SECONDS = 6 * 30 * 24 * 60 * 60;
|
|
24
|
+
const OUTSIDE_WINDOW_MESSAGE = 'Payments older than 6 months are not eligible for refunds';
|
|
25
|
+
|
|
26
|
+
// Providers with no refund API at all. Coinbase Commerce settles in crypto and
|
|
27
|
+
// exposes no refund endpoint — returning coins is a manual transfer the merchant
|
|
28
|
+
// makes from its dashboard, at whatever the coin is worth that day, and nothing
|
|
29
|
+
// about it is ever attached to the charge. So the refusal belongs HERE, with
|
|
30
|
+
// every other one, rather than as a provider call that could only ever fail: the
|
|
31
|
+
// route would answer the customer "try again shortly" for something no retry can
|
|
32
|
+
// fix, and the account page would offer a Refund button on it
|
|
33
|
+
// ([#642](https://github.com/Omega-JS-Stack/omega/issues/642)).
|
|
34
|
+
const NO_REFUND_PROVIDERS = ['coinbase'];
|
|
35
|
+
const NO_REFUND_MESSAGE = 'Crypto purchases cannot be refunded automatically. Contact support and we will arrange it by hand.';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Is a payment recent enough to refund? An absent date cannot disqualify one.
|
|
39
|
+
*
|
|
40
|
+
* @param {number} [paidUNIX] - When the payment happened
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
function isWithinRefundWindow(paidUNIX) {
|
|
44
|
+
if (!paidUNIX) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return paidUNIX >= Math.floor(Date.now() / 1000) - REFUND_WINDOW_SECONDS;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Why this one-time order cannot be refunded, if it cannot.
|
|
53
|
+
*
|
|
54
|
+
* Ownership is deliberately NOT here: that is an authorization question the
|
|
55
|
+
* caller answers (the refund route compares the order's owner against the
|
|
56
|
+
* caller; the orders route only ever reads the caller's own).
|
|
57
|
+
*
|
|
58
|
+
* @param {object} order - The payments-orders document
|
|
59
|
+
* @returns {{ reason: string, message: string }|null} The refusal, or null when the order is refundable
|
|
60
|
+
*/
|
|
61
|
+
function oneTimeRefundRefusal(order) {
|
|
62
|
+
if (!order || order.type !== 'one-time') {
|
|
63
|
+
return { reason: 'not-one-time', message: 'That order is not a one-time purchase' };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// requests.refund covers the in-app path; unified.status covers a refund issued
|
|
67
|
+
// from the provider dashboard, which arrives by webhook and writes no request
|
|
68
|
+
if (order.requests?.refund || order.unified?.status === 'refunded') {
|
|
69
|
+
return { reason: 'already-refunded', message: 'This purchase has already been refunded' };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Nothing was captured, so there is nothing to reverse. Every provider
|
|
73
|
+
// normalizes a successful purchase to 'completed' and passes its own word
|
|
74
|
+
// through otherwise (stripe.js:485, paypal.js:326, chargebee.js:416-423), so an
|
|
75
|
+
// abandoned checkout keeps its provider and its resourceId and passed every
|
|
76
|
+
// other refusal — the orders list offered a refund button on a Failed pill, and
|
|
77
|
+
// pressing it asked the provider to refund a charge that never happened
|
|
78
|
+
if (order.unified?.status !== 'completed') {
|
|
79
|
+
return { reason: 'not-completed', message: 'That purchase has not completed' };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The purchase date is the order's creation; the last webhook write is the fallback
|
|
83
|
+
const purchasedUNIX = order.metadata?.created?.timestampUNIX
|
|
84
|
+
|| order.unified?.payment?.updatedBy?.date?.timestampUNIX;
|
|
85
|
+
|
|
86
|
+
if (!isWithinRefundWindow(purchasedUNIX)) {
|
|
87
|
+
return { reason: 'outside-window', message: OUTSIDE_WINDOW_MESSAGE };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const provider = order.provider || order.unified?.payment?.provider;
|
|
91
|
+
const resourceId = order.resourceId || order.unified?.payment?.resourceId;
|
|
92
|
+
|
|
93
|
+
if (!provider || !resourceId) {
|
|
94
|
+
return { reason: 'missing-payment-details', message: 'Order payment details not found' };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Last, because it is the least specific thing wrong with an order: a crypto
|
|
98
|
+
// purchase that is also already refunded should still say so.
|
|
99
|
+
if (NO_REFUND_PROVIDERS.includes(provider)) {
|
|
100
|
+
return { reason: 'provider-cannot-refund', message: NO_REFUND_MESSAGE };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
FULL_REFUND_DAYS,
|
|
108
|
+
REFUND_WINDOW_SECONDS,
|
|
109
|
+
OUTSIDE_WINDOW_MESSAGE,
|
|
110
|
+
NO_REFUND_PROVIDERS,
|
|
111
|
+
isWithinRefundWindow,
|
|
112
|
+
oneTimeRefundRefusal,
|
|
113
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cancel-flow save offer, in the shape the payment stack already speaks
|
|
3
|
+
* ([#268](https://github.com/Omega-JS-Stack/omega/issues/268)).
|
|
4
|
+
*
|
|
5
|
+
* A customer who starts cancelling is pitched a discount on the next cycle
|
|
6
|
+
* before the questionnaire. What the offer IS belongs to the brand
|
|
7
|
+
* (`payment.winback` in omega.json5, resolved by @omega.js/config — 50% off the
|
|
8
|
+
* next cycle when a brand configures nothing), so nothing here carries a number
|
|
9
|
+
* of its own.
|
|
10
|
+
*
|
|
11
|
+
* Everything downstream of the apply route — the Stripe coupon builder, the
|
|
12
|
+
* order doc, the analytics line — already reads a discount-codes VALIDATE
|
|
13
|
+
* RESULT, so the offer is handed over as one instead of teaching each of them a
|
|
14
|
+
* second shape. It is not a code anyone can type: the codes table is the SSOT
|
|
15
|
+
* for what a customer may enter, and this offer is never entered, only accepted.
|
|
16
|
+
*/
|
|
17
|
+
const { resolveWinbackOffer } = require('../../../vendor/config/index.js');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The offer a resolved config makes, framework default applied.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} config - The Manager's resolved config
|
|
23
|
+
* @returns {{ enabled: boolean, percent?: number, amount?: number, duration: string }}
|
|
24
|
+
*/
|
|
25
|
+
function resolveOffer(config) {
|
|
26
|
+
return resolveWinbackOffer(config?.payment);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The offer as a discount-codes validate() result.
|
|
31
|
+
*
|
|
32
|
+
* The synthetic code names the offer for every downstream reader — it is what
|
|
33
|
+
* the providers derive their deterministic coupon id from, so two brands on the
|
|
34
|
+
* same percentage share one coupon and a brand that changes its mind gets a new
|
|
35
|
+
* one instead of silently reusing the old number.
|
|
36
|
+
*
|
|
37
|
+
* The absent shape is OMITTED, never set to undefined: this object is written
|
|
38
|
+
* onto payments-orders/{orderId}, and firebase-admin refuses a document carrying
|
|
39
|
+
* an undefined value (the rule discount-codes.validate() records at length).
|
|
40
|
+
*
|
|
41
|
+
* @param {object} offer - A resolveOffer() result
|
|
42
|
+
* @returns {{ valid: boolean, code: string, percent?: number, amount?: number, duration: string }}
|
|
43
|
+
*/
|
|
44
|
+
function toDiscount(offer) {
|
|
45
|
+
const isAmount = offer.amount > 0;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
valid: true,
|
|
49
|
+
code: isAmount ? `WINBACK${offer.amount}OFF` : `WINBACK${offer.percent}`,
|
|
50
|
+
...(isAmount ? { amount: offer.amount } : { percent: offer.percent }),
|
|
51
|
+
duration: offer.duration,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { resolveOffer, toDiscount };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<identity>
|
|
2
|
+
You extract real human names and company from email addresses.
|
|
3
|
+
</identity>
|
|
4
|
+
|
|
5
|
+
<rules>
|
|
6
|
+
- Only return a name if it is a REAL human name. If the local part contains placeholder text, gibberish, generic words, or fictional/brand names, return empty strings for firstName and lastName.
|
|
7
|
+
- Placeholder/test examples that are NOT real names: firstname.lastname, first.last, asdf.qwerty, test.user, mixed.case, bobs.burgers, john.doe (this is a well-known placeholder)
|
|
8
|
+
- Generic role words are NOT names: admin, info, support, hello, contact, sales, billing, noreply, webmaster, postmaster, dev, ceo
|
|
9
|
+
- Single letters or initials ARE acceptable (e.g., "j" from j@company.com → firstName: "J")
|
|
10
|
+
- ALWAYS infer company from the domain, even when there is no name. Generic email providers (gmail.com, yahoo.com, hotmail.com, outlook.com, aol.com, icloud.com, mail.com, protonmail.com, proton.me, zoho.com, yandex.com, gmx.com, live.com, msn.com, me.com) should return empty company.
|
|
11
|
+
- Hyphenated names should preserve capitalization on both parts (e.g., jean-pierre → Jean-Pierre)
|
|
12
|
+
- Plus-addressing tags are NOT part of the name — ignore everything from "+" to "@" (e.g., sarah.martinez+newsletter@acme.com → treat as sarah.martinez@acme.com). A +tag alone never makes an otherwise-real name a placeholder or test address.
|
|
13
|
+
- confidence should reflect how certain you are that the name is a REAL person's name. Placeholders and gibberish should never have confidence above 0.
|
|
14
|
+
</rules>
|
|
15
|
+
|
|
16
|
+
<format>
|
|
17
|
+
Return ONLY valid JSON:
|
|
18
|
+
{
|
|
19
|
+
"firstName": "...",
|
|
20
|
+
"lastName": "...",
|
|
21
|
+
"company": "...",
|
|
22
|
+
"confidence": "..."
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
- firstName: First name (string), properly capitalized
|
|
26
|
+
- lastName: Last name (string), properly capitalized
|
|
27
|
+
- company: Company name (string), capitalized. Infer from domain (not generic providers).
|
|
28
|
+
- confidence: Confidence level (number), 0-1 scale. How sure you are the name is real.
|
|
29
|
+
|
|
30
|
+
If you cannot determine a real name, use empty strings for firstName and lastName.
|
|
31
|
+
</format>
|
|
32
|
+
|
|
33
|
+
<examples>
|
|
34
|
+
<example>
|
|
35
|
+
<input>john.smith@acme.com</input>
|
|
36
|
+
<output>{"firstName": "John", "lastName": "Smith", "company": "Acme", "confidence": 0.9}</output>
|
|
37
|
+
</example>
|
|
38
|
+
<example>
|
|
39
|
+
<input>jsmith123@gmail.com</input>
|
|
40
|
+
<output>{"firstName": "J", "lastName": "Smith", "company": "", "confidence": 0.4}</output>
|
|
41
|
+
</example>
|
|
42
|
+
<example>
|
|
43
|
+
<input>support@bigcorp.io</input>
|
|
44
|
+
<output>{"firstName": "", "lastName": "", "company": "Bigcorp", "confidence": 0}</output>
|
|
45
|
+
</example>
|
|
46
|
+
<example>
|
|
47
|
+
<input>mary_jane_watson@stark-industries.com</input>
|
|
48
|
+
<output>{"firstName": "Mary", "lastName": "Watson", "company": "Stark Industries", "confidence": 0.85}</output>
|
|
49
|
+
</example>
|
|
50
|
+
<example>
|
|
51
|
+
<input>info@company.org</input>
|
|
52
|
+
<output>{"firstName": "", "lastName": "", "company": "Company", "confidence": 0}</output>
|
|
53
|
+
</example>
|
|
54
|
+
<example>
|
|
55
|
+
<input>firstname.lastname@company.com</input>
|
|
56
|
+
<output>{"firstName": "", "lastName": "", "company": "Company", "confidence": 0}</output>
|
|
57
|
+
</example>
|
|
58
|
+
<example>
|
|
59
|
+
<input>asdf.qwerty@outlook.com</input>
|
|
60
|
+
<output>{"firstName": "", "lastName": "", "company": "", "confidence": 0}</output>
|
|
61
|
+
</example>
|
|
62
|
+
<example>
|
|
63
|
+
<input>jean-pierre.dupont@orange.fr</input>
|
|
64
|
+
<output>{"firstName": "Jean-Pierre", "lastName": "Dupont", "company": "Orange", "confidence": 0.95}</output>
|
|
65
|
+
</example>
|
|
66
|
+
<example>
|
|
67
|
+
<input>bobs.burgers@example.com</input>
|
|
68
|
+
<output>{"firstName": "", "lastName": "", "company": "Example", "confidence": 0}</output>
|
|
69
|
+
</example>
|
|
70
|
+
<example>
|
|
71
|
+
<input>j@company.com</input>
|
|
72
|
+
<output>{"firstName": "J", "lastName": "", "company": "Company", "confidence": 0.3}</output>
|
|
73
|
+
</example>
|
|
74
|
+
<example>
|
|
75
|
+
<input>david.chen+newsletter@globex.com</input>
|
|
76
|
+
<output>{"firstName": "David", "lastName": "Chen", "company": "Globex", "confidence": 0.9}</output>
|
|
77
|
+
</example>
|
|
78
|
+
</examples>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework anti-abuse gate limits (SSOT)
|
|
3
|
+
*
|
|
4
|
+
* These are EXPLICIT limits on the framework's own public routes, never plan
|
|
5
|
+
* features a brand prices in its `features` catalog ([#647](https://github.com/Omega-JS-Stack/omega/issues/647)).
|
|
6
|
+
* The per-IP signup cap is the one gate a brand tunes, so it keeps its own
|
|
7
|
+
* config key (`targets.backend.auth.signup.maxPerIpPerDay`) instead of a
|
|
8
|
+
* constant here.
|
|
9
|
+
*
|
|
10
|
+
* Used by:
|
|
11
|
+
* - routes/marketing/contact/post.js (per-IP subscribe gate)
|
|
12
|
+
* - routes/marketing/email-preferences/post.js (per-user and per-IP toggle gate)
|
|
13
|
+
*/
|
|
14
|
+
module.exports = {
|
|
15
|
+
// How many marketing-form calls one caller may make in a counting period
|
|
16
|
+
MARKETING_RATE_LIMIT: 5,
|
|
17
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const fetch = require('wonderful-fetch');
|
|
2
|
+
const env = require('./env.js');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Print Google's verdict for a REJECTED token — never the token, never the secret.
|
|
6
|
+
*
|
|
7
|
+
* A rejection turns into a 403 the caller cannot explain on its own: wrong
|
|
8
|
+
* secret, wrong domain, low score and expired token all look identical
|
|
9
|
+
* downstream. This is the one line that names the reason.
|
|
10
|
+
*
|
|
11
|
+
* @param {object} data - The siteverify response
|
|
12
|
+
*/
|
|
13
|
+
function logRejection(data) {
|
|
14
|
+
const codes = (data['error-codes'] || []).join(',') || 'none';
|
|
15
|
+
|
|
16
|
+
console.warn(`[@omega.js/backend:recaptcha] verify() rejected: error-codes=${codes} score=${data.score ?? 'none'} action=${data.action || 'none'} hostname=${data.hostname || 'none'}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Verify a Google reCAPTCHA token
|
|
21
|
+
* @param {string} token - The reCAPTCHA response token
|
|
22
|
+
* @param {object} [options] - Options
|
|
23
|
+
* @param {number} [options.minScore=0.5] - Minimum score threshold (v3)
|
|
24
|
+
* @returns {Promise<boolean>} Whether the token is valid
|
|
25
|
+
*/
|
|
26
|
+
async function verify(token, options) {
|
|
27
|
+
const minScore = options?.minScore || 0.5;
|
|
28
|
+
|
|
29
|
+
if (!env.has('RECAPTCHA_SECRET_KEY')) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!token) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const data = await fetch('https://www.google.com/recaptcha/api/siteverify', {
|
|
39
|
+
method: 'post',
|
|
40
|
+
response: 'json',
|
|
41
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
42
|
+
body: `secret=${env.get('RECAPTCHA_SECRET_KEY')}&response=${token}`,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const passed = data.success && (data.score === undefined || data.score >= minScore);
|
|
46
|
+
|
|
47
|
+
if (!passed) {
|
|
48
|
+
logRejection(data);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return passed;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error('reCAPTCHA verification error:', e);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = { verify };
|