alepha 0.20.5 → 0.20.7

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 (367) hide show
  1. package/AGENTS.md +0 -1
  2. package/CLAUDE.md +0 -1
  3. package/assets/agents-template.md +0 -1
  4. package/dist/api/audits/index.browser.js +1 -0
  5. package/dist/api/audits/index.browser.js.map +1 -1
  6. package/dist/api/audits/index.d.ts +701 -654
  7. package/dist/api/audits/index.d.ts.map +1 -1
  8. package/dist/api/audits/index.js +24 -1
  9. package/dist/api/audits/index.js.map +1 -1
  10. package/dist/api/files/index.browser.js +1 -0
  11. package/dist/api/files/index.browser.js.map +1 -1
  12. package/dist/api/files/index.d.ts +193 -166
  13. package/dist/api/files/index.d.ts.map +1 -1
  14. package/dist/api/files/index.js +52 -0
  15. package/dist/api/files/index.js.map +1 -1
  16. package/dist/api/jobs/index.browser.js +40 -14
  17. package/dist/api/jobs/index.browser.js.map +1 -1
  18. package/dist/api/jobs/index.d.ts +639 -333
  19. package/dist/api/jobs/index.d.ts.map +1 -1
  20. package/dist/api/jobs/index.js +495 -162
  21. package/dist/api/jobs/index.js.map +1 -1
  22. package/dist/api/keys/index.d.ts +222 -188
  23. package/dist/api/keys/index.d.ts.map +1 -1
  24. package/dist/api/keys/index.js +54 -0
  25. package/dist/api/keys/index.js.map +1 -1
  26. package/dist/api/notifications/index.d.ts +265 -236
  27. package/dist/api/notifications/index.d.ts.map +1 -1
  28. package/dist/api/notifications/index.js +55 -13
  29. package/dist/api/notifications/index.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +100 -97
  31. package/dist/api/organizations/index.d.ts.map +1 -1
  32. package/dist/api/organizations/index.js.map +1 -1
  33. package/dist/api/parameters/index.d.ts +332 -314
  34. package/dist/api/parameters/index.d.ts.map +1 -1
  35. package/dist/api/parameters/index.js +37 -0
  36. package/dist/api/parameters/index.js.map +1 -1
  37. package/dist/api/payments/index.d.ts +431 -376
  38. package/dist/api/payments/index.d.ts.map +1 -1
  39. package/dist/api/payments/index.js +202 -87
  40. package/dist/api/payments/index.js.map +1 -1
  41. package/dist/api/subscriptions/index.d.ts +1695 -0
  42. package/dist/api/subscriptions/index.d.ts.map +1 -0
  43. package/dist/api/subscriptions/index.js +1919 -0
  44. package/dist/api/subscriptions/index.js.map +1 -0
  45. package/dist/api/users/index.d.ts +1001 -844
  46. package/dist/api/users/index.d.ts.map +1 -1
  47. package/dist/api/users/index.js +237 -28
  48. package/dist/api/users/index.js.map +1 -1
  49. package/dist/api/verifications/index.d.ts +123 -122
  50. package/dist/api/verifications/index.d.ts.map +1 -1
  51. package/dist/api/verifications/index.js.map +1 -1
  52. package/dist/batch/index.js.map +1 -1
  53. package/dist/bucket/index.d.ts +21 -2
  54. package/dist/bucket/index.d.ts.map +1 -1
  55. package/dist/bucket/index.js +47 -0
  56. package/dist/bucket/index.js.map +1 -1
  57. package/dist/bucket/index.workerd.js +24 -0
  58. package/dist/bucket/index.workerd.js.map +1 -1
  59. package/dist/cache/core/index.d.ts +134 -7
  60. package/dist/cache/core/index.d.ts.map +1 -1
  61. package/dist/cache/core/index.js +181 -15
  62. package/dist/cache/core/index.js.map +1 -1
  63. package/dist/cache/core/index.workerd.js +181 -15
  64. package/dist/cache/core/index.workerd.js.map +1 -1
  65. package/dist/cache/database/index.d.ts +156 -0
  66. package/dist/cache/database/index.d.ts.map +1 -0
  67. package/dist/cache/database/index.js +266 -0
  68. package/dist/cache/database/index.js.map +1 -0
  69. package/dist/cache/redis/index.d.ts +3 -2
  70. package/dist/cache/redis/index.d.ts.map +1 -1
  71. package/dist/cache/redis/index.js.map +1 -1
  72. package/dist/captcha/index.js.map +1 -1
  73. package/dist/cli/config/index.js.map +1 -1
  74. package/dist/cli/core/index.d.ts +142 -128
  75. package/dist/cli/core/index.d.ts.map +1 -1
  76. package/dist/cli/core/index.js +160 -13
  77. package/dist/cli/core/index.js.map +1 -1
  78. package/dist/cli/devtools/index.d.ts +3 -2
  79. package/dist/cli/devtools/index.d.ts.map +1 -1
  80. package/dist/cli/devtools/index.js.map +1 -1
  81. package/dist/cli/platform/index.d.ts +346 -290
  82. package/dist/cli/platform/index.d.ts.map +1 -1
  83. package/dist/cli/platform/index.js +106 -7
  84. package/dist/cli/platform/index.js.map +1 -1
  85. package/dist/cli/vendor/index.d.ts +12 -11
  86. package/dist/cli/vendor/index.d.ts.map +1 -1
  87. package/dist/cli/vendor/index.js.map +1 -1
  88. package/dist/command/index.d.ts +6 -5
  89. package/dist/command/index.d.ts.map +1 -1
  90. package/dist/command/index.js.map +1 -1
  91. package/dist/core/index.browser.js +1 -1
  92. package/dist/core/index.browser.js.map +1 -1
  93. package/dist/core/index.d.ts +119 -118
  94. package/dist/core/index.d.ts.map +1 -1
  95. package/dist/core/index.js +1 -1
  96. package/dist/core/index.js.map +1 -1
  97. package/dist/core/index.native.js +1 -1
  98. package/dist/core/index.native.js.map +1 -1
  99. package/dist/core/index.workerd.js +1 -1
  100. package/dist/core/index.workerd.js.map +1 -1
  101. package/dist/crypto/index.browser.js.map +1 -1
  102. package/dist/crypto/index.d.ts +3 -2
  103. package/dist/crypto/index.d.ts.map +1 -1
  104. package/dist/crypto/index.js.map +1 -1
  105. package/dist/datetime/index.js.map +1 -1
  106. package/dist/email/brevo/index.js.map +1 -1
  107. package/dist/email/core/index.d.ts +3 -2
  108. package/dist/email/core/index.d.ts.map +1 -1
  109. package/dist/email/core/index.js.map +1 -1
  110. package/dist/email/core/index.workerd.js.map +1 -1
  111. package/dist/email/smtp/index.d.ts +7 -6
  112. package/dist/email/smtp/index.d.ts.map +1 -1
  113. package/dist/email/smtp/index.js.map +1 -1
  114. package/dist/fake/index.js.map +1 -1
  115. package/dist/lock/core/index.d.ts +5 -4
  116. package/dist/lock/core/index.d.ts.map +1 -1
  117. package/dist/lock/core/index.js.map +1 -1
  118. package/dist/lock/redis/index.js.map +1 -1
  119. package/dist/logger/index.d.ts +10 -9
  120. package/dist/logger/index.d.ts.map +1 -1
  121. package/dist/logger/index.js.map +1 -1
  122. package/dist/mcp/index.d.ts +9 -8
  123. package/dist/mcp/index.d.ts.map +1 -1
  124. package/dist/mcp/index.js +1 -1
  125. package/dist/mcp/index.js.map +1 -1
  126. package/dist/orm/core/index.browser.js +9 -3
  127. package/dist/orm/core/index.browser.js.map +1 -1
  128. package/dist/orm/core/index.bun.js +31 -10
  129. package/dist/orm/core/index.bun.js.map +1 -1
  130. package/dist/orm/core/index.d.ts +33 -14
  131. package/dist/orm/core/index.d.ts.map +1 -1
  132. package/dist/orm/core/index.js +31 -10
  133. package/dist/orm/core/index.js.map +1 -1
  134. package/dist/orm/postgres/index.bun.js.map +1 -1
  135. package/dist/orm/postgres/index.d.ts +6 -5
  136. package/dist/orm/postgres/index.d.ts.map +1 -1
  137. package/dist/orm/postgres/index.js.map +1 -1
  138. package/dist/queue/core/index.d.ts +5 -4
  139. package/dist/queue/core/index.d.ts.map +1 -1
  140. package/dist/queue/core/index.js.map +1 -1
  141. package/dist/queue/core/index.workerd.js.map +1 -1
  142. package/dist/queue/redis/index.d.ts +3 -2
  143. package/dist/queue/redis/index.d.ts.map +1 -1
  144. package/dist/queue/redis/index.js.map +1 -1
  145. package/dist/react/auth/index.browser.js.map +1 -1
  146. package/dist/react/auth/index.js.map +1 -1
  147. package/dist/react/core/index.js.map +1 -1
  148. package/dist/react/form/index.d.ts +5 -0
  149. package/dist/react/form/index.d.ts.map +1 -1
  150. package/dist/react/form/index.js +8 -4
  151. package/dist/react/form/index.js.map +1 -1
  152. package/dist/react/head/index.browser.js.map +1 -1
  153. package/dist/react/head/index.js.map +1 -1
  154. package/dist/react/i18n/index.d.ts +2 -1
  155. package/dist/react/i18n/index.d.ts.map +1 -1
  156. package/dist/react/i18n/index.js.map +1 -1
  157. package/dist/react/intro/index.js.map +1 -1
  158. package/dist/react/router/index.browser.js.map +1 -1
  159. package/dist/react/router/index.d.ts +206 -205
  160. package/dist/react/router/index.d.ts.map +1 -1
  161. package/dist/react/router/index.js.map +1 -1
  162. package/dist/react/testing/index.js.map +1 -1
  163. package/dist/react/ui/index.d.ts +11 -11
  164. package/dist/react/ui/index.d.ts.map +1 -1
  165. package/dist/react/ui/index.js.map +1 -1
  166. package/dist/redis/index.bun.js.map +1 -1
  167. package/dist/redis/index.js.map +1 -1
  168. package/dist/retry/index.js.map +1 -1
  169. package/dist/router/index.js.map +1 -1
  170. package/dist/scheduler/index.d.ts +25 -2
  171. package/dist/scheduler/index.d.ts.map +1 -1
  172. package/dist/scheduler/index.js +12 -0
  173. package/dist/scheduler/index.js.map +1 -1
  174. package/dist/scheduler/index.workerd.js +12 -0
  175. package/dist/scheduler/index.workerd.js.map +1 -1
  176. package/dist/security/index.browser.js +29 -1
  177. package/dist/security/index.browser.js.map +1 -1
  178. package/dist/security/index.d.ts +82 -35
  179. package/dist/security/index.d.ts.map +1 -1
  180. package/dist/security/index.js +56 -3
  181. package/dist/security/index.js.map +1 -1
  182. package/dist/server/auth/index.d.ts +163 -158
  183. package/dist/server/auth/index.d.ts.map +1 -1
  184. package/dist/server/auth/index.js +16 -4
  185. package/dist/server/auth/index.js.map +1 -1
  186. package/dist/server/cookies/index.browser.js.map +1 -1
  187. package/dist/server/cookies/index.js.map +1 -1
  188. package/dist/server/core/index.browser.js.map +1 -1
  189. package/dist/server/core/index.d.ts +35 -34
  190. package/dist/server/core/index.d.ts.map +1 -1
  191. package/dist/server/core/index.js.map +1 -1
  192. package/dist/server/cors/index.d.ts +7 -6
  193. package/dist/server/cors/index.d.ts.map +1 -1
  194. package/dist/server/cors/index.js.map +1 -1
  195. package/dist/server/etag/index.js.map +1 -1
  196. package/dist/server/health/index.d.ts +16 -15
  197. package/dist/server/health/index.d.ts.map +1 -1
  198. package/dist/server/health/index.js.map +1 -1
  199. package/dist/server/links/index.browser.js.map +1 -1
  200. package/dist/server/links/index.d.ts +51 -50
  201. package/dist/server/links/index.d.ts.map +1 -1
  202. package/dist/server/links/index.js.map +1 -1
  203. package/dist/server/metrics/index.js.map +1 -1
  204. package/dist/server/proxy/index.js.map +1 -1
  205. package/dist/server/rate-limit/index.d.ts +6 -5
  206. package/dist/server/rate-limit/index.d.ts.map +1 -1
  207. package/dist/server/rate-limit/index.js.map +1 -1
  208. package/dist/server/static/index.js.map +1 -1
  209. package/dist/server/swagger/index.d.ts +2 -1
  210. package/dist/server/swagger/index.d.ts.map +1 -1
  211. package/dist/server/swagger/index.js.map +1 -1
  212. package/dist/sms/index.js.map +1 -1
  213. package/dist/system/index.browser.js.map +1 -1
  214. package/dist/system/index.js.map +1 -1
  215. package/dist/system/index.workerd.js.map +1 -1
  216. package/dist/topic/core/index.js.map +1 -1
  217. package/dist/topic/redis/index.d.ts +3 -2
  218. package/dist/topic/redis/index.d.ts.map +1 -1
  219. package/dist/topic/redis/index.js.map +1 -1
  220. package/package.json +33 -39
  221. package/src/api/audits/controllers/AdminAuditController.ts +29 -0
  222. package/src/api/audits/entities/audits.ts +1 -0
  223. package/src/api/files/controllers/FileController.ts +24 -0
  224. package/src/api/files/entities/files.ts +1 -0
  225. package/src/api/files/services/FileService.ts +41 -0
  226. package/src/api/jobs/__tests__/$job.spec.ts +501 -24
  227. package/src/api/jobs/entities/jobExecutionEntity.ts +4 -3
  228. package/src/api/jobs/index.ts +47 -10
  229. package/src/api/jobs/primitives/$job.ts +22 -9
  230. package/src/api/jobs/providers/DirectJobDispatcher.ts +71 -0
  231. package/src/api/jobs/providers/JobDispatcher.ts +49 -0
  232. package/src/api/jobs/providers/JobProvider.ts +385 -147
  233. package/src/api/jobs/providers/JobQueueProvider.ts +43 -18
  234. package/src/api/jobs/schemas/jobConfigAtom.ts +9 -3
  235. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +11 -0
  236. package/src/api/jobs/schemas/jobRegistrationSchema.ts +4 -2
  237. package/src/api/jobs/services/JobService.ts +21 -11
  238. package/src/api/keys/controllers/AdminApiKeyController.ts +23 -0
  239. package/src/api/keys/entities/apiKeyEntity.ts +1 -0
  240. package/src/api/keys/services/ApiKeyService.ts +42 -0
  241. package/src/api/notifications/__tests__/AlephaApiNotifications.spec.ts +63 -0
  242. package/src/api/notifications/controllers/AdminNotificationController.ts +48 -1
  243. package/src/api/notifications/index.ts +13 -3
  244. package/src/api/notifications/jobs/NotificationJobs.ts +0 -6
  245. package/src/api/parameters/controllers/AdminParameterController.ts +26 -0
  246. package/src/api/parameters/services/ParameterProvider.ts +18 -0
  247. package/src/api/payments/controllers/MockCheckoutController.ts +146 -0
  248. package/src/api/payments/index.ts +3 -0
  249. package/src/api/payments/providers/MemoryPaymentProvider.ts +9 -4
  250. package/src/api/payments/providers/PaymentProvider.ts +25 -9
  251. package/src/api/payments/services/PaymentService.ts +3 -0
  252. package/src/api/subscriptions/__tests__/BillingService.spec.ts +218 -0
  253. package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +278 -0
  254. package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +212 -0
  255. package/src/api/subscriptions/controllers/SubscriptionController.ts +189 -0
  256. package/src/api/subscriptions/entities/subscriptionEvents.ts +54 -0
  257. package/src/api/subscriptions/entities/subscriptions.ts +68 -0
  258. package/src/api/subscriptions/index.ts +133 -0
  259. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +382 -0
  260. package/src/api/subscriptions/middleware/$requireLimit.ts +50 -0
  261. package/src/api/subscriptions/middleware/$requirePlan.ts +49 -0
  262. package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +110 -0
  263. package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +8 -0
  264. package/src/api/subscriptions/schemas/changePlanSchema.ts +9 -0
  265. package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +11 -0
  266. package/src/api/subscriptions/schemas/entitlementsSchema.ts +21 -0
  267. package/src/api/subscriptions/schemas/mrrSchema.ts +13 -0
  268. package/src/api/subscriptions/schemas/planDefinitionSchema.ts +71 -0
  269. package/src/api/subscriptions/schemas/planResourceSchema.ts +25 -0
  270. package/src/api/subscriptions/schemas/subscriptionEventResourceSchema.ts +8 -0
  271. package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +19 -0
  272. package/src/api/subscriptions/schemas/subscriptionResourceSchema.ts +6 -0
  273. package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +32 -0
  274. package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +23 -0
  275. package/src/api/subscriptions/services/BillingService.ts +437 -0
  276. package/src/api/subscriptions/services/SubscriptionConfig.ts +56 -0
  277. package/src/api/subscriptions/services/SubscriptionService.ts +867 -0
  278. package/src/api/subscriptions/services/UsageService.ts +118 -0
  279. package/src/api/users/__tests__/Registration-emailMode.spec.ts +203 -0
  280. package/src/api/users/__tests__/UsernameSlugger.spec.ts +138 -0
  281. package/src/api/users/atoms/realmAuthSettingsAtom.ts +41 -3
  282. package/src/api/users/controllers/AdminSessionController.ts +29 -0
  283. package/src/api/users/controllers/AdminUserController.ts +32 -0
  284. package/src/api/users/index.ts +3 -0
  285. package/src/api/users/services/CredentialService.ts +5 -0
  286. package/src/api/users/services/RegistrationService.ts +49 -1
  287. package/src/api/users/services/SessionCrudService.ts +16 -0
  288. package/src/api/users/services/SessionService.ts +17 -59
  289. package/src/api/users/services/UsernameSlugger.ts +195 -0
  290. package/src/bucket/primitives/$bucket.ts +21 -0
  291. package/src/bucket/providers/CloudflareR2Provider.ts +15 -0
  292. package/src/bucket/providers/FileStorageProvider.ts +9 -0
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +14 -0
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +9 -0
  295. package/src/bucket/providers/NodeS3BucketProvider.ts +35 -0
  296. package/src/cache/core/__tests__/$cache.memory.spec.ts +450 -0
  297. package/src/cache/core/__tests__/$cache.swr.spec.ts +394 -0
  298. package/src/cache/core/index.ts +16 -0
  299. package/src/cache/core/primitives/$cache.ts +367 -24
  300. package/src/cache/database/__tests__/DatabaseCacheProvider.behavior.spec.ts +203 -0
  301. package/src/cache/database/__tests__/DatabaseCacheProvider.spec.ts +110 -0
  302. package/src/cache/database/entities/cacheEntries.ts +55 -0
  303. package/src/cache/database/index.ts +36 -0
  304. package/src/cache/database/providers/DatabaseCacheProvider.ts +348 -0
  305. package/src/cli/core/services/ProjectScaffolder.ts +0 -2
  306. package/src/cli/core/tasks/BuildCloudflareTask.ts +33 -3
  307. package/src/cli/core/tasks/BuildSitemapTask.ts +7 -0
  308. package/src/cli/core/tasks/BuildVercelTask.ts +82 -3
  309. package/src/cli/core/templates/agentMd.ts +39 -4
  310. package/src/cli/core/templates/biomeJson.ts +25 -1
  311. package/src/cli/core/templates/saasAdminLayoutTsx.ts +2 -2
  312. package/src/cli/platform/__tests__/CloudflareAdapter.spec.ts +117 -0
  313. package/src/cli/platform/__tests__/detectResources.spec.ts +96 -0
  314. package/src/cli/platform/adapters/CloudflareAdapter.ts +104 -7
  315. package/src/cli/platform/atoms/platformOptions.ts +13 -0
  316. package/src/cli/platform/commands/platform.ts +7 -1
  317. package/src/cli/platform/schemas/platform.ts +1 -0
  318. package/src/cli/platform/services/CloudflareApi.ts +61 -0
  319. package/src/cli/platform/services/PlatformOrchestrator.ts +9 -4
  320. package/src/core/__tests__/$module.spec.ts +2 -2
  321. package/src/core/primitives/$module.ts +4 -4
  322. package/src/mcp/providers/McpServerProvider.ts +1 -1
  323. package/src/orm/core/providers/DatabaseTypeProvider.ts +9 -3
  324. package/src/orm/core/providers/drivers/DatabaseProvider.ts +1 -1
  325. package/src/orm/core/schemas/insertSchema.ts +10 -2
  326. package/src/orm/core/services/Repository.ts +27 -7
  327. package/src/react/form/hooks/useFormState.ts +8 -1
  328. package/src/react/form/index.ts +10 -1
  329. package/src/react/form/services/FormModel.ts +9 -3
  330. package/src/scheduler/index.ts +14 -0
  331. package/src/scheduler/providers/CronProvider.ts +13 -0
  332. package/src/security/atoms/currentTenantAtom.ts +34 -0
  333. package/src/security/index.browser.ts +1 -0
  334. package/src/security/index.ts +12 -1
  335. package/src/security/primitives/$issuer.ts +17 -1
  336. package/src/security/providers/SecurityProvider.ts +37 -0
  337. package/src/server/auth/__tests__/validateRedirectUri.spec.ts +78 -0
  338. package/src/server/auth/providers/ServerAuthProvider.ts +21 -5
  339. package/tsconfig.base.json +2 -1
  340. package/dist/react/websocket/index.d.ts +0 -117
  341. package/dist/react/websocket/index.d.ts.map +0 -1
  342. package/dist/react/websocket/index.js +0 -108
  343. package/dist/react/websocket/index.js.map +0 -1
  344. package/dist/websocket/index.browser.js +0 -844
  345. package/dist/websocket/index.browser.js.map +0 -1
  346. package/dist/websocket/index.d.ts +0 -876
  347. package/dist/websocket/index.d.ts.map +0 -1
  348. package/dist/websocket/index.js +0 -1175
  349. package/dist/websocket/index.js.map +0 -1
  350. package/src/react/websocket/hooks/useRoom.tsx +0 -251
  351. package/src/react/websocket/index.ts +0 -7
  352. package/src/websocket/__tests__/$channel.spec.ts +0 -30
  353. package/src/websocket/__tests__/$websocket-new.spec.ts +0 -195
  354. package/src/websocket/__tests__/RoomManager.spec.ts +0 -146
  355. package/src/websocket/__tests__/websocket-integration.spec.ts +0 -951
  356. package/src/websocket/errors/WebSocketError.ts +0 -34
  357. package/src/websocket/index.browser.ts +0 -25
  358. package/src/websocket/index.shared.ts +0 -8
  359. package/src/websocket/index.ts +0 -85
  360. package/src/websocket/interfaces/WebSocketInterfaces.ts +0 -252
  361. package/src/websocket/primitives/$channel.ts +0 -131
  362. package/src/websocket/primitives/$websocket.ts +0 -107
  363. package/src/websocket/providers/NodeWebSocketServerProvider.ts +0 -617
  364. package/src/websocket/providers/WebSocketServerProvider.ts +0 -56
  365. package/src/websocket/services/RoomManager.ts +0 -160
  366. package/src/websocket/services/WebSocketClient.ts +0 -642
  367. package/src/websocket/services/WebSocketTopicService.ts +0 -108
