alepha 0.21.2 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (519) hide show
  1. package/README.md +0 -1
  2. package/dist/api/audits/index.browser.js.map +1 -1
  3. package/dist/api/audits/index.d.ts +393 -403
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/audits/index.js +25 -56
  6. package/dist/api/audits/index.js.map +1 -1
  7. package/dist/api/files/index.browser.js +31 -1
  8. package/dist/api/files/index.browser.js.map +1 -1
  9. package/dist/api/files/index.d.ts +313 -208
  10. package/dist/api/files/index.d.ts.map +1 -1
  11. package/dist/api/files/index.js +152 -42
  12. package/dist/api/files/index.js.map +1 -1
  13. package/dist/api/jobs/index.browser.js +2 -2
  14. package/dist/api/jobs/index.browser.js.map +1 -1
  15. package/dist/api/jobs/index.d.ts +282 -285
  16. package/dist/api/jobs/index.d.ts.map +1 -1
  17. package/dist/api/jobs/index.js +39 -33
  18. package/dist/api/jobs/index.js.map +1 -1
  19. package/dist/api/keys/index.d.ts +217 -222
  20. package/dist/api/keys/index.d.ts.map +1 -1
  21. package/dist/api/keys/index.js.map +1 -1
  22. package/dist/api/notifications/index.browser.js.map +1 -1
  23. package/dist/api/notifications/index.d.ts +188 -195
  24. package/dist/api/notifications/index.d.ts.map +1 -1
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/oauth/index.d.ts +71 -76
  27. package/dist/api/oauth/index.d.ts.map +1 -1
  28. package/dist/api/oauth/index.js.map +1 -1
  29. package/dist/api/organizations/index.browser.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +104 -109
  31. package/dist/api/organizations/index.d.ts.map +1 -1
  32. package/dist/api/organizations/index.js.map +1 -1
  33. package/dist/api/parameters/index.browser.js +43 -16
  34. package/dist/api/parameters/index.browser.js.map +1 -1
  35. package/dist/api/parameters/index.d.ts +488 -344
  36. package/dist/api/parameters/index.d.ts.map +1 -1
  37. package/dist/api/parameters/index.js +175 -35
  38. package/dist/api/parameters/index.js.map +1 -1
  39. package/dist/api/payments/index.d.ts +396 -402
  40. package/dist/api/payments/index.d.ts.map +1 -1
  41. package/dist/api/payments/index.js.map +1 -1
  42. package/dist/api/subscriptions/index.d.ts +644 -652
  43. package/dist/api/subscriptions/index.d.ts.map +1 -1
  44. package/dist/api/subscriptions/index.js +1 -1
  45. package/dist/api/subscriptions/index.js.map +1 -1
  46. package/dist/api/users/index.browser.js +7 -0
  47. package/dist/api/users/index.browser.js.map +1 -1
  48. package/dist/api/users/index.d.ts +1106 -1005
  49. package/dist/api/users/index.d.ts.map +1 -1
  50. package/dist/api/users/index.js +307 -64
  51. package/dist/api/users/index.js.map +1 -1
  52. package/dist/api/verifications/index.browser.js.map +1 -1
  53. package/dist/api/verifications/index.d.ts +137 -143
  54. package/dist/api/verifications/index.d.ts.map +1 -1
  55. package/dist/api/verifications/index.js.map +1 -1
  56. package/dist/background/index.d.ts +95 -0
  57. package/dist/background/index.d.ts.map +1 -0
  58. package/dist/background/index.js +121 -0
  59. package/dist/background/index.js.map +1 -0
  60. package/dist/background/index.workerd.js +110 -0
  61. package/dist/background/index.workerd.js.map +1 -0
  62. package/dist/batch/index.d.ts +5 -7
  63. package/dist/batch/index.d.ts.map +1 -1
  64. package/dist/batch/index.js.map +1 -1
  65. package/dist/bin/index.js.map +1 -1
  66. package/dist/bucket/index.d.ts +76 -54
  67. package/dist/bucket/index.d.ts.map +1 -1
  68. package/dist/bucket/index.js +58 -11
  69. package/dist/bucket/index.js.map +1 -1
  70. package/dist/bucket/index.workerd.js +200 -5
  71. package/dist/bucket/index.workerd.js.map +1 -1
  72. package/dist/cache/core/index.d.ts +7 -10
  73. package/dist/cache/core/index.d.ts.map +1 -1
  74. package/dist/cache/core/index.js.map +1 -1
  75. package/dist/cache/core/index.workerd.js.map +1 -1
  76. package/dist/cache/database/index.d.ts +22 -26
  77. package/dist/cache/database/index.d.ts.map +1 -1
  78. package/dist/cache/database/index.js.map +1 -1
  79. package/dist/cache/redis/index.d.ts +4 -7
  80. package/dist/cache/redis/index.d.ts.map +1 -1
  81. package/dist/cache/redis/index.js.map +1 -1
  82. package/dist/captcha/index.d.ts +3 -6
  83. package/dist/captcha/index.d.ts.map +1 -1
  84. package/dist/captcha/index.js.map +1 -1
  85. package/dist/cli/config/index.d.ts.map +1 -1
  86. package/dist/cli/config/index.js.map +1 -1
  87. package/dist/cli/core/index.d.ts +458 -249
  88. package/dist/cli/core/index.d.ts.map +1 -1
  89. package/dist/cli/core/index.js +372 -660
  90. package/dist/cli/core/index.js.map +1 -1
  91. package/dist/cli/devtools/index.d.ts +3 -5
  92. package/dist/cli/devtools/index.d.ts.map +1 -1
  93. package/dist/cli/devtools/index.js.map +1 -1
  94. package/dist/cli/i18n/index.d.ts +20 -17
  95. package/dist/cli/i18n/index.d.ts.map +1 -1
  96. package/dist/cli/i18n/index.js +45 -11
  97. package/dist/cli/i18n/index.js.map +1 -1
  98. package/dist/cli/platform/index.d.ts +126 -1342
  99. package/dist/cli/platform/index.d.ts.map +1 -1
  100. package/dist/cli/platform/index.js +136 -2374
  101. package/dist/cli/platform/index.js.map +1 -1
  102. package/dist/cli/platform-lib/index.d.ts +1472 -0
  103. package/dist/cli/platform-lib/index.d.ts.map +1 -0
  104. package/dist/cli/platform-lib/index.js +2660 -0
  105. package/dist/cli/platform-lib/index.js.map +1 -0
  106. package/dist/cli/vendor/index.d.ts +17 -21
  107. package/dist/cli/vendor/index.d.ts.map +1 -1
  108. package/dist/cli/vendor/index.js.map +1 -1
  109. package/dist/command/index.d.ts +20 -19
  110. package/dist/command/index.d.ts.map +1 -1
  111. package/dist/command/index.js +39 -10
  112. package/dist/command/index.js.map +1 -1
  113. package/dist/{containers → container}/core/index.d.ts +13 -15
  114. package/dist/container/core/index.d.ts.map +1 -0
  115. package/dist/{containers → container}/core/index.js +23 -14
  116. package/dist/container/core/index.js.map +1 -0
  117. package/dist/{containers → container}/core/index.workerd.js +37 -22
  118. package/dist/container/core/index.workerd.js.map +1 -0
  119. package/dist/core/index.browser.js +27 -1
  120. package/dist/core/index.browser.js.map +1 -1
  121. package/dist/core/index.d.ts +48 -24
  122. package/dist/core/index.d.ts.map +1 -1
  123. package/dist/core/index.js +27 -1
  124. package/dist/core/index.js.map +1 -1
  125. package/dist/core/index.native.js +27 -1
  126. package/dist/core/index.native.js.map +1 -1
  127. package/dist/core/index.workerd.js +27 -1
  128. package/dist/core/index.workerd.js.map +1 -1
  129. package/dist/crypto/index.browser.js.map +1 -1
  130. package/dist/crypto/index.d.ts +5 -8
  131. package/dist/crypto/index.d.ts.map +1 -1
  132. package/dist/crypto/index.js.map +1 -1
  133. package/dist/datetime/index.d.ts +3 -4
  134. package/dist/datetime/index.d.ts.map +1 -1
  135. package/dist/datetime/index.js.map +1 -1
  136. package/dist/email/brevo/index.d.ts +2 -4
  137. package/dist/email/brevo/index.d.ts.map +1 -1
  138. package/dist/email/brevo/index.js.map +1 -1
  139. package/dist/email/cloudflare/index.d.ts +20 -7
  140. package/dist/email/cloudflare/index.d.ts.map +1 -1
  141. package/dist/email/cloudflare/index.js +46 -9
  142. package/dist/email/cloudflare/index.js.map +1 -1
  143. package/dist/email/core/index.d.ts +6 -9
  144. package/dist/email/core/index.d.ts.map +1 -1
  145. package/dist/email/core/index.js.map +1 -1
  146. package/dist/email/core/index.workerd.js.map +1 -1
  147. package/dist/email/smtp/index.d.ts +10 -13
  148. package/dist/email/smtp/index.d.ts.map +1 -1
  149. package/dist/email/smtp/index.js +107 -32
  150. package/dist/email/smtp/index.js.map +1 -1
  151. package/dist/fake/index.d.ts +1 -2
  152. package/dist/fake/index.d.ts.map +1 -1
  153. package/dist/fake/index.js.map +1 -1
  154. package/dist/lock/core/index.d.ts +9 -14
  155. package/dist/lock/core/index.d.ts.map +1 -1
  156. package/dist/lock/core/index.js.map +1 -1
  157. package/dist/lock/redis/index.d.ts +2 -4
  158. package/dist/lock/redis/index.d.ts.map +1 -1
  159. package/dist/lock/redis/index.js.map +1 -1
  160. package/dist/logger/index.d.ts +105 -76
  161. package/dist/logger/index.d.ts.map +1 -1
  162. package/dist/logger/index.js +196 -174
  163. package/dist/logger/index.js.map +1 -1
  164. package/dist/mcp/index.d.ts +25 -20
  165. package/dist/mcp/index.d.ts.map +1 -1
  166. package/dist/mcp/index.js +23 -0
  167. package/dist/mcp/index.js.map +1 -1
  168. package/dist/orm/core/index.browser.js.map +1 -1
  169. package/dist/orm/core/index.bun.js +19 -1
  170. package/dist/orm/core/index.bun.js.map +1 -1
  171. package/dist/orm/core/index.d.ts +76 -62
  172. package/dist/orm/core/index.d.ts.map +1 -1
  173. package/dist/orm/core/index.js +20 -2
  174. package/dist/orm/core/index.js.map +1 -1
  175. package/dist/orm/postgres/index.bun.js.map +1 -1
  176. package/dist/orm/postgres/index.d.ts +28 -20
  177. package/dist/orm/postgres/index.d.ts.map +1 -1
  178. package/dist/orm/postgres/index.js.map +1 -1
  179. package/dist/queue/core/index.d.ts +12 -15
  180. package/dist/queue/core/index.d.ts.map +1 -1
  181. package/dist/queue/core/index.js.map +1 -1
  182. package/dist/queue/core/index.workerd.js.map +1 -1
  183. package/dist/queue/redis/index.d.ts +3 -5
  184. package/dist/queue/redis/index.d.ts.map +1 -1
  185. package/dist/queue/redis/index.js.map +1 -1
  186. package/dist/react/auth/index.browser.js +9 -2
  187. package/dist/react/auth/index.browser.js.map +1 -1
  188. package/dist/react/auth/index.d.ts +14 -9
  189. package/dist/react/auth/index.d.ts.map +1 -1
  190. package/dist/react/auth/index.js +9 -2
  191. package/dist/react/auth/index.js.map +1 -1
  192. package/dist/react/core/index.d.ts +7 -8
  193. package/dist/react/core/index.d.ts.map +1 -1
  194. package/dist/react/core/index.js +6 -3
  195. package/dist/react/core/index.js.map +1 -1
  196. package/dist/react/form/index.d.ts +2 -5
  197. package/dist/react/form/index.d.ts.map +1 -1
  198. package/dist/react/form/index.js +16 -15
  199. package/dist/react/form/index.js.map +1 -1
  200. package/dist/react/head/index.browser.js.map +1 -1
  201. package/dist/react/head/index.d.ts +2 -4
  202. package/dist/react/head/index.d.ts.map +1 -1
  203. package/dist/react/head/index.js.map +1 -1
  204. package/dist/react/i18n/index.d.ts +90 -11
  205. package/dist/react/i18n/index.d.ts.map +1 -1
  206. package/dist/react/i18n/index.js +147 -11
  207. package/dist/react/i18n/index.js.map +1 -1
  208. package/dist/react/intro/index.d.ts +1 -2
  209. package/dist/react/intro/index.d.ts.map +1 -1
  210. package/dist/react/intro/index.js +2 -2
  211. package/dist/react/intro/index.js.map +1 -1
  212. package/dist/react/router/index.browser.js +193 -24
  213. package/dist/react/router/index.browser.js.map +1 -1
  214. package/dist/react/router/index.d.ts +434 -222
  215. package/dist/react/router/index.d.ts.map +1 -1
  216. package/dist/react/router/index.js +249 -35
  217. package/dist/react/router/index.js.map +1 -1
  218. package/dist/react/sitemap/index.browser.js +35 -0
  219. package/dist/react/sitemap/index.browser.js.map +1 -0
  220. package/dist/react/sitemap/index.d.ts +92 -0
  221. package/dist/react/sitemap/index.d.ts.map +1 -0
  222. package/dist/react/sitemap/index.js +131 -0
  223. package/dist/react/sitemap/index.js.map +1 -0
  224. package/dist/react/testing/index.d.ts +1 -2
  225. package/dist/react/testing/index.d.ts.map +1 -1
  226. package/dist/react/testing/index.js +16 -17
  227. package/dist/react/testing/index.js.map +1 -1
  228. package/dist/react/ui/index.d.ts +20 -25
  229. package/dist/react/ui/index.d.ts.map +1 -1
  230. package/dist/react/ui/index.js.map +1 -1
  231. package/dist/redis/index.bun.js.map +1 -1
  232. package/dist/redis/index.d.ts +17 -19
  233. package/dist/redis/index.d.ts.map +1 -1
  234. package/dist/redis/index.js.map +1 -1
  235. package/dist/retry/index.d.ts +2 -4
  236. package/dist/retry/index.d.ts.map +1 -1
  237. package/dist/retry/index.js.map +1 -1
  238. package/dist/router/index.d.ts.map +1 -1
  239. package/dist/router/index.js.map +1 -1
  240. package/dist/scheduler/index.d.ts +10 -13
  241. package/dist/scheduler/index.d.ts.map +1 -1
  242. package/dist/scheduler/index.js.map +1 -1
  243. package/dist/scheduler/index.workerd.js.map +1 -1
  244. package/dist/security/index.browser.js.map +1 -1
  245. package/dist/security/index.d.ts +45 -48
  246. package/dist/security/index.d.ts.map +1 -1
  247. package/dist/security/index.js.map +1 -1
  248. package/dist/server/auth/index.browser.js.map +1 -1
  249. package/dist/server/auth/index.d.ts +272 -173
  250. package/dist/server/auth/index.d.ts.map +1 -1
  251. package/dist/server/auth/index.js +1608 -15
  252. package/dist/server/auth/index.js.map +1 -1
  253. package/dist/server/cookies/index.browser.js.map +1 -1
  254. package/dist/server/cookies/index.d.ts +20 -7
  255. package/dist/server/cookies/index.d.ts.map +1 -1
  256. package/dist/server/cookies/index.js +22 -3
  257. package/dist/server/cookies/index.js.map +1 -1
  258. package/dist/server/core/index.browser.js.map +1 -1
  259. package/dist/server/core/index.d.ts +106 -73
  260. package/dist/server/core/index.d.ts.map +1 -1
  261. package/dist/server/core/index.js +44 -0
  262. package/dist/server/core/index.js.map +1 -1
  263. package/dist/server/cors/index.d.ts +11 -14
  264. package/dist/server/cors/index.d.ts.map +1 -1
  265. package/dist/server/cors/index.js.map +1 -1
  266. package/dist/server/etag/index.d.ts +6 -9
  267. package/dist/server/etag/index.d.ts.map +1 -1
  268. package/dist/server/etag/index.js.map +1 -1
  269. package/dist/server/health/index.d.ts +18 -21
  270. package/dist/server/health/index.d.ts.map +1 -1
  271. package/dist/server/health/index.js.map +1 -1
  272. package/dist/server/links/index.browser.js +2 -0
  273. package/dist/server/links/index.browser.js.map +1 -1
  274. package/dist/server/links/index.d.ts +63 -67
  275. package/dist/server/links/index.d.ts.map +1 -1
  276. package/dist/server/links/index.js +2 -0
  277. package/dist/server/links/index.js.map +1 -1
  278. package/dist/server/metrics/index.d.ts +5 -7
  279. package/dist/server/metrics/index.d.ts.map +1 -1
  280. package/dist/server/metrics/index.js.map +1 -1
  281. package/dist/server/proxy/index.d.ts +3 -5
  282. package/dist/server/proxy/index.d.ts.map +1 -1
  283. package/dist/server/proxy/index.js.map +1 -1
  284. package/dist/server/rate-limit/index.d.ts +10 -13
  285. package/dist/server/rate-limit/index.d.ts.map +1 -1
  286. package/dist/server/rate-limit/index.js.map +1 -1
  287. package/dist/server/static/index.d.ts +3 -5
  288. package/dist/server/static/index.d.ts.map +1 -1
  289. package/dist/server/static/index.js.map +1 -1
  290. package/dist/server/swagger/index.d.ts +5 -8
  291. package/dist/server/swagger/index.d.ts.map +1 -1
  292. package/dist/server/swagger/index.js.map +1 -1
  293. package/dist/sms/index.d.ts +3 -5
  294. package/dist/sms/index.d.ts.map +1 -1
  295. package/dist/sms/index.js.map +1 -1
  296. package/dist/system/index.browser.js.map +1 -1
  297. package/dist/system/index.d.ts +2 -4
  298. package/dist/system/index.d.ts.map +1 -1
  299. package/dist/system/index.js.map +1 -1
  300. package/dist/system/index.workerd.js.map +1 -1
  301. package/dist/topic/core/index.d.ts +4 -6
  302. package/dist/topic/core/index.d.ts.map +1 -1
  303. package/dist/topic/core/index.js.map +1 -1
  304. package/dist/topic/redis/index.d.ts +5 -8
  305. package/dist/topic/redis/index.d.ts.map +1 -1
  306. package/dist/topic/redis/index.js.map +1 -1
  307. package/package.json +59 -23
  308. package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
  309. package/src/api/audits/controllers/AdminAuditController.ts +14 -0
  310. package/src/api/audits/services/AuditService.ts +21 -88
  311. package/src/api/files/__tests__/FileService.spec.ts +207 -2
  312. package/src/api/files/index.ts +3 -0
  313. package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
  314. package/src/api/files/schemas/fileResourceSchema.ts +10 -1
  315. package/src/api/files/services/FileService.ts +170 -72
  316. package/src/api/jobs/__tests__/$job.spec.ts +24 -1
  317. package/src/api/jobs/index.ts +4 -3
  318. package/src/api/jobs/primitives/$job.ts +7 -3
  319. package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
  320. package/src/api/jobs/providers/JobProvider.ts +53 -24
  321. package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
  322. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
  323. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
  324. package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
  325. package/src/api/parameters/audits/ParameterAudits.ts +17 -0
  326. package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
  327. package/src/api/parameters/index.ts +3 -0
  328. package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
  329. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
  330. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
  331. package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
  332. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
  333. package/src/api/parameters/services/ParameterProvider.ts +69 -6
  334. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
  335. package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
  336. package/src/api/users/audits/SessionAudits.ts +33 -0
  337. package/src/api/users/audits/UserAudits.ts +19 -43
  338. package/src/api/users/controllers/AdminUserController.ts +66 -1
  339. package/src/api/users/controllers/RealmController.ts +1 -0
  340. package/src/api/users/entities/sessions.ts +6 -0
  341. package/src/api/users/entities/users.ts +2 -0
  342. package/src/api/users/index.ts +9 -1
  343. package/src/api/users/primitives/$realm.ts +29 -0
  344. package/src/api/users/providers/RealmProvider.ts +15 -0
  345. package/src/api/users/schemas/realmConfigSchema.ts +14 -0
  346. package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
  347. package/src/api/users/schemas/updateUserSchema.ts +1 -8
  348. package/src/api/users/schemas/userQuerySchema.ts +7 -0
  349. package/src/api/users/services/CredentialService.ts +15 -6
  350. package/src/api/users/services/IdentityService.ts +2 -1
  351. package/src/api/users/services/RegistrationService.ts +2 -1
  352. package/src/api/users/services/SessionCrudService.ts +19 -2
  353. package/src/api/users/services/SessionService.ts +39 -19
  354. package/src/api/users/services/UserService.ts +106 -8
  355. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
  356. package/src/background/index.ts +37 -0
  357. package/src/background/index.workerd.ts +28 -0
  358. package/src/background/providers/BackgroundTaskProvider.ts +70 -0
  359. package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
  360. package/src/bucket/__tests__/$bucket.spec.ts +18 -0
  361. package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
  362. package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
  363. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
  364. package/src/bucket/__tests__/shared.ts +30 -0
  365. package/src/bucket/index.ts +5 -5
  366. package/src/bucket/index.workerd.ts +11 -4
  367. package/src/bucket/primitives/$bucket.ts +27 -0
  368. package/src/bucket/providers/FileStorageProvider.ts +13 -0
  369. package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
  370. package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
  371. package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
  372. package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
  373. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
  374. package/src/cli/core/__tests__/init.spec.ts +0 -219
  375. package/src/cli/core/atoms/buildOptions.ts +0 -12
  376. package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
  377. package/src/cli/core/commands/build.ts +105 -37
  378. package/src/cli/core/commands/init.ts +0 -12
  379. package/src/cli/core/commands/pack.ts +133 -0
  380. package/src/cli/core/index.ts +3 -3
  381. package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
  382. package/src/cli/core/services/PackageManagerUtils.ts +0 -16
  383. package/src/cli/core/services/ProjectScaffolder.ts +29 -291
  384. package/src/cli/core/tasks/BuildCloudflareTask.ts +382 -56
  385. package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
  386. package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
  387. package/src/cli/core/tasks/BuildTask.ts +34 -0
  388. package/src/cli/core/templates/apiIndexTs.ts +1 -22
  389. package/src/cli/core/templates/mainCss.ts +0 -1
  390. package/src/cli/core/templates/webAppRouterTs.ts +0 -99
  391. package/src/cli/core/templates/webIndexTs.ts +1 -22
  392. package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +48 -0
  393. package/src/cli/i18n/services/I18nCheckService.ts +65 -11
  394. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
  395. package/src/cli/platform/commands/SecretsCommand.ts +8 -6
  396. package/src/cli/platform/commands/platform.ts +192 -46
  397. package/src/cli/platform/index.ts +12 -52
  398. package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
  399. package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
  400. package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
  401. package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +519 -190
  402. package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
  403. package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
  404. package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
  405. package/src/cli/platform-lib/index.ts +67 -0
  406. package/src/cli/platform-lib/services/NamingService.ts +136 -0
  407. package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
  408. package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
  409. package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
  410. package/src/command/__tests__/Runner.spec.ts +20 -0
  411. package/src/command/helpers/EnvUtils.ts +19 -3
  412. package/src/command/helpers/Runner.ts +12 -2
  413. package/src/command/providers/CliProvider.ts +34 -1
  414. package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
  415. package/src/{containers → container}/core/index.ts +4 -4
  416. package/src/{containers → container}/core/index.workerd.ts +19 -3
  417. package/src/{containers → container}/core/primitives/$container.ts +1 -1
  418. package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
  419. package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
  420. package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
  421. package/src/core/Alepha.ts +49 -1
  422. package/src/core/__tests__/$env.spec.ts +42 -0
  423. package/src/core/__tests__/dump.spec.ts +47 -0
  424. package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
  425. package/src/email/cloudflare/index.ts +14 -5
  426. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
  427. package/src/logger/__tests__/Logger.spec.ts +55 -0
  428. package/src/logger/index.ts +13 -0
  429. package/src/logger/services/Logger.ts +31 -1
  430. package/src/mcp/__tests__/McpServerProvider.spec.ts +71 -0
  431. package/src/mcp/providers/McpServerProvider.ts +55 -0
  432. package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
  433. package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
  434. package/src/orm/core/interfaces/PgQuery.ts +4 -1
  435. package/src/orm/core/services/Repository.ts +27 -11
  436. package/src/react/auth/hooks/useAuth.ts +10 -5
  437. package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
  438. package/src/react/core/hooks/useAction.ts +14 -3
  439. package/src/react/core/hooks/useQuery.ts +24 -4
  440. package/src/react/form/__tests__/FormModel-submit-loading.spec.ts +71 -0
  441. package/src/react/form/__tests__/form-submitting-reactive.browser.spec.tsx +96 -0
  442. package/src/react/form/services/FormModel.ts +57 -39
  443. package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
  444. package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
  445. package/src/react/i18n/components/Translate.tsx +47 -0
  446. package/src/react/i18n/index.ts +2 -0
  447. package/src/react/i18n/providers/I18nProvider.ts +171 -12
  448. package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
  449. package/src/react/router/__tests__/$page.spec.tsx +3 -2
  450. package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
  451. package/src/react/router/__tests__/page-can.spec.ts +18 -13
  452. package/src/react/router/hooks/useQueryParams.ts +114 -14
  453. package/src/react/router/index.browser.ts +4 -0
  454. package/src/react/router/index.shared.ts +1 -0
  455. package/src/react/router/index.ts +9 -0
  456. package/src/react/router/primitives/$page.ts +85 -4
  457. package/src/react/router/providers/ReactBrowserRouterProvider.ts +18 -8
  458. package/src/react/router/providers/ReactPageProvider.ts +12 -1
  459. package/src/react/router/providers/ReactServerProvider.ts +96 -14
  460. package/src/react/router/providers/RootComponentsProvider.ts +13 -0
  461. package/src/react/router/providers/RouterLocaleProvider.ts +125 -0
  462. package/src/react/router/providers/__tests__/RootComponentsProvider.spec.ts +15 -0
  463. package/src/react/router/providers/__tests__/rootComponents.ssr.browser.spec.tsx +67 -0
  464. package/src/react/sitemap/__tests__/$sitemap.spec.ts +131 -0
  465. package/src/react/sitemap/index.browser.ts +21 -0
  466. package/src/react/sitemap/index.ts +25 -0
  467. package/src/react/sitemap/primitives/$sitemap.browser.ts +26 -0
  468. package/src/react/sitemap/primitives/$sitemap.ts +196 -0
  469. package/src/react/ui/services/SchemaControl.ts +3 -4
  470. package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
  471. package/src/server/auth/__tests__/authFederationClient.spec.ts +40 -0
  472. package/src/server/auth/__tests__/federationAssertion.spec.ts +146 -0
  473. package/src/server/auth/__tests__/federationRedirectReplay.spec.ts +44 -0
  474. package/src/server/auth/helpers/appleClientSecret.ts +24 -0
  475. package/src/server/auth/helpers/federationAssertion.ts +74 -0
  476. package/src/server/auth/helpers/jtiReplayGuard.ts +41 -0
  477. package/src/server/auth/helpers/safeRedirectPath.ts +19 -0
  478. package/src/server/auth/index.ts +4 -0
  479. package/src/server/auth/primitives/$authFederationBroker.ts +273 -0
  480. package/src/server/auth/primitives/$authFederationClient.ts +89 -0
  481. package/src/server/auth/providers/ServerAuthProvider.ts +18 -4
  482. package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +70 -0
  483. package/src/server/cookies/providers/ServerCookiesProvider.ts +23 -3
  484. package/src/server/core/interfaces/ServerRequest.ts +8 -0
  485. package/src/server/core/primitives/$route.ts +27 -0
  486. package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
  487. package/src/server/links/providers/LinkProvider.ts +10 -0
  488. package/dist/containers/core/index.d.ts.map +0 -1
  489. package/dist/containers/core/index.js.map +0 -1
  490. package/dist/containers/core/index.workerd.js.map +0 -1
  491. package/src/cli/core/tasks/BuildSitemapTask.ts +0 -130
  492. package/src/cli/core/templates/componentsJsonTs.ts +0 -39
  493. package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
  494. package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
  495. package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
  496. package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
  497. package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
  498. package/src/cli/platform/services/NamingService.ts +0 -54
  499. /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
  500. /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
  501. /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
  502. /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
  503. /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
  504. /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
  505. /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
  506. /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
  507. /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
  508. /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
  509. /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
  510. /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
  511. /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
  512. /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
  513. /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
  514. /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
  515. /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
  516. /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
  517. /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
  518. /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
  519. /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
