alepha 0.21.2 → 0.22.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 (463) 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 +289 -292
  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 +211 -216
  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 +1073 -1006
  49. package/dist/api/users/index.d.ts.map +1 -1
  50. package/dist/api/users/index.js +283 -61
  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 +134 -140
  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 +417 -214
  88. package/dist/cli/core/index.d.ts.map +1 -1
  89. package/dist/cli/core/index.js +325 -563
  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 +8 -12
  95. package/dist/cli/i18n/index.d.ts.map +1 -1
  96. package/dist/cli/i18n/index.js.map +1 -1
  97. package/dist/cli/platform/index.d.ts +126 -1342
  98. package/dist/cli/platform/index.d.ts.map +1 -1
  99. package/dist/cli/platform/index.js +136 -2374
  100. package/dist/cli/platform/index.js.map +1 -1
  101. package/dist/cli/platform-lib/index.d.ts +1446 -0
  102. package/dist/cli/platform-lib/index.d.ts.map +1 -0
  103. package/dist/cli/platform-lib/index.js +2597 -0
  104. package/dist/cli/platform-lib/index.js.map +1 -0
  105. package/dist/cli/vendor/index.d.ts +17 -21
  106. package/dist/cli/vendor/index.d.ts.map +1 -1
  107. package/dist/cli/vendor/index.js.map +1 -1
  108. package/dist/command/index.d.ts +21 -20
  109. package/dist/command/index.d.ts.map +1 -1
  110. package/dist/command/index.js +39 -10
  111. package/dist/command/index.js.map +1 -1
  112. package/dist/{containers → container}/core/index.d.ts +13 -15
  113. package/dist/container/core/index.d.ts.map +1 -0
  114. package/dist/{containers → container}/core/index.js +23 -14
  115. package/dist/container/core/index.js.map +1 -0
  116. package/dist/{containers → container}/core/index.workerd.js +37 -22
  117. package/dist/container/core/index.workerd.js.map +1 -0
  118. package/dist/core/index.browser.js +27 -1
  119. package/dist/core/index.browser.js.map +1 -1
  120. package/dist/core/index.d.ts +48 -24
  121. package/dist/core/index.d.ts.map +1 -1
  122. package/dist/core/index.js +27 -1
  123. package/dist/core/index.js.map +1 -1
  124. package/dist/core/index.native.js +27 -1
  125. package/dist/core/index.native.js.map +1 -1
  126. package/dist/core/index.workerd.js +27 -1
  127. package/dist/core/index.workerd.js.map +1 -1
  128. package/dist/crypto/index.browser.js.map +1 -1
  129. package/dist/crypto/index.d.ts +5 -8
  130. package/dist/crypto/index.d.ts.map +1 -1
  131. package/dist/crypto/index.js.map +1 -1
  132. package/dist/datetime/index.d.ts +3 -4
  133. package/dist/datetime/index.d.ts.map +1 -1
  134. package/dist/datetime/index.js.map +1 -1
  135. package/dist/email/brevo/index.d.ts +2 -4
  136. package/dist/email/brevo/index.d.ts.map +1 -1
  137. package/dist/email/brevo/index.js.map +1 -1
  138. package/dist/email/cloudflare/index.d.ts +20 -7
  139. package/dist/email/cloudflare/index.d.ts.map +1 -1
  140. package/dist/email/cloudflare/index.js +46 -9
  141. package/dist/email/cloudflare/index.js.map +1 -1
  142. package/dist/email/core/index.d.ts +6 -9
  143. package/dist/email/core/index.d.ts.map +1 -1
  144. package/dist/email/core/index.js.map +1 -1
  145. package/dist/email/core/index.workerd.js.map +1 -1
  146. package/dist/email/smtp/index.d.ts +10 -13
  147. package/dist/email/smtp/index.d.ts.map +1 -1
  148. package/dist/email/smtp/index.js +107 -32
  149. package/dist/email/smtp/index.js.map +1 -1
  150. package/dist/fake/index.d.ts +1 -2
  151. package/dist/fake/index.d.ts.map +1 -1
  152. package/dist/fake/index.js.map +1 -1
  153. package/dist/lock/core/index.d.ts +9 -14
  154. package/dist/lock/core/index.d.ts.map +1 -1
  155. package/dist/lock/core/index.js.map +1 -1
  156. package/dist/lock/redis/index.d.ts +2 -4
  157. package/dist/lock/redis/index.d.ts.map +1 -1
  158. package/dist/lock/redis/index.js.map +1 -1
  159. package/dist/logger/index.d.ts +105 -76
  160. package/dist/logger/index.d.ts.map +1 -1
  161. package/dist/logger/index.js +196 -174
  162. package/dist/logger/index.js.map +1 -1
  163. package/dist/mcp/index.d.ts +16 -20
  164. package/dist/mcp/index.d.ts.map +1 -1
  165. package/dist/mcp/index.js.map +1 -1
  166. package/dist/orm/core/index.browser.js.map +1 -1
  167. package/dist/orm/core/index.bun.js +19 -1
  168. package/dist/orm/core/index.bun.js.map +1 -1
  169. package/dist/orm/core/index.d.ts +76 -62
  170. package/dist/orm/core/index.d.ts.map +1 -1
  171. package/dist/orm/core/index.js +20 -2
  172. package/dist/orm/core/index.js.map +1 -1
  173. package/dist/orm/postgres/index.bun.js.map +1 -1
  174. package/dist/orm/postgres/index.d.ts +28 -20
  175. package/dist/orm/postgres/index.d.ts.map +1 -1
  176. package/dist/orm/postgres/index.js.map +1 -1
  177. package/dist/queue/core/index.d.ts +12 -15
  178. package/dist/queue/core/index.d.ts.map +1 -1
  179. package/dist/queue/core/index.js.map +1 -1
  180. package/dist/queue/core/index.workerd.js.map +1 -1
  181. package/dist/queue/redis/index.d.ts +3 -5
  182. package/dist/queue/redis/index.d.ts.map +1 -1
  183. package/dist/queue/redis/index.js.map +1 -1
  184. package/dist/react/auth/index.browser.js +9 -2
  185. package/dist/react/auth/index.browser.js.map +1 -1
  186. package/dist/react/auth/index.d.ts +14 -9
  187. package/dist/react/auth/index.d.ts.map +1 -1
  188. package/dist/react/auth/index.js +9 -2
  189. package/dist/react/auth/index.js.map +1 -1
  190. package/dist/react/core/index.d.ts +7 -8
  191. package/dist/react/core/index.d.ts.map +1 -1
  192. package/dist/react/core/index.js +6 -3
  193. package/dist/react/core/index.js.map +1 -1
  194. package/dist/react/form/index.d.ts +2 -4
  195. package/dist/react/form/index.d.ts.map +1 -1
  196. package/dist/react/form/index.js.map +1 -1
  197. package/dist/react/head/index.browser.js.map +1 -1
  198. package/dist/react/head/index.d.ts +2 -4
  199. package/dist/react/head/index.d.ts.map +1 -1
  200. package/dist/react/head/index.js.map +1 -1
  201. package/dist/react/i18n/index.d.ts +47 -11
  202. package/dist/react/i18n/index.d.ts.map +1 -1
  203. package/dist/react/i18n/index.js +33 -1
  204. package/dist/react/i18n/index.js.map +1 -1
  205. package/dist/react/intro/index.d.ts +1 -2
  206. package/dist/react/intro/index.d.ts.map +1 -1
  207. package/dist/react/intro/index.js +2 -2
  208. package/dist/react/intro/index.js.map +1 -1
  209. package/dist/react/router/index.browser.js +65 -19
  210. package/dist/react/router/index.browser.js.map +1 -1
  211. package/dist/react/router/index.d.ts +327 -222
  212. package/dist/react/router/index.d.ts.map +1 -1
  213. package/dist/react/router/index.js +65 -29
  214. package/dist/react/router/index.js.map +1 -1
  215. package/dist/react/testing/index.d.ts +1 -2
  216. package/dist/react/testing/index.d.ts.map +1 -1
  217. package/dist/react/testing/index.js +16 -17
  218. package/dist/react/testing/index.js.map +1 -1
  219. package/dist/react/ui/index.d.ts +20 -25
  220. package/dist/react/ui/index.d.ts.map +1 -1
  221. package/dist/react/ui/index.js.map +1 -1
  222. package/dist/redis/index.bun.js.map +1 -1
  223. package/dist/redis/index.d.ts +17 -19
  224. package/dist/redis/index.d.ts.map +1 -1
  225. package/dist/redis/index.js.map +1 -1
  226. package/dist/retry/index.d.ts +2 -4
  227. package/dist/retry/index.d.ts.map +1 -1
  228. package/dist/retry/index.js.map +1 -1
  229. package/dist/router/index.d.ts.map +1 -1
  230. package/dist/router/index.js.map +1 -1
  231. package/dist/scheduler/index.d.ts +10 -13
  232. package/dist/scheduler/index.d.ts.map +1 -1
  233. package/dist/scheduler/index.js.map +1 -1
  234. package/dist/scheduler/index.workerd.js.map +1 -1
  235. package/dist/security/index.browser.js.map +1 -1
  236. package/dist/security/index.d.ts +45 -48
  237. package/dist/security/index.d.ts.map +1 -1
  238. package/dist/security/index.js.map +1 -1
  239. package/dist/server/auth/index.browser.js.map +1 -1
  240. package/dist/server/auth/index.d.ts +167 -172
  241. package/dist/server/auth/index.d.ts.map +1 -1
  242. package/dist/server/auth/index.js +4 -8
  243. package/dist/server/auth/index.js.map +1 -1
  244. package/dist/server/cookies/index.browser.js.map +1 -1
  245. package/dist/server/cookies/index.d.ts +5 -7
  246. package/dist/server/cookies/index.d.ts.map +1 -1
  247. package/dist/server/cookies/index.js.map +1 -1
  248. package/dist/server/core/index.browser.js.map +1 -1
  249. package/dist/server/core/index.d.ts +88 -73
  250. package/dist/server/core/index.d.ts.map +1 -1
  251. package/dist/server/core/index.js +19 -0
  252. package/dist/server/core/index.js.map +1 -1
  253. package/dist/server/cors/index.d.ts +11 -14
  254. package/dist/server/cors/index.d.ts.map +1 -1
  255. package/dist/server/cors/index.js.map +1 -1
  256. package/dist/server/etag/index.d.ts +6 -9
  257. package/dist/server/etag/index.d.ts.map +1 -1
  258. package/dist/server/etag/index.js.map +1 -1
  259. package/dist/server/health/index.d.ts +18 -21
  260. package/dist/server/health/index.d.ts.map +1 -1
  261. package/dist/server/health/index.js.map +1 -1
  262. package/dist/server/links/index.browser.js +2 -0
  263. package/dist/server/links/index.browser.js.map +1 -1
  264. package/dist/server/links/index.d.ts +63 -67
  265. package/dist/server/links/index.d.ts.map +1 -1
  266. package/dist/server/links/index.js +2 -0
  267. package/dist/server/links/index.js.map +1 -1
  268. package/dist/server/metrics/index.d.ts +5 -7
  269. package/dist/server/metrics/index.d.ts.map +1 -1
  270. package/dist/server/metrics/index.js.map +1 -1
  271. package/dist/server/proxy/index.d.ts +3 -5
  272. package/dist/server/proxy/index.d.ts.map +1 -1
  273. package/dist/server/proxy/index.js.map +1 -1
  274. package/dist/server/rate-limit/index.d.ts +10 -13
  275. package/dist/server/rate-limit/index.d.ts.map +1 -1
  276. package/dist/server/rate-limit/index.js.map +1 -1
  277. package/dist/server/static/index.d.ts +3 -5
  278. package/dist/server/static/index.d.ts.map +1 -1
  279. package/dist/server/static/index.js.map +1 -1
  280. package/dist/server/swagger/index.d.ts +5 -8
  281. package/dist/server/swagger/index.d.ts.map +1 -1
  282. package/dist/server/swagger/index.js.map +1 -1
  283. package/dist/sms/index.d.ts +3 -5
  284. package/dist/sms/index.d.ts.map +1 -1
  285. package/dist/sms/index.js.map +1 -1
  286. package/dist/system/index.browser.js.map +1 -1
  287. package/dist/system/index.d.ts +2 -4
  288. package/dist/system/index.d.ts.map +1 -1
  289. package/dist/system/index.js.map +1 -1
  290. package/dist/system/index.workerd.js.map +1 -1
  291. package/dist/topic/core/index.d.ts +4 -6
  292. package/dist/topic/core/index.d.ts.map +1 -1
  293. package/dist/topic/core/index.js.map +1 -1
  294. package/dist/topic/redis/index.d.ts +5 -8
  295. package/dist/topic/redis/index.d.ts.map +1 -1
  296. package/dist/topic/redis/index.js.map +1 -1
  297. package/package.json +45 -22
  298. package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
  299. package/src/api/audits/controllers/AdminAuditController.ts +14 -0
  300. package/src/api/audits/services/AuditService.ts +21 -88
  301. package/src/api/files/__tests__/FileService.spec.ts +207 -2
  302. package/src/api/files/index.ts +3 -0
  303. package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
  304. package/src/api/files/schemas/fileResourceSchema.ts +10 -1
  305. package/src/api/files/services/FileService.ts +170 -72
  306. package/src/api/jobs/__tests__/$job.spec.ts +24 -1
  307. package/src/api/jobs/index.ts +4 -3
  308. package/src/api/jobs/primitives/$job.ts +7 -3
  309. package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
  310. package/src/api/jobs/providers/JobProvider.ts +53 -24
  311. package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
  312. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
  313. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
  314. package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
  315. package/src/api/parameters/audits/ParameterAudits.ts +17 -0
  316. package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
  317. package/src/api/parameters/index.ts +3 -0
  318. package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
  319. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
  320. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
  321. package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
  322. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
  323. package/src/api/parameters/services/ParameterProvider.ts +69 -6
  324. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
  325. package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
  326. package/src/api/users/audits/SessionAudits.ts +33 -0
  327. package/src/api/users/audits/UserAudits.ts +19 -43
  328. package/src/api/users/controllers/AdminUserController.ts +66 -1
  329. package/src/api/users/entities/sessions.ts +6 -0
  330. package/src/api/users/entities/users.ts +2 -0
  331. package/src/api/users/index.ts +9 -1
  332. package/src/api/users/primitives/$realm.ts +3 -0
  333. package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
  334. package/src/api/users/schemas/updateUserSchema.ts +1 -8
  335. package/src/api/users/schemas/userQuerySchema.ts +7 -0
  336. package/src/api/users/services/CredentialService.ts +15 -6
  337. package/src/api/users/services/IdentityService.ts +2 -1
  338. package/src/api/users/services/RegistrationService.ts +2 -1
  339. package/src/api/users/services/SessionCrudService.ts +19 -2
  340. package/src/api/users/services/SessionService.ts +39 -19
  341. package/src/api/users/services/UserService.ts +106 -8
  342. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
  343. package/src/background/index.ts +37 -0
  344. package/src/background/index.workerd.ts +28 -0
  345. package/src/background/providers/BackgroundTaskProvider.ts +70 -0
  346. package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
  347. package/src/bucket/__tests__/$bucket.spec.ts +18 -0
  348. package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
  349. package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
  350. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
  351. package/src/bucket/__tests__/shared.ts +30 -0
  352. package/src/bucket/index.ts +5 -5
  353. package/src/bucket/index.workerd.ts +11 -4
  354. package/src/bucket/primitives/$bucket.ts +27 -0
  355. package/src/bucket/providers/FileStorageProvider.ts +13 -0
  356. package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
  357. package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
  358. package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
  359. package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
  360. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
  361. package/src/cli/core/__tests__/init.spec.ts +0 -219
  362. package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
  363. package/src/cli/core/commands/build.ts +108 -30
  364. package/src/cli/core/commands/init.ts +0 -12
  365. package/src/cli/core/commands/pack.ts +133 -0
  366. package/src/cli/core/index.ts +3 -0
  367. package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
  368. package/src/cli/core/services/PackageManagerUtils.ts +0 -16
  369. package/src/cli/core/services/ProjectScaffolder.ts +29 -291
  370. package/src/cli/core/tasks/BuildCloudflareTask.ts +353 -47
  371. package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
  372. package/src/cli/core/tasks/BuildTask.ts +34 -0
  373. package/src/cli/core/templates/apiIndexTs.ts +1 -22
  374. package/src/cli/core/templates/mainCss.ts +0 -1
  375. package/src/cli/core/templates/webAppRouterTs.ts +0 -99
  376. package/src/cli/core/templates/webIndexTs.ts +1 -22
  377. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
  378. package/src/cli/platform/commands/SecretsCommand.ts +8 -6
  379. package/src/cli/platform/commands/platform.ts +192 -46
  380. package/src/cli/platform/index.ts +12 -52
  381. package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
  382. package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
  383. package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
  384. package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +402 -165
  385. package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
  386. package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
  387. package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
  388. package/src/cli/platform-lib/index.ts +67 -0
  389. package/src/cli/platform-lib/services/NamingService.ts +136 -0
  390. package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
  391. package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
  392. package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
  393. package/src/command/__tests__/Runner.spec.ts +20 -0
  394. package/src/command/helpers/EnvUtils.ts +19 -3
  395. package/src/command/helpers/Runner.ts +12 -2
  396. package/src/command/providers/CliProvider.ts +34 -1
  397. package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
  398. package/src/{containers → container}/core/index.ts +4 -4
  399. package/src/{containers → container}/core/index.workerd.ts +19 -3
  400. package/src/{containers → container}/core/primitives/$container.ts +1 -1
  401. package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
  402. package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
  403. package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
  404. package/src/core/Alepha.ts +49 -1
  405. package/src/core/__tests__/$env.spec.ts +42 -0
  406. package/src/core/__tests__/dump.spec.ts +47 -0
  407. package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
  408. package/src/email/cloudflare/index.ts +14 -5
  409. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
  410. package/src/logger/__tests__/Logger.spec.ts +55 -0
  411. package/src/logger/index.ts +13 -0
  412. package/src/logger/services/Logger.ts +31 -1
  413. package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
  414. package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
  415. package/src/orm/core/interfaces/PgQuery.ts +4 -1
  416. package/src/orm/core/services/Repository.ts +27 -11
  417. package/src/react/auth/hooks/useAuth.ts +10 -5
  418. package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
  419. package/src/react/core/hooks/useAction.ts +14 -3
  420. package/src/react/core/hooks/useQuery.ts +24 -4
  421. package/src/react/i18n/components/Translate.tsx +47 -0
  422. package/src/react/i18n/index.ts +2 -0
  423. package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
  424. package/src/react/router/__tests__/$page.spec.tsx +3 -2
  425. package/src/react/router/__tests__/page-can.spec.ts +18 -13
  426. package/src/react/router/hooks/useQueryParams.ts +114 -14
  427. package/src/react/router/primitives/$page.ts +85 -4
  428. package/src/react/router/providers/ReactBrowserRouterProvider.ts +3 -7
  429. package/src/react/router/providers/ReactServerProvider.ts +4 -13
  430. package/src/react/ui/services/SchemaControl.ts +3 -4
  431. package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
  432. package/src/server/links/providers/LinkProvider.ts +10 -0
  433. package/dist/containers/core/index.d.ts.map +0 -1
  434. package/dist/containers/core/index.js.map +0 -1
  435. package/dist/containers/core/index.workerd.js.map +0 -1
  436. package/src/cli/core/templates/componentsJsonTs.ts +0 -39
  437. package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
  438. package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
  439. package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
  440. package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
  441. package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
  442. package/src/cli/platform/services/NamingService.ts +0 -54
  443. /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
  444. /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
  445. /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
  446. /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
  447. /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
  448. /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
  449. /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
  450. /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
  451. /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
  452. /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
  453. /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
  454. /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
  455. /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
  456. /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
  457. /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
  458. /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
  459. /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
  460. /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
  461. /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
  462. /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
  463. /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