@@ -4,6 +4,8 @@ import { AlephaLock } from "alepha/lock";
4
4
  import { AlephaQueue } from "alepha/queue";
5
5
  import { AlephaScheduler } from "alepha/scheduler";
6
6
  import { AdminJobController } from "./controllers/AdminJobController.ts";
7
+ import { $job } from "./primitives/$job.ts";
8
+ import { DirectJobDispatcher } from "./providers/DirectJobDispatcher.ts";
7
9
  import { JobProvider } from "./providers/JobProvider.ts";
8
10
  import { JobQueueProvider } from "./providers/JobQueueProvider.ts";
9
11
  import { JobService } from "./services/JobService.ts";
@@ -13,6 +15,8 @@ import { JobService } from "./services/JobService.ts";
13
15
  export * from "./controllers/AdminJobController.ts";
14
16
  export * from "./entities/jobExecutionEntity.ts";
15
17
  export * from "./primitives/$job.ts";
18
+ export * from "./providers/DirectJobDispatcher.ts";
19
+ export * from "./providers/JobDispatcher.ts";
16
20
  export * from "./providers/JobProvider.ts";
17
21
  export * from "./providers/JobQueueProvider.ts";
18
22
  export * from "./schemas/jobConfigAtom.ts";
@@ -39,28 +43,61 @@ declare module "alepha" {
39
43
  /**
40
44
  * Job execution framework — cron and durable queue work with a single primitive.
41
45
  *
42
- * A `$job` is either **cron-only** (declares `cron`) or **queue-only** (declares `schema`).
43
- * Cron jobs run inline on their schedule and only record errors by default.
44
- * Queue jobs use the outbox pattern: push commits to DB first, then notifies via queue.
46
+ * A `$job` is either **cron-only** (declares `cron`) or **payload-only** (declares `schema`).
45
47
  *
46
- * **This module provides cron support only.** To enable queue-mode jobs, also
47
- * import {@link AlephaApiJobsQueue} — it brings in the queue layer and infrastructure
48
- * binding (e.g. Cloudflare Queues). Cron-only deployments (Vercel, CF-without-Queues)
49
- * do not need `AlephaApiJobsQueue`.
48
+ * **Three runtime modes:**
49
+ *
50
+ * - **cron** fires on a schedule. Cron-mode jobs are protected by a
51
+ * distributed lock by default (`lock: true`), so multi-replica Docker
52
+ * deployments only run the handler once per tick. Override with
53
+ * `lock: false` if you genuinely want every replica to fire.
54
+ * - **queue** — push-driven, dispatched through the queue infrastructure
55
+ * (`AlephaQueue`, e.g. Cloudflare Queues, Redis). Real-time delivery,
56
+ * ideal for high-volume systems. Requires `AlephaApiJobsQueue`.
57
+ * - **direct** — push-driven, processed in-process right after the caller
58
+ * awaits the push. The DB outbox row is the durability guarantee — if
59
+ * the process dies, the reconciliation sweep re-dispatches. Default
60
+ * when `AlephaApiJobsQueue` is *not* loaded. Best for cheap deployments
61
+ * (Cloudflare Workers, single-instance Node) where standing up a queue
62
+ * is overkill.
63
+ *
64
+ * **Retries** are sweep-driven across all modes (no exponential backoff).
65
+ * Granularity is bounded by `sweepCron` (default 5 min). The first retry
66
+ * may land anywhere from a few seconds to ~5 min later depending on when
67
+ * the next sweep tick fires. Cron jobs that declare `retry` go through
68
+ * the same sweep path — a transient failure no longer means waiting for
69
+ * the next cron tick (useful for once-daily jobs).
70
+ *
71
+ * **Runtime support for cron triggers**
72
+ *
73
+ * - **Long-running Node / Docker** — `CronProvider` runs an in-process
74
+ * timer loop. Multi-replica deployments serialize ticks via the cron
75
+ * lock (see `$job.lock`).
76
+ * - **Cloudflare Workers** — the build emits cron expressions into
77
+ * `wrangler.jsonc`; Cloudflare invokes the worker on schedule and the
78
+ * `cloudflare:scheduled` hook routes the event to the matching jobs.
79
+ * - **Vercel** — the build emits cron entries into
80
+ * `.vercel/output/config.json` mapped to `/_alepha/cron/:name`; the
81
+ * serverless handler emits `serverless:cron` and `CronProvider` runs
82
+ * the matching job. Set `CRON_SECRET` to require authenticated calls.
50
83
  *
51
84
  * @module alepha.api.jobs
52
85
  */
53
86
  export const AlephaApiJobs = $module({
54
87
  name: "alepha.api.jobs",
88
+ primitives: [$job],
55
89
  imports: [AlephaScheduler, AlephaLock],
56
- services: [JobProvider, JobService, AdminJobController],
90
+ services: [JobProvider, JobService, AdminJobController, DirectJobDispatcher],
57
91
  });
58
92
 
59
93
  /**
60
94
  * Queue support for `$job`. Import alongside {@link AlephaApiJobs} when your
61
- * app declares queue-mode jobs (any `$job` with a `schema`).
95
+ * app declares queue-mode jobs (any `$job` with a `schema`) and you want a
96
+ * real queue (e.g. Cloudflare Queues, Redis) instead of in-process direct
97
+ * execution.
62
98
  *
63
- * Adds `JobQueueProvider` which plumbs the outbox dispatch through `AlephaQueue`.
99
+ * Adds `JobQueueProvider` to the container. `JobProvider` detects its
100
+ * presence at start-up and routes dispatches through it.
64
101
  *
65
102
  * @module alepha.api.jobs.queue
66
103
  */
@@ -40,16 +40,8 @@ export interface JobHandlerArgs<T extends TSchema = TSchema> {
40
40
  executionId: string;
41
41
  }
42
42
 
43
- export interface JobRetryBackoff {
44
- initial: DurationLike;
45
- factor?: number;
46
- max?: DurationLike;
47
- jitter?: boolean;
48
- }
49
-
50
43
  export interface JobRetryOptions {
51
44
  retries: number;
52
- backoff?: DurationLike | JobRetryBackoff;
53
45
  when?: (error: Error) => boolean;
54
46
  }
55
47
 
@@ -81,11 +73,32 @@ export interface JobPrimitiveOptions<T extends TSchema = TSchema>
81
73
  cron?: string;
82
74
 
83
75
  /**
84
- * Retry policy for queue-mode jobs.
76
+ * Retry policy for queue-mode and direct-mode jobs.
85
77
  * Cron-mode jobs do not retry — the next tick re-runs.
78
+ *
79
+ * Retries are picked up by the reconciliation sweep, so retry granularity
80
+ * is bounded by `sweepCron` (default 5 minutes). The first retry may run
81
+ * earlier than 5 minutes if the sweep tick happens sooner.
86
82
  */
87
83
  retry?: JobRetryOptions;
88
84
 
85
+ /**
86
+ * **Cron-mode only.** Whether to acquire a distributed lock around the
87
+ * cron tick so that only one instance of a multi-replica deployment runs
88
+ * the handler per tick.
89
+ *
90
+ * Has **no effect** on queue-mode and direct-mode jobs — those rely on
91
+ * the outbox `claim()` UPDATE-guard to serialize work instead, which is
92
+ * always on.
93
+ *
94
+ * To get cross-instance coordination on Docker / Node deployments,
95
+ * register a real `LockProvider` (e.g. `alepha/lock/redis`). The default
96
+ * `MemoryLockProvider` is per-process only.
97
+ *
98
+ * @default true
99
+ */
100
+ lock?: boolean;
101
+
89
102
  /**
90
103
  * Max execution time per attempt. Handler receives an `AbortSignal`.
91
104
  */
@@ -0,0 +1,71 @@
1
+ import { $inject, Alepha } from "alepha";
2
+ import { $logger } from "alepha/logger";
3
+ import { JobDispatcher } from "./JobDispatcher.ts";
4
+ import { JobProvider } from "./JobProvider.ts";
5
+
6
+ /**
7
+ * Default `JobDispatcher` for environments without `AlephaApiJobsQueue`.
8
+ *
9
+ * Runs `JobProvider.processExecution` in the background — the caller's
10
+ * `push()` returns immediately while the handler continues to completion
11
+ * in the same process. The DB outbox row is the durability guarantee:
12
+ * if the process dies before the handler finishes, the next sweep tick
13
+ * picks the row up and re-dispatches.
14
+ *
15
+ * **Cloudflare Workers** — when an `executionCtx.waitUntil` is available
16
+ * in the alepha store at `cloudflare.waitUntil`, the dispatch wraps the
17
+ * background promise with `waitUntil` so the runtime keeps the isolate
18
+ * alive past the HTTP response. Without this, the handler would be
19
+ * terminated when the response is returned and only the next sweep
20
+ * (every 5 min by default) would re-dispatch.
21
+ *
22
+ * **Vercel / single-Node** — on long-running runtimes the event loop
23
+ * keeps the promise alive naturally; no special wiring is required.
24
+ */
25
+ export class DirectJobDispatcher extends JobDispatcher {
26
+ public readonly kind = "direct" as const;
27
+
28
+ protected readonly alepha = $inject(Alepha);
29
+ protected readonly log = $logger();
30
+
31
+ // Lazy: resolved on first dispatch to break the JobProvider ↔ Dispatcher
32
+ // injection cycle (JobProvider injects JobDispatcher to dispatch; we need
33
+ // JobProvider to actually run executions).
34
+ protected jobProviderRef?: JobProvider;
35
+ protected getJobProvider(): JobProvider {
36
+ if (!this.jobProviderRef) {
37
+ this.jobProviderRef = this.alepha.inject(JobProvider);
38
+ }
39
+ return this.jobProviderRef;
40
+ }
41
+
42
+ public async dispatch(jobName: string, executionId: string): Promise<void> {
43
+ const promise = this.getJobProvider()
44
+ .processExecution(jobName, executionId)
45
+ .catch((err) => {
46
+ this.log.warn(
47
+ `Direct execution failed for '${jobName}' (sweep will retry)`,
48
+ err,
49
+ );
50
+ });
51
+
52
+ // Cloudflare Workers: keep the isolate alive past the HTTP response so
53
+ // the handler actually finishes. Outside CF this read returns undefined
54
+ // and we fall through to plain fire-and-track.
55
+ const waitUntil = this.alepha.store.get("cloudflare.waitUntil") as
56
+ | ((p: Promise<unknown>) => void)
57
+ | undefined;
58
+ if (typeof waitUntil === "function") {
59
+ try {
60
+ waitUntil(promise);
61
+ } catch (e) {
62
+ // The runtime may reject waitUntil if called outside a request scope.
63
+ // Promise still runs; just log.
64
+ this.log.debug(
65
+ "waitUntil rejected — falling back to fire-and-track",
66
+ e,
67
+ );
68
+ }
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Abstract dispatcher for queued/direct job executions.
3
+ *
4
+ * The default implementation, {@link DirectJobDispatcher}, runs the handler
5
+ * in-process after the caller's `push()` returns — fast and dependency-free.
6
+ *
7
+ * `AlephaApiJobsQueue` substitutes this with `JobQueueProvider`, which
8
+ * publishes the executionId to `AlephaQueue` so a worker pool can consume
9
+ * the work asynchronously.
10
+ *
11
+ * Substitute via DI:
12
+ * ```ts
13
+ * Alepha.create()
14
+ * .with({ provide: JobDispatcher, use: MyCustomDispatcher })
15
+ * .with(AlephaApiJobs);
16
+ * ```
17
+ *
18
+ * The `kind` getter is read by the `JobProvider.effectiveMode` accessor
19
+ * and by the admin UI so users can see which dispatcher is currently active.
20
+ */
21
+ export abstract class JobDispatcher {
22
+ /**
23
+ * Identifier for this dispatcher's effective mode. Reported to the admin
24
+ * UI so operators can see whether `$job` is running in `queue` or
25
+ * `direct` mode.
26
+ */
27
+ public abstract readonly kind: "queue" | "direct";
28
+
29
+ /**
30
+ * Hand off a single execution. The caller's `push()` awaits this so the
31
+ * caller can be sure the dispatch has at least been initiated. Long-running
32
+ * work must NOT be awaited here (use background scheduling instead) — this
33
+ * call should return as quickly as possible.
34
+ */
35
+ public abstract dispatch(jobName: string, executionId: string): Promise<void>;
36
+
37
+ /**
38
+ * Optional batch dispatch. The default implementation loops, but
39
+ * dispatchers backed by a real queue should override this to use the
40
+ * provider's batch send (e.g. Cloudflare Queues `sendBatch`).
41
+ */
42
+ public async dispatchMany(
43
+ items: Array<{ jobName: string; executionId: string }>,
44
+ ): Promise<void> {
45
+ for (const item of items) {
46
+ await this.dispatch(item.jobName, item.executionId);
47
+ }
48
+ }
49
+ }