@omega.js/backend 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +98 -0
- package/README.md +1053 -0
- package/bin/omega +2 -0
- package/bin/omega-backend +2 -0
- package/bin/omg +2 -0
- package/cli.js +3 -0
- package/dist/cli/command-table.js +268 -0
- package/dist/cli/commands/auth.js +259 -0
- package/dist/cli/commands/base-command.js +451 -0
- package/dist/cli/commands/build.js +27 -0
- package/dist/cli/commands/clean.js +13 -0
- package/dist/cli/commands/clear.js +11 -0
- package/dist/cli/commands/cwd.js +9 -0
- package/dist/cli/commands/deploy.js +205 -0
- package/dist/cli/commands/emulator-orphans.js +440 -0
- package/dist/cli/commands/emulator.js +1829 -0
- package/dist/cli/commands/firebase-init.js +101 -0
- package/dist/cli/commands/firestore.js +261 -0
- package/dist/cli/commands/indexes.js +51 -0
- package/dist/cli/commands/install.js +151 -0
- package/dist/cli/commands/logs.js +358 -0
- package/dist/cli/commands/mcp.js +41 -0
- package/dist/cli/commands/migrate-markers.js +176 -0
- package/dist/cli/commands/migrate-rules.js +90 -0
- package/dist/cli/commands/migrate.js +59 -0
- package/dist/cli/commands/serve.js +208 -0
- package/dist/cli/commands/setup-tests/base-test.js +174 -0
- package/dist/cli/commands/setup-tests/emulator-config.js +109 -0
- package/dist/cli/commands/setup-tests/env-runtime-config-deprecated.js +47 -0
- package/dist/cli/commands/setup-tests/firebase-admin.js +49 -0
- package/dist/cli/commands/setup-tests/firebase-auth.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-cli.js +26 -0
- package/dist/cli/commands/setup-tests/firebase-functions.js +49 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-file.js +72 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-required.js +108 -0
- package/dist/cli/commands/setup-tests/firestore-indexes-synced.js +236 -0
- package/dist/cli/commands/setup-tests/firestore-rules-file.js +115 -0
- package/dist/cli/commands/setup-tests/firestore-rules-in-json.js +49 -0
- package/dist/cli/commands/setup-tests/functions-package.js +44 -0
- package/dist/cli/commands/setup-tests/gcloud-cli.js +26 -0
- package/dist/cli/commands/setup-tests/gitignore.js +122 -0
- package/dist/cli/commands/setup-tests/helpers/merge-line-files.js +28 -0
- package/dist/cli/commands/setup-tests/helpers/required-indexes.js +109 -0
- package/dist/cli/commands/setup-tests/helpers/seed-campaigns.js +246 -0
- package/dist/cli/commands/setup-tests/helpers.js +72 -0
- package/dist/cli/commands/setup-tests/hosting-folder.js +23 -0
- package/dist/cli/commands/setup-tests/hosting-rewrites.js +52 -0
- package/dist/cli/commands/setup-tests/index.js +111 -0
- package/dist/cli/commands/setup-tests/is-firebase-project.js +21 -0
- package/dist/cli/commands/setup-tests/java-installed.js +27 -0
- package/dist/cli/commands/setup-tests/legacy-tests-cleanup.js +43 -0
- package/dist/cli/commands/setup-tests/marketing-campaigns-seeded.js +230 -0
- package/dist/cli/commands/setup-tests/node-version.js +60 -0
- package/dist/cli/commands/setup-tests/npm-project-scripts.js +42 -0
- package/dist/cli/commands/setup-tests/nvmrc-version.js +36 -0
- package/dist/cli/commands/setup-tests/omega-backend.js +42 -0
- package/dist/cli/commands/setup-tests/omega-config.js +84 -0
- package/dist/cli/commands/setup-tests/project-directories.js +34 -0
- package/dist/cli/commands/setup-tests/project-id-consistency.js +201 -0
- package/dist/cli/commands/setup-tests/public-html-files.js +22 -0
- package/dist/cli/commands/setup-tests/realtime-rules-file.js +69 -0
- package/dist/cli/commands/setup-tests/realtime-rules-in-json.js +20 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-file.js +32 -0
- package/dist/cli/commands/setup-tests/remoteconfig-template-in-json.js +31 -0
- package/dist/cli/commands/setup-tests/service-account.js +86 -0
- package/dist/cli/commands/setup-tests/storage-lifecycle-policy.js +81 -0
- package/dist/cli/commands/setup-tests/storage-rules-file.js +32 -0
- package/dist/cli/commands/setup-tests/storage-rules-in-json.js +20 -0
- package/dist/cli/commands/stripe.js +14 -0
- package/dist/cli/commands/test-lanes/stripe-live.js +440 -0
- package/dist/cli/commands/test.js +976 -0
- package/dist/cli/commands/update.js +27 -0
- package/dist/cli/commands/version.js +10 -0
- package/dist/cli/commands/watch.js +196 -0
- package/dist/cli/flags.js +13 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/run.js +33 -0
- package/dist/cli/utils/attach-log-file.js +4 -0
- package/dist/cli/utils/compile-rules.js +1155 -0
- package/dist/cli/utils/ensure-target.js +314 -0
- package/dist/cli/utils/project-type.js +140 -0
- package/dist/cli/utils/public-files.js +49 -0
- package/dist/cli/utils/safe-install.js +4 -0
- package/dist/cli/utils/spawn-shell.js +94 -0
- package/dist/cli/utils/stage-functions.js +338 -0
- package/dist/cli/utils/stage-local-packages.js +210 -0
- package/dist/cli/utils/target-checks.js +161 -0
- package/dist/cli/utils/target.js +24 -0
- package/dist/cli/utils/ui.js +292 -0
- package/dist/defaults/AGENTS.md +125 -0
- package/dist/defaults/CHANGELOG.md +15 -0
- package/dist/defaults/CLAUDE.md +1 -0
- package/dist/defaults/_.gitignore +65 -0
- package/dist/defaults/docs/README.md +17 -0
- package/dist/defaults/test/README.md +65 -0
- package/dist/defaults/test/_init.js +14 -0
- package/dist/defaults/test/helpers/connect-trap.js +72 -0
- package/dist/defaults/test/unit/registration.test.js +143 -0
- package/dist/defaults/test/unit/rules-posture.test.js +101 -0
- package/dist/defaults/test/unit/socket-free.test.js +43 -0
- package/dist/manager/events/auth/before-create.js +89 -0
- package/dist/manager/events/auth/before-signin.js +76 -0
- package/dist/manager/events/auth/on-create.js +112 -0
- package/dist/manager/events/auth/on-delete.js +141 -0
- package/dist/manager/events/auth/utils.js +93 -0
- package/dist/manager/events/cron/daily/blog-auto-publisher.js +287 -0
- package/dist/manager/events/cron/daily/data-requests.js +57 -0
- package/dist/manager/events/cron/daily/expire-paypal-cancellations.js +191 -0
- package/dist/manager/events/cron/daily/marketing-prune.js +486 -0
- package/dist/manager/events/cron/daily/reset-usage.js +188 -0
- package/dist/manager/events/cron/daily/trial-lapse-sweep.js +355 -0
- package/dist/manager/events/cron/daily.js +3 -0
- package/dist/manager/events/cron/frequent/abandoned-carts.js +204 -0
- package/dist/manager/events/cron/frequent/email-queue.js +71 -0
- package/dist/manager/events/cron/frequent/marketing-campaigns.js +463 -0
- package/dist/manager/events/cron/frequent/retry-failed-webhooks.js +70 -0
- package/dist/manager/events/cron/frequent.js +3 -0
- package/dist/manager/events/cron/runner.js +64 -0
- package/dist/manager/events/firestore/notifications/on-write.js +123 -0
- package/dist/manager/events/firestore/payments-disputes/on-write.js +256 -0
- package/dist/manager/events/firestore/payments-disputes/providers/stripe.js +218 -0
- package/dist/manager/events/firestore/payments-disputes/providers/test.js +231 -0
- package/dist/manager/events/firestore/payments-webhooks/analytics.js +687 -0
- package/dist/manager/events/firestore/payments-webhooks/on-write.js +1224 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/index.js +395 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-completed.js +58 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-failed.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/one-time/purchase-refunded.js +30 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/send-email.js +74 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-removed.js +14 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/cancellation-requested.js +28 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/checkout-declined.js +18 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/new-subscription.js +67 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-failed.js +25 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-recovered.js +26 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/payment-refunded.js +34 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/plan-changed.js +42 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-cancelled.js +33 -0
- package/dist/manager/events/firestore/payments-webhooks/transitions/subscription/subscription-winback.js +17 -0
- package/dist/manager/functions/_legacy/actions/create-post-handler.js +188 -0
- package/dist/manager/functions/_legacy/actions/generate-uuid.js +63 -0
- package/dist/manager/functions/_legacy/actions/sign-up-handler.js +205 -0
- package/dist/manager/functions/_legacy/admin/create-post.js +207 -0
- package/dist/manager/functions/_legacy/admin/firestore-write.js +72 -0
- package/dist/manager/functions/_legacy/admin/get-stats.js +218 -0
- package/dist/manager/functions/_legacy/admin/query.js +198 -0
- package/dist/manager/functions/_legacy/admin/send-notification.js +206 -0
- package/dist/manager/functions/_legacy/template.js +33 -0
- package/dist/manager/functions/_legacy/test/authenticate.js +40 -0
- package/dist/manager/functions/_legacy/test/webhook.js +37 -0
- package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
- package/dist/manager/helpers/analytics.js +498 -0
- package/dist/manager/helpers/api-manager.js +313 -0
- package/dist/manager/helpers/backend-router.js +37 -0
- package/dist/manager/helpers/context/authenticate.js +215 -0
- package/dist/manager/helpers/context/client-info.js +91 -0
- package/dist/manager/helpers/context/index.js +228 -0
- package/dist/manager/helpers/context/logging.js +150 -0
- package/dist/manager/helpers/context/parse.js +160 -0
- package/dist/manager/helpers/context/respond.js +247 -0
- package/dist/manager/helpers/event-middleware.js +109 -0
- package/dist/manager/helpers/metadata.js +32 -0
- package/dist/manager/helpers/middleware.js +541 -0
- package/dist/manager/helpers/redact-secret.js +25 -0
- package/dist/manager/helpers/resolved-config.js +34 -0
- package/dist/manager/helpers/roles.js +69 -0
- package/dist/manager/helpers/safe-compare.js +31 -0
- package/dist/manager/helpers/schema-engine.js +314 -0
- package/dist/manager/helpers/schema-zod.js +203 -0
- package/dist/manager/helpers/settings.js +215 -0
- package/dist/manager/helpers/usage.js +541 -0
- package/dist/manager/helpers/user.js +57 -0
- package/dist/manager/helpers/utilities.js +565 -0
- package/dist/manager/index.js +1404 -0
- package/dist/manager/libraries/abandoned-cart-config.js +12 -0
- package/dist/manager/libraries/ai/index.js +321 -0
- package/dist/manager/libraries/ai/prompt.js +85 -0
- package/dist/manager/libraries/ai/providers/anthropic-format.js +297 -0
- package/dist/manager/libraries/ai/providers/anthropic.js +169 -0
- package/dist/manager/libraries/ai/providers/claude-code.js +183 -0
- package/dist/manager/libraries/ai/providers/openai.js +1272 -0
- package/dist/manager/libraries/ai/providers/test.js +257 -0
- package/dist/manager/libraries/ai/tokens.js +54 -0
- package/dist/manager/libraries/analytics/conversions.js +478 -0
- package/dist/manager/libraries/analytics/match-data.js +573 -0
- package/dist/manager/libraries/analytics/signup.js +120 -0
- package/dist/manager/libraries/auth-user.js +46 -0
- package/dist/manager/libraries/content/feed-parser.js +198 -0
- package/dist/manager/libraries/content/ghostii.js +191 -0
- package/dist/manager/libraries/content/source-resolver.js +629 -0
- package/dist/manager/libraries/email/constants.js +532 -0
- package/dist/manager/libraries/email/data/blocked-local-parts.json +55 -0
- package/dist/manager/libraries/email/data/blocked-local-patterns.js +14 -0
- package/dist/manager/libraries/email/data/corporate-domains.json +23 -0
- package/dist/manager/libraries/email/data/custom-disposable-domains.json +58 -0
- package/dist/manager/libraries/email/data/disposable-domains.json +8184 -0
- package/dist/manager/libraries/email/data/typo-domains.js +83 -0
- package/dist/manager/libraries/email/disposable-domains.js +92 -0
- package/dist/manager/libraries/email/generators/lib/filter.js +179 -0
- package/dist/manager/libraries/email/generators/lib/image-host.js +344 -0
- package/dist/manager/libraries/email/generators/lib/image-illustrator.js +154 -0
- package/dist/manager/libraries/email/generators/lib/markdown-renderer.js +294 -0
- package/dist/manager/libraries/email/generators/lib/mjml-template.js +120 -0
- package/dist/manager/libraries/email/generators/lib/structure.js +299 -0
- package/dist/manager/libraries/email/generators/lib/svg-illustrator.js +197 -0
- package/dist/manager/libraries/email/generators/lib/templates/base.js +229 -0
- package/dist/manager/libraries/email/generators/lib/templates/card.js +33 -0
- package/dist/manager/libraries/email/generators/lib/templates/classic-schema.js +59 -0
- package/dist/manager/libraries/email/generators/lib/templates/clean.js +82 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/helpers.js +100 -0
- package/dist/manager/libraries/email/generators/lib/templates/editorial/index.js +318 -0
- package/dist/manager/libraries/email/generators/lib/templates/feedback.js +101 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/helpers.js +138 -0
- package/dist/manager/libraries/email/generators/lib/templates/field-report/index.js +494 -0
- package/dist/manager/libraries/email/generators/lib/templates/index.js +47 -0
- package/dist/manager/libraries/email/generators/lib/templates/newsletter-shared.js +610 -0
- package/dist/manager/libraries/email/generators/lib/templates/order.js +461 -0
- package/dist/manager/libraries/email/generators/lib/templates/plain.js +83 -0
- package/dist/manager/libraries/email/generators/lib/templates/shared-campaign.js +64 -0
- package/dist/manager/libraries/email/generators/newsletter.js +899 -0
- package/dist/manager/libraries/email/index.js +146 -0
- package/dist/manager/libraries/email/marketing/index.js +754 -0
- package/dist/manager/libraries/email/prepare.js +365 -0
- package/dist/manager/libraries/email/providers/beehiiv.js +589 -0
- package/dist/manager/libraries/email/providers/sendgrid.js +845 -0
- package/dist/manager/libraries/email/transactional/index.js +510 -0
- package/dist/manager/libraries/email/utm.js +86 -0
- package/dist/manager/libraries/email/validation-provider-neverbounce.js +70 -0
- package/dist/manager/libraries/email/validation-provider-zerobounce.js +42 -0
- package/dist/manager/libraries/email/validation.js +255 -0
- package/dist/manager/libraries/env.js +198 -0
- package/dist/manager/libraries/infer-contact.js +101 -0
- package/dist/manager/libraries/load-provider.js +65 -0
- package/dist/manager/libraries/notification.js +256 -0
- package/dist/manager/libraries/openai.js +13 -0
- package/dist/manager/libraries/payment/discount-codes.js +204 -0
- package/dist/manager/libraries/payment/fetch-failure.js +56 -0
- package/dist/manager/libraries/payment/license.js +44 -0
- package/dist/manager/libraries/payment/order-id.js +57 -0
- package/dist/manager/libraries/payment/provider-errors.js +71 -0
- package/dist/manager/libraries/payment/providers/chargebee.js +817 -0
- package/dist/manager/libraries/payment/providers/coinbase.js +330 -0
- package/dist/manager/libraries/payment/providers/paypal.js +987 -0
- package/dist/manager/libraries/payment/providers/stripe.js +755 -0
- package/dist/manager/libraries/payment/providers/test.js +250 -0
- package/dist/manager/libraries/payment/refund-linkage.js +78 -0
- package/dist/manager/libraries/payment/refund-policy.js +113 -0
- package/dist/manager/libraries/payment/winback.js +55 -0
- package/dist/manager/libraries/prompts/infer-contact.md +78 -0
- package/dist/manager/libraries/rate-limits.js +17 -0
- package/dist/manager/libraries/recaptcha.js +58 -0
- package/dist/manager/libraries/user-doc.js +234 -0
- package/dist/manager/routes/admin/backup/post.js +106 -0
- package/dist/manager/routes/admin/cron/post.js +37 -0
- package/dist/manager/routes/admin/database/get.js +35 -0
- package/dist/manager/routes/admin/database/post.js +34 -0
- package/dist/manager/routes/admin/email/post.js +74 -0
- package/dist/manager/routes/admin/firestore/get.js +35 -0
- package/dist/manager/routes/admin/firestore/post.js +56 -0
- package/dist/manager/routes/admin/firestore/query/post.js +128 -0
- package/dist/manager/routes/admin/hook/post.js +104 -0
- package/dist/manager/routes/admin/infer-contact/post.js +35 -0
- package/dist/manager/routes/admin/notification/post.js +37 -0
- package/dist/manager/routes/admin/payment/post.js +56 -0
- package/dist/manager/routes/admin/post/deduplicate-image-alts.js +52 -0
- package/dist/manager/routes/admin/post/dispatch-deploy.js +36 -0
- package/dist/manager/routes/admin/post/post.js +487 -0
- package/dist/manager/routes/admin/post/put.js +146 -0
- package/dist/manager/routes/admin/post/templates/post.html +14 -0
- package/dist/manager/routes/admin/repo/content/post.js +106 -0
- package/dist/manager/routes/admin/stats/get.js +222 -0
- package/dist/manager/routes/admin/users/disable/post.js +50 -0
- package/dist/manager/routes/admin/users/list/get.js +110 -0
- package/dist/manager/routes/admin/users/sync/post.js +119 -0
- package/dist/manager/routes/brand/get.js +26 -0
- package/dist/manager/routes/content/post/get.js +110 -0
- package/dist/manager/routes/general/email/post.js +89 -0
- package/dist/manager/routes/general/email/templates/general/download-app-link.js +42 -0
- package/dist/manager/routes/general/uuid/post.js +31 -0
- package/dist/manager/routes/handler/post/post.js +142 -0
- package/dist/manager/routes/health/get.js +43 -0
- package/dist/manager/routes/index.js +11 -0
- package/dist/manager/routes/marketing/campaign/delete.js +45 -0
- package/dist/manager/routes/marketing/campaign/get.js +69 -0
- package/dist/manager/routes/marketing/campaign/post.js +124 -0
- package/dist/manager/routes/marketing/campaign/put.js +86 -0
- package/dist/manager/routes/marketing/campaign/utils.js +59 -0
- package/dist/manager/routes/marketing/contact/delete.js +100 -0
- package/dist/manager/routes/marketing/contact/post.js +149 -0
- package/dist/manager/routes/marketing/contact/put.js +37 -0
- package/dist/manager/routes/marketing/email-preferences/post.js +275 -0
- package/dist/manager/routes/marketing/webhook/forward/post.js +170 -0
- package/dist/manager/routes/marketing/webhook/post.js +123 -0
- package/dist/manager/routes/marketing/webhook/providers/beehiiv.js +197 -0
- package/dist/manager/routes/marketing/webhook/providers/sendgrid.js +194 -0
- package/dist/manager/routes/payments/cancel/_is-trialing.js +40 -0
- package/dist/manager/routes/payments/cancel/post.js +149 -0
- package/dist/manager/routes/payments/cancel/providers/chargebee.js +41 -0
- package/dist/manager/routes/payments/cancel/providers/paypal.js +56 -0
- package/dist/manager/routes/payments/cancel/providers/stripe.js +33 -0
- package/dist/manager/routes/payments/cancel/providers/test.js +118 -0
- package/dist/manager/routes/payments/discount/get.js +25 -0
- package/dist/manager/routes/payments/dispute-alert/post.js +117 -0
- package/dist/manager/routes/payments/dispute-alert/providers/chargeblast.js +55 -0
- package/dist/manager/routes/payments/intent/post.js +341 -0
- package/dist/manager/routes/payments/intent/providers/chargebee.js +197 -0
- package/dist/manager/routes/payments/intent/providers/coinbase.js +94 -0
- package/dist/manager/routes/payments/intent/providers/paypal.js +244 -0
- package/dist/manager/routes/payments/intent/providers/stripe.js +141 -0
- package/dist/manager/routes/payments/intent/providers/test.js +341 -0
- package/dist/manager/routes/payments/plan/post.js +147 -0
- package/dist/manager/routes/payments/plan/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/plan/providers/paypal.js +62 -0
- package/dist/manager/routes/payments/plan/providers/stripe.js +59 -0
- package/dist/manager/routes/payments/plan/providers/test.js +113 -0
- package/dist/manager/routes/payments/portal/post.js +113 -0
- package/dist/manager/routes/payments/portal/providers/chargebee.js +62 -0
- package/dist/manager/routes/payments/portal/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/portal/providers/stripe.js +62 -0
- package/dist/manager/routes/payments/portal/providers/test.js +18 -0
- package/dist/manager/routes/payments/refund/post.js +207 -0
- package/dist/manager/routes/payments/refund/providers/chargebee.js +147 -0
- package/dist/manager/routes/payments/refund/providers/coinbase.js +40 -0
- package/dist/manager/routes/payments/refund/providers/paypal.js +239 -0
- package/dist/manager/routes/payments/refund/providers/stripe.js +160 -0
- package/dist/manager/routes/payments/refund/providers/test.js +204 -0
- package/dist/manager/routes/payments/trial-eligibility/get.js +29 -0
- package/dist/manager/routes/payments/uncancel/post.js +106 -0
- package/dist/manager/routes/payments/uncancel/providers/chargebee.js +30 -0
- package/dist/manager/routes/payments/uncancel/providers/paypal.js +25 -0
- package/dist/manager/routes/payments/uncancel/providers/stripe.js +27 -0
- package/dist/manager/routes/payments/uncancel/providers/test.js +114 -0
- package/dist/manager/routes/payments/webhook/post.js +157 -0
- package/dist/manager/routes/payments/webhook/providers/chargebee.js +218 -0
- package/dist/manager/routes/payments/webhook/providers/coinbase.js +91 -0
- package/dist/manager/routes/payments/webhook/providers/paypal.js +214 -0
- package/dist/manager/routes/payments/webhook/providers/stripe.js +182 -0
- package/dist/manager/routes/payments/webhook/providers/test.js +18 -0
- package/dist/manager/routes/payments/winback/post.js +276 -0
- package/dist/manager/routes/payments/winback/providers/chargebee.js +24 -0
- package/dist/manager/routes/payments/winback/providers/paypal.js +22 -0
- package/dist/manager/routes/payments/winback/providers/stripe.js +41 -0
- package/dist/manager/routes/payments/winback/providers/test.js +42 -0
- package/dist/manager/routes/restart/index.js +37 -0
- package/dist/manager/routes/special/electron-client/post.js +59 -0
- package/dist/manager/routes/test/authenticate/get.js +11 -0
- package/dist/manager/routes/test/health/get.js +8 -0
- package/dist/manager/routes/test/index.js +16 -0
- package/dist/manager/routes/test/lab/post.js +17 -0
- package/dist/manager/routes/test/redirect/get.js +27 -0
- package/dist/manager/routes/test/reset-account/post.js +79 -0
- package/dist/manager/routes/test/roster/get.js +40 -0
- package/dist/manager/routes/test/schema/post.js +20 -0
- package/dist/manager/routes/test/usage/post.js +44 -0
- package/dist/manager/routes/test/webhook/post.js +21 -0
- package/dist/manager/routes/user/api-keys/post.js +51 -0
- package/dist/manager/routes/user/connections/_context.js +194 -0
- package/dist/manager/routes/user/connections/_grant.js +247 -0
- package/dist/manager/routes/user/connections/_lease.js +184 -0
- package/dist/manager/routes/user/connections/_providers.js +191 -0
- package/dist/manager/routes/user/connections/_state.js +117 -0
- package/dist/manager/routes/user/connections/delete.js +55 -0
- package/dist/manager/routes/user/connections/get.js +167 -0
- package/dist/manager/routes/user/connections/post.js +370 -0
- package/dist/manager/routes/user/connections/providers/discord.js +41 -0
- package/dist/manager/routes/user/connections/providers/google.js +55 -0
- package/dist/manager/routes/user/connections/providers/kick.js +68 -0
- package/dist/manager/routes/user/connections/providers/spotify.js +40 -0
- package/dist/manager/routes/user/connections/providers/twitch.js +52 -0
- package/dist/manager/routes/user/data-request/delete.js +84 -0
- package/dist/manager/routes/user/data-request/get.js +229 -0
- package/dist/manager/routes/user/data-request/post.js +136 -0
- package/dist/manager/routes/user/delete.js +149 -0
- package/dist/manager/routes/user/feedback/post.js +81 -0
- package/dist/manager/routes/user/get.js +14 -0
- package/dist/manager/routes/user/orders/get.js +95 -0
- package/dist/manager/routes/user/sessions/delete.js +95 -0
- package/dist/manager/routes/user/sessions/get.js +40 -0
- package/dist/manager/routes/user/settings/validate/post.js +86 -0
- package/dist/manager/routes/user/signup/post.js +662 -0
- package/dist/manager/routes/user/subscription/get.js +77 -0
- package/dist/manager/routes/user/token/post.js +30 -0
- package/dist/manager/routes/verts/delete.js +43 -0
- package/dist/manager/routes/verts/get.js +49 -0
- package/dist/manager/routes/verts/post.js +61 -0
- package/dist/manager/routes/verts/put.js +75 -0
- package/dist/manager/routes/verts/redirect/get.js +36 -0
- package/dist/manager/routes/verts/serve/get.js +67 -0
- package/dist/manager/routes/verts/utils.js +436 -0
- package/dist/manager/schemas/admin/backup/post.js +8 -0
- package/dist/manager/schemas/admin/cron/post.js +8 -0
- package/dist/manager/schemas/admin/database/get.js +5 -0
- package/dist/manager/schemas/admin/database/post.js +6 -0
- package/dist/manager/schemas/admin/email/post.js +31 -0
- package/dist/manager/schemas/admin/firestore/get.js +5 -0
- package/dist/manager/schemas/admin/firestore/post.js +8 -0
- package/dist/manager/schemas/admin/firestore/query/post.js +5 -0
- package/dist/manager/schemas/admin/hook/post.js +8 -0
- package/dist/manager/schemas/admin/infer-contact/post.js +6 -0
- package/dist/manager/schemas/admin/notification/post.js +23 -0
- package/dist/manager/schemas/admin/payment/post.js +8 -0
- package/dist/manager/schemas/admin/post/post.js +23 -0
- package/dist/manager/schemas/admin/post/put.js +13 -0
- package/dist/manager/schemas/admin/repo/content/post.js +10 -0
- package/dist/manager/schemas/admin/stats/get.js +5 -0
- package/dist/manager/schemas/admin/users/disable/post.js +9 -0
- package/dist/manager/schemas/admin/users/list/get.js +10 -0
- package/dist/manager/schemas/admin/users/sync/post.js +7 -0
- package/dist/manager/schemas/brand/get.js +3 -0
- package/dist/manager/schemas/content/post/get.js +8 -0
- package/dist/manager/schemas/general/email/post.js +10 -0
- package/dist/manager/schemas/general/uuid/post.js +9 -0
- package/dist/manager/schemas/handler/post/post.js +13 -0
- package/dist/manager/schemas/health/get.js +3 -0
- package/dist/manager/schemas/marketing/campaign/delete.js +8 -0
- package/dist/manager/schemas/marketing/campaign/get.js +13 -0
- package/dist/manager/schemas/marketing/campaign/post.js +43 -0
- package/dist/manager/schemas/marketing/campaign/put.js +37 -0
- package/dist/manager/schemas/marketing/contact/delete.js +8 -0
- package/dist/manager/schemas/marketing/contact/post.js +14 -0
- package/dist/manager/schemas/marketing/contact/put.js +8 -0
- package/dist/manager/schemas/marketing/email-preferences/post.js +15 -0
- package/dist/manager/schemas/marketing/webhook/forward/post.js +8 -0
- package/dist/manager/schemas/marketing/webhook/post.js +7 -0
- package/dist/manager/schemas/payments/cancel/post.js +15 -0
- package/dist/manager/schemas/payments/discount/get.js +8 -0
- package/dist/manager/schemas/payments/dispute-alert/post.js +6 -0
- package/dist/manager/schemas/payments/intent/post.js +28 -0
- package/dist/manager/schemas/payments/plan/post.js +11 -0
- package/dist/manager/schemas/payments/portal/post.js +12 -0
- package/dist/manager/schemas/payments/refund/post.js +14 -0
- package/dist/manager/schemas/payments/trial-eligibility/get.js +7 -0
- package/dist/manager/schemas/payments/uncancel/post.js +9 -0
- package/dist/manager/schemas/payments/webhook/post.js +6 -0
- package/dist/manager/schemas/payments/winback/post.js +12 -0
- package/dist/manager/schemas/restart/index.js +5 -0
- package/dist/manager/schemas/special/electron-client/post.js +11 -0
- package/dist/manager/schemas/test/authenticate/get.js +3 -0
- package/dist/manager/schemas/test/health/get.js +3 -0
- package/dist/manager/schemas/test/index.js +5 -0
- package/dist/manager/schemas/test/lab/post.js +3 -0
- package/dist/manager/schemas/test/redirect/get.js +7 -0
- package/dist/manager/schemas/test/reset-account/post.js +3 -0
- package/dist/manager/schemas/test/roster/get.js +3 -0
- package/dist/manager/schemas/test/schema/post.js +70 -0
- package/dist/manager/schemas/test/usage/post.js +8 -0
- package/dist/manager/schemas/test/webhook/post.js +7 -0
- package/dist/manager/schemas/user/api-keys/post.js +6 -0
- package/dist/manager/schemas/user/connections/delete.js +8 -0
- package/dist/manager/schemas/user/connections/get.js +21 -0
- package/dist/manager/schemas/user/connections/post.js +12 -0
- package/dist/manager/schemas/user/data-request/delete.js +3 -0
- package/dist/manager/schemas/user/data-request/get.js +5 -0
- package/dist/manager/schemas/user/data-request/post.js +6 -0
- package/dist/manager/schemas/user/delete.js +6 -0
- package/dist/manager/schemas/user/feedback/post.js +8 -0
- package/dist/manager/schemas/user/get.js +3 -0
- package/dist/manager/schemas/user/orders/get.js +6 -0
- package/dist/manager/schemas/user/sessions/delete.js +6 -0
- package/dist/manager/schemas/user/sessions/get.js +6 -0
- package/dist/manager/schemas/user/settings/validate/post.js +8 -0
- package/dist/manager/schemas/user/signup/post.js +27 -0
- package/dist/manager/schemas/user/subscription/get.js +5 -0
- package/dist/manager/schemas/user/token/post.js +5 -0
- package/dist/manager/schemas/verts/delete.js +8 -0
- package/dist/manager/schemas/verts/get.js +9 -0
- package/dist/manager/schemas/verts/post.js +23 -0
- package/dist/manager/schemas/verts/put.js +20 -0
- package/dist/manager/schemas/verts/redirect/get.js +10 -0
- package/dist/manager/schemas/verts/serve/get.js +14 -0
- package/dist/manager/server-manager.js +69 -0
- package/dist/mcp/client.js +98 -0
- package/dist/mcp/handler.js +521 -0
- package/dist/mcp/index.js +157 -0
- package/dist/mcp/tools.js +555 -0
- package/dist/mcp/utils.js +108 -0
- package/dist/omega-bin.js +6 -0
- package/dist/require.js +3 -0
- package/dist/test/fixtures/firebase-project/.firebaserc +5 -0
- package/dist/test/fixtures/firebase-project/config/omega.json5 +131 -0
- package/dist/test/fixtures/firebase-project/database.rules.json +6 -0
- package/dist/test/fixtures/firebase-project/firebase.json +49 -0
- package/dist/test/fixtures/firebase-project/firestore.indexes.json +4 -0
- package/dist/test/fixtures/firebase-project/package.json +14 -0
- package/dist/test/fixtures/firebase-project/src/index.js +11 -0
- package/dist/test/fixtures/firebase-project/storage.rules +8 -0
- package/dist/test/parse-audit.js +25 -0
- package/dist/test/run-tests.js +90 -0
- package/dist/test/runner.js +982 -0
- package/dist/test/seed.js +242 -0
- package/dist/test/test-accounts.js +2660 -0
- package/dist/test/utils/assertions.js +189 -0
- package/dist/test/utils/email-capture.js +252 -0
- package/dist/test/utils/extended-mode-warning.js +11 -0
- package/dist/test/utils/firestore-rules-client.js +277 -0
- package/dist/test/utils/http-client.js +228 -0
- package/dist/test/utils/test-mode-file.js +192 -0
- package/dist/utils/merge-line-files.js +6 -0
- package/dist/utils/scaffold-defaults.js +71 -0
- package/dist/utils/test-lanes.js +62 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/analytics/adapters/ga4.js +26 -0
- package/dist/vendor/analytics/adapters/meta.js +26 -0
- package/dist/vendor/analytics/adapters/resolve.js +130 -0
- package/dist/vendor/analytics/adapters/tiktok.js +27 -0
- package/dist/vendor/analytics/catalog.js +908 -0
- package/dist/vendor/analytics/identity.js +136 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bare-requires.js +153 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/npm-registry.js +52 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/parse-audit.js +74 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/assert.js +120 -0
- package/dist/vendor/devkit/test/define-cases.js +104 -0
- package/dist/vendor/devkit/test/runner-core.js +554 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/monitoring/core.js +180 -0
- package/dist/vendor/monitoring/env.js +49 -0
- package/dist/vendor/monitoring/logger.js +39 -0
- package/dist/vendor/monitoring/node.js +72 -0
- package/docs/admin-post-route.md +57 -0
- package/docs/ai-library.md +171 -0
- package/docs/architecture.md +62 -0
- package/docs/audit.md +70 -0
- package/docs/auth-hooks.md +74 -0
- package/docs/build-system.md +65 -0
- package/docs/cdp-debugging.md +29 -0
- package/docs/cli-firestore-auth.md +85 -0
- package/docs/cli-logs.md +67 -0
- package/docs/cli-output.md +146 -0
- package/docs/code-patterns.md +77 -0
- package/docs/common-mistakes.md +12 -0
- package/docs/common-operations.md +60 -0
- package/docs/connections.md +212 -0
- package/docs/consent.md +362 -0
- package/docs/directory-structure.md +150 -0
- package/docs/email-system.md +459 -0
- package/docs/environment-detection.md +93 -0
- package/docs/file-naming.md +10 -0
- package/docs/firestore.md +134 -0
- package/docs/ghostii.md +240 -0
- package/docs/index.md +299 -0
- package/docs/key-files.md +37 -0
- package/docs/logging.md +60 -0
- package/docs/marketing-campaigns.md +407 -0
- package/docs/marketing-fields.md +25 -0
- package/docs/mcp.md +222 -0
- package/docs/migration.md +129 -0
- package/docs/payment-system.md +856 -0
- package/docs/paypal-sandbox-qa.md +105 -0
- package/docs/response-headers.md +9 -0
- package/docs/routes.md +211 -0
- package/docs/sanitization.md +71 -0
- package/docs/schemas.md +163 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/stripe-webhook-forwarding.md +20 -0
- package/docs/test-boot-layer.md +67 -0
- package/docs/test-framework.md +583 -0
- package/docs/usage-rate-limiting.md +121 -0
- package/docs/verts.md +29 -0
- package/package.json +143 -0
- package/templates/config/omega.json5 +322 -0
- package/templates/database.rules.json +82 -0
- package/templates/firebase.json +67 -0
- package/templates/firestore.framework.rules +191 -0
- package/templates/firestore.indexes.json +4 -0
- package/templates/firestore.rules +59 -0
- package/templates/index.js +12 -0
- package/templates/public/404.html +26 -0
- package/templates/public/index.html +24 -0
- package/templates/remoteconfig.template.json +1 -0
- package/templates/storage-lifecycle-config-1-day.json +9 -0
- package/templates/storage-lifecycle-config-30-days.json +9 -0
- package/templates/storage.rules +11 -0
- package/test/_init/accounts-validation.js +58 -0
- package/test/ai/tools-live.test.js +171 -0
- package/test/analytics/conversion-delivery.test.js +1013 -0
- package/test/analytics/match-normalization.test.js +238 -0
- package/test/analytics/signup-conversion.test.js +135 -0
- package/test/boot/cli-dispatch.test.js +142 -0
- package/test/boot/defaults-scaffold.test.js +248 -0
- package/test/boot/deploy-staging.test.js +446 -0
- package/test/boot/disposable-domains.test.js +154 -0
- package/test/boot/emulator-boots.test.js +39 -0
- package/test/boot/emulator-port-preflight.test.js +126 -0
- package/test/boot/emulator-ready-timeout.test.js +46 -0
- package/test/boot/project-id-refresh.test.js +73 -0
- package/test/boot/suite-portability.test.js +278 -0
- package/test/boot/update-command.test.js +63 -0
- package/test/cli/cross-platform.test.js +168 -0
- package/test/cli/custom-project-type.test.js +426 -0
- package/test/cli/deploy-license-env.test.js +100 -0
- package/test/cli/emulator-adoption.test.js +254 -0
- package/test/cli/emulator-orphans.test.js +658 -0
- package/test/cli/emulator-ownership.test.js +177 -0
- package/test/cli/emulator-port-retry.test.js +395 -0
- package/test/cli/emulator-shutdown.test.js +788 -0
- package/test/cli/emulator-stale-reap.test.js +574 -0
- package/test/cli/ensure-target.test.js +325 -0
- package/test/cli/flags.test.js +64 -0
- package/test/cli/https-trust.test.js +38 -0
- package/test/cli/install-update-dispatch.test.js +47 -0
- package/test/cli/lane-environments.test.js +159 -0
- package/test/cli/marketing-campaigns-seeded.test.js +194 -0
- package/test/cli/migrate-bare-requires.test.js +128 -0
- package/test/cli/migrate-markers.test.js +530 -0
- package/test/cli/required-indexes.test.js +64 -0
- package/test/cli/rules-compile.test.js +622 -0
- package/test/cli/rules-migration-deferral.test.js +259 -0
- package/test/cli/rules-version.test.js +104 -0
- package/test/cli/setup-load-files.test.js +66 -0
- package/test/cli/setup-offline-mode.test.js +276 -0
- package/test/cli/setup-retired.test.js +64 -0
- package/test/cli/setup-shared-project-indexes.test.js +262 -0
- package/test/cli/setup-tests-requires.test.js +45 -0
- package/test/cli/stage-env-compose.test.js +316 -0
- package/test/cli/stripe-live-lane.test.js +303 -0
- package/test/cli/target.test.js +182 -0
- package/test/cli/templates.test.js +66 -0
- package/test/cli/test-runner-env.test.js +115 -0
- package/test/cli/test-stack-shutdown.test.js +275 -0
- package/test/cli/test-target-no-match.test.js +128 -0
- package/test/cli/verb-logs.test.js +118 -0
- package/test/cli/version-dispatch.test.js +39 -0
- package/test/content/blog-generate.test.js +164 -0
- package/test/email/campaign-config-fault.test.js +376 -0
- package/test/email/campaign-cron-pipeline.test.js +536 -0
- package/test/email/campaign-send.test.js +47 -0
- package/test/email/consent-lifecycle.test.js +258 -0
- package/test/email/content-html-policy.test.js +270 -0
- package/test/email/feedback-and-plain-send.test.js +54 -0
- package/test/email/fixtures/clean.json +30 -0
- package/test/email/fixtures/editorial.json +30 -0
- package/test/email/fixtures/field-report.json +53 -0
- package/test/email/identity.test.js +321 -0
- package/test/email/marketing/consent-gate.test.js +265 -0
- package/test/email/marketing/custom-fields-catalog.test.js +259 -0
- package/test/email/marketing/prune-per-provider.test.js +762 -0
- package/test/email/marketing/remove-log-privacy.test.js +225 -0
- package/test/email/marketing-lifecycle.test.js +139 -0
- package/test/email/newsletter-generate.test.js +853 -0
- package/test/email/newsletter-svg-tokens.test.js +51 -0
- package/test/email/newsletter-templates.test.js +492 -0
- package/test/email/order-one-time-cta.test.js +97 -0
- package/test/email/render-content.test.js +248 -0
- package/test/email/safe-url.test.js +0 -0
- package/test/email/sanitize-images.test.js +66 -0
- package/test/email/send-log-privacy.test.js +107 -0
- package/test/email/templates.test.js +288 -0
- package/test/email/testing-capture.test.js +260 -0
- package/test/email/transactional-send.test.js +36 -0
- package/test/email/transactional.test.js +562 -0
- package/test/email/unsubscribe-groups.test.js +155 -0
- package/test/email/unsubscribe-key.test.js +91 -0
- package/test/email/validation-cases.test.js +152 -0
- package/test/email/validation.test.js +746 -0
- package/test/events/auth-delete-conversion.test.js +138 -0
- package/test/events/auth-delete-race.test.js +211 -0
- package/test/events/auth-on-create-log.test.js +164 -0
- package/test/events/auth-signup-conversion.test.js +141 -0
- package/test/events/auth-signup-limit.test.js +142 -0
- package/test/events/auth-trigger-log-privacy.test.js +256 -0
- package/test/events/cron-job-doc-shape.test.js +101 -0
- package/test/events/cron-reset-usage.test.js +116 -0
- package/test/events/notification-conversion.test.js +182 -0
- package/test/events/payments/_webhook-harness.js +307 -0
- package/test/events/payments/abandoned-cart-activity.test.js +135 -0
- package/test/events/payments/analytics-payment-events.test.js +945 -0
- package/test/events/payments/dispute-email-status.test.js +55 -0
- package/test/events/payments/journey-payments-abandoned.test.js +126 -0
- package/test/events/payments/journey-payments-cancel-endpoint.test.js +102 -0
- package/test/events/payments/journey-payments-cancel-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-cancel.test.js +184 -0
- package/test/events/payments/journey-payments-decline.test.js +225 -0
- package/test/events/payments/journey-payments-discount.test.js +91 -0
- package/test/events/payments/journey-payments-dispute.test.js +190 -0
- package/test/events/payments/journey-payments-failure.test.js +148 -0
- package/test/events/payments/journey-payments-legacy-product.test.js +151 -0
- package/test/events/payments/journey-payments-one-time-decline.test.js +127 -0
- package/test/events/payments/journey-payments-one-time-failure.test.js +113 -0
- package/test/events/payments/journey-payments-one-time-refund.test.js +186 -0
- package/test/events/payments/journey-payments-one-time.test.js +175 -0
- package/test/events/payments/journey-payments-plan-change.test.js +146 -0
- package/test/events/payments/journey-payments-plan-switch-trial.test.js +161 -0
- package/test/events/payments/journey-payments-plan-switch.test.js +182 -0
- package/test/events/payments/journey-payments-refund-no-order.test.js +76 -0
- package/test/events/payments/journey-payments-refund-webhook.test.js +225 -0
- package/test/events/payments/journey-payments-suspend.test.js +183 -0
- package/test/events/payments/journey-payments-trial-cancel.test.js +132 -0
- package/test/events/payments/journey-payments-trial.test.js +173 -0
- package/test/events/payments/journey-payments-uid-resolution.test.js +134 -0
- package/test/events/payments/journey-payments-uncancel.test.js +157 -0
- package/test/events/payments/journey-payments-upgrade.test.js +137 -0
- package/test/events/payments/journey-payments-winback-decline.test.js +171 -0
- package/test/events/payments/journey-payments-winback.test.js +195 -0
- package/test/events/payments/paypal-expiry-cron.test.js +166 -0
- package/test/events/payments/purchase-failed-handler.test.js +80 -0
- package/test/events/payments/purchase-refunded-handler.test.js +108 -0
- package/test/events/payments/test-processor-doc-shape.test.js +162 -0
- package/test/events/payments/transition-order-emails.test.js +185 -0
- package/test/events/payments/transition-promo-lines.test.js +192 -0
- package/test/events/payments/transitions-detect.test.js +767 -0
- package/test/events/payments/trial-lapse-sweep-staleness.test.js +173 -0
- package/test/events/payments/trial-lapse-sweep.test.js +359 -0
- package/test/events/payments/webhook-atomic-writes.test.js +69 -0
- package/test/events/payments/webhook-chargebee-unreachable.test.js +106 -0
- package/test/events/payments/webhook-discount-clear.test.js +189 -0
- package/test/events/payments/webhook-failure-intent.test.js +93 -0
- package/test/events/payments/webhook-hosted-page-uid-trust.test.js +212 -0
- package/test/events/payments/webhook-ordering.test.js +326 -0
- package/test/events/payments/webhook-provider-lookup-trust.test.js +206 -0
- package/test/events/payments/webhook-refund-amount-trust.test.js +223 -0
- package/test/events/payments/webhook-refund-envelope-shape.test.js +148 -0
- package/test/events/payments/webhook-refund-linkage-trust.test.js +404 -0
- package/test/events/payments/webhook-refund-transaction-fallback.test.js +184 -0
- package/test/events/payments/webhook-refund-without-order.test.js +170 -0
- package/test/events/payments/webhook-refusal-reporting.test.js +194 -0
- package/test/events/payments/webhook-refused-intent.test.js +142 -0
- package/test/events/payments/webhook-retry-sweep.test.js +252 -0
- package/test/events/payments/webhook-transition-claim.test.js +389 -0
- package/test/events/payments/webhook-uid-trust.test.js +203 -0
- package/test/events/payments/webhook-user-without-auth.test.js +161 -0
- package/test/fixtures/chargebee/invoice-one-time.json +27 -0
- package/test/fixtures/chargebee/subscription-active.json +44 -0
- package/test/fixtures/chargebee/subscription-cancelled.json +42 -0
- package/test/fixtures/chargebee/subscription-in-trial.json +41 -0
- package/test/fixtures/chargebee/subscription-legacy-plan.json +41 -0
- package/test/fixtures/chargebee/subscription-non-renewing.json +41 -0
- package/test/fixtures/chargebee/subscription-paused.json +42 -0
- package/test/fixtures/chargebee/webhook-payment-failed.json +51 -0
- package/test/fixtures/chargebee/webhook-subscription-created.json +47 -0
- package/test/fixtures/coinbase/charge-confirmed.json +50 -0
- package/test/fixtures/coinbase/charge-failed.json +34 -0
- package/test/fixtures/coinbase/charge-pending.json +34 -0
- package/test/fixtures/migrate/ported-route.js.txt +11 -0
- package/test/fixtures/paypal/capture-completed.json +51 -0
- package/test/fixtures/paypal/capture-refunded.json +43 -0
- package/test/fixtures/paypal/order-approved.json +62 -0
- package/test/fixtures/paypal/order-completed.json +110 -0
- package/test/fixtures/paypal/sale-refunded.json +38 -0
- package/test/fixtures/paypal/subscription-active.json +76 -0
- package/test/fixtures/paypal/subscription-cancelled.json +50 -0
- package/test/fixtures/paypal/subscription-suspended.json +65 -0
- package/test/fixtures/stripe/checkout-session-completed.json +130 -0
- package/test/fixtures/stripe/invoice-payment-failed.json +148 -0
- package/test/fixtures/stripe/invoice-subscription-payment-failed.json +28 -0
- package/test/fixtures/stripe/invoice-subscription-payment-succeeded.json +28 -0
- package/test/fixtures/stripe/subscription-active.json +161 -0
- package/test/fixtures/stripe/subscription-canceled.json +161 -0
- package/test/fixtures/stripe/subscription-trialing.json +161 -0
- package/test/helpers/_shared-config.js +15 -0
- package/test/helpers/ai-request-payload.test.js +619 -0
- package/test/helpers/ai-schema-resolve.test.js +125 -0
- package/test/helpers/ai-test-provider.test.js +227 -0
- package/test/helpers/ai-token-accounting.test.js +150 -0
- package/test/helpers/ai-tools-format.test.js +384 -0
- package/test/helpers/analytics-no-id-notice.test.js +146 -0
- package/test/helpers/analytics-user-data.test.js +194 -0
- package/test/helpers/api-manager.test.js +311 -0
- package/test/helpers/backend-router.test.js +136 -0
- package/test/helpers/content/blog-auto-publisher.test.js +482 -0
- package/test/helpers/content/feed-parser.test.js +529 -0
- package/test/helpers/content/ghostii-blocks.test.js +135 -0
- package/test/helpers/content/ghostii-feed-integration.test.js +405 -0
- package/test/helpers/content/ghostii-write-article.test.js +244 -0
- package/test/helpers/dev-only-routes.test.js +225 -0
- package/test/helpers/env-reader.test.js +362 -0
- package/test/helpers/environment.test.js +263 -0
- package/test/helpers/event-middleware.test.js +407 -0
- package/test/helpers/infer-contact.test.js +157 -0
- package/test/helpers/lane-url.test.js +90 -0
- package/test/helpers/merge-line-files.test.js +272 -0
- package/test/helpers/metadata.test.js +122 -0
- package/test/helpers/middleware-request-log.test.js +134 -0
- package/test/helpers/middleware-user-log.test.js +124 -0
- package/test/helpers/payment/chargebee/parse-webhook.test.js +490 -0
- package/test/helpers/payment/chargebee/refund-details.test.js +198 -0
- package/test/helpers/payment/chargebee/to-unified-one-time.test.js +148 -0
- package/test/helpers/payment/chargebee/to-unified-subscription.test.js +649 -0
- package/test/helpers/payment/coinbase/create-intent.test.js +247 -0
- package/test/helpers/payment/coinbase/parse-webhook.test.js +195 -0
- package/test/helpers/payment/coinbase/refund-unsupported.test.js +141 -0
- package/test/helpers/payment/coinbase/to-unified-one-time.test.js +201 -0
- package/test/helpers/payment/discount-codes.test.js +141 -0
- package/test/helpers/payment/extract-resource.test.js +113 -0
- package/test/helpers/payment/fetch-failure.test.js +215 -0
- package/test/helpers/payment/license-gate.test.js +108 -0
- package/test/helpers/payment/order-id.test.js +99 -0
- package/test/helpers/payment/paypal/create-intent.test.js +382 -0
- package/test/helpers/payment/paypal/fetch-capture.test.js +123 -0
- package/test/helpers/payment/paypal/fetch-sale.test.js +183 -0
- package/test/helpers/payment/paypal/parse-webhook.test.js +678 -0
- package/test/helpers/payment/paypal/refund-details.test.js +202 -0
- package/test/helpers/payment/paypal/resolve-plan-id.test.js +108 -0
- package/test/helpers/payment/paypal/switch-plan.test.js +92 -0
- package/test/helpers/payment/paypal/to-unified-one-time.test.js +383 -0
- package/test/helpers/payment/paypal/to-unified-subscription.test.js +884 -0
- package/test/helpers/payment/stripe/fetch-charge.test.js +147 -0
- package/test/helpers/payment/stripe/parse-webhook.test.js +448 -0
- package/test/helpers/payment/stripe/refund-details.test.js +147 -0
- package/test/helpers/payment/stripe/to-unified-one-time.test.js +307 -0
- package/test/helpers/payment/stripe/to-unified-subscription.test.js +709 -0
- package/test/helpers/persona-domain.test.js +87 -0
- package/test/helpers/recaptcha.test.js +166 -0
- package/test/helpers/resolved-config.test.js +106 -0
- package/test/helpers/response-log-redaction.test.js +262 -0
- package/test/helpers/roles.test.js +155 -0
- package/test/helpers/route-context-debug-gate.test.js +118 -0
- package/test/helpers/route-context-logging.test.js +214 -0
- package/test/helpers/route-context.test.js +129 -0
- package/test/helpers/safe-compare.test.js +114 -0
- package/test/helpers/sanitize.test.js +223 -0
- package/test/helpers/schema-engine.test.js +537 -0
- package/test/helpers/schema-zod.test.js +554 -0
- package/test/helpers/seed-accounts-load.test.js +163 -0
- package/test/helpers/seed-google-personas.test.js +114 -0
- package/test/helpers/seeded-personas.test.js +823 -0
- package/test/helpers/settings.test.js +292 -0
- package/test/helpers/setup-engines-pin.test.js +68 -0
- package/test/helpers/setup-manifest-sync.test.js +116 -0
- package/test/helpers/slugify.test.js +395 -0
- package/test/helpers/storage.test.js +195 -0
- package/test/helpers/test-banner-latch.test.js +139 -0
- package/test/helpers/usage-consume.test.js +460 -0
- package/test/helpers/usage-log-privacy.test.js +121 -0
- package/test/helpers/user-doc-heal.test.js +540 -0
- package/test/helpers/user.test.js +771 -0
- package/test/helpers/webhook-forward.test.js +419 -0
- package/test/helpers/wipe-auth-project.test.js +143 -0
- package/test/mcp/discovery.test.js +52 -0
- package/test/mcp/oauth.test.js +160 -0
- package/test/mcp/protocol.test.js +278 -0
- package/test/mcp/roles.test.js +203 -0
- package/test/mcp/utils.test.js +245 -0
- package/test/notification/identity.test.js +155 -0
- package/test/routes/admin/create-post.test.js +362 -0
- package/test/routes/admin/database.test.js +133 -0
- package/test/routes/admin/deduplicate-image-alts.test.js +191 -0
- package/test/routes/admin/email-content-html.test.js +58 -0
- package/test/routes/admin/email-request-log.test.js +86 -0
- package/test/routes/admin/email.test.js +116 -0
- package/test/routes/admin/firestore-query.test.js +206 -0
- package/test/routes/admin/firestore.test.js +129 -0
- package/test/routes/admin/infer-contact.test.js +220 -0
- package/test/routes/admin/notification.test.js +199 -0
- package/test/routes/admin/post-convert-image.test.js +159 -0
- package/test/routes/admin/post-deploy-flag.test.js +81 -0
- package/test/routes/admin/post-download-error.test.js +90 -0
- package/test/routes/admin/post-resize-image.test.js +185 -0
- package/test/routes/admin/post.test.js +369 -0
- package/test/routes/admin/repo-content.test.js +223 -0
- package/test/routes/admin/stats.test.js +114 -0
- package/test/routes/admin/users-disable.test.js +63 -0
- package/test/routes/admin/users-list.test.js +71 -0
- package/test/routes/content/post.test.js +60 -0
- package/test/routes/general/uuid.test.js +133 -0
- package/test/routes/health.test.js +110 -0
- package/test/routes/marketing/campaign.test.js +184 -0
- package/test/routes/marketing/contact.test.js +416 -0
- package/test/routes/marketing/email-preferences.test.js +293 -0
- package/test/routes/marketing/push-send.test.js +34 -0
- package/test/routes/marketing/webhook-forward.test.js +63 -0
- package/test/routes/marketing/webhook.test.js +641 -0
- package/test/routes/payments/_route-harness.js +145 -0
- package/test/routes/payments/cancel-provider-errors.test.js +227 -0
- package/test/routes/payments/cancel-skip-guards.test.js +126 -0
- package/test/routes/payments/cancel-trialing.test.js +428 -0
- package/test/routes/payments/cancel.test.js +165 -0
- package/test/routes/payments/dedup-race.test.js +186 -0
- package/test/routes/payments/discount.test.js +82 -0
- package/test/routes/payments/dispute-alert.test.js +324 -0
- package/test/routes/payments/intent-discount-amounts.test.js +550 -0
- package/test/routes/payments/intent-discount-coupons.test.js +293 -0
- package/test/routes/payments/intent-one-time-metadata.test.js +122 -0
- package/test/routes/payments/intent-purchaser-guard.test.js +139 -0
- package/test/routes/payments/intent-zero-total.test.js +260 -0
- package/test/routes/payments/intent.test.js +413 -0
- package/test/routes/payments/plan.test.js +367 -0
- package/test/routes/payments/portal-return-url.test.js +107 -0
- package/test/routes/payments/portal.test.js +94 -0
- package/test/routes/payments/refund-one-time.test.js +254 -0
- package/test/routes/payments/refund-paypal-proration.test.js +190 -0
- package/test/routes/payments/refund.test.js +181 -0
- package/test/routes/payments/trial-eligibility.test.js +73 -0
- package/test/routes/payments/uncancel.test.js +270 -0
- package/test/routes/payments/webhook-stripe-invoice.test.js +129 -0
- package/test/routes/payments/webhook-stripe-refund-one-time.test.js +130 -0
- package/test/routes/payments/webhook-test-provider.test.js +156 -0
- package/test/routes/payments/webhook.test.js +115 -0
- package/test/routes/payments/winback-stripe-coupon.test.js +126 -0
- package/test/routes/payments/winback.test.js +597 -0
- package/test/routes/test/authenticate.test.js +79 -0
- package/test/routes/test/redirect.test.js +66 -0
- package/test/routes/test/reset-account.test.js +126 -0
- package/test/routes/test/roster.test.js +101 -0
- package/test/routes/test/schema.test.js +556 -0
- package/test/routes/test/usage.test.js +374 -0
- package/test/routes/user/api-keys.test.js +158 -0
- package/test/routes/user/connections-grant.test.js +759 -0
- package/test/routes/user/connections-identity.test.js +260 -0
- package/test/routes/user/connections-log-privacy.test.js +206 -0
- package/test/routes/user/connections-refresh-lease.test.js +696 -0
- package/test/routes/user/connections-return.test.js +261 -0
- package/test/routes/user/connections-uid.test.js +516 -0
- package/test/routes/user/delete.test.js +138 -0
- package/test/routes/user/feedback.test.js +106 -0
- package/test/routes/user/orders.test.js +233 -0
- package/test/routes/user/sessions.test.js +231 -0
- package/test/routes/user/settings-validate.test.js +84 -0
- package/test/routes/user/signup-emails.test.js +113 -0
- package/test/routes/user/signup-location.test.js +84 -0
- package/test/routes/user/signup-log-privacy.test.js +112 -0
- package/test/routes/user/signup.test.js +579 -0
- package/test/routes/user/subscription.test.js +101 -0
- package/test/routes/user/token.test.js +111 -0
- package/test/routes/user/user.test.js +158 -0
- package/test/routes/verts/cache.test.js +78 -0
- package/test/routes/verts/click-destination.test.js +76 -0
- package/test/routes/verts/crud.test.js +194 -0
- package/test/routes/verts/redirect.test.js +147 -0
- package/test/routes/verts/selection.test.js +237 -0
- package/test/routes/verts/serve.test.js +185 -0
- package/test/routes/verts/unit-document.test.js +117 -0
- package/test/rules/_environment.js +66 -0
- package/test/rules/brand-merge.test.js +195 -0
- package/test/rules/field-helpers.test.js +309 -0
- package/test/rules/notifications.test.js +577 -0
- package/test/rules/payments-carts.test.js +406 -0
- package/test/rules/sessions.test.js +170 -0
- package/test/rules/user.test.js +517 -0
- package/test/rules/verts.test.js +101 -0
- package/test/security/fetch-log-secrets.test.js +124 -0
- package/test/security/primitives.test.js +105 -0
- package/test/security/repo-pinning.test.js +77 -0
- package/test/stripe-live/subscription-lifecycle.test.js +141 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# PayPal sandbox QA drives (live sale + refund fixtures)
|
|
2
|
+
|
|
3
|
+
The repeatable recipe for driving a REAL PayPal sandbox payment through the deployed
|
|
4
|
+
playground backend, proven 2026-08-17 on the [#240](https://github.com/Omega-JS-Stack/omega/issues/240)
|
|
5
|
+
v1 sale fixture drive. Use it whenever a webhook change needs a live delivery instead
|
|
6
|
+
of a fixture replay. [#348](https://github.com/Omega-JS-Stack/omega/issues/348) precreated
|
|
7
|
+
what it could: the QA product's provider objects exist on every provider. The BUYER
|
|
8
|
+
stays hand-made — PayPal retired the sandbox-accounts API (see below).
|
|
9
|
+
|
|
10
|
+
## The standing fixtures
|
|
11
|
+
|
|
12
|
+
- **Merchant / API creds** — the sandbox business account (display name
|
|
13
|
+
"test facilitator's Test Store", PayPal's default; rename in the developer
|
|
14
|
+
dashboard if the checkout header matters). Creds: `PAYPAL_CLIENT_ID` +
|
|
15
|
+
`PAYPAL_CLIENT_SECRET` in the playground backend's `.env`
|
|
16
|
+
(`brands/omega-playground/targets/backend/.env`). The manager wants the client id in
|
|
17
|
+
config (`payment.providers.paypal.clientId`) and only the secret in `.env`;
|
|
18
|
+
the backend wants both as env vars.
|
|
19
|
+
- **Webhook** — registered by the manager payment walk, pointing at the deployed
|
|
20
|
+
playground backend (`api.playground.omegajs.dev/omega/payments/webhook`).
|
|
21
|
+
Deliveries arrive with real signature headers; the deployed backend is the
|
|
22
|
+
verification surface (a local emulator receives nothing — no forwarding path).
|
|
23
|
+
- **QA product** — `proof-press` ("Proof Press", $5 monthly, NO trial)
|
|
24
|
+
in `brands/omega-playground/config/omega.json5`. Trial-free ON PURPOSE: every public
|
|
25
|
+
tier carries a 14-day trial, which defers a subscription's first sale two weeks.
|
|
26
|
+
It lists on the playground /pricing page on purpose (Ian 2026-08-19, #348) so
|
|
27
|
+
real checkouts can be run against it by hand; the `hidden: true` mechanism
|
|
28
|
+
remains available for products that should stay off /pricing.
|
|
29
|
+
The manager payment walk owns the provider objects
|
|
30
|
+
(`npx mgr manage --service=payment` at the playground root); read the current
|
|
31
|
+
ids from the config write-backs (`stripe.productId`, `paypal.productId`) and
|
|
32
|
+
list plans via `GET /v1/billing/plans?product_id=<paypal.productId>`.
|
|
33
|
+
- **Sandbox buyer** — `qa-fixture-buyer@playground.omegajs.dev`, created by hand
|
|
34
|
+
through PayPal's guest checkout during the 2026-08-17 drive. Its wallet holds a
|
|
35
|
+
working generator-BIN Visa. It is DURABLE — the hoops are one-time, not per
|
|
36
|
+
drive. If the login is lost, recreate it through the guest flow below, or from
|
|
37
|
+
the Developer Dashboard (Sandbox → Accounts → Create Account).
|
|
38
|
+
**There is no API for this** (probed 2026-08-18, #348): the app-credential token
|
|
39
|
+
carries no sandbox-account scope (asking for one downgrades the token to
|
|
40
|
+
`openid`), the legacy `/v1/customer/partners/{merchant_id}/accounts` route 404s
|
|
41
|
+
even with our real merchant id, and every `developer.paypal.com` account path
|
|
42
|
+
redirects to an interactive login. Don't spend time re-probing it. Because the
|
|
43
|
+
walk cannot precreate the buyer, it REMINDS instead: a payment walk whose PayPal
|
|
44
|
+
credentials resolve to sandbox closes `paypal-products` with the buyer note and
|
|
45
|
+
the Sandbox → Accounts deep link (silent in live mode).
|
|
46
|
+
|
|
47
|
+
## Two lanes — pick deliberately (Ian's ruling, 2026-08-17)
|
|
48
|
+
|
|
49
|
+
- **Default: through omega's checkout.** Drive the deployed playground site's
|
|
50
|
+
checkout page as a user. That exercises the FULL pipeline — payments-intent,
|
|
51
|
+
cart, provider object, confirmation redirect — and the webhook folds onto an
|
|
52
|
+
existing trail. Any "does the pipeline work" drive belongs here.
|
|
53
|
+
- **Exception: raw API, only when the test target is the recovery path.** A
|
|
54
|
+
subscription created straight through PayPal's API arrives at the webhook with
|
|
55
|
+
no intent and no order, which is precisely what the uid-recovery code
|
|
56
|
+
(fetchResource + custom_id fold, #224) exists for. Know that this lane mints
|
|
57
|
+
the order FROM the webhook — the #335 refund-before-order shape — so never
|
|
58
|
+
mistake its result for proof of the checkout lane.
|
|
59
|
+
|
|
60
|
+
## The drive (subscription sale → refund, raw-API lane)
|
|
61
|
+
|
|
62
|
+
All API calls go to `https://api-m.sandbox.paypal.com` with an OAuth token from the
|
|
63
|
+
`.env` creds. A staged helper script from the 2026-08-17 run is described in the
|
|
64
|
+
#240 trail; rebuild it from this sequence if needed.
|
|
65
|
+
|
|
66
|
+
1. `POST /v1/billing/subscriptions` with the QA plan id,
|
|
67
|
+
`custom_id: "uid:{uid},orderId:{orderId}"` (the pipeline's parse format —
|
|
68
|
+
uid must exist on the LIVE project; export one with
|
|
69
|
+
`npx firebase auth:export --project omegajs-playground`), and an
|
|
70
|
+
`application_context` carrying `return_url`/`cancel_url` (omit it and PayPal
|
|
71
|
+
shows its own confirmation page instead of redirecting back).
|
|
72
|
+
2. Open the returned `approve` link in a browser, log in as the sandbox buyer,
|
|
73
|
+
pick the working card, Agree. Status flips `APPROVAL_PENDING → ACTIVE` and the
|
|
74
|
+
first REGULAR cycle charges immediately (no trial).
|
|
75
|
+
3. `GET /v1/billing/subscriptions/{id}` for `billing_info.last_payment`, then
|
|
76
|
+
`GET /v1/billing/subscriptions/{id}/transactions?start_time&end_time` for the
|
|
77
|
+
sale id. `PAYMENT.SALE.COMPLETED` arrives at the deployed backend.
|
|
78
|
+
4. Refund: `POST /v1/payments/sale/{saleId}/refund` with `{}` (full refund).
|
|
79
|
+
`PAYMENT.SALE.REFUNDED` arrives; the worker runs `fetchResource('sale')`,
|
|
80
|
+
resolves the uid, and folds the order to `status=refunded`.
|
|
81
|
+
5. Verify: `GET /v1/notifications/webhooks-events?event_type=...` for deliveries;
|
|
82
|
+
`npx firebase functions:log --project omegajs-playground` for the parse,
|
|
83
|
+
fetch, and transition lines.
|
|
84
|
+
6. Cleanup: `POST /v1/billing/subscriptions/{id}/cancel`. Leave the plan and
|
|
85
|
+
product alone — the manager owns them.
|
|
86
|
+
|
|
87
|
+
## Gotchas (each cost real time on the first drive)
|
|
88
|
+
|
|
89
|
+
- `PAYMENT.SALE.*` (v1) events come ONLY from subscription billing. One-time card
|
|
90
|
+
orders emit `PAYMENT.CAPTURE.*` (v2). Pick the lane for the event you need.
|
|
91
|
+
- The classic 4111/4012 test Visas fail: 4111… is declined at commit, 4012… is
|
|
92
|
+
claimed by another sandbox account. A Luhn-valid number on PayPal's generator
|
|
93
|
+
BIN (4032…) works — the buyer's saved card is one.
|
|
94
|
+
- Guest checkout hoops: the expiry mask wants `MM/YY`; the SMS gate accepts any
|
|
95
|
+
6-digit code in sandbox; a fake street address hard-rejects until PayPal's
|
|
96
|
+
normalizer can match it (a real street like `2211 N 1st St, San Jose` passes).
|
|
97
|
+
- A subscription created with `payment_source.card` does NOT auto-activate; it
|
|
98
|
+
still returns an approval link.
|
|
99
|
+
- A real v1 subscription sale carries `custom` + `billing_agreement_id` and no
|
|
100
|
+
`parent_payment`; the legacy one-time shape (uid via the `parent_payment`
|
|
101
|
+
fold) is covered by `test/fixtures/paypal/sale-refunded.json`. Both uid paths
|
|
102
|
+
stay pinned.
|
|
103
|
+
- v1 resources spell status `state`; the pipeline reads both
|
|
104
|
+
(`resource.status ?? resource.state`, [#347](https://github.com/Omega-JS-Stack/omega/issues/347)),
|
|
105
|
+
so a successful v1 fetch logs its real status (`status=refunded`).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Response Headers
|
|
2
|
+
|
|
3
|
+
@omega.js/backend automatically sets `omega-properties` header with:
|
|
4
|
+
- `code`: HTTP status code
|
|
5
|
+
- `tag`: Function name and execution ID
|
|
6
|
+
- `usage`: Current usage stats
|
|
7
|
+
- `schema`: Resolved schema info
|
|
8
|
+
|
|
9
|
+
The header rides every `ctx.respond()`/`ctx.report()` response (exposed via `Access-Control-Expose-Headers`) and is consumed automatically by @omega.js/client's `omega.request()`, which merges `usage.current` + `usage.limits` into the frontend `usage` bindings key — `data-omega-bind` elements refresh after every API call.
|
package/docs/routes.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Creating Routes, Events, Cron Jobs
|
|
2
|
+
|
|
3
|
+
Recipes for building consumer-side routes plus @omega.js/backend-side event handlers and cron jobs. See also [docs/schemas.md](schemas.md) for schema definitions, [docs/auth-hooks.md](auth-hooks.md) for auth lifecycle hooks, and [docs/common-operations.md](common-operations.md) for inside-the-handler patterns.
|
|
4
|
+
|
|
5
|
+
## New Route (Consumer Project)
|
|
6
|
+
|
|
7
|
+
Routes live at `src/routes/{path}/{method}.js` (staged to `dist/` by `omega build` — consumers are src-first, see [build-system.md](build-system.md)) — @omega.js/backend routes requests to the matching method file (`get.js` / `post.js` / `put.js` / `delete.js`), falling back to `index.js` if no method-specific file exists.
|
|
8
|
+
|
|
9
|
+
A route exports an **async function receiving a context object** (built by the middleware — see `src/manager/helpers/middleware.js`):
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
/**
|
|
13
|
+
* POST /items - Create a new item
|
|
14
|
+
*/
|
|
15
|
+
module.exports = async ({ Manager, ctx, analytics, usage, user, settings, libraries, utilities }) => {
|
|
16
|
+
if (!user.authenticated) {
|
|
17
|
+
return ctx.respond('Authentication required', { code: 401 });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const { admin } = libraries;
|
|
21
|
+
const firestore = admin.firestore();
|
|
22
|
+
|
|
23
|
+
// Count a use of a metered feature — check, count and write in ONE call
|
|
24
|
+
await usage.consume('requests');
|
|
25
|
+
|
|
26
|
+
// settings strings are whitespace-trimmed by middleware; HTML is preserved.
|
|
27
|
+
// Call utilities.sanitize() at the HTML-insertion site, or opt the whole
|
|
28
|
+
// route in to middleware HTML strip via { sanitize: true } on .run().
|
|
29
|
+
const id = settings.id; // auto-generated by the schema (see schemas.md)
|
|
30
|
+
|
|
31
|
+
await firestore.doc(`items/${id}`).set({ id, owner: user.auth.uid, ...settings });
|
|
32
|
+
|
|
33
|
+
return ctx.respond({ id });
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Context object fields: `Manager`, `ctx`, `user` (from `ctx.getUser()`), `usage`, `settings` (schema-resolved), `analytics`, `libraries`, `utilities`.
|
|
38
|
+
|
|
39
|
+
### CRUD method files
|
|
40
|
+
|
|
41
|
+
Every resource endpoint follows proper CRUD with **method-specific files** (plural-noun route names — `items`, not `item`):
|
|
42
|
+
|
|
43
|
+
| Method | File | Purpose | Path |
|
|
44
|
+
|--------|------|---------|------|
|
|
45
|
+
| GET | `get.js` | List all or fetch one | `/items` or `/items/{id}` |
|
|
46
|
+
| POST | `post.js` | Create new | `/items` |
|
|
47
|
+
| PUT | `put.js` | Update existing | `/items/{id}` |
|
|
48
|
+
| DELETE | `delete.js` | Delete existing | `/items/{id}` |
|
|
49
|
+
|
|
50
|
+
**GET routes exist for external API consumers.** The dashboard/frontend reads data directly from Firestore (faster, cheaper, no cold starts). POST/PUT/DELETE still go through Cloud Functions for server-side validation, usage tracking, and analytics.
|
|
51
|
+
|
|
52
|
+
**PUT and DELETE must verify ownership** before mutating:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
const existing = docSnap.data();
|
|
56
|
+
|
|
57
|
+
if (existing.owner !== user.auth.uid) {
|
|
58
|
+
return ctx.respond('Not authorized', { code: 403 });
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Immutable fields (`id`, `owner`, `stats`, `metadata.created`) should NOT be editable via PUT. ID generation (POST) and ID-from-path extraction (GET/PUT/DELETE) happen in the **schema**, not the route — see [schemas.md](schemas.md).
|
|
63
|
+
|
|
64
|
+
### Key route patterns
|
|
65
|
+
|
|
66
|
+
- Short-circuit returns for auth/validation checks
|
|
67
|
+
- `settings` contains the parsed + validated request data (from schemas)
|
|
68
|
+
- `ctx.respond()` for ALL responses (success and error)
|
|
69
|
+
- `admin.firestore().doc('collection/id')` shorthand for Firestore access ([firestore.md](firestore.md))
|
|
70
|
+
- Timestamps under `metadata.{created,updated}` ([firestore.md](firestore.md#document-metadata))
|
|
71
|
+
|
|
72
|
+
### The `test/` route folder is development-only
|
|
73
|
+
|
|
74
|
+
`routes/test/*` — the framework's own routes AND any a consumer adds under that folder — answers **404 in production**. The guard lives once in `Middleware.run()` (`src/manager/helpers/middleware.js`, `isDevOnlyRouteBlocked()`), the single place both request paths converge (the deployed `omega_api` function and the local express server), so a NEW test route is gated the day it lands instead of the day somebody remembers to copy a guard. Under the emulator (`isDevelopment()`/`isTesting()`) every one of them serves normally.
|
|
75
|
+
|
|
76
|
+
**Zero carve-outs.** The one route that used to need one — the liveness probe — is a real route now: see below.
|
|
77
|
+
|
|
78
|
+
Put debug/echo/reset routes in `test/` and they are safe by default. A route that must answer in production does NOT belong there.
|
|
79
|
+
|
|
80
|
+
Both the gate and the module loader read the route path **normalized** (`path.posix.normalize`, lowercased, `.js` dropped), because it arrives straight off the request URL — `./test/usage`, `.//test/usage` and `x/../test/usage` all resolve to the same handler and are all gated the same. A route path may also never escape the routes directory: a leading `..` or an absolute path is a flat 404, even when it climbs back in (`../routes/test/usage`) — `isRouteOutsideRoutesDir()`, same file.
|
|
81
|
+
|
|
82
|
+
### `GET /health` — the liveness probe
|
|
83
|
+
|
|
84
|
+
**`GET /omega/health`** (`src/manager/routes/health/get.js`) is the deployed backend's liveness + version endpoint. It is **public** (no auth) and **echoes no request input** — the payload is a fixed set of fields read from the Manager, never from the request:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"status": "healthy",
|
|
89
|
+
"timestamp": "2026-08-14T00:00:00.000Z",
|
|
90
|
+
"environment": "production",
|
|
91
|
+
"projectId": "your-project",
|
|
92
|
+
"version": "1.4.0",
|
|
93
|
+
"backendVersion": "5.9.0",
|
|
94
|
+
"testExtendedMode": false
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`omega manage`'s live API check reads it on a real host (`@omega.js/manager`'s testing service) and the test runner reads it to confirm the emulator's project and mode. `test/health` still serves the same handler in dev/testing for anything that has not moved yet, but it is a `test/` route — **404 in production** like the rest of the folder. Point liveness checks at `/omega/health`.
|
|
99
|
+
|
|
100
|
+
### Functions entry point (`src/index.js`)
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
const Manager = (new (require('@omega.js/backend'))).init(exports, {
|
|
104
|
+
setupFunctionsIdentity: false,
|
|
105
|
+
});
|
|
106
|
+
const { functions } = Manager.libraries;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @route /items
|
|
110
|
+
*
|
|
111
|
+
* @method GET /items - List all items
|
|
112
|
+
* @method GET /items/:itemId - Get single item
|
|
113
|
+
* @method POST /items - Create a new item
|
|
114
|
+
* @method PUT /items/:itemId - Update an item
|
|
115
|
+
* @method DELETE /items/:itemId - Delete an item
|
|
116
|
+
*/
|
|
117
|
+
exports.items = functions
|
|
118
|
+
.runWith({ memory: '256MB', timeoutSeconds: 120 })
|
|
119
|
+
.https.onRequest((req, res) => Manager.Middleware(req, res).run('items'));
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The schema defaults to the route name (`.run('items')` loads `src/schemas/items/`); pass `{ schema: 'custom' }` only when the schema path differs.
|
|
123
|
+
|
|
124
|
+
For operations that don't fit CRUD (e.g. `/items/:itemId/export`), add an **action sub-path** handled within the same Cloud Function (parsed from the request path) or as a separate function if resource needs differ significantly.
|
|
125
|
+
|
|
126
|
+
### firebase.json routing
|
|
127
|
+
|
|
128
|
+
Make routes public with rewrites. Use the bracket syntax so sub-paths like `/items/{id}` route correctly:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"hosting": {
|
|
133
|
+
"rewrites": [
|
|
134
|
+
{ "source": "{/items,/items/**}", "function": "items" }
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**CRITICAL**: Without the `/**` wildcard, requests to `/items/{id}` won't reach the function.
|
|
141
|
+
|
|
142
|
+
**CRITICAL: Rewrite order matters — first match wins.** When multiple functions share a path prefix, the most specific routes MUST come first and the catch-all last, otherwise it swallows all sub-routes:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"hosting": {
|
|
147
|
+
"rewrites": [
|
|
148
|
+
{ "source": "{/agents/*/chat,/agents/*/chat/**}", "function": "agentsChat" },
|
|
149
|
+
{ "source": "/agents/*/conversations/**", "function": "agentsConversations" },
|
|
150
|
+
{ "source": "{/agents,/agents/**}", "function": "agents" }
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Order: most specific → least specific → catch-all.
|
|
157
|
+
|
|
158
|
+
## New Event Handler
|
|
159
|
+
|
|
160
|
+
Handlers live at `src/manager/events/{type}/{event}.js` — `auth/` (the Identity Platform user lifecycle), `firestore/{collection}/on-write.js` (document triggers), `cron/` (the scheduled runner, below).
|
|
161
|
+
|
|
162
|
+
A handler exports an **async function receiving a context object**, exactly like a route — `await handler({ Manager, ctx, libraries, user, context, change, snapshot })` is the one call the middleware makes (`src/manager/helpers/event-middleware.js`). A handler exported any other way is called as a plain function: its body never runs and nothing errors.
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
/**
|
|
166
|
+
* Notification subscription write handler
|
|
167
|
+
*/
|
|
168
|
+
module.exports = async ({ Manager, ctx, change, context, libraries }) => {
|
|
169
|
+
const { admin } = libraries;
|
|
170
|
+
|
|
171
|
+
ctx.log('Event triggered', context.params);
|
|
172
|
+
|
|
173
|
+
// Event logic here
|
|
174
|
+
};
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Which payload keys carry a value is the TRIGGER's business — auth events bring `user` + `context`, Firestore document triggers bring `change` (or `snapshot`) + `context`, cron jobs bring `context` alone; the rest arrive `undefined`. `Manager`, `ctx` (a fresh `RouteContext` per event) and `libraries` always ride.
|
|
178
|
+
|
|
179
|
+
Wire it to its trigger in `src/manager/index.js`, where every framework event runs through `EventMiddleware` (`events` is the absolute `src/manager/events` path):
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
exporter.omega_notificationsOnWrite =
|
|
183
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
184
|
+
.firestore.document('notifications/{token}')
|
|
185
|
+
.onWrite((change, context) => self.EventMiddleware({ change, context }).run(`${events}/firestore/notifications/on-write.js`));
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
A **consumer project** wires its own the same way, naming the handler relatively: `Manager.EventMiddleware({ snapshot, context }).run('users/on-create')` loads `{Manager.cwd}/events/users/on-create.js` — the STAGED copy (`dist/events/`, the deployed functions source), so author it at `src/events/users/on-create.js` and let `omega build` stage it. A name starting with `/` is used verbatim, which is how the framework points at its own.
|
|
189
|
+
|
|
190
|
+
Throwing is the error contract: an `HttpsError` or an explicit numeric 4xx `code` rejects untouched (the trigger's client fault), and anything else is reported — logged AND captured to Sentry — as a server fault.
|
|
191
|
+
|
|
192
|
+
## New Cron Job (Consumer Project)
|
|
193
|
+
|
|
194
|
+
Create `src/hooks/cron/daily/{job}.js` — the runner reads the STAGED copy (`dist/hooks/cron/{name}/`, off `Manager.cwd`), so author it in `src/` and let `omega build` stage it.
|
|
195
|
+
|
|
196
|
+
A job exports an **async function receiving a context object**, exactly like a route — `await handler({ Manager, ctx, context, libraries })` is the one call the runner makes (`src/manager/events/cron/runner.js`). A job exported any other way is called as a plain function: its body never runs and nothing errors.
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
/**
|
|
200
|
+
* Daily job
|
|
201
|
+
*/
|
|
202
|
+
module.exports = async ({ Manager, ctx, context, libraries }) => {
|
|
203
|
+
const { admin } = libraries;
|
|
204
|
+
|
|
205
|
+
ctx.log('Running daily job...');
|
|
206
|
+
|
|
207
|
+
// Job logic here
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Every schedule works the same way — `daily/`, `frequent/` — and the framework's own jobs (`src/manager/events/cron/{name}/`) are written in this exact shape.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Sanitization (XSS Prevention)
|
|
2
|
+
|
|
3
|
+
@omega.js/backend middleware always **trims** whitespace on incoming string fields (via `utilities.trim()`). HTML sanitization is **opt-in** — it's not run by default because it mangles legitimate input like URL query strings (`&` → `&`) and Markdown.
|
|
4
|
+
|
|
5
|
+
The expectation is that you sanitize at the **HTML-insertion site** (in the template, in the email body, etc.) — not at the request boundary.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
1. **Trimming**: Every string in `settings` is whitespace-trimmed by the middleware (objects + arrays walked recursively). Always on.
|
|
10
|
+
2. **HTML sanitization**: Off by default. Opt in per-route with `{ sanitize: true }` on `Manager.Middleware(...).run(...)`.
|
|
11
|
+
3. **Schemas** can mark individual fields with `sanitize: false` to skip the HTML strip for that field when route-level sanitize is enabled (used for fields that legitimately need raw HTML — rich-text editors, email templates).
|
|
12
|
+
|
|
13
|
+
## Route-Level Opt-In
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
// In functions/index.js — enable HTML strip for a specific route
|
|
17
|
+
Manager.Middleware(req, res).run('my-route', { sanitize: true });
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
When enabled, every string in `settings` is run through `sanitize-html` (strip all tags) unless the schema marks the field with `sanitize: false`.
|
|
21
|
+
|
|
22
|
+
## Schema Field Opt-Out (when route-level sanitize is on)
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// This field will NOT be sanitized — raw HTML is preserved
|
|
26
|
+
htmlContent: {
|
|
27
|
+
types: ['string'],
|
|
28
|
+
default: '',
|
|
29
|
+
sanitize: false,
|
|
30
|
+
},
|
|
31
|
+
// This field IS sanitized when route-level sanitize is enabled
|
|
32
|
+
name: {
|
|
33
|
+
types: ['string'],
|
|
34
|
+
default: '',
|
|
35
|
+
},
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
In zod schemas the same option rides the builder: `f.string({ default: '', sanitize: false })`.
|
|
39
|
+
|
|
40
|
+
## Manual Sanitization (Recommended)
|
|
41
|
+
|
|
42
|
+
For most use cases — particularly anywhere you're inserting user-supplied content into HTML — call `utilities.sanitize()` directly at the insertion site:
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Available in route context
|
|
46
|
+
const safeHtml = utilities.sanitize(untrustedData);
|
|
47
|
+
|
|
48
|
+
// Or via Manager
|
|
49
|
+
const safeHtml = Manager.Utilities().sanitize(untrustedData);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Accepts any data type — strings, objects, arrays, primitives. Walks objects/arrays recursively, strips HTML from strings, passes everything else through unchanged.
|
|
53
|
+
|
|
54
|
+
## Why HTML Sanitization Is Not the Middleware Default
|
|
55
|
+
|
|
56
|
+
Stripping HTML from every incoming string at the request boundary is too aggressive — it corrupts legitimate input:
|
|
57
|
+
|
|
58
|
+
- URL query strings: `https://example.com/?a=1&b=2` becomes `https://example.com/?a=1&b=2`
|
|
59
|
+
- Markdown / code snippets with `<`, `>`, `&` characters get mangled
|
|
60
|
+
- API payloads round-tripped through the system get silently rewritten
|
|
61
|
+
|
|
62
|
+
Stored XSS comes from rendering, not from receiving. Sanitize at the render site (where you know the output context — HTML body, attribute, URL, JSON) instead of at the front door.
|
|
63
|
+
|
|
64
|
+
## Route Handler Context
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
module.exports = async ({ Manager, ctx, analytics, usage, user, settings, libraries, utilities }) => {
|
|
68
|
+
// settings — whitespace-trimmed by middleware; HTML preserved unless route opts in via { sanitize: true }
|
|
69
|
+
// utilities — Manager.Utilities() instance for manual sanitize()/trim()
|
|
70
|
+
};
|
|
71
|
+
```
|
package/docs/schemas.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Schemas
|
|
2
|
+
|
|
3
|
+
Schemas define and validate the payload your routes accept. They live at `functions/schemas/{name}/{method}.js` — the resolver loads the method-specific file first (`get.js` / `post.js` / …), falling back to `{name}/index.js` (see `src/manager/helpers/settings.js`). The schema name defaults to the route name (`.run('items')` ↔ `functions/schemas/items/`).
|
|
4
|
+
|
|
5
|
+
## Schema function contract
|
|
6
|
+
|
|
7
|
+
A schema exports a function that receives a **context object** and returns a **flat schema object**. Plan-based adjustments happen INSIDE the function (there is no tier system):
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
module.exports = ({ ctx, user, data, method, headers, geolocation, client }) => {
|
|
11
|
+
const planId = user?.subscription?.product?.id || 'basic';
|
|
12
|
+
const isPremium = planId !== 'basic';
|
|
13
|
+
|
|
14
|
+
const schema = {
|
|
15
|
+
name: {
|
|
16
|
+
types: ['string'],
|
|
17
|
+
default: '',
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
limit: {
|
|
21
|
+
types: ['number'],
|
|
22
|
+
default: 10,
|
|
23
|
+
min: 1,
|
|
24
|
+
max: isPremium ? 1000 : 100, // plan-based limit
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Premium-only field (not present for basic users)
|
|
29
|
+
if (isPremium) {
|
|
30
|
+
schema.premiumOnlyField = {
|
|
31
|
+
types: ['string'],
|
|
32
|
+
default: 'premium-feature',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return schema;
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Context fields: `ctx`, `user` (resolved user), `data` (raw request data), `method`, `headers`, `geolocation`, `client`.
|
|
41
|
+
|
|
42
|
+
## Field Properties
|
|
43
|
+
|
|
44
|
+
- `types` — array of allowed types: `['string']`, `['number']`, `['boolean']`, `['object']`, `['array']`, `['any']`, or multiple (`['string', 'number']`)
|
|
45
|
+
- `default` — default value if not provided; may be a function (`default: () => ...`)
|
|
46
|
+
- `value` — force-set value (ignores user input — e.g. auto-generated IDs)
|
|
47
|
+
- `required` — `true`/`false` or a function `(ctx, settings, options) => bool`. A key counts as missing when it's `undefined` **or `''`** (null/0/false pass). **NEVER combine with `default`** — see the footgun below
|
|
48
|
+
- `min` / `max` — validation bounds (string length, number range, array length), enforced per type. `max`: numbers clamp down, strings/arrays truncate. `min`: numbers clamp up, but a **string or array shorter than `min` is REFUSED** — `400 Invalid settings {field}: must be at least N characters` (`must have at least N items` for arrays), never padded. The length refusal is checked post-resolution at the route boundary, like `enum`, so it sees the value the handler would have gotten; unlike `enum`, it applies even when the caller did not send the field (a `default: ''` with `min: 1` refuses every request that omits it). Enforced **only when declared** — no `min` means negatives and empty strings pass through, and a declared `0` is a real bound
|
|
49
|
+
- `enum` — array of allowed values. Enforced for values the caller sends (checked post-coercion): out-of-list → `400 Invalid settings {field}: must be one of [...]`. Absent fields pass — combine with `required` if the field must also be present
|
|
50
|
+
- `clean` — a RegExp (matched chars removed) or function `(value) => cleaned`
|
|
51
|
+
- `sanitize` — per-field opt-out (`false`) for HTML sanitization; only meaningful when the route opts in via `Manager.Middleware(req, res).run('route', { sanitize: true })`. See [sanitization.md](sanitization.md)
|
|
52
|
+
|
|
53
|
+
### ⚠️ `required` + `default` footgun
|
|
54
|
+
|
|
55
|
+
@omega.js/backend checks `required` against the ORIGINAL request value, before defaults apply — so `required: true` on a field with a `default` throws `Required key {field} is missing in settings` before the default is ever used. For fields that must be non-empty but have a derived default (like path-extracted IDs), use `min: 1` instead — it refuses an empty value with a 400 AFTER the default applies.
|
|
56
|
+
|
|
57
|
+
## Zod schemas
|
|
58
|
+
|
|
59
|
+
A schema module may return a **zod schema** instead of a declarative node object — `Settings.resolve()` detects it and parses with zod in place of the declarative walk. **All framework route schemas use this form** (except the deliberately-empty provider webhook schemas); the declarative form above remains fully supported for consumer projects — both engines run the SAME field pipeline (`src/manager/helpers/schema-engine.js`), so wire shapes are identical either way (proven by `test/helpers/schema-zod.test.js`). Build with the `fields` helpers for the shared semantics (coerce-never-reject, `max` clamp/truncate, a short string/array refused at `min`, `required` fires on `undefined`/`''`, unknown keys stripped):
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const { fields: f } = require('@omega.js/backend/dist/manager/helpers/schema-zod.js'); // framework schemas use a relative path
|
|
63
|
+
|
|
64
|
+
module.exports = ({ user }) => f.object({
|
|
65
|
+
name: f.string({ default: undefined, required: true }),
|
|
66
|
+
limit: f.number({ default: 10, min: 1, max: 100 }),
|
|
67
|
+
tags: f.array({ default: [] }),
|
|
68
|
+
config: f.passthrough({ default: {} }), // types: ['object'] — nested content passes through
|
|
69
|
+
version: f.multi(['string', 'number'], { default: '5' }),
|
|
70
|
+
nested: f.object({ level1: f.string({ default: 'x' }) }),
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Every builder takes the exact declarative node options (`types` via the builder name, plus `default`, `value`, `min`, `max`, `required`, `enum`, `clean`, `sanitize`); `f.field(opts)` is the generic form. Builders throw on unknown options (catches typos). All declarative quirks are preserved, including the `required`+`default` footgun above; `min`/`max` enforce only when declared (no implicit `0` floor — fixed deliberately, see the field-properties list), and a length `min` refuses with the byte-identical 400 the declarative engine raises.
|
|
75
|
+
|
|
76
|
+
Exporting **raw zod** (no builders) opts into zod-native semantics instead: invalid input **rejects with 400** rather than coercing. Use deliberately — it's a behavior change from the declarative contract.
|
|
77
|
+
|
|
78
|
+
Both engines carry two deliberate fixes over the old powertools resolver (documented + asserted in `test/helpers/schema-zod.test.js`): non-empty object/array defaults are returned **clean** (powertools injected `types`/`min`/`max` keys into them) and **cloned per request** (powertools returned the schema's default object by reference). `powertools.defaults()` is no longer used for settings resolution anywhere — node-powertools remains a dependency for its other utilities.
|
|
79
|
+
|
|
80
|
+
Webhook routes (`payments/webhook`, `marketing/webhook`, …) keep their **empty schemas** by design — the body is the raw provider payload; don't wrap them in zod.
|
|
81
|
+
|
|
82
|
+
## ID Generation (POST — Create)
|
|
83
|
+
|
|
84
|
+
IDs are auto-generated in the **schema**, NOT in the route. Use `value` to force-generate via @omega.js/backend's built-in `randomId()` (14-char nanoid, 62-char alphabet, no `-` or `_`):
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
id: {
|
|
88
|
+
types: ['string'],
|
|
89
|
+
value: () => ctx.Manager.Utilities().randomId(),
|
|
90
|
+
},
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The route just reads `settings.id` — no ID generation logic needed.
|
|
94
|
+
|
|
95
|
+
## ID Extraction from Path (GET, PUT, DELETE)
|
|
96
|
+
|
|
97
|
+
For single-item operations, extract the ID from the URL path in the **schema**:
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
// /items/{id} → split('/') = ['', 'items', '{id}'] → index 2
|
|
101
|
+
id: {
|
|
102
|
+
types: ['string'],
|
|
103
|
+
default: (ctx.request.path || '').split('/')[2] || '',
|
|
104
|
+
min: 1, // enforce non-empty (NOT required: true — see footgun above)
|
|
105
|
+
max: 128,
|
|
106
|
+
},
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`min: 1` is a real guard: a request with no ID in the path resolves to `''` and is refused with `400 Invalid settings {id}: must be at least 1 character` before the route runs, so a handler never reads or writes the wrong document.
|
|
110
|
+
|
|
111
|
+
For GET list endpoints, omit `min` so an empty ID means "list" (a declared `min: 1` would refuse the list call):
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
id: {
|
|
115
|
+
types: ['string'],
|
|
116
|
+
default: (ctx.request.path || '').split('/')[2] || '',
|
|
117
|
+
},
|
|
118
|
+
limit: { types: ['number'], default: 20, min: 1, max: 100 },
|
|
119
|
+
startAfter: { types: ['string'], default: '' },
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Dynamic Schemas
|
|
123
|
+
|
|
124
|
+
Schemas can branch on request data (e.g. different fields per type):
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
module.exports = ({ ctx, data }) => {
|
|
128
|
+
const type = data?.type || '';
|
|
129
|
+
|
|
130
|
+
const schema = {
|
|
131
|
+
name: { types: ['string'], default: undefined, required: true },
|
|
132
|
+
type: { types: ['string'], default: undefined, required: true },
|
|
133
|
+
options: {},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
switch (type) {
|
|
137
|
+
case 'url':
|
|
138
|
+
schema.options = { url: { types: ['string'], default: undefined, required: true } };
|
|
139
|
+
break;
|
|
140
|
+
case 'text':
|
|
141
|
+
schema.options = { text: { types: ['string'], default: undefined, required: true } };
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
schema.options = {};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return schema;
|
|
148
|
+
};
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Reference Implementation
|
|
152
|
+
|
|
153
|
+
The comprehensive test schema exercising every field option (types, function defaults, forced `value`, conditional `required`, min/max clamping, `clean` regex + function, nested objects, plan-based fields): [`src/manager/schemas/test/schema/post.js`](../src/manager/schemas/test/schema/post.js) — in zod `fields` form; its frozen declarative twin (the powertools reference it must keep matching) lives in [`test/helpers/schema-zod.test.js`](../test/helpers/schema-zod.test.js).
|
|
154
|
+
|
|
155
|
+
## Field Sanitization
|
|
156
|
+
|
|
157
|
+
Middleware always trims whitespace on string fields. HTML sanitization is **opt-in per route** — `Manager.Middleware(req, res).run('my-route', { sanitize: true })`. When opted in, fields can individually opt back out with `sanitize: false`. See [sanitization.md](sanitization.md).
|
|
158
|
+
|
|
159
|
+
## See also
|
|
160
|
+
|
|
161
|
+
- [routes.md](routes.md) — the routes consuming `settings`
|
|
162
|
+
- [sanitization.md](sanitization.md) — trim vs HTML-strip behavior
|
|
163
|
+
- [test-framework.md](test-framework.md) — schema tests (`test/routes/test/schema.test.js`)
|