@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,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: the notification subscribe/unsubscribe events are CANONICAL conversions
|
|
3
|
+
* ([#328](https://github.com/Omega-JS-Stack/omega/issues/328)).
|
|
4
|
+
*
|
|
5
|
+
* The handler used to reach `Manager.Analytics(...).event()` directly with
|
|
6
|
+
* hyphenated names of its own invention — `notification-subscribe` and
|
|
7
|
+
* `notification-unsubscribe`, which appear in no catalog and therefore in no
|
|
8
|
+
* other surface's vocabulary. Both now go through `deliverConversion`, which is
|
|
9
|
+
* what gives them the three things the raw call had none of: the catalog's
|
|
10
|
+
* name, the consent gate, and the per-provider walk (GA4 only, by catalog
|
|
11
|
+
* design — no ad platform maps a push subscription).
|
|
12
|
+
*
|
|
13
|
+
* THE DEDUPE ID IS `<event>.<token>`. The doc id IS the push token, and it is
|
|
14
|
+
* the only stable key this doc has: `owner` is null on an anonymous subscribe,
|
|
15
|
+
* so a uid-derived id would collapse every anonymous device onto one id.
|
|
16
|
+
*
|
|
17
|
+
* Real handler, real Manager, real ctx, real Firestore counter write. The
|
|
18
|
+
* `change` pair is built by hand — the trigger's own shape — so no notification
|
|
19
|
+
* doc has to exist for the branch under test.
|
|
20
|
+
*
|
|
21
|
+
* Run: npx omega test framework:events/notification-conversion
|
|
22
|
+
*/
|
|
23
|
+
const onWrite = require('../../dist/manager/events/firestore/notifications/on-write.js');
|
|
24
|
+
const defineCases = require('../../dist/vendor/devkit/test/define-cases.js');
|
|
25
|
+
|
|
26
|
+
const TOKEN = '_test-notification-conversion-token';
|
|
27
|
+
|
|
28
|
+
const EVENT_CONTEXT = {
|
|
29
|
+
resource: { service: 'firestore.googleapis.com' },
|
|
30
|
+
params: { token: TOKEN },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// A subscription doc in the shape the client writes it.
|
|
34
|
+
function subscriptionDoc({ owner = null, attribution } = {}) {
|
|
35
|
+
return {
|
|
36
|
+
token: TOKEN,
|
|
37
|
+
owner: owner,
|
|
38
|
+
tags: ['general'],
|
|
39
|
+
attribution: attribution,
|
|
40
|
+
context: { client: {} },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The Change pair the Firestore trigger hands the handler. */
|
|
45
|
+
function change({ before, after }) {
|
|
46
|
+
return {
|
|
47
|
+
before: { data: () => before },
|
|
48
|
+
after: { data: () => after },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Record every console call the handler makes, restoring console afterward.
|
|
53
|
+
async function withConsoleRecorder(fn) {
|
|
54
|
+
const calls = { log: [], debug: [], error: [] };
|
|
55
|
+
const original = { log: console.log, debug: console.debug, error: console.error };
|
|
56
|
+
|
|
57
|
+
console.log = (...args) => calls.log.push(args);
|
|
58
|
+
console.debug = (...args) => calls.debug.push(args);
|
|
59
|
+
console.error = (...args) => calls.error.push(args);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await fn();
|
|
63
|
+
return calls;
|
|
64
|
+
} finally {
|
|
65
|
+
console.log = original.log;
|
|
66
|
+
console.debug = original.debug;
|
|
67
|
+
console.error = original.error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Run the real handler for one change pair; hand back its delivery lines. */
|
|
72
|
+
async function runHandler({ Manager, before, after }) {
|
|
73
|
+
const ctx = Manager.RouteContext({}, { functionName: 'omega_notificationsOnWrite' });
|
|
74
|
+
const admin = Manager.libraries.admin;
|
|
75
|
+
|
|
76
|
+
const calls = await withConsoleRecorder(async () => {
|
|
77
|
+
await onWrite({
|
|
78
|
+
Manager: Manager,
|
|
79
|
+
ctx: ctx,
|
|
80
|
+
change: change({ before: before, after: after }),
|
|
81
|
+
context: EVENT_CONTEXT,
|
|
82
|
+
libraries: { admin: admin },
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const delivery = calls.log
|
|
87
|
+
.map((args) => String(args[1]))
|
|
88
|
+
.filter((line) => line.startsWith('deliverConversion: '));
|
|
89
|
+
|
|
90
|
+
return { calls: calls, delivery: delivery };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = defineCases({
|
|
94
|
+
description: 'notifications:on-write fires canonical notification conversions',
|
|
95
|
+
type: 'group',
|
|
96
|
+
timeout: 30000,
|
|
97
|
+
|
|
98
|
+
tests: [
|
|
99
|
+
{
|
|
100
|
+
name: 'a-new-subscription-fires-the-canonical-notification-subscribe',
|
|
101
|
+
async run({ assert, Manager }) {
|
|
102
|
+
const { delivery } = await runHandler({
|
|
103
|
+
Manager: Manager,
|
|
104
|
+
before: undefined,
|
|
105
|
+
after: subscriptionDoc({ owner: '_test-notification-owner' }),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
assert.equal(delivery.length, 1, `expected one conversion delivery, got ${delivery.length}: ${delivery.join(' | ')}`);
|
|
109
|
+
assert.equal(delivery[0].startsWith('deliverConversion: notification_subscribe →'), true, `the canonical catalog name, not the hyphenated invention: ${delivery[0]}`);
|
|
110
|
+
assert.equal(delivery[0].includes(`(event_id=notification_subscribe.${TOKEN})`), true, `the token is the stable per-doc key: ${delivery[0]}`);
|
|
111
|
+
|
|
112
|
+
// GA4 only — no ad platform maps a push subscription, and an unmapped
|
|
113
|
+
// provider is a decision the catalog makes, not an event to invent.
|
|
114
|
+
for (const provider of ['meta', 'tiktok']) {
|
|
115
|
+
assert.equal(delivery[0].includes(`${provider} skipped (no mapping)`), true, `${provider} has no mapping for this event: ${delivery[0]}`);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
{
|
|
121
|
+
name: 'a-deleted-subscription-fires-the-canonical-notification-unsubscribe',
|
|
122
|
+
async run({ assert, Manager }) {
|
|
123
|
+
const { delivery } = await runHandler({
|
|
124
|
+
Manager: Manager,
|
|
125
|
+
before: subscriptionDoc({ owner: '_test-notification-owner' }),
|
|
126
|
+
after: undefined,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
assert.equal(delivery.length, 1, `expected one conversion delivery, got ${delivery.length}: ${delivery.join(' | ')}`);
|
|
130
|
+
assert.equal(delivery[0].startsWith('deliverConversion: notification_unsubscribe →'), true, `the canonical catalog name: ${delivery[0]}`);
|
|
131
|
+
assert.equal(delivery[0].includes(`(event_id=notification_unsubscribe.${TOKEN})`), true, `the token keys the unsubscribe too: ${delivery[0]}`);
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
{
|
|
136
|
+
name: 'an-update-fires-nothing',
|
|
137
|
+
async run({ assert, Manager }) {
|
|
138
|
+
// Re-tagging a device is not a subscription event. The handler returns
|
|
139
|
+
// at its update branch, before any tracking.
|
|
140
|
+
const { delivery } = await runHandler({
|
|
141
|
+
Manager: Manager,
|
|
142
|
+
before: subscriptionDoc(),
|
|
143
|
+
after: subscriptionDoc({ owner: '_test-notification-owner' }),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
assert.equal(delivery.length, 0, `an update must fire no conversion: ${delivery.join(' | ')}`);
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
{
|
|
151
|
+
name: 'an-anonymous-subscribe-still-fires-and-still-keys-on-the-token',
|
|
152
|
+
async run({ assert, Manager }) {
|
|
153
|
+
// `owner: null` is the anonymous-subscribe shape the rules explicitly
|
|
154
|
+
// allow. There is no uid to key on and no identity to match — which is
|
|
155
|
+
// exactly why the doc id is the id.
|
|
156
|
+
const { delivery } = await runHandler({
|
|
157
|
+
Manager: Manager,
|
|
158
|
+
before: undefined,
|
|
159
|
+
after: subscriptionDoc({ owner: null }),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
assert.equal(delivery.length, 1, `an anonymous device is still a subscription: ${delivery.join(' | ')}`);
|
|
163
|
+
assert.equal(delivery[0].includes(`(event_id=notification_subscribe.${TOKEN})`), true, delivery[0]);
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
{
|
|
168
|
+
name: 'a-declined-analytics-snapshot-blocks-the-fire',
|
|
169
|
+
async run({ assert, Manager }) {
|
|
170
|
+
// The gate is the whole point of routing through deliverConversion: a
|
|
171
|
+
// raw Manager.Analytics call asked nobody anything.
|
|
172
|
+
const doc = subscriptionDoc({ owner: '_test-notification-owner' });
|
|
173
|
+
doc.trackingConsent = { analytics: false, marketing: false, region: 'opt-in', version: 1 };
|
|
174
|
+
|
|
175
|
+
const { delivery } = await runHandler({ Manager: Manager, before: undefined, after: doc });
|
|
176
|
+
|
|
177
|
+
assert.equal(delivery.length, 1, delivery.join(' | '));
|
|
178
|
+
assert.equal(delivery[0].includes('ga4 skipped (consent: analytics)'), true, `an opted-out device reaches no platform: ${delivery[0]}`);
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
});
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared harness for the PLAIN-NODE webhook-pipeline suites (no emulator, no
|
|
3
|
+
* network): the real payments-webhooks trigger run against a minimal in-memory
|
|
4
|
+
* Firestore stand-in.
|
|
5
|
+
*
|
|
6
|
+
* The stand-in is the honest layer for these cases. The emulator cannot produce
|
|
7
|
+
* a mid-batch write fault at all (the admin SDK bypasses rules, every write is
|
|
8
|
+
* legal), and it cannot hand one test a user doc seeded into an exact prior
|
|
9
|
+
* state without minting a persona and a payment history per permutation. The
|
|
10
|
+
* emulator suites stay the integration surface for the happy paths.
|
|
11
|
+
*
|
|
12
|
+
* `_`-prefixed, so the runner never discovers it as a suite.
|
|
13
|
+
*/
|
|
14
|
+
const onWrite = require('../../../dist/manager/events/firestore/payments-webhooks/on-write.js');
|
|
15
|
+
|
|
16
|
+
// A contended transaction re-runs; a stand-in that re-ran forever would hang a suite
|
|
17
|
+
// instead of failing it. Firestore's own client gives up too.
|
|
18
|
+
const MAX_TRANSACTION_ATTEMPTS = 5;
|
|
19
|
+
|
|
20
|
+
// The brand config the transformers read products out of
|
|
21
|
+
const CONFIG = {
|
|
22
|
+
payment: {
|
|
23
|
+
products: [
|
|
24
|
+
{ id: 'basic', name: 'Basic', type: 'subscription' },
|
|
25
|
+
{ id: 'premium', name: 'Premium', type: 'subscription', prices: { monthly: 4.99 }, stripe: { productId: '_test_premium' } },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Minimal in-memory Firestore stand-in: the doc reads/writes, the collection query
|
|
32
|
+
* the test provider's fetchResource() makes, and the write batch. `failPath` is the
|
|
33
|
+
* document path whose write rejects — mid-batch in the real world, before anything
|
|
34
|
+
* lands once the writes are batched.
|
|
35
|
+
*
|
|
36
|
+
* `authUids` is the project's auth store: the pipeline asks it whether a uid is one
|
|
37
|
+
* of ours before it will create a user doc ([#399]).
|
|
38
|
+
*
|
|
39
|
+
* @param {object} options
|
|
40
|
+
* @param {object} options.seed - Document path → data, the state the run starts from
|
|
41
|
+
* @param {string|function|null} options.failPath - The document path whose write rejects, or a
|
|
42
|
+
* `(path, data) => boolean` predicate for a fault that depends on WHICH write it is
|
|
43
|
+
* (the refusal stamp and the failure stamp land on the same doc — [#535])
|
|
44
|
+
* @param {string[]} options.authUids - The uids that have a Firebase auth user
|
|
45
|
+
* @param {function|null} options.onRead - Called with (path, { store, write }) the moment
|
|
46
|
+
* ANY read of a document resolves, transactional or not — the seam a suite writes
|
|
47
|
+
* THROUGH, to put a contending write exactly in the window between a read and the
|
|
48
|
+
* write that acts on it. Deliberately not transaction-only: a suite proving a
|
|
49
|
+
* read-then-write race must be able to reproduce the race against the racy shape too
|
|
50
|
+
* @returns {{ admin: object, store: Map }}
|
|
51
|
+
*/
|
|
52
|
+
function buildAdmin({ seed = {}, failPath = null, authUids = [], onRead = null } = {}) {
|
|
53
|
+
const store = new Map(Object.entries(seed));
|
|
54
|
+
const shouldFail = typeof failPath === 'function' ? failPath : (path) => path === failPath;
|
|
55
|
+
|
|
56
|
+
// Per-document write counter — the stand-in's version stamp, so a transaction can
|
|
57
|
+
// tell "nobody touched this since I read it" from "somebody did"
|
|
58
|
+
const versions = new Map();
|
|
59
|
+
|
|
60
|
+
const write = (path, data, options) => {
|
|
61
|
+
if (shouldFail(path, data)) {
|
|
62
|
+
throw new Error(`Firestore write to ${path} failed`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
store.set(path, options?.merge ? merge(store.get(path) || {}, data) : data);
|
|
66
|
+
versions.set(path, (versions.get(path) || 0) + 1);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// A read is a POINT-IN-TIME snapshot, captured before the seam below can move the
|
|
70
|
+
// store — anything else would hand a racy read-then-write the winner's data and
|
|
71
|
+
// hide the very race a suite is trying to reproduce.
|
|
72
|
+
const read = async (path) => {
|
|
73
|
+
const captured = store.get(path);
|
|
74
|
+
const snapshot = { exists: store.has(path), data: () => captured };
|
|
75
|
+
|
|
76
|
+
if (onRead) {
|
|
77
|
+
await onRead(path, { store, write });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return snapshot;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const doc = (path) => ({
|
|
84
|
+
path,
|
|
85
|
+
get: async () => read(path),
|
|
86
|
+
set: async (data, options) => write(path, data, options),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const query = (collection, filters) => ({
|
|
90
|
+
where: (field, op, value) => query(collection, [...filters, { field, op, value }]),
|
|
91
|
+
limit: () => query(collection, filters),
|
|
92
|
+
get: async () => {
|
|
93
|
+
const paths = [...store.keys()]
|
|
94
|
+
.filter(path => path.startsWith(`${collection}/`))
|
|
95
|
+
.filter(path => filters.every(f => matches(fieldValue(store.get(path), f.field), f.op, f.value)));
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
empty: paths.length === 0,
|
|
99
|
+
size: paths.length,
|
|
100
|
+
docs: paths.map(path => ({
|
|
101
|
+
id: path.split('/').pop(),
|
|
102
|
+
ref: doc(path),
|
|
103
|
+
data: () => store.get(path),
|
|
104
|
+
})),
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const admin = {
|
|
110
|
+
auth: () => ({
|
|
111
|
+
getUser: async (uid) => {
|
|
112
|
+
if (!authUids.includes(uid)) {
|
|
113
|
+
// The admin SDK's own not-found shape — the code branches on the code
|
|
114
|
+
const error = new Error(`There is no user record corresponding to the provided identifier.`);
|
|
115
|
+
error.code = 'auth/user-not-found';
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return { uid: uid };
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
firestore: () => ({
|
|
123
|
+
doc,
|
|
124
|
+
collection: (name) => query(name, []),
|
|
125
|
+
batch: () => {
|
|
126
|
+
const staged = [];
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
set: (ref, data, options) => staged.push([ref.path, data, options]),
|
|
130
|
+
commit: async () => {
|
|
131
|
+
// A real batch is atomic: one rejected write means none of them landed
|
|
132
|
+
for (const [path, data] of staged) {
|
|
133
|
+
if (shouldFail(path, data)) {
|
|
134
|
+
throw new Error(`Firestore batch write to ${path} failed`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
staged.forEach(args => write(...args));
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
runTransaction: async (body) => {
|
|
143
|
+
// Firestore's actual contract, which is the whole point of the caller
|
|
144
|
+
// using one: reads are versioned, writes are staged, and if any document
|
|
145
|
+
// the block READ changed before the commit, the block RE-RUNS against the
|
|
146
|
+
// new state. Modelled here rather than assumed — a guard-then-write that
|
|
147
|
+
// is only atomic because nothing raced it proves nothing.
|
|
148
|
+
for (let attempt = 0; attempt < MAX_TRANSACTION_ATTEMPTS; attempt++) {
|
|
149
|
+
const versionsRead = new Map();
|
|
150
|
+
const staged = [];
|
|
151
|
+
|
|
152
|
+
const result = await body({
|
|
153
|
+
get: async (ref) => {
|
|
154
|
+
versionsRead.set(ref.path, versions.get(ref.path) || 0);
|
|
155
|
+
return read(ref.path);
|
|
156
|
+
},
|
|
157
|
+
set: (ref, data, options) => staged.push([ref.path, data, options]),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const contended = [...versionsRead].some(([path, version]) => (versions.get(path) || 0) !== version);
|
|
161
|
+
|
|
162
|
+
if (contended) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
staged.forEach(args => write(...args));
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
throw new Error('Firestore transaction failed after too many contended attempts');
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return { admin, store };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Firestore addresses nested fields with a dotted path — `subscription.status` */
|
|
180
|
+
function fieldValue(data, field) {
|
|
181
|
+
return field.split('.').reduce((node, key) => (node == null ? undefined : node[key]), data);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** The query operators the suites here filter on */
|
|
185
|
+
function matches(value, op, expected) {
|
|
186
|
+
if (op === '>=') { return value >= expected; }
|
|
187
|
+
if (op === '<=') { return value <= expected; }
|
|
188
|
+
if (op === '>') { return value > expected; }
|
|
189
|
+
if (op === '<') { return value < expected; }
|
|
190
|
+
|
|
191
|
+
return value === expected;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Deep-merge for the stand-in's `{ merge: true }` writes (metadata nests one level) */
|
|
195
|
+
function merge(existing, data) {
|
|
196
|
+
const result = { ...existing };
|
|
197
|
+
|
|
198
|
+
for (const [key, value] of Object.entries(data)) {
|
|
199
|
+
result[key] = value && typeof value === 'object' && !Array.isArray(value)
|
|
200
|
+
? merge(existing[key] || {}, value)
|
|
201
|
+
: value;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* A Stripe-shaped active subscription — the test provider's payload shape
|
|
209
|
+
*
|
|
210
|
+
* @param {object} options - uid, orderId, resourceId
|
|
211
|
+
* @returns {object}
|
|
212
|
+
*/
|
|
213
|
+
function subscriptionPayload({ uid, orderId, resourceId }) {
|
|
214
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
id: resourceId,
|
|
218
|
+
object: 'subscription',
|
|
219
|
+
status: 'active',
|
|
220
|
+
metadata: { uid: uid, orderId: orderId },
|
|
221
|
+
cancel_at_period_end: false,
|
|
222
|
+
current_period_start: nowUNIX,
|
|
223
|
+
current_period_end: nowUNIX + 86400,
|
|
224
|
+
start_date: nowUNIX,
|
|
225
|
+
plan: { product: '_test_premium', interval: 'month' },
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Run the real trigger over a pending webhook doc against the stand-in
|
|
231
|
+
*
|
|
232
|
+
* @param {object} options
|
|
233
|
+
* @param {string} options.uid - The subscriber the event belongs to
|
|
234
|
+
* @param {string} options.orderId - The order the event writes
|
|
235
|
+
* @param {string} options.resourceId - The subscription the event is about
|
|
236
|
+
* @param {string} options.eventId - The webhook doc id
|
|
237
|
+
* @param {string} options.eventType - The provider's event name
|
|
238
|
+
* @param {string} options.resourceType - The parsed event's resource type (a subscription-category event can ride an invoice or sale resource)
|
|
239
|
+
* @param {string} options.category - The parsed event's category ('subscription' | 'one-time')
|
|
240
|
+
* @param {object|null} options.payload - The resource the webhook envelope carries (defaults to an active subscription)
|
|
241
|
+
* @param {object|null} options.raw - The whole envelope, for a provider that nests its resource
|
|
242
|
+
* somewhere other than Stripe's `data.object` (PayPal `resource`, Chargebee `content.<type>`)
|
|
243
|
+
* @param {string|null} options.refundId - The refund's own id, as the parser threads it ([#510])
|
|
244
|
+
* @param {object} options.seed - Extra documents the run starts from
|
|
245
|
+
* @param {string|function|null} options.failPath - The document path whose write rejects, or a
|
|
246
|
+
* `(path, data) => boolean` predicate
|
|
247
|
+
* @param {string[]} [options.authUids] - The uids that have a Firebase auth user (default: the subscriber, as every real one does)
|
|
248
|
+
* @param {boolean} [options.reporting] - Whether a Sentry handle is configured at all (false = no DSN, `libraries.sentry` is null)
|
|
249
|
+
* @param {string} [options.provider] - The provider library the event loads (default: the test provider; a real one lets a suite stub its API at the transport boundary)
|
|
250
|
+
* @param {number|null} [options.receivedUNIX] - The second the event ARRIVED (`metadata.created`), which is the staleness clock the pipeline compares against the order
|
|
251
|
+
* @param {boolean} [options.previouslyCompleted] - Whether this doc already completed once (a redelivery, or the retry sweep re-flipping it)
|
|
252
|
+
* @returns {Promise<{ store: Map, logs: string[], captures: object[] }>}
|
|
253
|
+
*/
|
|
254
|
+
async function runTrigger({ uid, orderId, resourceId, eventId, eventType = 'customer.subscription.updated', resourceType = 'subscription', category = 'subscription', payload = null, raw = null, refundId = null, seed = {}, failPath = null, authUids = null, reporting = true, provider = 'test', receivedUNIX = null, previouslyCompleted = false } = {}) {
|
|
255
|
+
const resource = payload || subscriptionPayload({ uid, orderId, resourceId });
|
|
256
|
+
const envelope = raw || { id: eventId, type: eventType, data: { object: resource } };
|
|
257
|
+
const webhookDoc = {
|
|
258
|
+
id: eventId,
|
|
259
|
+
provider: provider,
|
|
260
|
+
status: 'pending',
|
|
261
|
+
raw: envelope,
|
|
262
|
+
owner: uid,
|
|
263
|
+
event: { type: eventType, category: category, resourceType: resourceType, resourceId: resourceId, refundId: refundId },
|
|
264
|
+
metadata: { created: { timestampUNIX: receivedUNIX || Math.floor(Date.now() / 1000) } },
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const { admin, store } = buildAdmin({
|
|
268
|
+
seed: { [`payments-webhooks/${eventId}`]: webhookDoc, ...seed },
|
|
269
|
+
failPath: failPath,
|
|
270
|
+
authUids: authUids || [uid],
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const logs = [];
|
|
274
|
+
|
|
275
|
+
// The error reporter is an external SINK, recorded rather than run — the same
|
|
276
|
+
// treatment the route harness gives `res`. `libraries.sentry` IS the backend's
|
|
277
|
+
// one capture handle (helpers/context/respond.js reads exactly this), and it is
|
|
278
|
+
// null whenever no DSN is configured, which `reporting: false` reproduces.
|
|
279
|
+
const captures = [];
|
|
280
|
+
const sentry = reporting
|
|
281
|
+
? { captureMessage: (message, context) => captures.push({ message, ...context }) }
|
|
282
|
+
: null;
|
|
283
|
+
|
|
284
|
+
const Manager = { config: CONFIG, libraries: { admin, sentry } };
|
|
285
|
+
const ctx = {
|
|
286
|
+
Manager,
|
|
287
|
+
isTesting: () => true,
|
|
288
|
+
log: (...args) => logs.push(args.join(' ')),
|
|
289
|
+
warn: (...args) => logs.push(args.join(' ')),
|
|
290
|
+
error: (...args) => logs.push(args.join(' ')),
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// `before` is what the trigger reads to decide a doc is being REPROCESSED — a
|
|
294
|
+
// redelivery, or the retry sweep putting a failed doc back to pending. Same doc
|
|
295
|
+
// by default (no prior completion), the completed shape when a suite asks.
|
|
296
|
+
const before = previouslyCompleted ? { ...webhookDoc, status: 'completed' } : webhookDoc;
|
|
297
|
+
|
|
298
|
+
await onWrite({
|
|
299
|
+
ctx,
|
|
300
|
+
change: { before: { data: () => before }, after: { data: () => webhookDoc } },
|
|
301
|
+
context: { params: { eventId: eventId } },
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
return { store, logs, captures };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
module.exports = { CONFIG, buildAdmin, merge, subscriptionPayload, runTrigger };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: a cart with checkout activity inside its window is not abandoned
|
|
3
|
+
* ([#655](https://github.com/Omega-JS-Stack/omega/issues/655)).
|
|
4
|
+
*
|
|
5
|
+
* Seen in the playground logs: the sweep mailed "Complete your … checkout" at
|
|
6
|
+
* 01:50:28Z, the intent POST followed at 01:52:54Z and the purchase completed at
|
|
7
|
+
* 01:53:35Z. The cart's reminder clock was set ONCE, when the checkout page
|
|
8
|
+
* opened, and nothing ever moved it — so a shopper still working through the
|
|
9
|
+
* checkout was nudged about the cart they were paying for.
|
|
10
|
+
*
|
|
11
|
+
* The signal is the intent route's own: asking for a provider session is the
|
|
12
|
+
* loudest "I am buying this right now" the backend ever hears, and it stamps
|
|
13
|
+
* `lastActivityAt` on the cart. The sweep restarts the current reminder's clock
|
|
14
|
+
* from that touch instead of mailing.
|
|
15
|
+
*
|
|
16
|
+
* Plain-node: the real cron against the webhook suites' in-memory Firestore
|
|
17
|
+
* stand-in, with the email library RECORDED (it is an external sink).
|
|
18
|
+
*
|
|
19
|
+
* Run: npx omega test backend:events/payments/abandoned-cart-activity
|
|
20
|
+
*/
|
|
21
|
+
const sweep = require('../../../dist/manager/events/cron/frequent/abandoned-carts.js');
|
|
22
|
+
const { REMINDER_DELAYS, COLLECTION } = require('../../../dist/manager/libraries/abandoned-cart-config.js');
|
|
23
|
+
const { buildAdmin, CONFIG } = require('./_webhook-harness.js');
|
|
24
|
+
const defineCases = require('../../../dist/vendor/devkit/test/define-cases.js');
|
|
25
|
+
|
|
26
|
+
const UID = '_test-abandoned-cart-activity-uid';
|
|
27
|
+
|
|
28
|
+
/** A pending cart whose first reminder is due right now */
|
|
29
|
+
function dueCart(extra) {
|
|
30
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
id: UID,
|
|
34
|
+
owner: UID,
|
|
35
|
+
status: 'pending',
|
|
36
|
+
productId: 'premium',
|
|
37
|
+
type: 'subscription',
|
|
38
|
+
frequency: 'monthly',
|
|
39
|
+
reminderIndex: 0,
|
|
40
|
+
nextReminderAt: nowUNIX - 5,
|
|
41
|
+
...(extra || {}),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Run the real sweep over one seeded cart
|
|
47
|
+
*
|
|
48
|
+
* @param {object} cart - The payments-carts document
|
|
49
|
+
* @returns {Promise<{ store: Map, logs: string[], sent: object[] }>}
|
|
50
|
+
*/
|
|
51
|
+
async function runSweep(cart) {
|
|
52
|
+
const { admin, store } = buildAdmin({
|
|
53
|
+
seed: {
|
|
54
|
+
[`${COLLECTION}/${UID}`]: cart,
|
|
55
|
+
[`users/${UID}`]: { auth: { uid: UID, email: 'shopper@test.dev' }, subscription: { product: { id: 'basic' }, status: 'active' } },
|
|
56
|
+
},
|
|
57
|
+
authUids: [UID],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const logs = [];
|
|
61
|
+
const sent = [];
|
|
62
|
+
const Manager = {
|
|
63
|
+
config: { ...CONFIG, brand: { name: 'Test Brand' } },
|
|
64
|
+
project: { websiteUrl: 'https://test.dev' },
|
|
65
|
+
libraries: { admin },
|
|
66
|
+
Email: () => ({ send: async (payload) => { sent.push(payload); return { status: 'sent' }; } }),
|
|
67
|
+
};
|
|
68
|
+
const ctx = {
|
|
69
|
+
Manager,
|
|
70
|
+
isTesting: () => true,
|
|
71
|
+
log: (...args) => logs.push(args.join(' ')),
|
|
72
|
+
warn: (...args) => logs.push(args.join(' ')),
|
|
73
|
+
error: (...args) => logs.push(args.join(' ')),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
await sweep({ Manager, ctx, context: {}, libraries: { admin } });
|
|
77
|
+
|
|
78
|
+
return { store, logs, sent };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = defineCases({
|
|
82
|
+
description: 'Abandoned-cart sweep: checkout activity inside the window defers the reminder',
|
|
83
|
+
type: 'group',
|
|
84
|
+
timeout: 15000,
|
|
85
|
+
|
|
86
|
+
tests: [
|
|
87
|
+
{
|
|
88
|
+
name: 'a-cart-whose-checkout-just-started-is-never-mailed',
|
|
89
|
+
async run({ assert }) {
|
|
90
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
91
|
+
|
|
92
|
+
// The shopper asked for a session a minute ago and is at the provider's
|
|
93
|
+
// page right now — which is exactly the state that got mailed.
|
|
94
|
+
const { store, sent, logs } = await runSweep(dueCart({ lastActivityAt: nowUNIX - 60 }));
|
|
95
|
+
|
|
96
|
+
assert.equal(sent.length, 0, `A shopper mid-checkout owes no nudge, got ${sent.length}: ${logs.join(' | ')}`);
|
|
97
|
+
|
|
98
|
+
const cart = store.get(`${COLLECTION}/${UID}`);
|
|
99
|
+
|
|
100
|
+
assert.equal(cart.status, 'pending', 'The cart is still open — deferring is not completing it');
|
|
101
|
+
assert.equal(cart.reminderIndex, 0, 'And it did not spend a reminder it never sent');
|
|
102
|
+
assert.equal(
|
|
103
|
+
cart.nextReminderAt,
|
|
104
|
+
(nowUNIX - 60) + REMINDER_DELAYS[0],
|
|
105
|
+
'The reminder clock restarts from the activity, so the same window is measured from the last touch',
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
name: 'a-cart-whose-activity-has-gone-quiet-is-still-mailed',
|
|
112
|
+
async run({ assert }) {
|
|
113
|
+
const nowUNIX = Math.floor(Date.now() / 1000);
|
|
114
|
+
|
|
115
|
+
// A checkout started and went nowhere: past the window, this IS the
|
|
116
|
+
// abandonment the sweep exists for.
|
|
117
|
+
const { sent } = await runSweep(dueCart({ lastActivityAt: nowUNIX - REMINDER_DELAYS[0] - 60 }));
|
|
118
|
+
|
|
119
|
+
assert.equal(sent.length, 1, `A cart quiet longer than the window is abandoned, got ${sent.length}`);
|
|
120
|
+
assert.equal(sent[0].data.content.event, 'abandoned-cart', 'And it is the abandoned-cart mail that goes out');
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
{
|
|
125
|
+
name: 'a-cart-that-never-reached-a-checkout-is-mailed-as-before',
|
|
126
|
+
async run({ assert }) {
|
|
127
|
+
// Every cart written before this stamp existed carries no activity at
|
|
128
|
+
// all — the sweep must read that as "nothing happened", not as "just now"
|
|
129
|
+
const { sent } = await runSweep(dueCart());
|
|
130
|
+
|
|
131
|
+
assert.equal(sent.length, 1, `An untouched cart is the ordinary abandoned one, got ${sent.length}`);
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
});
|