alepha 0.21.2 → 0.23.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 (519) hide show
  1. package/README.md +0 -1
  2. package/dist/api/audits/index.browser.js.map +1 -1
  3. package/dist/api/audits/index.d.ts +393 -403
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/audits/index.js +25 -56
  6. package/dist/api/audits/index.js.map +1 -1
  7. package/dist/api/files/index.browser.js +31 -1
  8. package/dist/api/files/index.browser.js.map +1 -1
  9. package/dist/api/files/index.d.ts +313 -208
  10. package/dist/api/files/index.d.ts.map +1 -1
  11. package/dist/api/files/index.js +152 -42
  12. package/dist/api/files/index.js.map +1 -1
  13. package/dist/api/jobs/index.browser.js +2 -2
  14. package/dist/api/jobs/index.browser.js.map +1 -1
  15. package/dist/api/jobs/index.d.ts +282 -285
  16. package/dist/api/jobs/index.d.ts.map +1 -1
  17. package/dist/api/jobs/index.js +39 -33
  18. package/dist/api/jobs/index.js.map +1 -1
  19. package/dist/api/keys/index.d.ts +217 -222
  20. package/dist/api/keys/index.d.ts.map +1 -1
  21. package/dist/api/keys/index.js.map +1 -1
  22. package/dist/api/notifications/index.browser.js.map +1 -1
  23. package/dist/api/notifications/index.d.ts +188 -195
  24. package/dist/api/notifications/index.d.ts.map +1 -1
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/oauth/index.d.ts +71 -76
  27. package/dist/api/oauth/index.d.ts.map +1 -1
  28. package/dist/api/oauth/index.js.map +1 -1
  29. package/dist/api/organizations/index.browser.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +104 -109
  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.browser.js +43 -16
  34. package/dist/api/parameters/index.browser.js.map +1 -1
  35. package/dist/api/parameters/index.d.ts +488 -344
  36. package/dist/api/parameters/index.d.ts.map +1 -1
  37. package/dist/api/parameters/index.js +175 -35
  38. package/dist/api/parameters/index.js.map +1 -1
  39. package/dist/api/payments/index.d.ts +396 -402
  40. package/dist/api/payments/index.d.ts.map +1 -1
  41. package/dist/api/payments/index.js.map +1 -1
  42. package/dist/api/subscriptions/index.d.ts +644 -652
  43. package/dist/api/subscriptions/index.d.ts.map +1 -1
  44. package/dist/api/subscriptions/index.js +1 -1
  45. package/dist/api/subscriptions/index.js.map +1 -1
  46. package/dist/api/users/index.browser.js +7 -0
  47. package/dist/api/users/index.browser.js.map +1 -1
  48. package/dist/api/users/index.d.ts +1106 -1005
  49. package/dist/api/users/index.d.ts.map +1 -1
  50. package/dist/api/users/index.js +307 -64
  51. package/dist/api/users/index.js.map +1 -1
  52. package/dist/api/verifications/index.browser.js.map +1 -1
  53. package/dist/api/verifications/index.d.ts +137 -143
  54. package/dist/api/verifications/index.d.ts.map +1 -1
  55. package/dist/api/verifications/index.js.map +1 -1
  56. package/dist/background/index.d.ts +95 -0
  57. package/dist/background/index.d.ts.map +1 -0
  58. package/dist/background/index.js +121 -0
  59. package/dist/background/index.js.map +1 -0
  60. package/dist/background/index.workerd.js +110 -0
  61. package/dist/background/index.workerd.js.map +1 -0
  62. package/dist/batch/index.d.ts +5 -7
  63. package/dist/batch/index.d.ts.map +1 -1
  64. package/dist/batch/index.js.map +1 -1
  65. package/dist/bin/index.js.map +1 -1
  66. package/dist/bucket/index.d.ts +76 -54
  67. package/dist/bucket/index.d.ts.map +1 -1
  68. package/dist/bucket/index.js +58 -11
  69. package/dist/bucket/index.js.map +1 -1
  70. package/dist/bucket/index.workerd.js +200 -5
  71. package/dist/bucket/index.workerd.js.map +1 -1
  72. package/dist/cache/core/index.d.ts +7 -10
  73. package/dist/cache/core/index.d.ts.map +1 -1
  74. package/dist/cache/core/index.js.map +1 -1
  75. package/dist/cache/core/index.workerd.js.map +1 -1
  76. package/dist/cache/database/index.d.ts +22 -26
  77. package/dist/cache/database/index.d.ts.map +1 -1
  78. package/dist/cache/database/index.js.map +1 -1
  79. package/dist/cache/redis/index.d.ts +4 -7
  80. package/dist/cache/redis/index.d.ts.map +1 -1
  81. package/dist/cache/redis/index.js.map +1 -1
  82. package/dist/captcha/index.d.ts +3 -6
  83. package/dist/captcha/index.d.ts.map +1 -1
  84. package/dist/captcha/index.js.map +1 -1
  85. package/dist/cli/config/index.d.ts.map +1 -1
  86. package/dist/cli/config/index.js.map +1 -1
  87. package/dist/cli/core/index.d.ts +458 -249
  88. package/dist/cli/core/index.d.ts.map +1 -1
  89. package/dist/cli/core/index.js +372 -660
  90. package/dist/cli/core/index.js.map +1 -1
  91. package/dist/cli/devtools/index.d.ts +3 -5
  92. package/dist/cli/devtools/index.d.ts.map +1 -1
  93. package/dist/cli/devtools/index.js.map +1 -1
  94. package/dist/cli/i18n/index.d.ts +20 -17
  95. package/dist/cli/i18n/index.d.ts.map +1 -1
  96. package/dist/cli/i18n/index.js +45 -11
  97. package/dist/cli/i18n/index.js.map +1 -1
  98. package/dist/cli/platform/index.d.ts +126 -1342
  99. package/dist/cli/platform/index.d.ts.map +1 -1
  100. package/dist/cli/platform/index.js +136 -2374
  101. package/dist/cli/platform/index.js.map +1 -1
  102. package/dist/cli/platform-lib/index.d.ts +1472 -0
  103. package/dist/cli/platform-lib/index.d.ts.map +1 -0
  104. package/dist/cli/platform-lib/index.js +2660 -0
  105. package/dist/cli/platform-lib/index.js.map +1 -0
  106. package/dist/cli/vendor/index.d.ts +17 -21
  107. package/dist/cli/vendor/index.d.ts.map +1 -1
  108. package/dist/cli/vendor/index.js.map +1 -1
  109. package/dist/command/index.d.ts +20 -19
  110. package/dist/command/index.d.ts.map +1 -1
  111. package/dist/command/index.js +39 -10
  112. package/dist/command/index.js.map +1 -1
  113. package/dist/{containers → container}/core/index.d.ts +13 -15
  114. package/dist/container/core/index.d.ts.map +1 -0
  115. package/dist/{containers → container}/core/index.js +23 -14
  116. package/dist/container/core/index.js.map +1 -0
  117. package/dist/{containers → container}/core/index.workerd.js +37 -22
  118. package/dist/container/core/index.workerd.js.map +1 -0
  119. package/dist/core/index.browser.js +27 -1
  120. package/dist/core/index.browser.js.map +1 -1
  121. package/dist/core/index.d.ts +48 -24
  122. package/dist/core/index.d.ts.map +1 -1
  123. package/dist/core/index.js +27 -1
  124. package/dist/core/index.js.map +1 -1
  125. package/dist/core/index.native.js +27 -1
  126. package/dist/core/index.native.js.map +1 -1
  127. package/dist/core/index.workerd.js +27 -1
  128. package/dist/core/index.workerd.js.map +1 -1
  129. package/dist/crypto/index.browser.js.map +1 -1
  130. package/dist/crypto/index.d.ts +5 -8
  131. package/dist/crypto/index.d.ts.map +1 -1
  132. package/dist/crypto/index.js.map +1 -1
  133. package/dist/datetime/index.d.ts +3 -4
  134. package/dist/datetime/index.d.ts.map +1 -1
  135. package/dist/datetime/index.js.map +1 -1
  136. package/dist/email/brevo/index.d.ts +2 -4
  137. package/dist/email/brevo/index.d.ts.map +1 -1
  138. package/dist/email/brevo/index.js.map +1 -1
  139. package/dist/email/cloudflare/index.d.ts +20 -7
  140. package/dist/email/cloudflare/index.d.ts.map +1 -1
  141. package/dist/email/cloudflare/index.js +46 -9
  142. package/dist/email/cloudflare/index.js.map +1 -1
  143. package/dist/email/core/index.d.ts +6 -9
  144. package/dist/email/core/index.d.ts.map +1 -1
  145. package/dist/email/core/index.js.map +1 -1
  146. package/dist/email/core/index.workerd.js.map +1 -1
  147. package/dist/email/smtp/index.d.ts +10 -13
  148. package/dist/email/smtp/index.d.ts.map +1 -1
  149. package/dist/email/smtp/index.js +107 -32
  150. package/dist/email/smtp/index.js.map +1 -1
  151. package/dist/fake/index.d.ts +1 -2
  152. package/dist/fake/index.d.ts.map +1 -1
  153. package/dist/fake/index.js.map +1 -1
  154. package/dist/lock/core/index.d.ts +9 -14
  155. package/dist/lock/core/index.d.ts.map +1 -1
  156. package/dist/lock/core/index.js.map +1 -1
  157. package/dist/lock/redis/index.d.ts +2 -4
  158. package/dist/lock/redis/index.d.ts.map +1 -1
  159. package/dist/lock/redis/index.js.map +1 -1
  160. package/dist/logger/index.d.ts +105 -76
  161. package/dist/logger/index.d.ts.map +1 -1
  162. package/dist/logger/index.js +196 -174
  163. package/dist/logger/index.js.map +1 -1
  164. package/dist/mcp/index.d.ts +25 -20
  165. package/dist/mcp/index.d.ts.map +1 -1
  166. package/dist/mcp/index.js +23 -0
  167. package/dist/mcp/index.js.map +1 -1
  168. package/dist/orm/core/index.browser.js.map +1 -1
  169. package/dist/orm/core/index.bun.js +19 -1
  170. package/dist/orm/core/index.bun.js.map +1 -1
  171. package/dist/orm/core/index.d.ts +76 -62
  172. package/dist/orm/core/index.d.ts.map +1 -1
  173. package/dist/orm/core/index.js +20 -2
  174. package/dist/orm/core/index.js.map +1 -1
  175. package/dist/orm/postgres/index.bun.js.map +1 -1
  176. package/dist/orm/postgres/index.d.ts +28 -20
  177. package/dist/orm/postgres/index.d.ts.map +1 -1
  178. package/dist/orm/postgres/index.js.map +1 -1
  179. package/dist/queue/core/index.d.ts +12 -15
  180. package/dist/queue/core/index.d.ts.map +1 -1
  181. package/dist/queue/core/index.js.map +1 -1
  182. package/dist/queue/core/index.workerd.js.map +1 -1
  183. package/dist/queue/redis/index.d.ts +3 -5
  184. package/dist/queue/redis/index.d.ts.map +1 -1
  185. package/dist/queue/redis/index.js.map +1 -1
  186. package/dist/react/auth/index.browser.js +9 -2
  187. package/dist/react/auth/index.browser.js.map +1 -1
  188. package/dist/react/auth/index.d.ts +14 -9
  189. package/dist/react/auth/index.d.ts.map +1 -1
  190. package/dist/react/auth/index.js +9 -2
  191. package/dist/react/auth/index.js.map +1 -1
  192. package/dist/react/core/index.d.ts +7 -8
  193. package/dist/react/core/index.d.ts.map +1 -1
  194. package/dist/react/core/index.js +6 -3
  195. package/dist/react/core/index.js.map +1 -1
  196. package/dist/react/form/index.d.ts +2 -5
  197. package/dist/react/form/index.d.ts.map +1 -1
  198. package/dist/react/form/index.js +16 -15
  199. package/dist/react/form/index.js.map +1 -1
  200. package/dist/react/head/index.browser.js.map +1 -1
  201. package/dist/react/head/index.d.ts +2 -4
  202. package/dist/react/head/index.d.ts.map +1 -1
  203. package/dist/react/head/index.js.map +1 -1
  204. package/dist/react/i18n/index.d.ts +90 -11
  205. package/dist/react/i18n/index.d.ts.map +1 -1
  206. package/dist/react/i18n/index.js +147 -11
  207. package/dist/react/i18n/index.js.map +1 -1
  208. package/dist/react/intro/index.d.ts +1 -2
  209. package/dist/react/intro/index.d.ts.map +1 -1
  210. package/dist/react/intro/index.js +2 -2
  211. package/dist/react/intro/index.js.map +1 -1
  212. package/dist/react/router/index.browser.js +193 -24
  213. package/dist/react/router/index.browser.js.map +1 -1
  214. package/dist/react/router/index.d.ts +434 -222
  215. package/dist/react/router/index.d.ts.map +1 -1
  216. package/dist/react/router/index.js +249 -35
  217. package/dist/react/router/index.js.map +1 -1
  218. package/dist/react/sitemap/index.browser.js +35 -0
  219. package/dist/react/sitemap/index.browser.js.map +1 -0
  220. package/dist/react/sitemap/index.d.ts +92 -0
  221. package/dist/react/sitemap/index.d.ts.map +1 -0
  222. package/dist/react/sitemap/index.js +131 -0
  223. package/dist/react/sitemap/index.js.map +1 -0
  224. package/dist/react/testing/index.d.ts +1 -2
  225. package/dist/react/testing/index.d.ts.map +1 -1
  226. package/dist/react/testing/index.js +16 -17
  227. package/dist/react/testing/index.js.map +1 -1
  228. package/dist/react/ui/index.d.ts +20 -25
  229. package/dist/react/ui/index.d.ts.map +1 -1
  230. package/dist/react/ui/index.js.map +1 -1
  231. package/dist/redis/index.bun.js.map +1 -1
  232. package/dist/redis/index.d.ts +17 -19
  233. package/dist/redis/index.d.ts.map +1 -1
  234. package/dist/redis/index.js.map +1 -1
  235. package/dist/retry/index.d.ts +2 -4
  236. package/dist/retry/index.d.ts.map +1 -1
  237. package/dist/retry/index.js.map +1 -1
  238. package/dist/router/index.d.ts.map +1 -1
  239. package/dist/router/index.js.map +1 -1
  240. package/dist/scheduler/index.d.ts +10 -13
  241. package/dist/scheduler/index.d.ts.map +1 -1
  242. package/dist/scheduler/index.js.map +1 -1
  243. package/dist/scheduler/index.workerd.js.map +1 -1
  244. package/dist/security/index.browser.js.map +1 -1
  245. package/dist/security/index.d.ts +45 -48
  246. package/dist/security/index.d.ts.map +1 -1
  247. package/dist/security/index.js.map +1 -1
  248. package/dist/server/auth/index.browser.js.map +1 -1
  249. package/dist/server/auth/index.d.ts +272 -173
  250. package/dist/server/auth/index.d.ts.map +1 -1
  251. package/dist/server/auth/index.js +1608 -15
  252. package/dist/server/auth/index.js.map +1 -1
  253. package/dist/server/cookies/index.browser.js.map +1 -1
  254. package/dist/server/cookies/index.d.ts +20 -7
  255. package/dist/server/cookies/index.d.ts.map +1 -1
  256. package/dist/server/cookies/index.js +22 -3
  257. package/dist/server/cookies/index.js.map +1 -1
  258. package/dist/server/core/index.browser.js.map +1 -1
  259. package/dist/server/core/index.d.ts +106 -73
  260. package/dist/server/core/index.d.ts.map +1 -1
  261. package/dist/server/core/index.js +44 -0
  262. package/dist/server/core/index.js.map +1 -1
  263. package/dist/server/cors/index.d.ts +11 -14
  264. package/dist/server/cors/index.d.ts.map +1 -1
  265. package/dist/server/cors/index.js.map +1 -1
  266. package/dist/server/etag/index.d.ts +6 -9
  267. package/dist/server/etag/index.d.ts.map +1 -1
  268. package/dist/server/etag/index.js.map +1 -1
  269. package/dist/server/health/index.d.ts +18 -21
  270. package/dist/server/health/index.d.ts.map +1 -1
  271. package/dist/server/health/index.js.map +1 -1
  272. package/dist/server/links/index.browser.js +2 -0
  273. package/dist/server/links/index.browser.js.map +1 -1
  274. package/dist/server/links/index.d.ts +63 -67
  275. package/dist/server/links/index.d.ts.map +1 -1
  276. package/dist/server/links/index.js +2 -0
  277. package/dist/server/links/index.js.map +1 -1
  278. package/dist/server/metrics/index.d.ts +5 -7
  279. package/dist/server/metrics/index.d.ts.map +1 -1
  280. package/dist/server/metrics/index.js.map +1 -1
  281. package/dist/server/proxy/index.d.ts +3 -5
  282. package/dist/server/proxy/index.d.ts.map +1 -1
  283. package/dist/server/proxy/index.js.map +1 -1
  284. package/dist/server/rate-limit/index.d.ts +10 -13
  285. package/dist/server/rate-limit/index.d.ts.map +1 -1
  286. package/dist/server/rate-limit/index.js.map +1 -1
  287. package/dist/server/static/index.d.ts +3 -5
  288. package/dist/server/static/index.d.ts.map +1 -1
  289. package/dist/server/static/index.js.map +1 -1
  290. package/dist/server/swagger/index.d.ts +5 -8
  291. package/dist/server/swagger/index.d.ts.map +1 -1
  292. package/dist/server/swagger/index.js.map +1 -1
  293. package/dist/sms/index.d.ts +3 -5
  294. package/dist/sms/index.d.ts.map +1 -1
  295. package/dist/sms/index.js.map +1 -1
  296. package/dist/system/index.browser.js.map +1 -1
  297. package/dist/system/index.d.ts +2 -4
  298. package/dist/system/index.d.ts.map +1 -1
  299. package/dist/system/index.js.map +1 -1
  300. package/dist/system/index.workerd.js.map +1 -1
  301. package/dist/topic/core/index.d.ts +4 -6
  302. package/dist/topic/core/index.d.ts.map +1 -1
  303. package/dist/topic/core/index.js.map +1 -1
  304. package/dist/topic/redis/index.d.ts +5 -8
  305. package/dist/topic/redis/index.d.ts.map +1 -1
  306. package/dist/topic/redis/index.js.map +1 -1
  307. package/package.json +59 -23
  308. package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
  309. package/src/api/audits/controllers/AdminAuditController.ts +14 -0
  310. package/src/api/audits/services/AuditService.ts +21 -88
  311. package/src/api/files/__tests__/FileService.spec.ts +207 -2
  312. package/src/api/files/index.ts +3 -0
  313. package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
  314. package/src/api/files/schemas/fileResourceSchema.ts +10 -1
  315. package/src/api/files/services/FileService.ts +170 -72
  316. package/src/api/jobs/__tests__/$job.spec.ts +24 -1
  317. package/src/api/jobs/index.ts +4 -3
  318. package/src/api/jobs/primitives/$job.ts +7 -3
  319. package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
  320. package/src/api/jobs/providers/JobProvider.ts +53 -24
  321. package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
  322. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
  323. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
  324. package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
  325. package/src/api/parameters/audits/ParameterAudits.ts +17 -0
  326. package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
  327. package/src/api/parameters/index.ts +3 -0
  328. package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
  329. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
  330. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
  331. package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
  332. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
  333. package/src/api/parameters/services/ParameterProvider.ts +69 -6
  334. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
  335. package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
  336. package/src/api/users/audits/SessionAudits.ts +33 -0
  337. package/src/api/users/audits/UserAudits.ts +19 -43
  338. package/src/api/users/controllers/AdminUserController.ts +66 -1
  339. package/src/api/users/controllers/RealmController.ts +1 -0
  340. package/src/api/users/entities/sessions.ts +6 -0
  341. package/src/api/users/entities/users.ts +2 -0
  342. package/src/api/users/index.ts +9 -1
  343. package/src/api/users/primitives/$realm.ts +29 -0
  344. package/src/api/users/providers/RealmProvider.ts +15 -0
  345. package/src/api/users/schemas/realmConfigSchema.ts +14 -0
  346. package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
  347. package/src/api/users/schemas/updateUserSchema.ts +1 -8
  348. package/src/api/users/schemas/userQuerySchema.ts +7 -0
  349. package/src/api/users/services/CredentialService.ts +15 -6
  350. package/src/api/users/services/IdentityService.ts +2 -1
  351. package/src/api/users/services/RegistrationService.ts +2 -1
  352. package/src/api/users/services/SessionCrudService.ts +19 -2
  353. package/src/api/users/services/SessionService.ts +39 -19
  354. package/src/api/users/services/UserService.ts +106 -8
  355. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
  356. package/src/background/index.ts +37 -0
  357. package/src/background/index.workerd.ts +28 -0
  358. package/src/background/providers/BackgroundTaskProvider.ts +70 -0
  359. package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
  360. package/src/bucket/__tests__/$bucket.spec.ts +18 -0
  361. package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
  362. package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
  363. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
  364. package/src/bucket/__tests__/shared.ts +30 -0
  365. package/src/bucket/index.ts +5 -5
  366. package/src/bucket/index.workerd.ts +11 -4
  367. package/src/bucket/primitives/$bucket.ts +27 -0
  368. package/src/bucket/providers/FileStorageProvider.ts +13 -0
  369. package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
  370. package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
  371. package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
  372. package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
  373. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
  374. package/src/cli/core/__tests__/init.spec.ts +0 -219
  375. package/src/cli/core/atoms/buildOptions.ts +0 -12
  376. package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
  377. package/src/cli/core/commands/build.ts +105 -37
  378. package/src/cli/core/commands/init.ts +0 -12
  379. package/src/cli/core/commands/pack.ts +133 -0
  380. package/src/cli/core/index.ts +3 -3
  381. package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
  382. package/src/cli/core/services/PackageManagerUtils.ts +0 -16
  383. package/src/cli/core/services/ProjectScaffolder.ts +29 -291
  384. package/src/cli/core/tasks/BuildCloudflareTask.ts +382 -56
  385. package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
  386. package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
  387. package/src/cli/core/tasks/BuildTask.ts +34 -0
  388. package/src/cli/core/templates/apiIndexTs.ts +1 -22
  389. package/src/cli/core/templates/mainCss.ts +0 -1
  390. package/src/cli/core/templates/webAppRouterTs.ts +0 -99
  391. package/src/cli/core/templates/webIndexTs.ts +1 -22
  392. package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +48 -0
  393. package/src/cli/i18n/services/I18nCheckService.ts +65 -11
  394. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
  395. package/src/cli/platform/commands/SecretsCommand.ts +8 -6
  396. package/src/cli/platform/commands/platform.ts +192 -46
  397. package/src/cli/platform/index.ts +12 -52
  398. package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
  399. package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
  400. package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
  401. package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +519 -190
  402. package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
  403. package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
  404. package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
  405. package/src/cli/platform-lib/index.ts +67 -0
  406. package/src/cli/platform-lib/services/NamingService.ts +136 -0
  407. package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
  408. package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
  409. package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
  410. package/src/command/__tests__/Runner.spec.ts +20 -0
  411. package/src/command/helpers/EnvUtils.ts +19 -3
  412. package/src/command/helpers/Runner.ts +12 -2
  413. package/src/command/providers/CliProvider.ts +34 -1
  414. package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
  415. package/src/{containers → container}/core/index.ts +4 -4
  416. package/src/{containers → container}/core/index.workerd.ts +19 -3
  417. package/src/{containers → container}/core/primitives/$container.ts +1 -1
  418. package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
  419. package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
  420. package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
  421. package/src/core/Alepha.ts +49 -1
  422. package/src/core/__tests__/$env.spec.ts +42 -0
  423. package/src/core/__tests__/dump.spec.ts +47 -0
  424. package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
  425. package/src/email/cloudflare/index.ts +14 -5
  426. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
  427. package/src/logger/__tests__/Logger.spec.ts +55 -0
  428. package/src/logger/index.ts +13 -0
  429. package/src/logger/services/Logger.ts +31 -1
  430. package/src/mcp/__tests__/McpServerProvider.spec.ts +71 -0
  431. package/src/mcp/providers/McpServerProvider.ts +55 -0
  432. package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
  433. package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
  434. package/src/orm/core/interfaces/PgQuery.ts +4 -1
  435. package/src/orm/core/services/Repository.ts +27 -11
  436. package/src/react/auth/hooks/useAuth.ts +10 -5
  437. package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
  438. package/src/react/core/hooks/useAction.ts +14 -3
  439. package/src/react/core/hooks/useQuery.ts +24 -4
  440. package/src/react/form/__tests__/FormModel-submit-loading.spec.ts +71 -0
  441. package/src/react/form/__tests__/form-submitting-reactive.browser.spec.tsx +96 -0
  442. package/src/react/form/services/FormModel.ts +57 -39
  443. package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
  444. package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
  445. package/src/react/i18n/components/Translate.tsx +47 -0
  446. package/src/react/i18n/index.ts +2 -0
  447. package/src/react/i18n/providers/I18nProvider.ts +171 -12
  448. package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
  449. package/src/react/router/__tests__/$page.spec.tsx +3 -2
  450. package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
  451. package/src/react/router/__tests__/page-can.spec.ts +18 -13
  452. package/src/react/router/hooks/useQueryParams.ts +114 -14
  453. package/src/react/router/index.browser.ts +4 -0
  454. package/src/react/router/index.shared.ts +1 -0
  455. package/src/react/router/index.ts +9 -0
  456. package/src/react/router/primitives/$page.ts +85 -4
  457. package/src/react/router/providers/ReactBrowserRouterProvider.ts +18 -8
  458. package/src/react/router/providers/ReactPageProvider.ts +12 -1
  459. package/src/react/router/providers/ReactServerProvider.ts +96 -14
  460. package/src/react/router/providers/RootComponentsProvider.ts +13 -0
  461. package/src/react/router/providers/RouterLocaleProvider.ts +125 -0
  462. package/src/react/router/providers/__tests__/RootComponentsProvider.spec.ts +15 -0
  463. package/src/react/router/providers/__tests__/rootComponents.ssr.browser.spec.tsx +67 -0
  464. package/src/react/sitemap/__tests__/$sitemap.spec.ts +131 -0
  465. package/src/react/sitemap/index.browser.ts +21 -0
  466. package/src/react/sitemap/index.ts +25 -0
  467. package/src/react/sitemap/primitives/$sitemap.browser.ts +26 -0
  468. package/src/react/sitemap/primitives/$sitemap.ts +196 -0
  469. package/src/react/ui/services/SchemaControl.ts +3 -4
  470. package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
  471. package/src/server/auth/__tests__/authFederationClient.spec.ts +40 -0
  472. package/src/server/auth/__tests__/federationAssertion.spec.ts +146 -0
  473. package/src/server/auth/__tests__/federationRedirectReplay.spec.ts +44 -0
  474. package/src/server/auth/helpers/appleClientSecret.ts +24 -0
  475. package/src/server/auth/helpers/federationAssertion.ts +74 -0
  476. package/src/server/auth/helpers/jtiReplayGuard.ts +41 -0
  477. package/src/server/auth/helpers/safeRedirectPath.ts +19 -0
  478. package/src/server/auth/index.ts +4 -0
  479. package/src/server/auth/primitives/$authFederationBroker.ts +273 -0
  480. package/src/server/auth/primitives/$authFederationClient.ts +89 -0
  481. package/src/server/auth/providers/ServerAuthProvider.ts +18 -4
  482. package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +70 -0
  483. package/src/server/cookies/providers/ServerCookiesProvider.ts +23 -3
  484. package/src/server/core/interfaces/ServerRequest.ts +8 -0
  485. package/src/server/core/primitives/$route.ts +27 -0
  486. package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
  487. package/src/server/links/providers/LinkProvider.ts +10 -0
  488. package/dist/containers/core/index.d.ts.map +0 -1
  489. package/dist/containers/core/index.js.map +0 -1
  490. package/dist/containers/core/index.workerd.js.map +0 -1
  491. package/src/cli/core/tasks/BuildSitemapTask.ts +0 -130
  492. package/src/cli/core/templates/componentsJsonTs.ts +0 -39
  493. package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
  494. package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
  495. package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
  496. package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
  497. package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
  498. package/src/cli/platform/services/NamingService.ts +0 -54
  499. /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
  500. /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
  501. /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
  502. /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
  503. /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
  504. /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
  505. /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
  506. /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
  507. /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
  508. /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
  509. /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
  510. /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
  511. /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
  512. /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
  513. /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
  514. /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
  515. /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
  516. /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
  517. /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
  518. /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
  519. /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
