@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,1404 @@
|
|
|
1
|
+
// Libraries
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { get: _get, set: _set } = require('lodash');
|
|
4
|
+
const jetpack = require('fs-jetpack');
|
|
5
|
+
const { hasOmegaConfig, loadConfig, loadEnv, formatErrors, backendProjectType } = require('../vendor/config/index.js');
|
|
6
|
+
const { resolvedConfigValues } = require('./helpers/resolved-config.js');
|
|
7
|
+
const env = require('./libraries/env.js');
|
|
8
|
+
const EventEmitter = require('events');
|
|
9
|
+
// const EventEmitter = require('events').EventEmitter;
|
|
10
|
+
const util = require('util');
|
|
11
|
+
|
|
12
|
+
// const { debug, log, error, warn } = require('firebase-functions/lib/logger');
|
|
13
|
+
// let User;
|
|
14
|
+
// let Analytics;
|
|
15
|
+
// Paths
|
|
16
|
+
const wrappers = './functions/wrappers';
|
|
17
|
+
const _legacy = './functions/_legacy';
|
|
18
|
+
const events = path.resolve(__dirname, './events');
|
|
19
|
+
const cron = path.resolve(events, './cron');
|
|
20
|
+
|
|
21
|
+
const BEM_TEMPLATES_DIR = path.resolve(__dirname, '../../templates');
|
|
22
|
+
const BEM_PACKAGE = require('../../package.json');
|
|
23
|
+
|
|
24
|
+
function Manager() {
|
|
25
|
+
const self = this;
|
|
26
|
+
|
|
27
|
+
// @omega.js/backend library version
|
|
28
|
+
self.version = BEM_PACKAGE.version;
|
|
29
|
+
|
|
30
|
+
// Constants
|
|
31
|
+
self.SERVER_UUID = '11111111-1111-1111-1111-111111111111';
|
|
32
|
+
|
|
33
|
+
// Modable
|
|
34
|
+
self.libraries = {};
|
|
35
|
+
self.handlers = {};
|
|
36
|
+
|
|
37
|
+
self._internal = {
|
|
38
|
+
storage: {},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
self.interface = {}
|
|
42
|
+
|
|
43
|
+
// Setup EventEmitter
|
|
44
|
+
EventEmitter.call(self);
|
|
45
|
+
|
|
46
|
+
// Return
|
|
47
|
+
return self;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Inherit from EventEmitter
|
|
51
|
+
util.inherits(Manager, EventEmitter);
|
|
52
|
+
|
|
53
|
+
// Process-level latch for the TEST-environment banner. init() can run more than
|
|
54
|
+
// once in a single process (the test runner, a custom server, a re-entrant boot);
|
|
55
|
+
// the banner is boot information, not per-init information, so it says its piece
|
|
56
|
+
// once and then stays quiet.
|
|
57
|
+
let _testBannerLogged = false;
|
|
58
|
+
|
|
59
|
+
// The emulator boots a FRESH functions worker per invocation — measured on one
|
|
60
|
+
// playground seed: 53 worker processes for 92 invocations, so a once-per-process
|
|
61
|
+
// line still prints 53 times to announce what the emulator itself announced. The
|
|
62
|
+
// test-environment boot lines are therefore silent under the emulator. They stay
|
|
63
|
+
// LOUD (once) in a deployed process that resolves test mode, which is the case
|
|
64
|
+
// where "this is a test environment" is an alarm, not a truism.
|
|
65
|
+
function isUnderEmulator() {
|
|
66
|
+
return process.env.FUNCTIONS_EMULATOR === 'true';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Manager.prototype.init = function (exporter, options) {
|
|
70
|
+
const self = this;
|
|
71
|
+
|
|
72
|
+
// Auto-detect test-runner context. The test runner sets OMEGA_TEST_RUNNER=1
|
|
73
|
+
// before invoking anything that loads @omega.js/backend. When detected, init() runs the
|
|
74
|
+
// library-loading + project-config-setup pieces normally, but skips wiring
|
|
75
|
+
// Firebase Cloud Functions handlers and the custom-server boot (neither
|
|
76
|
+
// works outside an actual Functions runtime). The runner has already called
|
|
77
|
+
// firebase-admin.initializeApp() so we also skip that step to avoid the
|
|
78
|
+
// "default app already initialized" crash.
|
|
79
|
+
const isTestRunner = !!process.env.OMEGA_TEST_RUNNER;
|
|
80
|
+
|
|
81
|
+
// Set options defaults
|
|
82
|
+
options = options || {};
|
|
83
|
+
options.initialize = typeof options.initialize === 'undefined' ? !isTestRunner : options.initialize;
|
|
84
|
+
options.log = typeof options.log === 'undefined' ? false : options.log;
|
|
85
|
+
// projectType (firebase | custom) is resolved AFTER the config load below —
|
|
86
|
+
// the brand's own omega.json5 is its home (`targets.backend.projectType`,
|
|
87
|
+
// #584), so a custom backend needs no init flag a brand has to remember. An
|
|
88
|
+
// explicit option passed here still wins; until then it stays undefined.
|
|
89
|
+
options.routes = typeof options.routes === 'undefined' ? '/routes' : options.routes;
|
|
90
|
+
options.schemas = typeof options.schemas === 'undefined' ? '/schemas' : options.schemas;
|
|
91
|
+
options.setupFunctions = typeof options.setupFunctions === 'undefined' ? !isTestRunner : options.setupFunctions;
|
|
92
|
+
options.setupFunctionsLegacy = typeof options.setupFunctionsLegacy === 'undefined' ? false : options.setupFunctionsLegacy;
|
|
93
|
+
options.setupFunctionsIdentity = typeof options.setupFunctionsIdentity === 'undefined' ? !isTestRunner : options.setupFunctionsIdentity;
|
|
94
|
+
options.setupServer = typeof options.setupServer === 'undefined' ? !isTestRunner : options.setupServer;
|
|
95
|
+
options.initializeLocalStorage = typeof options.initializeLocalStorage === 'undefined' ? false : options.initializeLocalStorage;
|
|
96
|
+
options.resourceZone = typeof options.resourceZone === 'undefined' ? 'us-central1' : options.resourceZone;
|
|
97
|
+
options.sentry = typeof options.sentry === 'undefined' ? !isTestRunner : options.sentry;
|
|
98
|
+
options.reportErrorsInDev = typeof options.reportErrorsInDev === 'undefined' ? false : options.reportErrorsInDev;
|
|
99
|
+
options.firebaseConfig = options.firebaseConfig;
|
|
100
|
+
options.useFirebaseLogger = typeof options.useFirebaseLogger === 'undefined' ? true : options.useFirebaseLogger;
|
|
101
|
+
options.serviceAccountPath = typeof options.serviceAccountPath === 'undefined' ? 'service-account.json' : options.serviceAccountPath;;
|
|
102
|
+
options.fetchStats = typeof options.fetchStats === 'undefined'
|
|
103
|
+
// ? options.projectType === 'firebase'
|
|
104
|
+
? false
|
|
105
|
+
: options.fetchStats;
|
|
106
|
+
options.checkNodeVersion = typeof options.checkNodeVersion === 'undefined' ? true : options.checkNodeVersion;
|
|
107
|
+
options.uniqueAppName = options.uniqueAppName || undefined;
|
|
108
|
+
options.ctx = options.ctx || {};
|
|
109
|
+
options.cwd = typeof options.cwd === 'undefined' ? process.cwd() : options.cwd;
|
|
110
|
+
options.projectPackageDirectory = typeof options.projectPackageDirectory === 'undefined' ? undefined : options.projectPackageDirectory;
|
|
111
|
+
options.logSavePath = typeof options.logSavePath === 'undefined' ? false : options.logSavePath;
|
|
112
|
+
// options.ctx.optionsLogString = options.ctx.optionsLogString || undefined;
|
|
113
|
+
|
|
114
|
+
// Express options
|
|
115
|
+
options.express = options.express || {};
|
|
116
|
+
options.express.bodyParser = options.express.bodyParser || {};
|
|
117
|
+
options.express.bodyParser.json = options.express.bodyParser.json || { limit: '100kb' };
|
|
118
|
+
options.express.bodyParser.urlencoded = options.express.bodyParser.urlencoded || { limit: '100kb', extended: true };
|
|
119
|
+
|
|
120
|
+
// Load libraries
|
|
121
|
+
self.libraries = {
|
|
122
|
+
// Third-party
|
|
123
|
+
functions: null, // firebase-functions, loaded once projectType resolves (#584)
|
|
124
|
+
admin: require('firebase-admin'),
|
|
125
|
+
cors: require('cors')({ origin: true }),
|
|
126
|
+
sentry: null,
|
|
127
|
+
|
|
128
|
+
// First-party
|
|
129
|
+
RouteContext: require('./helpers/context/index.js'),
|
|
130
|
+
localDatabase: null,
|
|
131
|
+
User: null,
|
|
132
|
+
Analytics: null,
|
|
133
|
+
logger: null,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Set properties
|
|
137
|
+
self.cwd = options.cwd;
|
|
138
|
+
self.rootDirectory = __dirname;
|
|
139
|
+
|
|
140
|
+
// Set options
|
|
141
|
+
self.options = options;
|
|
142
|
+
self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG || '{}');
|
|
143
|
+
self.project.resourceZone = options.resourceZone;
|
|
144
|
+
self.project.serviceAccountPath = path.resolve(self.cwd, options.serviceAccountPath);
|
|
145
|
+
|
|
146
|
+
// Load package.json
|
|
147
|
+
self.package = resolveProjectPackage(options.projectPackageDirectory || self.cwd);
|
|
148
|
+
|
|
149
|
+
// Resolve the .env cascade from the functions dir (functions/.env rides
|
|
150
|
+
// the deploy artifact; the brand/company layers exist only in local dev)
|
|
151
|
+
try {
|
|
152
|
+
loadEnv(self.cwd);
|
|
153
|
+
} catch (e) {
|
|
154
|
+
self.ctx.error(new Error(`Failed to set up environment variables from .env file: ${e.message}`));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Load config — the consumer's config/omega.json5 resolved through
|
|
158
|
+
// @omega.js/config (brand-monorepo aware: cwd is the functions dir, the
|
|
159
|
+
// loader walks up to the brand layer when one exists). The framework
|
|
160
|
+
// defaults layer is templates/config/omega.json5 resolved through the SAME
|
|
161
|
+
// loader, so both sides live in one shape. Missing consumer config
|
|
162
|
+
// (non-consumer cwd, some tests) → defaults only, same as before the flip.
|
|
163
|
+
const configDefaults = loadConfig(BEM_TEMPLATES_DIR, 'backend').config;
|
|
164
|
+
delete configDefaults.targets;
|
|
165
|
+
|
|
166
|
+
// A consumer omega.json5 is what makes this process a BRAND's backend —
|
|
167
|
+
// the env guard below is advisory without one (framework fixture, #581)
|
|
168
|
+
const hasConsumerConfig = hasOmegaConfig(self.cwd);
|
|
169
|
+
|
|
170
|
+
if (hasConsumerConfig) {
|
|
171
|
+
const { config, errors } = loadConfig(self.cwd, 'backend', { defaults: configDefaults });
|
|
172
|
+
self.config = config;
|
|
173
|
+
|
|
174
|
+
// Boot warns on schema findings, audit (the target checks) throws — the two-mode
|
|
175
|
+
// contract from @omega.js/config. Secrets in the file already threw above.
|
|
176
|
+
if (errors.length) {
|
|
177
|
+
console.warn(`[@omega.js/backend] config/omega.json5 schema warnings:\n${formatErrors(errors)}`);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
self.config = configDefaults;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// How this backend RUNS (#584): Cloud Functions, or the same app listening
|
|
184
|
+
// on PORT for a container host. The brand's config is the switch —
|
|
185
|
+
// `targets.backend.projectType`, resolved onto the top level here — and an
|
|
186
|
+
// explicit init option still wins for a caller that means to override it.
|
|
187
|
+
// firebase-functions is loaded only for the mode that has functions.
|
|
188
|
+
options.projectType = options.projectType || backendProjectType(self.config);
|
|
189
|
+
self.libraries.functions = options.projectType === 'firebase' ? require('firebase-functions/v1') : null;
|
|
190
|
+
|
|
191
|
+
// Config-DERIVED values, on the config object consumer code already reads
|
|
192
|
+
// (#290): `config.resolved.github.repo` and whatever joins it. The recipes
|
|
193
|
+
// live in @omega.js/config — private, so a brand target cannot call them and
|
|
194
|
+
// used to re-implement them — and the framework runs them once, here, on the
|
|
195
|
+
// composed config.
|
|
196
|
+
self.config.resolved = resolvedConfigValues(self.config);
|
|
197
|
+
|
|
198
|
+
// Expose config on the constructor for static access by internal libraries.
|
|
199
|
+
// Since Node.js caches require(), any `require('./index.js')` returns this same
|
|
200
|
+
// Manager function with .config already set — no need for setConfig() patterns.
|
|
201
|
+
Manager.config = self.config;
|
|
202
|
+
|
|
203
|
+
// Set PAYPAL_CLIENT_ID from config (clientId is public, not a secret — lives in config, not .env)
|
|
204
|
+
process.env.PAYPAL_CLIENT_ID = process.env.PAYPAL_CLIENT_ID || self.config?.payment?.providers?.paypal?.clientId || '';
|
|
205
|
+
|
|
206
|
+
// Set CHARGEBEE_SITE from config (site is public, not a secret — lives in config, not .env)
|
|
207
|
+
process.env.CHARGEBEE_SITE = process.env.CHARGEBEE_SITE || self.config?.payment?.providers?.chargebee?.site || '';
|
|
208
|
+
|
|
209
|
+
// Get brand ID
|
|
210
|
+
const brandId = self.config?.brand?.id;
|
|
211
|
+
|
|
212
|
+
// Set log
|
|
213
|
+
if (options.logSavePath) {
|
|
214
|
+
self.libraries.logger = new (require('wonderful-log'))({
|
|
215
|
+
console: {
|
|
216
|
+
enabled: false,
|
|
217
|
+
},
|
|
218
|
+
file: {
|
|
219
|
+
enabled: true,
|
|
220
|
+
path: options.logSavePath,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Environment helpers — the Manager is the SINGLE SOURCE OF TRUTH (mirrors EM/UJM/BXM,
|
|
226
|
+
// where the Manager owns these). The resolution itself lives in the env reader
|
|
227
|
+
// (libraries/env.js, the ONLY place that reads the raw OMEGA_TEST_MODE /
|
|
228
|
+
// ENVIRONMENT / FUNCTIONS_EMULATOR / TERM_PROGRAM vars) because the provider
|
|
229
|
+
// libraries need the same answer with no Manager handle (#586's dev/live
|
|
230
|
+
// payment split); the three is*() checks derive from it live on every call.
|
|
231
|
+
// They return exactly ONE of three mutually-exclusive values — testing wins,
|
|
232
|
+
// then production, else development.
|
|
233
|
+
// The ctx exposes the same methods but FORWARDS to these (ctx.isTesting()
|
|
234
|
+
// → Manager.isTesting()), so request handlers can keep calling `ctx.*`.
|
|
235
|
+
// Defined BEFORE the ctx is constructed so the ctx's own init() can call back.
|
|
236
|
+
self.getEnvironment = function() {
|
|
237
|
+
return env.environment();
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// The three checks are mutually exclusive — each true for ONLY its own environment.
|
|
241
|
+
// isDevelopment() is NOT true in testing; isProduction() is a real positive check
|
|
242
|
+
// (never `!isDevelopment()`). Gate "anything non-production" with `!isProduction()`
|
|
243
|
+
// or `isDevelopment() || isTesting()` intentionally.
|
|
244
|
+
self.isDevelopment = function() {
|
|
245
|
+
return self.getEnvironment() === 'development';
|
|
246
|
+
};
|
|
247
|
+
self.isProduction = function() {
|
|
248
|
+
return self.getEnvironment() === 'production';
|
|
249
|
+
};
|
|
250
|
+
self.isTesting = function() {
|
|
251
|
+
return self.getEnvironment() === 'testing';
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// Boot guard for every REQUIRED env key (#581, superseding #569's
|
|
255
|
+
// production-only unsubscribe-key branch). A process without one serves
|
|
256
|
+
// every route fine and then crashes at the first customer action that needs
|
|
257
|
+
// it — a real customer's order email, in the case that started this — so a
|
|
258
|
+
// brand's backend refuses to boot instead, in every environment: the keys
|
|
259
|
+
// are one `npx omega manage` away, and a dev loop that boots without them
|
|
260
|
+
// only moves the crash downstream. The one advisory lane is a process with
|
|
261
|
+
// no consumer config at all (the framework's own fixture), which says the
|
|
262
|
+
// fault out loud and continues.
|
|
263
|
+
try {
|
|
264
|
+
env.assertRequired('backend');
|
|
265
|
+
} catch (e) {
|
|
266
|
+
if (!env.guardIsAdvisory({ hasConsumerConfig })) { throw e; }
|
|
267
|
+
console.warn(`[@omega.js/backend:index] ${e.message}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// The other half of the boot guard (#626): the keys this brand's OWN config
|
|
271
|
+
// made mandatory (the schema's `requiredWhen` rules — a configured GA4 stream
|
|
272
|
+
// with no Measurement Protocol secret, a reCAPTCHA site key with no secret
|
|
273
|
+
// half). A deployed backend REFUSES: those are the runs where the silence is
|
|
274
|
+
// a customer's. Every other environment says it once and continues, because
|
|
275
|
+
// a half-configured local loop is a normal step on the way to a full one.
|
|
276
|
+
try {
|
|
277
|
+
env.assertRules(self.config, 'backend');
|
|
278
|
+
} catch (e) {
|
|
279
|
+
if (env.environment() === 'production') { throw e; }
|
|
280
|
+
console.warn(`[@omega.js/backend:index] ${e.message}`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Init ctx
|
|
284
|
+
self.ctx = self.RouteContext().init({
|
|
285
|
+
req: null,
|
|
286
|
+
res: null,
|
|
287
|
+
admin: self.libraries.admin,
|
|
288
|
+
functions: self.libraries.functions,
|
|
289
|
+
Manager: self,
|
|
290
|
+
}, options.ctx);
|
|
291
|
+
|
|
292
|
+
// Helper functions for URLs based on environment
|
|
293
|
+
self.getFunctionsUrl = function(env) {
|
|
294
|
+
// Auto-detect (no explicit env): development OR testing → local URLs. Test runs
|
|
295
|
+
// hit the local emulator, so getApiUrl/getFunctionsUrl/getWebsiteUrl must resolve
|
|
296
|
+
// to localhost. NOTE: getParentApiUrl/getParentUrl are intentionally NOT changed —
|
|
297
|
+
// the parent is a real remote server with no localhost equivalent.
|
|
298
|
+
const isDev = env === 'development' || (!env && (self.isDevelopment() || self.isTesting()));
|
|
299
|
+
// N7: the CLI that booted the stack publishes resolved ports via
|
|
300
|
+
// OMEGA_*_PORT env (functions workers inherit them) — classic default
|
|
301
|
+
// when unset (plain local boot).
|
|
302
|
+
return isDev
|
|
303
|
+
? `http://localhost:${process.env.OMEGA_FUNCTIONS_PORT || 5001}/${self.project.projectId}/${self.project.resourceZone}`
|
|
304
|
+
: `https://${self.project.resourceZone}-${self.project.projectId}.cloudfunctions.net`;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
self.getApiUrl = function(env) {
|
|
308
|
+
// Auto-detect (no explicit env): development OR testing → local URLs. Test runs
|
|
309
|
+
// hit the local emulator, so getApiUrl/getFunctionsUrl/getWebsiteUrl must resolve
|
|
310
|
+
// to localhost. NOTE: getParentApiUrl/getParentUrl are intentionally NOT changed —
|
|
311
|
+
// the parent is a real remote server with no localhost equivalent.
|
|
312
|
+
const isDev = env === 'development' || (!env && (self.isDevelopment() || self.isTesting()));
|
|
313
|
+
if (isDev) {
|
|
314
|
+
const httpsPort = process.env.OMEGA_HTTPS_PORT;
|
|
315
|
+
return httpsPort
|
|
316
|
+
? `https://localhost:${httpsPort}`
|
|
317
|
+
: `http://localhost:${process.env.OMEGA_HOSTING_PORT || 5002}`;
|
|
318
|
+
}
|
|
319
|
+
return `https://api.${(self.config.brand?.url || '').replace(/^https?:\/\//, '')}`;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
self.getWebsiteUrl = function(env) {
|
|
323
|
+
// Auto-detect (no explicit env): development OR testing → local URLs. Test runs
|
|
324
|
+
// hit the local emulator, so getApiUrl/getFunctionsUrl/getWebsiteUrl must resolve
|
|
325
|
+
// to localhost. NOTE: getParentApiUrl/getParentUrl are intentionally NOT changed —
|
|
326
|
+
// the parent is a real remote server with no localhost equivalent.
|
|
327
|
+
const isDev = env === 'development' || (!env && (self.isDevelopment() || self.isTesting()));
|
|
328
|
+
// Scheme follows the local https stack (cp176): ONE mkcert install fronts
|
|
329
|
+
// backend AND web dev alike, so this process's own proxy presence
|
|
330
|
+
// (OMEGA_HTTPS_PORT) is the honest signal for the website's scheme too —
|
|
331
|
+
// --no-https / missing mkcert drops both sides back to plain http.
|
|
332
|
+
const websiteScheme = process.env.OMEGA_HTTPS_PORT ? 'https' : 'http';
|
|
333
|
+
return isDev
|
|
334
|
+
? `${websiteScheme}://localhost:${process.env.OMEGA_WEBSITE_PORT || 4000}`
|
|
335
|
+
: self.config.brand?.url || '';
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// Resolve the parent @omega.js/backend's website URL (the parent's brand domain, NO `api.` subdomain).
|
|
339
|
+
// - If config.parent === 'self', THIS @omega.js/backend is the parent — returns this brand's own URL.
|
|
340
|
+
// - If config.parent is a URL, returns it as-is.
|
|
341
|
+
// - Returns '' if neither is configured.
|
|
342
|
+
// Use getParentApiUrl() for the API URL (with `api.` subdomain inserted).
|
|
343
|
+
self.getParentUrl = function() {
|
|
344
|
+
const parent = self.config.parent;
|
|
345
|
+
if (parent === 'self') {
|
|
346
|
+
return self.config.brand?.url || '';
|
|
347
|
+
}
|
|
348
|
+
return parent || '';
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// Resolve the parent @omega.js/backend's API URL (`https://api.{parent-host}`).
|
|
352
|
+
// ALWAYS returns the live production URL — even when THIS brand is running
|
|
353
|
+
// in dev/test mode. The parent's API is a real remote server (no localhost
|
|
354
|
+
// equivalent), so dev-mode does NOT redirect to localhost the way getApiUrl()
|
|
355
|
+
// does. Use this when you need to call the parent's API from any environment.
|
|
356
|
+
self.getParentApiUrl = function() {
|
|
357
|
+
const base = self.getParentUrl().replace(/^https?:\/\//, '');
|
|
358
|
+
return base ? `https://api.${base}` : '';
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// Returns true when this @omega.js/backend IS the parent (config.parent === 'self').
|
|
362
|
+
// Gates parent-only routes like /marketing/webhook/forward.
|
|
363
|
+
self.isParent = function() {
|
|
364
|
+
return self.config.parent === 'self';
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
// Set more properties (need to wait for ctx to determine if DEV)
|
|
368
|
+
self.project.functionsUrl = self.getFunctionsUrl();
|
|
369
|
+
|
|
370
|
+
// Set API URL (like @omega.js/client's getApiUrl)
|
|
371
|
+
// Testing: http://localhost:5002 (hosting emulator with rewrites)
|
|
372
|
+
// Development: http://localhost:5002 (local hosting)
|
|
373
|
+
// Production: https://api.{domain}
|
|
374
|
+
self.project.apiUrl = self.getApiUrl();
|
|
375
|
+
|
|
376
|
+
// Set website URL
|
|
377
|
+
// Development: http://localhost:4000 (local `omega dev` hosting)
|
|
378
|
+
// Production: https://{domain} (from brand.url)
|
|
379
|
+
self.project.websiteUrl = self.getWebsiteUrl();
|
|
380
|
+
|
|
381
|
+
// Set environment
|
|
382
|
+
process.env.ENVIRONMENT = process.env.ENVIRONMENT || self.getEnvironment();
|
|
383
|
+
|
|
384
|
+
// Set @omega.js/backend env variables
|
|
385
|
+
process.env.OMEGA_FUNCTIONS_URL = self.project.functionsUrl;
|
|
386
|
+
process.env.OMEGA_API_URL = self.project.apiUrl;
|
|
387
|
+
process.env.OMEGA_WEBSITE_URL = self.project.websiteUrl;
|
|
388
|
+
|
|
389
|
+
// Use the working Firebase logger that they disabled for whatever reason
|
|
390
|
+
// Load the Firebase logger compat shim only in production (NOT development or testing).
|
|
391
|
+
if (
|
|
392
|
+
process.env.GCLOUD_PROJECT
|
|
393
|
+
&& self.isProduction()
|
|
394
|
+
&& options.useFirebaseLogger
|
|
395
|
+
) {
|
|
396
|
+
// require('firebase-functions/lib/logger/compat'); // Old way
|
|
397
|
+
require('firebase-functions/logger/compat'); // firebase-functions@4 and above?
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Handle test environment
|
|
401
|
+
if (self.isTesting()) {
|
|
402
|
+
if (!isUnderEmulator() && !_testBannerLogged) {
|
|
403
|
+
_testBannerLogged = true;
|
|
404
|
+
self.ctx.log('⚠️⚠️⚠️ Running in TEST environment, some features may be disabled ⚠️⚠️⚠️');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Install the test-mode-file watcher exactly once. Lets the test command
|
|
408
|
+
// flip env vars (currently just TEST_EXTENDED_MODE) on the running emulator
|
|
409
|
+
// mid-session without restarting it. See src/test/utils/test-mode-file.js
|
|
410
|
+
// for the file format and allowlist.
|
|
411
|
+
setupTestModeWatcher(self);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Handle dev environments
|
|
415
|
+
if (self.isDevelopment()) {
|
|
416
|
+
const version = require('wonderful-version');
|
|
417
|
+
const nodeUsing = version.major(process.versions.node);
|
|
418
|
+
const nodeRequired = version.major(self.package?.engines?.node || '0.0.0');
|
|
419
|
+
|
|
420
|
+
// Fix firebase-tools overwriting console.log
|
|
421
|
+
// https://stackoverflow.com/questions/56026747/firebase-console-log-on-localhost
|
|
422
|
+
if (process.env.GCLOUD_PROJECT) {
|
|
423
|
+
function logFix() {
|
|
424
|
+
console.error(...arguments);
|
|
425
|
+
}
|
|
426
|
+
console.log = logFix;
|
|
427
|
+
console.info = logFix;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Reject if we're using an unsupported Node.js version
|
|
431
|
+
if (version.is(nodeUsing, '<', nodeRequired)) {
|
|
432
|
+
const msg = `Node.js version mismatch: using ${nodeUsing} but asked for ${nodeRequired}`;
|
|
433
|
+
if (options.checkNodeVersion) {
|
|
434
|
+
self.ctx.error(new Error(msg));
|
|
435
|
+
return process.exit(1);
|
|
436
|
+
} else {
|
|
437
|
+
self.ctx.log(msg);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (options.log) {
|
|
443
|
+
// self.ctx.log('process.env', process.env)
|
|
444
|
+
self.ctx.log('Resolved serviceAccountPath', self.project.serviceAccountPath);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (!brandId) {
|
|
448
|
+
self.ctx.warn('⚠️ Missing config.brand.id');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Setup sentry — @omega.js/monitoring owns the policy (config resolution from
|
|
452
|
+
// `monitoring.providers.sentry.*`, the release tag, the gates) for every OMEGA
|
|
453
|
+
// target (#380).
|
|
454
|
+
// The gates run at BOOT, not per event: getEnvironment() is env-derived and
|
|
455
|
+
// stable for the life of a process, so a non-production run that would have
|
|
456
|
+
// dropped every event in beforeSend now never loads @sentry/node at all.
|
|
457
|
+
// `libraries.sentry` stays the ONE capture handle (null when off) — the
|
|
458
|
+
// chokepoint in helpers/context/respond.js reads it exactly as before.
|
|
459
|
+
if (self.options.sentry) {
|
|
460
|
+
self.libraries.sentry = require('../vendor/monitoring/node.js').initialize({
|
|
461
|
+
config: self.config?.monitoring,
|
|
462
|
+
release: { id: brandId || self.project.projectId, version: self.package.version },
|
|
463
|
+
isProduction: self.isProduction(),
|
|
464
|
+
allowInDev: self.options.reportErrorsInDev,
|
|
465
|
+
// Read at capture time: one process serves many invocations, so the
|
|
466
|
+
// function identity belongs to the event, not the boot.
|
|
467
|
+
tags: () => ({
|
|
468
|
+
'function.name': self.ctx.meta.name,
|
|
469
|
+
'function.type': self.ctx.meta.type,
|
|
470
|
+
'environment': self.getEnvironment(),
|
|
471
|
+
}),
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Setup options features
|
|
476
|
+
if (self.options.initialize) {
|
|
477
|
+
// Initialize Firebase. On any managed runtime — explicit ADC pointer, deployed Cloud
|
|
478
|
+
// Functions/Cloud Run (K_SERVICE/FUNCTION_TARGET), or the emulator — a no-args
|
|
479
|
+
// initializeApp() authenticates with the runtime's own identity. A staged
|
|
480
|
+
// service-account.json is ONLY for local scripts hitting the real project.
|
|
481
|
+
const onCloudRuntime = !!process.env.K_SERVICE || !!process.env.FUNCTION_TARGET;
|
|
482
|
+
const onEmulator = process.env.FUNCTIONS_EMULATOR === 'true';
|
|
483
|
+
|
|
484
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS || onCloudRuntime || onEmulator) {
|
|
485
|
+
self.libraries.initializedAdmin = self.libraries.admin.initializeApp();
|
|
486
|
+
} else {
|
|
487
|
+
const serviceAccount = require(self.project.serviceAccountPath);
|
|
488
|
+
const loadedProjectId = serviceAccount.project_id;
|
|
489
|
+
const expectedProjectId = self.project.projectId;
|
|
490
|
+
|
|
491
|
+
// A cert for the wrong project authenticates every Firestore call with the wrong
|
|
492
|
+
// identity — gRPC UNAUTHENTICATED at request time, far from the cause. Refuse to boot.
|
|
493
|
+
// Compare project id to project id, EXACTLY: a brand id is not a project id (brand
|
|
494
|
+
// `omega-playground` runs on project `omegajs-playground`), so matching against the
|
|
495
|
+
// brand — by substring or otherwise — both false-negatives and false-positives.
|
|
496
|
+
// When the expected project is unknown (no FIREBASE_CONFIG), there is nothing to
|
|
497
|
+
// verify against, so boot proceeds rather than guessing.
|
|
498
|
+
if (expectedProjectId && loadedProjectId !== expectedProjectId) {
|
|
499
|
+
throw new Error(`Service account project mismatch: ${loadedProjectId} is not ${expectedProjectId} — fix ${self.project.serviceAccountPath}`);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
|
|
503
|
+
credential: self.libraries.admin.credential.cert(serviceAccount),
|
|
504
|
+
databaseURL: self.project.databaseURL || `https://${self.project.projectId}.firebaseio.com`,
|
|
505
|
+
}, options.uniqueAppName);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Setup main functions
|
|
510
|
+
if (options.projectType === 'firebase' && options.setupFunctions) {
|
|
511
|
+
self.setupFunctions(exporter, options);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Setup custom server
|
|
515
|
+
if (options.projectType === 'custom' && options.setupServer) {
|
|
516
|
+
self.setupCustomServer(exporter, options);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Setup LocalDatabase
|
|
520
|
+
if (options.initializeLocalStorage) {
|
|
521
|
+
self.storage();
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Fetch stats
|
|
525
|
+
if (self.isDevelopment() && options.fetchStats) {
|
|
526
|
+
setTimeout(function () {
|
|
527
|
+
self.ctx.log('Fetching meta/stats...');
|
|
528
|
+
self.libraries.admin
|
|
529
|
+
.firestore().doc('meta/stats')
|
|
530
|
+
.get()
|
|
531
|
+
.then(doc => {
|
|
532
|
+
self.ctx.log('meta/stats', doc.data());
|
|
533
|
+
})
|
|
534
|
+
}, 100);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Send analytics
|
|
538
|
+
self.Analytics({
|
|
539
|
+
ctx: self.ctx,
|
|
540
|
+
uuid: self.SERVER_UUID,
|
|
541
|
+
})
|
|
542
|
+
.event('admin/initialized', {});
|
|
543
|
+
|
|
544
|
+
// Return
|
|
545
|
+
return self;
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
// HELPERS
|
|
549
|
+
Manager.prototype._preProcess = function (mod) {
|
|
550
|
+
const self = this;
|
|
551
|
+
const name = mod.ctx.meta.name;
|
|
552
|
+
return new Promise(async function(resolve, reject) {
|
|
553
|
+
if (self.handlers && self.handlers[name]) {
|
|
554
|
+
let result;
|
|
555
|
+
try {
|
|
556
|
+
result = self.handlers[name](mod)
|
|
557
|
+
} catch (e) {
|
|
558
|
+
mod.ctx.error(e);
|
|
559
|
+
return reject(e);
|
|
560
|
+
}
|
|
561
|
+
if (Promise.resolve(result) == result) {
|
|
562
|
+
result
|
|
563
|
+
.then(r => {
|
|
564
|
+
return resolve(r);
|
|
565
|
+
})
|
|
566
|
+
.catch(e => {
|
|
567
|
+
mod.ctx.error(e);
|
|
568
|
+
return reject(e);
|
|
569
|
+
})
|
|
570
|
+
} else {
|
|
571
|
+
return resolve(result);
|
|
572
|
+
}
|
|
573
|
+
} else {
|
|
574
|
+
return resolve(null);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
Manager.prototype._handleMcp = function (req, res, routePath) {
|
|
580
|
+
const self = this;
|
|
581
|
+
const cors = self.libraries.cors;
|
|
582
|
+
|
|
583
|
+
return cors(req, res, async () => {
|
|
584
|
+
const { handleMcpRoute } = require('../mcp/handler.js');
|
|
585
|
+
await handleMcpRoute(req, res, {
|
|
586
|
+
Manager: self,
|
|
587
|
+
routePath: routePath,
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
Manager.prototype._processMiddleware = function (req, res, routePath) {
|
|
593
|
+
const self = this;
|
|
594
|
+
|
|
595
|
+
const bemRoutesDir = path.resolve(__dirname, './routes');
|
|
596
|
+
const bemSchemasDir = path.resolve(__dirname, './schemas');
|
|
597
|
+
const consumerRoutesDir = path.normalize(`${self.cwd}${self.options.routes || '/routes'}`);
|
|
598
|
+
const consumerSchemasDir = path.normalize(`${self.cwd}${self.options.schemas || '/schemas'}`);
|
|
599
|
+
|
|
600
|
+
// Check if the route exists in the consumer's routes directory first
|
|
601
|
+
const consumerRoutePath = path.resolve(consumerRoutesDir, routePath);
|
|
602
|
+
const isConsumerRoute = require('fs').existsSync(consumerRoutePath);
|
|
603
|
+
|
|
604
|
+
const routesDir = isConsumerRoute ? consumerRoutesDir : bemRoutesDir;
|
|
605
|
+
const schemasDir = isConsumerRoute ? consumerSchemasDir : bemSchemasDir;
|
|
606
|
+
|
|
607
|
+
return self.Middleware(req, res).run(routePath, {
|
|
608
|
+
routesDir,
|
|
609
|
+
schemasDir,
|
|
610
|
+
schema: routePath,
|
|
611
|
+
});
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
Manager.prototype.RouteContext = function(ref, options) {
|
|
615
|
+
const self = this;
|
|
616
|
+
|
|
617
|
+
// Set options defaults
|
|
618
|
+
ref = ref || {};
|
|
619
|
+
options = options || {};
|
|
620
|
+
|
|
621
|
+
// Create ctx instance
|
|
622
|
+
return (new self.libraries.RouteContext()).init({
|
|
623
|
+
req: ref.req,
|
|
624
|
+
res: ref.res,
|
|
625
|
+
admin: self.libraries.admin,
|
|
626
|
+
functions: self.libraries.functions,
|
|
627
|
+
Manager: self,
|
|
628
|
+
}, options)
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
Manager.prototype.User = function () {
|
|
632
|
+
const self = this;
|
|
633
|
+
self.libraries.User = self.libraries.User || require('./helpers/user.js');
|
|
634
|
+
return new self.libraries.User(self, ...arguments);
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
Manager.prototype.Analytics = function () {
|
|
638
|
+
const self = this;
|
|
639
|
+
self.libraries.Analytics = self.libraries.Analytics || require('./helpers/analytics.js');
|
|
640
|
+
return new self.libraries.Analytics(self, ...arguments);
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
Manager.prototype.ApiManager = function () {
|
|
644
|
+
const self = this;
|
|
645
|
+
self.libraries.ApiManager = self.libraries.ApiManager || require('./helpers/api-manager.js');
|
|
646
|
+
return new self.libraries.ApiManager(self, ...arguments);
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
Manager.prototype.Roles = function () {
|
|
650
|
+
const self = this;
|
|
651
|
+
self.libraries.Roles = self.libraries.Roles || require('./helpers/roles.js');
|
|
652
|
+
return new self.libraries.Roles(self, ...arguments);
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
Manager.prototype.Usage = function () {
|
|
656
|
+
const self = this;
|
|
657
|
+
self.libraries.Usage = self.libraries.Usage || require('./helpers/usage.js');
|
|
658
|
+
return new self.libraries.Usage(self, ...arguments);
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
Manager.prototype.Middleware = function () {
|
|
662
|
+
const self = this;
|
|
663
|
+
self.libraries.Middleware = self.libraries.Middleware || require('./helpers/middleware.js');
|
|
664
|
+
return new self.libraries.Middleware(self, ...arguments);
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
Manager.prototype.BackendRouter = function (req, res) {
|
|
668
|
+
const self = this;
|
|
669
|
+
self.libraries.BackendRouter = self.libraries.BackendRouter || require('./helpers/backend-router.js');
|
|
670
|
+
return new self.libraries.BackendRouter(self, req, res);
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
Manager.prototype.EventMiddleware = function (payload) {
|
|
674
|
+
const self = this;
|
|
675
|
+
self.libraries.EventMiddleware = self.libraries.EventMiddleware || require('./helpers/event-middleware.js');
|
|
676
|
+
return new self.libraries.EventMiddleware(self, payload);
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
Manager.prototype.Settings = function () {
|
|
680
|
+
const self = this;
|
|
681
|
+
self.libraries.Settings = self.libraries.Settings || require('./helpers/settings.js');
|
|
682
|
+
return new self.libraries.Settings(self, ...arguments);
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
Manager.prototype.Metadata = function () {
|
|
686
|
+
const self = this;
|
|
687
|
+
self.libraries.Metadata = self.libraries.Metadata || require('./helpers/metadata.js');
|
|
688
|
+
return new self.libraries.Metadata(self, ...arguments);
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
Manager.prototype.Email = function (ctx) {
|
|
692
|
+
const self = this;
|
|
693
|
+
self.libraries.Email = self.libraries.Email || require('./libraries/email/index.js');
|
|
694
|
+
return new self.libraries.Email(ctx);
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
Manager.prototype.AI = function (ctx, key) {
|
|
698
|
+
const self = this;
|
|
699
|
+
self.libraries.AI = self.libraries.AI || require('./libraries/ai/index.js');
|
|
700
|
+
return new self.libraries.AI(ctx, key);
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
// Manager.prototype.Utilities = function () {
|
|
704
|
+
// const self = this;
|
|
705
|
+
// self.libraries.Utilities = self.libraries.Utilities || require('./helpers/utilities.js');
|
|
706
|
+
// return new self.libraries.Utilities(self, ...arguments);
|
|
707
|
+
// };
|
|
708
|
+
|
|
709
|
+
Manager.prototype.Utilities = function () {
|
|
710
|
+
const self = this;
|
|
711
|
+
|
|
712
|
+
if (!self._internal.utilities) {
|
|
713
|
+
self.libraries.Utilities = require('./helpers/utilities.js');
|
|
714
|
+
self._internal.utilities = new self.libraries.Utilities(self, ...arguments);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
return self._internal.utilities;
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
Manager.prototype.storage = function (options) {
|
|
721
|
+
const self = this;
|
|
722
|
+
options = options || {};
|
|
723
|
+
options.name = options.name || 'main';
|
|
724
|
+
|
|
725
|
+
if (!self._internal.storage[options.name]) {
|
|
726
|
+
options.temporary = typeof options.temporary === 'undefined' ? false : options.temporary;
|
|
727
|
+
options.clear = typeof options.clear === 'undefined' ? true : options.clear;
|
|
728
|
+
options.log = typeof options.log === 'undefined' ? false : options.log;
|
|
729
|
+
|
|
730
|
+
// Set path
|
|
731
|
+
const subfolder = `storage/${self.options.uniqueAppName || 'primary'}/${options.name}`;
|
|
732
|
+
|
|
733
|
+
// Setup lowdb
|
|
734
|
+
const { LowSync } = require('lowdb');
|
|
735
|
+
const { JSONFileSync } = require('lowdb/node');
|
|
736
|
+
const location = options.temporary
|
|
737
|
+
? `${require('os').tmpdir()}/${subfolder}.json`
|
|
738
|
+
: `./.data/${subfolder}.json`;
|
|
739
|
+
|
|
740
|
+
// Log
|
|
741
|
+
if (options.log) {
|
|
742
|
+
self.ctx.log('storage(): Location', location);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Clear temporary storage
|
|
746
|
+
if (
|
|
747
|
+
options.temporary
|
|
748
|
+
&& self.isDevelopment()
|
|
749
|
+
&& options.clear
|
|
750
|
+
) {
|
|
751
|
+
self.ctx.log('Removed temporary file @', location);
|
|
752
|
+
jetpack.remove(location);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Setup options
|
|
756
|
+
options.clearInvalid = typeof options.clearInvalid === 'undefined'
|
|
757
|
+
? true
|
|
758
|
+
: options.clearInvalid;
|
|
759
|
+
|
|
760
|
+
function _setup() {
|
|
761
|
+
if (!jetpack.exists(location)) {
|
|
762
|
+
jetpack.write(location, {});
|
|
763
|
+
}
|
|
764
|
+
const db = new LowSync(new JSONFileSync(location), {});
|
|
765
|
+
db.read();
|
|
766
|
+
|
|
767
|
+
// Wrap lowdb in a v1-compatible API so consumers don't need lodash
|
|
768
|
+
self._internal.storage[options.name] = {
|
|
769
|
+
_db: db,
|
|
770
|
+
_location: location,
|
|
771
|
+
get(path, defaultValue) {
|
|
772
|
+
const result = _get(db.data, path, defaultValue);
|
|
773
|
+
return { value() { return result; } };
|
|
774
|
+
},
|
|
775
|
+
set(path, value) { _set(db.data, path, value); return this; },
|
|
776
|
+
write() { db.write(); return this; },
|
|
777
|
+
getState() { return db.data; },
|
|
778
|
+
setState(data) { db.data = data; return this; },
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
try {
|
|
783
|
+
_setup()
|
|
784
|
+
} catch (e) {
|
|
785
|
+
self.ctx.error(`Could not setup storage: ${location}`, e);
|
|
786
|
+
|
|
787
|
+
try {
|
|
788
|
+
if (options.clearInvalid) {
|
|
789
|
+
self.ctx.log(`Clearing invalid storage: ${location}`);
|
|
790
|
+
jetpack.write(location, {});
|
|
791
|
+
}
|
|
792
|
+
_setup()
|
|
793
|
+
} catch (e) {
|
|
794
|
+
self.ctx.error(`Failed to clear invalid storage: ${location}`, e);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
return self._internal.storage[options.name]
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
Manager.prototype.getCustomServer = function () {
|
|
803
|
+
const self = this;
|
|
804
|
+
|
|
805
|
+
if (!self._internal.server || !self._internal.app) {
|
|
806
|
+
throw new Error('Server not set up');
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
return {
|
|
810
|
+
server: self._internal.server,
|
|
811
|
+
app: self._internal.app,
|
|
812
|
+
};
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
Manager.prototype.install = function (controller, options) {
|
|
816
|
+
const self = this;
|
|
817
|
+
|
|
818
|
+
// Set options defaults
|
|
819
|
+
options = options || {};
|
|
820
|
+
options.prefix = typeof options.prefix === 'undefined' ? null : options.prefix;
|
|
821
|
+
options.dir = typeof options.dir === 'undefined' ? '' : options.dir;
|
|
822
|
+
options.log = typeof options.log === 'undefined' ? false : options.log;
|
|
823
|
+
|
|
824
|
+
// Fix dir
|
|
825
|
+
options.dir = path.resolve(self.cwd, options.dir);
|
|
826
|
+
|
|
827
|
+
// If dir is a single file, install it. if its a directory, install all
|
|
828
|
+
const isDirectory = jetpack.exists(options.dir) === 'dir';
|
|
829
|
+
|
|
830
|
+
if (options.log) {
|
|
831
|
+
self.ctx.log(`Installing from ${options.dir}, prefix=${options.prefix}, isDirectory=${isDirectory}...`);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// function _install(prefix, file) {
|
|
835
|
+
// if (!file.includes('.js')) {return}
|
|
836
|
+
// const name = file.replace('.js', '');
|
|
837
|
+
// const _prefix = prefix ? `${prefix}_${name}` : name;
|
|
838
|
+
|
|
839
|
+
// const fullPath = path.resolve(options.dir, file);
|
|
840
|
+
|
|
841
|
+
// if (options.log) {
|
|
842
|
+
// self.ctx.log(`Installing ${_prefix} from ${fullPath}...`);
|
|
843
|
+
// }
|
|
844
|
+
|
|
845
|
+
// controller[`${_prefix}`] = require(fullPath);
|
|
846
|
+
// }
|
|
847
|
+
|
|
848
|
+
function _install(prefix, file) {
|
|
849
|
+
if (!file.includes('.js')) return;
|
|
850
|
+
|
|
851
|
+
const name = file.replace('.js', '');
|
|
852
|
+
const _prefix = prefix ? `${prefix}_${name}` : name;
|
|
853
|
+
const fullPath = path.resolve(options.dir, file);
|
|
854
|
+
|
|
855
|
+
if (options.log) {
|
|
856
|
+
self.ctx.log(`Installing ${_prefix} from ${fullPath}...`);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
const mod = require(fullPath);
|
|
860
|
+
|
|
861
|
+
// If module exports a function, bind it to controller
|
|
862
|
+
if (typeof mod === 'function') {
|
|
863
|
+
controller[_prefix] = mod.bind(controller);
|
|
864
|
+
} else {
|
|
865
|
+
controller[_prefix] = mod;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
if (isDirectory) {
|
|
870
|
+
jetpack.list(options.dir)
|
|
871
|
+
.forEach(file => _install(options.prefix, file))
|
|
872
|
+
} else {
|
|
873
|
+
_install(options.prefix, options.dir);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
|
|
877
|
+
// Require
|
|
878
|
+
Manager.prototype.require = function (name) {
|
|
879
|
+
return require(name);
|
|
880
|
+
};
|
|
881
|
+
Manager.require = function (name) {
|
|
882
|
+
return require(name);
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
Manager.prototype.debug = function () {
|
|
886
|
+
return {
|
|
887
|
+
throwException: function () {
|
|
888
|
+
throw new Error('TEST_ERROR');
|
|
889
|
+
},
|
|
890
|
+
throwRejection: function () {
|
|
891
|
+
Promise.reject(new Error('TEST_ERROR'));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Setup functions
|
|
897
|
+
Manager.prototype.setupFunctions = function (exporter, options) {
|
|
898
|
+
const self = this;
|
|
899
|
+
const resourceZone = options.resourceZone;
|
|
900
|
+
|
|
901
|
+
// Helper to create a function builder with region + runtime options
|
|
902
|
+
function fn(runtimeOptions) {
|
|
903
|
+
return self.libraries.functions
|
|
904
|
+
.runWith(runtimeOptions)
|
|
905
|
+
.region(resourceZone);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// Log
|
|
909
|
+
if (options.log) {
|
|
910
|
+
self.ctx.log('Setting up Firebase functions...');
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Setup functions
|
|
914
|
+
exporter.omega_api =
|
|
915
|
+
fn({memory: '256MB', timeoutSeconds: 60 * 5})
|
|
916
|
+
.https.onRequest(async (req, res) => {
|
|
917
|
+
const route = self.BackendRouter(req, res).resolve();
|
|
918
|
+
|
|
919
|
+
// MCP endpoint — bypass middleware, handle protocol directly
|
|
920
|
+
const mcpRoutePath = resolveMcpRoutePath(route.routePath);
|
|
921
|
+
if (mcpRoutePath) {
|
|
922
|
+
return self._handleMcp(req, res, mcpRoutePath);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// RESTful middleware system
|
|
926
|
+
return self._processMiddleware(req, res, route.routePath);
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
// Setup legacy functions
|
|
930
|
+
if (options.setupFunctionsLegacy) {
|
|
931
|
+
exporter.omega_signUpHandler =
|
|
932
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
933
|
+
.https.onRequest(async (req, res) => {
|
|
934
|
+
const Module = require(`${_legacy}/actions/sign-up-handler.js`);
|
|
935
|
+
Module.init(self, { req: req, res: res, });
|
|
936
|
+
|
|
937
|
+
return self._preProcess(Module)
|
|
938
|
+
.then(r => Module.main())
|
|
939
|
+
.catch(e => {
|
|
940
|
+
self.ctx.error(e);
|
|
941
|
+
return res.status(500).send(e.message);
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
// Admin
|
|
946
|
+
exporter.omega_createPost =
|
|
947
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
948
|
+
.https.onRequest(async (req, res) => {
|
|
949
|
+
const Module = require(`${_legacy}/admin/create-post.js`);
|
|
950
|
+
Module.init(self, { req: req, res: res, });
|
|
951
|
+
|
|
952
|
+
return self._preProcess(Module)
|
|
953
|
+
.then(r => Module.main())
|
|
954
|
+
.catch(e => {
|
|
955
|
+
self.ctx.error(e);
|
|
956
|
+
return res.status(500).send(e.message);
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
exporter.omega_firestoreWrite =
|
|
961
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
962
|
+
.https.onRequest(async (req, res) => {
|
|
963
|
+
const Module = require(`${_legacy}/admin/firestore-write.js`);
|
|
964
|
+
Module.init(self, { req: req, res: res, });
|
|
965
|
+
|
|
966
|
+
return self._preProcess(Module)
|
|
967
|
+
.then(r => Module.main())
|
|
968
|
+
.catch(e => {
|
|
969
|
+
self.ctx.error(e);
|
|
970
|
+
return res.status(500).send(e.message);
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
exporter.omega_getStats =
|
|
975
|
+
fn({memory: '256MB', timeoutSeconds: 420})
|
|
976
|
+
.https.onRequest(async (req, res) => {
|
|
977
|
+
const Module = require(`${_legacy}/admin/get-stats.js`);
|
|
978
|
+
Module.init(self, { req: req, res: res, });
|
|
979
|
+
|
|
980
|
+
return self._preProcess(Module)
|
|
981
|
+
.then(r => Module.main())
|
|
982
|
+
.catch(e => {
|
|
983
|
+
self.ctx.error(e);
|
|
984
|
+
return res.status(500).send(e.message);
|
|
985
|
+
});
|
|
986
|
+
});
|
|
987
|
+
|
|
988
|
+
exporter.omega_sendNotification =
|
|
989
|
+
fn({memory: '1GB', timeoutSeconds: 420})
|
|
990
|
+
.https.onRequest(async (req, res) => {
|
|
991
|
+
const Module = require(`${_legacy}/admin/send-notification.js`);
|
|
992
|
+
Module.init(self, { req: req, res: res, });
|
|
993
|
+
|
|
994
|
+
return self._preProcess(Module)
|
|
995
|
+
.then(r => Module.main())
|
|
996
|
+
.catch(e => {
|
|
997
|
+
self.ctx.error(e);
|
|
998
|
+
return res.status(500).send(e.message);
|
|
999
|
+
});
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
exporter.omega_query =
|
|
1003
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1004
|
+
.https.onRequest(async (req, res) => {
|
|
1005
|
+
const Module = require(`${_legacy}/admin/query.js`);
|
|
1006
|
+
Module.init(self, { req: req, res: res, });
|
|
1007
|
+
|
|
1008
|
+
return self._preProcess(Module)
|
|
1009
|
+
.then(r => Module.main())
|
|
1010
|
+
.catch(e => {
|
|
1011
|
+
self.ctx.error(e);
|
|
1012
|
+
return res.status(500).send(e.message);
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
|
|
1016
|
+
exporter.omega_createPostHandler =
|
|
1017
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1018
|
+
.https.onRequest(async (req, res) => {
|
|
1019
|
+
const Module = require(`${_legacy}/actions/create-post-handler.js`);
|
|
1020
|
+
Module.init(self, { req: req, res: res, });
|
|
1021
|
+
|
|
1022
|
+
return self._preProcess(Module)
|
|
1023
|
+
.then(r => Module.main())
|
|
1024
|
+
.catch(e => {
|
|
1025
|
+
self.ctx.error(e);
|
|
1026
|
+
return res.status(500).send(e.message);
|
|
1027
|
+
});
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
exporter.omega_generateUuid =
|
|
1031
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1032
|
+
.https.onRequest(async (req, res) => {
|
|
1033
|
+
const Module = require(`${_legacy}/actions/generate-uuid.js`);
|
|
1034
|
+
Module.init(self, { req: req, res: res, });
|
|
1035
|
+
|
|
1036
|
+
return self._preProcess(Module)
|
|
1037
|
+
.then(r => Module.main())
|
|
1038
|
+
.catch(e => {
|
|
1039
|
+
self.ctx.error(e);
|
|
1040
|
+
return res.status(500).send(e.message);
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
// Test
|
|
1045
|
+
exporter.omega_test_authenticate =
|
|
1046
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1047
|
+
.https.onRequest(async (req, res) => {
|
|
1048
|
+
const Module = require(`${_legacy}/test/authenticate.js`);
|
|
1049
|
+
Module.init(self, { req: req, res: res, });
|
|
1050
|
+
|
|
1051
|
+
return self._preProcess(Module)
|
|
1052
|
+
.then(r => Module.main())
|
|
1053
|
+
.catch(e => {
|
|
1054
|
+
self.ctx.error(e);
|
|
1055
|
+
return res.status(500).send(e.message);
|
|
1056
|
+
});
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
exporter.omega_test_webhook =
|
|
1060
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1061
|
+
.https.onRequest(async (req, res) => {
|
|
1062
|
+
const Module = require(`${_legacy}/test/webhook.js`);
|
|
1063
|
+
Module.init(self, { req: req, res: res, });
|
|
1064
|
+
|
|
1065
|
+
return self._preProcess(Module)
|
|
1066
|
+
.then(r => Module.main())
|
|
1067
|
+
.catch(e => {
|
|
1068
|
+
self.ctx.error(e);
|
|
1069
|
+
return res.status(500).send(e.message);
|
|
1070
|
+
});
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// Setup identity functions
|
|
1075
|
+
if (options.setupFunctionsIdentity) {
|
|
1076
|
+
exporter.omega_authBeforeCreate =
|
|
1077
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1078
|
+
.auth.user()
|
|
1079
|
+
.beforeCreate((user, context) => self.EventMiddleware({ user, context }).run(`${events}/auth/before-create.js`));
|
|
1080
|
+
|
|
1081
|
+
exporter.omega_authBeforeSignIn =
|
|
1082
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1083
|
+
.auth.user()
|
|
1084
|
+
.beforeSignIn((user, context) => self.EventMiddleware({ user, context }).run(`${events}/auth/before-signin.js`));
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// Setup events
|
|
1088
|
+
exporter.omega_authOnCreate =
|
|
1089
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1090
|
+
.auth.user()
|
|
1091
|
+
.onCreate((user, context) => self.EventMiddleware({ user, context }).run(`${events}/auth/on-create.js`));
|
|
1092
|
+
|
|
1093
|
+
exporter.omega_authOnDelete =
|
|
1094
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1095
|
+
.auth.user()
|
|
1096
|
+
.onDelete((user, context) => self.EventMiddleware({ user, context }).run(`${events}/auth/on-delete.js`));
|
|
1097
|
+
|
|
1098
|
+
exporter.omega_notificationsOnWrite =
|
|
1099
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1100
|
+
.firestore.document('notifications/{token}')
|
|
1101
|
+
.onWrite((change, context) => self.EventMiddleware({ change, context }).run(`${events}/firestore/notifications/on-write.js`));
|
|
1102
|
+
|
|
1103
|
+
exporter.omega_paymentsWebhookOnWrite =
|
|
1104
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1105
|
+
.firestore.document('payments-webhooks/{eventId}')
|
|
1106
|
+
.onWrite((change, context) => self.EventMiddleware({ change, context }).run(`${events}/firestore/payments-webhooks/on-write.js`));
|
|
1107
|
+
|
|
1108
|
+
exporter.omega_paymentsDisputeOnWrite =
|
|
1109
|
+
fn({memory: '256MB', timeoutSeconds: 60})
|
|
1110
|
+
.firestore.document('payments-disputes/{alertId}')
|
|
1111
|
+
.onWrite((change, context) => self.EventMiddleware({ change, context }).run(`${events}/firestore/payments-disputes/on-write.js`));
|
|
1112
|
+
|
|
1113
|
+
// Setup cron jobs
|
|
1114
|
+
exporter.omega_cronDaily =
|
|
1115
|
+
fn({memory: '256MB', timeoutSeconds: 60 * 5})
|
|
1116
|
+
.pubsub.schedule('0 0 * * *')
|
|
1117
|
+
.onRun((context) => self.EventMiddleware({ context }).run(`${cron}/daily.js`));
|
|
1118
|
+
|
|
1119
|
+
// Frequent cron runs the inline newsletter generator (AI structure + section
|
|
1120
|
+
// images + article + uploads) — needs the v1 max timeout. If a run times out
|
|
1121
|
+
// or OOMs, the campaign lease reclaim in marketing-campaigns.js retries it
|
|
1122
|
+
// safely.
|
|
1123
|
+
exporter.omega_cronFrequent =
|
|
1124
|
+
fn({memory: '256MB', timeoutSeconds: 540})
|
|
1125
|
+
.pubsub.schedule('*/10 * * * *')
|
|
1126
|
+
.onRun((context) => self.EventMiddleware({ context }).run(`${cron}/frequent.js`));
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1129
|
+
// Setup Custom Server
|
|
1130
|
+
Manager.prototype.setupCustomServer = function (_library, options) {
|
|
1131
|
+
const self = this;
|
|
1132
|
+
|
|
1133
|
+
// Require
|
|
1134
|
+
const glob = require('glob').globSync;
|
|
1135
|
+
|
|
1136
|
+
// Log
|
|
1137
|
+
if (options.log) {
|
|
1138
|
+
self.ctx.log('Setting up custom server...');
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// Setup express
|
|
1142
|
+
const app = require('express')({
|
|
1143
|
+
logger: true,
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
// Setup body parser with configurable limits
|
|
1147
|
+
app.use(require('body-parser').json(options.express.bodyParser.json));
|
|
1148
|
+
app.use(require('body-parser').urlencoded(options.express.bodyParser.urlencoded));
|
|
1149
|
+
|
|
1150
|
+
// Handle errors with custom error handler
|
|
1151
|
+
app.use((err, req, res, next) => {
|
|
1152
|
+
// Create a new ctx because our custom Middleware has not been run yet
|
|
1153
|
+
const ctx = self.RouteContext({ req: req, res: res, }, {});
|
|
1154
|
+
|
|
1155
|
+
// Handle PayloadTooLargeError from body-parser
|
|
1156
|
+
if (err.type === 'entity.too.large') {
|
|
1157
|
+
return ctx.respond('Request payload too large.', { code: 413 });
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// Catch-all for other body-parser and middleware errors
|
|
1161
|
+
if (err) {
|
|
1162
|
+
// Log
|
|
1163
|
+
// @TODO: REMOVE THIS LOG ONCE WE'RE CONFIDENT IT'S WORKING AS INTENDED
|
|
1164
|
+
console.log('@TODO: Custom Error Handler:', err);
|
|
1165
|
+
|
|
1166
|
+
// Return
|
|
1167
|
+
return ctx.respond(err.message || 'Bad request', { code: err.status || err.code || err.statusCode || 400 });
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// If no error, continue
|
|
1171
|
+
next(err);
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
// Designate paths
|
|
1175
|
+
const managerRoutesPath = path.normalize(`${__dirname}/routes`);
|
|
1176
|
+
const managerSchemasPath = path.normalize(`${__dirname}/schemas`);
|
|
1177
|
+
const customRoutesPath = path.normalize(`${self.cwd}${options.routes}`);
|
|
1178
|
+
const customSchemasPath = path.normalize(`${self.cwd}${options.schemas}`);
|
|
1179
|
+
|
|
1180
|
+
// Create routes
|
|
1181
|
+
const routes = [];
|
|
1182
|
+
|
|
1183
|
+
// Push function
|
|
1184
|
+
function _push(dir, isManager) {
|
|
1185
|
+
// Get all files (index.js and method-specific files like get.js, post.js)
|
|
1186
|
+
glob('**/*.js', { cwd: dir })
|
|
1187
|
+
.forEach((file) => {
|
|
1188
|
+
const fileName = path.basename(file, '.js');
|
|
1189
|
+
const dirName = path.dirname(file);
|
|
1190
|
+
|
|
1191
|
+
// Determine method and route name
|
|
1192
|
+
let method = 'all'; // default to all methods
|
|
1193
|
+
let routeName;
|
|
1194
|
+
|
|
1195
|
+
if (fileName === 'index') {
|
|
1196
|
+
// Traditional index.js file: routes/restart/index.js -> restart
|
|
1197
|
+
// Root index.js: routes/index.js -> '' (empty string for root path)
|
|
1198
|
+
routeName = dirName === '.' ? '' : dirName;
|
|
1199
|
+
} else if (['get', 'post', 'put', 'delete', 'patch', 'options', 'head'].includes(fileName.toLowerCase())) {
|
|
1200
|
+
// Method-specific file: routes/restart/get.js -> restart (GET only)
|
|
1201
|
+
method = fileName.toLowerCase();
|
|
1202
|
+
routeName = dirName === '.' ? '' : dirName;
|
|
1203
|
+
} else {
|
|
1204
|
+
// Unknown pattern, skip
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// Build the item
|
|
1209
|
+
const item = {
|
|
1210
|
+
name: routeName,
|
|
1211
|
+
method: method,
|
|
1212
|
+
namespace: file,
|
|
1213
|
+
path: path.resolve(dir, file),
|
|
1214
|
+
dir: dir,
|
|
1215
|
+
isManager: isManager,
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// If it exists in routes with same name AND method, replace it
|
|
1219
|
+
const existing = routes.findIndex(r => r.name === item.name && r.method === item.method);
|
|
1220
|
+
if (existing > -1) {
|
|
1221
|
+
routes[existing] = item;
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// Otherwise, push it
|
|
1226
|
+
routes.push(item);
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// Push routes
|
|
1231
|
+
// _push(`${__dirname}/routes`)
|
|
1232
|
+
_push(managerRoutesPath, true)
|
|
1233
|
+
_push(customRoutesPath, false)
|
|
1234
|
+
|
|
1235
|
+
// Log routes
|
|
1236
|
+
// if (options.log) {
|
|
1237
|
+
// self.ctx.log('Routes:', routes);
|
|
1238
|
+
// }
|
|
1239
|
+
|
|
1240
|
+
// Install process
|
|
1241
|
+
routes.forEach((file) => {
|
|
1242
|
+
// self.ctx.log('---file', file);
|
|
1243
|
+
// Require the file
|
|
1244
|
+
const cors = self.libraries.cors;
|
|
1245
|
+
|
|
1246
|
+
// Log
|
|
1247
|
+
// if (options.log) {
|
|
1248
|
+
self.ctx.log(`Initializing route: ${file.method.toUpperCase()} /${file.name} @ ${file.path}`);
|
|
1249
|
+
// }
|
|
1250
|
+
|
|
1251
|
+
// Register the route with the appropriate HTTP method
|
|
1252
|
+
app[file.method](`/${file.name}`, async (req, res) => {
|
|
1253
|
+
return cors(req, res, async () => {
|
|
1254
|
+
// For root route (empty name), skip schema validation
|
|
1255
|
+
const middlewareOptions = {
|
|
1256
|
+
routesDir: file.isManager ? managerRoutesPath : customRoutesPath,
|
|
1257
|
+
schemasDir: file.isManager ? managerSchemasPath : customSchemasPath,
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
// Only set schema if route name is not empty
|
|
1261
|
+
if (file.name) {
|
|
1262
|
+
middlewareOptions.schema = file.name;
|
|
1263
|
+
} else {
|
|
1264
|
+
middlewareOptions.setupSettings = false;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
self.Middleware(req, res).run(file.name, middlewareOptions)
|
|
1268
|
+
});
|
|
1269
|
+
})
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
// Run the server!
|
|
1273
|
+
const server = app.listen({ port: process.env.PORT || 3000, host: '0.0.0.0' }, (error) => {
|
|
1274
|
+
if (error) {
|
|
1275
|
+
self.ctx.error(error);
|
|
1276
|
+
process.exit(1);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
const address = server.address();
|
|
1280
|
+
|
|
1281
|
+
// Log
|
|
1282
|
+
if (options.log) {
|
|
1283
|
+
self.ctx.log(`Server listening on ${address.address}:${address.port}`);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// Set server and app to internal
|
|
1287
|
+
self._internal.server = server;
|
|
1288
|
+
self._internal.app = app;
|
|
1289
|
+
|
|
1290
|
+
// Emit event
|
|
1291
|
+
self.emit('online', new Event('online'), server, app);
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function resolveProjectPackage(dir) {
|
|
1296
|
+
try {
|
|
1297
|
+
return require(path.resolve(dir, 'functions', 'package.json'));
|
|
1298
|
+
} catch (e) {}
|
|
1299
|
+
|
|
1300
|
+
try {
|
|
1301
|
+
return require(path.resolve(dir, 'package.json'));
|
|
1302
|
+
} catch (e) {}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* Check if a routePath is an MCP-related route and normalize it.
|
|
1307
|
+
* Handles /omega/mcp/* paths and /.well-known/oauth-* discovery.
|
|
1308
|
+
*
|
|
1309
|
+
* @param {string} routePath - Resolved route path from BackendRouter
|
|
1310
|
+
* @returns {string|null} - Normalized MCP route path, or null if not MCP
|
|
1311
|
+
*/
|
|
1312
|
+
function resolveMcpRoutePath(routePath) {
|
|
1313
|
+
// Direct MCP paths (via /mcp/* or /omega/mcp/*)
|
|
1314
|
+
if (routePath === 'mcp' || routePath.startsWith('mcp/')) {
|
|
1315
|
+
return routePath;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
// OAuth discovery (via /.well-known/oauth-*)
|
|
1319
|
+
if (routePath === '.well-known/oauth-protected-resource'
|
|
1320
|
+
|| routePath === '.well-known/oauth-authorization-server') {
|
|
1321
|
+
return routePath;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// Root-level OAuth paths — Claude Chat sends these directly
|
|
1325
|
+
// regardless of what the discovery endpoints return
|
|
1326
|
+
if (routePath === 'authorize') {
|
|
1327
|
+
return 'mcp/authorize';
|
|
1328
|
+
}
|
|
1329
|
+
if (routePath === 'token') {
|
|
1330
|
+
return 'mcp/token';
|
|
1331
|
+
}
|
|
1332
|
+
if (routePath === 'register') {
|
|
1333
|
+
return 'mcp/register';
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
return null;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* Install the test-mode-file watcher. Called once during Manager.init() when
|
|
1341
|
+
* running in the test environment (emulator). Reads the shared state file
|
|
1342
|
+
* (`<projectRoot>/.temp/test-mode.json`) at startup to sync any env vars
|
|
1343
|
+
* set by an earlier test command, then watches the file for live changes.
|
|
1344
|
+
*
|
|
1345
|
+
* Idempotent — guarded by a module-level flag so reload-during-nodemon
|
|
1346
|
+
* doesn't stack listeners.
|
|
1347
|
+
*
|
|
1348
|
+
* @param {Manager} manager
|
|
1349
|
+
*/
|
|
1350
|
+
let _testModeWatcherInstalled = false;
|
|
1351
|
+
function setupTestModeWatcher(manager) {
|
|
1352
|
+
if (_testModeWatcherInstalled) {
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
_testModeWatcherInstalled = true;
|
|
1356
|
+
|
|
1357
|
+
const fs = require('fs');
|
|
1358
|
+
const jetpack = require('fs-jetpack');
|
|
1359
|
+
const { TEST_MODE_FILENAME, TEMP_DIR_NAME, getTestModeFilePath, readTestMode, applyEnvFromFile } = require('../test/utils/test-mode-file.js');
|
|
1360
|
+
|
|
1361
|
+
// Resolve the consumer's project root. self.cwd is the consumer's
|
|
1362
|
+
// functions/ directory; the test-mode file lives one level up at
|
|
1363
|
+
// <projectRoot>/.temp/test-mode.json.
|
|
1364
|
+
const projectDir = path.dirname(manager.cwd);
|
|
1365
|
+
const filePath = getTestModeFilePath(projectDir);
|
|
1366
|
+
const tempDir = path.join(projectDir, TEMP_DIR_NAME);
|
|
1367
|
+
|
|
1368
|
+
// Initial sync — apply any state the test/emulator command wrote before
|
|
1369
|
+
// this process booted. A sync/flip is an EVENT and always says so; the
|
|
1370
|
+
// resolved mode is per-worker boot noise under the emulator (see
|
|
1371
|
+
// isUnderEmulator) and only announces itself outside one.
|
|
1372
|
+
const initial = readTestMode(projectDir);
|
|
1373
|
+
const changed = applyEnvFromFile(initial);
|
|
1374
|
+
for (const c of changed) {
|
|
1375
|
+
manager.ctx.log(`test-mode sync ${c.key}: ${c.was || '(unset)'} → ${c.now || '(unset)'}`);
|
|
1376
|
+
}
|
|
1377
|
+
if (!isUnderEmulator()) {
|
|
1378
|
+
manager.ctx.log(`test-mode resolved TEST_EXTENDED_MODE=${!!process.env.TEST_EXTENDED_MODE} (file ${initial ? 'present' : 'absent'})`);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
// Ensure .temp/ exists so we can watch the directory (fs.watch on a missing
|
|
1382
|
+
// path throws synchronously). Watching the directory rather than the file
|
|
1383
|
+
// means deletes/recreations of test-mode.json don't break the watcher, and
|
|
1384
|
+
// we don't depend on whatever writer happened to run first.
|
|
1385
|
+
jetpack.dir(tempDir);
|
|
1386
|
+
|
|
1387
|
+
try {
|
|
1388
|
+
fs.watch(tempDir, { persistent: false }, (eventType, filename) => {
|
|
1389
|
+
// Only react to our file. fs.watch may emit for any change in the dir.
|
|
1390
|
+
if (filename && filename !== TEST_MODE_FILENAME) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const next = readTestMode(projectDir);
|
|
1394
|
+
const flipped = applyEnvFromFile(next);
|
|
1395
|
+
for (const c of flipped) {
|
|
1396
|
+
manager.ctx.log(`test-mode flip ${c.key}: ${c.was || '(unset)'} → ${c.now || '(unset)'}`);
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
} catch (e) {
|
|
1400
|
+
manager.ctx.log(`test-mode watcher failed to install (${e.message}), live sync disabled`);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
module.exports = Manager;
|