@omega.js/manager 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 (416) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/LICENSE +98 -0
  3. package/README.md +165 -0
  4. package/bin/omega +2 -0
  5. package/bin/omg +2 -0
  6. package/claude-plugin/.claude-plugin/plugin.json +11 -0
  7. package/claude-plugin/.mcp.json +9 -0
  8. package/claude-plugin/README.md +139 -0
  9. package/claude-plugin/hooks/gate/mark.sh +58 -0
  10. package/claude-plugin/hooks/gate/run.sh +97 -0
  11. package/claude-plugin/hooks/guard/run.sh +249 -0
  12. package/claude-plugin/hooks/hooks.json +63 -0
  13. package/claude-plugin/hooks/inject/run.sh +127 -0
  14. package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
  15. package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
  16. package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
  17. package/claude-plugin/hooks/quality/run.sh +132 -0
  18. package/claude-plugin/hooks/shape/run.sh +45 -0
  19. package/claude-plugin/mcp-router-launch.js +29 -0
  20. package/claude-plugin/skills/README.md +48 -0
  21. package/claude-plugin/skills/accessibility/SKILL.md +31 -0
  22. package/claude-plugin/skills/analytics/SKILL.md +30 -0
  23. package/claude-plugin/skills/backend/SKILL.md +25 -0
  24. package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
  25. package/claude-plugin/skills/browser/SKILL.md +64 -0
  26. package/claude-plugin/skills/client/SKILL.md +24 -0
  27. package/claude-plugin/skills/desktop/SKILL.md +25 -0
  28. package/claude-plugin/skills/extension/SKILL.md +25 -0
  29. package/claude-plugin/skills/main/SKILL.md +54 -0
  30. package/claude-plugin/skills/manager/SKILL.md +25 -0
  31. package/claude-plugin/skills/seo/SKILL.md +36 -0
  32. package/claude-plugin/skills/theme/SKILL.md +33 -0
  33. package/claude-plugin/skills/web/SKILL.md +29 -0
  34. package/dist/cli-run.js +34 -0
  35. package/dist/cli.js +29 -0
  36. package/dist/commands/build.js +17 -0
  37. package/dist/commands/clean.js +16 -0
  38. package/dist/commands/company.js +46 -0
  39. package/dist/commands/deploy.js +143 -0
  40. package/dist/commands/dev.js +437 -0
  41. package/dist/commands/devlog.js +25 -0
  42. package/dist/commands/help.js +48 -0
  43. package/dist/commands/manage.js +53 -0
  44. package/dist/commands/migrate.js +76 -0
  45. package/dist/commands/onboard.js +31 -0
  46. package/dist/commands/pipeline.js +319 -0
  47. package/dist/commands/test.js +380 -0
  48. package/dist/commands/update.js +128 -0
  49. package/dist/commands/version.js +8 -0
  50. package/dist/company-init.js +167 -0
  51. package/dist/company.js +283 -0
  52. package/dist/config.js +1359 -0
  53. package/dist/devlog/index.js +226 -0
  54. package/dist/devlog/lib/collect-commits.js +136 -0
  55. package/dist/devlog/lib/generate-post.js +201 -0
  56. package/dist/devlog/lib/ghostii.js +122 -0
  57. package/dist/devlog/lib/project-map.js +98 -0
  58. package/dist/devlog/lib/publish-website.js +88 -0
  59. package/dist/index.js +45 -0
  60. package/dist/lib/agents-md.js +201 -0
  61. package/dist/lib/analytics-secret.js +22 -0
  62. package/dist/lib/argv.js +21 -0
  63. package/dist/lib/auth-admin.js +120 -0
  64. package/dist/lib/automation-client.js +210 -0
  65. package/dist/lib/backend-marketing.js +49 -0
  66. package/dist/lib/brand.js +240 -0
  67. package/dist/lib/bundle-id.js +53 -0
  68. package/dist/lib/claude-settings.js +125 -0
  69. package/dist/lib/company-scaffold.js +213 -0
  70. package/dist/lib/company.js +227 -0
  71. package/dist/lib/config-flow.js +350 -0
  72. package/dist/lib/config-write.js +41 -0
  73. package/dist/lib/custom-target.js +75 -0
  74. package/dist/lib/domain-utils.js +19 -0
  75. package/dist/lib/duration.js +39 -0
  76. package/dist/lib/env-order.js +236 -0
  77. package/dist/lib/env-secret.js +78 -0
  78. package/dist/lib/firestore-rest.js +326 -0
  79. package/dist/lib/framework-bin.js +156 -0
  80. package/dist/lib/gitignore.js +63 -0
  81. package/dist/lib/google-auth.js +495 -0
  82. package/dist/lib/google-token.js +66 -0
  83. package/dist/lib/jwt.js +31 -0
  84. package/dist/lib/legacy-oauth.js +59 -0
  85. package/dist/lib/node-version.js +127 -0
  86. package/dist/lib/owner-plan.js +78 -0
  87. package/dist/lib/package-scripts.js +152 -0
  88. package/dist/lib/preflight.js +470 -0
  89. package/dist/lib/product-create.js +144 -0
  90. package/dist/lib/run-command.js +74 -0
  91. package/dist/lib/run-gates.js +70 -0
  92. package/dist/lib/run-output.js +42 -0
  93. package/dist/lib/run-summary.js +384 -0
  94. package/dist/lib/scaffold.js +427 -0
  95. package/dist/lib/service-input.js +207 -0
  96. package/dist/lib/service-runner.js +466 -0
  97. package/dist/lib/stale.js +24 -0
  98. package/dist/lib/target-selection.js +155 -0
  99. package/dist/lib/verb-fanout.js +128 -0
  100. package/dist/lib/verify-live.js +188 -0
  101. package/dist/manage.js +311 -0
  102. package/dist/omega-bin.js +7 -0
  103. package/dist/onboard.js +532 -0
  104. package/dist/services/account/ensure/users.js +259 -0
  105. package/dist/services/account/index.js +97 -0
  106. package/dist/services/account/lib/backend-client.js +107 -0
  107. package/dist/services/account/lib/password.js +36 -0
  108. package/dist/services/account/lib/resolve-password.js +100 -0
  109. package/dist/services/advertising/ensure/sites.js +101 -0
  110. package/dist/services/advertising/index.js +101 -0
  111. package/dist/services/advertising/lib/adsense-api.js +41 -0
  112. package/dist/services/ai/ensure/keys.js +21 -0
  113. package/dist/services/ai/index.js +36 -0
  114. package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
  115. package/dist/services/analytics/ensure/google-streams.js +256 -0
  116. package/dist/services/analytics/ensure/meta-pixel.js +22 -0
  117. package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
  118. package/dist/services/analytics/index.js +134 -0
  119. package/dist/services/analytics/lib/analytics-api.js +156 -0
  120. package/dist/services/analytics/lib/meta-api.js +83 -0
  121. package/dist/services/analytics/lib/pixel-account.js +78 -0
  122. package/dist/services/analytics/lib/pixel-provision.js +152 -0
  123. package/dist/services/analytics/lib/pixel-specs.js +57 -0
  124. package/dist/services/analytics/lib/pixel-token.js +88 -0
  125. package/dist/services/analytics/lib/property-flow.js +77 -0
  126. package/dist/services/analytics/lib/tiktok-api.js +157 -0
  127. package/dist/services/analytics/lib/tiktok-auth.js +153 -0
  128. package/dist/services/assets/ensure/logo-gen.js +68 -0
  129. package/dist/services/assets/index.js +109 -0
  130. package/dist/services/assets/lib/assets-config.js +168 -0
  131. package/dist/services/assets/lib/brandmark-api.js +160 -0
  132. package/dist/services/assets/lib/derived.js +113 -0
  133. package/dist/services/assets/lib/font-loader.js +67 -0
  134. package/dist/services/assets/lib/reconcile.js +122 -0
  135. package/dist/services/assets/lib/reset.js +118 -0
  136. package/dist/services/assets/lib/svg-logo-generator.js +154 -0
  137. package/dist/services/assets/lib/svg-to-black.js +32 -0
  138. package/dist/services/assets/write/favicons.js +82 -0
  139. package/dist/services/assets/write/icons.js +64 -0
  140. package/dist/services/assets/write/process.js +96 -0
  141. package/dist/services/assets/write/reconcile.js +30 -0
  142. package/dist/services/assets/write/social-icons.js +108 -0
  143. package/dist/services/assets/write/templates.js +345 -0
  144. package/dist/services/bookmark/ensure/sync.js +255 -0
  145. package/dist/services/bookmark/index.js +17 -0
  146. package/dist/services/campaigns/ensure/contact-person.js +40 -0
  147. package/dist/services/campaigns/ensure/custom-fields.js +84 -0
  148. package/dist/services/campaigns/ensure/domain-auth.js +92 -0
  149. package/dist/services/campaigns/ensure/event-webhook.js +89 -0
  150. package/dist/services/campaigns/ensure/link-branding.js +187 -0
  151. package/dist/services/campaigns/ensure/list.js +50 -0
  152. package/dist/services/campaigns/ensure/segments.js +109 -0
  153. package/dist/services/campaigns/ensure/sender-identity.js +153 -0
  154. package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
  155. package/dist/services/campaigns/index.js +79 -0
  156. package/dist/services/campaigns/lib/dns-sync.js +81 -0
  157. package/dist/services/campaigns/lib/segment-query.js +138 -0
  158. package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
  159. package/dist/services/captcha/ensure/site-key.js +83 -0
  160. package/dist/services/captcha/index.js +78 -0
  161. package/dist/services/captcha/lib/console-url.js +45 -0
  162. package/dist/services/captcha/lib/recaptcha-api.js +36 -0
  163. package/dist/services/certificates/ensure/api-key.js +22 -0
  164. package/dist/services/certificates/ensure/bundle-ids.js +115 -0
  165. package/dist/services/certificates/ensure/certificates.js +187 -0
  166. package/dist/services/certificates/ensure/profiles.js +143 -0
  167. package/dist/services/certificates/index.js +225 -0
  168. package/dist/services/certificates/lib/apple-api.js +183 -0
  169. package/dist/services/certificates/lib/certificate-manager.js +252 -0
  170. package/dist/services/certificates/lib/identifier-manager.js +107 -0
  171. package/dist/services/certificates/lib/keychain.js +135 -0
  172. package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
  173. package/dist/services/certificates/lib/profile-manager.js +115 -0
  174. package/dist/services/chat/data/baseline-knowledge.md +96 -0
  175. package/dist/services/chat/ensure/chat.js +106 -0
  176. package/dist/services/chat/ensure/user.js +45 -0
  177. package/dist/services/chat/index.js +139 -0
  178. package/dist/services/chat/lib/baseline-knowledge.js +137 -0
  179. package/dist/services/cloud/ensure/authentication.js +267 -0
  180. package/dist/services/cloud/ensure/billing.js +120 -0
  181. package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
  182. package/dist/services/cloud/ensure/database.js +60 -0
  183. package/dist/services/cloud/ensure/firestore.js +79 -0
  184. package/dist/services/cloud/ensure/functions.js +49 -0
  185. package/dist/services/cloud/ensure/hosting.js +398 -0
  186. package/dist/services/cloud/ensure/oauth-consent.js +248 -0
  187. package/dist/services/cloud/ensure/project-settings.js +72 -0
  188. package/dist/services/cloud/ensure/sdk-config.js +95 -0
  189. package/dist/services/cloud/ensure/service-account.js +152 -0
  190. package/dist/services/cloud/ensure/services.js +103 -0
  191. package/dist/services/cloud/ensure/storage.js +47 -0
  192. package/dist/services/cloud/index.js +130 -0
  193. package/dist/services/cloud/lib/access-heal.js +130 -0
  194. package/dist/services/cloud/lib/firebase-api.js +662 -0
  195. package/dist/services/cloud/lib/project-flow.js +102 -0
  196. package/dist/services/directory/ensure/entry.js +48 -0
  197. package/dist/services/directory/index.js +64 -0
  198. package/dist/services/directory/lib/blocks.js +104 -0
  199. package/dist/services/disperse/index.js +45 -0
  200. package/dist/services/disperse/write/certs.js +117 -0
  201. package/dist/services/domain/ensure/nameservers.js +179 -0
  202. package/dist/services/domain/index.js +69 -0
  203. package/dist/services/domain/lib/namecheap-api.js +167 -0
  204. package/dist/services/domain/lib/registrars.js +46 -0
  205. package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
  206. package/dist/services/edge/ensure/cache-rules.js +105 -0
  207. package/dist/services/edge/ensure/dns-records.js +304 -0
  208. package/dist/services/edge/ensure/email-routing.js +292 -0
  209. package/dist/services/edge/ensure/rules-configuration.js +98 -0
  210. package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
  211. package/dist/services/edge/ensure/rules-redirect.js +107 -0
  212. package/dist/services/edge/ensure/rules-response-headers.js +90 -0
  213. package/dist/services/edge/ensure/rules-security.js +142 -0
  214. package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
  215. package/dist/services/edge/ensure/workers.js +219 -0
  216. package/dist/services/edge/ensure/zone-settings.js +108 -0
  217. package/dist/services/edge/ensure/zone.js +183 -0
  218. package/dist/services/edge/index.js +73 -0
  219. package/dist/services/edge/lib/cloudflare-api.js +84 -0
  220. package/dist/services/edge/lib/dns-records-helpers.js +518 -0
  221. package/dist/services/edge/lib/read-cache.js +16 -0
  222. package/dist/services/edge/lib/ruleset-helper.js +108 -0
  223. package/dist/services/edge/workers/omega-api-proxy.js +43 -0
  224. package/dist/services/email/data/baseline-filter.md +4 -0
  225. package/dist/services/email/data/baseline-knowledge.md +86 -0
  226. package/dist/services/email/ensure/agent.js +107 -0
  227. package/dist/services/email/ensure/user.js +45 -0
  228. package/dist/services/email/index.js +138 -0
  229. package/dist/services/email/lib/baseline.js +82 -0
  230. package/dist/services/email/lib/knowledge-file.js +53 -0
  231. package/dist/services/forms/ensure/form.js +46 -0
  232. package/dist/services/forms/ensure/user.js +45 -0
  233. package/dist/services/forms/index.js +138 -0
  234. package/dist/services/migrations/ensure/notifications.js +189 -0
  235. package/dist/services/migrations/ensure/orders.js +34 -0
  236. package/dist/services/migrations/ensure/payment-provider.js +132 -0
  237. package/dist/services/migrations/ensure/payments-intents.js +34 -0
  238. package/dist/services/migrations/ensure/state-retirement.js +266 -0
  239. package/dist/services/migrations/ensure/targets-rename.js +124 -0
  240. package/dist/services/migrations/ensure/users.js +1176 -0
  241. package/dist/services/migrations/index.js +101 -0
  242. package/dist/services/migrations/lib/attribution-touch.js +64 -0
  243. package/dist/services/migrations/lib/ensure-metadata.js +144 -0
  244. package/dist/services/migrations/lib/migration-runner.js +473 -0
  245. package/dist/services/migrations/lib/sanitize-strings.js +112 -0
  246. package/dist/services/migrations/lib/schema-validator.js +154 -0
  247. package/dist/services/monitoring/ensure/dsn.js +54 -0
  248. package/dist/services/monitoring/ensure/projects.js +135 -0
  249. package/dist/services/monitoring/index.js +54 -0
  250. package/dist/services/monitoring/lib/sentry-api.js +94 -0
  251. package/dist/services/newsletter/ensure/custom-fields.js +90 -0
  252. package/dist/services/newsletter/ensure/publication.js +94 -0
  253. package/dist/services/newsletter/ensure/segments.js +140 -0
  254. package/dist/services/newsletter/ensure/webhook.js +108 -0
  255. package/dist/services/newsletter/index.js +64 -0
  256. package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
  257. package/dist/services/newsletter/lib/segment-automation.js +577 -0
  258. package/dist/services/payment/ensure/chargebee-account.js +30 -0
  259. package/dist/services/payment/ensure/chargebee-products.js +359 -0
  260. package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
  261. package/dist/services/payment/ensure/paypal-account.js +36 -0
  262. package/dist/services/payment/ensure/paypal-products.js +374 -0
  263. package/dist/services/payment/ensure/paypal-webhook.js +128 -0
  264. package/dist/services/payment/ensure/stripe-account.js +93 -0
  265. package/dist/services/payment/ensure/stripe-disputes.js +56 -0
  266. package/dist/services/payment/ensure/stripe-products.js +245 -0
  267. package/dist/services/payment/ensure/stripe-radar.js +74 -0
  268. package/dist/services/payment/ensure/stripe-webhook.js +130 -0
  269. package/dist/services/payment/index.js +163 -0
  270. package/dist/services/payment/lib/chargebee-api.js +338 -0
  271. package/dist/services/payment/lib/payment-utils.js +116 -0
  272. package/dist/services/payment/lib/paypal-api.js +354 -0
  273. package/dist/services/payment/lib/provider-setup.js +134 -0
  274. package/dist/services/payment/lib/stripe-api.js +152 -0
  275. package/dist/services/repo/ensure/org.js +70 -0
  276. package/dist/services/repo/ensure/pages.js +72 -0
  277. package/dist/services/repo/ensure/repo.js +90 -0
  278. package/dist/services/repo/index.js +52 -0
  279. package/dist/services/repo/lib/github-api.js +196 -0
  280. package/dist/services/search/ensure/ga-link.js +57 -0
  281. package/dist/services/search/ensure/property.js +137 -0
  282. package/dist/services/search/ensure/sitemaps.js +70 -0
  283. package/dist/services/search/index.js +61 -0
  284. package/dist/services/search/lib/search-console-api.js +92 -0
  285. package/dist/services/seo/ensure/github-repos.js +271 -0
  286. package/dist/services/seo/index.js +55 -0
  287. package/dist/services/seo/lib/gh-api.js +161 -0
  288. package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
  289. package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
  290. package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
  291. package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
  292. package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
  293. package/dist/services/seo/templates/index.js +57 -0
  294. package/dist/services/server/ensure/brands.js +63 -0
  295. package/dist/services/server/index.js +42 -0
  296. package/dist/services/testing/ensure/target-checks.js +97 -0
  297. package/dist/services/testing/index.js +11 -0
  298. package/dist/services/testing/lib/checks.js +467 -0
  299. package/dist/services/update/index.js +20 -0
  300. package/dist/services/update/lib/cache.js +59 -0
  301. package/dist/services/update/lib/fingerprint.js +157 -0
  302. package/dist/services/update/write/targets.js +206 -0
  303. package/dist/services/workspace/ensure/agents.js +42 -0
  304. package/dist/services/workspace/ensure/claude-settings.js +34 -0
  305. package/dist/services/workspace/ensure/config.js +54 -0
  306. package/dist/services/workspace/ensure/defaults.js +60 -0
  307. package/dist/services/workspace/ensure/env-keys.js +55 -0
  308. package/dist/services/workspace/ensure/env-order.js +66 -0
  309. package/dist/services/workspace/ensure/env-rules.js +97 -0
  310. package/dist/services/workspace/ensure/gitignore.js +18 -0
  311. package/dist/services/workspace/ensure/scripts.js +126 -0
  312. package/dist/services/workspace/ensure/structure.js +97 -0
  313. package/dist/services/workspace/ensure/translation-sdk.js +148 -0
  314. package/dist/services/workspace/ensure/workflows.js +54 -0
  315. package/dist/services/workspace/index.js +8 -0
  316. package/dist/vendor/account/engine.js +182 -0
  317. package/dist/vendor/account/features.js +220 -0
  318. package/dist/vendor/account/index.js +53 -0
  319. package/dist/vendor/account/schema.js +272 -0
  320. package/dist/vendor/account/subscription.js +38 -0
  321. package/dist/vendor/config/company.js +31 -0
  322. package/dist/vendor/config/defaults.js +173 -0
  323. package/dist/vendor/config/demo.js +18 -0
  324. package/dist/vendor/config/desktop-artifacts.js +110 -0
  325. package/dist/vendor/config/edit.js +769 -0
  326. package/dist/vendor/config/env-delivery.js +145 -0
  327. package/dist/vendor/config/env-rules.js +93 -0
  328. package/dist/vendor/config/env-schema.js +1078 -0
  329. package/dist/vendor/config/env.js +445 -0
  330. package/dist/vendor/config/hooks.js +97 -0
  331. package/dist/vendor/config/index.js +237 -0
  332. package/dist/vendor/config/instances.js +208 -0
  333. package/dist/vendor/config/load.js +490 -0
  334. package/dist/vendor/config/merge.js +68 -0
  335. package/dist/vendor/config/order.js +139 -0
  336. package/dist/vendor/config/ports.js +374 -0
  337. package/dist/vendor/config/providers.js +32 -0
  338. package/dist/vendor/config/repo.js +142 -0
  339. package/dist/vendor/config/retired-keys.js +430 -0
  340. package/dist/vendor/config/schema.js +1610 -0
  341. package/dist/vendor/config/secrets.js +50 -0
  342. package/dist/vendor/config/seed.js +34 -0
  343. package/dist/vendor/config/site-global.js +205 -0
  344. package/dist/vendor/config/validate.js +554 -0
  345. package/dist/vendor/config/winback.js +61 -0
  346. package/dist/vendor/devkit/attach-log-file.js +262 -0
  347. package/dist/vendor/devkit/certs.js +199 -0
  348. package/dist/vendor/devkit/ci-workflows.js +520 -0
  349. package/dist/vendor/devkit/cli-router.js +156 -0
  350. package/dist/vendor/devkit/command-path.js +46 -0
  351. package/dist/vendor/devkit/deploy-record.js +180 -0
  352. package/dist/vendor/devkit/flows.js +317 -0
  353. package/dist/vendor/devkit/local-https.js +360 -0
  354. package/dist/vendor/devkit/local.js +1905 -0
  355. package/dist/vendor/devkit/logger.js +128 -0
  356. package/dist/vendor/devkit/omega-bin.js +345 -0
  357. package/dist/vendor/devkit/prompt.js +187 -0
  358. package/dist/vendor/devkit/safe-install.js +18 -0
  359. package/dist/vendor/devkit/stop-signals.js +28 -0
  360. package/dist/vendor/devkit/test/scope.js +162 -0
  361. package/dist/vendor/devkit/translate/cache.js +84 -0
  362. package/dist/vendor/devkit/translate/engine.js +243 -0
  363. package/dist/vendor/devkit/translate/index.js +49 -0
  364. package/dist/vendor/devkit/translate/languages.js +134 -0
  365. package/dist/vendor/devkit/translate/providers.js +188 -0
  366. package/dist/vendor/devkit/update.js +569 -0
  367. package/docs/AGENTS.md +200 -0
  368. package/docs/account.md +45 -0
  369. package/docs/advertising.md +46 -0
  370. package/docs/ai.md +34 -0
  371. package/docs/analytics.md +69 -0
  372. package/docs/assets.md +57 -0
  373. package/docs/bookmark.md +26 -0
  374. package/docs/brand.md +151 -0
  375. package/docs/campaigns.md +96 -0
  376. package/docs/captcha.md +46 -0
  377. package/docs/certificates.md +68 -0
  378. package/docs/chat.md +47 -0
  379. package/docs/cloud.md +110 -0
  380. package/docs/company.md +64 -0
  381. package/docs/directory.md +140 -0
  382. package/docs/disperse.md +46 -0
  383. package/docs/domain.md +56 -0
  384. package/docs/edge.md +234 -0
  385. package/docs/email.md +42 -0
  386. package/docs/forms.md +48 -0
  387. package/docs/index.md +109 -0
  388. package/docs/migration.md +203 -0
  389. package/docs/migrations.md +56 -0
  390. package/docs/monitoring.md +41 -0
  391. package/docs/newsletter.md +48 -0
  392. package/docs/payment.md +83 -0
  393. package/docs/repo.md +48 -0
  394. package/docs/search.md +44 -0
  395. package/docs/seo.md +34 -0
  396. package/docs/server.md +37 -0
  397. package/docs/shared/agent-docs.md +89 -0
  398. package/docs/shared/analytics.md +612 -0
  399. package/docs/shared/brands.md +51 -0
  400. package/docs/shared/breaking-changes.md +497 -0
  401. package/docs/shared/config.md +1387 -0
  402. package/docs/shared/deploys.md +215 -0
  403. package/docs/shared/icons.md +201 -0
  404. package/docs/shared/local-dev.md +147 -0
  405. package/docs/shared/logging.md +202 -0
  406. package/docs/shared/monitoring.md +153 -0
  407. package/docs/shared/publishing.md +183 -0
  408. package/docs/shared/rulings.md +34 -0
  409. package/docs/shared/testing.md +147 -0
  410. package/docs/shared/theming.md +604 -0
  411. package/docs/shared/translation.md +291 -0
  412. package/docs/shared/updates.md +61 -0
  413. package/docs/testing.md +34 -0
  414. package/docs/update.md +36 -0
  415. package/docs/workspace.md +64 -0
  416. package/package.json +88 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * "How is this run asked to stop?" The ONE list every supervisor registers.