@@ -1,22 +1,113 @@
1
1
  import { basename } from "node:path";
2
2
  import { $inject } from "alepha";
3
3
  import { KV_DEFAULT_BINDING } from "alepha/cache";
4
- import { $container, type ContainerPrimitive } from "alepha/containers";
5
- import { EmailProvider } from "alepha/email";
6
- import {
7
- CloudflareEmailProvider,
8
- SEND_EMAIL_DEFAULT_BINDING,
9
- } from "alepha/email/cloudflare";
4
+ import type { ContainerPrimitive } from "alepha/container";
5
+ import { SEND_EMAIL_DEFAULT_BINDING } from "alepha/email/cloudflare";
10
6
  import { QUEUE_DEFAULT_BINDING } from "alepha/queue";
11
7
  import type { CronProvider, WorkerdCronProvider } from "alepha/scheduler";
12
8
  import { FileSystemProvider } from "alepha/system";
13
9
  import { ViteUtils } from "../services/ViteUtils.ts";
14
10
  import { BuildTask, type BuildTaskContext } from "./BuildTask.ts";
15
11
 
12
+ // Looked up by class name string (not by class identity) because
13
+ // BuildCloudflareTask runs in the CLI's Alepha context while ctx.alepha
14
+ // is the workspace's separate context. Two module graphs = two distinct
15
+ // `CloudflareEmailProvider` class objects, so the imported reference
16
+ // here wouldn't match the one the workspace registered.
17
+ const CLOUDFLARE_EMAIL_PROVIDER_NAME = "CloudflareEmailProvider";
18
+
16
19
  interface WranglerConfig {
17
20
  [key: string]: any;
18
21
  }