@@ -1,22 +1,105 @@
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
+ * `$container()` descriptors — image, port, lifecycle settings.
79
+ * Used both to populate Cloudflare Containers bindings in
80
+ * wrangler.jsonc and (in future) to know which images Rocket should
81
+ * pull on the deploy side.
82
+ */
83
+ containers: Array<{
84
+ name: string;
85
+ className: string;
86
+ image: string;
87
+ port: number;
88
+ sleepAfter: string;
89
+ instanceType: string;
90
+ maxInstances: number;
91
+ }>;
92
+ /**
93
+ * Every env var the app declares via `$env`, captured from
94
+ * `alepha.dump().env` at build time. The deploy `secrets` step uses this
95
+ * as the worker-secret allowlist (minus build/binding vars) so CI can
96
+ * deliver secrets straight from `process.env` without a `.env` file —
97
+ * `platform.secrets.keys` overrides it when set. Empty when introspection
98
+ * was unavailable (older artifacts / prebuilt mode).
99
+ */
100
+ env: string[];
101
+ }
102
+
20
103
  /**
21
104
  * Generate Cloudflare Workers deployment configuration.
22
105
  *
@@ -52,7 +135,15 @@ export class BuildCloudflareTask extends BuildTask {
52
135
  distDir: string,
53
136
  ): Promise<void> {
54
137
  const root = ctx.root;
55
- const name = basename(root);
138
+ // Slugify the dir basename — wrangler rejects names that aren't
139
+ // `^[a-z0-9-]+$` (no uppercase, dots, underscores, spaces, etc.).
140
+ // Without this, running `alepha build -t cloudflare` in a dir like
141
+ // `My App` or `club-0.0.2` produces an unusable `wrangler.jsonc`.
142
+ const name = basename(root)
143
+ .toLowerCase()
144
+ .replace(/[^a-z0-9-]+/g, "-")
145
+ .replace(/^-+|-+$/g, "")
146
+ .slice(0, 63);
56
147
  const hasAssets = await this.fs.exists(
57
148
  this.fs.join(root, distDir, "public"),
58
149
  );
@@ -98,9 +189,128 @@ export class BuildCloudflareTask extends BuildTask {
98
189
  JSON.stringify(wrangler, null, 2),
99
190
  );
100
191
 
192
+ // Only write a fresh manifest when we discovered it from a booted
193
+ // Alepha instance. In manifest mode (ctx.manifest != null) we're
194
+ // re-emitting the same data we just read — skip to avoid a redundant
195
+ // write and to keep the original manifest as the canonical record.
196
+ if (!ctx.manifest) {
197
+ await this.writeManifest(ctx, root, distDir, name, containers);
198
+ }
101
199
  await this.writeWorkerEntryPoint(root, distDir, containers);
102
200
  }
103
201
 
202
+ /**
203
+ * Write `dist/manifest.json` — a build-time snapshot of everything
204
+ * downstream tooling needs to know about the app without re-booting
205
+ * it. Used by `alepha platform up --prebuilt` (and Alepha Rocket) so
206
+ * the deploy path can skip the Vite-based introspection step and the
207
+ * workspace's runtime npm install.
208
+ */
209
+ protected async writeManifest(
210
+ ctx: BuildTaskContext,
211
+ root: string,
212
+ distDir: string,
213
+ name: string,
214
+ containers: ContainerDescriptor[],
215
+ ): Promise<void> {
216
+ // Discover the same primitive shapes the enhance* methods read.
217
+ // Errors are silently swallowed — an absent primitive class just
218
+ // means the app doesn't use that resource.
219
+ let hasDatabase = false;
220
+ let hasBucket = false;
221
+ let hasKV = false;
222
+ let hasQueue = false;
223
+ let crons: string[] = [];
224
+
225
+ try {
226
+ const repo = ctx.alepha.inject("RepositoryProvider") as {
227
+ getRepositories?: () => unknown[];
228
+ };
229
+ hasDatabase = (repo.getRepositories?.() ?? []).length > 0;
230
+ } catch {}
231
+
232
+ try {
233
+ hasBucket = ctx.alepha.primitives("$bucket").length > 0;
234
+ } catch {}
235
+
236
+ try {
237
+ // Only count $cache primitives without an explicit `provider`
238
+ // option — those fall back to KV on workerd. Explicit memory /
239
+ // Redis / Postgres providers opt out of KV provisioning.
240
+ hasKV =
241
+ ctx.alepha
242
+ .primitives("cache")
243
+ .filter(
244
+ (p) =>
245
+ (p as { options?: { provider?: unknown } }).options?.provider ==
246
+ null,
247
+ ).length > 0;
248
+ } catch {}
249
+
250
+ try {
251
+ hasQueue = ctx.alepha.primitives("$queue").length > 0;
252
+ } catch {}
253
+
254
+ try {
255
+ const cronProvider = ctx.alepha.inject("CronProvider") as {
256
+ getCronJobs?: () => Array<{ expression: string }>;
257
+ };
258
+ crons = [
259
+ ...new Set(
260
+ (cronProvider.getCronJobs?.() ?? []).map((c) => c.expression),
261
+ ),
262
+ ];
263
+ } catch {}
264
+
265
+ // platformOptions come from the CLI's Alepha instance (where
266
+ // alepha.config.ts ran during the configure hook). BuildCommand
267
+ // reads them up there and threads them via ctx — ctx.alepha here
268
+ // is the WORKSPACE's Vite-booted Alepha, which never saw the
269
+ // platform options.
270
+ const defaultEnv = ctx.platformOptions?.default ?? "production";
271
+ const environments = (ctx.platformOptions?.environments ??
272
+ {}) as BuildManifest["environments"];
273
+
274
+ // Every declared `$env` key. dump() force-instantiates the graph (no
275
+ // start/ready hooks), so this is the full env surface — used by the
276
+ // deploy `secrets` step as the worker-secret allowlist.
277
+ let env: string[] = [];
278
+ try {
279
+ env = Object.keys(ctx.alepha.dump().env).sort();
280
+ } catch {}
281
+
282
+ const manifest: BuildManifest = {
283
+ version: 1,
284
+ project: name,
285
+ defaultEnv,
286
+ tenancy: ctx.platformOptions?.tenancy,
287
+ environments,
288
+ resources: {
289
+ hasDatabase,
290
+ hasBucket,
291
+ hasKV,
292
+ hasQueue,
293
+ hasCron: crons.length > 0,
294
+ },
295
+ crons,
296
+ containers: containers.map((c) => ({
297
+ name: c.name,
298
+ className: c.className,
299
+ image: c.image,
300
+ port: c.port,
301
+ sleepAfter: c.sleepAfter,
302
+ instanceType: c.instanceType,
303
+ maxInstances: c.maxInstances,
304
+ })),
305
+ env,
306
+ };
307
+
308
+ await this.fs.writeFile(
309
+ this.fs.join(root, distDir, "manifest.json"),
310
+ JSON.stringify(manifest, null, 2),
311
+ );
312
+ }
313
+
104
314
  protected enhanceDomain(wrangler: WranglerConfig): void {
105
315
  const domain = process.env.CLOUDFLARE_DOMAIN;
106
316
  if (!domain) {
@@ -132,23 +342,29 @@ export class BuildCloudflareTask extends BuildTask {
132
342
  }
133
343
 
134
344
  protected enhanceCron(ctx: BuildTaskContext, wrangler: WranglerConfig): void {
135
- if (ctx.alepha.primitives("scheduler").length === 0) {
345
+ const cronExpressions = ctx.manifest
346
+ ? ctx.manifest.crons
347
+ : this.discoverCrons(ctx);
348
+ if (cronExpressions.length === 0) {
136
349
  return;
137
350
  }
351
+ wrangler.triggers ??= {};
352
+ wrangler.triggers.crons = cronExpressions;
353
+ }
138
354
 
355
+ protected discoverCrons(ctx: BuildTaskContext): string[] {
356
+ if (ctx.alepha.primitives("scheduler").length === 0) {
357
+ return [];
358
+ }
139
359
  let cronProvider: CronProvider | undefined;
140
360
  try {
141
361
  cronProvider = ctx.alepha.inject("CronProvider") as WorkerdCronProvider;
142
362
  } catch {}
143
-
144
363
  const crons = cronProvider?.getCronJobs();
145
364
  if (!crons || crons.length === 0) {
146
- return;
365
+ return [];
147
366
  }
148
-
149
- const cronExpressions = [...new Set(crons.map((c) => c.expression))];
150
- wrangler.triggers ??= {};
151
- wrangler.triggers.crons = cronExpressions;
367
+ return [...new Set(crons.map((c) => c.expression))];
152
368
  }
153
369
 
154
370
  protected enhanceDatabase(wrangler: WranglerConfig): void {
@@ -256,14 +472,16 @@ export class BuildCloudflareTask extends BuildTask {
256
472
  ctx: BuildTaskContext,
257
473
  wrangler: WranglerConfig,
258
474
  ): void {
259
- let provider: EmailProvider | undefined;
260
- try {
261
- provider = ctx.alepha.inject(EmailProvider);
262
- } catch {
475
+ // Manifest mode doesn't capture email provider details yet. Apps
476
+ // using CloudflareEmailProvider would need a manifest field added.
477
+ // For now, skip — non-email apps and apps using non-CF providers
478
+ // are unaffected. TODO: add `emailProvider` to BuildManifest.
479
+ if (ctx.manifest || !ctx.alepha) {
263
480
  return;
264
481
  }
265
-
266
- if (!(provider instanceof CloudflareEmailProvider)) {
482
+ try {
483
+ ctx.alepha.inject(CLOUDFLARE_EMAIL_PROVIDER_NAME);
484
+ } catch {
267
485
  return;
268
486
  }
269
487
 
@@ -276,11 +494,17 @@ export class BuildCloudflareTask extends BuildTask {
276
494
  return;
277
495
  }
278
496
 
497
+ // NOTE: do NOT set `destination_address` here. On a Cloudflare
498
+ // `send_email` binding, `destination_address` is a *recipient* allow-list
499
+ // lock (the worker may then only send TO that one address) — it is not the
500
+ // sender. Setting it to `EMAIL_FROM` (the sender) broke all outbound mail:
501
+ // a bare address locked delivery to that single recipient ("email to … not
502
+ // allowed"), and a display-name form like `Lore <noreply@…>` is a malformed
503
+ // destination value that Cloudflare rejects with "internal error". The
504
+ // sender goes in the message `from` field (see CloudflareEmailProvider.send);
505
+ // leaving the binding unrestricted lets the worker send to any verified
506
+ // destination.
279
507
  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
508
 
285
509
  wrangler.send_email.push(entry);
286
510
  }
@@ -295,18 +519,19 @@ export class BuildCloudflareTask extends BuildTask {
295
519
  * `writeWorkerEntryPoint` can emit `export class <NAME> extends
296
520
  * Container` declarations referencing them.
297
521
  */
298
- protected enhanceContainers(
299
- ctx: BuildTaskContext,
300
- wrangler: WranglerConfig,
301
- ): ContainerDescriptor[] {
522
+ protected discoverContainers(ctx: BuildTaskContext): ContainerDescriptor[] {
523
+ // String key, not the `$container` factory. The build task runs in
524
+ // the CLI's Node realm, while the workspace's entry module is
525
+ // loaded by Vite — two separate module copies of
526
+ // `alepha/container`. Looking up by `$container[KIND]` (a class
527
+ // reference) would dereference the CLI's ContainerPrimitive class,
528
+ // which never matches the workspace's. The string form iterates
529
+ // the registry by class name and survives the dual-realm — same
530
+ // pattern used for `$bucket`, `$queue`, `scheduler` below.
302
531
  const primitives = ctx.alepha.primitives(
303
- $container,
532
+ "container",
304
533
  ) as ContainerPrimitive[];
305
- if (primitives.length === 0) {
306
- return [];
307
- }
308
-
309
- const descriptors: ContainerDescriptor[] = primitives.map((p) => ({
534
+ return primitives.map((p) => ({
310
535
  name: p.name.toUpperCase(),
311
536
  className: p.name
312
537
  .split(/[^a-zA-Z0-9]/)
@@ -317,10 +542,67 @@ export class BuildCloudflareTask extends BuildTask {
317
542
  port: p.options.port ?? 3000,
318
543
  sleepAfter:
319
544
  typeof p.options.sleepAfter === "string" ? p.options.sleepAfter : "15m",
320
- instanceType: p.options.instanceType ?? "dev",
545
+ // `lite` is the post-GA name for what `$container` historically
546
+ // called `dev`. Default to `lite` here and rewrite any
547
+ // explicit `dev` to it on the way out — wrangler warns
548
+ // otherwise.
549
+ instanceType:
550
+ p.options.instanceType === "dev"
551
+ ? "lite"
552
+ : (p.options.instanceType ?? "lite"),
321
553
  maxInstances: p.options.maxInstances ?? 5,
322
554
  envVars: p.options.envVars,
323
555
  }));
556
+ }
557
+
558
+ /**
559
+ * Expand a short image ref (e.g. `alepha-rocket:0.1.0`) into the
560
+ * fully-qualified `registry.cloudflare.com/<account>/<image>:<tag>`
561
+ * URL that wrangler validates at deploy time.
562
+ *
563
+ * Cloudflare Containers only pulls from `registry.cloudflare.com`;
564
+ * wrangler accepts either a Dockerfile path or a fully-qualified
565
+ * registry URL in the `image` field — not a bare DockerHub-style
566
+ * name. We let `$container({ image })` callers write the short
567
+ * form (it matches what `wrangler containers push <local>` accepts
568
+ * + matches the local docker tag) and rewrite to the CF registry
569
+ * URL here.
570
+ *
571
+ * Pass-through cases:
572
+ * - already a full URL: starts with `registry.cloudflare.com/`
573
+ * or contains a scheme/`://`
574
+ * - looks like a Dockerfile path: starts with `./` or `/`
575
+ */
576
+ protected resolveContainerImage(image: string): string {
577
+ if (
578
+ image.startsWith("./") ||
579
+ image.startsWith("/") ||
580
+ image.startsWith("registry.cloudflare.com/") ||
581
+ image.includes("://")
582
+ ) {
583
+ return image;
584
+ }
585
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
586
+ if (!accountId) {
587
+ // No account id — leave the short form and let wrangler error
588
+ // out with a clearer message. This branch fires only in dry
589
+ // builds where the env isn't wired (e.g. `alepha build` without
590
+ // `alepha platform up` around it).
591
+ return image;
592
+ }
593
+ return `registry.cloudflare.com/${accountId}/${image}`;
594
+ }
595
+
596
+ protected enhanceContainers(
597
+ ctx: BuildTaskContext,
598
+ wrangler: WranglerConfig,
599
+ ): ContainerDescriptor[] {
600
+ const descriptors: ContainerDescriptor[] = ctx.manifest
601
+ ? (ctx.manifest.containers as ContainerDescriptor[])
602
+ : this.discoverContainers(ctx);
603
+ if (descriptors.length === 0) {
604
+ return [];
605
+ }
324
606
 
325
607
  wrangler.containers = wrangler.containers || [];
326
608
  wrangler.durable_objects = wrangler.durable_objects || {};
@@ -331,7 +613,7 @@ export class BuildCloudflareTask extends BuildTask {
331
613
  for (const d of descriptors) {
332
614
  wrangler.containers.push({
333
615
  class_name: d.className,
334
- image: d.image,
616
+ image: this.resolveContainerImage(d.image),
335
617
  instance_type: d.instanceType,
336
618
  max_instances: d.maxInstances,
337
619
  });
@@ -357,20 +639,24 @@ export class BuildCloudflareTask extends BuildTask {
357
639
  distDir: string,
358
640
  containers: ContainerDescriptor[] = [],
359
641
  ): Promise<void> {
642
+ // Extend `globalThis.__alepha_CloudflareContainer` instead of
643
+ // importing `@cloudflare/containers` directly. The entry is
644
+ // written AFTER Vite, so any bare specifier in here survives to
645
+ // workerd (which has `no_bundle: true`) and 10021's out. The
646
+ // global is set by a side-effect in `alepha/container`'s
647
+ // workerd entry, which Vite has already inlined into
648
+ // `./index.js`. ESM evaluates top-level imports before the
649
+ // module body, so by the time the `extends` expression below is
650
+ // evaluated, the global is set.
360
651
  const containerDeclarations = containers
361
652
  .map((c) => {
362
653
  const envVars = c.envVars
363
654
  ? ` envVars = ${JSON.stringify(c.envVars)};\n`
364
655
  : "";
365
- return `export class ${c.className} extends Container {\n defaultPort = ${c.port};\n sleepAfter = "${c.sleepAfter}";\n${envVars}}`;
656
+ return `export class ${c.className} extends globalThis.__alepha_CloudflareContainer {\n defaultPort = ${c.port};\n sleepAfter = "${c.sleepAfter}";\n${envVars}}`;
366
657
  })
367
658
  .join("\n\n");
368
659
 
369
- const containerImport =
370
- containers.length > 0
371
- ? `import { Container } from "@cloudflare/containers";\n\n${containerDeclarations}\n\n`
372
- : "";
373
-
374
660
  const workerCode = `
375
661
  import "./index.js";
376
662
 
@@ -385,11 +671,19 @@ const setWaitUntil = (executionCtx) => {
385
671
  }
386
672
  };
387
673
 
674
+ // Bind the per-invocation Worker \`env\`: keep the full binding (D1, R2, KV, …)
675
+ // in the store for providers, and lift its string values (secrets/vars like
676
+ // PUBLIC_URL) into \`alepha.env\` so \`$env\` resolves them at runtime.
677
+ const bindEnv = (env) => {
678
+ __alepha.set("cloudflare.env", env);
679
+ __alepha.loadEnv(env);
680
+ };
681
+
388
682
  export default {
389
683
  fetch: async (request, env, executionCtx) => {
390
684
  const ctx = { req: request, res: undefined };
391
685
 
392
- __alepha.set("cloudflare.env", env);
686
+ bindEnv(env);
393
687
  setWaitUntil(executionCtx);
394
688
 
395
689
  try {
@@ -405,7 +699,7 @@ export default {
405
699
  },
406
700
 
407
701
  scheduled: async (event, env, executionCtx) => {
408
- __alepha.set("cloudflare.env", env);
702
+ bindEnv(env);
409
703
  setWaitUntil(executionCtx);
410
704
 
411
705
  try {
@@ -422,7 +716,7 @@ export default {
422
716
  },
423
717
 
424
718
  queue: async (batch, env, executionCtx) => {
425
- __alepha.set("cloudflare.env", env);
719
+ bindEnv(env);
426
720
  setWaitUntil(executionCtx);
427
721
 
428
722
  try {
@@ -444,9 +738,12 @@ export default {
444
738
  };
445
739
  `.trim();
446
740
 
741
+ const containerBlock =
742
+ containers.length > 0 ? `${containerDeclarations}\n\n` : "";
743
+
447
744
  await this.fs.writeFile(
448
745
  this.fs.join(root, distDir, "main.cloudflare.js"),
449
- `${this.warningComment}\n${containerImport}${workerCode}`.trim(),
746
+ `${this.warningComment}\n${containerBlock}${workerCode}`.trim(),
450
747
  );
451
748
  }
452
749
  }
@@ -457,7 +754,16 @@ interface ContainerDescriptor {
457
754
  image: string;
458
755
  port: number;
459
756
  sleepAfter: string;
460
- instanceType: "dev" | "basic" | "standard";
757
+ /**
758
+ * Cloudflare Containers instance class.
759
+ *
760
+ * `dev` is the wrangler-pre-GA name; the platform accepts it but
761
+ * emits a deprecation warning telling you to use `lite`. We
762
+ * silently translate at write time (see `discoverContainers`
763
+ * default + `enhanceContainers` write) so older
764
+ * `$container({ instanceType: "dev" })` declarations keep working.
765
+ */
766
+ instanceType: "dev" | "lite" | "basic" | "standard";
461
767
  maxInstances: number;
462
768
  envVars?: Record<string, string>;
463
769
  }
@@ -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"]
@@ -2,6 +2,7 @@ import type { Alepha } from "alepha";
2
2
  import type { RunnerMethod } from "alepha/command";
3
3
  import type { BuildOptions } from "../atoms/buildOptions.ts";
4
4
  import type { AppEntry } from "../providers/AppEntryProvider.ts";
5
+ import type { BuildManifest } from "./BuildCloudflareTask.ts";
5
6
 
6
7
  export interface BuildTaskContext {
7
8
  /**
@@ -43,6 +44,39 @@ export interface BuildTaskContext {
43
44
  * Raw CLI flags passed through from the command.
44
45
  * Tasks can read flags relevant to their domain.
45
46
  */
47
+ /**
48
+ * Build-time snapshot of primitive data, read from
49
+ * `dist/manifest.json`. Populated only in `--prebuilt` mode when a
50
+ * previous build's manifest is present — lets BuildCloudflareTask
51
+ * regenerate `wrangler.jsonc` without re-booting the workspace.
52
+ * `null` when introspection (`ctx.alepha`) is the source of truth.
53
+ */
54
+ manifest: BuildManifest | null;
55
+
56
+ /**
57
+ * Resolved `platform({ default, environments, ... })` options from
58
+ * the workspace's `alepha.config.ts`. Populated by `BuildCommand`
59
+ * from the CLI's Alepha instance (where alepha.config.ts ran) —
60
+ * BuildCloudflareTask uses these to write the corresponding fields
61
+ * into `dist/manifest.json` so the deploy side doesn't need to
62
+ * re-load `alepha.config.ts`. `null` when no platform options were
63
+ * declared.
64
+ */
65
+ platformOptions: {
66
+ default?: string;
67
+ tenancy?: "none" | "optional" | "required";
68
+ environments?: Record<
69
+ string,
70
+ {
71
+ adapter: "cloudflare" | "vercel";
72
+ domain?: string;
73
+ zone?: string;
74
+ jurisdiction?: "eu" | "fedramp";
75
+ accountId?: string;
76
+ }
77
+ >;
78
+ } | null;
79
+
46
80
  flags?: {
47
81
  image?: boolean | string;
48
82
  /**