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