@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,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reset usage cron job
|
|
3
|
+
*
|
|
4
|
+
* Runs daily at midnight UTC and handles different reset schedules:
|
|
5
|
+
* - Local storage: cleared every day
|
|
6
|
+
* - Unauthenticated usage collection: deleted every day
|
|
7
|
+
* - Authenticated user daily counters: reset every day
|
|
8
|
+
* - Authenticated user monthly counters: reset on the 1st of each month
|
|
9
|
+
* - Per-user overrides (`usage.overrides`): never touched — an admin granted
|
|
10
|
+
* those credits and a reset is not a revoke ([#647](https://github.com/Omega-JS-Stack/omega/issues/647))
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// The features contract, shared with the gate — see helpers/usage.js for why
|
|
14
|
+
// this resolves two ways
|
|
15
|
+
let account;
|
|
16
|
+
try {
|
|
17
|
+
account = require('../../../../vendor/account/features.js');
|
|
18
|
+
} catch (e) {
|
|
19
|
+
account = require('../../../../../dist/vendor/account/features.js');
|
|
20
|
+
}
|
|
21
|
+
const { isCountedFeature } = account;
|
|
22
|
+
|
|
23
|
+
// The key under `usage` that is NOT a counter: a map of admin-granted limits.
|
|
24
|
+
// Named rather than shape-tested, because a brand feature could legitimately be
|
|
25
|
+
// called anything and the shape test below is what protects the rest.
|
|
26
|
+
const OVERRIDES_KEY = 'overrides';
|
|
27
|
+
|
|
28
|
+
// Counters that live on a USER doc with no catalog entry: the framework's own
|
|
29
|
+
// anti-abuse gates, which pass consume() an explicit limit because they are
|
|
30
|
+
// security controls rather than plan features. Only the ids that reach a user
|
|
31
|
+
// document belong here — an anonymous-keyed counter (signups, the public
|
|
32
|
+
// marketing subscribe lane) lives in the `usage` collection this cron deletes
|
|
33
|
+
// wholesale.
|
|
34
|
+
const FRAMEWORK_COUNTERS = ['email-preferences'];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Is this value a usage COUNTER block rather than something else stored beside
|
|
38
|
+
* one? The shape is what answers: the counters `consume()` writes.
|
|
39
|
+
* @param {*} value - a value under the user doc's `usage` key
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function isCounterBlock(value) {
|
|
43
|
+
return !!value
|
|
44
|
+
&& typeof value === 'object'
|
|
45
|
+
&& !Array.isArray(value)
|
|
46
|
+
&& (typeof value.daily === 'number' || typeof value.monthly === 'number');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = async ({ Manager, ctx, context, libraries }) => {
|
|
50
|
+
const storage = Manager.storage({ name: 'usage', temporary: true, clear: false, log: false });
|
|
51
|
+
|
|
52
|
+
ctx.log('Starting...');
|
|
53
|
+
|
|
54
|
+
// Clear local storage (daily)
|
|
55
|
+
clearLocal(ctx, storage);
|
|
56
|
+
|
|
57
|
+
// Clear unauthenticated usage collection (daily)
|
|
58
|
+
await clearUnauthenticatedUsage(ctx, libraries);
|
|
59
|
+
|
|
60
|
+
// Reset authenticated user counters (daily + monthly on 1st)
|
|
61
|
+
await resetAuthenticated(Manager, ctx);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function clearLocal(ctx, storage) {
|
|
65
|
+
ctx.log('local: Clearing...');
|
|
66
|
+
storage.setState({}).write();
|
|
67
|
+
ctx.log('local: Completed!');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function clearUnauthenticatedUsage(ctx, libraries) {
|
|
71
|
+
const { admin } = libraries;
|
|
72
|
+
|
|
73
|
+
ctx.log('unauthenticated: Deleting usage collection...');
|
|
74
|
+
|
|
75
|
+
await admin.firestore().recursiveDelete(admin.firestore().collection('usage'))
|
|
76
|
+
.then(() => {
|
|
77
|
+
ctx.log('unauthenticated: Completed!');
|
|
78
|
+
})
|
|
79
|
+
.catch((e) => {
|
|
80
|
+
ctx.report(`Error deleting usage collection: ${e}`, { code: 500 });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function resetAuthenticated(Manager, ctx) {
|
|
85
|
+
const isFirstOfMonth = new Date().getDate() === 1;
|
|
86
|
+
|
|
87
|
+
// The field paths to QUERY on. A Firestore query names a field, so the ids
|
|
88
|
+
// have to be enumerable: every counted feature the catalog defines, plus the
|
|
89
|
+
// framework's own gates, which count on a user doc with an explicit limit and
|
|
90
|
+
// carry no catalog entry ([#647](https://github.com/Omega-JS-Stack/omega/issues/647)).
|
|
91
|
+
// This list decides who is FOUND; it does not decide what is reset — see
|
|
92
|
+
// below, where every counter-shaped key on the fetched document is cleared.
|
|
93
|
+
const catalog = Manager.config.features || {};
|
|
94
|
+
const features = [
|
|
95
|
+
...Object.keys(catalog).filter((id) => isCountedFeature(catalog[id])),
|
|
96
|
+
...FRAMEWORK_COUNTERS.filter((id) => !catalog[id]),
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
ctx.log(`authenticated: Resetting ${isFirstOfMonth ? 'daily + monthly' : 'daily'} for features`, features);
|
|
100
|
+
|
|
101
|
+
// Collect all user IDs that need resetting (deduplicated across features)
|
|
102
|
+
// Each entry maps uid -> { ref, usage } so we only write once per user
|
|
103
|
+
const usersToReset = {};
|
|
104
|
+
|
|
105
|
+
for (const feature of features) {
|
|
106
|
+
// Query users with daily > 0 for this feature
|
|
107
|
+
await Manager.Utilities().iterateCollection((batch) => {
|
|
108
|
+
return new Promise(async (resolve) => {
|
|
109
|
+
for (const doc of batch.docs) {
|
|
110
|
+
if (!usersToReset[doc.id]) {
|
|
111
|
+
usersToReset[doc.id] = { ref: doc.ref, usage: doc.data().usage || {} };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return resolve();
|
|
115
|
+
});
|
|
116
|
+
}, {
|
|
117
|
+
collection: 'users',
|
|
118
|
+
where: [
|
|
119
|
+
{ field: `usage.${feature}.daily`, operator: '>', value: 0 },
|
|
120
|
+
],
|
|
121
|
+
batchSize: 5000,
|
|
122
|
+
log: false,
|
|
123
|
+
})
|
|
124
|
+
.catch(e => {
|
|
125
|
+
ctx.report(`Error querying ${feature}.daily: ${e}`, { code: 500 });
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// On the 1st, also query users with monthly > 0
|
|
129
|
+
if (isFirstOfMonth) {
|
|
130
|
+
await Manager.Utilities().iterateCollection((batch) => {
|
|
131
|
+
return new Promise(async (resolve) => {
|
|
132
|
+
for (const doc of batch.docs) {
|
|
133
|
+
if (!usersToReset[doc.id]) {
|
|
134
|
+
usersToReset[doc.id] = { ref: doc.ref, usage: doc.data().usage || {} };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return resolve();
|
|
138
|
+
});
|
|
139
|
+
}, {
|
|
140
|
+
collection: 'users',
|
|
141
|
+
where: [
|
|
142
|
+
{ field: `usage.${feature}.monthly`, operator: '>', value: 0 },
|
|
143
|
+
],
|
|
144
|
+
batchSize: 5000,
|
|
145
|
+
log: false,
|
|
146
|
+
})
|
|
147
|
+
.catch(e => {
|
|
148
|
+
ctx.report(`Error querying ${feature}.monthly: ${e}`, { code: 500 });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const userIds = Object.keys(usersToReset);
|
|
154
|
+
ctx.log(`authenticated: Found ${userIds.length} users to reset`);
|
|
155
|
+
|
|
156
|
+
// Single write per user: reset daily (always) + monthly (on 1st) on EVERY
|
|
157
|
+
// counter block the document carries, whatever its key. Catalog membership is
|
|
158
|
+
// deliberately not the test — a counter the catalog never named is still a
|
|
159
|
+
// counter, and sweeping only the catalog left the framework's own gates
|
|
160
|
+
// growing forever, which permanently refused a user after five uses.
|
|
161
|
+
// `usage.overrides` is a map of LIMITS, not counts, so it is skipped: an
|
|
162
|
+
// admin granted those credits and a reset is not a revoke.
|
|
163
|
+
for (const uid of userIds) {
|
|
164
|
+
const { ref, usage } = usersToReset[uid];
|
|
165
|
+
|
|
166
|
+
for (const key of Object.keys(usage)) {
|
|
167
|
+
if (key === OVERRIDES_KEY || !isCounterBlock(usage[key])) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
usage[key].daily = 0;
|
|
172
|
+
|
|
173
|
+
if (isFirstOfMonth) {
|
|
174
|
+
usage[key].monthly = 0;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await ref.update({ usage })
|
|
179
|
+
.then(() => {
|
|
180
|
+
ctx.log(`authenticated: Reset ${uid}`);
|
|
181
|
+
})
|
|
182
|
+
.catch(e => {
|
|
183
|
+
ctx.report(`Error resetting ${uid}: ${e}`, { code: 500 });
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
ctx.log(`authenticated: Completed!`);
|
|
188
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const powertools = require('node-powertools');
|
|
3
|
+
const loadProvider = require('../../../libraries/load-provider.js');
|
|
4
|
+
const { deliverConversion } = require('../../../libraries/analytics/conversions.js');
|
|
5
|
+
const { buildAttributionContext, buildIdentity } = require('../../../libraries/analytics/match-data.js');
|
|
6
|
+
// The payment webhook's analytics module owns what "still inside the trial" means
|
|
7
|
+
// for reporting, and this sweep reports the outcomes that webhook never sees — so
|
|
8
|
+
// both read the one predicate rather than keeping a copy each ([#407]).
|
|
9
|
+
const { isInsideTrial } = require('../../firestore/payments-webhooks/analytics.js');
|
|
10
|
+
|
|
11
|
+
const PROVIDERS_DIR = path.join(__dirname, '../../../libraries/payment/providers');
|
|
12
|
+
|
|
13
|
+
// The candidate window, at both edges.
|
|
14
|
+
//
|
|
15
|
+
// GRACE — a trial that ended within the last 24 hours is left alone. Webhook lag at
|
|
16
|
+
// trial end is normal, and PayPal's stored trial expiry is a COMPUTED ESTIMATE
|
|
17
|
+
// (PayPal fires no trial-end event), so acting the minute the stored date passes
|
|
18
|
+
// would cancel subscriptions the provider is about to confirm.
|
|
19
|
+
//
|
|
20
|
+
// FLOOR — a trial that ended more than 30 days ago ages out of the sweep. This is a
|
|
21
|
+
// BACKSTOP for missed webhooks, not the primary path (Stripe and Chargebee fire real
|
|
22
|
+
// events at trial end); without a floor every trial ever claimed is re-examined for
|
|
23
|
+
// the life of the brand.
|
|
24
|
+
const GRACE_SECONDS = 24 * 60 * 60;
|
|
25
|
+
const FLOOR_SECONDS = 30 * 24 * 60 * 60;
|
|
26
|
+
|
|
27
|
+
// Bounded per run. The window keeps the set small on its own; this is the ceiling.
|
|
28
|
+
const SWEEP_LIMIT = 200;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Trial lapse sweep
|
|
32
|
+
*
|
|
33
|
+
* A trial that ends without converting should leave the user on basic. The providers
|
|
34
|
+
* say so with a webhook — and when that webhook is missed or never fires, the user
|
|
35
|
+
* keeps a paid product they never paid for. Nothing else notices: `trial.claimed`
|
|
36
|
+
* means "this subscription HAD a trial", never "it converted", so a lapsed trial and
|
|
37
|
+
* a converted one are indistinguishable on the user doc alone.
|
|
38
|
+
*
|
|
39
|
+
* So this asks the provider. Every candidate is CONFIRMED against live provider
|
|
40
|
+
* state before anything is written — the sweep never infers a lapse from dates.
|
|
41
|
+
*
|
|
42
|
+
* Flow:
|
|
43
|
+
* 1. Query users whose claimed trial expired inside the window and who are still active
|
|
44
|
+
* 2. Skip the ones already stamped, on basic, or with no provider to ask
|
|
45
|
+
* 3. Fetch the live subscription from the provider
|
|
46
|
+
* 4. Provider says active → the trial CONVERTED: stamp `trial.outcome` and nothing else
|
|
47
|
+
* Provider says gone or cancelled → the trial LAPSED: reset to basic + stamp
|
|
48
|
+
* Anything else (dunning) → leave it; the provider still has it
|
|
49
|
+
* 5. Re-read before writing so a webhook that landed since the query is never clobbered
|
|
50
|
+
* 6. Report the outcome to analytics — but ONLY when this sweep is the one that saw it
|
|
51
|
+
*
|
|
52
|
+
* No email is sent from here. The sweep is state correction — the customer-facing
|
|
53
|
+
* message for a lapsed trial is its own piece of work.
|
|
54
|
+
*
|
|
55
|
+
* **Analytics.** For PayPal this sweep is the only place a trial outcome is ever
|
|
56
|
+
* known: PayPal fires no trial-end event, so nothing in the webhook pipeline is told
|
|
57
|
+
* and the funnel had no signal at all ([#407]). So the outcome is reported here, at
|
|
58
|
+
* the moment it is stamped, through the same `deliverConversion` path the payment
|
|
59
|
+
* webhook uses. The guard against double-counting is
|
|
60
|
+
* `resolveTrialOutcomeConversion()` below.
|
|
61
|
+
*/
|
|
62
|
+
module.exports = async ({ Manager, ctx, context, libraries }) => {
|
|
63
|
+
const { admin } = libraries;
|
|
64
|
+
|
|
65
|
+
// The read stamp: any subscription write newer than this landed AFTER our snapshot,
|
|
66
|
+
// which means a webhook has since spoken and this sweep's answer is stale.
|
|
67
|
+
const now = powertools.timestamp(new Date(), { output: 'string' });
|
|
68
|
+
const nowUNIX = powertools.timestamp(now, { output: 'unix' });
|
|
69
|
+
const sweepReadUNIX = nowUNIX;
|
|
70
|
+
|
|
71
|
+
const ceilingUNIX = nowUNIX - GRACE_SECONDS;
|
|
72
|
+
const floorUNIX = nowUNIX - FLOOR_SECONDS;
|
|
73
|
+
|
|
74
|
+
ctx.log(`Checking for lapsed trials (expired between ${floorUNIX} and ${ceilingUNIX})...`);
|
|
75
|
+
|
|
76
|
+
const snapshot = await admin.firestore()
|
|
77
|
+
.collection('users')
|
|
78
|
+
.where('subscription.trial.claimed', '==', true)
|
|
79
|
+
.where('subscription.status', '==', 'active')
|
|
80
|
+
.where('subscription.trial.expires.timestampUNIX', '>=', floorUNIX)
|
|
81
|
+
.where('subscription.trial.expires.timestampUNIX', '<=', ceilingUNIX)
|
|
82
|
+
.limit(SWEEP_LIMIT)
|
|
83
|
+
.get();
|
|
84
|
+
|
|
85
|
+
if (snapshot.empty) {
|
|
86
|
+
ctx.log('No expired trials to check');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
ctx.log(`Sweeping ${snapshot.size} expired trial(s)...`);
|
|
91
|
+
|
|
92
|
+
let lapsed = 0;
|
|
93
|
+
let converted = 0;
|
|
94
|
+
let skipped = 0;
|
|
95
|
+
let failed = 0;
|
|
96
|
+
|
|
97
|
+
for (const doc of snapshot.docs) {
|
|
98
|
+
const uid = doc.id;
|
|
99
|
+
|
|
100
|
+
// Per-candidate isolation, like the runner's per-job isolation: one user whose
|
|
101
|
+
// provider is unreachable must not cost every user behind them in the batch.
|
|
102
|
+
try {
|
|
103
|
+
const sub = doc.data().subscription || {};
|
|
104
|
+
|
|
105
|
+
// Already answered — the outcome is stamped once and never revisited
|
|
106
|
+
if (sub.trial?.outcome) {
|
|
107
|
+
ctx.log(`skip ${uid}: trial already stamped ${sub.trial.outcome}`);
|
|
108
|
+
skipped++;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Nothing to lapse — basic IS the lapsed end state
|
|
113
|
+
if (sub.product?.id === 'basic') {
|
|
114
|
+
ctx.log(`skip ${uid}: already on basic`);
|
|
115
|
+
skipped++;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const provider = sub.payment?.provider;
|
|
120
|
+
const resourceId = sub.payment?.resourceId;
|
|
121
|
+
|
|
122
|
+
if (!provider || !resourceId) {
|
|
123
|
+
ctx.log(`skip ${uid}: no provider to confirm with (provider=${provider || 'null'}, resourceId=${resourceId || 'null'})`);
|
|
124
|
+
skipped++;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let library;
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
library = loadProvider(PROVIDERS_DIR, provider);
|
|
132
|
+
} catch (e) {
|
|
133
|
+
ctx.warn(`skip ${uid}: unknown provider library '${provider}' — nothing can confirm this trial`);
|
|
134
|
+
skipped++;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Ask the provider. Its answer is the only thing this sweep acts on — a fetch
|
|
139
|
+
// that cannot answer throws rather than handing back anything older.
|
|
140
|
+
let live = null;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
live = await library.fetchResource('subscription', resourceId, { admin, ctx, config: Manager.config });
|
|
144
|
+
} catch (e) {
|
|
145
|
+
// A provider that cannot answer is not a provider saying "cancelled". Only
|
|
146
|
+
// "no such subscription" means gone; everything else is transient and waits
|
|
147
|
+
// for the next run rather than fabricating a cancellation.
|
|
148
|
+
if (!e.notFound) {
|
|
149
|
+
ctx.warn(`skip ${uid}: provider ${provider} could not confirm ${resourceId} (${e.message}) — retrying next run`);
|
|
150
|
+
skipped++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// No resource, or one with no status, is the provider saying it is gone
|
|
156
|
+
const gone = !live || !live.status;
|
|
157
|
+
const liveStatus = gone ? null : library.toUnifiedSubscription(live, { config: Manager.config }).status;
|
|
158
|
+
|
|
159
|
+
let outcome;
|
|
160
|
+
|
|
161
|
+
if (!gone && liveStatus === 'active') {
|
|
162
|
+
outcome = 'converted';
|
|
163
|
+
} else if (gone || liveStatus === 'cancelled') {
|
|
164
|
+
outcome = 'lapsed';
|
|
165
|
+
} else {
|
|
166
|
+
// Dunning (suspended): the provider still holds the subscription and is still
|
|
167
|
+
// trying. Neither outcome is true yet, so nothing is stamped and the next run
|
|
168
|
+
// asks again.
|
|
169
|
+
ctx.log(`skip ${uid}: provider ${provider} reports ${liveStatus} — no outcome yet`);
|
|
170
|
+
skipped++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// The trial converted into a paid subscription: stamp the outcome and touch
|
|
175
|
+
// NOTHING else — the subscription the user is paying for is correct as it is.
|
|
176
|
+
// A lapse writes the same end state the cancel route does for a subscription
|
|
177
|
+
// the provider no longer has: cancelled, back on basic, nothing pending.
|
|
178
|
+
const write = outcome === 'converted'
|
|
179
|
+
? { subscription: { trial: { outcome: 'converted' } } }
|
|
180
|
+
: {
|
|
181
|
+
subscription: {
|
|
182
|
+
status: 'cancelled',
|
|
183
|
+
product: { id: 'basic', name: 'Basic' },
|
|
184
|
+
cancellation: { pending: false, date: { timestamp: now, timestampUNIX: nowUNIX } },
|
|
185
|
+
trial: { outcome: 'lapsed' },
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Re-read and write in ONE transaction. The snapshot above is from the top of
|
|
190
|
+
// the run; a webhook may have written this subscription since, and that write
|
|
191
|
+
// is the newer truth — the sweep must never clobber it. As a bare read followed
|
|
192
|
+
// by a separate set, a webhook landing BETWEEN the two was clobbered anyway:
|
|
193
|
+
// the guard proved freshness at a moment that had already passed by the time
|
|
194
|
+
// the write went out. A transaction re-runs the whole block when the document
|
|
195
|
+
// changes under it, so the guard and the write see one state
|
|
196
|
+
// ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)).
|
|
197
|
+
const result = await admin.firestore().runTransaction(async (transaction) => {
|
|
198
|
+
const fresh = await transaction.get(doc.ref);
|
|
199
|
+
const freshSub = fresh.data()?.subscription || {};
|
|
200
|
+
const freshStampUNIX = freshSub.payment?.updatedBy?.date?.timestampUNIX || 0;
|
|
201
|
+
|
|
202
|
+
if (isNewerThanSweep(freshStampUNIX, sweepReadUNIX)) {
|
|
203
|
+
return { skipped: `a newer subscription write landed (updatedBy=${freshStampUNIX} >= read=${sweepReadUNIX})` };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (freshSub.status !== 'active' || freshSub.trial?.outcome) {
|
|
207
|
+
return { skipped: `no longer a candidate (status=${freshSub.status}, outcome=${freshSub.trial?.outcome || 'null'})` };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
transaction.set(doc.ref, write, { merge: true });
|
|
211
|
+
|
|
212
|
+
return { userData: fresh.data() || {}, sub: freshSub };
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
if (result.skipped) {
|
|
216
|
+
ctx.log(`skip ${uid}: ${result.skipped}`);
|
|
217
|
+
skipped++;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (outcome === 'converted') {
|
|
222
|
+
ctx.log(`convert ${uid}: provider ${provider} reports the subscription is active, trial.outcome=converted`);
|
|
223
|
+
trackOutcome({ outcome, uid, userData: result.userData, sub: result.sub, Manager, ctx });
|
|
224
|
+
converted++;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
ctx.log(`lapse ${uid}: provider ${provider} reports ${gone ? 'the subscription is gone' : liveStatus}, reset to basic, trial.outcome=lapsed`);
|
|
229
|
+
trackOutcome({ outcome, uid, userData: result.userData, sub: result.sub, Manager, ctx });
|
|
230
|
+
lapsed++;
|
|
231
|
+
} catch (e) {
|
|
232
|
+
ctx.error(`Failed to sweep ${uid}: ${e.message}`);
|
|
233
|
+
failed++;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
ctx.log(`Completed! (${lapsed} lapsed, ${converted} converted, ${skipped} skipped, ${failed} failed)`);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Has a subscription write landed since this sweep read its candidates?
|
|
242
|
+
*
|
|
243
|
+
* `>=`, not `>`. Both numbers are whole SECONDS, so a webhook that wrote inside the
|
|
244
|
+
* same second the sweep took its snapshot carries an EQUAL stamp — and a strict `>`
|
|
245
|
+
* read that as older and let the sweep write over it, which is precisely the write
|
|
246
|
+
* the guard exists to protect (a provider's own trial-end event resolving the trial
|
|
247
|
+
* while the backstop was mid-run). Equal reads as newer: the cost of being wrong is
|
|
248
|
+
* one candidate re-examined on the next run, against a subscription silently
|
|
249
|
+
* reverted to a state the provider had already moved past.
|
|
250
|
+
*
|
|
251
|
+
* @param {number} freshStampUNIX - `subscription.payment.updatedBy.date.timestampUNIX`, 0 when never stamped
|
|
252
|
+
* @param {number} sweepReadUNIX - The second this run read its candidate snapshot
|
|
253
|
+
* @returns {boolean} True when the sweep's answer is stale and must not be written
|
|
254
|
+
*/
|
|
255
|
+
function isNewerThanSweep(freshStampUNIX, sweepReadUNIX) {
|
|
256
|
+
return (freshStampUNIX || 0) >= sweepReadUNIX;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* The conversion to report for an outcome this sweep just decided, or null when the
|
|
261
|
+
* outcome was already reported at the moment it happened.
|
|
262
|
+
*
|
|
263
|
+
* THE GUARD IS THE TERM. A conversion a payment webhook already saw moved `expires`
|
|
264
|
+
* out past the trial's end, and a lapse it saw left the subscription suspended or
|
|
265
|
+
* cancelled — which this sweep's own query (`status == active`) never selects. So a
|
|
266
|
+
* candidate still inside its trial is exactly one no webhook has resolved, and it is
|
|
267
|
+
* the only one this backstop has anything new to say about.
|
|
268
|
+
*
|
|
269
|
+
* The subscription-keyed event id collapses a genuine race on the two platforms that
|
|
270
|
+
* key on an event id; this guard is what keeps GA4 honest, because GA4 deduplicates
|
|
271
|
+
* a `purchase` on `transaction_id` alone — and this path has no invoice to name, so
|
|
272
|
+
* a conversion reported twice would arrive under two different ids and count twice
|
|
273
|
+
* ([#656](https://github.com/Omega-JS-Stack/omega/issues/656)).
|
|
274
|
+
*
|
|
275
|
+
* Which makes this the ONE documented exception to "`transaction_id` is a charge's
|
|
276
|
+
* id, never the subscription's": this path has no invoice to name, and the outcome
|
|
277
|
+
* stamp keeps it to one fire (docs/shared/analytics.md).
|
|
278
|
+
*
|
|
279
|
+
* The subscription passed in is the one read BEFORE the lapse write — the paid
|
|
280
|
+
* product that lapsed, not the `basic` the sweep resets it to.
|
|
281
|
+
*
|
|
282
|
+
* @param {object} sub - The subscription as it stood before this sweep wrote
|
|
283
|
+
* @param {string} outcome - 'converted' | 'lapsed'
|
|
284
|
+
* @param {string} currency - The brand's payment currency
|
|
285
|
+
* @returns {{ event: string, eventId: string, params: object }|null}
|
|
286
|
+
*/
|
|
287
|
+
function resolveTrialOutcomeConversion(sub, outcome, currency) {
|
|
288
|
+
if (!isInsideTrial(sub)) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const event = outcome === 'converted' ? 'trial_convert' : 'trial_lapse';
|
|
293
|
+
// The full price: a conversion the provider made without telling us leaves no
|
|
294
|
+
// invoice here to read a discount off, and the plan price is the honest number
|
|
295
|
+
// this path can actually stand behind.
|
|
296
|
+
const price = parseFloat(sub.payment?.price || 0);
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
event: event,
|
|
300
|
+
eventId: `${event}.${sub.payment?.resourceId}`,
|
|
301
|
+
params: {
|
|
302
|
+
transaction_id: sub.payment?.resourceId,
|
|
303
|
+
value: price,
|
|
304
|
+
currency: currency,
|
|
305
|
+
items: [{
|
|
306
|
+
item_id: sub.product?.id,
|
|
307
|
+
item_name: sub.product?.name,
|
|
308
|
+
price: price,
|
|
309
|
+
quantity: 1,
|
|
310
|
+
}],
|
|
311
|
+
payment_provider: sub.payment?.provider,
|
|
312
|
+
payment_frequency: sub.payment?.frequency || null,
|
|
313
|
+
is_trial: true,
|
|
314
|
+
is_recurring: false,
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Report a trial outcome this sweep decided (non-blocking, never throws at the sweep)
|
|
321
|
+
*
|
|
322
|
+
* @param {object} options
|
|
323
|
+
* @param {string} options.outcome - 'converted' | 'lapsed'
|
|
324
|
+
* @param {string} options.uid - The owner
|
|
325
|
+
* @param {object} options.userData - The user doc (attribution + consent + match data)
|
|
326
|
+
* @param {object} options.sub - The subscription as it stood before the write
|
|
327
|
+
* @param {object} options.Manager - The backend Manager
|
|
328
|
+
* @param {object} options.ctx - The event context
|
|
329
|
+
*/
|
|
330
|
+
function trackOutcome({ outcome, uid, userData, sub, Manager, ctx }) {
|
|
331
|
+
try {
|
|
332
|
+
const conversion = resolveTrialOutcomeConversion(sub, outcome, Manager.config.payment?.currency || 'USD');
|
|
333
|
+
|
|
334
|
+
if (!conversion) {
|
|
335
|
+
ctx.log(`skip analytics ${uid}: the term has moved past the trial end (expires=${sub.expires?.timestampUNIX || 'null'}, trial.expires=${sub.trial?.expires?.timestampUNIX || 'null'})`);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
deliverConversion({
|
|
340
|
+
...conversion,
|
|
341
|
+
attribution: buildAttributionContext(userData.attribution),
|
|
342
|
+
// The whole doc, read by the ONE match reader (#577)
|
|
343
|
+
identity: buildIdentity({ uid: uid, user: userData }),
|
|
344
|
+
trackingConsent: userData.trackingConsent,
|
|
345
|
+
ctx: ctx,
|
|
346
|
+
Manager: Manager,
|
|
347
|
+
});
|
|
348
|
+
} catch (e) {
|
|
349
|
+
ctx.error(`Trial outcome tracking failed for ${uid}: ${e.message}`, e);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// The sweep IS the module; these ride alongside it for the pipeline and the tests.
|
|
354
|
+
module.exports.resolveTrialOutcomeConversion = resolveTrialOutcomeConversion;
|
|
355
|
+
module.exports.isNewerThanSweep = isNewerThanSweep;
|