@@ -0,0 +1,125 @@
1
+ import { $inject, Alepha } from "alepha";
2
+
3
+ /**
4
+ * Generic locale path-prefix mechanism for the router.
5
+ *
6
+ * This provider knows nothing about i18n — it only deals with URL path
7
+ * segments. It is configured by the i18n module (`I18nProvider`) when
8
+ * `routing: "prefix"` is enabled, which keeps the dependency one-directional
9
+ * (`i18n → router`) and avoids a module cycle.
10
+ *
11
+ * The default locale is served WITHOUT a prefix (`/about` = default,
12
+ * `/fr/about` = French). The active locale is derived from the current
13
+ * request/navigation and stored under `alepha.react.router.locale`, so every
14
+ * URL the router builds (`pathname()`) automatically carries the right prefix.
15
+ */
16
+ export class RouterLocaleProvider {
17
+ protected readonly alepha = $inject(Alepha);
18
+
19
+ /**
20
+ * Whether locale path-prefixing is active. Off by default — opt-in via the
21
+ * i18n module.
22
+ */
23
+ public enabled = false;
24
+
25
+ /**
26
+ * The default locale, served without a path prefix (e.g. `"en"` → `/about`).
27
+ */
28
+ public defaultLocale = "";
29
+
30
+ /**
31
+ * All known locales, including the default one.
32
+ */
33
+ public locales: string[] = [];
34
+
35
+ /**
36
+ * Configure the provider. Called by the i18n module before the SSR routes
37
+ * are registered.
38
+ */
39
+ public configure(options: {
40
+ enabled?: boolean;
41
+ defaultLocale?: string;
42
+ locales?: string[];
43
+ }): void {
44
+ if (options.enabled !== undefined) {
45
+ this.enabled = options.enabled;
46
+ }
47
+ if (options.defaultLocale !== undefined) {
48
+ this.defaultLocale = options.defaultLocale;
49
+ }
50
+ if (options.locales !== undefined) {
51
+ this.locales = options.locales;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Locales that carry a URL prefix — every known locale except the default.
57
+ */
58
+ public get prefixedLocales(): string[] {
59
+ return this.locales.filter((locale) => locale !== this.defaultLocale);
60
+ }
61
+
62
+ /**
63
+ * Splits a leading locale segment off a pathname.
64
+ *
65
+ * - `/fr/about` → `{ locale: "fr", pathname: "/about" }` when `fr` is a
66
+ * prefixed locale.
67
+ * - `/about` → `{ locale: defaultLocale, pathname: "/about" }`.
68
+ *
69
+ * When prefixing is disabled the pathname is returned untouched.
70
+ */
71
+ public detect(pathname: string): { locale: string; pathname: string } {
72
+ if (this.enabled) {
73
+ const first = pathname.split("/")[1];
74
+ if (first && this.prefixedLocales.includes(first)) {
75
+ const rest = pathname.slice(first.length + 1);
76
+ return { locale: first, pathname: this.normalize(rest) };
77
+ }
78
+ }
79
+ return { locale: this.defaultLocale, pathname };
80
+ }
81
+
82
+ /**
83
+ * Prepends the locale prefix to a pathname when needed. The default locale
84
+ * (and any unknown/disabled case) returns the pathname unchanged.
85
+ */
86
+ public withPrefix(pathname: string, locale: string = this.current): string {
87
+ if (
88
+ !this.enabled ||
89
+ !locale ||
90
+ locale === this.defaultLocale ||
91
+ !this.prefixedLocales.includes(locale)
92
+ ) {
93
+ return pathname;
94
+ }
95
+ return `/${locale}${pathname === "/" ? "" : pathname}`;
96
+ }
97
+
98
+ /**
99
+ * The active locale, derived from the current request/navigation. Falls back
100
+ * to the default locale when nothing has been detected.
101
+ */
102
+ public get current(): string {
103
+ return (
104
+ this.alepha.store.get("alepha.react.router.locale") || this.defaultLocale
105
+ );
106
+ }
107
+
108
+ public set current(locale: string) {
109
+ this.alepha.store.set("alepha.react.router.locale", locale);
110
+ }
111
+
112
+ /**
113
+ * Normalizes a stripped pathname so it always starts with a single slash and
114
+ * carries no trailing slash (except the root `/`).
115
+ */
116
+ protected normalize(pathname: string): string {
117
+ if (!pathname || pathname === "/") {
118
+ return "/";
119
+ }
120
+ const withLeading = pathname.startsWith("/") ? pathname : `/${pathname}`;
121
+ return withLeading.length > 1 && withLeading.endsWith("/")
122
+ ? withLeading.slice(0, -1)
123
+ : withLeading;
124
+ }
125
+ }
@@ -0,0 +1,15 @@
1
+ import { Alepha } from "alepha";
2
+ import { describe, expect, it } from "vitest";
3
+ import { RootComponentsProvider } from "../RootComponentsProvider.ts";
4
+
5
+ describe("RootComponentsProvider", () => {
6
+ it("starts empty and accepts pushed nodes", () => {
7
+ const alepha = Alepha.create();
8
+ const provider = alepha.inject(RootComponentsProvider);
9
+ expect(provider.rootComponents).toEqual([]);
10
+ provider.rootComponents.push("x" as any);
11
+ expect(alepha.inject(RootComponentsProvider).rootComponents).toHaveLength(
12
+ 1,
13
+ );
14
+ });
15
+ });
@@ -0,0 +1,67 @@
1
+ import { Alepha } from "alepha";
2
+ import { createElement } from "react";
3
+ import { describe, expect, it } from "vitest";
4
+ import type { ReactRouterState } from "../ReactPageProvider.ts";
5
+ import { ReactPageProvider } from "../ReactPageProvider.ts";
6
+ import { RootComponentsProvider } from "../RootComponentsProvider.ts";
7
+
8
+ /**
9
+ * Walk a React element tree (non-circular, element children only) and collect
10
+ * all "data-testid" values found in any element's props.
11
+ */
12
+ function collectTestIds(node: any, seen = new Set<any>()): string[] {
13
+ if (!node || typeof node !== "object" || seen.has(node)) {
14
+ return [];
15
+ }
16
+ seen.add(node);
17
+
18
+ const ids: string[] = [];
19
+
20
+ if (node.props?.["data-testid"]) {
21
+ ids.push(node.props["data-testid"]);
22
+ }
23
+
24
+ // Children may be a single node or an array
25
+ const children = node.props?.children;
26
+ if (Array.isArray(children)) {
27
+ for (const child of children) {
28
+ ids.push(...collectTestIds(child, seen));
29
+ }
30
+ } else if (children) {
31
+ ids.push(...collectTestIds(children, seen));
32
+ }
33
+
34
+ // Also walk positional children (args 2+ on createElement are spread as props.children
35
+ // but StrictMode wraps with a single child — unwrap one level manually)
36
+ return ids;
37
+ }
38
+
39
+ describe("rootComponents in ReactPageProvider.root", () => {
40
+ it("includes pushed components in the rendered root element tree", () => {
41
+ const alepha = Alepha.create();
42
+ alepha
43
+ .inject(RootComponentsProvider)
44
+ .rootComponents.push(
45
+ createElement("div", { "data-testid": "sigil-marker", key: "m" }),
46
+ );
47
+
48
+ const page = alepha.inject(ReactPageProvider);
49
+
50
+ const state: ReactRouterState = {
51
+ layers: [{ element: null } as any],
52
+ url: new URL("http://localhost/"),
53
+ onError: () => undefined as any,
54
+ params: {},
55
+ query: {},
56
+ meta: {},
57
+ head: {} as any,
58
+ };
59
+
60
+ const element: any = page.root(state);
61
+
62
+ // StrictMode wraps the root — unwrap one level
63
+ const inner = element?.props?.children ?? element;
64
+ const ids = collectTestIds(inner);
65
+ expect(ids).toContain("sigil-marker");
66
+ });
67
+ });
@@ -0,0 +1,131 @@
1
+ import { Alepha, t } from "alepha";
2
+ import { DateTimeProvider } from "alepha/datetime";
3
+ import { $page, AlephaReactRouter } from "alepha/react/router";
4
+ import { ServerRouterProvider } from "alepha/server";
5
+ import { describe, it } from "vitest";
6
+ import { AlephaReactSitemap } from "../index.ts";
7
+ import { $sitemap, type SitemapPrimitive } from "../primitives/$sitemap.ts";
8
+
9
+ describe("$sitemap", () => {
10
+ class App {
11
+ sitemap = $sitemap({ hostname: "https://example.com" });
12
+
13
+ home = $page({
14
+ path: "/",
15
+ static: true,
16
+ component: () => "home",
17
+ });
18
+
19
+ about = $page({
20
+ path: "/about",
21
+ static: true,
22
+ component: () => "about",
23
+ });
24
+
25
+ notFound = $page({
26
+ path: "/*",
27
+ component: () => "404",
28
+ });
29
+
30
+ github404 = $page({
31
+ path: "/404",
32
+ static: true,
33
+ component: () => "404",
34
+ });
35
+
36
+ blog = $page({
37
+ path: "/blog/:slug",
38
+ schema: { params: t.object({ slug: t.text() }) },
39
+ static: { entries: [{ params: { slug: "hello" } }] },
40
+ component: () => "post",
41
+ });
42
+ }
43
+
44
+ const start = async () => {
45
+ const alepha = Alepha.create()
46
+ .with(AlephaReactRouter)
47
+ .with(AlephaReactSitemap);
48
+ alepha.inject(App);
49
+ const router = alepha.inject(ServerRouterProvider);
50
+ await alepha.start();
51
+ return { alepha, router };
52
+ };
53
+
54
+ const sitemapOf = (alepha: Alepha) =>
55
+ alepha.primitives("sitemap")[0] as SitemapPrimitive;
56
+
57
+ const findSitemapRoute = (router: ServerRouterProvider) =>
58
+ router.getRoutes().find((route) => route.path === "/sitemap.xml");
59
+
60
+ it("registers a static GET /sitemap.xml route", async ({ expect }) => {
61
+ const { router } = await start();
62
+ const route = findSitemapRoute(router);
63
+ expect(route).toBeDefined();
64
+ expect(route?.method).toBe("GET");
65
+ expect(route?.static).toBe(true);
66
+ });
67
+
68
+ it("prerenders xml built from the app's pages", async ({ expect }) => {
69
+ const { alepha } = await start();
70
+ const { path, body } = sitemapOf(alepha).prerender();
71
+
72
+ expect(path).toBe("/sitemap.xml");
73
+ expect(body).toContain('<?xml version="1.0" encoding="UTF-8"?>');
74
+ expect(body).toContain("<loc>https://example.com/</loc>");
75
+ expect(body).toContain("<loc>https://example.com/about</loc>");
76
+ });
77
+
78
+ it("serves application/xml at request time", async ({ expect }) => {
79
+ const { router } = await start();
80
+ const route = findSitemapRoute(router)!;
81
+ const headers: Record<string, string> = {};
82
+ const reply = {
83
+ headers,
84
+ setHeader(name: string, value: string) {
85
+ headers[name.toLowerCase()] = value;
86
+ return this;
87
+ },
88
+ };
89
+ const body = await route.handler.run({ reply } as any);
90
+ expect(headers["content-type"]).toBe("application/xml");
91
+ expect(String(body)).toContain("<urlset");
92
+ });
93
+
94
+ it("expands parameterized pages via static.entries", async ({ expect }) => {
95
+ const { alepha } = await start();
96
+ const { body } = sitemapOf(alepha).prerender();
97
+ expect(body).toContain("<loc>https://example.com/blog/hello</loc>");
98
+ });
99
+
100
+ it("excludes wildcard and 404 routes", async ({ expect }) => {
101
+ const { alepha } = await start();
102
+ const { body } = sitemapOf(alepha).prerender();
103
+ expect(body).not.toContain("/*");
104
+ expect(body).not.toContain("/404");
105
+ });
106
+
107
+ it("falls back to PUBLIC_URL, then relative, when no hostname is given", async ({
108
+ expect,
109
+ }) => {
110
+ class RelApp {
111
+ sitemap = $sitemap();
112
+ home = $page({ path: "/", static: true, component: () => "home" });
113
+ }
114
+ const alepha = Alepha.create()
115
+ .with(AlephaReactRouter)
116
+ .with(AlephaReactSitemap);
117
+ alepha.inject(RelApp);
118
+ await alepha.start();
119
+
120
+ const { body } = sitemapOf(alepha).prerender();
121
+ expect(body).toContain("<loc>/</loc>");
122
+ });
123
+
124
+ it("uses DateTimeProvider for lastmod (travel-able)", async ({ expect }) => {
125
+ const { alepha } = await start();
126
+ const dateTime = alepha.inject(DateTimeProvider);
127
+ const expected = dateTime.now().format("YYYY-MM-DD");
128
+ const { body } = sitemapOf(alepha).prerender();
129
+ expect(body).toContain(`<lastmod>${expected}</lastmod>`);
130
+ });
131
+ });
@@ -0,0 +1,21 @@
1
+ import { $module } from "alepha";
2
+ import { $sitemap } from "./primitives/$sitemap.browser.ts";
3
+
4
+ // ---------------------------------------------------------------------------------------------------------------------
5
+
6
+ export * from "./primitives/$sitemap.browser.ts";
7
+
8
+ // ---------------------------------------------------------------------------------------------------------------------
9
+
10
+ /**
11
+ * Sitemap generation for React applications (browser entry).
12
+ *
13
+ * The sitemap route only exists server-side, so the browser build ships a
14
+ * no-op {@link $sitemap}. See the server entry for the real implementation.
15
+ *
16
+ * @module alepha.react.sitemap
17
+ */
18
+ export const AlephaReactSitemap = $module({
19
+ name: "alepha.react.sitemap",
20
+ primitives: [$sitemap],
21
+ });
@@ -0,0 +1,25 @@
1
+ import { $module } from "alepha";
2
+ import { AlephaDateTime } from "alepha/datetime";
3
+ import { AlephaServer } from "alepha/server";
4
+ import { $sitemap } from "./primitives/$sitemap.ts";
5
+
6
+ // ---------------------------------------------------------------------------------------------------------------------
7
+
8
+ export * from "./primitives/$sitemap.ts";
9
+
10
+ // ---------------------------------------------------------------------------------------------------------------------
11
+
12
+ /**
13
+ * Sitemap generation for React applications.
14
+ *
15
+ * Exposes the {@link $sitemap} primitive, which serves a `sitemap.xml` built
16
+ * from the app's `$page` primitives — live at request time and prerendered to a
17
+ * static file at build time.
18
+ *
19
+ * @module alepha.react.sitemap
20
+ */
21
+ export const AlephaReactSitemap = $module({
22
+ name: "alepha.react.sitemap",
23
+ imports: [AlephaServer, AlephaDateTime],
24
+ primitives: [$sitemap],
25
+ });
@@ -0,0 +1,26 @@
1
+ import { createPrimitive, KIND, Primitive } from "alepha";
2
+ import type { SitemapPrimitiveOptions } from "./$sitemap.ts";
3
+
4
+ export type { SitemapPrimitiveOptions } from "./$sitemap.ts";
5
+
6
+ /**
7
+ * Browser variant of {@link $sitemap}.
8
+ *
9
+ * The sitemap is a server-only route — there is nothing to register in the
10
+ * client bundle, so this is a no-op primitive. It exists only to keep
11
+ * `$sitemap()` valid as an isomorphic router field; the real implementation
12
+ * lives in `$sitemap.ts` (server entry).
13
+ */
14
+ export const $sitemap = (
15
+ options: SitemapPrimitiveOptions = {},
16
+ ): SitemapPrimitive => {
17
+ return createPrimitive(SitemapPrimitive, options);
18
+ };
19
+
20
+ export class SitemapPrimitive extends Primitive<SitemapPrimitiveOptions> {
21
+ protected onInit() {
22
+ // no-op in the browser
23
+ }
24
+ }
25
+
26
+ $sitemap[KIND] = SitemapPrimitive;
@@ -0,0 +1,196 @@
1
+ import { $inject, createPrimitive, KIND, Primitive } from "alepha";
2
+ import { DateTimeProvider } from "alepha/datetime";
3
+ import { type ServerRequest, ServerRouterProvider } from "alepha/server";
4
+
5
+ /**
6
+ * Expose a `sitemap.xml` generated from the application's `$page` primitives.
7
+ *
8
+ * Registers a `GET /sitemap.xml` route that reads every registered page at
9
+ * request time and emits a standard XML sitemap. Marked `static` by default, so
10
+ * the build prerenders it to `dist/public/sitemap.xml` for static deployments —
11
+ * while SSR runtimes also serve it live.
12
+ *
13
+ * The hostname comes from `options.hostname`, falling back to `PUBLIC_URL`, then
14
+ * to `""` (relative URLs).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { $sitemap } from "alepha/react/sitemap";
19
+ *
20
+ * class AppRouter {
21
+ * sitemap = $sitemap();
22
+ * }
23
+ * ```
24
+ */
25
+ export const $sitemap = (
26
+ options: SitemapPrimitiveOptions = {},
27
+ ): SitemapPrimitive => {
28
+ return createPrimitive(SitemapPrimitive, options);
29
+ };
30
+
31
+ // ---------------------------------------------------------------------------------------------------------------------
32
+
33
+ export interface SitemapPrimitiveOptions {
34
+ /**
35
+ * Absolute base URL used to build `<loc>` entries (e.g. "https://alepha.dev").
36
+ *
37
+ * Defaults to `PUBLIC_URL`, then to `""` (relative URLs).
38
+ */
39
+ hostname?: string;
40
+
41
+ /**
42
+ * Route path the sitemap is served at.
43
+ *
44
+ * @default "/sitemap.xml"
45
+ */
46
+ path?: string;
47
+
48
+ /**
49
+ * Prerender the sitemap to a static file at build time.
50
+ *
51
+ * @default true
52
+ */
53
+ static?: boolean;
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------------------------------------------------
57
+
58
+ export class SitemapPrimitive extends Primitive<SitemapPrimitiveOptions> {
59
+ protected readonly router = $inject(ServerRouterProvider);
60
+ protected readonly dateTime = $inject(DateTimeProvider);
61
+
62
+ protected onInit() {
63
+ this.router.createRoute({
64
+ method: "GET",
65
+ path: this.options.path ?? "/sitemap.xml",
66
+ static: this.options.static ?? true,
67
+ silent: true,
68
+ handler: (request: ServerRequest) => {
69
+ request.reply.setHeader("content-type", "application/xml");
70
+ return this.buildSitemap();
71
+ },
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Render the sitemap to its path and body. Used by the build to snapshot the
77
+ * sitemap to a static file.
78
+ */
79
+ public prerender(): { path: string; body: string } {
80
+ return {
81
+ path: this.options.path ?? "/sitemap.xml",
82
+ body: this.buildSitemap(),
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Build the sitemap XML from the application's page primitives.
88
+ */
89
+ protected buildSitemap(): string {
90
+ const hostname =
91
+ this.options.hostname ?? String(this.alepha.env.PUBLIC_URL ?? "");
92
+ const pages = this.getSitemapPages();
93
+ return this.generateSitemapFromPages(pages, hostname);
94
+ }
95
+
96
+ /**
97
+ * Select the pages that should appear in the sitemap.
98
+ *
99
+ * Excludes layout pages (with `children`), wildcard paths, and `/404`.
100
+ * Parameterized pages are included only when they declare `static.entries`.
101
+ */
102
+ protected getSitemapPages(): any[] {
103
+ const pages = this.alepha.primitives("page") as any[];
104
+ return pages.filter((page) => {
105
+ const options = page.options;
106
+ const path: string = options.path ?? "";
107
+ if (options.children) {
108
+ return false;
109
+ }
110
+ if (path.includes("*")) {
111
+ return false;
112
+ }
113
+ if (path === "/404") {
114
+ return false;
115
+ }
116
+ if (!options.schema?.params) {
117
+ return true;
118
+ }
119
+ if (
120
+ options.static &&
121
+ typeof options.static === "object" &&
122
+ options.static.entries
123
+ ) {
124
+ return true;
125
+ }
126
+ return false;
127
+ });
128
+ }
129
+
130
+ protected generateSitemapFromPages(pages: any[], baseUrl: string): string {
131
+ const urls: string[] = [];
132
+ const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
133
+
134
+ for (const page of pages) {
135
+ const options = page.options;
136
+
137
+ if (!options.schema?.params) {
138
+ const path = options.path || "";
139
+ const url = `${normalizedBaseUrl}${path === "" ? "/" : path}`;
140
+ urls.push(url);
141
+ } else if (
142
+ options.static &&
143
+ typeof options.static === "object" &&
144
+ options.static.entries
145
+ ) {
146
+ for (const entry of options.static.entries) {
147
+ const path = this.buildPathFromParams(
148
+ options.path || "",
149
+ entry.params || {},
150
+ );
151
+ const url = `${normalizedBaseUrl}${path}`;
152
+ urls.push(url);
153
+ }
154
+ }
155
+ }
156
+
157
+ return this.buildSitemapXml(urls);
158
+ }
159
+
160
+ protected buildPathFromParams(
161
+ pathPattern: string,
162
+ params: Record<string, any>,
163
+ ): string {
164
+ let path = pathPattern;
165
+ for (const [key, value] of Object.entries(params)) {
166
+ path = path.replace(`:${key}`, String(value));
167
+ }
168
+ return path || "/";
169
+ }
170
+
171
+ protected buildSitemapXml(urls: string[]): string {
172
+ const lastMod = this.dateTime.now().format("YYYY-MM-DD");
173
+ const urlEntries = urls
174
+ .map(
175
+ (url) =>
176
+ ` <url>\n <loc>${this.escapeXml(url)}</loc>\n <lastmod>${lastMod}</lastmod>\n </url>`,
177
+ )
178
+ .join("\n");
179
+
180
+ return `<?xml version="1.0" encoding="UTF-8"?>
181
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
182
+ ${urlEntries}
183
+ </urlset>`;
184
+ }
185
+
186
+ protected escapeXml(str: string): string {
187
+ return str
188
+ .replace(/&/g, "&amp;")
189
+ .replace(/</g, "&lt;")
190
+ .replace(/>/g, "&gt;")
191
+ .replace(/"/g, "&quot;")
192
+ .replace(/'/g, "&#39;");
193
+ }
194
+ }
195
+
196
+ $sitemap[KIND] = SitemapPrimitive;
@@ -1,9 +1,8 @@
1
1
  import type { FormModel } from "alepha/react/form";
2
2
 
3
3
  /**
4
- * Schema-bound metadata read by `<Control>` (in `@alepha/ui-registry`) to
5
- * configure how a field renders. Place under `$control` on any TypeBox
6
- * schema option.
4
+ * Schema-bound metadata read by `<Control>` (in `@alepha/ui`) to configure
5
+ * how a field renders. Place under `$control` on any TypeBox schema option.
7
6
  *
8
7
  * Two forms:
9
8
  *
@@ -201,7 +200,7 @@ export const resolveSchemaControl = (
201
200
  declare module "typebox" {
202
201
  interface TSchemaOptions {
203
202
  /**
204
- * UI metadata read by `<Control>` from `@alepha/ui-registry`. See
203
+ * UI metadata read by `<Control>` from `@alepha/ui`. See
205
204
  * {@link SchemaControl}.
206
205
  */
207
206
  $control?: SchemaControlOption;
@@ -0,0 +1,34 @@
1
+ import {
2
+ decodeJwt,
3
+ decodeProtectedHeader,
4
+ exportPKCS8,
5
+ generateKeyPair,
6
+ } from "jose";
7
+ import { describe, expect, it } from "vitest";
8
+ import { signAppleClientSecret } from "../helpers/appleClientSecret.ts";
9
+
10
+ describe("apple client secret", () => {
11
+ it("signs an ES256 JWT with the Apple-required claims + kid header", async () => {
12
+ const { privateKey } = await generateKeyPair("ES256", {
13
+ crv: "P-256",
14
+ extractable: true,
15
+ });
16
+ const pem = await exportPKCS8(privateKey);
17
+ const secret = await signAppleClientSecret({
18
+ privateKeyPem: pem,
19
+ teamId: "TEAM123456",
20
+ serviceId: "club.alepha.signin",
21
+ keyId: "KEY1234567",
22
+ });
23
+ const claims = decodeJwt(secret);
24
+ expect(claims.iss).toBe("TEAM123456");
25
+ expect(claims.sub).toBe("club.alepha.signin");
26
+ expect(claims.aud).toBe("https://appleid.apple.com");
27
+ expect(typeof claims.exp).toBe("number");
28
+
29
+ // Apple requires ES256 + the Key ID in the protected header.
30
+ const header = decodeProtectedHeader(secret);
31
+ expect(header.alg).toBe("ES256");
32
+ expect(header.kid).toBe("KEY1234567");
33
+ });
34
+ });