3
+ *
4
+ * A supervisor is any process that owns a child, a watcher or a long-running
5
+ * loop it must unwind before it goes: the backend's emulator and test runner,
6
+ * the manager's `omega dev`, the web dev server, the log tails. Each of them
7
+ * used to hand-type its own subset, and the subsets disagreed. The manager
8
+ * registered SIGINT and SIGTERM only, so a CLOSED TERMINAL (SIGHUP) killed the
9
+ * orchestrator outright and its detached legs, the emulator tree among them,
10
+ * orphaned with their ports ([#629](https://github.com/Omega-JS-Stack/omega/issues/629)).
11
+ *
12
+ * A signal with no listener is not a shutdown: node kills THIS process only,
13
+ * and anything detached below it survives. So all three take the SAME teardown:
14
+ * Ctrl+C (SIGINT), a programmatic stop (a supervisor's own shutdown, `omega
15
+ * dev`'s stop, the journey lane, all SIGTERM), and a closed terminal (SIGHUP).
16
+ *
17
+ * Stdlib-only on purpose: a vendored module must not push a dependency onto
18
+ * its hosts.
19
+ */
20
+
21
+ /**
22
+ * Every way a run is asked to stop.
23
+ *
24
+ * @type {string[]}
25
+ */
26
+ const STOP_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
27
+
28
+ module.exports = { STOP_SIGNALS };
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Test-scope grammar (C5) — ONE parser for `omega test` targets across every
3
+ * framework, so scoping means the same thing in a web app, a backend, a
4
+ * desktop app, and an extension:
5
+ *
6
+ * npx omega test → PROJECT tests only (consumer context)
7
+ * npx omega test pages/ → project tests under pages/
8
+ * npx omega test project:pages/ → same, explicit (`brand:` = alias)
9
+ * npx omega test framework: → the framework's own suite
10
+ * npx omega test framework:routes/ → framework suite, scoped
11
+ * npx omega test full: → both sources
12
+ * npx omega test full:auth → both sources, path-scoped
13
+ *
14
+ * `omega:` and `mgr:` are universal framework aliases; each framework also
15
+ * answers to its own id (`backend:`, `desktop:`, `extension:`, `web:`) via
16
+ * `frameworkAliases`. Bare paths bind to the PROJECT source — reaching the
17
+ * framework suite is always an explicit choice (Ian 2026-07-11: bare runs
18
+ * from a brand must never drag the framework corpus in).
19
+ *
20
+ * Framework SELF context (running inside the framework package itself —
21
+ * `selfTest: true`) flips the no-target default to the framework suite, so
22
+ * each package's own `npm test` keeps meaning "run my suite".
23
+ */
24
+
25
+ const UNIVERSAL_FRAMEWORK_ALIASES = ['framework', 'omega', 'mgr'];
26
+ const PROJECT_ALIASES = ['project', 'brand'];
27
+ const FULL_ALIASES = ['full'];
28
+
29
+ // Per-framework id prefixes, keyed by package name. The SSOT for "which
30
+ // prefixes does each framework answer to": framework runners pass their own
31
+ // entry as `frameworkAliases`, and the manager's brand-root `test` fan-out
32
+ // routes `web:`/`desktop:`/… targets to the target owning that framework.
33
+ // Legacy short ids (ujm/em/bxm) retired with cp262's legacy-name sweep.
34
+ const FRAMEWORK_IDS = {
35
+ '@omega.js/web': ['web'],
36
+ '@omega.js/backend': ['backend'],
37
+ '@omega.js/desktop': ['desktop'],
38
+ '@omega.js/extension': ['extension'],
39
+ };
40
+
41
+ /**
42
+ * Parse `omega test` positional targets into sources + per-source path filters.
43
+ *
44
+ * @param {string[]} rawTargets - Positional targets (may be empty)
45
+ * @param {Object} [options]
46
+ * @param {string[]} [options.frameworkAliases] - Extra framework prefixes for
47
+ * this framework (e.g. ['backend'], ['desktop'], ['extension'], ['web'])
48
+ * @param {boolean} [options.selfTest] - True when running inside the framework
49
+ * package itself (no consumer project)
50
+ * @returns {{
51
+ * sources: string[], // subset of ['framework', 'project']
52
+ * filters: { framework: string[], project: string[] }, // prefix-stripped path filters per source
53
+ * invalid: string[], // unrecognized `<word>:` prefixes (likely typos)
54
+ * }}
55
+ */
56
+ function parseTestScope(rawTargets, options = {}) {
57
+ const frameworkAliases = new Set([
58
+ ...UNIVERSAL_FRAMEWORK_ALIASES,
59
+ ...(options.frameworkAliases || []),
60
+ ]);
61
+
62
+ const sources = new Set();
63
+ const filters = { framework: [], project: [] };
64
+ const invalid = [];
65
+
66
+ for (const raw of rawTargets || []) {
67
+ const target = String(raw).trim();
68
+ if (!target) continue;
69
+
70
+ const match = target.match(/^([a-z-]+):(.*)$/);
71
+
72
+ if (!match) {
73
+ // Bare path — binds to the PROJECT source.
74
+ sources.add('project');
75
+ filters.project.push(target);
76
+ continue;
77
+ }
78
+
79
+ const [, prefix, pathPart] = match;
80
+
81
+ if (frameworkAliases.has(prefix)) {
82
+ sources.add('framework');
83
+ if (pathPart) filters.framework.push(pathPart);
84
+ } else if (PROJECT_ALIASES.includes(prefix)) {
85
+ sources.add('project');
86
+ if (pathPart) filters.project.push(pathPart);
87
+ } else if (FULL_ALIASES.includes(prefix)) {
88
+ sources.add('framework');
89
+ sources.add('project');
90
+ if (pathPart) {
91
+ filters.framework.push(pathPart);
92
+ filters.project.push(pathPart);
93
+ }
94
+ } else {
95
+ // Unknown prefix — surface it rather than silently matching nothing.
96
+ invalid.push(target);
97
+ }
98
+ }
99
+
100
+ // No targets (or only invalid ones): consumer default = project only;
101
+ // framework self context = the framework's own suite.
102
+ if (sources.size === 0) {
103
+ sources.add(options.selfTest ? 'framework' : 'project');
104
+ }
105
+
106
+ return {
107
+ sources: ['framework', 'project'].filter((s) => sources.has(s)),
108
+ filters,
109
+ invalid,
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Did the run ask for test files BY NAME? A path filter (`build/x`,
115
+ * `project:x`, `desktop:x`, `full:x`) names files; a bare run, or a bare
116
+ * source prefix, asks for a source. Only the first kind can be a typo, so
117
+ * only the first kind fails when it selects nothing
118
+ * ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)).
119
+ *
120
+ * @param {{filters: {framework: string[], project: string[]}}} scope - A parseTestScope() result
121
+ * @returns {boolean} True when at least one path filter was given
122
+ */
123
+ function isPathTargeted(scope) {
124
+ return scope.filters.framework.length > 0 || scope.filters.project.length > 0;
125
+ }
126
+
127
+ /**
128
+ * The ONE line every framework prints when a named target selects zero test
129
+ * files: the same sentence in a web app, a backend, a desktop app and an
130
+ * extension ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)).
131
+ *
132
+ * @param {string} target - The target as the caller spelled it
133
+ * @returns {string} The message (the caller adds its own log tag)
134
+ */
135
+ function noMatchMessage(target) {
136
+ return `No test file matches "${target}".`;
137
+ }
138
+
139
+ // A brand-root run fans ONE target out over every target, where a target that
140
+ // does not carry that path is a legitimate no-op rather than a typo. The
141
+ // manager sets this signal on the runs it forwards and reads the exit code
142
+ // below to tell a miss from a failure
143
+ // ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)). Its presence is
144
+ // the whole signal, the way OMEGA_CASE_RUNNER's is.
145
+ const FANOUT_ENV = 'OMEGA_TEST_FANOUT';
146
+
147
+ // The exit code a no-match answers with under that signal: distinct, so the
148
+ // fan-out counts misses without confusing them with failures. A standalone run
149
+ // stays 1, the code every human and every CI already reads as "this failed".
150
+ const NO_MATCH_EXIT_CODE = 3;
151
+
152
+ /**
153
+ * The exit code a no-match run ends on, given its environment.
154
+ *
155
+ * @param {object} [env] - The environment to read (defaults to process.env)
156
+ * @returns {number} NO_MATCH_EXIT_CODE inside a brand-root fan-out, else 1
157
+ */
158
+ function noMatchExitCode(env = process.env) {
159
+ return env[FANOUT_ENV] ? NO_MATCH_EXIT_CODE : 1;
160
+ }
161
+
162
+ module.exports = { parseTestScope, isPathTargeted, noMatchMessage, noMatchExitCode, NO_MATCH_EXIT_CODE, FANOUT_ENV, UNIVERSAL_FRAMEWORK_ALIASES, PROJECT_ALIASES, FULL_ALIASES, FRAMEWORK_IDS };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The committed translation cache — per-string maps keyed by a hash of the
3
+ * SOURCE string, stored as reviewable JSON in the consumer's `translations/`
4
+ * directory (committed to git, replacing both the legacy gitignored `.cache/`
5
+ * and the cache-uj-translation GitHub-branch flow). A source edit changes the
6
+ * hash → cache miss → only that string re-translates; a human can hand-fix a
7
+ * translation VALUE and it sticks for as long as the source is unchanged.
8
+ *
9
+ * Layout: <rootDir>/<lang>/<namespace>.json → { "<hash12>": "translation" }
10
+ * (namespace = a page path for web, 'messages'/'description' for extension).
11
+ */
12
+ const path = require('node:path');
13
+ const crypto = require('node:crypto');
14
+ const jetpack = require('fs-jetpack');
15
+
16
+ /**
17
+ * Cache key for a source string.
18
+ * @param {string} source - the source-language string
19
+ * @returns {string} 12-hex-char sha256 prefix
20
+ */
21
+ function hashKey(source) {
22
+ return crypto.createHash('sha256').update(source).digest('hex').slice(0, 12);
23
+ }
24
+
25
+ /**
26
+ * Resolve a namespace's cache file path.
27
+ * @param {string} rootDir - translations root (e.g. <consumer>/translations)
28
+ * @param {string} lang - language code
29
+ * @param {string} namespace - cache namespace (slashes allowed)
30
+ * @returns {string}
31
+ */
32
+ function cachePath(rootDir, lang, namespace) {
33
+ return path.join(rootDir, lang, `${namespace}.json`);
34
+ }
35
+
36
+ /**
37
+ * Load a namespace's hash → translation map ({} when absent/corrupt).
38
+ * @param {string} rootDir - translations root
39
+ * @param {string} lang - language code
40
+ * @param {string} namespace - cache namespace
41
+ * @returns {object}
42
+ */
43
+ function loadCache(rootDir, lang, namespace) {
44
+ const file = cachePath(rootDir, lang, namespace);
45
+
46
+ if (!jetpack.exists(file)) {
47
+ return {};
48
+ }
49
+
50
+ try {
51
+ return JSON.parse(jetpack.read(file)) || {};
52
+ } catch (e) {
53
+ return {};
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Save a namespace's map, pruned to the CURRENT source strings so stale
59
+ * entries never accumulate. No-op delete when the map is empty.
60
+ * @param {string} rootDir - translations root
61
+ * @param {string} lang - language code
62
+ * @param {string} namespace - cache namespace
63
+ * @param {object} map - hash → translation
64
+ * @param {string[]} [currentSources] - prune to these sources' hashes
65
+ */
66
+ function saveCache(rootDir, lang, namespace, map, currentSources) {
67
+ let pruned = map;
68
+
69
+ if (currentSources) {
70
+ const keep = new Set(currentSources.map(hashKey));
71
+ pruned = Object.fromEntries(Object.entries(map).filter(([key]) => keep.has(key)));
72
+ }
73
+
74
+ const file = cachePath(rootDir, lang, namespace);
75
+
76
+ if (!Object.keys(pruned).length) {
77
+ jetpack.remove(file);
78
+ return;
79
+ }
80
+
81
+ jetpack.write(file, `${JSON.stringify(pruned, null, 2)}\n`);
82
+ }
83
+
84
+ module.exports = { hashKey, cachePath, loadCache, saveCache };
@@ -0,0 +1,243 @@
1
+ /**
2
+ * The translation engine — one provider-agnostic protocol for translating a
3
+ * batch of strings: JSON array in → same-length JSON array out, with a control
4
+ * sentinel appended to every batch to prove alignment, automatic batching,
5
+ * validation retries, and a HALVING re-ask for a batch the model keeps
6
+ * collapsing. Frameworks feed it strings (page text nodes, extension messages)
7
+ * and get positionally-aligned translations back.
8
+ */
9
+
10
+ // Alignment sentinel — appended to every batch, must return unchanged
11
+ const CONTROL = 'OMEGA-TRANSLATION-CONTROL';
12
+
13
+ const BATCH_SIZE = 25;
14
+ const MAX_RETRIES = 2;
15
+
16
+ // How many batches are in flight at once (#604). A batch is one model call and
17
+ // the model's latency dominates it, so a serial pass paid that latency once per
18
+ // 25 strings — a language took minutes it never needed to. Raise it only as far
19
+ // as the providers' rate limits allow.
20
+ const CONCURRENCY = 5;
21
+
22
+ const SYSTEM_PROMPT = `<role>
23
+ Professional translator. Return ONLY a valid JSON array — no commentary, no markdown fences, no wrapping.
24
+ </role>
25
+
26
+ <task>
27
+ Translate the input JSON array of strings into the target language.
28
+ The output array MUST have the EXACT same length as the input array.
29
+ </task>
30
+
31
+ <rules>
32
+ - Input: a JSON array of strings. Output: a JSON array of translated strings of the SAME length.
33
+ - DO NOT add, remove, merge, or reorder elements.
34
+ - Consider adjacent strings for context — they come from the same document.
35
+ - Preserve leading and trailing whitespace in each string.
36
+ - Keep HTML tags, attributes, URLs, and email addresses verbatim — never translate them.
37
+ - Preserve placeholder tokens exactly (e.g. $1, $2, %s, {name}, {{ value }}).
38
+ - Keep brand names, product names, and company names in their original language.
39
+ - Never translate the brand name "{brand}".
40
+ - The control string "${CONTROL}" must be returned unchanged at its exact position.
41
+ {extraRules}
42
+ </rules>
43
+
44
+ <example lang="es">
45
+ Input: ["Welcome to {brand}", "Get started today", "${CONTROL}"]
46
+ Output: ["Bienvenido a {brand}", "Comienza hoy", "${CONTROL}"]
47
+ </example>`;
48
+
49
+ /**
50
+ * Parse the provider's response into a JSON array (strips accidental fences).
51
+ * @param {string} text - raw provider response
52
+ * @returns {Array} parsed array
53
+ */
54
+ function parseArrayResponse(text) {
55
+ const cleaned = (text || '').trim().replace(/^```json?\n?|\n?```$/g, '');
56
+ const parsed = JSON.parse(cleaned);
57
+
58
+ if (!Array.isArray(parsed)) {
59
+ throw new Error(`translation result is not an array (got ${typeof parsed})`);
60
+ }
61
+
62
+ return parsed;
63
+ }
64
+
65
+ /**
66
+ * Re-apply the original string's leading/trailing whitespace to a translation
67
+ * (models trim despite instructions; surrounding markup relies on it).
68
+ * @param {string} original - source string
69
+ * @param {string} translated - translated string
70
+ * @returns {string}
71
+ */
72
+ function preserveWhitespace(original, translated) {
73
+ const leading = original.match(/^\s*/)[0];
74
+ const trailing = original.match(/\s*$/)[0];
75
+
76
+ return `${leading}${String(translated).trim()}${trailing}`;
77
+ }
78
+
79
+ /**
80
+ * An alignment failure — the batch came back, but not one-for-one. Marked so
81
+ * the caller can tell it from a provider that never answered at all.
82
+ * @param {string} message
83
+ * @returns {Error}
84
+ */
85
+ function alignmentError(message) {
86
+ const error = new Error(message);
87
+ error.alignment = true;
88
+ return error;
89
+ }
90
+
91
+ /**
92
+ * Translate one batch (with the control sentinel and validation retries).
93
+ * @param {object} ctx - { send, system, language, languageName }
94
+ * @param {string[]} batch - strings to translate
95
+ * @param {number} attempt - current attempt (0-based)
96
+ * @returns {Promise<{ result: string[], usage: object }>}
97
+ */
98
+ async function translateBatch(ctx, batch, attempt) {
99
+ const payload = [...batch, CONTROL];
100
+ const user = `Target language: ${ctx.language} (${ctx.languageName})\nArray length: ${payload.length}\n\n${JSON.stringify(payload)}`;
101
+
102
+ const { text, usage } = await ctx.send({ system: ctx.system, user });
103
+
104
+ try {
105
+ const parsed = parseArrayResponse(text);
106
+
107
+ if (parsed.length !== payload.length) {
108
+ throw alignmentError(`length mismatch: expected ${payload.length}, got ${parsed.length}`);
109
+ }
110
+
111
+ if (parsed[parsed.length - 1] !== CONTROL) {
112
+ throw alignmentError('control sentinel missing or altered at the last position');
113
+ }
114
+
115
+ return { result: parsed.slice(0, -1), usage };
116
+ } catch (e) {
117
+ if (attempt < MAX_RETRIES) {
118
+ return translateBatch(ctx, batch, attempt + 1);
119
+ }
120
+
121
+ // A batch a model MERGES is deterministic (#523): the playground's
122
+ // ship-the-docs page came back 25-for-26 on all six attempts, in two
123
+ // languages — re-asking the same array can only fail the same way. Halving
124
+ // it separates whatever pair collapsed, and each half is asked in full,
125
+ // so nothing is guessed at and the page stops shipping untranslated.
126
+ if (e.alignment && batch.length > 1) {
127
+ return splitBatch(ctx, batch);
128
+ }
129
+
130
+ throw new Error(`translation failed after ${MAX_RETRIES + 1} attempts: ${e.message}`);
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Re-ask a collapsing batch in halves, bottoming out at one string (a single
136
+ * string plus the sentinel is unambiguous — a provider that still drops it is
137
+ * broken, and the caller skips the page-language pair whole).
138
+ * @param {object} ctx - { send, system, language, languageName }
139
+ * @param {string[]} batch - the batch that would not come back aligned
140
+ * @returns {Promise<{ result: string[], usage: object }>}
141
+ */
142
+ async function splitBatch(ctx, batch) {
143
+ const middle = Math.ceil(batch.length / 2);
144
+ const result = [];
145
+ const usage = { input: 0, output: 0 };
146
+
147
+ for (const half of [batch.slice(0, middle), batch.slice(middle)]) {
148
+ const outcome = await translateBatch(ctx, half, 0);
149
+ result.push(...outcome.result);
150
+ usage.input += outcome.usage?.input || 0;
151
+ usage.output += outcome.usage?.output || 0;
152
+ }
153
+
154
+ return { result, usage };
155
+ }
156
+
157
+ /**
158
+ * Run a worker over every item with at most CONCURRENCY of them in flight,
159
+ * returning results in the ITEMS' order — never completion order.
160
+ * @param {Array} items - the work items
161
+ * @param {Function} worker - (item) → Promise
162
+ * @returns {Promise<Array>} results, positionally aligned with items
163
+ */
164
+ async function mapLimited(items, worker) {
165
+ const results = new Array(items.length);
166
+ let next = 0;
167
+
168
+ const drain = async () => {
169
+ while (next < items.length) {
170
+ const index = next++;
171
+ results[index] = await worker(items[index]);
172
+ }
173
+ };
174
+
175
+ await Promise.all(Array.from({ length: Math.min(CONCURRENCY, items.length) }, drain));
176
+
177
+ return results;
178
+ }
179
+
180
+ /**
181
+ * Translate an array of strings, batching + validating along the way.
182
+ * @param {object} options
183
+ * @param {string[]} options.strings - source strings
184
+ * @param {string} options.language - target language code (e.g. 'es')
185
+ * @param {string} options.languageName - English name of the target language
186
+ * @param {Function} options.send - provider send ({ system, user }) → { text, usage }
187
+ * @param {string} [options.brand] - brand name to keep untranslated
188
+ * @param {string} [options.extraRules] - extra rule lines for the system prompt
189
+ * @returns {Promise<{ result: string[], usage: { input: number, output: number } }>}
190
+ * result is positionally aligned with options.strings, original whitespace preserved
191
+ */
192
+ async function translateStrings(options) {
193
+ const { strings, language, languageName, send, brand, extraRules } = options;
194
+
195
+ if (!strings.length) {
196
+ return { result: [], usage: { input: 0, output: 0 } };
197
+ }
198
+
199
+ const system = SYSTEM_PROMPT
200
+ .split('{brand}').join(brand || 'the brand')
201
+ .replace('{extraRules}', extraRules ? `${extraRules.trim()}\n` : '');
202
+
203
+ const ctx = { send, system, language, languageName };
204
+ const translated = [];
205
+ const usage = { input: 0, output: 0 };
206
+
207
+ // Dedupe before batching (#529): a page sends its title and description once
208
+ // per meta tag, so the same string rode a batch three times over — three
209
+ // times the AI spend, and adjacent twins are exactly what a model merges.
210
+ // Each unique string is translated ONCE and fanned back below.
211
+ const unique = [];
212
+ const position = new Map();
213
+ for (const string of strings) {
214
+ if (!position.has(string)) {
215
+ position.set(string, unique.length);
216
+ unique.push(string);
217
+ }
218
+ }
219
+
220
+ const batches = [];
221
+ for (let i = 0; i < unique.length; i += BATCH_SIZE) {
222
+ batches.push(unique.slice(i, i + BATCH_SIZE));
223
+ }
224
+
225
+ // Batches fly CONCURRENCY-wide (#604) and are stitched back in BATCH order:
226
+ // the sentinel, the alignment checks, and the #523 split backstop all stay
227
+ // per batch, so what a batch does on its own is exactly what it always did.
228
+ const outcomes = await mapLimited(batches, (batch) => translateBatch(ctx, batch, 0));
229
+
230
+ outcomes.forEach((outcome, i) => {
231
+ translated.push(...outcome.result.map((text, j) => preserveWhitespace(batches[i][j], text)));
232
+ usage.input += outcome.usage?.input || 0;
233
+ usage.output += outcome.usage?.output || 0;
234
+ });
235
+
236
+ // Occurrences are keyed on the exact source string, whitespace included, so
237
+ // every one of them gets back the translation its own text asked for.
238
+ const result = strings.map((string) => translated[position.get(string)]);
239
+
240
+ return { result, usage };
241
+ }
242
+
243
+ module.exports = { translateStrings, preserveWhitespace, CONTROL, BATCH_SIZE, CONCURRENCY };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @omega.js/devkit/translate — the shared OMEGA translation system: language
3
+ * SSOT, provider abstraction (claude via local Claude Code / chatgpt via
4
+ * OpenAI), the batch translation engine, and the committed per-string cache.
5
+ * Config contract (shared `translation` section of omega.json5):
6
+ * { enabled, default, languages, providers: { claude|chatgpt: {} }, model, exclude }
7
+ */
8
+ const { chosenProvider } = require('../../config/index.js');
9
+ const { LANGUAGE_NAMES, LANGUAGE_LOCALES, RTL_LANGUAGES, isRTL, languageName, ogLocale, assertKnownLanguages } = require('./languages.js');
10
+ const { PROVIDERS, DEFAULT_MODELS, resolveProvider } = require('./providers.js');
11
+ const { translateStrings, preserveWhitespace, CONTROL, BATCH_SIZE, CONCURRENCY } = require('./engine.js');
12
+ const { hashKey, cachePath, loadCache, saveCache } = require('./cache.js');
13
+
14
+ /**
15
+ * Read + validate the `translation` section of a resolved config.
16
+ * @param {object} config - resolved omega.json5 config
17
+ * @returns {{ enabled: boolean, default: string, languages: string[], provider: string, model: string|null, exclude: string[] }}
18
+ * enabled is false when the section is off or lists no languages
19
+ */
20
+ function resolveTranslationSettings(config) {
21
+ const section = config?.translation || {};
22
+ const languages = section.languages || [];
23
+
24
+ assertKnownLanguages(languages);
25
+
26
+ return {
27
+ enabled: section.enabled !== false && languages.length > 0,
28
+ default: section.default || 'en',
29
+ languages,
30
+ // The engine is a KEY under translation.providers (#425); no block at all
31
+ // means claude, the no-API-key default.
32
+ provider: chosenProvider(section.providers) || 'claude',
33
+ model: section.model || null,
34
+ exclude: section.exclude || [],
35
+ };
36
+ }
37
+
38
+ module.exports = {
39
+ // languages
40
+ LANGUAGE_NAMES, LANGUAGE_LOCALES, RTL_LANGUAGES, isRTL, languageName, ogLocale, assertKnownLanguages,
41
+ // providers
42
+ PROVIDERS, DEFAULT_MODELS, resolveProvider,
43
+ // engine
44
+ translateStrings, preserveWhitespace, CONTROL, BATCH_SIZE, CONCURRENCY,
45
+ // cache
46
+ hashKey, cachePath, loadCache, saveCache,
47
+ // config
48
+ resolveTranslationSettings,
49
+ };