@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,541 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage — the counted-feature gate
|
|
3
|
+
* ([#647](https://github.com/Omega-JS-Stack/omega/issues/647)).
|
|
4
|
+
*
|
|
5
|
+
* ONE call does the whole job:
|
|
6
|
+
*
|
|
7
|
+
* const left = await ctx.usage.consume('saves'); // throws a 429 over limit
|
|
8
|
+
*
|
|
9
|
+
* `consume` checks both counters, refuses with a 429 that names WHICH one hit,
|
|
10
|
+
* else counts, writes, and returns what is left. There is no separate
|
|
11
|
+
* "validate then increment then update" dance for a caller to get half right —
|
|
12
|
+
* every hand-rolled gate in the framework's own routes existed because there
|
|
13
|
+
* was one.
|
|
14
|
+
*
|
|
15
|
+
* What a feature IS lives in config, once: the top-level `features` catalog
|
|
16
|
+
* defines it (name, icon, definition, and the `usage` block that meters it)
|
|
17
|
+
* and each product names only its VALUE. @omega.js/account's features module
|
|
18
|
+
* owns every derivation from those two halves plus the user's counters — the
|
|
19
|
+
* effective limit (a per-user override wins over the plan's number), the day
|
|
20
|
+
* share, what is left — so this gate and the browser's account page can never
|
|
21
|
+
* speak different numbers.
|
|
22
|
+
*
|
|
23
|
+
* Two counters per counted feature per user, month and day. The day's share is
|
|
24
|
+
* the month limit spread over the days of this month, so a quota cannot be
|
|
25
|
+
* burned on day one; `usage: { pace: false }` on the catalog entry opts out.
|
|
26
|
+
* Either counter full refuses, and the month cap always holds.
|
|
27
|
+
*
|
|
28
|
+
* Init is LAZY: the middleware `attach`es a counter that resolves the account
|
|
29
|
+
* on the first consume/read, so a route that never counts pays nothing.
|
|
30
|
+
*
|
|
31
|
+
* Anonymous counting is EXPLICIT: `ctx.usage.forKey(ip)` returns a separate
|
|
32
|
+
* keyed counter. Passing a key can never silently move a signed-in user's
|
|
33
|
+
* counters into the anonymous store, which is what the old `options.key` did.
|
|
34
|
+
*
|
|
35
|
+
* Mirrors are declared in the CATALOG (`usage: { mirror: ['teams'] }`), never
|
|
36
|
+
* at the call site: `consume` writes the touched feature's counters — that
|
|
37
|
+
* feature's, not the whole usage object — to the user doc and to every doc the
|
|
38
|
+
* account owns of each named kind (`owns.teams`), in one parallel write.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
const User = require('./user.js');
|
|
42
|
+
const env = require('../libraries/env.js');
|
|
43
|
+
|
|
44
|
+
// @omega.js/account is a private workspace package: in the monorepo the bare
|
|
45
|
+
// specifier resolves via the workspace link (and the prepare-package vendor
|
|
46
|
+
// hook rewrites it in dist/), but src/ ships in the tarball UNREWRITTEN — so
|
|
47
|
+
// fall back to the copy vendored into dist/, which sits at the same depth from
|
|
48
|
+
// both trees. The same two-step user.js makes.
|
|
49
|
+
let features;
|
|
50
|
+
try {
|
|
51
|
+
features = require('../../vendor/account/features.js');
|
|
52
|
+
} catch (e) {
|
|
53
|
+
features = require('../../../dist/vendor/account/features.js');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Where an anonymous key's counters live when the brand stores them in
|
|
57
|
+
// Firestore (the default) — one document per key, wiped daily by the cron.
|
|
58
|
+
const ANONYMOUS_COLLECTION = 'usage';
|
|
59
|
+
|
|
60
|
+
function Usage(m) {
|
|
61
|
+
const self = this;
|
|
62
|
+
|
|
63
|
+
self.Manager = m;
|
|
64
|
+
|
|
65
|
+
self.ctx = null;
|
|
66
|
+
self.options = null;
|
|
67
|
+
|
|
68
|
+
// The anonymous key this counter counts against, or null for the signed-in
|
|
69
|
+
// user. Set ONLY by forKey() — never inferred from a request.
|
|
70
|
+
self.key = null;
|
|
71
|
+
|
|
72
|
+
// The account (or the keyed counter document) the counters live on, resolved
|
|
73
|
+
// on first use.
|
|
74
|
+
self.user = null;
|
|
75
|
+
self.resolved = false;
|
|
76
|
+
|
|
77
|
+
self.storage = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Attach a counter to a request. Synchronous and I/O-free: nothing is read
|
|
82
|
+
* until the first consume/read, so a route that never counts pays nothing.
|
|
83
|
+
*
|
|
84
|
+
* @param {object} ctx - The RouteContext
|
|
85
|
+
* @param {object} [options] - Counter options
|
|
86
|
+
* @param {string} [options.unauthenticatedMode] - 'firestore' (default) or 'local', for keyed counters
|
|
87
|
+
* @param {string[]} [options.whitelistKeys] - API keys that never get refused
|
|
88
|
+
* @param {Date} [options.today] - The day being counted (tests)
|
|
89
|
+
* @param {boolean} [options.log] - Log the counter lines (defaults to dev)
|
|
90
|
+
* @returns {Usage} this
|
|
91
|
+
*/
|
|
92
|
+
Usage.prototype.attach = function (ctx, options) {
|
|
93
|
+
const self = this;
|
|
94
|
+
|
|
95
|
+
if (!ctx) {
|
|
96
|
+
throw new Error('Usage.attach(): Missing required {ctx} parameter');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Set options
|
|
100
|
+
options = options || {};
|
|
101
|
+
options.unauthenticatedMode = typeof options.unauthenticatedMode === 'undefined' ? 'firestore' : options.unauthenticatedMode;
|
|
102
|
+
options.whitelistKeys = options.whitelistKeys || [];
|
|
103
|
+
options.today = typeof options.today === 'undefined' ? undefined : options.today;
|
|
104
|
+
options.log = typeof options.log === 'undefined' ? ctx.isDevelopment() : options.log;
|
|
105
|
+
|
|
106
|
+
// The framework's own admin key always bypasses
|
|
107
|
+
options.whitelistKeys = options.whitelistKeys.concat([env.get('OMEGA_ADMIN_KEY')]);
|
|
108
|
+
|
|
109
|
+
self.ctx = ctx;
|
|
110
|
+
self.options = options;
|
|
111
|
+
|
|
112
|
+
return self;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A counter for an anonymous key (an IP, an installation id) — a SEPARATE
|
|
117
|
+
* counter, so a signed-in user's own counters are never moved into the
|
|
118
|
+
* anonymous store by a caller that only meant to rate-limit by address.
|
|
119
|
+
*
|
|
120
|
+
* Keyed counters are day-only in practice: the reset cron wipes the whole
|
|
121
|
+
* anonymous store every day (docs/usage-rate-limiting.md).
|
|
122
|
+
*
|
|
123
|
+
* @param {string} key - The key to count against
|
|
124
|
+
* @returns {Usage} A new counter bound to that key
|
|
125
|
+
*/
|
|
126
|
+
Usage.prototype.forKey = function (key) {
|
|
127
|
+
const self = this;
|
|
128
|
+
|
|
129
|
+
const keyed = new Usage(self.Manager);
|
|
130
|
+
|
|
131
|
+
keyed.attach(self.ctx, { ...self.options });
|
|
132
|
+
keyed.key = `${key || 'unknown'}`;
|
|
133
|
+
|
|
134
|
+
return keyed;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The brand's feature catalog.
|
|
139
|
+
* @returns {object} config.features, keyed by feature id
|
|
140
|
+
*/
|
|
141
|
+
Usage.prototype.catalog = function () {
|
|
142
|
+
const self = this;
|
|
143
|
+
|
|
144
|
+
return self.Manager.config.features || {};
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The product whose numbers apply: the account's RESOLVED plan (a cancelled or
|
|
149
|
+
* suspended subscription resolves to the free tier), else `basic`.
|
|
150
|
+
* @param {string} [id] - Force a specific product id
|
|
151
|
+
* @returns {object} The catalog entry, or {}
|
|
152
|
+
*/
|
|
153
|
+
Usage.prototype.getProduct = function (id) {
|
|
154
|
+
const self = this;
|
|
155
|
+
|
|
156
|
+
const products = self.Manager.config.payment?.products || [];
|
|
157
|
+
|
|
158
|
+
id = id || User.resolveSubscription(self.user).plan;
|
|
159
|
+
|
|
160
|
+
return products.find((product) => product.id === id)
|
|
161
|
+
|| products.find((product) => product.id === 'basic')
|
|
162
|
+
|| {};
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Resolve the account (or the keyed counter document) this counter counts on.
|
|
167
|
+
* Runs at most once — every consume/read awaits it first.
|
|
168
|
+
* @returns {Promise<Usage>} this
|
|
169
|
+
*/
|
|
170
|
+
Usage.prototype.resolve = async function () {
|
|
171
|
+
const self = this;
|
|
172
|
+
|
|
173
|
+
if (self.resolved) {
|
|
174
|
+
return self;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (self.key) {
|
|
178
|
+
self.user = { usage: await self.loadKeyed() };
|
|
179
|
+
} else if (self.ctx.resolvedUser) {
|
|
180
|
+
// The middleware already authenticated this request — re-authenticating
|
|
181
|
+
// would verify the token and re-read the user doc a second time
|
|
182
|
+
self.user = self.ctx.request.user;
|
|
183
|
+
} else {
|
|
184
|
+
self.user = await self.ctx.authenticate();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// A signed-OUT caller has no document to count on. `authenticate()` resolves
|
|
188
|
+
// a full account SHAPE for one (uid null) and marks the request resolved all
|
|
189
|
+
// the same, so without this the write below would land on `users/null` — one
|
|
190
|
+
// document every anonymous caller on earth would share, and a limit none of
|
|
191
|
+
// them could ever exceed. Silently routing to the anonymous store instead
|
|
192
|
+
// would be the OTHER old bug: a key that switches storage behind the caller's
|
|
193
|
+
// back. Anonymous counting is explicit, so this says so.
|
|
194
|
+
if (!self.key && !self.user?.auth?.uid) {
|
|
195
|
+
throw new Error('usage: no signed-in account to count against; use usage.forKey(<key>) for anonymous callers');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
self.resolved = true;
|
|
199
|
+
|
|
200
|
+
// Log — the counters this counter arrived with, never the document holding
|
|
201
|
+
// them: it carries api.privateKey, consent and attribution, and a backend
|
|
202
|
+
// line lands in Cloud Logging for the whole retention window
|
|
203
|
+
// ([#632](https://github.com/Omega-JS-Stack/omega/issues/632)).
|
|
204
|
+
self.log(`Usage.resolve(): Resolved ${self.key || self.user?.auth?.uid || 'unauthenticated'}`, self.user?.usage);
|
|
205
|
+
|
|
206
|
+
return self;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The stored counters for this counter's anonymous key.
|
|
211
|
+
* @returns {Promise<object>} feature id → counters
|
|
212
|
+
*/
|
|
213
|
+
Usage.prototype.loadKeyed = async function () {
|
|
214
|
+
const self = this;
|
|
215
|
+
|
|
216
|
+
if (self.options.unauthenticatedMode !== 'firestore') {
|
|
217
|
+
self.storage = self.storage || self.Manager.storage({ name: ANONYMOUS_COLLECTION, temporary: true, clear: false, log: false });
|
|
218
|
+
|
|
219
|
+
return self.storage.get(`users.${self.key}.usage`, {}).value() || {};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const found = await self.Manager.libraries.admin.firestore().doc(`${ANONYMOUS_COLLECTION}/${self.key}`)
|
|
223
|
+
.get()
|
|
224
|
+
.then((r) => r.data())
|
|
225
|
+
.catch((e) => {
|
|
226
|
+
self.ctx.report(`Usage.loadKeyed(): Error fetching usage data: ${e}`, { code: 500 });
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
return found || {};
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* What this account's state is for a feature, WITHOUT counting: the effective
|
|
234
|
+
* limit (overrides applied), both counters, and what is left of each.
|
|
235
|
+
* @param {string} feature - Feature id from the catalog
|
|
236
|
+
* @returns {Promise<object>} { id, name, limit, used, left, day: { limit, used, left }, ... }
|
|
237
|
+
*/
|
|
238
|
+
Usage.prototype.read = async function (feature) {
|
|
239
|
+
const self = this;
|
|
240
|
+
|
|
241
|
+
await self.resolve();
|
|
242
|
+
|
|
243
|
+
return self.state(feature);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The resolved feature state, from what is already loaded (no I/O).
|
|
248
|
+
* @param {string} feature - Feature id from the catalog
|
|
249
|
+
* @returns {object} @omega.js/account's resolveFeature shape
|
|
250
|
+
*/
|
|
251
|
+
Usage.prototype.state = function (feature) {
|
|
252
|
+
const self = this;
|
|
253
|
+
|
|
254
|
+
return features.resolveFeature(feature, {
|
|
255
|
+
catalog: self.catalog(),
|
|
256
|
+
product: self.getProduct(),
|
|
257
|
+
account: self.user,
|
|
258
|
+
now: self.options.today,
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The state of a counter running against an EXPLICIT limit rather than the
|
|
264
|
+
* plan's — same shape as state(), with no day share (see consume's options).
|
|
265
|
+
* @param {string} feature - Counter id
|
|
266
|
+
* @param {number} limit - The limit that applies
|
|
267
|
+
* @returns {object} The resolveFeature shape
|
|
268
|
+
*/
|
|
269
|
+
Usage.prototype.explicitState = function (feature, limit) {
|
|
270
|
+
const self = this;
|
|
271
|
+
|
|
272
|
+
return features.resolveFeature(feature, {
|
|
273
|
+
catalog: { [feature]: { name: feature, usage: { pace: false } } },
|
|
274
|
+
product: { features: { [feature]: limit } },
|
|
275
|
+
account: self.user,
|
|
276
|
+
now: self.options.today,
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Count one use of a feature — the ONE call a route makes.
|
|
282
|
+
*
|
|
283
|
+
* Refuses with a 429 naming which counter hit: the MONTH is checked first (a
|
|
284
|
+
* spent month is not "try again tomorrow"), then the day's share.
|
|
285
|
+
*
|
|
286
|
+
* `options.limit` is for the counters that are NOT plan features — a per-IP
|
|
287
|
+
* signup gate is a security control with its own declared config key
|
|
288
|
+
* (`targets.backend.auth.signup.maxPerIpPerDay`), not a tier anybody buys. An
|
|
289
|
+
* explicit limit supplies the definition the catalog would have, so the
|
|
290
|
+
* catalog lookup and the product read are skipped, and the counter is a plain
|
|
291
|
+
* period counter with no day share (an anonymous key's store is wiped daily,
|
|
292
|
+
* so its period IS the day).
|
|
293
|
+
*
|
|
294
|
+
* @param {string} feature - Feature id from the catalog
|
|
295
|
+
* @param {number} [amount] - How much to count (default 1)
|
|
296
|
+
* @param {object} [options] - Consume options
|
|
297
|
+
* @param {number} [options.limit] - An explicit limit for a non-plan counter
|
|
298
|
+
* @returns {Promise<object>} { used, left, day: { used, left } } after counting
|
|
299
|
+
*/
|
|
300
|
+
Usage.prototype.consume = async function (feature, amount, options) {
|
|
301
|
+
const self = this;
|
|
302
|
+
const ctx = self.ctx;
|
|
303
|
+
|
|
304
|
+
// Set amount
|
|
305
|
+
amount = typeof amount === 'undefined' ? 1 : amount;
|
|
306
|
+
|
|
307
|
+
// Set options
|
|
308
|
+
options = options || {};
|
|
309
|
+
|
|
310
|
+
const explicit = typeof options.limit === 'number';
|
|
311
|
+
const entry = self.catalog()[feature];
|
|
312
|
+
|
|
313
|
+
// A feature no catalog defines, or a perk, is a PROGRAMMER error: the route
|
|
314
|
+
// asked to meter something the config never made countable, and counting it
|
|
315
|
+
// anyway would build a limit nothing enforces.
|
|
316
|
+
if (!explicit && !entry) {
|
|
317
|
+
throw ctx.report(`Usage.consume(): "${feature}" is not defined in the features catalog (config.features)`, { code: 500 });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!explicit && !features.isCountedFeature(entry)) {
|
|
321
|
+
throw ctx.report(`Usage.consume(): "${feature}" is a perk, not a counted feature — give features.${feature} a \`usage\` block to meter it`, { code: 500 });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await self.resolve();
|
|
325
|
+
|
|
326
|
+
const state = explicit ? self.explicitState(feature, options.limit) : self.state(feature);
|
|
327
|
+
const name = (entry && entry.name) || feature;
|
|
328
|
+
|
|
329
|
+
// A whitelisted API key still COUNTS (the record stays honest) — it only
|
|
330
|
+
// never gets refused.
|
|
331
|
+
const whitelisted = self.options.whitelistKeys.some((key) => key && key === self.user?.api?.privateKey);
|
|
332
|
+
|
|
333
|
+
if (!whitelisted) {
|
|
334
|
+
if (state.limit >= 0 && state.used + amount > state.limit) {
|
|
335
|
+
throw ctx.report(
|
|
336
|
+
`You have used all ${state.limit} of your ${name} this month (${state.used}/${state.limit}). Upgrade your plan for more.`,
|
|
337
|
+
{ code: 429 },
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (state.day.limit >= 0 && state.day.used + amount > state.day.limit) {
|
|
342
|
+
throw ctx.report(
|
|
343
|
+
`You have used today's ${name} (${state.day.used}/${state.day.limit} of the ${state.limit} on your plan this month). Try again tomorrow.`,
|
|
344
|
+
{ code: 429 },
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
self.count(feature, amount);
|
|
350
|
+
|
|
351
|
+
await self.write(feature);
|
|
352
|
+
|
|
353
|
+
const counted = explicit ? self.explicitState(feature, options.limit) : self.state(feature);
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
used: counted.used,
|
|
357
|
+
left: counted.left,
|
|
358
|
+
day: { used: counted.day.used, left: counted.day.left },
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Move the counters in memory. `total` never resets; `last` records when the
|
|
364
|
+
* feature moved.
|
|
365
|
+
* @param {string} feature - Feature id
|
|
366
|
+
* @param {number} amount - How much to count
|
|
367
|
+
* @returns {Usage} this
|
|
368
|
+
*/
|
|
369
|
+
Usage.prototype.count = function (feature, amount) {
|
|
370
|
+
const self = this;
|
|
371
|
+
|
|
372
|
+
const now = self.options.today ? new Date(self.options.today) : new Date();
|
|
373
|
+
|
|
374
|
+
self.user.usage = self.user.usage || {};
|
|
375
|
+
|
|
376
|
+
const counters = self.user.usage[feature] || {};
|
|
377
|
+
|
|
378
|
+
self.user.usage[feature] = {
|
|
379
|
+
...counters,
|
|
380
|
+
monthly: (counters.monthly || 0) + amount,
|
|
381
|
+
daily: (counters.daily || 0) + amount,
|
|
382
|
+
total: (counters.total || 0) + amount,
|
|
383
|
+
last: {
|
|
384
|
+
timestamp: now.toISOString(),
|
|
385
|
+
timestampUNIX: Math.floor(now.getTime() / 1000),
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// Log the counter this moved — not the whole user document (#632)
|
|
390
|
+
self.log(`Usage.count(): Counted ${amount} ${feature} for ${self.key || self.user?.auth?.uid || 'unauthenticated'}`, self.user.usage[feature]);
|
|
391
|
+
|
|
392
|
+
return self;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* The write payload for ONE feature: that feature's counters and nothing else,
|
|
397
|
+
* so two features counted in the same second cannot overwrite each other.
|
|
398
|
+
* @param {string} feature - Feature id
|
|
399
|
+
* @returns {object} { usage: { <feature>: counters } }
|
|
400
|
+
*/
|
|
401
|
+
Usage.prototype.countersPatch = function (feature) {
|
|
402
|
+
const self = this;
|
|
403
|
+
|
|
404
|
+
return { usage: { [feature]: (self.user.usage || {})[feature] } };
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* The mirror documents this feature's counters also land on: every doc the
|
|
409
|
+
* account owns of each kind the CATALOG names. Declared in config, never at
|
|
410
|
+
* the call site.
|
|
411
|
+
* @param {string} feature - Feature id
|
|
412
|
+
* @returns {string[]} Firestore document paths
|
|
413
|
+
*/
|
|
414
|
+
Usage.prototype.mirrorPaths = function (feature) {
|
|
415
|
+
const self = this;
|
|
416
|
+
|
|
417
|
+
// An anonymous key owns nothing
|
|
418
|
+
if (self.key) {
|
|
419
|
+
return [];
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const owns = self.user?.owns || {};
|
|
423
|
+
const paths = [];
|
|
424
|
+
|
|
425
|
+
features.featureMirrors(self.catalog()[feature]).forEach((kind) => {
|
|
426
|
+
const owned = owns[kind];
|
|
427
|
+
const ids = Array.isArray(owned) ? owned : (owned ? [owned] : []);
|
|
428
|
+
|
|
429
|
+
ids.forEach((id) => paths.push(`${kind}/${id}`));
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
return paths;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Persist one feature's counters: the user document and every mirror, in ONE
|
|
437
|
+
* parallel write.
|
|
438
|
+
* @param {string} feature - Feature id
|
|
439
|
+
* @returns {Promise<void>}
|
|
440
|
+
*/
|
|
441
|
+
Usage.prototype.write = async function (feature) {
|
|
442
|
+
const self = this;
|
|
443
|
+
|
|
444
|
+
const { admin } = self.Manager.libraries;
|
|
445
|
+
const counters = (self.user.usage || {})[feature];
|
|
446
|
+
|
|
447
|
+
if (self.key) {
|
|
448
|
+
if (self.options.unauthenticatedMode !== 'firestore') {
|
|
449
|
+
self.storage = self.storage || self.Manager.storage({ name: ANONYMOUS_COLLECTION, temporary: true, clear: false, log: false });
|
|
450
|
+
self.storage.set(`users.${self.key}.usage.${feature}`, counters).write();
|
|
451
|
+
|
|
452
|
+
self.log(`Usage.write(): Wrote ${feature} to local storage`, counters);
|
|
453
|
+
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
await admin.firestore().doc(`${ANONYMOUS_COLLECTION}/${self.key}`)
|
|
458
|
+
.set({ [feature]: counters }, { merge: true })
|
|
459
|
+
.catch((e) => {
|
|
460
|
+
throw self.ctx.report(e, { code: 500 });
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const patch = self.countersPatch(feature);
|
|
467
|
+
const paths = [`users/${self.user.auth.uid}`, ...self.mirrorPaths(feature)];
|
|
468
|
+
|
|
469
|
+
await Promise.all(paths.map((path) => admin.firestore().doc(path).set(patch, { merge: true })))
|
|
470
|
+
.then(() => {
|
|
471
|
+
self.log(`Usage.write(): Wrote ${feature} to ${paths.length} document(s)`, counters);
|
|
472
|
+
})
|
|
473
|
+
.catch((e) => {
|
|
474
|
+
throw self.ctx.report(e, { code: 500 });
|
|
475
|
+
});
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* The counters this account arrived with — the `omega-properties` header's
|
|
480
|
+
* `usage.current`. Empty until the counter has RESOLVED: a route that never
|
|
481
|
+
* counted read nothing, and the header must not force a read to report one.
|
|
482
|
+
* @returns {object} feature id → counters
|
|
483
|
+
*/
|
|
484
|
+
Usage.prototype.counters = function () {
|
|
485
|
+
const self = this;
|
|
486
|
+
|
|
487
|
+
return self.resolved ? (self.user?.usage || {}) : {};
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Every counted feature's EFFECTIVE limit for this account (overrides applied)
|
|
492
|
+
* — the `omega-properties` header's `usage.limits`, which the client merges
|
|
493
|
+
* into its `usage` bindings. Empty until the counter has resolved.
|
|
494
|
+
* @returns {object} feature id → limit (-1 unlimited)
|
|
495
|
+
*/
|
|
496
|
+
Usage.prototype.limits = function () {
|
|
497
|
+
const self = this;
|
|
498
|
+
|
|
499
|
+
if (!self.resolved) {
|
|
500
|
+
return {};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const catalog = self.catalog();
|
|
504
|
+
const limits = {};
|
|
505
|
+
|
|
506
|
+
Object.keys(catalog).forEach((id) => {
|
|
507
|
+
if (features.isCountedFeature(catalog[id])) {
|
|
508
|
+
limits[id] = self.state(id).limit;
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
return limits;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Add API keys that never get refused (they still count).
|
|
517
|
+
* @param {string|string[]} keys - Key(s) to whitelist
|
|
518
|
+
* @returns {Usage} this
|
|
519
|
+
*/
|
|
520
|
+
Usage.prototype.addWhitelistKeys = function (keys) {
|
|
521
|
+
const self = this;
|
|
522
|
+
|
|
523
|
+
// Make keys an array if not already
|
|
524
|
+
keys = Array.isArray(keys) ? keys : [keys];
|
|
525
|
+
|
|
526
|
+
// Add keys to whitelist
|
|
527
|
+
self.options.whitelistKeys = self.options.whitelistKeys.concat(keys);
|
|
528
|
+
|
|
529
|
+
return self;
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
Usage.prototype.log = function () {
|
|
533
|
+
const self = this;
|
|
534
|
+
|
|
535
|
+
// Log
|
|
536
|
+
if (self.options.log) {
|
|
537
|
+
self.ctx.log(...arguments);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
module.exports = Usage;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User — thin wrapper over @omega.js/account, the single source of truth for
|
|
3
|
+
* the OMEGA user/account schema (shared with @omega.js/client, so a doc resolved
|
|
4
|
+
* here is byte-identical to one resolved on the frontend).
|
|
5
|
+
*
|
|
6
|
+
* @omega.js/backend's contribution is injecting the real value generators for the
|
|
7
|
+
* '$uuid'/'$randomId'/'$apiKey' schema tokens — the frontend injects none and
|
|
8
|
+
* those fields resolve to null (real values always come from the backend).
|
|
9
|
+
* API unchanged:
|
|
10
|
+
* new User(Manager, settings).properties
|
|
11
|
+
* User.resolveSubscription(accountOrUserInstance)
|
|
12
|
+
*/
|
|
13
|
+
const uuid4 = require('uuid').v4;
|
|
14
|
+
const UIDGenerator = require('uid-generator');
|
|
15
|
+
const uidgen = new UIDGenerator(256);
|
|
16
|
+
|
|
17
|
+
// @omega.js/account is a private workspace package: in the monorepo the bare
|
|
18
|
+
// specifier resolves via the workspace link (and the prepare-package vendor
|
|
19
|
+
// hook rewrites it in dist/), but src/ ships in the tarball UNREWRITTEN and
|
|
20
|
+
// the test corpus deep-requires it in consumers — so fall back to the copy
|
|
21
|
+
// vendored into dist/, which sits at the same depth from both trees.
|
|
22
|
+
let account;
|
|
23
|
+
try {
|
|
24
|
+
account = require('../../vendor/account/index.js');
|
|
25
|
+
} catch (e) {
|
|
26
|
+
account = require('../../../dist/vendor/account/index.js');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function User(Manager, settings) {
|
|
30
|
+
const self = this;
|
|
31
|
+
|
|
32
|
+
self.Manager = Manager;
|
|
33
|
+
|
|
34
|
+
settings = settings || {};
|
|
35
|
+
|
|
36
|
+
self.properties = account.resolveAccount(settings, {
|
|
37
|
+
generators: {
|
|
38
|
+
uuid: () => `${uuid4()}`,
|
|
39
|
+
randomId: () => Manager.Utilities().randomId({ size: 8 }),
|
|
40
|
+
apiKey: () => `${uidgen.generateSync()}`,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return self;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
User.resolveSubscription = account.resolveSubscription;
|
|
48
|
+
|
|
49
|
+
// The schema's own EMPTY discount node, which is what a CLEARED discount is
|
|
50
|
+
// ([#333](https://github.com/Omega-JS-Stack/omega/issues/333)). The webhook
|
|
51
|
+
// pipeline clears the node with a MERGE write, so every field has to be named or
|
|
52
|
+
// half of the old claim survives it. Read off the resolver rather than spelled
|
|
53
|
+
// out again: the node's shape keeps its one home in the schema, and a field
|
|
54
|
+
// added there is cleared without anyone remembering a second list.
|
|
55
|
+
User.EMPTY_DISCOUNT = account.resolveAccount({}).subscription.discount;
|
|
56
|
+
|
|
57
|
+
module.exports = User;
|