19
22
 
23
+ /**
24
+ * Build-time snapshot describing what the workspace needs at deploy
25
+ * time. Written to `dist/manifest.json` alongside `wrangler.jsonc`.
26
+ *
27
+ * Lets `alepha platform up --prebuilt` skip the Vite-based
28
+ * introspection step on the deploy side — and lets Alepha Rocket skip
29
+ * the workspace's runtime `npm install` because no app source is
30
+ * booted at deploy time. The manifest captures the bits of primitive
31
+ * data that the deploy steps (provision, secrets, hooks) need to
32
+ * know.
33
+ */
34
+ export interface BuildManifest {
35
+ version: 1;
36
+ project: string;
37
+ /**
38
+ * Default environment when `--env` is omitted at deploy time.
39
+ * Captured from `platformOptions.default` (defaults to `"production"`).
40
+ */
41
+ defaultEnv: string;
42
+ /**
43
+ * Multi-tenancy mode (`none` | `optional` | `required`). Captured from
44
+ * `platformOptions.tenancy` so the prebuilt deploy side (Rocket) can
45
+ * validate `--tenant` without re-evaluating `alepha.config.ts`.
46
+ */
47
+ tenancy?: "none" | "optional" | "required";
48
+ /**
49
+ * Resolved `platform({ environments: ... })` map. Captured at build
50
+ * time from the workspace's `alepha.config.ts` so the deploy side
51
+ * doesn't need to re-evaluate the config. Each value is the same
52
+ * `EnvironmentConfig` shape consumed by the orchestrator (adapter,
53
+ * domain, zone, jurisdiction, accountId).
54
+ */
55
+ environments: Record<
56
+ string,
57
+ {
58
+ adapter: "cloudflare" | "vercel";
59
+ domain?: string;
60
+ zone?: string;
61
+ jurisdiction?: "eu" | "fedramp";
62
+ accountId?: string;
63
+ }
64
+ >;
65
+ resources: {
66
+ hasDatabase: boolean;
67
+ hasBucket: boolean;
68
+ hasKV: boolean;
69
+ hasQueue: boolean;
70
+ hasCron: boolean;
71
+ };
72
+ /**
73
+ * All distinct cron expressions registered by `$scheduler`
74
+ * primitives. Empty when `hasCron` is false.
75
+ */
76
+ crons: string[];
77
+ /**
78
+ * Cloudflare email binding, captured when the app registers
79
+ * `CloudflareEmailProvider` at artifact-build time. The prebuilt/manifest
80
+ * deploy path (Alepha Rocket `--prebuilt`) has no Vite introspection, so it
81
+ * reads this to re-emit the `send_email` wrangler binding. Absent when the
82
+ * app doesn't use Cloudflare email.
83
+ */
84
+ email?: { binding: string };
85
+ /**
86
+ * `$container()` descriptors — image, port, lifecycle settings.
87
+ * Used both to populate Cloudflare Containers bindings in
88
+ * wrangler.jsonc and (in future) to know which images Rocket should
89
+ * pull on the deploy side.
90
+ */
91
+ containers: Array<{
92
+ name: string;
93
+ className: string;
94
+ image: string;
95
+ port: number;
96
+ sleepAfter: string;
97
+ instanceType: string;
98
+ maxInstances: number;
99
+ }>;
100
+ /**
101
+ * Every env var the app declares via `$env`, captured from
102
+ * `alepha.dump().env` at build time. The deploy `secrets` step uses this
103
+ * as the worker-secret allowlist (minus build/binding vars) so CI can
104
+ * deliver secrets straight from `process.env` without a `.env` file —
105
+ * `platform.secrets.keys` overrides it when set. Empty when introspection
106
+ * was unavailable (older artifacts / prebuilt mode).
107
+ */
108
+ env: string[];
109
+ }
110
+
20
111
  /**
21
112
  * Generate Cloudflare Workers deployment configuration.
22
113
  *
@@ -52,7 +143,15 @@ export class BuildCloudflareTask extends BuildTask {
52
143
  distDir: string,
53
144
  ): Promise<void> {
54
145
  const root = ctx.root;
55
- const name = basename(root);
146
+ // Slugify the dir basename — wrangler rejects names that aren't
147
+ // `^[a-z0-9-]+$` (no uppercase, dots, underscores, spaces, etc.).
148
+ // Without this, running `alepha build -t cloudflare` in a dir like
149
+ // `My App` or `club-0.0.2` produces an unusable `wrangler.jsonc`.
150
+ const name = basename(root)
151
+ .toLowerCase()
152
+ .replace(/[^a-z0-9-]+/g, "-")
153
+ .replace(/^-+|-+$/g, "")
154
+ .slice(0, 63);
56
155
  const hasAssets = await this.fs.exists(
57
156
  this.fs.join(root, distDir, "public"),
58
157
  );
@@ -98,9 +197,137 @@ export class BuildCloudflareTask extends BuildTask {
98
197
  JSON.stringify(wrangler, null, 2),
99
198
  );
100
199
 
200
+ // Only write a fresh manifest when we discovered it from a booted
201
+ // Alepha instance. In manifest mode (ctx.manifest != null) we're
202
+ // re-emitting the same data we just read — skip to avoid a redundant
203
+ // write and to keep the original manifest as the canonical record.
204
+ if (!ctx.manifest) {
205
+ await this.writeManifest(ctx, root, distDir, name, containers);
206
+ }
101
207
  await this.writeWorkerEntryPoint(root, distDir, containers);
102
208
  }
103
209
 
210
+ /**
211
+ * Write `dist/manifest.json` — a build-time snapshot of everything
212
+ * downstream tooling needs to know about the app without re-booting
213
+ * it. Used by `alepha platform up --prebuilt` (and Alepha Rocket) so
214
+ * the deploy path can skip the Vite-based introspection step and the
215
+ * workspace's runtime npm install.
216
+ */
217
+ protected async writeManifest(
218
+ ctx: BuildTaskContext,
219
+ root: string,
220
+ distDir: string,
221
+ name: string,
222
+ containers: ContainerDescriptor[],
223
+ ): Promise<void> {
224
+ // Discover the same primitive shapes the enhance* methods read.
225
+ // Errors are silently swallowed — an absent primitive class just
226
+ // means the app doesn't use that resource.
227
+ let hasDatabase = false;
228
+ let hasBucket = false;
229
+ let hasKV = false;
230
+ let hasQueue = false;
231
+ let crons: string[] = [];
232
+
233
+ try {
234
+ const repo = ctx.alepha.inject("RepositoryProvider") as {
235
+ getRepositories?: () => unknown[];
236
+ };
237
+ hasDatabase = (repo.getRepositories?.() ?? []).length > 0;
238
+ } catch {}
239
+
240
+ try {
241
+ hasBucket = ctx.alepha.primitives("$bucket").length > 0;
242
+ } catch {}
243
+
244
+ try {
245
+ // Only count $cache primitives without an explicit `provider`
246
+ // option — those fall back to KV on workerd. Explicit memory /
247
+ // Redis / Postgres providers opt out of KV provisioning.
248
+ hasKV =
249
+ ctx.alepha
250
+ .primitives("cache")
251
+ .filter(
252
+ (p) =>
253
+ (p as { options?: { provider?: unknown } }).options?.provider ==
254
+ null,
255
+ ).length > 0;
256
+ } catch {}
257
+
258
+ try {
259
+ hasQueue = ctx.alepha.primitives("$queue").length > 0;
260
+ } catch {}
261
+
262
+ try {
263
+ const cronProvider = ctx.alepha.inject("CronProvider") as {
264
+ getCronJobs?: () => Array<{ expression: string }>;
265
+ };
266
+ crons = [
267
+ ...new Set(
268
+ (cronProvider.getCronJobs?.() ?? []).map((c) => c.expression),
269
+ ),
270
+ ];
271
+ } catch {}
272
+
273
+ // platformOptions come from the CLI's Alepha instance (where
274
+ // alepha.config.ts ran during the configure hook). BuildCommand
275
+ // reads them up there and threads them via ctx — ctx.alepha here
276
+ // is the WORKSPACE's Vite-booted Alepha, which never saw the
277
+ // platform options.
278
+ const defaultEnv = ctx.platformOptions?.default ?? "production";
279
+ const environments = (ctx.platformOptions?.environments ??
280
+ {}) as BuildManifest["environments"];
281
+
282
+ // Every declared `$env` key. dump() force-instantiates the graph (no
283
+ // start/ready hooks), so this is the full env surface — used by the
284
+ // deploy `secrets` step as the worker-secret allowlist.
285
+ let env: string[] = [];
286
+ try {
287
+ env = Object.keys(ctx.alepha.dump().env).sort();
288
+ } catch {}
289
+
290
+ // Capture the CF email binding so manifest-mode deploys (Rocket) can
291
+ // re-emit `send_email` — `enhanceEmail` can't introspect there.
292
+ let email: BuildManifest["email"];
293
+ try {
294
+ ctx.alepha.inject(CLOUDFLARE_EMAIL_PROVIDER_NAME);
295
+ email = { binding: SEND_EMAIL_DEFAULT_BINDING };
296
+ } catch {}
297
+
298
+ const manifest: BuildManifest = {
299
+ version: 1,
300
+ project: name,
301
+ defaultEnv,
302
+ tenancy: ctx.platformOptions?.tenancy,
303
+ environments,
304
+ resources: {
305
+ hasDatabase,
306
+ hasBucket,
307
+ hasKV,
308
+ hasQueue,
309
+ hasCron: crons.length > 0,
310
+ },
311
+ crons,
312
+ containers: containers.map((c) => ({
313
+ name: c.name,
314
+ className: c.className,
315
+ image: c.image,
316
+ port: c.port,
317
+ sleepAfter: c.sleepAfter,
318
+ instanceType: c.instanceType,
319
+ maxInstances: c.maxInstances,
320
+ })),
321
+ email,
322
+ env,
323
+ };
324
+
325
+ await this.fs.writeFile(
326
+ this.fs.join(root, distDir, "manifest.json"),
327
+ JSON.stringify(manifest, null, 2),
328
+ );
329
+ }
330
+
104
331
  protected enhanceDomain(wrangler: WranglerConfig): void {
105
332
  const domain = process.env.CLOUDFLARE_DOMAIN;
106
333
  if (!domain) {
@@ -132,23 +359,29 @@ export class BuildCloudflareTask extends BuildTask {
132
359
  }
133
360
 
134
361
  protected enhanceCron(ctx: BuildTaskContext, wrangler: WranglerConfig): void {
135
- if (ctx.alepha.primitives("scheduler").length === 0) {
362
+ const cronExpressions = ctx.manifest
363
+ ? ctx.manifest.crons
364
+ : this.discoverCrons(ctx);
365
+ if (cronExpressions.length === 0) {
136
366
  return;
137
367
  }
368
+ wrangler.triggers ??= {};
369
+ wrangler.triggers.crons = cronExpressions;
370
+ }
138
371
 
372
+ protected discoverCrons(ctx: BuildTaskContext): string[] {
373
+ if (ctx.alepha.primitives("scheduler").length === 0) {
374
+ return [];
375
+ }
139
376
  let cronProvider: CronProvider | undefined;
140
377
  try {
141
378
  cronProvider = ctx.alepha.inject("CronProvider") as WorkerdCronProvider;
142
379
  } catch {}
143
-
144
380
  const crons = cronProvider?.getCronJobs();
145
381
  if (!crons || crons.length === 0) {
146
- return;
382
+ return [];
147
383
  }
148
-
149
- const cronExpressions = [...new Set(crons.map((c) => c.expression))];
150
- wrangler.triggers ??= {};
151
- wrangler.triggers.crons = cronExpressions;
384
+ return [...new Set(crons.map((c) => c.expression))];
152
385
  }
153
386
 
154
387
  protected enhanceDatabase(wrangler: WranglerConfig): void {
@@ -256,33 +489,44 @@ export class BuildCloudflareTask extends BuildTask {
256
489
  ctx: BuildTaskContext,
257
490
  wrangler: WranglerConfig,
258
491
  ): void {
259
- let provider: EmailProvider | undefined;
260
- try {
261
- provider = ctx.alepha.inject(EmailProvider);
262
- } catch {
263
- return;
492
+ // Resolve the CF email binding from whichever source this build path has:
493
+ // - manifest/prebuilt mode (Alepha Rocket `--prebuilt`): no app boot, so
494
+ // read the binding captured into the manifest at artifact-build time.
495
+ // Without this the deploy silently drops `send_email` and the worker
496
+ // boots with email inert (binding not found).
497
+ // - full Vite introspection (`ctx.alepha`, no manifest): probe for the
498
+ // registered CloudflareEmailProvider.
499
+ let binding: string | undefined;
500
+ if (ctx.manifest) {
501
+ binding = ctx.manifest.email?.binding;
502
+ } else if (ctx.alepha) {
503
+ try {
504
+ ctx.alepha.inject(CLOUDFLARE_EMAIL_PROVIDER_NAME);
505
+ binding = SEND_EMAIL_DEFAULT_BINDING;
506
+ } catch {
507
+ // app doesn't use CloudflareEmailProvider — nothing to emit
508
+ }
264
509
  }
265
-
266
- if (!(provider instanceof CloudflareEmailProvider)) {
510
+ if (!binding) {
267
511
  return;
268
512
  }
269
513
 
270
514
  wrangler.send_email = wrangler.send_email || [];
271
- if (
272
- wrangler.send_email.some(
273
- (b: { name: string }) => b.name === SEND_EMAIL_DEFAULT_BINDING,
274
- )
275
- ) {
515
+ if (wrangler.send_email.some((b: { name: string }) => b.name === binding)) {
276
516
  return;
277
517
  }
278
518
 
279
- const entry: Record<string, unknown> = { name: SEND_EMAIL_DEFAULT_BINDING };
280
- const destination = process.env.EMAIL_FROM;
281
- if (destination) {
282
- entry.destination_address = destination;
283
- }
284
-
285
- wrangler.send_email.push(entry);
519
+ // NOTE: do NOT set `destination_address` here. On a Cloudflare
520
+ // `send_email` binding, `destination_address` is a *recipient* allow-list
521
+ // lock (the worker may then only send TO that one address) — it is not the
522
+ // sender. Setting it to `EMAIL_FROM` (the sender) broke all outbound mail:
523
+ // a bare address locked delivery to that single recipient ("email to … not
524
+ // allowed"), and a display-name form like `Lore <noreply@…>` is a malformed
525
+ // destination value that Cloudflare rejects with "internal error". The
526
+ // sender goes in the message `from` field (see CloudflareEmailProvider.send);
527
+ // leaving the binding unrestricted lets the worker send to any verified
528
+ // destination.
529
+ wrangler.send_email.push({ name: binding });
286
530
  }
287
531
 
288
532
  /**
@@ -295,18 +539,19 @@ export class BuildCloudflareTask extends BuildTask {
295
539
  * `writeWorkerEntryPoint` can emit `export class <NAME> extends
296
540
  * Container` declarations referencing them.
297
541
  */
298
- protected enhanceContainers(
299
- ctx: BuildTaskContext,
300
- wrangler: WranglerConfig,
301
- ): ContainerDescriptor[] {
542
+ protected discoverContainers(ctx: BuildTaskContext): ContainerDescriptor[] {
543
+ // String key, not the `$container` factory. The build task runs in
544
+ // the CLI's Node realm, while the workspace's entry module is
545
+ // loaded by Vite — two separate module copies of
546
+ // `alepha/container`. Looking up by `$container[KIND]` (a class
547
+ // reference) would dereference the CLI's ContainerPrimitive class,
548
+ // which never matches the workspace's. The string form iterates
549
+ // the registry by class name and survives the dual-realm — same
550
+ // pattern used for `$bucket`, `$queue`, `scheduler` below.
302
551
  const primitives = ctx.alepha.primitives(
303
- $container,
552
+ "container",
304
553
  ) as ContainerPrimitive[];
305
- if (primitives.length === 0) {
306
- return [];
307
- }
308
-
309
- const descriptors: ContainerDescriptor[] = primitives.map((p) => ({
554
+ return primitives.map((p) => ({
310
555
  name: p.name.toUpperCase(),
311
556
  className: p.name
312
557
  .split(/[^a-zA-Z0-9]/)
@@ -317,10 +562,67 @@ export class BuildCloudflareTask extends BuildTask {
317
562
  port: p.options.port ?? 3000,
318
563
  sleepAfter:
319
564
  typeof p.options.sleepAfter === "string" ? p.options.sleepAfter : "15m",
320
- instanceType: p.options.instanceType ?? "dev",
565
+ // `lite` is the post-GA name for what `$container` historically
566
+ // called `dev`. Default to `lite` here and rewrite any
567
+ // explicit `dev` to it on the way out — wrangler warns
568
+ // otherwise.
569
+ instanceType:
570
+ p.options.instanceType === "dev"
571
+ ? "lite"
572
+ : (p.options.instanceType ?? "lite"),
321
573
  maxInstances: p.options.maxInstances ?? 5,
322
574
  envVars: p.options.envVars,
323
575
  }));
576
+ }
577
+
578
+ /**
579
+ * Expand a short image ref (e.g. `alepha-rocket:0.1.0`) into the
580
+ * fully-qualified `registry.cloudflare.com/<account>/<image>:<tag>`
581
+ * URL that wrangler validates at deploy time.
582
+ *
583
+ * Cloudflare Containers only pulls from `registry.cloudflare.com`;
584
+ * wrangler accepts either a Dockerfile path or a fully-qualified
585
+ * registry URL in the `image` field — not a bare DockerHub-style
586
+ * name. We let `$container({ image })` callers write the short
587
+ * form (it matches what `wrangler containers push <local>` accepts
588
+ * + matches the local docker tag) and rewrite to the CF registry
589
+ * URL here.
590
+ *
591
+ * Pass-through cases:
592
+ * - already a full URL: starts with `registry.cloudflare.com/`
593
+ * or contains a scheme/`://`
594
+ * - looks like a Dockerfile path: starts with `./` or `/`
595
+ */
596
+ protected resolveContainerImage(image: string): string {
597
+ if (
598
+ image.startsWith("./") ||
599
+ image.startsWith("/") ||
600
+ image.startsWith("registry.cloudflare.com/") ||
601
+ image.includes("://")
602
+ ) {
603
+ return image;
604
+ }
605
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
606
+ if (!accountId) {
607
+ // No account id — leave the short form and let wrangler error
608
+ // out with a clearer message. This branch fires only in dry
609
+ // builds where the env isn't wired (e.g. `alepha build` without
610
+ // `alepha platform up` around it).
611
+ return image;
612
+ }
613
+ return `registry.cloudflare.com/${accountId}/${image}`;
614
+ }
615
+
616
+ protected enhanceContainers(
617
+ ctx: BuildTaskContext,
618
+ wrangler: WranglerConfig,
619
+ ): ContainerDescriptor[] {
620
+ const descriptors: ContainerDescriptor[] = ctx.manifest
621
+ ? (ctx.manifest.containers as ContainerDescriptor[])
622
+ : this.discoverContainers(ctx);
623
+ if (descriptors.length === 0) {
624
+ return [];
625
+ }
324
626
 
325
627
  wrangler.containers = wrangler.containers || [];
326
628
  wrangler.durable_objects = wrangler.durable_objects || {};
@@ -331,7 +633,7 @@ export class BuildCloudflareTask extends BuildTask {
331
633
  for (const d of descriptors) {
332
634
  wrangler.containers.push({
333
635
  class_name: d.className,
334
- image: d.image,
636
+ image: this.resolveContainerImage(d.image),
335
637
  instance_type: d.instanceType,
336
638
  max_instances: d.maxInstances,
337
639
  });
@@ -357,20 +659,24 @@ export class BuildCloudflareTask extends BuildTask {
357
659
  distDir: string,
358
660
  containers: ContainerDescriptor[] = [],
359
661
  ): Promise<void> {
662
+ // Extend `globalThis.__alepha_CloudflareContainer` instead of
663
+ // importing `@cloudflare/containers` directly. The entry is
664
+ // written AFTER Vite, so any bare specifier in here survives to
665
+ // workerd (which has `no_bundle: true`) and 10021's out. The
666
+ // global is set by a side-effect in `alepha/container`'s
667
+ // workerd entry, which Vite has already inlined into
668
+ // `./index.js`. ESM evaluates top-level imports before the
669
+ // module body, so by the time the `extends` expression below is
670
+ // evaluated, the global is set.
360
671
  const containerDeclarations = containers
361
672
  .map((c) => {
362
673
  const envVars = c.envVars
363
674
  ? ` envVars = ${JSON.stringify(c.envVars)};\n`
364
675
  : "";
365
- return `export class ${c.className} extends Container {\n defaultPort = ${c.port};\n sleepAfter = "${c.sleepAfter}";\n${envVars}}`;
676
+ return `export class ${c.className} extends globalThis.__alepha_CloudflareContainer {\n defaultPort = ${c.port};\n sleepAfter = "${c.sleepAfter}";\n${envVars}}`;
366
677
  })
367
678
  .join("\n\n");
368
679
 
369
- const containerImport =
370
- containers.length > 0
371
- ? `import { Container } from "@cloudflare/containers";\n\n${containerDeclarations}\n\n`
372
- : "";
373
-
374
680
  const workerCode = `
375
681
  import "./index.js";
376
682
 
@@ -385,11 +691,19 @@ const setWaitUntil = (executionCtx) => {
385
691
  }
386
692
  };
387
693
 
694
+ // Bind the per-invocation Worker \`env\`: keep the full binding (D1, R2, KV, …)
695
+ // in the store for providers, and lift its string values (secrets/vars like
696
+ // PUBLIC_URL) into \`alepha.env\` so \`$env\` resolves them at runtime.
697
+ const bindEnv = (env) => {
698
+ __alepha.set("cloudflare.env", env);
699
+ __alepha.loadEnv(env);
700
+ };
701
+
388
702
  export default {
389
703
  fetch: async (request, env, executionCtx) => {
390
704
  const ctx = { req: request, res: undefined };
391
705
 
392
- __alepha.set("cloudflare.env", env);
706
+ bindEnv(env);
393
707
  setWaitUntil(executionCtx);
394
708
 
395
709
  try {
@@ -405,7 +719,7 @@ export default {
405
719
  },
406
720
 
407
721
  scheduled: async (event, env, executionCtx) => {
408
- __alepha.set("cloudflare.env", env);
722
+ bindEnv(env);
409
723
  setWaitUntil(executionCtx);
410
724
 
411
725
  try {
@@ -422,7 +736,7 @@ export default {
422
736
  },
423
737
 
424
738
  queue: async (batch, env, executionCtx) => {
425
- __alepha.set("cloudflare.env", env);
739
+ bindEnv(env);
426
740
  setWaitUntil(executionCtx);
427
741
 
428
742
  try {
@@ -444,9 +758,12 @@ export default {
444
758
  };
445
759
  `.trim();
446
760
 
761
+ const containerBlock =
762
+ containers.length > 0 ? `${containerDeclarations}\n\n` : "";
763
+
447
764
  await this.fs.writeFile(
448
765
  this.fs.join(root, distDir, "main.cloudflare.js"),
449
- `${this.warningComment}\n${containerImport}${workerCode}`.trim(),
766
+ `${this.warningComment}\n${containerBlock}${workerCode}`.trim(),
450
767
  );
451
768
  }
452
769
  }
@@ -457,7 +774,16 @@ interface ContainerDescriptor {
457
774
  image: string;
458
775
  port: number;
459
776
  sleepAfter: string;
460
- instanceType: "dev" | "basic" | "standard";
777
+ /**
778
+ * Cloudflare Containers instance class.
779
+ *
780
+ * `dev` is the wrangler-pre-GA name; the platform accepts it but
781
+ * emits a deprecation warning telling you to use `lite`. We
782
+ * silently translate at write time (see `discoverContainers`
783
+ * default + `enhanceContainers` write) so older
784
+ * `$container({ instanceType: "dev" })` declarations keep working.
785
+ */
786
+ instanceType: "dev" | "lite" | "basic" | "standard";
461
787
  maxInstances: number;
462
788
  envVars?: Record<string, string>;
463
789
  }
@@ -73,10 +73,12 @@ export class BuildDockerTask extends BuildTask {
73
73
  name: "generate deploy config (docker)",
74
74
  handler: async () => {
75
75
  const migrationsCopied = await this.copyMigrations(ctx.root, distDir);
76
+ const hasDeps = await this.hasRuntimeDeps(ctx.root, distDir);
76
77
  await this.writeDockerfile(ctx.root, distDir, {
77
78
  compile,
78
79
  standard: { image: dockerFrom, command: dockerCommand },
79
80
  hasMigrations: migrationsCopied,
81
+ hasDeps,
80
82
  install: ctx.options.docker?.install ?? [],
81
83
  });
82
84
  },
@@ -211,6 +213,28 @@ export class BuildDockerTask extends BuildTask {
211
213
  return false;
212
214
  }
213
215
 
216
+ /**
217
+ * Whether the produced `dist/package.json` declares any runtime
218
+ * dependencies. Alepha apps normally bundle everything into the
219
+ * server entry via Vite, leaving `dependencies: {}` — in which case
220
+ * the generated Dockerfile's `RUN npm install` is wasted work
221
+ * (and emits deprecation noise). Skip the line when empty.
222
+ */
223
+ protected async hasRuntimeDeps(
224
+ root: string,
225
+ distDir: string,
226
+ ): Promise<boolean> {
227
+ try {
228
+ const pkg = await this.fs.readJsonFile<{
229
+ dependencies?: Record<string, string>;
230
+ }>(this.fs.join(root, distDir, "package.json"));
231
+ return Object.keys(pkg.dependencies ?? {}).length > 0;
232
+ } catch {
233
+ // No package.json in dist/ → nothing to install.
234
+ return false;
235
+ }
236
+ }
237
+
214
238
  protected async writeDockerfile(
215
239
  root: string,
216
240
  distDir: string,
@@ -218,6 +242,7 @@ export class BuildDockerTask extends BuildTask {
218
242
  compile: ResolvedCompile | null;
219
243
  standard: { image: string; command: string };
220
244
  hasMigrations: boolean;
245
+ hasDeps: boolean;
221
246
  install: string[];
222
247
  },
223
248
  ): Promise<void> {
@@ -244,12 +269,18 @@ ENTRYPOINT ["/app/app"]
244
269
  `;
245
270
  } else {
246
271
  const { image, command } = opts.standard;
272
+ // Skip `RUN <pm> install` when `dist/package.json` declares no
273
+ // runtime deps — Alepha apps normally bundle everything via Vite,
274
+ // making the install a no-op that just emits deprecation noise.
275
+ const baseInstallLine = opts.hasDeps
276
+ ? `RUN ${command === "bun" ? "bun" : "npm"} install\n`
277
+ : "";
247
278
  // Install requested packages locally (no --global). They land in
248
279
  // `/app/node_modules/`, alongside the app's own deps. Use
249
280
  // `--no-save` so we don't mutate the bundled package.json. Node
250
281
  // module resolution walks up into `/app/node_modules/` when the
251
282
  // workspace lives under `/app/workspace/<deploy-id>/`.
252
- const installLine = opts.install.length
283
+ const extraInstallLine = opts.install.length
253
284
  ? `RUN npm install --no-save --no-fund --no-audit ${opts.install.join(" ")}\n`
254
285
  : "";
255
286
  dockerfile = `${header}FROM ${image}
@@ -257,8 +288,7 @@ WORKDIR /app
257
288
 
258
289
  COPY . .
259
290
 
260
- RUN ${command === "bun" ? "bun" : "npm"} install
261
- ${installLine}
291
+ ${baseInstallLine}${extraInstallLine}
262
292
  ENV SERVER_HOST=0.0.0.0
263
293
 
264
294
  CMD ["${command}", "index.js"]