@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,982 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const Module = require('module');
|
|
4
|
+
const jetpack = require('fs-jetpack');
|
|
5
|
+
const chalk = require('chalk').default;
|
|
6
|
+
|
|
7
|
+
const HttpClient = require('./utils/http-client.js');
|
|
8
|
+
const assertions = require('./utils/assertions.js');
|
|
9
|
+
const { seed } = require('./seed.js');
|
|
10
|
+
const rulesClient = require('./utils/firestore-rules-client.js');
|
|
11
|
+
const { EXTENDED_MODE_WARNING } = require('./utils/extended-mode-warning.js');
|
|
12
|
+
const { SkipError } = require('../vendor/devkit/test/runner-core.js');
|
|
13
|
+
const { markRunnerActive } = require('../vendor/devkit/test/define-cases.js');
|
|
14
|
+
const { parseTestScope, isPathTargeted, noMatchMessage, FRAMEWORK_IDS } = require('../vendor/devkit/test/scope.js');
|
|
15
|
+
const { declaredLanes } = require('../utils/test-lanes.js');
|
|
16
|
+
|
|
17
|
+
// Test directories that belong to an OPT-IN lane, discovered only when that
|
|
18
|
+
// lane's own gate opened it (`npx omega test --lane=<name>`). The names come
|
|
19
|
+
// from this framework's own package.json `omega.testLanes` — the one home the
|
|
20
|
+
// gate modules and the brand-root fan-out read too (src/utils/test-lanes.js).
|
|
21
|
+
const LANE_DIRECTORIES = new Set(declaredLanes());
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @omega.js/backend Integration Test Runner
|
|
25
|
+
* Supports standalone tests and test suites with sequential tests and shared state
|
|
26
|
+
*/
|
|
27
|
+
class TestRunner {
|
|
28
|
+
constructor(options) {
|
|
29
|
+
options = options || {};
|
|
30
|
+
|
|
31
|
+
// Store config directly, only add defaults for truly optional fields
|
|
32
|
+
this.config = {
|
|
33
|
+
...options,
|
|
34
|
+
bemDir: options.bemDir || path.resolve(__dirname, '..'),
|
|
35
|
+
timeout: options.timeout || 30000,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Alias for backwards compatibility
|
|
39
|
+
this.options = this.config;
|
|
40
|
+
|
|
41
|
+
this.rulesContext = null;
|
|
42
|
+
|
|
43
|
+
this.accounts = null;
|
|
44
|
+
this.results = {
|
|
45
|
+
passed: 0,
|
|
46
|
+
failed: 0,
|
|
47
|
+
skipped: 0,
|
|
48
|
+
aborted: false, // pre-flight abort (config/health/accounts) — must exit non-zero
|
|
49
|
+
noMatch: null, // a named target that selected nothing (#814) — must exit non-zero
|
|
50
|
+
tests: [],
|
|
51
|
+
startTime: null,
|
|
52
|
+
endTime: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Main run method
|
|
58
|
+
*/
|
|
59
|
+
async run() {
|
|
60
|
+
// Abort if @omega.js/backend is running from the user's home directory (e.g., accidental ~/node_modules install)
|
|
61
|
+
const homeDir = os.homedir();
|
|
62
|
+
if (__dirname.startsWith(path.join(homeDir, 'node_modules'))) {
|
|
63
|
+
console.error(chalk.red('\n ERROR: @omega.js/backend is running from ~/node_modules (home directory install).'));
|
|
64
|
+
console.error(chalk.red(' This is likely an accidental global install that shadows local project copies.'));
|
|
65
|
+
console.error(chalk.red(` Fix: rm -rf ${path.join(homeDir, 'node_modules')} ${path.join(homeDir, 'package.json')} ${path.join(homeDir, 'package-lock.json')}`));
|
|
66
|
+
console.error(chalk.red(` Running from: ${__dirname}\n`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Set testing flag to skip external API calls (emails, SendGrid)
|
|
71
|
+
process.env.OMEGA_TEST_MODE = 'true';
|
|
72
|
+
|
|
73
|
+
// Claim the run before any case file is required: defineCases() only lets a
|
|
74
|
+
// spec through once a real runner is loading it (#630).
|
|
75
|
+
markRunnerActive();
|
|
76
|
+
|
|
77
|
+
this.results.startTime = Date.now();
|
|
78
|
+
|
|
79
|
+
console.log(chalk.bold('\n @omega.js/backend Integration Tests\n'));
|
|
80
|
+
|
|
81
|
+
// Warn if TEST_EXTENDED_MODE is enabled
|
|
82
|
+
if (process.env.TEST_EXTENDED_MODE) {
|
|
83
|
+
console.log(chalk.yellow.bold(` ${EXTENDED_MODE_WARNING[0]}`));
|
|
84
|
+
EXTENDED_MODE_WARNING.slice(1).forEach((line) => console.log(chalk.yellow(` ${line}`)));
|
|
85
|
+
console.log('');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Which files this run selects
|
|
89
|
+
// @omega.js/backend tests are in the top-level test/ directory of the package
|
|
90
|
+
const frameworkTestsDir = path.resolve(__dirname, '../../test');
|
|
91
|
+
const projectTestsDir = path.join(this.options.projectDir, 'test');
|
|
92
|
+
|
|
93
|
+
// C5 scoping: bare/`project:`/`brand:` = project tests only,
|
|
94
|
+
// `framework:`/`omega:`/`mgr:`/`backend:` = the framework suite,
|
|
95
|
+
// `full:` = both. Framework self-test defaults to the framework source.
|
|
96
|
+
this.scope = parseTestScope(this.options.testPaths, {
|
|
97
|
+
frameworkAliases: FRAMEWORK_IDS['@omega.js/backend'],
|
|
98
|
+
selfTest: this.options.isFrameworkSelfTest,
|
|
99
|
+
});
|
|
100
|
+
for (const target of this.scope.invalid) {
|
|
101
|
+
console.log(chalk.yellow(` ⚠ Unknown test scope prefix ignored: ${target}`));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// A target that names a path and selects nothing is a typo, or a suite
|
|
105
|
+
// renamed out from under it: reporting "0 passing" at exit 0 there runs
|
|
106
|
+
// silently green ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)).
|
|
107
|
+
// Ahead of the preflight below, so a typo costs a second, not a whole stack.
|
|
108
|
+
if (isPathTargeted(this.scope) && this.countSelected(frameworkTestsDir, projectTestsDir) === 0) {
|
|
109
|
+
const target = this.options.testPaths.join(' ');
|
|
110
|
+
console.log(chalk.red(` ${noMatchMessage(target)}`));
|
|
111
|
+
this.results.noMatch = target;
|
|
112
|
+
return this.results;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Validate configuration
|
|
116
|
+
if (!this.validateConfig()) {
|
|
117
|
+
this.results.aborted = true;
|
|
118
|
+
return this.results;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Health check (use basic http client without accounts)
|
|
122
|
+
// Use hosting URL for all requests (rewrites to omega_api function)
|
|
123
|
+
const healthHttp = new HttpClient({
|
|
124
|
+
apiUrl: this.options.apiUrl,
|
|
125
|
+
timeout: this.options.timeout,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const healthy = await this.healthCheck(healthHttp);
|
|
129
|
+
if (!healthy) {
|
|
130
|
+
this.results.aborted = true;
|
|
131
|
+
return this.results;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Setup accounts
|
|
135
|
+
const accountsReady = await this.setupAccounts();
|
|
136
|
+
if (!accountsReady) {
|
|
137
|
+
this.results.aborted = true;
|
|
138
|
+
return this.results;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Run @omega.js/backend default tests
|
|
142
|
+
if (this.scope.sources.includes('framework') && jetpack.exists(frameworkTestsDir)) {
|
|
143
|
+
console.log(chalk.bold(' @omega.js/backend Core Tests'));
|
|
144
|
+
await this.runTestsInDir(frameworkTestsDir, 'backend');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Run project-specific tests
|
|
148
|
+
if (this.scope.sources.includes('project') && jetpack.exists(projectTestsDir)) {
|
|
149
|
+
console.log(chalk.bold('\n Project Tests'));
|
|
150
|
+
await this.runTestsInDir(projectTestsDir, 'project');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Cleanup rules context
|
|
154
|
+
if (this.rulesContext) {
|
|
155
|
+
await this.rulesContext.cleanup();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Report results
|
|
159
|
+
this.reportResults();
|
|
160
|
+
|
|
161
|
+
this.results.endTime = Date.now();
|
|
162
|
+
return this.results;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Validate configuration
|
|
167
|
+
*/
|
|
168
|
+
validateConfig() {
|
|
169
|
+
if (!this.options.apiUrl) {
|
|
170
|
+
console.log(chalk.red(' ✗ Missing apiUrl'));
|
|
171
|
+
console.log(chalk.gray(' Set OMEGA_API_URL environment variable or pass --url flag'));
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!this.options.adminKey) {
|
|
176
|
+
console.log(chalk.red(' ✗ Missing adminKey'));
|
|
177
|
+
console.log(chalk.gray(' Set OMEGA_ADMIN_KEY environment variable or pass --key flag'));
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!this.options.webhookKey) {
|
|
182
|
+
console.log(chalk.red(' ✗ Missing webhookKey'));
|
|
183
|
+
console.log(chalk.gray(' Set OMEGA_WEBHOOK_KEY environment variable or pass --webhook-key flag'));
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!this.options.brand?.id) {
|
|
188
|
+
console.log(chalk.red(' ✗ Missing brand.id'));
|
|
189
|
+
console.log(chalk.gray(' Could not determine brand ID from configuration'));
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!this.options.domain) {
|
|
194
|
+
console.log(chalk.red(' ✗ Missing domain'));
|
|
195
|
+
console.log(chalk.gray(' Could not determine the brand host from brand.url'));
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Check if server is healthy
|
|
204
|
+
*/
|
|
205
|
+
async healthCheck(http) {
|
|
206
|
+
process.stdout.write(chalk.gray(' Checking server health... '));
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
const response = await http.get('omega/health');
|
|
210
|
+
|
|
211
|
+
if (response.success) {
|
|
212
|
+
console.log(chalk.green('✓'));
|
|
213
|
+
|
|
214
|
+
// Abort if the running emulator belongs to a different project.
|
|
215
|
+
// This catches the case where you run `npx omega test` in project A
|
|
216
|
+
// while project B's emulator is still up on the same ports — requests
|
|
217
|
+
// hit the wrong hosting rewrites and tests fail with mysterious 404s.
|
|
218
|
+
const mismatch = await this.checkProjectMismatch(response.data);
|
|
219
|
+
if (mismatch) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Report the live mode the emulator just confirmed. The test command
|
|
224
|
+
// writes `.temp/test-mode.json` before invoking us; the emulator's
|
|
225
|
+
// file-watcher mutates its `process.env.TEST_EXTENDED_MODE` to match;
|
|
226
|
+
// the health endpoint re-reads the file as a freshness guard. By
|
|
227
|
+
// construction these are equal — no mismatch warning needed.
|
|
228
|
+
const emulatorExtended = !!response.data?.testExtendedMode;
|
|
229
|
+
console.log(chalk.gray(` Mode: ${emulatorExtended ? 'extended (real external APIs)' : 'normal (external APIs skipped)'}`));
|
|
230
|
+
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log(chalk.red('✗'));
|
|
235
|
+
console.log(chalk.red(` Server not responding: ${response.error}`));
|
|
236
|
+
console.log(chalk.gray(` Make sure your functions are deployed and running at ${this.options.apiUrl}`));
|
|
237
|
+
return false;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.log(chalk.red('✗'));
|
|
240
|
+
console.log(chalk.red(` Health check failed: ${error.message}`));
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Verify the running emulator belongs to this project. The hub's
|
|
247
|
+
* GET /emulators carries no projectId (confirmed against firebase-tools 15.x),
|
|
248
|
+
* so that leg always comes back empty; the health endpoint's projectId field
|
|
249
|
+
* (added in @omega.js/backend 5.3.3+) is the working source. Returns true
|
|
250
|
+
* (= mismatch, abort) if the project IDs differ.
|
|
251
|
+
*/
|
|
252
|
+
async checkProjectMismatch(healthData) {
|
|
253
|
+
const expectedProjectId = this.options.cloud?.config?.projectId;
|
|
254
|
+
if (!expectedProjectId) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
let emulatorProjectId;
|
|
259
|
+
|
|
260
|
+
// Try the Firebase Emulator Hub first (version-independent, always correct)
|
|
261
|
+
try {
|
|
262
|
+
const http = require('http');
|
|
263
|
+
const body = await new Promise((resolve, reject) => {
|
|
264
|
+
const req = http.get('http://localhost:4400/emulators', (res) => {
|
|
265
|
+
let data = '';
|
|
266
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
267
|
+
res.on('end', () => resolve(data));
|
|
268
|
+
});
|
|
269
|
+
req.on('error', reject);
|
|
270
|
+
req.setTimeout(3000, () => { req.destroy(); reject(new Error('timeout')); });
|
|
271
|
+
});
|
|
272
|
+
emulatorProjectId = JSON.parse(body).projectId;
|
|
273
|
+
} catch (e) {
|
|
274
|
+
// Hub unreachable — fall back to health endpoint
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Fall back to the health endpoint's projectId (@omega.js/backend 5.3.3+)
|
|
278
|
+
if (!emulatorProjectId) {
|
|
279
|
+
emulatorProjectId = healthData?.projectId;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (emulatorProjectId && emulatorProjectId !== expectedProjectId) {
|
|
283
|
+
console.log(chalk.red(`\n ✗ Project mismatch: the running emulator belongs to "${emulatorProjectId}" but this project is "${expectedProjectId}".`));
|
|
284
|
+
console.log(chalk.red(` Stop the other emulator first, then run: npx omega emulator`));
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Setup test accounts - delegates to the shared seed module, then initializes
|
|
293
|
+
* the rules-testing context (test-runner-specific, not needed for standalone seeding).
|
|
294
|
+
*/
|
|
295
|
+
async setupAccounts() {
|
|
296
|
+
const result = await seed({
|
|
297
|
+
admin: this.options.admin,
|
|
298
|
+
domain: this.options.domain,
|
|
299
|
+
config: this.config,
|
|
300
|
+
projectDir: this.options.projectDir,
|
|
301
|
+
Manager: this.config.Manager,
|
|
302
|
+
ctx: this.config.ctx,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
if (!result.accounts) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.accounts = result.accounts;
|
|
310
|
+
|
|
311
|
+
// Initialize rules testing context for security rules tests
|
|
312
|
+
process.stdout.write(chalk.gray(' Initializing rules testing context... '));
|
|
313
|
+
try {
|
|
314
|
+
this.rulesContext = await rulesClient.createRulesContext({
|
|
315
|
+
projectId: this.options.cloud?.config?.projectId,
|
|
316
|
+
rulesPath: this.options.rulesPath,
|
|
317
|
+
port: this.options.emulatorPorts?.firestore,
|
|
318
|
+
accounts: this.accounts,
|
|
319
|
+
});
|
|
320
|
+
console.log(chalk.green('✓'));
|
|
321
|
+
} catch (error) {
|
|
322
|
+
console.log(chalk.red(`✗ (${error.message})`));
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Run all tests in a directory
|
|
331
|
+
*/
|
|
332
|
+
async runTestsInDir(dir, source) {
|
|
333
|
+
const testFiles = this.discoverTests(dir);
|
|
334
|
+
const filteredTests = this.filterTests(testFiles, source);
|
|
335
|
+
|
|
336
|
+
for (const testFile of filteredTests) {
|
|
337
|
+
await this.runTestFile(testFile, source);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Discover test files in directory
|
|
343
|
+
*/
|
|
344
|
+
discoverTests(dir) {
|
|
345
|
+
const tests = [];
|
|
346
|
+
const items = jetpack.list(dir) || [];
|
|
347
|
+
|
|
348
|
+
for (const item of items) {
|
|
349
|
+
// Skip _-prefixed files and directories (fixtures, helpers, internal data).
|
|
350
|
+
// Matches EM/BXM/UJM convention — `test/_fixtures/`, `test/_helpers/`, etc.
|
|
351
|
+
if (item.startsWith('_')) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Skip the boot/ smoke layer except during framework self-test. It targets
|
|
356
|
+
// the bundled fixture project and would be redundant noise in a real
|
|
357
|
+
// consumer's run (mirrors EM/BXM/UJM excluding boot/** for consumers).
|
|
358
|
+
if (item === 'boot' && !this.options.isFrameworkSelfTest) {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// An opt-in lane's suites are named for the lane and are UNREACHABLE by
|
|
363
|
+
// any run that did not ask for it: they need credentials and the network,
|
|
364
|
+
// and the `--lane=` gate is the only thing that sets this
|
|
365
|
+
// ([#212](https://github.com/Omega-JS-Stack/omega/issues/212)). A path
|
|
366
|
+
// filter naming the directory does not open it — only the gate does.
|
|
367
|
+
if (LANE_DIRECTORIES.has(item) && process.env.OMEGA_TEST_LANE !== item) {
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const fullPath = path.join(dir, item);
|
|
372
|
+
const stat = jetpack.inspect(fullPath);
|
|
373
|
+
|
|
374
|
+
if (stat.type === 'dir') {
|
|
375
|
+
tests.push(...this.discoverTests(fullPath));
|
|
376
|
+
} else if (stat.type === 'file' && item.endsWith('.test.js')) {
|
|
377
|
+
tests.push(fullPath);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return tests;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* How many test files this run's scope selects, across both sources: the
|
|
386
|
+
* count a named target has to beat to be a real selection rather than a typo
|
|
387
|
+
* ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)).
|
|
388
|
+
*
|
|
389
|
+
* @param {string} frameworkTestsDir - @omega.js/backend's own test/ dir
|
|
390
|
+
* @param {string} projectTestsDir - the consumer project's test/ dir
|
|
391
|
+
* @returns {number} Files the run would load
|
|
392
|
+
*/
|
|
393
|
+
countSelected(frameworkTestsDir, projectTestsDir) {
|
|
394
|
+
let count = 0;
|
|
395
|
+
|
|
396
|
+
if (this.scope.sources.includes('framework') && jetpack.exists(frameworkTestsDir)) {
|
|
397
|
+
count += this.filterTests(this.discoverTests(frameworkTestsDir), 'backend').length;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (this.scope.sources.includes('project') && jetpack.exists(projectTestsDir)) {
|
|
401
|
+
count += this.filterTests(this.discoverTests(projectTestsDir), 'project').length;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return count;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Filter tests for a source using the C5 scope's prefix-stripped paths
|
|
409
|
+
* (source selection already happened in run() via parseTestScope — this
|
|
410
|
+
* only path-matches within the source's own tree).
|
|
411
|
+
*/
|
|
412
|
+
filterTests(testFiles, source) {
|
|
413
|
+
const filters = this.scope.filters[source === 'backend' ? 'framework' : 'project'];
|
|
414
|
+
if (filters.length === 0) {
|
|
415
|
+
return testFiles;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return testFiles.filter((testFile) => {
|
|
419
|
+
const relativePath = this.getRelativeTestPath(testFile, source);
|
|
420
|
+
return filters.some((filterPath) => relativePath.startsWith(filterPath)
|
|
421
|
+
|| relativePath === `${filterPath.replace(/(\.test)?\.js$/, '')}.test.js`);
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Get relative test path for display
|
|
427
|
+
*/
|
|
428
|
+
getRelativeTestPath(testFile, source) {
|
|
429
|
+
if (source === 'backend') {
|
|
430
|
+
return path.relative(path.resolve(__dirname, '../../test'), testFile);
|
|
431
|
+
}
|
|
432
|
+
return path.relative(path.join(this.options.projectDir, 'test'), testFile);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Run a test file (handles both standalone tests and suites)
|
|
437
|
+
*/
|
|
438
|
+
async runTestFile(testFile, source) {
|
|
439
|
+
const relativePath = this.getRelativeTestPath(testFile, source);
|
|
440
|
+
let testModule;
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
const searchPaths = [
|
|
444
|
+
// The target root + its install — deps live on the ONE target manifest
|
|
445
|
+
// (src/dist pillar); dist/node_modules covers legacy installs
|
|
446
|
+
this.options.projectDir,
|
|
447
|
+
path.join(this.options.projectDir, 'node_modules'),
|
|
448
|
+
path.join(this.options.projectDir, 'dist', 'node_modules'),
|
|
449
|
+
path.resolve(__dirname, '../../'),
|
|
450
|
+
];
|
|
451
|
+
const origResolve = Module._resolveFilename.bind(Module);
|
|
452
|
+
Module._resolveFilename = function (request, parent, isMain, options) {
|
|
453
|
+
// Try normal resolution first (preserves nested node_modules traversal)
|
|
454
|
+
try {
|
|
455
|
+
return origResolve(request, parent, isMain, options);
|
|
456
|
+
} catch (err) {
|
|
457
|
+
// Fallback: try resolving from project's search paths
|
|
458
|
+
if (!request.startsWith('.') && !path.isAbsolute(request)) {
|
|
459
|
+
const extra = (options && options.paths) ? options.paths : [];
|
|
460
|
+
return origResolve(request, parent, isMain, {
|
|
461
|
+
...options,
|
|
462
|
+
paths: [...extra, ...searchPaths],
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
throw err;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
try {
|
|
469
|
+
testModule = require(testFile);
|
|
470
|
+
} finally {
|
|
471
|
+
Module._resolveFilename = origResolve;
|
|
472
|
+
}
|
|
473
|
+
} catch (error) {
|
|
474
|
+
console.log(chalk.red(` ✗ ${relativePath}`));
|
|
475
|
+
console.log(chalk.red(` Failed to load: ${error.message}`));
|
|
476
|
+
this.results.failed++;
|
|
477
|
+
this.results.tests.push({
|
|
478
|
+
path: relativePath,
|
|
479
|
+
passed: false,
|
|
480
|
+
error: `Failed to load: ${error.message}`,
|
|
481
|
+
});
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Check if entire file should be skipped
|
|
486
|
+
if (testModule.skip) {
|
|
487
|
+
const skipReason = typeof testModule.skip === 'string' ? testModule.skip : '';
|
|
488
|
+
const description = testModule.description || relativePath;
|
|
489
|
+
console.log(chalk.yellow(` ○ ${description}`) + chalk.gray(` (skipped${skipReason ? `: ${skipReason}` : ''})`));
|
|
490
|
+
|
|
491
|
+
this.results.skipped++;
|
|
492
|
+
this.results.tests.push({
|
|
493
|
+
path: relativePath,
|
|
494
|
+
description,
|
|
495
|
+
skipped: true,
|
|
496
|
+
skipReason,
|
|
497
|
+
});
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Check if this is a suite/group (has tests array) or standalone test
|
|
502
|
+
if (testModule.type === 'suite' || testModule.type === 'group' || Array.isArray(testModule.tests)) {
|
|
503
|
+
await this.runSuite(testModule, relativePath);
|
|
504
|
+
} else if (Array.isArray(testModule)) {
|
|
505
|
+
// Plain array treated as a group (independent tests)
|
|
506
|
+
await this.runSuite({ type: 'group', tests: testModule }, relativePath);
|
|
507
|
+
} else {
|
|
508
|
+
await this.runStandaloneTest(testModule, relativePath);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Run a test suite with sequential tests and shared state
|
|
514
|
+
*/
|
|
515
|
+
async runSuite(suite, relativePath) {
|
|
516
|
+
const suiteDescription = suite.description || relativePath;
|
|
517
|
+
const suiteTimeout = suite.timeout || this.options.timeout;
|
|
518
|
+
const tests = suite.tests || [];
|
|
519
|
+
|
|
520
|
+
console.log(chalk.cyan(` ⤷ ${suiteDescription}`));
|
|
521
|
+
|
|
522
|
+
// Shared state across all tests in the suite
|
|
523
|
+
const state = {};
|
|
524
|
+
|
|
525
|
+
for (let i = 0; i < tests.length; i++) {
|
|
526
|
+
const test = tests[i];
|
|
527
|
+
const testName = test.name || `step-${i + 1}`;
|
|
528
|
+
const testTimeout = test.timeout || suiteTimeout;
|
|
529
|
+
const auth = test.auth || suite.auth || 'none';
|
|
530
|
+
|
|
531
|
+
// Check if test should be skipped
|
|
532
|
+
if (test.skip) {
|
|
533
|
+
const skipReason = typeof test.skip === 'string' ? test.skip : '';
|
|
534
|
+
console.log(chalk.yellow(` ○ ${testName}`) + chalk.gray(` (skipped${skipReason ? `: ${skipReason}` : ''})`));
|
|
535
|
+
|
|
536
|
+
this.results.skipped++;
|
|
537
|
+
this.results.tests.push({
|
|
538
|
+
path: `${relativePath}:${testName}`,
|
|
539
|
+
description: testName,
|
|
540
|
+
skipped: true,
|
|
541
|
+
skipReason,
|
|
542
|
+
suite: suiteDescription,
|
|
543
|
+
});
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Create context with shared state
|
|
548
|
+
const context = this.createContext(auth, state);
|
|
549
|
+
|
|
550
|
+
const startTime = Date.now();
|
|
551
|
+
|
|
552
|
+
try {
|
|
553
|
+
await Promise.race([
|
|
554
|
+
test.run(context),
|
|
555
|
+
new Promise((_, reject) =>
|
|
556
|
+
setTimeout(() => reject(new Error('Test timeout')), testTimeout)
|
|
557
|
+
),
|
|
558
|
+
]);
|
|
559
|
+
|
|
560
|
+
const duration = Date.now() - startTime;
|
|
561
|
+
console.log(chalk.green(` ✓ ${testName}`) + chalk.gray(` (${duration}ms)`));
|
|
562
|
+
|
|
563
|
+
this.results.passed++;
|
|
564
|
+
this.results.tests.push({
|
|
565
|
+
path: `${relativePath}:${testName}`,
|
|
566
|
+
description: testName,
|
|
567
|
+
passed: true,
|
|
568
|
+
duration,
|
|
569
|
+
suite: suiteDescription,
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Run cleanup if defined
|
|
573
|
+
if (test.cleanup) {
|
|
574
|
+
try {
|
|
575
|
+
await test.cleanup(context);
|
|
576
|
+
} catch (cleanupError) {
|
|
577
|
+
console.log(chalk.yellow(` ⚠ Cleanup failed: ${cleanupError.message}`));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} catch (error) {
|
|
581
|
+
const duration = Date.now() - startTime;
|
|
582
|
+
|
|
583
|
+
// Check for runtime skip (test called skip())
|
|
584
|
+
if (error.name === 'SkipError') {
|
|
585
|
+
const skipReason = error.message;
|
|
586
|
+
console.log(chalk.yellow(` ○ ${testName}`) + chalk.gray(` (skipped: ${skipReason})`));
|
|
587
|
+
|
|
588
|
+
this.results.skipped++;
|
|
589
|
+
this.results.tests.push({
|
|
590
|
+
path: `${relativePath}:${testName}`,
|
|
591
|
+
description: testName,
|
|
592
|
+
skipped: true,
|
|
593
|
+
skipReason,
|
|
594
|
+
duration,
|
|
595
|
+
suite: suiteDescription,
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// For suites (sequential, state-dependent tests), a skip on any step means
|
|
599
|
+
// subsequent steps can't run cleanly — propagate skip to the rest of the suite.
|
|
600
|
+
// Groups (independent tests) continue normally.
|
|
601
|
+
const shouldStopOnSkip = suite.type !== 'group' && suite.stopOnFailure !== false;
|
|
602
|
+
if (shouldStopOnSkip) {
|
|
603
|
+
const remaining = tests.length - i - 1;
|
|
604
|
+
if (remaining > 0) {
|
|
605
|
+
console.log(chalk.yellow(` Skipping ${remaining} remaining test(s) in suite (suite-level skip)`));
|
|
606
|
+
this.results.skipped += remaining;
|
|
607
|
+
}
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
console.log(chalk.red(` ✗ ${testName}`) + chalk.gray(` (${duration}ms)`));
|
|
615
|
+
console.log(chalk.red(` ${error.message}`));
|
|
616
|
+
|
|
617
|
+
this.results.failed++;
|
|
618
|
+
this.results.tests.push({
|
|
619
|
+
path: `${relativePath}:${testName}`,
|
|
620
|
+
description: testName,
|
|
621
|
+
passed: false,
|
|
622
|
+
duration,
|
|
623
|
+
error: error.message,
|
|
624
|
+
suite: suiteDescription,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// Stop the suite on first failure (sequential tests depend on each other)
|
|
628
|
+
// Groups (type: 'group') continue running all tests regardless of failures
|
|
629
|
+
const shouldStopOnFailure = suite.type !== 'group' && suite.stopOnFailure !== false;
|
|
630
|
+
if (shouldStopOnFailure) {
|
|
631
|
+
const remaining = tests.length - i - 1;
|
|
632
|
+
if (remaining > 0) {
|
|
633
|
+
console.log(chalk.yellow(` Skipping ${remaining} remaining test(s) in suite`));
|
|
634
|
+
this.results.skipped += remaining;
|
|
635
|
+
}
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Run suite-level cleanup
|
|
642
|
+
if (suite.cleanup) {
|
|
643
|
+
try {
|
|
644
|
+
const context = this.createContext('admin', state);
|
|
645
|
+
await suite.cleanup(context);
|
|
646
|
+
} catch (cleanupError) {
|
|
647
|
+
console.log(chalk.yellow(` ⚠ Suite cleanup failed: ${cleanupError.message}`));
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Run a standalone test
|
|
654
|
+
*/
|
|
655
|
+
async runStandaloneTest(testModule, relativePath) {
|
|
656
|
+
const description = testModule.description || relativePath;
|
|
657
|
+
const timeout = testModule.timeout || this.options.timeout;
|
|
658
|
+
const auth = testModule.auth || testModule.authLevel || 'none';
|
|
659
|
+
|
|
660
|
+
// Create context (no shared state for standalone tests)
|
|
661
|
+
const context = this.createContext(auth);
|
|
662
|
+
|
|
663
|
+
const startTime = Date.now();
|
|
664
|
+
|
|
665
|
+
try {
|
|
666
|
+
await Promise.race([
|
|
667
|
+
testModule.run(context),
|
|
668
|
+
new Promise((_, reject) =>
|
|
669
|
+
setTimeout(() => reject(new Error('Test timeout')), timeout)
|
|
670
|
+
),
|
|
671
|
+
]);
|
|
672
|
+
|
|
673
|
+
const duration = Date.now() - startTime;
|
|
674
|
+
console.log(chalk.green(` ✓ ${description}`) + chalk.gray(` (${duration}ms)`));
|
|
675
|
+
|
|
676
|
+
this.results.passed++;
|
|
677
|
+
this.results.tests.push({
|
|
678
|
+
path: relativePath,
|
|
679
|
+
description,
|
|
680
|
+
passed: true,
|
|
681
|
+
duration,
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
// Run cleanup if defined
|
|
685
|
+
if (testModule.cleanup) {
|
|
686
|
+
try {
|
|
687
|
+
await testModule.cleanup(context);
|
|
688
|
+
} catch (cleanupError) {
|
|
689
|
+
console.log(chalk.yellow(` ⚠ Cleanup failed: ${cleanupError.message}`));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
} catch (error) {
|
|
693
|
+
const duration = Date.now() - startTime;
|
|
694
|
+
|
|
695
|
+
// Check for runtime skip (test called skip())
|
|
696
|
+
if (error.name === 'SkipError') {
|
|
697
|
+
const skipReason = error.message;
|
|
698
|
+
console.log(chalk.yellow(` ○ ${description}`) + chalk.gray(` (skipped: ${skipReason})`));
|
|
699
|
+
|
|
700
|
+
this.results.skipped++;
|
|
701
|
+
this.results.tests.push({
|
|
702
|
+
path: relativePath,
|
|
703
|
+
description,
|
|
704
|
+
skipped: true,
|
|
705
|
+
skipReason,
|
|
706
|
+
duration,
|
|
707
|
+
});
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
console.log(chalk.red(` ✗ ${description}`) + chalk.gray(` (${duration}ms)`));
|
|
712
|
+
console.log(chalk.red(` ${error.message}`));
|
|
713
|
+
|
|
714
|
+
this.results.failed++;
|
|
715
|
+
this.results.tests.push({
|
|
716
|
+
path: relativePath,
|
|
717
|
+
description,
|
|
718
|
+
passed: false,
|
|
719
|
+
duration,
|
|
720
|
+
error: error.message,
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Create test context with all utilities
|
|
727
|
+
* @param {string} auth - Default auth level: 'admin', 'basic', 'premium-active', 'premium-expired', 'none'
|
|
728
|
+
* @param {object} state - Shared state object (for suites)
|
|
729
|
+
*/
|
|
730
|
+
createContext(auth, state) {
|
|
731
|
+
// Create HTTP client with accounts for as() method
|
|
732
|
+
// Use hosting URL for all requests (rewrites to omega_api function)
|
|
733
|
+
const http = new HttpClient({
|
|
734
|
+
apiUrl: this.options.apiUrl,
|
|
735
|
+
timeout: this.options.timeout,
|
|
736
|
+
accounts: this.accounts,
|
|
737
|
+
adminKey: this.options.adminKey,
|
|
738
|
+
webhookKey: this.options.webhookKey,
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
// Set default auth
|
|
742
|
+
if (auth === 'admin') {
|
|
743
|
+
http.setAuth('adminKey', { key: this.options.adminKey });
|
|
744
|
+
} else if (auth === 'none') {
|
|
745
|
+
http.setAuth('none');
|
|
746
|
+
} else if (auth === 'user') {
|
|
747
|
+
// Alias for basic
|
|
748
|
+
if (this.accounts?.basic?.privateKey) {
|
|
749
|
+
http.setAuth('privateKey', { privateKey: this.accounts.basic.privateKey });
|
|
750
|
+
}
|
|
751
|
+
} else if (this.accounts?.[auth]?.privateKey) {
|
|
752
|
+
// Dynamic lookup — any account type with a privateKey
|
|
753
|
+
http.setAuth('privateKey', { privateKey: this.accounts[auth].privateKey });
|
|
754
|
+
} else {
|
|
755
|
+
http.setAuth('none');
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Create firestore helper (only if admin SDK available)
|
|
759
|
+
const firestore = this.options.admin
|
|
760
|
+
? this.createFirestoreHelper()
|
|
761
|
+
: null;
|
|
762
|
+
|
|
763
|
+
// Create waitFor helper
|
|
764
|
+
const waitFor = this.createWaitFor();
|
|
765
|
+
|
|
766
|
+
// Create pubsub helper
|
|
767
|
+
const pubsub = this.createPubSubHelper();
|
|
768
|
+
|
|
769
|
+
// Skip function for runtime skipping
|
|
770
|
+
const skip = (reason) => {
|
|
771
|
+
throw new SkipError(reason);
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
// Precomputed product metadata for payment tests — SSOT for all product-aware tests.
|
|
775
|
+
// Each product gets: stripeProductId, frequency, interval, price resolved from config.
|
|
776
|
+
// Tests use payments.products[id].* instead of recomputing per-test.
|
|
777
|
+
const FREQ_TO_INTERVAL = { daily: 'day', weekly: 'week', monthly: 'month', annually: 'year' };
|
|
778
|
+
const products = this.config.payment?.products || [];
|
|
779
|
+
const stripeProductIds = Object.fromEntries(
|
|
780
|
+
products.map((p) => [p.id, p.stripe?.productId || `_test_${p.id}`])
|
|
781
|
+
);
|
|
782
|
+
const productMeta = Object.fromEntries(
|
|
783
|
+
products.map((p) => {
|
|
784
|
+
const freq = p.prices ? Object.keys(p.prices)[0] : null;
|
|
785
|
+
return [p.id, {
|
|
786
|
+
id: p.id,
|
|
787
|
+
name: p.name,
|
|
788
|
+
type: p.type,
|
|
789
|
+
stripeProductId: p.stripe?.productId || `_test_${p.id}`,
|
|
790
|
+
frequency: freq,
|
|
791
|
+
interval: FREQ_TO_INTERVAL[freq] || null,
|
|
792
|
+
price: freq ? p.prices[freq] : 0,
|
|
793
|
+
trial: p.trial || null,
|
|
794
|
+
}];
|
|
795
|
+
})
|
|
796
|
+
);
|
|
797
|
+
|
|
798
|
+
return {
|
|
799
|
+
http,
|
|
800
|
+
accounts: this.accounts,
|
|
801
|
+
assert: assertions,
|
|
802
|
+
state: state || {},
|
|
803
|
+
firestore,
|
|
804
|
+
waitFor,
|
|
805
|
+
pubsub,
|
|
806
|
+
skip,
|
|
807
|
+
admin: this.config.admin,
|
|
808
|
+
// Real @omega.js/backend Manager + ctx, booted by run-tests.js with OMEGA_TEST_RUNNER=1.
|
|
809
|
+
// Tests can call Manager.AI(), Manager.Email(), Manager.User(), etc. exactly
|
|
810
|
+
// like production code — no stubs.
|
|
811
|
+
Manager: this.config.Manager,
|
|
812
|
+
ctx: this.config.ctx,
|
|
813
|
+
rules: this.rulesContext,
|
|
814
|
+
config: this.config,
|
|
815
|
+
payments: { stripeProductIds, products: productMeta },
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Create Firestore helper for direct database access
|
|
821
|
+
*/
|
|
822
|
+
createFirestoreHelper() {
|
|
823
|
+
const admin = this.options.admin;
|
|
824
|
+
const db = admin.firestore();
|
|
825
|
+
|
|
826
|
+
return {
|
|
827
|
+
/**
|
|
828
|
+
* Get a document
|
|
829
|
+
* @param {string} docPath - Document path (e.g., 'users/abc123')
|
|
830
|
+
* @returns {Promise<object|null>} Document data or null
|
|
831
|
+
*/
|
|
832
|
+
async get(docPath) {
|
|
833
|
+
const doc = await db.doc(docPath).get();
|
|
834
|
+
return doc.exists ? doc.data() : null;
|
|
835
|
+
},
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Check if a document exists
|
|
839
|
+
* @param {string} docPath - Document path
|
|
840
|
+
* @returns {Promise<boolean>}
|
|
841
|
+
*/
|
|
842
|
+
async exists(docPath) {
|
|
843
|
+
const doc = await db.doc(docPath).get();
|
|
844
|
+
return doc.exists;
|
|
845
|
+
},
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Set a document
|
|
849
|
+
* @param {string} docPath - Document path
|
|
850
|
+
* @param {object} data - Data to set
|
|
851
|
+
* @param {object} options - Firestore set options
|
|
852
|
+
*/
|
|
853
|
+
async set(docPath, data, options) {
|
|
854
|
+
await db.doc(docPath).set(data, options || {});
|
|
855
|
+
},
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Delete a document
|
|
859
|
+
* @param {string} docPath - Document path
|
|
860
|
+
*/
|
|
861
|
+
async delete(docPath) {
|
|
862
|
+
await db.doc(docPath).delete();
|
|
863
|
+
},
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Query a collection
|
|
867
|
+
* @param {string} collectionPath - Collection path
|
|
868
|
+
* @returns {object} Firestore collection reference
|
|
869
|
+
*/
|
|
870
|
+
collection(collectionPath) {
|
|
871
|
+
return db.collection(collectionPath);
|
|
872
|
+
},
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Create waitFor helper for polling conditions
|
|
878
|
+
*/
|
|
879
|
+
createWaitFor() {
|
|
880
|
+
/**
|
|
881
|
+
* Wait for a condition to be true
|
|
882
|
+
* @param {Function} condition - Async function that returns truthy when ready
|
|
883
|
+
* @param {number} timeoutMs - Maximum time to wait (default 5000)
|
|
884
|
+
* @param {number} intervalMs - Polling interval (default 100)
|
|
885
|
+
* @returns {Promise<*>} The truthy value returned by condition
|
|
886
|
+
*/
|
|
887
|
+
return async function waitFor(condition, timeoutMs, intervalMs) {
|
|
888
|
+
timeoutMs = timeoutMs || 5000;
|
|
889
|
+
intervalMs = intervalMs || 100;
|
|
890
|
+
|
|
891
|
+
const startTime = Date.now();
|
|
892
|
+
|
|
893
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
894
|
+
try {
|
|
895
|
+
const result = await condition();
|
|
896
|
+
if (result) {
|
|
897
|
+
return result;
|
|
898
|
+
}
|
|
899
|
+
} catch (error) {
|
|
900
|
+
// Condition threw - keep polling
|
|
901
|
+
}
|
|
902
|
+
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
throw new Error(`waitFor timed out after ${timeoutMs}ms`);
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Create PubSub helper for triggering scheduled functions
|
|
911
|
+
*/
|
|
912
|
+
createPubSubHelper() {
|
|
913
|
+
const config = this.config;
|
|
914
|
+
|
|
915
|
+
// The port the RUNNING emulator resolved, never the classic 8085. Anything
|
|
916
|
+
// else on the machine holding 8085 bumps this stack's Pub/Sub emulator off
|
|
917
|
+
// it (N7), and a hardcoded endpoint then published into whatever owns that
|
|
918
|
+
// port instead: the scheduled function never fired HERE, so every
|
|
919
|
+
// cron-driven test sat out its full waitFor deadline with no error to name
|
|
920
|
+
// ([#404](https://github.com/Omega-JS-Stack/omega/issues/404)).
|
|
921
|
+
const pubsubPort = this.options.emulatorPorts?.pubsub;
|
|
922
|
+
|
|
923
|
+
return {
|
|
924
|
+
/**
|
|
925
|
+
* Trigger a Firebase scheduled function via PubSub
|
|
926
|
+
* @param {string} functionName - The function name (e.g., 'omega_cronDaily')
|
|
927
|
+
* @returns {Promise<string>} The message ID
|
|
928
|
+
*/
|
|
929
|
+
async trigger(functionName) {
|
|
930
|
+
if (!pubsubPort) {
|
|
931
|
+
throw new Error(`Cannot trigger ${functionName}: the test config carries no resolved Pub/Sub port (emulatorPorts.pubsub)`);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const { PubSub } = require('@google-cloud/pubsub');
|
|
935
|
+
const pubsub = new PubSub({
|
|
936
|
+
projectId: config.cloud?.config?.projectId,
|
|
937
|
+
apiEndpoint: `127.0.0.1:${pubsubPort}`,
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
const topicName = `firebase-schedule-${functionName}`;
|
|
941
|
+
|
|
942
|
+
// Get or create the topic (emulator may not have it yet)
|
|
943
|
+
let topic = pubsub.topic(topicName);
|
|
944
|
+
const [exists] = await topic.exists();
|
|
945
|
+
|
|
946
|
+
if (!exists) {
|
|
947
|
+
[topic] = await pubsub.createTopic(topicName);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
const messageId = await topic.publishMessage({ json: {} });
|
|
951
|
+
return messageId;
|
|
952
|
+
},
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Report final results
|
|
958
|
+
*/
|
|
959
|
+
reportResults() {
|
|
960
|
+
const total = this.results.passed + this.results.failed + this.results.skipped;
|
|
961
|
+
const duration = Date.now() - this.results.startTime;
|
|
962
|
+
|
|
963
|
+
console.log(`\n ${chalk.bold('Results')}`);
|
|
964
|
+
console.log(` ${chalk.green(`${this.results.passed} passing`)}`);
|
|
965
|
+
|
|
966
|
+
if (this.results.failed > 0) {
|
|
967
|
+
console.log(` ${chalk.red(`${this.results.failed} failing`)}`);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (this.results.skipped > 0) {
|
|
971
|
+
console.log(` ${chalk.yellow(`${this.results.skipped} skipped`)}`);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
console.log(chalk.gray(`\n Total: ${total} tests in ${duration}ms\n`));
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// The lane list rides alongside the runner: a lane whose directory name drifted
|
|
979
|
+
// from its `--lane=` name would be silently unreachable, or worse, silently open.
|
|
980
|
+
TestRunner.LANE_DIRECTORIES = LANE_DIRECTORIES;
|
|
981
|
+
|
|
982
|
+
module.exports = TestRunner;
|