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,15 +1,21 @@
1
1
  import { $inject, Alepha, AlephaError } from "alepha";
2
+ import type { AppEntry } from "alepha/cli";
2
3
  import type { RunnerMethod } from "alepha/command";
3
4
  import { $logger, ConsoleColorProvider } from "alepha/logger";
4
5
  import { CloudflareAdapter } from "../adapters/CloudflareAdapter.ts";
5
6
  import type {
6
- AppDefinition,
7
+ DetectedResources,
7
8
  PlatformAdapter,
8
9
  PlatformContext,
9
10
  PlatformState,
10
11
  } from "../adapters/PlatformAdapter.ts";
11
12
  import { VercelAdapter } from "../adapters/VercelAdapter.ts";
12
- import { type NamingContext, NamingService } from "./NamingService.ts";
13
+ import {
14
+ type NamingContext,
15
+ NamingService,
16
+ resolveTenant,
17
+ tenantDomain,
18
+ } from "./NamingService.ts";
13
19
  import {
14
20
  PlatformInspector,
15
21
  type ResolvedPlatformConfig,
@@ -52,7 +58,8 @@ export class PlatformOrchestrator {
52
58
  public async up(options: {
53
59
  root: string;
54
60
  env: string;
55
- apps: AppDefinition[];
61
+ entry: AppEntry;
62
+ resources: DetectedResources;
56
63
  run: RunnerMethod;
57
64
  /**
58
65
  * Pre-built mode — the artifact's `dist/` is already produced.
@@ -66,54 +73,43 @@ export class PlatformOrchestrator {
66
73
  * per-tenant overrides on every deploy.
67
74
  */
68
75
  prebuilt?: boolean;
76
+ /** Tenant slug (apps with tenancy optional|required). */
77
+ tenant?: string;
69
78
  }): Promise<{ urls: string[]; domain?: string }> {
70
- const { root, env, apps, run, prebuilt } = options;
79
+ const { root, env, entry, resources, run, prebuilt } = options;
71
80
  const envConfig = await this.inspector.resolveEnvironment(root, env);
72
81
  const config = await this.inspector.resolveConfig(root);
73
82
  const adapter = this.resolveAdapter(envConfig.adapter);
74
- const namingCtx = this.naming.forContext(config.project, env);
83
+ const tenant = resolveTenant(config.tenancy, options.tenant);
84
+ const namingCtx = this.naming.forContext(config.project, env, tenant);
75
85
 
76
86
  const ctx: PlatformContext = {
77
87
  project: config.project,
78
88
  env,
79
89
  envConfig,
80
- apps,
81
90
  root,
91
+ entry,
92
+ resources,
82
93
  naming: namingCtx,
94
+ tenant,
83
95
  prebuilt,
84
96
  };
85
97
 
86
- // 1. Auth
87
98
  await adapter.authenticate(ctx, run);
88
-
89
- // 2. Provision (before build so resource IDs are available for wrangler config)
90
99
  await adapter.provision(ctx, run);
91
-
92
- // 3. Build
93
- // Always runs — the adapter checks `ctx.prebuilt` to decide whether
94
- // to do a full bundle build or just regenerate deploy config.
95
- for (const a of apps) {
96
- await adapter.build({ ...ctx, app: a }, run);
97
- }
98
-
99
- // 4. Migrate
100
+ // `build` always runs — adapter checks `ctx.prebuilt` to decide
101
+ // whether to do a full bundle build or only regenerate deploy config.
102
+ await adapter.build(ctx, run);
100
103
  await adapter.migrate(ctx, run);
101
-
102
- // 5. Deploy
103
- const urls: string[] = [];
104
- for (const a of apps) {
105
- const url = await adapter.deploy({ ...ctx, app: a }, run);
106
- if (url) {
107
- urls.push(url);
108
- }
109
- }
110
-
111
- // 6. Secrets (push .env.{env} secrets to deployed workers)
104
+ const url = await adapter.deploy(ctx, run);
112
105
  await adapter.secrets(ctx, run);
113
106
 
114
107
  run.end();
115
108
 
116
- return { urls, domain: envConfig.domain };
109
+ return {
110
+ urls: url ? [url] : [],
111
+ domain: tenantDomain(envConfig.domain, tenant),
112
+ };
117
113
  }
118
114
 
119
115
  /**
@@ -146,23 +142,29 @@ export class PlatformOrchestrator {
146
142
  public async down(options: {
147
143
  root: string;
148
144
  env: string;
149
- apps: AppDefinition[];
145
+ entry: AppEntry;
146
+ resources: DetectedResources;
150
147
  run: RunnerMethod;
151
148
  confirm: (prompt: string) => Promise<string>;
149
+ /** Tenant slug (apps with tenancy optional|required). */
150
+ tenant?: string;
152
151
  }): Promise<boolean> {
153
- const { root, env, apps, run, confirm } = options;
152
+ const { root, env, entry, resources, run, confirm } = options;
154
153
  const envConfig = await this.inspector.resolveEnvironment(root, env);
155
154
  const config = await this.inspector.resolveConfig(root);
156
155
  const adapter = this.resolveAdapter(envConfig.adapter);
157
- const namingCtx = this.naming.forContext(config.project, env);
156
+ const tenant = resolveTenant(config.tenancy, options.tenant);
157
+ const namingCtx = this.naming.forContext(config.project, env, tenant);
158
158
 
159
159
  const ctx: PlatformContext = {
160
160
  project: config.project,
161
161
  env,
162
162
  envConfig,
163
- apps,
164
163
  root,
164
+ entry,
165
+ resources,
165
166
  naming: namingCtx,
167
+ tenant,
166
168
  };
167
169
 
168
170
  // Confirm (skip for tmp envs)
@@ -192,16 +194,19 @@ export class PlatformOrchestrator {
192
194
  public async plan(options: {
193
195
  root: string;
194
196
  env: string;
195
- apps: AppDefinition[];
197
+ resources: DetectedResources;
198
+ /** Tenant slug (apps with tenancy optional|required). */
199
+ tenant?: string;
196
200
  }): Promise<{
197
201
  config: ResolvedPlatformConfig;
198
202
  naming: NamingContext;
199
- apps: AppDefinition[];
203
+ resources: DetectedResources;
200
204
  }> {
201
- const { root, env, apps } = options;
205
+ const { root, env, resources } = options;
202
206
  const config = await this.inspector.resolveConfig(root);
203
- const namingCtx = this.naming.forContext(config.project, env);
204
- return { config, naming: namingCtx, apps };
207
+ const tenant = resolveTenant(config.tenancy, options.tenant);
208
+ const namingCtx = this.naming.forContext(config.project, env, tenant);
209
+ return { config, naming: namingCtx, resources };
205
210
  }
206
211
 
207
212
  // -------------------------------------------------------------------------
@@ -211,22 +216,28 @@ export class PlatformOrchestrator {
211
216
  public async status(options: {
212
217
  root: string;
213
218
  env: string;
214
- apps: AppDefinition[];
219
+ entry: AppEntry;
220
+ resources: DetectedResources;
215
221
  run: RunnerMethod;
222
+ /** Tenant slug (apps with tenancy optional|required). */
223
+ tenant?: string;
216
224
  }): Promise<{ config: ResolvedPlatformConfig; state: PlatformState }> {
217
- const { root, env, apps, run } = options;
225
+ const { root, env, entry, resources, run } = options;
218
226
  const envConfig = await this.inspector.resolveEnvironment(root, env);
219
227
  const config = await this.inspector.resolveConfig(root);
220
228
  const adapter = this.resolveAdapter(envConfig.adapter);
221
- const namingCtx = this.naming.forContext(config.project, env);
229
+ const tenant = resolveTenant(config.tenancy, options.tenant);
230
+ const namingCtx = this.naming.forContext(config.project, env, tenant);
222
231
 
223
232
  const ctx: PlatformContext = {
224
233
  project: config.project,
225
234
  env,
226
235
  envConfig,
227
- apps,
228
236
  root,
237
+ entry,
238
+ resources,
229
239
  naming: namingCtx,
240
+ tenant,
230
241
  };
231
242
 
232
243
  await adapter.authenticate(ctx, run);
@@ -98,10 +98,11 @@ export class WranglerApi {
98
98
  public async deploy(
99
99
  workerName: string,
100
100
  configPath: string,
101
+ root?: string,
101
102
  ): Promise<string | undefined> {
102
103
  const output = await this.runShell(
103
104
  `wrangler deploy --name=${workerName} --no-bundle --config=${configPath}`,
104
- { resolve: true, capture: true },
105
+ { resolve: true, capture: true, root },
105
106
  );
106
107
 
107
108
  const match = output.match(/https:\/\/[^\s]*\.workers\.dev/);
@@ -118,10 +119,11 @@ export class WranglerApi {
118
119
  public async d1MigrationsApply(
119
120
  dbName: string,
120
121
  configPath: string,
122
+ root?: string,
121
123
  ): Promise<void> {
122
124
  await this.runShell(
123
125
  `wrangler d1 migrations apply ${dbName} --remote --config=${configPath}`,
124
- { resolve: true, env: { CI: "1" } },
126
+ { resolve: true, env: { CI: "1" }, root },
125
127
  );
126
128
  }
127
129
  }
@@ -37,6 +37,26 @@ describe("Runner", () => {
37
37
  vi.clearAllMocks();
38
38
  });
39
39
 
40
+ test("useDynamicLogger: state overrides disable the stylish UI even with LOG_FORMAT=raw", () => {
41
+ // env says "raw" (stylish), but a runtime state override (what the CLI
42
+ // `--verbose` flag sets) must win. Asserting the *false* direction is
43
+ // deterministic across CI/non-CI (the dynamic-on path is gated on isCI).
44
+ const alepha = Alepha.create({
45
+ env: { LOG_LEVEL: "info", LOG_FORMAT: "raw" },
46
+ }).with({
47
+ provide: LogDestinationProvider,
48
+ use: MemoryDestinationProvider,
49
+ });
50
+ const r = alepha.inject(Runner);
51
+
52
+ alepha.store.set("alepha.logger.format", "pretty");
53
+ expect(r.useDynamicLogger).toBe(false);
54
+
55
+ alepha.store.set("alepha.logger.format", undefined);
56
+ alepha.store.set("alepha.logger.level", "debug");
57
+ expect(r.useDynamicLogger).toBe(false);
58
+ });
59
+
40
60
  test("should execute a single shell command via run.sh", async () => {
41
61
  await runner.run(`echo "hello"`);
42
62
 
@@ -52,11 +52,27 @@ export class EnvUtils {
52
52
  const trimmedKey = key.trim();
53
53
  if (trimmedKey && !trimmedKey.startsWith("#")) {
54
54
  let value = rest.join("=").trim();
55
- // Strip matching surrounding quotes (single or double)
55
+ const last = value.length - 1;
56
56
  if (
57
57
  value.length >= 2 &&
58
- ((value[0] === '"' && value[value.length - 1] === '"') ||
59
- (value[0] === "'" && value[value.length - 1] === "'"))
58
+ value[0] === '"' &&
59
+ value[last] === '"'
60
+ ) {
61
+ // Double-quoted: JSON-decode so escapes round-trip with a
62
+ // `JSON.stringify`-based writer (e.g. Rocket's
63
+ // `.env.<env>.local` overrides, which write JSON values like
64
+ // CLUB_CONFIG_JSON). Falls back to a naive strip when the
65
+ // body isn't valid JSON (e.g. a Windows path with `\`), so
66
+ // simple `KEY="value"` still behaves as before.
67
+ try {
68
+ value = JSON.parse(value);
69
+ } catch {
70
+ value = value.slice(1, -1);
71
+ }
72
+ } else if (
73
+ value.length >= 2 &&
74
+ value[0] === "'" &&
75
+ value[last] === "'"
60
76
  ) {
61
77
  value = value.slice(1, -1);
62
78
  }
@@ -78,12 +78,22 @@ export class Runner {
78
78
  return false;
79
79
  }
80
80
 
81
- const logLevel = String(this.alepha.env.LOG_LEVEL || "").toLowerCase();
81
+ // Runtime state overrides the env defaults (e.g. the CLI `--verbose`
82
+ // flag sets level=debug + format=pretty), so a flag can flip the
83
+ // stylish task UI off without restarting with LOG_* env vars.
84
+ const logLevel = String(
85
+ this.alepha.store.get("alepha.logger.level") ??
86
+ this.alepha.env.LOG_LEVEL ??
87
+ "",
88
+ ).toLowerCase();
82
89
  if (logLevel === "debug" || logLevel === "trace") {
83
90
  return false;
84
91
  }
85
92
 
86
- return this.alepha.env.LOG_FORMAT === "raw";
93
+ const format =
94
+ this.alepha.store.get("alepha.logger.format") ??
95
+ this.alepha.env.LOG_FORMAT;
96
+ return format === "raw";
87
97
  }
88
98
 
89
99
  /**
@@ -145,6 +145,13 @@ export class CliProvider {
145
145
  description: "Show this help message",
146
146
  schema: t.boolean(),
147
147
  },
148
+ verbose: {
149
+ // No `-v` alias — it collides with `--version` on the root command.
150
+ aliases: ["verbose"],
151
+ description:
152
+ "Verbose output: debug logs in plain pretty format (turns off the dynamic CLI UI).",
153
+ schema: t.boolean(),
154
+ },
148
155
  };
149
156
 
150
157
  // ─────────────────────────────────────────────────────────────────────────────
@@ -175,6 +182,14 @@ export class CliProvider {
175
182
  { strict: false }, // Don't throw for command-specific flags
176
183
  );
177
184
 
185
+ // `--verbose` → flip the logger to debug + plain pretty output via
186
+ // state (read live by Logger + Runner). Set before the command runs
187
+ // so its output and task UI honor it.
188
+ if (globalFlags.verbose) {
189
+ this.alepha.store.set("alepha.logger.level", "debug");
190
+ this.alepha.store.set("alepha.logger.format", "pretty");
191
+ }
192
+
178
193
  if (globalFlags.help) {
179
194
  this.printHelp(command);
180
195
  return;
@@ -552,10 +567,28 @@ export class CliProvider {
552
567
  });
553
568
  }
554
569
 
570
+ // Tolerate global flags (--help, --verbose) so strict command parsing
571
+ // doesn't reject them — they're consumed by the onReady global pass,
572
+ // not by the command. Skip any whose alias the command already claims
573
+ // (e.g. a command with its own `verbose` flag handles it directly).
574
+ const claimed = new Set(flagDefs.flatMap((d) => d.aliases));
575
+ for (const [key, value] of Object.entries(this.getAllGlobalFlags())) {
576
+ if (value.aliases.some((a: string) => claimed.has(a))) continue;
577
+ flagDefs.push({
578
+ key: `__global_${key}__`,
579
+ aliases: value.aliases,
580
+ description: undefined,
581
+ schema: value.schema,
582
+ });
583
+ }
584
+
555
585
  const parsed = this.parseFlags(argv, flagDefs);
556
586
 
557
- // Remove the mode flag from parsed result (it's handled separately)
587
+ // Remove the mode + global flags from parsed result (handled separately)
558
588
  parsed.__mode__ = undefined;
589
+ for (const key of Object.keys(parsed)) {
590
+ if (key.startsWith("__global_")) delete parsed[key];
591
+ }
559
592
 
560
593
  // apply manually defaults for optional properties that have defaults
561
594
  for (const [key, value] of Object.entries(schema.properties)) {
@@ -2,7 +2,7 @@ import { Alepha, t } from "alepha";
2
2
  import { $action, AlephaServer } from "alepha/server";
3
3
  import { AlephaServerLinks } from "alepha/server/links";
4
4
  import { describe, it } from "vitest";
5
- import { AlephaContainers } from "../index.ts";
5
+ import { AlephaContainer } from "../index.ts";
6
6
  import { $container } from "../primitives/$container.ts";
7
7
  import { ContainerProvider } from "../providers/ContainerProvider.ts";
8
8
  import { NodeContainerProvider } from "../providers/NodeContainerProvider.ts";
@@ -28,13 +28,13 @@ describe("$container", () => {
28
28
  });
29
29
  }
30
30
 
31
- // In test mode AlephaContainers binds the Mock provider by default,
31
+ // In test mode AlephaContainer binds the Mock provider by default,
32
32
  // which routes the proxy's `.createJob(...)` call back through
33
33
  // LinkProvider — so RocketController must live on the same Alepha.
34
34
  const alepha = Alepha.create({ env: { LOG_LEVEL: "warn" } })
35
35
  .with(AlephaServer)
36
36
  .with(AlephaServerLinks)
37
- .with(AlephaContainers)
37
+ .with(AlephaContainer)
38
38
  .with(RocketController)
39
39
  .with(DeployService);
40
40
 
@@ -55,7 +55,7 @@ describe("$container", () => {
55
55
  });
56
56
  }
57
57
 
58
- const alepha = Alepha.create({ env: {} }).with(AlephaContainers).with(App);
58
+ const alepha = Alepha.create({ env: {} }).with(AlephaContainer).with(App);
59
59
 
60
60
  // Force App instantiation so the primitive registers.
61
61
  const app = alepha.inject(App);
@@ -71,7 +71,7 @@ describe("$container", () => {
71
71
 
72
72
  const alepha = Alepha.create({ env: {} })
73
73
  .with({ provide: ContainerProvider, use: NodeContainerProvider })
74
- .with(AlephaContainers)
74
+ .with(AlephaContainer)
75
75
  .with(App);
76
76
  await alepha.start();
77
77
 
@@ -24,7 +24,7 @@ export * from "./providers/NodeContainerProvider.ts";
24
24
  * - Pluggable transport: Node (plain `fetch` against a configured URL),
25
25
  * Mock (in-process call via `LinkProvider.follow` for tests),
26
26
  * Cloudflare workerd (`getContainer().fetch()` through the Containers
27
- * binding — see `alepha/containers` workerd entry).
27
+ * binding — see `alepha/container` workerd entry).
28
28
  * - Build-time integration: `BuildCloudflareTask.enhanceContainers`
29
29
  * emits the matching wrangler bindings and Durable Object class
30
30
  * declarations.
@@ -33,10 +33,10 @@ export * from "./providers/NodeContainerProvider.ts";
33
33
  * the spec — apps need to provide an explicit `url` per primitive
34
34
  * until a `target=docker` adapter ships.
35
35
  *
36
- * @module alepha.containers
36
+ * @module alepha.container
37
37
  */
38
- export const AlephaContainers = $module({
39
- name: "alepha.containers",
38
+ export const AlephaContainer = $module({
39
+ name: "alepha.container",
40
40
  primitives: [$container],
41
41
  services: [ContainerProvider],
42
42
  variants: [MockContainerProvider, NodeContainerProvider],
@@ -1,8 +1,24 @@
1
+ import { Container } from "@cloudflare/containers";
1
2
  import { $module } from "alepha";
2
3
  import { $container } from "./primitives/$container.ts";
3
4
  import { CloudflareContainerProvider } from "./providers/CloudflareContainerProvider.ts";
4
5
  import { ContainerProvider } from "./providers/ContainerProvider.ts";
5
6
 
7
+ // Stash the Cloudflare Containers `Container` base class on globalThis
8
+ // so `BuildCloudflareTask`'s post-Vite-emitted entry
9
+ // (`dist/main.cloudflare.js`) can declare
10
+ // `class <T> extends globalThis.__alepha_CloudflareContainer` without
11
+ // introducing a bare `@cloudflare/containers` specifier.
12
+ //
13
+ // The entry is written AFTER Vite — anything Vite hasn't seen
14
+ // survives as an unresolved import all the way to workerd (where the
15
+ // upload is `no_bundle: true`). This side-effect runs whenever an app
16
+ // imports anything from `alepha/container` (Vite picks this file via
17
+ // the `workerd` export condition), so by the time the entry's
18
+ // `import "./index.js"` finishes, the global is set and the
19
+ // `extends` expression resolves.
20
+ (globalThis as any).__alepha_CloudflareContainer = Container;
21
+
6
22
  // ---------------------------------------------------------------------------------------------------------------------
7
23
 
8
24
  export * from "./interfaces/ContainerOptions.ts";
@@ -21,10 +37,10 @@ export * from "./providers/ContainerProvider.ts";
21
37
  * `BuildCloudflareTask.enhanceContainers` (in `alepha/cli/core`) which
22
38
  * emits the wrangler.jsonc bindings and DO class declarations.
23
39
  *
24
- * @module alepha.containers
40
+ * @module alepha.container
25
41
  */
26
- export const AlephaContainers = $module({
27
- name: "alepha.containers",
42
+ export const AlephaContainer = $module({
43
+ name: "alepha.container",
28
44
  primitives: [$container],
29
45
  services: [ContainerProvider, CloudflareContainerProvider],
30
46
  register: (alepha) => {
@@ -23,7 +23,7 @@ import { ContainerProvider } from "../providers/ContainerProvider.ts";
23
23
  *
24
24
  * @example
25
25
  * ```ts
26
- * import { $container } from "alepha/containers";
26
+ * import { $container } from "alepha/container";
27
27
  * import type { RocketController } from "@alepha/rocket";
28
28
  *
29
29
  * class DeployService {
@@ -1,3 +1,4 @@
1
+ import { getContainer } from "@cloudflare/containers";
1
2
  import { $inject, Alepha, AlephaError } from "alepha";
2
3
  import type { ContainerPrimitive } from "../primitives/$container.ts";
3
4
  import {
@@ -8,15 +9,18 @@ import {
8
9
  /**
9
10
  * Cloudflare Workers (workerd) container provider.
10
11
  *
11
- * Routes proxy calls through the Cloudflare Containers binding bound on
12
- * `env.<NAME>`, using a single shared instance per container
13
- * (`getContainer(env.NAME, "shared")`). The binding is generated by
14
- * `BuildCloudflareTask.enhanceContainers` from the `$container`
15
- * primitives discovered in the app.
12
+ * Routes proxy calls through the Cloudflare Containers binding bound
13
+ * on `env.<NAME>`, using a single shared instance per container.
14
+ * `getContainer` from `@cloudflare/containers` is a free function (not
15
+ * a method on the binding) — it takes the DO namespace and an id and
16
+ * returns a stub with a `.fetch()` method targeting the running
17
+ * container instance.
16
18
  *
17
- * The runtime `env` object is pulled from the Alepha store key
18
- * `cloudflare.env` the worker entry point publishes it there on every
19
- * fetch (`__alepha.set("cloudflare.env", env)`).
19
+ * The binding is generated by `BuildCloudflareTask.enhanceContainers`
20
+ * from the `$container` primitives discovered in the app. The runtime
21
+ * `env` object is pulled from the Alepha store key `cloudflare.env`
22
+ * — the worker entry point publishes it there on every fetch
23
+ * (`__alepha.set("cloudflare.env", env)`).
20
24
  */
21
25
  export class CloudflareContainerProvider extends ContainerProvider {
22
26
  protected readonly alepha = $inject(Alepha);
@@ -35,21 +39,15 @@ export class CloudflareContainerProvider extends ContainerProvider {
35
39
  );
36
40
  }
37
41
 
38
- const binding = env[container.name.toUpperCase()] as
39
- | {
40
- getContainer?: (id: string) => {
41
- fetch(req: Request): Promise<Response>;
42
- };
43
- }
44
- | undefined;
45
-
46
- if (!binding?.getContainer) {
42
+ const bindingName = container.name.toUpperCase();
43
+ const binding = env[bindingName];
44
+ if (!binding) {
47
45
  throw new AlephaError(
48
- `Cloudflare Containers binding '${container.name.toUpperCase()}' not found on env — check wrangler.jsonc.`,
46
+ `Cloudflare Containers binding '${bindingName}' not found on env — check wrangler.jsonc.`,
49
47
  );
50
48
  }
51
49
 
52
- const instance = binding.getContainer("shared");
50
+ const instance = getContainer(binding as never, "shared");
53
51
  const { path, init } = this.buildRequest(action, config);
54
52
  const request = new Request(`http://container${path}`, init);
55
53
  const response = await instance.fetch(request);
@@ -33,7 +33,7 @@ export abstract class ContainerProvider {
33
33
  void config;
34
34
  throw new AlephaError(
35
35
  `No ContainerProvider configured for container '${container.name}' (action '${action}'). ` +
36
- `Set up alepha/containers via AlephaContainers and either supply 'url' (Node) or build for target=cloudflare.`,
36
+ `Set up alepha/container via AlephaContainer and either supply 'url' (Node) or build for target=cloudflare.`,
37
37
  );
38
38
  }
39
39
 
@@ -54,11 +54,25 @@ export abstract class ContainerProvider {
54
54
  }
55
55
  }
56
56
 
57
+ // Match the route Alepha generates server-side when no explicit
58
+ // `path:` is set on `$action`: `/${name}` with one `/:<key>`
59
+ // segment appended per param. Params that match a `:key`
60
+ // placeholder are substituted in place; any remaining params are
61
+ // appended in declaration order so `params: {id:"abc"}` against a
62
+ // proxy action `getDeploy` yields `/api/getDeploy/abc`.
57
63
  let path = `/api/${action}`;
58
64
  if (config.params) {
65
+ const tail: string[] = [];
59
66
  for (const [k, v] of Object.entries(config.params)) {
60
- path = path.replace(`:${k}`, encodeURIComponent(String(v)));
67
+ const placeholder = `:${k}`;
68
+ const encoded = encodeURIComponent(String(v));
69
+ if (path.includes(placeholder)) {
70
+ path = path.replace(placeholder, encoded);
71
+ } else {
72
+ tail.push(encoded);
73
+ }
61
74
  }
75
+ if (tail.length) path += `/${tail.join("/")}`;
62
76
  }
63
77
 
64
78
  const search = params.toString();
@@ -17,7 +17,7 @@ import {
17
17
  * @example
18
18
  * ```ts
19
19
  * const alepha = Alepha.create()
20
- * .with(AlephaContainers)
20
+ * .with(AlephaContainer)
21
21
  * .with(RocketController)
22
22
  * .with(MyApp)
23
23
  * .with({ provide: ContainerProvider, use: MockContainerProvider });
@@ -971,6 +971,33 @@ export class Alepha {
971
971
 
972
972
  // -------------------------------------------------------------------------------------------------------------------
973
973
 
974
+ /**
975
+ * Merge additional environment variables into the env store at runtime.
976
+ *
977
+ * Serverless entrypoints (Cloudflare Workers) receive their secrets and
978
+ * vars on the runtime `env` binding rather than `process.env`, so they are
979
+ * absent from `alepha.env` — which is frozen at `create()` from
980
+ * `process.env`. Call this from the entrypoint to lift the binding's string
981
+ * values into `alepha.env`, so `$env` and `alepha.env.*` resolve them (e.g.
982
+ * `PUBLIC_URL`).
983
+ *
984
+ * Only string values are lifted; non-string bindings (D1, R2, KV, queues,
985
+ * …) are skipped. Existing env values win, so explicit configuration is
986
+ * never clobbered. The env cache is cleared so subsequent `$env` reads see
987
+ * the merged values.
988
+ */
989
+ public loadEnv(env: Record<string, unknown>): this {
990
+ const incoming: Record<string, string> = {};
991
+ for (const [key, value] of Object.entries(env)) {
992
+ if (typeof value === "string") {
993
+ incoming[key] = value;
994
+ }
995
+ }
996
+ this.store.set("env", { ...incoming, ...this.env });
997
+ this.cacheEnv.clear();
998
+ return this;
999
+ }
1000
+
974
1001
  /**
975
1002
  * Applies environment variables to the provided schema and state object.
976
1003
  *
@@ -1087,6 +1114,16 @@ export class Alepha {
1087
1114
  }
1088
1115
 
1089
1116
  public dump(): AlephaDump {
1117
+ // Force-instantiate the graph FIRST. `$env` is lazy — a key only lands in
1118
+ // `cacheEnv` once its owning service is constructed. `graph()` injects
1119
+ // every registered substitution (without emitting start/ready hooks), so
1120
+ // calling it before reading `cacheEnv` ensures `env` reflects the whole
1121
+ // app, not just whatever happened to be instantiated already. Reading
1122
+ // `cacheEnv` first (the old order) under-reported env on a not-yet-started
1123
+ // app and was internally inconsistent: dump() instantiated providers for
1124
+ // `providers` but never saw their env.
1125
+ const providers = this.graph();
1126
+
1090
1127
  const env: Record<string, AlephaDumpEnvVariable> = {};
1091
1128
  for (const [schema] of this.cacheEnv.entries()) {
1092
1129
  const ref = schema as any;
@@ -1103,7 +1140,7 @@ export class Alepha {
1103
1140
 
1104
1141
  return {
1105
1142
  env,
1106
- providers: this.graph(),
1143
+ providers,
1107
1144
  };
1108
1145
  }
1109
1146
 
@@ -1271,6 +1308,17 @@ export interface Env {
1271
1308
  * The secret key used for signing JWTs, encrypting cookies, and other security features.
1272
1309
  */
1273
1310
  APP_SECRET?: string;
1311
+
1312
+ /**
1313
+ * Public-facing base URL of the deployed app (e.g. "https://lore.alepha.dev").
1314
+ *
1315
+ * Used to render absolute links — emails, OAuth callbacks, sitemap. On the
1316
+ * Cloudflare platform it is auto-derived from the configured production
1317
+ * domain and pushed as a Worker secret by `alepha platform up`; otherwise
1318
+ * set it explicitly in `.env.<env>`. Unset → empty, and absolute-link
1319
+ * builders fall back to relative URLs.
1320
+ */
1321
+ PUBLIC_URL?: string;
1274
1322
  }
1275
1323
 
1276
1324
  // ---------------------------------------------------------------------------------------------------------------------