@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,112 @@
|
|
|
1
|
+
const { retryWrite, runAuthHook, MAX_RETRIES } = require('./utils.js');
|
|
2
|
+
const { buildUserDoc, isUserDoc, extractProviderName } = require('../../libraries/user-doc.js');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* onCreate - Create user doc
|
|
6
|
+
*
|
|
7
|
+
* This function fires for ALL user creations (including Admin SDK).
|
|
8
|
+
* It creates the user doc in Firestore.
|
|
9
|
+
*
|
|
10
|
+
* Key behaviors:
|
|
11
|
+
* - Checks if user doc already exists (auth.uid) → skips if exists (handles test accounts, provider linking)
|
|
12
|
+
* - Retries up to 3 times with exponential backoff on failure
|
|
13
|
+
*
|
|
14
|
+
* If the user signed up via a provider (Google, Facebook, etc.), their display name
|
|
15
|
+
* is extracted and stored as personal.name.first/last on the user doc.
|
|
16
|
+
*
|
|
17
|
+
* Non-critical work (welcome emails, marketing contact) is handled
|
|
18
|
+
* by the user/signup endpoint, which the frontend calls after account creation.
|
|
19
|
+
*
|
|
20
|
+
* Available parameters (1st gen):
|
|
21
|
+
*
|
|
22
|
+
* user (UserRecord — firebase-admin):
|
|
23
|
+
* uid, email, emailVerified, displayName, photoURL, phoneNumber, disabled,
|
|
24
|
+
* metadata: { creationTime, lastSignInTime, lastRefreshTime },
|
|
25
|
+
* providerData: [{ uid, displayName, email, photoURL, providerId, phoneNumber }],
|
|
26
|
+
* passwordHash, passwordSalt, customClaims, tenantId, tokensValidAfterTime, multiFactor
|
|
27
|
+
*
|
|
28
|
+
* context (EventContext — NOT AuthEventContext, no ipAddress/userAgent/locale):
|
|
29
|
+
* eventId, eventType, timestamp, resource: { service, name }, params
|
|
30
|
+
*/
|
|
31
|
+
module.exports = async ({ Manager, ctx, user, context, libraries }) => {
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
const { admin } = libraries;
|
|
34
|
+
|
|
35
|
+
// The uid and nothing else — the one spelling the other three auth triggers
|
|
36
|
+
// carry since the #657 sweep, so the family reads the same way
|
|
37
|
+
// ([#710](https://github.com/Omega-JS-Stack/omega/issues/710)). The email is
|
|
38
|
+
// legal on a log line, but it is not what NAMES this invocation, and the
|
|
39
|
+
// account it belongs to is one debug line away. The full UserRecord
|
|
40
|
+
// (passwordHash, providerData, metadata) and the event context go with it.
|
|
41
|
+
ctx.log(`onCreate: ${user.uid}`);
|
|
42
|
+
ctx.debug(`onCreate: ${user.uid} record`, user, context);
|
|
43
|
+
|
|
44
|
+
// Skip anonymous users
|
|
45
|
+
if (user.providerData?.every(p => p.providerId === 'anonymous')) {
|
|
46
|
+
ctx.log(`onCreate: Skipping anonymous user ${user.uid} (${Date.now() - startTime}ms)`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check if user doc already exists (handles test accounts, provider linking)
|
|
51
|
+
const existingDoc = await admin.firestore().doc(`users/${user.uid}`)
|
|
52
|
+
.get()
|
|
53
|
+
.catch(e => {
|
|
54
|
+
ctx.error(`onCreate: Failed to check existing doc for ${user.uid}:`, e);
|
|
55
|
+
return null;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (isUserDoc(existingDoc?.exists ? existingDoc.data() : null)) {
|
|
59
|
+
ctx.log(`onCreate: User doc already exists for ${user.uid}, skipping creation (${Date.now() - startTime}ms)`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Extract name from provider data (e.g., Google, Facebook, GitHub). WHETHER a
|
|
64
|
+
// name came back, never the name itself: a person's first/last is their PII,
|
|
65
|
+
// and this line lands in Cloud Logging for the whole retention window
|
|
66
|
+
// (docs/shared/logging.md § PII — identifier not payload,
|
|
67
|
+
// [#710](https://github.com/Omega-JS-Stack/omega/issues/710)). The parsed
|
|
68
|
+
// name stays one debug line down.
|
|
69
|
+
const providerName = extractProviderName(user);
|
|
70
|
+
|
|
71
|
+
ctx.log(`onCreate: Inferred name from provider for ${user.uid}: ${providerName ? 'yes' : 'no'}`);
|
|
72
|
+
ctx.debug(`onCreate: Inferred name from provider for ${user.uid}:`, providerName);
|
|
73
|
+
|
|
74
|
+
// Build the user doc — the same shape the sign-in heal recreates when this doc
|
|
75
|
+
// goes missing later ([#405](https://github.com/Omega-JS-Stack/omega/issues/405))
|
|
76
|
+
const userRecord = buildUserDoc({ Manager: Manager, user: user, tag: 'auth:on-create' });
|
|
77
|
+
|
|
78
|
+
// The UID and nothing else. The doc carries the email, the name, the signup IP
|
|
79
|
+
// and the geolocation, and a backend line lands in Cloud Logging for the whole
|
|
80
|
+
// retention window — so none of it rides this line
|
|
81
|
+
// ([#641](https://github.com/Omega-JS-Stack/omega/issues/641)).
|
|
82
|
+
ctx.log(`onCreate: Creating user doc for ${user.uid}`);
|
|
83
|
+
|
|
84
|
+
// Write user doc with retry
|
|
85
|
+
try {
|
|
86
|
+
await retryWrite(ctx, 'onCreate', async () => {
|
|
87
|
+
await admin.firestore().doc(`users/${user.uid}`).set(userRecord);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
ctx.log(`onCreate: Successfully created user doc for ${user.uid} (${Date.now() - startTime}ms)`);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
ctx.error(`onCreate: Failed to create user doc after ${MAX_RETRIES} retries:`, error);
|
|
93
|
+
|
|
94
|
+
// Don't reject - the user was already created in Auth
|
|
95
|
+
// The user/signup endpoint will handle creating the doc if it's missing
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// The SERVER half of `sign_up` does NOT fire here
|
|
99
|
+
// ([#577](https://github.com/Omega-JS-Stack/omega/issues/577)). A trigger has
|
|
100
|
+
// no HTTP request behind it, so a registration fired from here reached Meta
|
|
101
|
+
// and TikTok with no IP, no user agent, no platform cookies and an attribution
|
|
102
|
+
// the browser had not posted yet — around 4/10 on Meta's match quality. It
|
|
103
|
+
// fires from `routes/user/signup` instead, the post-auth request that carries
|
|
104
|
+
// all four (`libraries/analytics/signup.js`). Adding it back here would count
|
|
105
|
+
// every registration twice.
|
|
106
|
+
|
|
107
|
+
// Run consumer hook (non-blocking — errors logged but don't fail)
|
|
108
|
+
await runAuthHook('on-create', { Manager, ctx, user, context, libraries }).catch(e => {
|
|
109
|
+
ctx.error('onCreate: Consumer hook error:', e);
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
const { retryWrite, runAuthHook, MAX_RETRIES } = require('./utils.js');
|
|
2
|
+
const { deliverConversion } = require('../../libraries/analytics/conversions.js');
|
|
3
|
+
const { buildAttributionContext, buildIdentity } = require('../../libraries/analytics/match-data.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* onDelete - Delete user doc
|
|
7
|
+
*
|
|
8
|
+
* This function fires when a user is deleted from Firebase Auth.
|
|
9
|
+
* It deletes the user doc from Firestore.
|
|
10
|
+
*
|
|
11
|
+
* Key behaviors:
|
|
12
|
+
* - Checks if user doc exists before attempting delete
|
|
13
|
+
* - Retries up to 3 times with exponential backoff on failure
|
|
14
|
+
* - Logs timing for performance monitoring
|
|
15
|
+
*
|
|
16
|
+
* Available parameters (1st gen):
|
|
17
|
+
*
|
|
18
|
+
* user (UserRecord — firebase-admin):
|
|
19
|
+
* uid, email, emailVerified, displayName, photoURL, phoneNumber, disabled,
|
|
20
|
+
* metadata: { creationTime, lastSignInTime, lastRefreshTime },
|
|
21
|
+
* providerData: [{ uid, displayName, email, photoURL, providerId, phoneNumber }],
|
|
22
|
+
* passwordHash, passwordSalt, customClaims, tenantId, tokensValidAfterTime, multiFactor
|
|
23
|
+
*
|
|
24
|
+
* context (EventContext — NOT AuthEventContext, no ipAddress/userAgent/locale):
|
|
25
|
+
* eventId, eventType, timestamp, resource: { service, name }, params
|
|
26
|
+
*/
|
|
27
|
+
module.exports = async ({ Manager, ctx, user, context, libraries }) => {
|
|
28
|
+
const startTime = Date.now();
|
|
29
|
+
const { admin } = libraries;
|
|
30
|
+
|
|
31
|
+
// The UID and nothing else. The UserRecord carries the email, the display name,
|
|
32
|
+
// the provider data and the password hash, and a backend line lands in Cloud
|
|
33
|
+
// Logging for the whole retention window — so none of it rides this line
|
|
34
|
+
// ([#657](https://github.com/Omega-JS-Stack/omega/issues/657)). The record and
|
|
35
|
+
// the event context stay reachable one level down, at debug.
|
|
36
|
+
ctx.log(`onDelete: ${user.uid}`);
|
|
37
|
+
ctx.debug(`onDelete: ${user.uid} record`, user, context);
|
|
38
|
+
|
|
39
|
+
// Check if user doc exists before attempting delete
|
|
40
|
+
const existingDoc = await admin.firestore().doc(`users/${user.uid}`)
|
|
41
|
+
.get()
|
|
42
|
+
.catch(e => {
|
|
43
|
+
ctx.error(`onDelete: Failed to check existing doc for ${user.uid}:`, e);
|
|
44
|
+
return null;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (!existingDoc || !existingDoc.exists) {
|
|
48
|
+
ctx.log(`onDelete: User doc does not exist for ${user.uid}, skipping (${Date.now() - startTime}ms)`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Read the doc BEFORE it goes: the consent snapshot and the campaign that won
|
|
53
|
+
// this account are the only record of either, and the delete below is the
|
|
54
|
+
// moment they stop existing.
|
|
55
|
+
const userDoc = existingDoc.data();
|
|
56
|
+
|
|
57
|
+
// Delete user doc with retry
|
|
58
|
+
try {
|
|
59
|
+
await retryWrite(ctx, 'onDelete', async () => {
|
|
60
|
+
await admin.firestore().doc(`users/${user.uid}`).delete();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
ctx.log(`onDelete: Successfully deleted user doc for ${user.uid}`);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
ctx.error(`onDelete: Failed to delete user doc after ${MAX_RETRIES} retries:`, error);
|
|
66
|
+
|
|
67
|
+
// Don't reject - the user was already deleted from Auth
|
|
68
|
+
// Just log the error and continue
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Remove marketing contact from all providers (non-blocking)
|
|
73
|
+
if (user.email) {
|
|
74
|
+
const email = Manager.Email(ctx);
|
|
75
|
+
email.remove(user.email)
|
|
76
|
+
.then((r) => {
|
|
77
|
+
// The uid and how many providers answered. The results object carries
|
|
78
|
+
// each provider's own payload — a contact record, a subscriber — and
|
|
79
|
+
// every one of them carries the deleted user's address back, into the
|
|
80
|
+
// Cloud Logging retention window the headline above stopped writing to
|
|
81
|
+
// ([#710](https://github.com/Omega-JS-Stack/omega/issues/710)).
|
|
82
|
+
ctx.log(`onDelete: Marketing remove for ${user.uid}: ${Object.keys(r).length} provider(s)`);
|
|
83
|
+
ctx.debug('onDelete: Marketing remove:', r);
|
|
84
|
+
})
|
|
85
|
+
.catch((e) => ctx.error('onDelete: Marketing remove failed:', e));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Send delete analytics (server-side only event)
|
|
89
|
+
trackDelete({ Manager, ctx, user, userDoc });
|
|
90
|
+
|
|
91
|
+
// Run consumer hook (non-blocking — errors logged but don't fail)
|
|
92
|
+
await runAuthHook('on-delete', { Manager, ctx, user, context, libraries }).catch(e => {
|
|
93
|
+
ctx.error('onDelete: Consumer hook error:', e);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
ctx.log(`onDelete: Completed for ${user.uid} (${Date.now() - startTime}ms)`);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Fire the canonical `user_delete` conversion (non-blocking).
|
|
101
|
+
*
|
|
102
|
+
* The same treatment `notification_subscribe` gets, and for the same reason: a
|
|
103
|
+
* raw `Manager.Analytics(...).event()` reaches GA4 without ever asking the
|
|
104
|
+
* consent gate, and names an event no catalog knows. `user_delete` is a
|
|
105
|
+
* `placement: 'server'`, GA4-only entry — nothing else can observe an account
|
|
106
|
+
* ending, and no ad platform has anything to do with it.
|
|
107
|
+
*
|
|
108
|
+
* THE DEDUPE ID IS `user_delete.<uid>` — an account is deleted once, and the
|
|
109
|
+
* uid is what the deletion is about, so a redelivered trigger reports the same
|
|
110
|
+
* event rather than a second one.
|
|
111
|
+
*
|
|
112
|
+
* The consent snapshot and the attribution come off the doc read BEFORE the
|
|
113
|
+
* delete — the last moment either exists. An ABSENT snapshot grants: a legacy
|
|
114
|
+
* account predating the consent system still gets counted, which is the
|
|
115
|
+
* standing rule for every server conversion (conversions.js).
|
|
116
|
+
*
|
|
117
|
+
* @param {object} options
|
|
118
|
+
* @param {object} options.Manager - The backend Manager.
|
|
119
|
+
* @param {object} options.ctx - The event context.
|
|
120
|
+
* @param {object} options.user - The deleted Auth UserRecord.
|
|
121
|
+
* @param {object} [options.userDoc] - The user doc as it stood before deletion.
|
|
122
|
+
* @returns {void}
|
|
123
|
+
*/
|
|
124
|
+
function trackDelete({ Manager, ctx, user, userDoc }) {
|
|
125
|
+
try {
|
|
126
|
+
deliverConversion({
|
|
127
|
+
event: 'user_delete',
|
|
128
|
+
attribution: buildAttributionContext(userDoc?.attribution),
|
|
129
|
+
// The doc as it stood, through the ONE match reader: a deletion is an
|
|
130
|
+
// exclusion audience, and an exclusion nobody can be matched to excludes
|
|
131
|
+
// nobody ([#577](https://github.com/Omega-JS-Stack/omega/issues/577)).
|
|
132
|
+
identity: buildIdentity({ uid: user.uid, user: userDoc, email: user.email, telephone: user.phoneNumber }),
|
|
133
|
+
trackingConsent: userDoc?.trackingConsent,
|
|
134
|
+
eventId: `user_delete.${user.uid}`,
|
|
135
|
+
ctx: ctx,
|
|
136
|
+
Manager: Manager,
|
|
137
|
+
});
|
|
138
|
+
} catch (e) {
|
|
139
|
+
ctx.error(`onDelete: user_delete tracking failed for ${user.uid}:`, e);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const jetpack = require('fs-jetpack');
|
|
2
|
+
|
|
3
|
+
const MAX_RETRIES = 3;
|
|
4
|
+
const RETRY_DELAY_MS = 1000;
|
|
5
|
+
const DEFAULT_MAX_SIGNUPS_PER_DAY = 2;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the per-IP daily signup cap the beforeUserCreated guard enforces.
|
|
9
|
+
*
|
|
10
|
+
* Config home: targets.backend.auth.signup.maxPerIpPerDay, which the config
|
|
11
|
+
* loader overlays at the top level like every other target key. The value is a
|
|
12
|
+
* positive integer (@omega.js/config hard-fails anything else), so a value that
|
|
13
|
+
* still arrives broken keeps the framework default instead of leaving the guard
|
|
14
|
+
* running unprotected.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} config - The resolved config (Manager.config).
|
|
17
|
+
* @returns {number} Signups allowed per client IP per day.
|
|
18
|
+
*/
|
|
19
|
+
function resolveSignupLimit(config) {
|
|
20
|
+
const limit = config?.auth?.signup?.maxPerIpPerDay;
|
|
21
|
+
|
|
22
|
+
return Number.isInteger(limit) && limit > 0 ? limit : DEFAULT_MAX_SIGNUPS_PER_DAY;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Retry a function up to maxRetries times with exponential backoff
|
|
27
|
+
*/
|
|
28
|
+
async function retryWrite(ctx, tag, fn) {
|
|
29
|
+
let lastError;
|
|
30
|
+
|
|
31
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
await fn();
|
|
34
|
+
return; // Success
|
|
35
|
+
} catch (error) {
|
|
36
|
+
lastError = error;
|
|
37
|
+
ctx.error(`${tag}: Write attempt ${attempt}/${MAX_RETRIES} failed:`, error);
|
|
38
|
+
|
|
39
|
+
if (attempt < MAX_RETRIES) {
|
|
40
|
+
const delay = RETRY_DELAY_MS * Math.pow(2, attempt - 1); // Exponential backoff: 1s, 2s, 4s
|
|
41
|
+
ctx.log(`${tag}: Retrying in ${delay}ms...`);
|
|
42
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
throw lastError; // All retries failed
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Run consumer auth hooks from hooks/auth/{eventName}.js
|
|
52
|
+
*
|
|
53
|
+
* Similar to how cron discovers hooks at hooks/cron/{schedule}/*.js,
|
|
54
|
+
* auth hooks are discovered at hooks/auth/{eventName}.js in the consumer project.
|
|
55
|
+
*
|
|
56
|
+
* For blocking functions (before-create, before-signin):
|
|
57
|
+
* - Hook can throw HttpsError to block the operation
|
|
58
|
+
* - Hook runs AFTER @omega.js/backend's core checks (disposable email, rate limiting, etc.)
|
|
59
|
+
*
|
|
60
|
+
* For trigger functions (on-create, on-delete):
|
|
61
|
+
* - Hook errors are logged but don't block the operation
|
|
62
|
+
*
|
|
63
|
+
* Hook signature:
|
|
64
|
+
* module.exports = async ({ Manager, ctx, user, context, libraries }) => { ... }
|
|
65
|
+
*
|
|
66
|
+
* Consumer project structure:
|
|
67
|
+
* functions/
|
|
68
|
+
* hooks/
|
|
69
|
+
* auth/
|
|
70
|
+
* before-create.js — runs after @omega.js/backend checks, can block signup
|
|
71
|
+
* before-signin.js — runs after @omega.js/backend signin logic, can block signin
|
|
72
|
+
* on-create.js — runs after @omega.js/backend creates user doc
|
|
73
|
+
* on-delete.js — runs after @omega.js/backend deletes user doc
|
|
74
|
+
*/
|
|
75
|
+
async function runAuthHook(eventName, args) {
|
|
76
|
+
const { Manager, ctx } = args;
|
|
77
|
+
const hookPath = `${Manager.cwd}/hooks/auth/${eventName}.js`;
|
|
78
|
+
|
|
79
|
+
// Check if hook file exists
|
|
80
|
+
if (!jetpack.exists(hookPath)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
ctx.log(`${eventName}: Running consumer hook @ ${hookPath}`);
|
|
85
|
+
|
|
86
|
+
// Load and execute — passes the same args object the @omega.js/backend handler received
|
|
87
|
+
const hook = require(hookPath);
|
|
88
|
+
await hook(args);
|
|
89
|
+
|
|
90
|
+
ctx.log(`${eventName}: Consumer hook completed`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { retryWrite, runAuthHook, resolveSignupLimit, MAX_RETRIES, DEFAULT_MAX_SIGNUPS_PER_DAY };
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blog Auto Publisher — daily cron job.
|
|
3
|
+
*
|
|
4
|
+
* Generates and publishes blog posts using a provider-based article engine
|
|
5
|
+
* (default: Ghostii). Iterates `config.blog.content[]` entries, each defining
|
|
6
|
+
* a source pool (generic topics, URLs, text prompts, RSS/Atom feeds, or parent
|
|
7
|
+
* server sources) and per-entry overrides for the provider API params.
|
|
8
|
+
*
|
|
9
|
+
* Source types:
|
|
10
|
+
* '$brand' — generic brand-topic generation
|
|
11
|
+
* '$feed:<url>' — RSS/Atom/JSON feed: pick one unprocessed article per run
|
|
12
|
+
* '$parent' — fetch sources from parent server's source pool (without claiming)
|
|
13
|
+
* 'https://...' — fetch URL content as prompt seed
|
|
14
|
+
* '<text>' — use directly as prompt seed
|
|
15
|
+
*
|
|
16
|
+
* Source picking, fallback hierarchy, Firestore dedup, and tracking live in
|
|
17
|
+
* the shared source-resolver library — the SAME resolution the newsletter
|
|
18
|
+
* generator uses. Per article, ONE random source is picked from the pool;
|
|
19
|
+
* failures follow the type hierarchy ($feed → other feeds → $parent; $parent
|
|
20
|
+
* → other parent items; NOTHING falls back to $brand).
|
|
21
|
+
*/
|
|
22
|
+
const powertools = require('node-powertools');
|
|
23
|
+
const moment = require('moment');
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
PROMPT_SOURCE,
|
|
27
|
+
PROMPT,
|
|
28
|
+
resolveSources,
|
|
29
|
+
trackContentSource,
|
|
30
|
+
getRecentTitles,
|
|
31
|
+
} = require('../../../libraries/content/source-resolver.js');
|
|
32
|
+
|
|
33
|
+
let postId;
|
|
34
|
+
|
|
35
|
+
module.exports = async ({ Manager, ctx, context, libraries }) => {
|
|
36
|
+
// External boundary (live feed fetches + AI generation + publishing) — the
|
|
37
|
+
// cron entry gates itself like every other external call. Ungated, a normal
|
|
38
|
+
// test run harvests real feeds from the consumer's blog config, delaying the
|
|
39
|
+
// serial omega_cronDaily sequence past the usage suite's reset-usage deadline.
|
|
40
|
+
if (ctx.isTesting() && !process.env.TEST_EXTENDED_MODE) {
|
|
41
|
+
ctx.log('Blog auto-publisher skipped (test mode without TEST_EXTENDED_MODE)');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!Manager.config.blog?.enabled) {
|
|
46
|
+
ctx.log('Blog auto-publisher disabled in config');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ctx.log('Starting...');
|
|
51
|
+
|
|
52
|
+
postId = moment().unix();
|
|
53
|
+
|
|
54
|
+
const brandConfig = buildBrandConfig(Manager.config);
|
|
55
|
+
ctx.log('Brand config', brandConfig);
|
|
56
|
+
|
|
57
|
+
const blog = Manager.config.blog;
|
|
58
|
+
const contentArray = powertools.arrayify(blog.content);
|
|
59
|
+
const { admin } = libraries;
|
|
60
|
+
|
|
61
|
+
const providerName = Object.keys(blog.providers || {}).find((key) => blog.providers[key]) || 'ghostii';
|
|
62
|
+
const provider = require(`../../../libraries/content/${providerName}.js`);
|
|
63
|
+
|
|
64
|
+
for (const entry of contentArray) {
|
|
65
|
+
entry.quantity = entry.quantity || 0;
|
|
66
|
+
entry.sources = entry.sources || [];
|
|
67
|
+
entry.links = randomize(entry.links || []);
|
|
68
|
+
entry.instructions = entry.instructions || '';
|
|
69
|
+
entry.tone = entry.tone || 'professional';
|
|
70
|
+
entry.categories = entry.categories || [];
|
|
71
|
+
entry.keywords = entry.keywords || [];
|
|
72
|
+
entry.chance = entry.chance || 1.0;
|
|
73
|
+
entry.author = entry.author || undefined;
|
|
74
|
+
entry.postPath = entry.postPath || providerName;
|
|
75
|
+
entry.overrides = entry.overrides || {};
|
|
76
|
+
|
|
77
|
+
if (entry.brand && entry.brandUrl) {
|
|
78
|
+
entry.brand = await fetchRemoteBrand(entry.brandUrl).catch((e) => e);
|
|
79
|
+
if (entry.brand instanceof Error) {
|
|
80
|
+
ctx.error('Error fetching remote brand data', entry.brand);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
entry.brand = brandConfig;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ctx.log(`Entry (brand=${entry.brand.brand.id})`, entry);
|
|
88
|
+
|
|
89
|
+
if (!entry.quantity || !entry.sources.length) {
|
|
90
|
+
ctx.log('Quitting because quantity is 0 or no sources');
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const chance = Math.random();
|
|
95
|
+
if (chance > entry.chance) {
|
|
96
|
+
ctx.log(`Quitting because the chance is not met (${chance} <= ${entry.chance})`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const result = await harvest(ctx, entry, admin, provider, Manager).catch((e) => e);
|
|
101
|
+
if (result instanceof Error) {
|
|
102
|
+
throw result;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
ctx.log('Finished!', result);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
function buildBrandConfig(config) {
|
|
110
|
+
const { buildPublicConfig } = require(require('path').join(__dirname, '..', '..', '..', 'routes', 'brand', 'get.js'));
|
|
111
|
+
return buildPublicConfig(config);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function fetchRemoteBrand(brandUrl) {
|
|
115
|
+
const fetch = require('wonderful-fetch');
|
|
116
|
+
return fetch(`${brandUrl}/omega/brand`, {
|
|
117
|
+
timeout: 120000,
|
|
118
|
+
tries: 3,
|
|
119
|
+
response: 'json',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function harvest(ctx, entry, admin, provider, Manager) {
|
|
124
|
+
ctx.log(`harvest(): Starting ${entry.brand.brand.id}...`);
|
|
125
|
+
|
|
126
|
+
const recentTitles = admin
|
|
127
|
+
? await getRecentTitles(admin, entry.brand.brand.id).catch((e) => {
|
|
128
|
+
ctx.error('harvest(): Error fetching recent titles (continuing)', e);
|
|
129
|
+
return [];
|
|
130
|
+
})
|
|
131
|
+
: [];
|
|
132
|
+
const runTitles = [];
|
|
133
|
+
|
|
134
|
+
if (recentTitles.length) {
|
|
135
|
+
ctx.log(`harvest(): ${recentTitles.length} recent titles loaded for topic dedup`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (let index = 0; index < entry.quantity; index++) {
|
|
139
|
+
ctx.log(`harvest(): Processing ${index + 1}/${entry.quantity}`);
|
|
140
|
+
|
|
141
|
+
const allKnownTitles = [...recentTitles, ...runTitles];
|
|
142
|
+
|
|
143
|
+
// ONE random source per article — fallback hierarchy handled by the resolver.
|
|
144
|
+
// Tracking between iterations means the next resolve sees this run's usage.
|
|
145
|
+
const [source] = await resolveSources({
|
|
146
|
+
sources: entry.sources,
|
|
147
|
+
count: 1,
|
|
148
|
+
categories: entry.categories,
|
|
149
|
+
admin,
|
|
150
|
+
Manager,
|
|
151
|
+
ctx,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!source) {
|
|
155
|
+
ctx.log('harvest(): No source could be resolved for this article, skipping');
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const resolved = buildPromptFromSource(source, entry);
|
|
160
|
+
|
|
161
|
+
if (allKnownTitles.length) {
|
|
162
|
+
resolved.description += `\n\nTOPIC DEDUPLICATION (STRICT):\n`
|
|
163
|
+
+ `These articles were RECENTLY published on our blog. You MUST NOT write about the same topic, theme, or subject area as ANY of them.\n`
|
|
164
|
+
+ `Do NOT cover the same story from a different angle, do NOT write about the same theme with different examples, `
|
|
165
|
+
+ `and do NOT reuse the same primary keyword/category combination. `
|
|
166
|
+
+ `If a recent article covers "lifestyle tech + habits", do NOT write about "lifestyle tech + policy" — that is the SAME theme. `
|
|
167
|
+
+ `Pick an entirely different domain.\n`
|
|
168
|
+
+ `Recent articles:\n${allKnownTitles.slice(0, 25).map((t) => `- ${t}`).join('\n')}`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
ctx.log('harvest(): Resolved source', { type: source.type, title: source.title, url: source.url });
|
|
172
|
+
|
|
173
|
+
const overrides = { ...entry.overrides };
|
|
174
|
+
if (!overrides.keywords && entry.keywords.length) {
|
|
175
|
+
overrides.keywords = entry.keywords;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const article = await provider.writeArticle({
|
|
179
|
+
brand: entry.brand,
|
|
180
|
+
description: resolved.description,
|
|
181
|
+
links: entry.links,
|
|
182
|
+
sourceContent: resolved.sourceContent || '',
|
|
183
|
+
overrides: overrides,
|
|
184
|
+
}).catch((e) => e);
|
|
185
|
+
if (article instanceof Error) {
|
|
186
|
+
ctx.error('harvest(): Error requesting article from provider', article);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ctx.log('harvest(): Article', article);
|
|
191
|
+
|
|
192
|
+
const post = provider.blocksToPost?.(article.json);
|
|
193
|
+
const generatedTitle = post?.title || article.title || '';
|
|
194
|
+
|
|
195
|
+
const publishArgs = {
|
|
196
|
+
brand: entry.brand,
|
|
197
|
+
article,
|
|
198
|
+
id: postId++,
|
|
199
|
+
author: entry.author,
|
|
200
|
+
postPath: entry.postPath,
|
|
201
|
+
source: source.trackingData?.url || null,
|
|
202
|
+
};
|
|
203
|
+
ctx.log('harvest(): publishArgs', publishArgs);
|
|
204
|
+
|
|
205
|
+
const uploadedPost = await provider.publishArticle(ctx, publishArgs).catch((e) => e);
|
|
206
|
+
if (uploadedPost instanceof Error) {
|
|
207
|
+
ctx.error('harvest(): Error uploading post to blog', uploadedPost);
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
ctx.log('harvest(): Uploaded post', uploadedPost);
|
|
212
|
+
|
|
213
|
+
if (generatedTitle) {
|
|
214
|
+
runTitles.push(generatedTitle);
|
|
215
|
+
}
|
|
216
|
+
if (source.trackingData?.itemTitle) {
|
|
217
|
+
runTitles.push(source.trackingData.itemTitle);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Mark the source used ONLY now that the article actually published.
|
|
221
|
+
// $brand/url/text picks have no trackingData — synthesize one for $brand
|
|
222
|
+
// so recent-title dedup still sees the post.
|
|
223
|
+
const trackingData = source.trackingData || {
|
|
224
|
+
url: uploadedPost.slug || `brand-${postId}`,
|
|
225
|
+
origin: '$brand',
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
if (admin) {
|
|
229
|
+
await trackContentSource(admin, {
|
|
230
|
+
...trackingData,
|
|
231
|
+
usedBy: 'blog',
|
|
232
|
+
brandId: entry.brand.brand.id,
|
|
233
|
+
postUrl: uploadedPost.url,
|
|
234
|
+
postSlug: uploadedPost.slug,
|
|
235
|
+
postTitle: generatedTitle || null,
|
|
236
|
+
}).catch((e) => {
|
|
237
|
+
ctx.error('harvest(): Error tracking content source (non-fatal)', e);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Map a resolved source to the provider prompt shape.
|
|
245
|
+
* feed/parent sources rewrite an existing article (PROMPT_SOURCE);
|
|
246
|
+
* brand/url/text sources seed a fresh topic (PROMPT).
|
|
247
|
+
*
|
|
248
|
+
* @param {object} source - resolved source from resolveSources()
|
|
249
|
+
* @param {object} entry - the blog content entry
|
|
250
|
+
* @returns {{ description: string, sourceContent: string }}
|
|
251
|
+
*/
|
|
252
|
+
function buildPromptFromSource(source, entry) {
|
|
253
|
+
const templateVars = {
|
|
254
|
+
...entry,
|
|
255
|
+
instructions: entry.instructions,
|
|
256
|
+
date: moment().format('MMMM YYYY'),
|
|
257
|
+
tone: entry.tone || '',
|
|
258
|
+
categories: (entry.categories || []).join(', '),
|
|
259
|
+
keywords: (entry.keywords || []).join(', '),
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
if (source.type === 'feed' || source.type === 'parent') {
|
|
263
|
+
return {
|
|
264
|
+
description: powertools.template(PROMPT_SOURCE, {
|
|
265
|
+
...templateVars,
|
|
266
|
+
sourceTitle: source.title,
|
|
267
|
+
}),
|
|
268
|
+
sourceContent: source.content || '',
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const suggestion = source.type === 'brand'
|
|
273
|
+
? 'Write an article about any topic that would be relevant to our website and business (it does not have to be about our company, but it can be)'
|
|
274
|
+
: source.content;
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
description: powertools.template(PROMPT, {
|
|
278
|
+
...templateVars,
|
|
279
|
+
suggestion: suggestion,
|
|
280
|
+
}),
|
|
281
|
+
sourceContent: '',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function randomize(array) {
|
|
286
|
+
return array.sort(() => Math.random() - 0.5);
|
|
287
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data requests cron job
|
|
3
|
+
*
|
|
4
|
+
* Processes data request status transitions:
|
|
5
|
+
* - pending → completed: 14 days after creation
|
|
6
|
+
* - completed → expired: 30 days after becoming completed (44 days after creation)
|
|
7
|
+
*
|
|
8
|
+
* Scans the entire collection (no index required) since data-requests is small.
|
|
9
|
+
*/
|
|
10
|
+
module.exports = async ({ Manager, ctx, context, libraries }) => {
|
|
11
|
+
const { admin } = libraries;
|
|
12
|
+
const nowUNIX = Math.round(Date.now() / 1000);
|
|
13
|
+
|
|
14
|
+
const FOURTEEN_DAYS = 14 * 24 * 60 * 60;
|
|
15
|
+
const FORTY_FOUR_DAYS = 44 * 24 * 60 * 60;
|
|
16
|
+
|
|
17
|
+
ctx.log('Starting...');
|
|
18
|
+
|
|
19
|
+
// Only fetch requests created within the last 45 days (single-field filter, no composite index needed)
|
|
20
|
+
const snapshot = await admin.firestore()
|
|
21
|
+
.collection('data-requests')
|
|
22
|
+
.where('metadata.created.timestampUNIX', '>', nowUNIX - FORTY_FOUR_DAYS - 86400)
|
|
23
|
+
.get();
|
|
24
|
+
|
|
25
|
+
ctx.log(`Found ${snapshot.size} total data requests`);
|
|
26
|
+
|
|
27
|
+
let completed = 0;
|
|
28
|
+
let expired = 0;
|
|
29
|
+
|
|
30
|
+
for (const doc of snapshot.docs) {
|
|
31
|
+
const data = doc.data();
|
|
32
|
+
const createdUNIX = data.metadata?.created?.timestampUNIX || 0;
|
|
33
|
+
const age = nowUNIX - createdUNIX;
|
|
34
|
+
|
|
35
|
+
if (data.status === 'pending' && age >= FOURTEEN_DAYS) {
|
|
36
|
+
await doc.ref.update({ status: 'completed' })
|
|
37
|
+
.then(() => {
|
|
38
|
+
completed++;
|
|
39
|
+
ctx.log(`Completed request ${doc.id} (age: ${Math.round(age / 86400)}d)`);
|
|
40
|
+
})
|
|
41
|
+
.catch((e) => {
|
|
42
|
+
ctx.error(`Failed to complete request ${doc.id}: ${e.message}`);
|
|
43
|
+
});
|
|
44
|
+
} else if (data.status === 'completed' && age >= FORTY_FOUR_DAYS) {
|
|
45
|
+
await doc.ref.update({ status: 'expired' })
|
|
46
|
+
.then(() => {
|
|
47
|
+
expired++;
|
|
48
|
+
ctx.log(`Expired request ${doc.id} (age: ${Math.round(age / 86400)}d)`);
|
|
49
|
+
})
|
|
50
|
+
.catch((e) => {
|
|
51
|
+
ctx.error(`Failed to expire request ${doc.id}: ${e.message}`);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ctx.log(`Completed! (${completed} completed, ${expired} expired)`);
|
|
57
|
+
};
|