@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
package/README.md
ADDED
|
@@ -0,0 +1,1053 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://itwcreativeworks.com">
|
|
3
|
+
<img src="https://cdn.itwcreativeworks.com/assets/itw-creative-works/images/logo/itw-creative-works-brandmark-black-x.svg" width="100px">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>OMEGA Backend</strong> — all-in-one development framework for Firebase Cloud Functions backends. Sister project to
|
|
9
|
+
<a href="../desktop/">@omega.js/desktop</a>,
|
|
10
|
+
<a href="../extension/">@omega.js/extension</a>, and
|
|
11
|
+
<a href="https://github.com/itw-creative-works/ultimate-jekyll-manager">Ultimate Jekyll Manager</a>.
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @omega.js/backend
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Requirements:**
|
|
21
|
+
- Node.js 22
|
|
22
|
+
- Firebase project with Firestore and Authentication enabled
|
|
23
|
+
- `service-account.json` - Firebase service account credentials
|
|
24
|
+
- `config/omega.json5` - OMEGA configuration file (in your functions directory)
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
Create `functions/index.js`:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const Manager = (new (require('@omega.js/backend'))).init(exports, {
|
|
32
|
+
setupFunctionsIdentity: true,
|
|
33
|
+
});
|
|
34
|
+
const { functions } = Manager.libraries;
|
|
35
|
+
|
|
36
|
+
// Create a custom function
|
|
37
|
+
exports.myEndpoint = functions
|
|
38
|
+
.runWith({ memory: '256MB', timeoutSeconds: 120 })
|
|
39
|
+
.https.onRequest((req, res) => Manager.Middleware(req, res).run('myEndpoint', { /* options */ }));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Create `functions/routes/myEndpoint/index.js`:
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
function Route() {}
|
|
46
|
+
|
|
47
|
+
Route.prototype.main = async function (ctx) {
|
|
48
|
+
const Manager = ctx.Manager;
|
|
49
|
+
const user = ctx.usage.user;
|
|
50
|
+
const settings = ctx.settings;
|
|
51
|
+
|
|
52
|
+
ctx.log('Request data:', ctx.request.data);
|
|
53
|
+
|
|
54
|
+
// Return response
|
|
55
|
+
ctx.respond({ success: true, timestamp: new Date().toISOString() });
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = Route;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Create `functions/schemas/myEndpoint/index.js`:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
module.exports = function (ctx) {
|
|
65
|
+
return {
|
|
66
|
+
defaults: {
|
|
67
|
+
message: {
|
|
68
|
+
types: ['string'],
|
|
69
|
+
default: 'Hello World',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Run any verb; the first one scaffolds the project:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx omega test
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Initialization Options
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
const Manager = (new (require('@omega.js/backend'))).init(exports, options);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Option | Default | Description |
|
|
89
|
+
|--------|---------|-------------|
|
|
90
|
+
| `initialize` | `true` | Initialize Firebase Admin SDK |
|
|
91
|
+
| `projectType` | `targets.backend.projectType` (default `'firebase'`) | `'firebase'` for Cloud Functions, `'custom'` for an Express server on `PORT`. The brand's `config/omega.json5` is the switch ([#584](https://github.com/Omega-JS-Stack/omega/issues/584)) — pass it here only to override the config |
|
|
92
|
+
| `setupFunctions` | `true` | Setup built-in Cloud Functions (`omega_api`, etc.) |
|
|
93
|
+
| `setupFunctionsIdentity` | `true` | Setup auth event functions (onCreate, onDelete, beforeCreate, beforeSignIn) |
|
|
94
|
+
| `setupFunctionsLegacy` | `false` | Setup legacy admin functions |
|
|
95
|
+
| `setupServer` | `true` | Setup custom Express server for routes |
|
|
96
|
+
| `routes` | `'/routes'` | Directory for custom route handlers |
|
|
97
|
+
| `schemas` | `'/schemas'` | Directory for schema definitions |
|
|
98
|
+
| `resourceZone` | `'us-central1'` | Firebase/GCP region |
|
|
99
|
+
| `sentry` | `true` | Enable Sentry error tracking |
|
|
100
|
+
| `serviceAccountPath` | `'service-account.json'` | Path to Firebase service account |
|
|
101
|
+
| `initializeLocalStorage` | `false` | Initialize local lowdb storage on startup |
|
|
102
|
+
| `checkNodeVersion` | `true` | Validate Node.js version on startup |
|
|
103
|
+
| `express.bodyParser.json` | `{ limit: '100kb' }` | Express JSON body parser options |
|
|
104
|
+
| `express.bodyParser.urlencoded` | `{ limit: '100kb', extended: true }` | Express URL-encoded options |
|
|
105
|
+
|
|
106
|
+
## Configuration File
|
|
107
|
+
|
|
108
|
+
Create `config/omega.json5` in your functions directory (the first verb scaffolds it from the template). Shared sections (`brand`, `cloud`, `analytics`, `payment`, `monitoring`, `connections`) sit at the top level with identical spelling in every OMEGA project; backend-specific settings live under `targets.backend`. Secrets NEVER go in this file — they belong in `.env` (the loader hard-fails on secret-shaped keys).
|
|
109
|
+
|
|
110
|
+
```json5
|
|
111
|
+
{
|
|
112
|
+
brand: {
|
|
113
|
+
id: 'my-app',
|
|
114
|
+
name: 'My Brand',
|
|
115
|
+
url: 'https://example.com',
|
|
116
|
+
contact: {
|
|
117
|
+
email: 'support@example.com',
|
|
118
|
+
},
|
|
119
|
+
images: {
|
|
120
|
+
wordmark: 'https://example.com/wordmark.png',
|
|
121
|
+
brandmark: 'https://example.com/brandmark.png',
|
|
122
|
+
combomark: 'https://example.com/combomark.png',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
monitoring: {
|
|
126
|
+
providers: {
|
|
127
|
+
sentry: {
|
|
128
|
+
dsn: 'https://xxx@xxx.ingest.sentry.io/xxx',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
analytics: {
|
|
133
|
+
providers: {
|
|
134
|
+
google: { id: 'G-XXXXXXXXXX' },
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
cloud: {
|
|
138
|
+
provider: 'firebase',
|
|
139
|
+
config: {
|
|
140
|
+
apiKey: 'xxx',
|
|
141
|
+
authDomain: 'your-brand.com', // brand host — the web build self-hosts /__/auth/*
|
|
142
|
+
projectId: 'project-id',
|
|
143
|
+
storageBucket: 'project-id.appspot.com',
|
|
144
|
+
messagingSenderId: '123456789',
|
|
145
|
+
appId: '1:123:web:456',
|
|
146
|
+
measurementId: 'G-XXXXXXXXXX',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
targets: {
|
|
150
|
+
backend: {
|
|
151
|
+
parent: '',
|
|
152
|
+
github: { user: 'username' },
|
|
153
|
+
marketing: { /* campaigns, newsletter, prune */ },
|
|
154
|
+
reviews: { enabled: true, sites: ['trustpilot.com'] },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
In a brand monorepo (`{brand}/targets/backend`), shared sections can live in the brand root's `config/omega.json5` instead — the loader merges `brand shared → brand targets.backend → local shared → local targets.backend`, and any shared key inside `targets.backend` acts as a backend-only override.
|
|
161
|
+
|
|
162
|
+
## Creating Custom Functions
|
|
163
|
+
|
|
164
|
+
### Routes
|
|
165
|
+
|
|
166
|
+
Routes handle HTTP requests. Create files in your `routes/` directory:
|
|
167
|
+
|
|
168
|
+
**Structure:**
|
|
169
|
+
- `routes/{name}/index.js` - Handles all HTTP methods
|
|
170
|
+
- `routes/{name}/get.js` - Handles GET requests only
|
|
171
|
+
- `routes/{name}/post.js` - Handles POST requests only
|
|
172
|
+
- (also supports `put.js`, `delete.js`, `patch.js`)
|
|
173
|
+
|
|
174
|
+
**Route File Pattern:**
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
function Route() {}
|
|
178
|
+
|
|
179
|
+
Route.prototype.main = async function (ctx) {
|
|
180
|
+
// Access Manager and helpers
|
|
181
|
+
const Manager = ctx.Manager;
|
|
182
|
+
const usage = ctx.usage;
|
|
183
|
+
const user = ctx.usage.user;
|
|
184
|
+
const analytics = ctx.analytics;
|
|
185
|
+
const settings = ctx.settings;
|
|
186
|
+
|
|
187
|
+
// Access request data
|
|
188
|
+
const data = ctx.request.data; // Merged body + query
|
|
189
|
+
const body = ctx.request.body; // POST body
|
|
190
|
+
const query = ctx.request.query; // Query params
|
|
191
|
+
const headers = ctx.request.headers;
|
|
192
|
+
const method = ctx.request.method;
|
|
193
|
+
const geolocation = ctx.request.geolocation; // { ip, country, region, city, latitude, longitude }
|
|
194
|
+
const client = ctx.request.client; // { userAgent, language, platform, mobile }
|
|
195
|
+
|
|
196
|
+
// Check authentication
|
|
197
|
+
if (!user.authenticated) {
|
|
198
|
+
return ctx.respond('Authentication required', { code: 401 });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Check admin role
|
|
202
|
+
if (!user.roles.admin) {
|
|
203
|
+
return ctx.respond('Admin required', { code: 403 });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Track analytics
|
|
207
|
+
analytics.event('my_event', { action: 'test' });
|
|
208
|
+
|
|
209
|
+
// Count a use of a metered feature — check, count and write in ONE call,
|
|
210
|
+
// throwing a 429 over limit
|
|
211
|
+
await usage.consume('requests');
|
|
212
|
+
|
|
213
|
+
// Send response
|
|
214
|
+
ctx.respond({ success: true, data: settings });
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
module.exports = Route;
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Schemas
|
|
221
|
+
|
|
222
|
+
Schemas define and validate request parameters with defaults and plan-based limits:
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
module.exports = function (ctx, settings, options) {
|
|
226
|
+
const user = options.user;
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
// Default values for all plans
|
|
230
|
+
defaults: {
|
|
231
|
+
message: {
|
|
232
|
+
types: ['string'],
|
|
233
|
+
default: 'Hello',
|
|
234
|
+
required: false,
|
|
235
|
+
},
|
|
236
|
+
count: {
|
|
237
|
+
types: ['number'],
|
|
238
|
+
default: 10,
|
|
239
|
+
min: 1,
|
|
240
|
+
max: 100,
|
|
241
|
+
},
|
|
242
|
+
format: {
|
|
243
|
+
types: ['string'],
|
|
244
|
+
default: 'json',
|
|
245
|
+
// Dynamic required based on other settings
|
|
246
|
+
required: (ctx, settings) => settings.output === 'file',
|
|
247
|
+
// Clean/sanitize input
|
|
248
|
+
clean: (value) => value.toLowerCase().trim(),
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
// Override defaults for premium plan
|
|
253
|
+
premium: {
|
|
254
|
+
count: {
|
|
255
|
+
types: ['number'],
|
|
256
|
+
default: 100,
|
|
257
|
+
max: 1000,
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Schema Property Options:**
|
|
265
|
+
|
|
266
|
+
| Property | Type | Description |
|
|
267
|
+
|----------|------|-------------|
|
|
268
|
+
| `types` | `string[]` | Allowed types: `'string'`, `'number'`, `'boolean'`, `'object'`, `'array'` |
|
|
269
|
+
| `default` | `any` | Default value if not provided |
|
|
270
|
+
| `required` | `boolean \| function` | Whether the field is required |
|
|
271
|
+
| `clean` | `RegExp \| function` | Sanitize/transform the value |
|
|
272
|
+
| `min` | `number` | Minimum value (for numbers) |
|
|
273
|
+
| `max` | `number` | Maximum value (for numbers) |
|
|
274
|
+
| `available` | `boolean` | Whether the field is available |
|
|
275
|
+
|
|
276
|
+
### Middleware Options
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
Manager.Middleware(req, res).run('routeName', {
|
|
280
|
+
authenticate: true, // Authenticate user (default: true)
|
|
281
|
+
setupAnalytics: true, // Initialize analytics (default: true)
|
|
282
|
+
setupUsage: true, // Initialize usage tracking (default: true)
|
|
283
|
+
setupSettings: true, // Resolve settings from schema (default: true)
|
|
284
|
+
schema: 'routeName', // Schema file to use (default: same as route)
|
|
285
|
+
parseMultipartFormData: true, // Parse multipart uploads (default: true)
|
|
286
|
+
routesDir: '/routes', // Custom routes directory
|
|
287
|
+
schemasDir: '/schemas', // Custom schemas directory
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Built-in Functions
|
|
292
|
+
|
|
293
|
+
### HTTP API (`omega_api`)
|
|
294
|
+
|
|
295
|
+
The main API endpoint serves the RESTful routes system. Requests to `/omega/<route>` (hosting rewrite; the legacy `/backend-manager/` prefix works as an alias) resolve to `routes/{name}/{method}.js` handlers with their matching schemas — see [Creating Custom Functions](#creating-custom-functions) above.
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
// POST https://api.<yourdomain>/omega/user/token
|
|
299
|
+
// → routes/user/token/post.js (responds { token })
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Auth Events
|
|
303
|
+
|
|
304
|
+
| Function | Trigger | Description |
|
|
305
|
+
|----------|---------|-------------|
|
|
306
|
+
| `omega_authBeforeCreate` | `beforeUserCreated` | Runs before user creation, can block signup |
|
|
307
|
+
| `omega_authBeforeSignIn` | `beforeUserSignedIn` | Runs before sign-in, can block login |
|
|
308
|
+
| `omega_authOnCreate` | `onCreate` | Runs after user creation, creates user document |
|
|
309
|
+
| `omega_authOnDelete` | `onDelete` | Runs when user is deleted, cleanup |
|
|
310
|
+
|
|
311
|
+
### Firestore Events
|
|
312
|
+
|
|
313
|
+
| Function | Trigger | Description |
|
|
314
|
+
|----------|---------|-------------|
|
|
315
|
+
| `omega_notificationsOnWrite` | `onWrite` | Triggers on `notifications/{id}` changes |
|
|
316
|
+
|
|
317
|
+
### Cron Jobs
|
|
318
|
+
|
|
319
|
+
| Function | Schedule | Description |
|
|
320
|
+
|----------|----------|-------------|
|
|
321
|
+
| `omega_cronDaily` | Every 24 hours | Runs daily jobs from `cron/daily/` and `hooks/cron/daily/` |
|
|
322
|
+
|
|
323
|
+
**Creating Custom Cron Jobs:**
|
|
324
|
+
|
|
325
|
+
Create `hooks/cron/daily/myJob.js` in your functions directory:
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
function Job() {}
|
|
329
|
+
|
|
330
|
+
Job.prototype.main = function () {
|
|
331
|
+
const self = this;
|
|
332
|
+
const Manager = self.Manager;
|
|
333
|
+
const ctx = self.ctx;
|
|
334
|
+
|
|
335
|
+
return new Promise(async function(resolve, reject) {
|
|
336
|
+
ctx.log('Running my daily job...');
|
|
337
|
+
|
|
338
|
+
// Your job logic here
|
|
339
|
+
|
|
340
|
+
return resolve();
|
|
341
|
+
});
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
module.exports = Job;
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Email System
|
|
348
|
+
|
|
349
|
+
Unified MJML-based email rendering for transactional, marketing, and newsletter emails. All emails are rendered server-side — no SendGrid dynamic templates.
|
|
350
|
+
|
|
351
|
+
- **Unified pipeline** — shared `prepare.js` layer for brand, sender, content, signoff, categories, unsubscribe URL
|
|
352
|
+
- **Composable template system** — `base.js` provides building blocks (skeleton, logo, card wrapper, signoff, button, footer); templates compose what they need
|
|
353
|
+
- **4 email templates** — `card` (default workhorse), `plain` (personal email feel), `order` (all 9 payment event types), `feedback` (rating faces)
|
|
354
|
+
- **MJML compilation** — templates return MJML strings, compiled to email-safe HTML via the `mjml` package
|
|
355
|
+
- **Hidden ASM + category tags** — baked into the skeleton to suppress SendGrid's auto-unsubscribe and enable email sorting
|
|
356
|
+
|
|
357
|
+
### Email API
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
const email = Manager.Email(ctx);
|
|
361
|
+
await email.send({
|
|
362
|
+
template: 'card',
|
|
363
|
+
subject: 'Welcome!',
|
|
364
|
+
to: 'user@example.com',
|
|
365
|
+
sender: 'hello',
|
|
366
|
+
data: { body: { title: 'Welcome', message: '# Hello!\n\nWelcome aboard.' } },
|
|
367
|
+
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Marketing & Campaigns
|
|
371
|
+
|
|
372
|
+
Built-in marketing system with multi-provider support (SendGrid + Beehiiv + FCM push).
|
|
373
|
+
|
|
374
|
+
- **Contact management** — add, sync, remove contacts across providers with custom field syncing
|
|
375
|
+
- **Campaign CRUD** — `POST/GET/PUT/DELETE /marketing/campaign` with calendar-backed scheduling
|
|
376
|
+
- **Recurring campaigns** — seasonal sales, newsletters with automatic sendAt advancement
|
|
377
|
+
- **Newsletter generator** — AI-assembled newsletters from parent server content sources
|
|
378
|
+
- **Newsletter-driven blog articles** — `content.article.enabled` expands the newsletter's lead section into a full blog post (via Ghostii → `admin/post`) and links to it with a "Read the full article" CTA
|
|
379
|
+
- **Segment SSOT** — 22 segment definitions resolved to provider IDs at runtime
|
|
380
|
+
- **UTM auto-tagging** — brand domain links tagged automatically in marketing + transactional emails
|
|
381
|
+
- **Contact pruning** — monthly 2-stage re-engagement + deletion of inactive contacts
|
|
382
|
+
- **Template variables** — `{brand.name}`, `{holiday.name}`, `{season.name}`, `{date.*}` resolved at send time
|
|
383
|
+
|
|
384
|
+
Configure via the `marketing` section under `targets.backend` in `config/omega.json5`. See [docs/marketing-campaigns.md](docs/marketing-campaigns.md) and [docs/marketing-fields.md](docs/marketing-fields.md) for full documentation.
|
|
385
|
+
|
|
386
|
+
## Marketing Consent
|
|
387
|
+
|
|
388
|
+
GDPR/CASL-compliant consent capture and cross-provider unsubscribe sync.
|
|
389
|
+
|
|
390
|
+
- **Two-checkbox signup form** — separate legal (required) and marketing (optional) consent
|
|
391
|
+
- **Canonical user-doc shape** — `consent.{legal,marketing}.{status, grantedAt, revokedAt}` with full audit metadata (timestamp, source, IP, exact label text)
|
|
392
|
+
- **Server-authoritative timestamps** — client timestamps ignored, defending against clock manipulation
|
|
393
|
+
- **Account-page toggle** — `/account` notifications section lets logged-in users opt in/out, hits both SendGrid + Beehiiv
|
|
394
|
+
- **HMAC unsubscribe links** — email-footer one-click flow continues to work; unsubscribe removes the contact from ALL providers (not just the SendGrid ASM group), re-subscribe re-adds the contact
|
|
395
|
+
- **Provider webhook receivers** — `POST /marketing/webhook?provider=sendgrid|beehiiv&key=X` catches unsubscribe / spam / bounce events from SendGrid and Beehiiv, writes the user doc + syncs to the OTHER provider
|
|
396
|
+
- **Parent forwarder** — single public webhook endpoint (`/marketing/webhook/forward`) on the parent @omega.js/backend fans out to every brand's child @omega.js/backend so each one updates its own Firestore
|
|
397
|
+
- **Library-level consent gate** — `email.add()` and `email.sync()` skip users whose `consent.marketing.status === 'revoked'` (covers every call site: payment syncs, admin re-syncs, newsletter form); admin contact DELETE mirrors `revoked` back to the user doc so removals stick
|
|
398
|
+
|
|
399
|
+
See [docs/consent.md](docs/consent.md) for the full architecture, source enum reference, migration script template, and provider configuration steps.
|
|
400
|
+
|
|
401
|
+
## Helper Classes
|
|
402
|
+
|
|
403
|
+
### RouteContext
|
|
404
|
+
|
|
405
|
+
Handles request/response lifecycle, authentication, and logging.
|
|
406
|
+
|
|
407
|
+
```javascript
|
|
408
|
+
const ctx = Manager.RouteContext({ req, res });
|
|
409
|
+
|
|
410
|
+
// Authentication
|
|
411
|
+
const user = await ctx.authenticate();
|
|
412
|
+
// Returns: { authenticated, auth: { uid, email }, roles, plan, ... }
|
|
413
|
+
|
|
414
|
+
// Request data
|
|
415
|
+
ctx.request.data; // Merged body + query
|
|
416
|
+
ctx.request.body; // POST body
|
|
417
|
+
ctx.request.query; // Query params
|
|
418
|
+
ctx.request.headers; // Request headers
|
|
419
|
+
ctx.request.method; // HTTP method
|
|
420
|
+
ctx.request.geolocation; // { ip, country, region, city, latitude, longitude }
|
|
421
|
+
ctx.request.client; // { userAgent, language, platform, mobile }
|
|
422
|
+
|
|
423
|
+
// Response
|
|
424
|
+
ctx.respond({ success: true }); // 200 JSON
|
|
425
|
+
ctx.respond({ success: true }, { code: 201 }); // Custom status
|
|
426
|
+
ctx.respond('https://example.com', { code: 302 }); // Redirect
|
|
427
|
+
|
|
428
|
+
// Errors
|
|
429
|
+
ctx.report('Something went wrong', { code: 500, sentry: true });
|
|
430
|
+
ctx.respond(new Error('Bad request'), { code: 400 });
|
|
431
|
+
|
|
432
|
+
// Logging
|
|
433
|
+
ctx.log('Info message');
|
|
434
|
+
ctx.warn('Warning message');
|
|
435
|
+
ctx.error('Error message');
|
|
436
|
+
ctx.debug('Debug message');
|
|
437
|
+
|
|
438
|
+
// Environment
|
|
439
|
+
ctx.isDevelopment(); // true in emulator
|
|
440
|
+
ctx.isProduction(); // true in production
|
|
441
|
+
ctx.isTesting(); // true when running tests
|
|
442
|
+
|
|
443
|
+
// File uploads
|
|
444
|
+
const { fields, files } = await ctx.parseMultipartFormData();
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### User
|
|
448
|
+
|
|
449
|
+
Creates user objects with default properties:
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
const userProps = Manager.User(existingData, { defaults: true }).properties;
|
|
453
|
+
|
|
454
|
+
// User structure:
|
|
455
|
+
{
|
|
456
|
+
auth: { uid, email, temporary },
|
|
457
|
+
subscription: {
|
|
458
|
+
product: { id, name }, // product from config ('basic', 'premium', etc.)
|
|
459
|
+
status: 'active', // active | suspended | cancelled
|
|
460
|
+
expires: { timestamp, timestampUNIX },
|
|
461
|
+
trial: { claimed, expires: {...} },
|
|
462
|
+
cancellation: { pending, date: {...} },
|
|
463
|
+
limits: {},
|
|
464
|
+
payment: { provider, resourceId, frequency, startDate, updatedBy }
|
|
465
|
+
},
|
|
466
|
+
roles: { admin, betaTester, developer },
|
|
467
|
+
affiliate: { code, referrals, referrer },
|
|
468
|
+
metadata: { created, updated },
|
|
469
|
+
activity: { geolocation, client },
|
|
470
|
+
api: { clientId, privateKey },
|
|
471
|
+
usage: { requests: { monthly, daily, total, last } },
|
|
472
|
+
personal: { birthday, gender, location, name, company, telephone },
|
|
473
|
+
connections: {}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Methods
|
|
477
|
+
userProps.merge(otherUser); // Merge with another user object
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Analytics
|
|
481
|
+
|
|
482
|
+
Send events to Google Analytics 4:
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
const analytics = Manager.Analytics({
|
|
486
|
+
ctx: ctx,
|
|
487
|
+
uuid: user.auth.uid,
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
analytics.event('purchase', {
|
|
491
|
+
item_id: 'product-123',
|
|
492
|
+
value: 29.99,
|
|
493
|
+
currency: 'USD',
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Auto-tracked User Properties:**
|
|
498
|
+
- `app_version`, `device_category`, `operating_system`, `platform`
|
|
499
|
+
- `authenticated`, `subscription_id`, `subscription_trial_claimed`, `activity_created`
|
|
500
|
+
- `country`, `city`, `language`, `age`, `gender`
|
|
501
|
+
|
|
502
|
+
### Usage
|
|
503
|
+
|
|
504
|
+
Track and limit API usage:
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
// The middleware attaches `ctx.usage` to every route. Attaching is I/O-free —
|
|
508
|
+
// the counter resolves the account on its first consume()/read()
|
|
509
|
+
const usage = ctx.usage;
|
|
510
|
+
|
|
511
|
+
// Read the state WITHOUT counting: the effective limit (per-user overrides
|
|
512
|
+
// applied), both counters, and what is left of each
|
|
513
|
+
const state = await usage.read('requests');
|
|
514
|
+
// → { limit, planLimit, override, used, left, day: { limit, used, left }, ... }
|
|
515
|
+
|
|
516
|
+
// Count a use: check both counters, refuse with a 429 naming which one hit,
|
|
517
|
+
// else count and write. Returns what is left.
|
|
518
|
+
const left = await usage.consume('requests'); // { used, left, day: { used, left } }
|
|
519
|
+
await usage.consume('requests', 5); // a bigger bite
|
|
520
|
+
|
|
521
|
+
// Whitelist keys (they never get refused, and still count)
|
|
522
|
+
usage.addWhitelistKeys(['another-key']);
|
|
523
|
+
|
|
524
|
+
// An anonymous key is EXPLICIT — a SEPARATE counter, so a key can never move a
|
|
525
|
+
// signed-in user's own counters into the anonymous store
|
|
526
|
+
await usage.forKey(ctx.request.geolocation.ip).consume('signups', 1, { limit: 5 });
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
A feature is defined ONCE in the top-level `features` catalog (name, icon, definition, and the `usage` block that meters it); each product names only its VALUE. Mirrors are declared there too — no call-site mirror API. Full reference: [docs/usage-rate-limiting.md](docs/usage-rate-limiting.md).
|
|
530
|
+
|
|
531
|
+
### Middleware
|
|
532
|
+
|
|
533
|
+
Process requests through the middleware pipeline:
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
// In your function definition
|
|
537
|
+
exports.myEndpoint = functions
|
|
538
|
+
.https.onRequest((req, res) => Manager.Middleware(req, res).run('myEndpoint', {
|
|
539
|
+
authenticate: true,
|
|
540
|
+
setupAnalytics: true,
|
|
541
|
+
setupUsage: true,
|
|
542
|
+
setupSettings: true,
|
|
543
|
+
schema: 'myEndpoint',
|
|
544
|
+
}));
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
The middleware automatically:
|
|
548
|
+
1. Parses multipart form data
|
|
549
|
+
2. Logs request details
|
|
550
|
+
3. Loads route handler (method-specific or index.js)
|
|
551
|
+
4. Authenticates user
|
|
552
|
+
5. Initializes usage tracking
|
|
553
|
+
6. Sets up analytics
|
|
554
|
+
7. Resolves settings from schema
|
|
555
|
+
8. Calls your route handler
|
|
556
|
+
|
|
557
|
+
### Settings
|
|
558
|
+
|
|
559
|
+
Resolve and validate request settings against a schema:
|
|
560
|
+
|
|
561
|
+
```javascript
|
|
562
|
+
const settings = Manager.Settings().resolve(ctx, schema, inputSettings, {
|
|
563
|
+
dir: '/schemas',
|
|
564
|
+
schema: 'mySchema',
|
|
565
|
+
user: user,
|
|
566
|
+
checkRequired: true,
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// Timestamp constants
|
|
570
|
+
const timestamp = Manager.Settings().constant('timestamp');
|
|
571
|
+
// { types: ['string'], value: undefined, default: '2024-01-01T00:00:00.000Z' }
|
|
572
|
+
|
|
573
|
+
const timestampUNIX = Manager.Settings().constant('timestampUNIX');
|
|
574
|
+
// { types: ['number'], value: undefined, default: 1704067200 }
|
|
575
|
+
|
|
576
|
+
const timestampFULL = Manager.Settings().constant('timestampFULL');
|
|
577
|
+
// { timestamp: {...}, timestampUNIX: {...} }
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Utilities
|
|
581
|
+
|
|
582
|
+
Batch operations and helper functions:
|
|
583
|
+
|
|
584
|
+
```javascript
|
|
585
|
+
const utilities = Manager.Utilities();
|
|
586
|
+
|
|
587
|
+
// Batch iterate Firestore collection
|
|
588
|
+
const results = await utilities.iterateCollection(
|
|
589
|
+
async ({ docs }, batch, totalCount) => {
|
|
590
|
+
for (const doc of docs) {
|
|
591
|
+
// Process each document
|
|
592
|
+
}
|
|
593
|
+
return { processed: docs.length };
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
collection: 'users',
|
|
597
|
+
batchSize: 1000,
|
|
598
|
+
maxBatches: 10,
|
|
599
|
+
where: [{ field: 'subscription.product.id', operator: '==', value: 'premium' }],
|
|
600
|
+
orderBy: { field: 'metadata.created.timestamp', direction: 'desc' },
|
|
601
|
+
startAfter: 'lastDocId',
|
|
602
|
+
log: true,
|
|
603
|
+
}
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
// Batch iterate Firebase Auth users
|
|
607
|
+
await utilities.iterateUsers(
|
|
608
|
+
async ({ users, pageToken }, batch) => {
|
|
609
|
+
for (const user of users) {
|
|
610
|
+
// Process each auth user
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
batchSize: 1000,
|
|
615
|
+
maxBatches: Infinity,
|
|
616
|
+
log: true,
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
// Get document with owner user
|
|
621
|
+
const { document, user } = await utilities.getDocumentWithOwnerUser('posts/abc123', {
|
|
622
|
+
owner: 'owner',
|
|
623
|
+
resolve: {
|
|
624
|
+
schema: 'posts',
|
|
625
|
+
ctx: ctx,
|
|
626
|
+
checkRequired: false,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// Generate random ID
|
|
631
|
+
const id = utilities.randomId({ size: 14 }); // 'A1b2C3d4E5f6G7'
|
|
632
|
+
|
|
633
|
+
// Cached Firestore read
|
|
634
|
+
const doc = await utilities.get('users/abc123', {
|
|
635
|
+
maxAge: 1000 * 60 * 5, // 5 minute cache
|
|
636
|
+
format: 'data', // 'raw' or 'data'
|
|
637
|
+
});
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### Metadata
|
|
641
|
+
|
|
642
|
+
Add timestamps and tags to documents:
|
|
643
|
+
|
|
644
|
+
```javascript
|
|
645
|
+
const metadata = Manager.Metadata(document);
|
|
646
|
+
|
|
647
|
+
document.metadata = metadata.set({ tag: 'my-operation' });
|
|
648
|
+
// {
|
|
649
|
+
// updated: { timestamp: '...', timestampUNIX: ... },
|
|
650
|
+
// tag: 'my-operation'
|
|
651
|
+
// }
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### Local Storage
|
|
655
|
+
|
|
656
|
+
Persistent JSON storage using lowdb:
|
|
657
|
+
|
|
658
|
+
```javascript
|
|
659
|
+
const storage = Manager.storage({
|
|
660
|
+
name: 'myStorage', // Storage name (default: 'main')
|
|
661
|
+
temporary: false, // Use OS temp directory (default: false)
|
|
662
|
+
clear: true, // Clear on dev startup (default: true)
|
|
663
|
+
log: false, // Enable logging
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// lowdb API
|
|
667
|
+
storage.set('key', 'value').write();
|
|
668
|
+
const value = storage.get('key').value();
|
|
669
|
+
storage.set('nested.path', { data: true }).write();
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## Authentication
|
|
673
|
+
|
|
674
|
+
@omega.js/backend supports multiple authentication methods (checked in order):
|
|
675
|
+
|
|
676
|
+
1. **Bearer Token (JWT)**
|
|
677
|
+
```
|
|
678
|
+
Authorization: Bearer <firebase-id-token>
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
2. **API Key**
|
|
682
|
+
```javascript
|
|
683
|
+
{ apiKey: 'user-private-key' }
|
|
684
|
+
// or
|
|
685
|
+
{ authenticationToken: 'user-private-key' }
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
3. **OMEGA Admin Key** (Admin access — header only, never query/body)
|
|
689
|
+
```
|
|
690
|
+
omega-admin-key: <OMEGA_ADMIN_KEY>
|
|
691
|
+
```
|
|
692
|
+
A separate lane from `Authorization` (which stays user-only), so one request can be admin-authenticated AND carry a user token at the same time.
|
|
693
|
+
|
|
694
|
+
4. **Session Cookie**
|
|
695
|
+
```
|
|
696
|
+
Cookie: __session=<firebase-id-token>
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
**Authenticated User Object:**
|
|
700
|
+
|
|
701
|
+
```javascript
|
|
702
|
+
const user = await ctx.authenticate();
|
|
703
|
+
|
|
704
|
+
{
|
|
705
|
+
authenticated: true,
|
|
706
|
+
auth: { uid: 'abc123', email: 'user@example.com' },
|
|
707
|
+
roles: { admin: false, betaTester: false, developer: false },
|
|
708
|
+
subscription: { product: { id: 'basic', name: 'Basic' }, status: 'active', ... },
|
|
709
|
+
api: { clientId: '...', privateKey: '...' },
|
|
710
|
+
// ... other user properties
|
|
711
|
+
}
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
## CLI Commands
|
|
715
|
+
|
|
716
|
+
@omega.js/backend includes a CLI for development and deployment:
|
|
717
|
+
|
|
718
|
+
```bash
|
|
719
|
+
# Install globally or use npx
|
|
720
|
+
npm install -g @omega.js/backend
|
|
721
|
+
# or
|
|
722
|
+
npx @omega.js/backend <command>
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
| Command | Description |
|
|
726
|
+
|---------|-------------|
|
|
727
|
+
| `mgr setup` | Run Firebase project setup and validation |
|
|
728
|
+
| `mgr serve` | Start local Firebase emulator |
|
|
729
|
+
| `mgr deploy` | Deploy functions to Firebase |
|
|
730
|
+
| `mgr test [paths...]` | Run integration tests |
|
|
731
|
+
| `mgr emulator` | Start Firebase emulator (keep-alive mode; HTTPS proxy on the public port, `--no-https` for plain http) |
|
|
732
|
+
| `mgr stripe` | Start Stripe CLI webhook forwarding to local server |
|
|
733
|
+
| `mgr version`, `mgr v` | Show @omega.js/backend version |
|
|
734
|
+
| `mgr clear` | Clear cache and temp files |
|
|
735
|
+
| `mgr install`, `mgr i` | Install @omega.js/backend (local — links every `@omega.js/*` dep from the Omega monorepo — or production) |
|
|
736
|
+
| `mgr clean` | Clean and reinstall npm modules (alias `clean:npm`) |
|
|
737
|
+
| `mgr help`, `mgr -h` | Print the command listing; bare `mgr` runs `setup`, unknown commands print the listing and exit 1 |
|
|
738
|
+
| `mgr firestore:indexes:get` | Get Firestore indexes |
|
|
739
|
+
| `mgr cwd` | Show current working directory |
|
|
740
|
+
| `mgr firestore:get <path>` | Read a Firestore document |
|
|
741
|
+
| `mgr firestore:set <path> '<json>'` | Write/merge a Firestore document (emulator unless `--production`) |
|
|
742
|
+
| `mgr firestore:query <collection>` | Query a Firestore collection |
|
|
743
|
+
| `mgr firestore:delete <path>` | Delete a Firestore document (emulator unless `--production`) |
|
|
744
|
+
| `mgr auth:get <uid-or-email>` | Get an Auth user by UID or email |
|
|
745
|
+
| `mgr auth:list` | List Auth users |
|
|
746
|
+
| `mgr auth:delete <uid-or-email>` | Delete an Auth user (emulator unless `--production`) |
|
|
747
|
+
| `mgr auth:set-claims <uid-or-email> '<json>'` | Set custom claims on an Auth user (emulator unless `--production`) |
|
|
748
|
+
| `mgr logs:read` | Fetch Cloud Function logs from Google Cloud Logging |
|
|
749
|
+
| `mgr logs:tail` | Stream live Cloud Function logs |
|
|
750
|
+
|
|
751
|
+
Every Firestore/Auth subcommand — reads and writes alike — targets the local emulator by default and reaches live only with `--production` (one rule, no exceptions; `--emulator` is accepted but just names the default). All of them support `--force` to skip confirmation and `--raw` for compact JSON output, and every one prints the stack it hit.
|
|
752
|
+
|
|
753
|
+
Logs commands support `--fn <name>` (function name filter), `--severity <level>`, `--since <duration>` (read only), `--limit <n>` (read only), and `--raw`. Requires `gcloud` CLI installed and authenticated.
|
|
754
|
+
|
|
755
|
+
## Environment Variables
|
|
756
|
+
|
|
757
|
+
Set these in your `functions/.env` file:
|
|
758
|
+
|
|
759
|
+
| Variable | Description |
|
|
760
|
+
|----------|-------------|
|
|
761
|
+
| `OMEGA_ADMIN_KEY` | Admin authentication key |
|
|
762
|
+
| `STRIPE_SECRET_KEY` | Stripe secret key (enables auto webhook forwarding in `serve`/`emulator`) |
|
|
763
|
+
|
|
764
|
+
## Response Headers
|
|
765
|
+
|
|
766
|
+
@omega.js/backend attaches metadata to responses:
|
|
767
|
+
|
|
768
|
+
```
|
|
769
|
+
omega-properties: {"code":200,"tag":"functionName/executionId","usage":{...},"schema":{...}}
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
## Testing
|
|
773
|
+
|
|
774
|
+
@omega.js/backend includes an integration test framework that runs against the Firebase emulator.
|
|
775
|
+
|
|
776
|
+
### Running Tests
|
|
777
|
+
|
|
778
|
+
```bash
|
|
779
|
+
# Option 1: Two terminals (recommended for development)
|
|
780
|
+
npx omega emulator # Terminal 1 - keeps emulator running
|
|
781
|
+
npx omega test # Terminal 2 - runs tests
|
|
782
|
+
|
|
783
|
+
# Option 2: Single command (auto-starts emulator, shuts down after)
|
|
784
|
+
npx omega test
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
`npx omega emulator` **seeds the test personas on boot** (same wipe-and-create pass the test runner uses), so an emulator-connected dev site is signin-able immediately — any persona email + the deterministic `TEST_ACCOUNT_PASSWORD` (`omega-test-password`). Pass `--no-seed` to boot without seeding. Seeding is non-fatal: if it fails (e.g. missing config), the emulator keeps running. See [docs/test-framework.md](docs/test-framework.md#personas-n6).
|
|
788
|
+
|
|
789
|
+
**Ports auto-allocate (N7)**: boot resolves each emulator port from firebase.json, bumping +1 when taken — so a second brand's emulator runs ALONGSIDE the first instead of killing it (bumped runs boot via a generated, gitignored `firebase.resolved.json`; the committed firebase.json never changes). The resolved map publishes to `.temp/ports.json` (sibling processes — `omega test` reads it automatically) and `OMEGA_<NAME>_PORT` env (URL getters). Pin a port explicitly with the config `ports` section — pins never bump (busy pin = hard error). Single-brand dev on free defaults behaves exactly as before. `mgr serve` and `mgr emulator` allocate the same way (`--port` pins) and publish `https` (the mkcert proxy on the public port) + `hosting` (the internal plain-http port) so siblings — including `omega dev`'s page chrome — follow even a bumped run; Stripe forwarding targets the resolved plain-http port. Plain-http requests to the public port get a 307 redirect to https (typing `http://localhost:5002` lands in the right place). Pass `--no-https` (or run without mkcert installed) for plain http on the public port; the emulator an `omega test` run auto-starts is always plain.
|
|
790
|
+
|
|
791
|
+
### Extended Mode (real APIs)
|
|
792
|
+
|
|
793
|
+
Pass `--extended` (or set `TEST_EXTENDED_MODE=true`) on the **test command** to opt into real external API calls (SendGrid, Beehiiv, Stripe webhook handlers, marketing libraries). `--extended` is the CLI shorthand for the shared, unprefixed `TEST_EXTENDED_MODE` env var standardized across @omega.js/backend/BXM/UJM/EM — the two forms are equivalent. The mode flows automatically to BOTH the test-runner subprocess and the running emulator (via `<projectRoot>/.temp/test-mode.json`) — no need to set it on the emulator too:
|
|
794
|
+
|
|
795
|
+
```bash
|
|
796
|
+
# Terminal 1 — start once, no flag needed
|
|
797
|
+
npx omega emulator
|
|
798
|
+
|
|
799
|
+
# Terminal 2 — toggle freely between runs
|
|
800
|
+
npx omega test --extended ... # extended mode (--extended sets TEST_EXTENDED_MODE)
|
|
801
|
+
TEST_EXTENDED_MODE=true npx omega test ... # identical — the env-var form
|
|
802
|
+
npx omega test ... # normal mode (next run flips back)
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
See [docs/test-framework.md](docs/test-framework.md#extended-mode-test_extended_mode) for the full mechanism.
|
|
806
|
+
|
|
807
|
+
### Filtering Tests
|
|
808
|
+
|
|
809
|
+
```bash
|
|
810
|
+
npx omega test rules/ # Project rules tests (bare paths = project source; C5 — docs/shared/testing.md)
|
|
811
|
+
npx omega test framework:rules/ # Only @omega.js/backend's rules tests (aliases: omega:, mgr:, backend:)
|
|
812
|
+
npx omega test full:rules/ # Both sources
|
|
813
|
+
npx omega test user/ admin/ # Multiple project paths
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### Log Files
|
|
817
|
+
|
|
818
|
+
@omega.js/backend CLI commands automatically save their output — two lanes, two homes.
|
|
819
|
+
|
|
820
|
+
The **verb** tees its own run to `<projectDir>/logs/`, the lane every OMEGA framework shares:
|
|
821
|
+
- **`logs/dev.log`** — `npx omega serve` / `npx omega emulator` (port allocation, the proxy, the watcher)
|
|
822
|
+
- **`logs/build.log`** — `npx omega build`
|
|
823
|
+
- **`logs/test.log`** — `npx omega test` (setup lines, port summary, emulator boot)
|
|
824
|
+
|
|
825
|
+
The firebase **children** write to `<projectDir>/dist/`, alongside firebase-tools' own `*-debug.log` files so everything is grep-able from one place:
|
|
826
|
+
- **`dist/dev.log`** — the `firebase serve` child
|
|
827
|
+
- **`dist/emulator.log`** — full emulator + Cloud Functions output
|
|
828
|
+
- **`dist/test.log`** — the test runner child
|
|
829
|
+
- **`dist/deploy.log`** — `npx omega deploy`
|
|
830
|
+
- **`dist/production.log`** — Production Cloud Function logs (`npx omega logs:read` or `npx omega logs:tail`)
|
|
831
|
+
|
|
832
|
+
Every log is truncated on each run (`logs/` is gitignored; `dist/` output is gitignored via `*.log`), and the stale-log sweep at each verb start clears ours while deliberately leaving firebase-tools' debug logs alone. Read them to debug failing tests or review function output instead of restarting a long-running process. Transient internal artifacts (reset sentinels, watch trigger, `test-mode.json`) live separately in `<projectDir>/.temp/`. The cross-framework contract and the full path table: `docs/shared/logging.md` in the Omega repo.
|
|
833
|
+
|
|
834
|
+
### Test Locations
|
|
835
|
+
|
|
836
|
+
- **@omega.js/backend core tests:** `test/`
|
|
837
|
+
- **Project tests:** `functions/test/`
|
|
838
|
+
|
|
839
|
+
Bare runs and bare paths are PROJECT-scoped (C5); reach the framework corpus explicitly with `framework:`/`omega:`/`mgr:`/`backend:`, or `full:` for both. Grammar: docs/shared/testing.md in the Omega repo.
|
|
840
|
+
|
|
841
|
+
### Writing Tests
|
|
842
|
+
|
|
843
|
+
**Suite** - Sequential tests with shared state (stops on first failure):
|
|
844
|
+
|
|
845
|
+
```javascript
|
|
846
|
+
// test/functions/user/sign-up.js
|
|
847
|
+
module.exports = {
|
|
848
|
+
description: 'User signup flow with affiliate tracking',
|
|
849
|
+
type: 'suite',
|
|
850
|
+
tests: [
|
|
851
|
+
{
|
|
852
|
+
name: 'verify-referrer-exists',
|
|
853
|
+
async run({ firestore, assert, state, accounts }) {
|
|
854
|
+
state.referrerUid = accounts.referrer.uid;
|
|
855
|
+
const doc = await firestore.get(`users/${state.referrerUid}`);
|
|
856
|
+
assert.ok(doc, 'Referrer should exist');
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
name: 'call-user-signup-with-affiliate',
|
|
861
|
+
async run({ http, assert, state }) {
|
|
862
|
+
const response = await http.as('signup-referred').command('user:sign-up', {
|
|
863
|
+
attribution: { affiliate: { code: 'TESTREF' } },
|
|
864
|
+
});
|
|
865
|
+
assert.isSuccess(response);
|
|
866
|
+
},
|
|
867
|
+
},
|
|
868
|
+
],
|
|
869
|
+
};
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
**Group** - Independent tests (continues even if one fails):
|
|
873
|
+
|
|
874
|
+
```javascript
|
|
875
|
+
// test/functions/admin/firestore-write.js
|
|
876
|
+
module.exports = {
|
|
877
|
+
description: 'Admin Firestore write operation',
|
|
878
|
+
type: 'group',
|
|
879
|
+
tests: [
|
|
880
|
+
{
|
|
881
|
+
name: 'admin-auth-succeeds',
|
|
882
|
+
auth: 'admin',
|
|
883
|
+
async run({ http, assert }) {
|
|
884
|
+
const response = await http.command('admin:firestore-write', {
|
|
885
|
+
path: '_test/doc',
|
|
886
|
+
document: { test: 'value' },
|
|
887
|
+
});
|
|
888
|
+
assert.isSuccess(response);
|
|
889
|
+
},
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
name: 'unauthenticated-rejected',
|
|
893
|
+
auth: 'none',
|
|
894
|
+
async run({ http, assert }) {
|
|
895
|
+
const response = await http.command('admin:firestore-write', {
|
|
896
|
+
path: '_test/doc',
|
|
897
|
+
document: { test: 'value' },
|
|
898
|
+
});
|
|
899
|
+
assert.isError(response, 401);
|
|
900
|
+
},
|
|
901
|
+
},
|
|
902
|
+
],
|
|
903
|
+
};
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
**Auth levels:** `none`, `user`/`basic`, `admin`, `premium-active`, `premium-expired`
|
|
907
|
+
|
|
908
|
+
See [docs/test-framework.md](docs/test-framework.md) for complete test API documentation.
|
|
909
|
+
|
|
910
|
+
## Subscription System
|
|
911
|
+
|
|
912
|
+
@omega.js/backend includes a built-in payment/subscription system with Stripe and PayPal integration.
|
|
913
|
+
|
|
914
|
+
### Subscription Statuses
|
|
915
|
+
|
|
916
|
+
| Status | Meaning | User can delete account? |
|
|
917
|
+
|--------|---------|--------------------------|
|
|
918
|
+
| `active` | Subscription is current and valid (includes trialing) | No (unless `product.id === 'basic'`) |
|
|
919
|
+
| `suspended` | Payment failed (Stripe: `past_due`, `unpaid`) | No |
|
|
920
|
+
| `cancelled` | Subscription terminated (Stripe: `canceled`, `incomplete`, `incomplete_expired`) | Yes |
|
|
921
|
+
|
|
922
|
+
### Stripe Status Mapping
|
|
923
|
+
|
|
924
|
+
| Stripe Status | `subscription.status` | Notes |
|
|
925
|
+
|---|---|---|
|
|
926
|
+
| `active` | `active` | Normal active subscription |
|
|
927
|
+
| `trialing` | `active` | `trial.claimed = true` |
|
|
928
|
+
| `past_due` | `suspended` | Payment failed, retrying |
|
|
929
|
+
| `unpaid` | `suspended` | Payment failed |
|
|
930
|
+
| `canceled` | `cancelled` | Subscription terminated |
|
|
931
|
+
| `incomplete` | `cancelled` | Never completed initial payment |
|
|
932
|
+
| `incomplete_expired` | `cancelled` | Expired before completion |
|
|
933
|
+
| `active` + `cancel_at_period_end` | `active` | `cancellation.pending = true` |
|
|
934
|
+
|
|
935
|
+
### PayPal Status Mapping
|
|
936
|
+
|
|
937
|
+
| PayPal Status | `subscription.status` | Notes |
|
|
938
|
+
|---|---|---|
|
|
939
|
+
| `ACTIVE` | `active` | Normal active subscription |
|
|
940
|
+
| `SUSPENDED` | `suspended` | Payment failed or manually suspended |
|
|
941
|
+
| `CANCELLED` | `cancelled` | Subscription terminated |
|
|
942
|
+
| `EXPIRED` | `cancelled` | Billing cycles completed |
|
|
943
|
+
|
|
944
|
+
### Product Configuration
|
|
945
|
+
|
|
946
|
+
Products are defined in `config.payment.products` with flat prices and per-provider IDs:
|
|
947
|
+
|
|
948
|
+
```javascript
|
|
949
|
+
payment: {
|
|
950
|
+
products: [
|
|
951
|
+
{ id: 'basic', name: 'Basic', type: 'subscription', limits: { requests: 10 } },
|
|
952
|
+
{
|
|
953
|
+
id: 'plus', name: 'Plus', type: 'subscription',
|
|
954
|
+
limits: { requests: 100 }, trial: { days: 14 },
|
|
955
|
+
prices: { monthly: 28, annually: 276 }, // also supports 'weekly' and 'daily'
|
|
956
|
+
stripe: { productId: 'prod_xxx' },
|
|
957
|
+
paypal: { productId: 'PROD-abc123' },
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
id: 'boost', name: 'Boost Pack', type: 'one-time',
|
|
961
|
+
prices: { once: 9.99 },
|
|
962
|
+
stripe: { productId: 'prod_yyy' },
|
|
963
|
+
},
|
|
964
|
+
],
|
|
965
|
+
}
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
### Unified Subscription Object
|
|
969
|
+
|
|
970
|
+
The same subscription shape is stored in `users/{uid}.subscription` and `payments-orders/{orderId}.subscription`:
|
|
971
|
+
|
|
972
|
+
```javascript
|
|
973
|
+
subscription: {
|
|
974
|
+
product: {
|
|
975
|
+
id: 'basic', // product ID from config ('basic', 'premium', etc.)
|
|
976
|
+
name: 'Basic', // display name from config
|
|
977
|
+
},
|
|
978
|
+
status: 'active', // 'active' | 'suspended' | 'cancelled'
|
|
979
|
+
expires: { timestamp, timestampUNIX },
|
|
980
|
+
trial: {
|
|
981
|
+
claimed: false, // has user EVER used a trial
|
|
982
|
+
expires: { timestamp, timestampUNIX },
|
|
983
|
+
},
|
|
984
|
+
cancellation: {
|
|
985
|
+
pending: false, // true = cancel at period end
|
|
986
|
+
date: { timestamp, timestampUNIX },
|
|
987
|
+
},
|
|
988
|
+
payment: {
|
|
989
|
+
provider: null, // 'stripe' | 'paypal' | etc.
|
|
990
|
+
resourceId: null, // provider subscription ID (e.g., 'sub_xxx')
|
|
991
|
+
frequency: null, // 'monthly' | 'annually' | 'weekly' | 'daily'
|
|
992
|
+
startDate: { timestamp, timestampUNIX },
|
|
993
|
+
updatedBy: {
|
|
994
|
+
event: { name: null, id: null },
|
|
995
|
+
date: { timestamp, timestampUNIX },
|
|
996
|
+
},
|
|
997
|
+
},
|
|
998
|
+
}
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
### Access Check Patterns
|
|
1002
|
+
|
|
1003
|
+
```javascript
|
|
1004
|
+
// Is premium (paid)?
|
|
1005
|
+
user.subscription.status === 'active' && user.subscription.product.id !== 'basic'
|
|
1006
|
+
|
|
1007
|
+
// Is on trial?
|
|
1008
|
+
user.subscription.trial.claimed && user.subscription.status === 'active'
|
|
1009
|
+
|
|
1010
|
+
// Has pending cancellation?
|
|
1011
|
+
user.subscription.cancellation.pending === true
|
|
1012
|
+
|
|
1013
|
+
// Payment failed?
|
|
1014
|
+
user.subscription.status === 'suspended'
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
### resolveSubscription(account)
|
|
1018
|
+
|
|
1019
|
+
Static method on the `User` helper that derives calculated subscription fields. Returns only fields that require derivation logic — raw data lives on the account object directly.
|
|
1020
|
+
|
|
1021
|
+
```javascript
|
|
1022
|
+
const User = require('@omega.js/backend/dist/manager/helpers/user');
|
|
1023
|
+
|
|
1024
|
+
const resolved = User.resolveSubscription(account);
|
|
1025
|
+
// Returns: { plan, active, trialing, cancelling }
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
| Field | Type | Description |
|
|
1029
|
+
|-------|------|-------------|
|
|
1030
|
+
| `plan` | `string` | Effective plan ID right now (`'basic'` if cancelled/suspended) |
|
|
1031
|
+
| `active` | `boolean` | Has paid access (product is not `'basic'` and status is `'active'`) |
|
|
1032
|
+
| `trialing` | `boolean` | In active trial (status `'active'` + claimed + unexpired) |
|
|
1033
|
+
| `cancelling` | `boolean` | Cancellation pending (status `'active'` + `cancellation.pending`) |
|
|
1034
|
+
|
|
1035
|
+
The same function exists as `auth.resolveSubscription(account)` in [@omega.js/client](../client/) with identical logic and return shape.
|
|
1036
|
+
|
|
1037
|
+
## Final Words
|
|
1038
|
+
|
|
1039
|
+
If you are still having difficulty, open an issue in the OMEGA monorepo. It is much easier to answer questions that include your code and relevant files! So if you can provide them, we'd be extremely grateful (and more likely to help you find the answer!)
|
|
1040
|
+
|
|
1041
|
+
## Projects Using this Library
|
|
1042
|
+
|
|
1043
|
+
[Somiibo](https://somiibo.com/): A Social Media Bot with an open-source module library.
|
|
1044
|
+
[JekyllUp](https://jekyllup.com/): A website devoted to sharing the best Jekyll themes.
|
|
1045
|
+
[Slapform](https://slapform.com/): A backend provider for your HTML forms on static sites.
|
|
1046
|
+
[SoundGrail Music App](https://app.soundgrail.com/): A resource for producers, musicians, and DJs.
|
|
1047
|
+
[Hammock Report](https://hammockreport.com/): An API for exploring and listing backyard products.
|
|
1048
|
+
|
|
1049
|
+
Ask us to have your project listed! :)
|
|
1050
|
+
|
|
1051
|
+
## License
|
|
1052
|
+
|
|
1053
|
+
[Elastic License 2.0](LICENSE). The source is free to use and modify; a license key unlocks payments in production deploys and removes the attribution (local dev and test payments are always free); and you may not offer `@omega.js/backend` to third parties as a hosted or managed service.
|