alepha 0.21.2 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (519) hide show
  1. package/README.md +0 -1
  2. package/dist/api/audits/index.browser.js.map +1 -1
  3. package/dist/api/audits/index.d.ts +393 -403
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/audits/index.js +25 -56
  6. package/dist/api/audits/index.js.map +1 -1
  7. package/dist/api/files/index.browser.js +31 -1
  8. package/dist/api/files/index.browser.js.map +1 -1
  9. package/dist/api/files/index.d.ts +313 -208
  10. package/dist/api/files/index.d.ts.map +1 -1
  11. package/dist/api/files/index.js +152 -42
  12. package/dist/api/files/index.js.map +1 -1
  13. package/dist/api/jobs/index.browser.js +2 -2
  14. package/dist/api/jobs/index.browser.js.map +1 -1
  15. package/dist/api/jobs/index.d.ts +282 -285
  16. package/dist/api/jobs/index.d.ts.map +1 -1
  17. package/dist/api/jobs/index.js +39 -33
  18. package/dist/api/jobs/index.js.map +1 -1
  19. package/dist/api/keys/index.d.ts +217 -222
  20. package/dist/api/keys/index.d.ts.map +1 -1
  21. package/dist/api/keys/index.js.map +1 -1
  22. package/dist/api/notifications/index.browser.js.map +1 -1
  23. package/dist/api/notifications/index.d.ts +188 -195
  24. package/dist/api/notifications/index.d.ts.map +1 -1
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/oauth/index.d.ts +71 -76
  27. package/dist/api/oauth/index.d.ts.map +1 -1
  28. package/dist/api/oauth/index.js.map +1 -1
  29. package/dist/api/organizations/index.browser.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +104 -109
  31. package/dist/api/organizations/index.d.ts.map +1 -1
  32. package/dist/api/organizations/index.js.map +1 -1
  33. package/dist/api/parameters/index.browser.js +43 -16
  34. package/dist/api/parameters/index.browser.js.map +1 -1
  35. package/dist/api/parameters/index.d.ts +488 -344
  36. package/dist/api/parameters/index.d.ts.map +1 -1
  37. package/dist/api/parameters/index.js +175 -35
  38. package/dist/api/parameters/index.js.map +1 -1
  39. package/dist/api/payments/index.d.ts +396 -402
  40. package/dist/api/payments/index.d.ts.map +1 -1
  41. package/dist/api/payments/index.js.map +1 -1
  42. package/dist/api/subscriptions/index.d.ts +644 -652
  43. package/dist/api/subscriptions/index.d.ts.map +1 -1
  44. package/dist/api/subscriptions/index.js +1 -1
  45. package/dist/api/subscriptions/index.js.map +1 -1
  46. package/dist/api/users/index.browser.js +7 -0
  47. package/dist/api/users/index.browser.js.map +1 -1
  48. package/dist/api/users/index.d.ts +1106 -1005
  49. package/dist/api/users/index.d.ts.map +1 -1
  50. package/dist/api/users/index.js +307 -64
  51. package/dist/api/users/index.js.map +1 -1
  52. package/dist/api/verifications/index.browser.js.map +1 -1
  53. package/dist/api/verifications/index.d.ts +137 -143
  54. package/dist/api/verifications/index.d.ts.map +1 -1
  55. package/dist/api/verifications/index.js.map +1 -1
  56. package/dist/background/index.d.ts +95 -0
  57. package/dist/background/index.d.ts.map +1 -0
  58. package/dist/background/index.js +121 -0
  59. package/dist/background/index.js.map +1 -0
  60. package/dist/background/index.workerd.js +110 -0
  61. package/dist/background/index.workerd.js.map +1 -0
  62. package/dist/batch/index.d.ts +5 -7
  63. package/dist/batch/index.d.ts.map +1 -1
  64. package/dist/batch/index.js.map +1 -1
  65. package/dist/bin/index.js.map +1 -1
  66. package/dist/bucket/index.d.ts +76 -54
  67. package/dist/bucket/index.d.ts.map +1 -1
  68. package/dist/bucket/index.js +58 -11
  69. package/dist/bucket/index.js.map +1 -1
  70. package/dist/bucket/index.workerd.js +200 -5
  71. package/dist/bucket/index.workerd.js.map +1 -1
  72. package/dist/cache/core/index.d.ts +7 -10
  73. package/dist/cache/core/index.d.ts.map +1 -1
  74. package/dist/cache/core/index.js.map +1 -1
  75. package/dist/cache/core/index.workerd.js.map +1 -1
  76. package/dist/cache/database/index.d.ts +22 -26
  77. package/dist/cache/database/index.d.ts.map +1 -1
  78. package/dist/cache/database/index.js.map +1 -1
  79. package/dist/cache/redis/index.d.ts +4 -7
  80. package/dist/cache/redis/index.d.ts.map +1 -1
  81. package/dist/cache/redis/index.js.map +1 -1
  82. package/dist/captcha/index.d.ts +3 -6
  83. package/dist/captcha/index.d.ts.map +1 -1
  84. package/dist/captcha/index.js.map +1 -1
  85. package/dist/cli/config/index.d.ts.map +1 -1
  86. package/dist/cli/config/index.js.map +1 -1
  87. package/dist/cli/core/index.d.ts +458 -249
  88. package/dist/cli/core/index.d.ts.map +1 -1
  89. package/dist/cli/core/index.js +372 -660
  90. package/dist/cli/core/index.js.map +1 -1
  91. package/dist/cli/devtools/index.d.ts +3 -5
  92. package/dist/cli/devtools/index.d.ts.map +1 -1
  93. package/dist/cli/devtools/index.js.map +1 -1
  94. package/dist/cli/i18n/index.d.ts +20 -17
  95. package/dist/cli/i18n/index.d.ts.map +1 -1
  96. package/dist/cli/i18n/index.js +45 -11
  97. package/dist/cli/i18n/index.js.map +1 -1
  98. package/dist/cli/platform/index.d.ts +126 -1342
  99. package/dist/cli/platform/index.d.ts.map +1 -1
  100. package/dist/cli/platform/index.js +136 -2374
  101. package/dist/cli/platform/index.js.map +1 -1
  102. package/dist/cli/platform-lib/index.d.ts +1472 -0
  103. package/dist/cli/platform-lib/index.d.ts.map +1 -0
  104. package/dist/cli/platform-lib/index.js +2660 -0
  105. package/dist/cli/platform-lib/index.js.map +1 -0
  106. package/dist/cli/vendor/index.d.ts +17 -21
  107. package/dist/cli/vendor/index.d.ts.map +1 -1
  108. package/dist/cli/vendor/index.js.map +1 -1
  109. package/dist/command/index.d.ts +20 -19
  110. package/dist/command/index.d.ts.map +1 -1
  111. package/dist/command/index.js +39 -10
  112. package/dist/command/index.js.map +1 -1
  113. package/dist/{containers → container}/core/index.d.ts +13 -15
  114. package/dist/container/core/index.d.ts.map +1 -0
  115. package/dist/{containers → container}/core/index.js +23 -14
  116. package/dist/container/core/index.js.map +1 -0
  117. package/dist/{containers → container}/core/index.workerd.js +37 -22
  118. package/dist/container/core/index.workerd.js.map +1 -0
  119. package/dist/core/index.browser.js +27 -1
  120. package/dist/core/index.browser.js.map +1 -1
  121. package/dist/core/index.d.ts +48 -24
  122. package/dist/core/index.d.ts.map +1 -1
  123. package/dist/core/index.js +27 -1
  124. package/dist/core/index.js.map +1 -1
  125. package/dist/core/index.native.js +27 -1
  126. package/dist/core/index.native.js.map +1 -1
  127. package/dist/core/index.workerd.js +27 -1
  128. package/dist/core/index.workerd.js.map +1 -1
  129. package/dist/crypto/index.browser.js.map +1 -1
  130. package/dist/crypto/index.d.ts +5 -8
  131. package/dist/crypto/index.d.ts.map +1 -1
  132. package/dist/crypto/index.js.map +1 -1
  133. package/dist/datetime/index.d.ts +3 -4
  134. package/dist/datetime/index.d.ts.map +1 -1
  135. package/dist/datetime/index.js.map +1 -1
  136. package/dist/email/brevo/index.d.ts +2 -4
  137. package/dist/email/brevo/index.d.ts.map +1 -1
  138. package/dist/email/brevo/index.js.map +1 -1
  139. package/dist/email/cloudflare/index.d.ts +20 -7
  140. package/dist/email/cloudflare/index.d.ts.map +1 -1
  141. package/dist/email/cloudflare/index.js +46 -9
  142. package/dist/email/cloudflare/index.js.map +1 -1
  143. package/dist/email/core/index.d.ts +6 -9
  144. package/dist/email/core/index.d.ts.map +1 -1
  145. package/dist/email/core/index.js.map +1 -1
  146. package/dist/email/core/index.workerd.js.map +1 -1
  147. package/dist/email/smtp/index.d.ts +10 -13
  148. package/dist/email/smtp/index.d.ts.map +1 -1
  149. package/dist/email/smtp/index.js +107 -32
  150. package/dist/email/smtp/index.js.map +1 -1
  151. package/dist/fake/index.d.ts +1 -2
  152. package/dist/fake/index.d.ts.map +1 -1
  153. package/dist/fake/index.js.map +1 -1
  154. package/dist/lock/core/index.d.ts +9 -14
  155. package/dist/lock/core/index.d.ts.map +1 -1
  156. package/dist/lock/core/index.js.map +1 -1
  157. package/dist/lock/redis/index.d.ts +2 -4
  158. package/dist/lock/redis/index.d.ts.map +1 -1
  159. package/dist/lock/redis/index.js.map +1 -1
  160. package/dist/logger/index.d.ts +105 -76
  161. package/dist/logger/index.d.ts.map +1 -1
  162. package/dist/logger/index.js +196 -174
  163. package/dist/logger/index.js.map +1 -1
  164. package/dist/mcp/index.d.ts +25 -20
  165. package/dist/mcp/index.d.ts.map +1 -1
  166. package/dist/mcp/index.js +23 -0
  167. package/dist/mcp/index.js.map +1 -1
  168. package/dist/orm/core/index.browser.js.map +1 -1
  169. package/dist/orm/core/index.bun.js +19 -1
  170. package/dist/orm/core/index.bun.js.map +1 -1
  171. package/dist/orm/core/index.d.ts +76 -62
  172. package/dist/orm/core/index.d.ts.map +1 -1
  173. package/dist/orm/core/index.js +20 -2
  174. package/dist/orm/core/index.js.map +1 -1
  175. package/dist/orm/postgres/index.bun.js.map +1 -1
  176. package/dist/orm/postgres/index.d.ts +28 -20
  177. package/dist/orm/postgres/index.d.ts.map +1 -1
  178. package/dist/orm/postgres/index.js.map +1 -1
  179. package/dist/queue/core/index.d.ts +12 -15
  180. package/dist/queue/core/index.d.ts.map +1 -1
  181. package/dist/queue/core/index.js.map +1 -1
  182. package/dist/queue/core/index.workerd.js.map +1 -1
  183. package/dist/queue/redis/index.d.ts +3 -5
  184. package/dist/queue/redis/index.d.ts.map +1 -1
  185. package/dist/queue/redis/index.js.map +1 -1
  186. package/dist/react/auth/index.browser.js +9 -2
  187. package/dist/react/auth/index.browser.js.map +1 -1
  188. package/dist/react/auth/index.d.ts +14 -9
  189. package/dist/react/auth/index.d.ts.map +1 -1
  190. package/dist/react/auth/index.js +9 -2
  191. package/dist/react/auth/index.js.map +1 -1
  192. package/dist/react/core/index.d.ts +7 -8
  193. package/dist/react/core/index.d.ts.map +1 -1
  194. package/dist/react/core/index.js +6 -3
  195. package/dist/react/core/index.js.map +1 -1
  196. package/dist/react/form/index.d.ts +2 -5
  197. package/dist/react/form/index.d.ts.map +1 -1
  198. package/dist/react/form/index.js +16 -15
  199. package/dist/react/form/index.js.map +1 -1
  200. package/dist/react/head/index.browser.js.map +1 -1
  201. package/dist/react/head/index.d.ts +2 -4
  202. package/dist/react/head/index.d.ts.map +1 -1
  203. package/dist/react/head/index.js.map +1 -1
  204. package/dist/react/i18n/index.d.ts +90 -11
  205. package/dist/react/i18n/index.d.ts.map +1 -1
  206. package/dist/react/i18n/index.js +147 -11
  207. package/dist/react/i18n/index.js.map +1 -1
  208. package/dist/react/intro/index.d.ts +1 -2
  209. package/dist/react/intro/index.d.ts.map +1 -1
  210. package/dist/react/intro/index.js +2 -2
  211. package/dist/react/intro/index.js.map +1 -1
  212. package/dist/react/router/index.browser.js +193 -24
  213. package/dist/react/router/index.browser.js.map +1 -1
  214. package/dist/react/router/index.d.ts +434 -222
  215. package/dist/react/router/index.d.ts.map +1 -1
  216. package/dist/react/router/index.js +249 -35
  217. package/dist/react/router/index.js.map +1 -1
  218. package/dist/react/sitemap/index.browser.js +35 -0
  219. package/dist/react/sitemap/index.browser.js.map +1 -0
  220. package/dist/react/sitemap/index.d.ts +92 -0
  221. package/dist/react/sitemap/index.d.ts.map +1 -0
  222. package/dist/react/sitemap/index.js +131 -0
  223. package/dist/react/sitemap/index.js.map +1 -0
  224. package/dist/react/testing/index.d.ts +1 -2
  225. package/dist/react/testing/index.d.ts.map +1 -1
  226. package/dist/react/testing/index.js +16 -17
  227. package/dist/react/testing/index.js.map +1 -1
  228. package/dist/react/ui/index.d.ts +20 -25
  229. package/dist/react/ui/index.d.ts.map +1 -1
  230. package/dist/react/ui/index.js.map +1 -1
  231. package/dist/redis/index.bun.js.map +1 -1
  232. package/dist/redis/index.d.ts +17 -19
  233. package/dist/redis/index.d.ts.map +1 -1
  234. package/dist/redis/index.js.map +1 -1
  235. package/dist/retry/index.d.ts +2 -4
  236. package/dist/retry/index.d.ts.map +1 -1
  237. package/dist/retry/index.js.map +1 -1
  238. package/dist/router/index.d.ts.map +1 -1
  239. package/dist/router/index.js.map +1 -1
  240. package/dist/scheduler/index.d.ts +10 -13
  241. package/dist/scheduler/index.d.ts.map +1 -1
  242. package/dist/scheduler/index.js.map +1 -1
  243. package/dist/scheduler/index.workerd.js.map +1 -1
  244. package/dist/security/index.browser.js.map +1 -1
  245. package/dist/security/index.d.ts +45 -48
  246. package/dist/security/index.d.ts.map +1 -1
  247. package/dist/security/index.js.map +1 -1
  248. package/dist/server/auth/index.browser.js.map +1 -1
  249. package/dist/server/auth/index.d.ts +272 -173
  250. package/dist/server/auth/index.d.ts.map +1 -1
  251. package/dist/server/auth/index.js +1608 -15
  252. package/dist/server/auth/index.js.map +1 -1
  253. package/dist/server/cookies/index.browser.js.map +1 -1
  254. package/dist/server/cookies/index.d.ts +20 -7
  255. package/dist/server/cookies/index.d.ts.map +1 -1
  256. package/dist/server/cookies/index.js +22 -3
  257. package/dist/server/cookies/index.js.map +1 -1
  258. package/dist/server/core/index.browser.js.map +1 -1
  259. package/dist/server/core/index.d.ts +106 -73
  260. package/dist/server/core/index.d.ts.map +1 -1
  261. package/dist/server/core/index.js +44 -0
  262. package/dist/server/core/index.js.map +1 -1
  263. package/dist/server/cors/index.d.ts +11 -14
  264. package/dist/server/cors/index.d.ts.map +1 -1
  265. package/dist/server/cors/index.js.map +1 -1
  266. package/dist/server/etag/index.d.ts +6 -9
  267. package/dist/server/etag/index.d.ts.map +1 -1
  268. package/dist/server/etag/index.js.map +1 -1
  269. package/dist/server/health/index.d.ts +18 -21
  270. package/dist/server/health/index.d.ts.map +1 -1
  271. package/dist/server/health/index.js.map +1 -1
  272. package/dist/server/links/index.browser.js +2 -0
  273. package/dist/server/links/index.browser.js.map +1 -1
  274. package/dist/server/links/index.d.ts +63 -67
  275. package/dist/server/links/index.d.ts.map +1 -1
  276. package/dist/server/links/index.js +2 -0
  277. package/dist/server/links/index.js.map +1 -1
  278. package/dist/server/metrics/index.d.ts +5 -7
  279. package/dist/server/metrics/index.d.ts.map +1 -1
  280. package/dist/server/metrics/index.js.map +1 -1
  281. package/dist/server/proxy/index.d.ts +3 -5
  282. package/dist/server/proxy/index.d.ts.map +1 -1
  283. package/dist/server/proxy/index.js.map +1 -1
  284. package/dist/server/rate-limit/index.d.ts +10 -13
  285. package/dist/server/rate-limit/index.d.ts.map +1 -1
  286. package/dist/server/rate-limit/index.js.map +1 -1
  287. package/dist/server/static/index.d.ts +3 -5
  288. package/dist/server/static/index.d.ts.map +1 -1
  289. package/dist/server/static/index.js.map +1 -1
  290. package/dist/server/swagger/index.d.ts +5 -8
  291. package/dist/server/swagger/index.d.ts.map +1 -1
  292. package/dist/server/swagger/index.js.map +1 -1
  293. package/dist/sms/index.d.ts +3 -5
  294. package/dist/sms/index.d.ts.map +1 -1
  295. package/dist/sms/index.js.map +1 -1
  296. package/dist/system/index.browser.js.map +1 -1
  297. package/dist/system/index.d.ts +2 -4
  298. package/dist/system/index.d.ts.map +1 -1
  299. package/dist/system/index.js.map +1 -1
  300. package/dist/system/index.workerd.js.map +1 -1
  301. package/dist/topic/core/index.d.ts +4 -6
  302. package/dist/topic/core/index.d.ts.map +1 -1
  303. package/dist/topic/core/index.js.map +1 -1
  304. package/dist/topic/redis/index.d.ts +5 -8
  305. package/dist/topic/redis/index.d.ts.map +1 -1
  306. package/dist/topic/redis/index.js.map +1 -1
  307. package/package.json +59 -23
  308. package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
  309. package/src/api/audits/controllers/AdminAuditController.ts +14 -0
  310. package/src/api/audits/services/AuditService.ts +21 -88
  311. package/src/api/files/__tests__/FileService.spec.ts +207 -2
  312. package/src/api/files/index.ts +3 -0
  313. package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
  314. package/src/api/files/schemas/fileResourceSchema.ts +10 -1
  315. package/src/api/files/services/FileService.ts +170 -72
  316. package/src/api/jobs/__tests__/$job.spec.ts +24 -1
  317. package/src/api/jobs/index.ts +4 -3
  318. package/src/api/jobs/primitives/$job.ts +7 -3
  319. package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
  320. package/src/api/jobs/providers/JobProvider.ts +53 -24
  321. package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
  322. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
  323. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
  324. package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
  325. package/src/api/parameters/audits/ParameterAudits.ts +17 -0
  326. package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
  327. package/src/api/parameters/index.ts +3 -0
  328. package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
  329. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
  330. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
  331. package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
  332. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
  333. package/src/api/parameters/services/ParameterProvider.ts +69 -6
  334. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
  335. package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
  336. package/src/api/users/audits/SessionAudits.ts +33 -0
  337. package/src/api/users/audits/UserAudits.ts +19 -43
  338. package/src/api/users/controllers/AdminUserController.ts +66 -1
  339. package/src/api/users/controllers/RealmController.ts +1 -0
  340. package/src/api/users/entities/sessions.ts +6 -0
  341. package/src/api/users/entities/users.ts +2 -0
  342. package/src/api/users/index.ts +9 -1
  343. package/src/api/users/primitives/$realm.ts +29 -0
  344. package/src/api/users/providers/RealmProvider.ts +15 -0
  345. package/src/api/users/schemas/realmConfigSchema.ts +14 -0
  346. package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
  347. package/src/api/users/schemas/updateUserSchema.ts +1 -8
  348. package/src/api/users/schemas/userQuerySchema.ts +7 -0
  349. package/src/api/users/services/CredentialService.ts +15 -6
  350. package/src/api/users/services/IdentityService.ts +2 -1
  351. package/src/api/users/services/RegistrationService.ts +2 -1
  352. package/src/api/users/services/SessionCrudService.ts +19 -2
  353. package/src/api/users/services/SessionService.ts +39 -19
  354. package/src/api/users/services/UserService.ts +106 -8
  355. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
  356. package/src/background/index.ts +37 -0
  357. package/src/background/index.workerd.ts +28 -0
  358. package/src/background/providers/BackgroundTaskProvider.ts +70 -0
  359. package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
  360. package/src/bucket/__tests__/$bucket.spec.ts +18 -0
  361. package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
  362. package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
  363. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
  364. package/src/bucket/__tests__/shared.ts +30 -0
  365. package/src/bucket/index.ts +5 -5
  366. package/src/bucket/index.workerd.ts +11 -4
  367. package/src/bucket/primitives/$bucket.ts +27 -0
  368. package/src/bucket/providers/FileStorageProvider.ts +13 -0
  369. package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
  370. package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
  371. package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
  372. package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
  373. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
  374. package/src/cli/core/__tests__/init.spec.ts +0 -219
  375. package/src/cli/core/atoms/buildOptions.ts +0 -12
  376. package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
  377. package/src/cli/core/commands/build.ts +105 -37
  378. package/src/cli/core/commands/init.ts +0 -12
  379. package/src/cli/core/commands/pack.ts +133 -0
  380. package/src/cli/core/index.ts +3 -3
  381. package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
  382. package/src/cli/core/services/PackageManagerUtils.ts +0 -16
  383. package/src/cli/core/services/ProjectScaffolder.ts +29 -291
  384. package/src/cli/core/tasks/BuildCloudflareTask.ts +382 -56
  385. package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
  386. package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
  387. package/src/cli/core/tasks/BuildTask.ts +34 -0
  388. package/src/cli/core/templates/apiIndexTs.ts +1 -22
  389. package/src/cli/core/templates/mainCss.ts +0 -1
  390. package/src/cli/core/templates/webAppRouterTs.ts +0 -99
  391. package/src/cli/core/templates/webIndexTs.ts +1 -22
  392. package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +48 -0
  393. package/src/cli/i18n/services/I18nCheckService.ts +65 -11
  394. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
  395. package/src/cli/platform/commands/SecretsCommand.ts +8 -6
  396. package/src/cli/platform/commands/platform.ts +192 -46
  397. package/src/cli/platform/index.ts +12 -52
  398. package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
  399. package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
  400. package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
  401. package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +519 -190
  402. package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
  403. package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
  404. package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
  405. package/src/cli/platform-lib/index.ts +67 -0
  406. package/src/cli/platform-lib/services/NamingService.ts +136 -0
  407. package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
  408. package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
  409. package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
  410. package/src/command/__tests__/Runner.spec.ts +20 -0
  411. package/src/command/helpers/EnvUtils.ts +19 -3
  412. package/src/command/helpers/Runner.ts +12 -2
  413. package/src/command/providers/CliProvider.ts +34 -1
  414. package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
  415. package/src/{containers → container}/core/index.ts +4 -4
  416. package/src/{containers → container}/core/index.workerd.ts +19 -3
  417. package/src/{containers → container}/core/primitives/$container.ts +1 -1
  418. package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
  419. package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
  420. package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
  421. package/src/core/Alepha.ts +49 -1
  422. package/src/core/__tests__/$env.spec.ts +42 -0
  423. package/src/core/__tests__/dump.spec.ts +47 -0
  424. package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
  425. package/src/email/cloudflare/index.ts +14 -5
  426. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
  427. package/src/logger/__tests__/Logger.spec.ts +55 -0
  428. package/src/logger/index.ts +13 -0
  429. package/src/logger/services/Logger.ts +31 -1
  430. package/src/mcp/__tests__/McpServerProvider.spec.ts +71 -0
  431. package/src/mcp/providers/McpServerProvider.ts +55 -0
  432. package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
  433. package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
  434. package/src/orm/core/interfaces/PgQuery.ts +4 -1
  435. package/src/orm/core/services/Repository.ts +27 -11
  436. package/src/react/auth/hooks/useAuth.ts +10 -5
  437. package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
  438. package/src/react/core/hooks/useAction.ts +14 -3
  439. package/src/react/core/hooks/useQuery.ts +24 -4
  440. package/src/react/form/__tests__/FormModel-submit-loading.spec.ts +71 -0
  441. package/src/react/form/__tests__/form-submitting-reactive.browser.spec.tsx +96 -0
  442. package/src/react/form/services/FormModel.ts +57 -39
  443. package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
  444. package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
  445. package/src/react/i18n/components/Translate.tsx +47 -0
  446. package/src/react/i18n/index.ts +2 -0
  447. package/src/react/i18n/providers/I18nProvider.ts +171 -12
  448. package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
  449. package/src/react/router/__tests__/$page.spec.tsx +3 -2
  450. package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
  451. package/src/react/router/__tests__/page-can.spec.ts +18 -13
  452. package/src/react/router/hooks/useQueryParams.ts +114 -14
  453. package/src/react/router/index.browser.ts +4 -0
  454. package/src/react/router/index.shared.ts +1 -0
  455. package/src/react/router/index.ts +9 -0
  456. package/src/react/router/primitives/$page.ts +85 -4
  457. package/src/react/router/providers/ReactBrowserRouterProvider.ts +18 -8
  458. package/src/react/router/providers/ReactPageProvider.ts +12 -1
  459. package/src/react/router/providers/ReactServerProvider.ts +96 -14
  460. package/src/react/router/providers/RootComponentsProvider.ts +13 -0
  461. package/src/react/router/providers/RouterLocaleProvider.ts +125 -0
  462. package/src/react/router/providers/__tests__/RootComponentsProvider.spec.ts +15 -0
  463. package/src/react/router/providers/__tests__/rootComponents.ssr.browser.spec.tsx +67 -0
  464. package/src/react/sitemap/__tests__/$sitemap.spec.ts +131 -0
  465. package/src/react/sitemap/index.browser.ts +21 -0
  466. package/src/react/sitemap/index.ts +25 -0
  467. package/src/react/sitemap/primitives/$sitemap.browser.ts +26 -0
  468. package/src/react/sitemap/primitives/$sitemap.ts +196 -0
  469. package/src/react/ui/services/SchemaControl.ts +3 -4
  470. package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
  471. package/src/server/auth/__tests__/authFederationClient.spec.ts +40 -0
  472. package/src/server/auth/__tests__/federationAssertion.spec.ts +146 -0
  473. package/src/server/auth/__tests__/federationRedirectReplay.spec.ts +44 -0
  474. package/src/server/auth/helpers/appleClientSecret.ts +24 -0
  475. package/src/server/auth/helpers/federationAssertion.ts +74 -0
  476. package/src/server/auth/helpers/jtiReplayGuard.ts +41 -0
  477. package/src/server/auth/helpers/safeRedirectPath.ts +19 -0
  478. package/src/server/auth/index.ts +4 -0
  479. package/src/server/auth/primitives/$authFederationBroker.ts +273 -0
  480. package/src/server/auth/primitives/$authFederationClient.ts +89 -0
  481. package/src/server/auth/providers/ServerAuthProvider.ts +18 -4
  482. package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +70 -0
  483. package/src/server/cookies/providers/ServerCookiesProvider.ts +23 -3
  484. package/src/server/core/interfaces/ServerRequest.ts +8 -0
  485. package/src/server/core/primitives/$route.ts +27 -0
  486. package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
  487. package/src/server/links/providers/LinkProvider.ts +10 -0
  488. package/dist/containers/core/index.d.ts.map +0 -1
  489. package/dist/containers/core/index.js.map +0 -1
  490. package/dist/containers/core/index.workerd.js.map +0 -1
  491. package/src/cli/core/tasks/BuildSitemapTask.ts +0 -130
  492. package/src/cli/core/templates/componentsJsonTs.ts +0 -39
  493. package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
  494. package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
  495. package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
  496. package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
  497. package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
  498. package/src/cli/platform/services/NamingService.ts +0 -54
  499. /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
  500. /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
  501. /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
  502. /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
  503. /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
  504. /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
  505. /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
  506. /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
  507. /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
  508. /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
  509. /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
  510. /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
  511. /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
  512. /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
  513. /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
  514. /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
  515. /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
  516. /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
  517. /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
  518. /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
  519. /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/index.browser.ts"],"sourcesContent":["import type { Head, HeadMeta } from \"../interfaces/Head.ts\";\n\n/**\n * Expands Head configuration into SEO meta tags.\n *\n * Generates:\n * - `<meta name=\"description\">` from head.description\n * - `<meta property=\"og:*\">` OpenGraph tags\n * - `<meta name=\"twitter:*\">` Twitter Card tags\n *\n * @example\n * ```ts\n * const helper = new SeoExpander();\n * const { meta, link } = helper.expand({\n * title: \"My App\",\n * description: \"Build amazing apps\",\n * image: \"https://example.com/og.png\",\n * url: \"https://example.com/\",\n * });\n * ```\n */\nexport class SeoExpander {\n public expand(head: Head): {\n meta: HeadMeta[];\n link: Array<{ rel: string; href: string }>;\n } {\n const meta: HeadMeta[] = [];\n const link: Array<{ rel: string; href: string }> = [];\n\n // Only expand SEO if there's meaningful content beyond just title\n const hasSeoContent =\n head.description ||\n head.image ||\n head.url ||\n head.siteName ||\n head.locale ||\n head.type ||\n head.og ||\n head.twitter;\n\n if (!hasSeoContent) {\n return { meta, link };\n }\n\n // Base description\n if (head.description) {\n meta.push({ name: \"description\", content: head.description });\n }\n\n // Canonical URL\n if (head.url) {\n link.push({ rel: \"canonical\", href: head.url });\n }\n\n // OpenGraph tags\n this.expandOpenGraph(head, meta);\n\n // Twitter Card tags\n this.expandTwitter(head, meta);\n\n return { meta, link };\n }\n\n protected expandOpenGraph(head: Head, meta: HeadMeta[]): void {\n const ogTitle = head.og?.title ?? head.title;\n const ogDescription = head.og?.description ?? head.description;\n const ogImage = head.og?.image ?? head.image;\n\n if (head.type || ogTitle) {\n meta.push({ property: \"og:type\", content: head.type ?? \"website\" });\n }\n if (head.url) {\n meta.push({ property: \"og:url\", content: head.url });\n }\n if (ogTitle) {\n meta.push({ property: \"og:title\", content: ogTitle });\n }\n if (ogDescription) {\n meta.push({ property: \"og:description\", content: ogDescription });\n }\n if (ogImage) {\n meta.push({ property: \"og:image\", content: ogImage });\n if (head.imageWidth) {\n meta.push({\n property: \"og:image:width\",\n content: String(head.imageWidth),\n });\n }\n if (head.imageHeight) {\n meta.push({\n property: \"og:image:height\",\n content: String(head.imageHeight),\n });\n }\n if (head.imageAlt) {\n meta.push({ property: \"og:image:alt\", content: head.imageAlt });\n }\n }\n if (head.siteName) {\n meta.push({ property: \"og:site_name\", content: head.siteName });\n }\n if (head.locale) {\n meta.push({ property: \"og:locale\", content: head.locale });\n }\n }\n\n protected expandTwitter(head: Head, meta: HeadMeta[]): void {\n const twitterTitle = head.twitter?.title ?? head.title;\n const twitterDescription = head.twitter?.description ?? head.description;\n const twitterImage = head.twitter?.image ?? head.image;\n\n if (head.twitter?.card || twitterTitle || twitterImage) {\n meta.push({\n name: \"twitter:card\",\n content:\n head.twitter?.card ??\n (twitterImage ? \"summary_large_image\" : \"summary\"),\n });\n }\n if (head.url) {\n meta.push({ name: \"twitter:url\", content: head.url });\n }\n if (twitterTitle) {\n meta.push({ name: \"twitter:title\", content: twitterTitle });\n }\n if (twitterDescription) {\n meta.push({ name: \"twitter:description\", content: twitterDescription });\n }\n if (twitterImage) {\n meta.push({ name: \"twitter:image\", content: twitterImage });\n if (head.imageAlt) {\n meta.push({ name: \"twitter:image:alt\", content: head.imageAlt });\n }\n }\n if (head.twitter?.site) {\n meta.push({ name: \"twitter:site\", content: head.twitter.site });\n }\n if (head.twitter?.creator) {\n meta.push({ name: \"twitter:creator\", content: head.twitter.creator });\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { SeoExpander } from \"../helpers/SeoExpander.ts\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\n/**\n * Provides methods to fill and merge head information into the application state.\n *\n * Used both on server and client side to manage document head.\n *\n * @see {@link SeoExpander}\n * @see {@link ServerHeadProvider}\n * @see {@link BrowserHeadProvider}\n */\nexport class HeadProvider {\n protected readonly log = $logger();\n protected readonly seoExpander = $inject(SeoExpander);\n\n public global?: Array<Head | (() => Head)> = [];\n\n /**\n * Track if we've warned about page-level htmlAttributes to avoid spam.\n */\n protected warnedAboutHtmlAttributes = false;\n\n /**\n * Resolve global head configuration (from $head primitives only).\n *\n * This is used to get htmlAttributes early, before page loaders run.\n * Only htmlAttributes from global $head are allowed; page-level htmlAttributes\n * are ignored for early streaming optimization.\n *\n * @returns Merged global head with htmlAttributes\n */\n public resolveGlobalHead(): Head {\n const head: Head = {\n htmlAttributes: { lang: \"en\" },\n };\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n if (resolved.htmlAttributes) {\n head.htmlAttributes = {\n ...head.htmlAttributes,\n ...resolved.htmlAttributes,\n };\n }\n }\n\n return head;\n }\n\n /**\n * Fully resolve all global $head entries (functions re-evaluated, objects kept as-is).\n *\n * Unlike resolveGlobalHead() which only extracts htmlAttributes for streaming,\n * this resolves all head properties (meta, link, script, htmlAttributes, etc.).\n *\n * Used by BrowserHeadProvider.refreshGlobalHead() to re-apply global head to the DOM.\n */\n public resolveGlobal(): Head {\n let head: Head = {};\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n const { meta, link } = this.seoExpander.expand(resolved);\n head = {\n ...head,\n ...resolved,\n meta: [...(head.meta ?? []), ...meta, ...(resolved.meta ?? [])],\n link: [...(head.link ?? []), ...link, ...(resolved.link ?? [])],\n script: [...(head.script ?? []), ...(resolved.script ?? [])],\n };\n }\n\n return head;\n }\n\n public fillHead(state: HeadState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head = typeof h === \"function\" ? h() : h;\n this.mergeHead(state, head);\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n\n // Defaults if none were set by global $head or page head\n state.head.title ??= \"App\";\n state.head.htmlAttributes = {\n lang: \"en\",\n ...state.head.htmlAttributes,\n };\n }\n\n protected mergeHead(state: HeadState, head: Head): void {\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...meta, ...(head.meta ?? [])],\n link: [...(state.head.link ?? []), ...link, ...(head.link ?? [])],\n script: [...(state.head.script ?? []), ...(head.script ?? [])],\n };\n }\n\n protected fillHeadByPage(\n page: HeadRoute,\n state: HeadState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head.meta = [...(state.head.meta ?? []), ...meta];\n state.head.link = [...(state.head.link ?? []), ...link];\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n // htmlAttributes from pages are ignored for early streaming optimization.\n // Only global $head can set htmlAttributes.\n if (head.htmlAttributes && !this.warnedAboutHtmlAttributes) {\n this.warnedAboutHtmlAttributes = true;\n this.log.warn(\n \"Page-level htmlAttributes are ignored. Use global $head() for htmlAttributes instead, \" +\n \"as they are sent before page loaders run for early streaming optimization.\",\n );\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n\n if (head.link) {\n state.head.link = [...(state.head.link ?? []), ...(head.link ?? [])];\n }\n\n if (head.script) {\n state.head.script = [\n ...(state.head.script ?? []),\n ...(head.script ?? []),\n ];\n }\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimal route interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadRoute {\n head?: Head | ((props: Record<string, any>, previous?: Head) => Head);\n}\n\n/**\n * Minimal state interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadState {\n head: Head;\n layers: Array<{\n route?: HeadRoute;\n props?: Record<string, any>;\n error?: Error;\n }>;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [...(this.provider.global ?? []), this.options];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $inject, Alepha } from \"alepha\";\nimport type { Head, HeadMeta } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Browser-side head provider that manages document head elements.\n *\n * Used by ReactBrowserProvider and ReactBrowserRouterProvider to update\n * document title, meta tags, and other head elements during client-side\n * navigation.\n */\nexport class BrowserHeadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n /**\n * Fill head state from route configurations and render to document.\n * Combines fillHead from HeadProvider with renderHead to the DOM.\n *\n * Only runs in browser environment - no-op on server.\n */\n public fillAndRenderHead(state: { head: Head; layers: Array<any> }): void {\n // Skip on server-side\n if (!this.alepha.isBrowser()) {\n return;\n }\n\n this.headProvider.fillHead(state as any);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n }\n\n /**\n * Re-evaluate all global $head entries and apply the result to the DOM.\n *\n * Call this when something that affects global $head output changes at runtime\n * (e.g., theme switch). Page-level head (title, meta from routes) is not touched.\n */\n public refreshGlobalHead(): void {\n const head = this.headProvider.resolveGlobal();\n this.renderHead(this.document, head);\n }\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: HeadMeta[] = [];\n // Get meta tags with name attribute\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n // Get meta tags with property attribute (OpenGraph)\n for (const meta of document.head.querySelectorAll(\"meta[property]\")) {\n const property = meta.getAttribute(\"property\");\n const content = meta.getAttribute(\"content\");\n if (property && content) {\n metas.push({ property, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n this.renderMetaTag(document, it);\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n if (it.type) {\n link.setAttribute(\"type\", it.type);\n }\n if (it.as) {\n link.setAttribute(\"as\", it.as);\n }\n if (it.crossorigin != null) {\n link.setAttribute(\"crossorigin\", \"\");\n }\n if (it.media) {\n link.setAttribute(\"media\", it.media);\n }\n if (it.sizes) {\n link.setAttribute(\"sizes\", it.sizes);\n }\n if (it.hreflang) {\n link.setAttribute(\"hreflang\", it.hreflang);\n }\n document.head.appendChild(link);\n }\n }\n }\n\n if (head.script) {\n for (const it of head.script) {\n this.renderScriptTag(document, it);\n }\n }\n }\n\n protected renderScriptTag(\n document: Document,\n script:\n | string\n | (Record<string, string | boolean | undefined> & { content?: string }),\n ): void {\n // Plain string → inline script. Dedupe by exact content match against\n // any existing inline script (handles SSR-emitted globals that would\n // otherwise be re-appended on hydration).\n if (typeof script === \"string\") {\n if (this.findInlineScriptByContent(document, script)) return;\n const el = document.createElement(\"script\");\n el.textContent = script;\n document.head.appendChild(el);\n return;\n }\n\n const { content, ...attrs } = script;\n\n // src-based scripts: dedupe by src attribute (existing behaviour).\n if (attrs.src) {\n if (document.querySelector(`script[src=\"${attrs.src}\"]`)) return;\n } else if (typeof attrs.id === \"string\") {\n // id-based dedupe — single source of truth per id.\n if (document.querySelector(`script#${CSS.escape(attrs.id)}`)) return;\n } else if (content) {\n // Inline scripts with `content` and no src/id: fall back to content match.\n if (this.findInlineScriptByContent(document, content)) return;\n }\n\n const el = document.createElement(\"script\");\n for (const [key, value] of Object.entries(attrs)) {\n if (value === true) {\n el.setAttribute(key, \"\");\n } else if (value !== undefined && value !== false) {\n el.setAttribute(key, String(value));\n }\n }\n if (content) {\n el.textContent = content;\n }\n document.head.appendChild(el);\n }\n\n /**\n * Find an existing inline `<script>` tag (no `src`) with matching textContent.\n * Used to make `renderScriptTag` idempotent across hydration + navigation,\n * so SSR-emitted global scripts aren't re-appended client-side.\n */\n protected findInlineScriptByContent(\n document: Document,\n content: string,\n ): Element | null {\n for (const existing of document.head.querySelectorAll(\n \"script:not([src])\",\n )) {\n if (existing.textContent === content) return existing;\n }\n return null;\n }\n\n protected renderMetaTag(document: Document, meta: HeadMeta): void {\n const { content } = meta;\n\n // Handle OpenGraph tags (property attribute)\n if (meta.property) {\n const existing = document.querySelector(\n `meta[property=\"${meta.property}\"]`,\n );\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"property\", meta.property);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n return;\n }\n\n // Handle standard meta tags (name attribute)\n if (meta.name) {\n const existing = document.querySelector(`meta[name=\"${meta.name}\"]`);\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", meta.name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n}\n","import { Alepha } from \"alepha\";\nimport { useInject } from \"alepha/react\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const headProvider = alepha.inject(BrowserHeadProvider);\n const resolved =\n typeof head === \"function\"\n ? head(headProvider.getHead(window.document))\n : head || {};\n headProvider.renderHead(window.document, resolved);\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import { $module } from \"alepha\";\nimport { AlephaReact } from \"alepha/react\";\nimport { $head } from \"./primitives/$head.ts\";\nimport { BrowserHeadProvider } from \"./providers/BrowserHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./helpers/SeoExpander.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./primitives/$head.ts\";\nexport * from \"./providers/BrowserHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Alepha React Head Module\n *\n * @see {@link BrowserHeadProvider}\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [AlephaReact, BrowserHeadProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/index.browser.ts"],"sourcesContent":["import type { Head, HeadMeta } from \"../interfaces/Head.ts\";\n\n/**\n * Expands Head configuration into SEO meta tags.\n *\n * Generates:\n * - `<meta name=\"description\">` from head.description\n * - `<meta property=\"og:*\">` OpenGraph tags\n * - `<meta name=\"twitter:*\">` Twitter Card tags\n *\n * @example\n * ```ts\n * const helper = new SeoExpander();\n * const { meta, link } = helper.expand({\n * title: \"My App\",\n * description: \"Build amazing apps\",\n * image: \"https://example.com/og.png\",\n * url: \"https://example.com/\",\n * });\n * ```\n */\nexport class SeoExpander {\n public expand(head: Head): {\n meta: HeadMeta[];\n link: Array<{ rel: string; href: string }>;\n } {\n const meta: HeadMeta[] = [];\n const link: Array<{ rel: string; href: string }> = [];\n\n // Only expand SEO if there's meaningful content beyond just title\n const hasSeoContent =\n head.description ||\n head.image ||\n head.url ||\n head.siteName ||\n head.locale ||\n head.type ||\n head.og ||\n head.twitter;\n\n if (!hasSeoContent) {\n return { meta, link };\n }\n\n // Base description\n if (head.description) {\n meta.push({ name: \"description\", content: head.description });\n }\n\n // Canonical URL\n if (head.url) {\n link.push({ rel: \"canonical\", href: head.url });\n }\n\n // OpenGraph tags\n this.expandOpenGraph(head, meta);\n\n // Twitter Card tags\n this.expandTwitter(head, meta);\n\n return { meta, link };\n }\n\n protected expandOpenGraph(head: Head, meta: HeadMeta[]): void {\n const ogTitle = head.og?.title ?? head.title;\n const ogDescription = head.og?.description ?? head.description;\n const ogImage = head.og?.image ?? head.image;\n\n if (head.type || ogTitle) {\n meta.push({ property: \"og:type\", content: head.type ?? \"website\" });\n }\n if (head.url) {\n meta.push({ property: \"og:url\", content: head.url });\n }\n if (ogTitle) {\n meta.push({ property: \"og:title\", content: ogTitle });\n }\n if (ogDescription) {\n meta.push({ property: \"og:description\", content: ogDescription });\n }\n if (ogImage) {\n meta.push({ property: \"og:image\", content: ogImage });\n if (head.imageWidth) {\n meta.push({\n property: \"og:image:width\",\n content: String(head.imageWidth),\n });\n }\n if (head.imageHeight) {\n meta.push({\n property: \"og:image:height\",\n content: String(head.imageHeight),\n });\n }\n if (head.imageAlt) {\n meta.push({ property: \"og:image:alt\", content: head.imageAlt });\n }\n }\n if (head.siteName) {\n meta.push({ property: \"og:site_name\", content: head.siteName });\n }\n if (head.locale) {\n meta.push({ property: \"og:locale\", content: head.locale });\n }\n }\n\n protected expandTwitter(head: Head, meta: HeadMeta[]): void {\n const twitterTitle = head.twitter?.title ?? head.title;\n const twitterDescription = head.twitter?.description ?? head.description;\n const twitterImage = head.twitter?.image ?? head.image;\n\n if (head.twitter?.card || twitterTitle || twitterImage) {\n meta.push({\n name: \"twitter:card\",\n content:\n head.twitter?.card ??\n (twitterImage ? \"summary_large_image\" : \"summary\"),\n });\n }\n if (head.url) {\n meta.push({ name: \"twitter:url\", content: head.url });\n }\n if (twitterTitle) {\n meta.push({ name: \"twitter:title\", content: twitterTitle });\n }\n if (twitterDescription) {\n meta.push({ name: \"twitter:description\", content: twitterDescription });\n }\n if (twitterImage) {\n meta.push({ name: \"twitter:image\", content: twitterImage });\n if (head.imageAlt) {\n meta.push({ name: \"twitter:image:alt\", content: head.imageAlt });\n }\n }\n if (head.twitter?.site) {\n meta.push({ name: \"twitter:site\", content: head.twitter.site });\n }\n if (head.twitter?.creator) {\n meta.push({ name: \"twitter:creator\", content: head.twitter.creator });\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { SeoExpander } from \"../helpers/SeoExpander.ts\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\n/**\n * Provides methods to fill and merge head information into the application state.\n *\n * Used both on server and client side to manage document head.\n *\n * @see {@link SeoExpander}\n * @see {@link ServerHeadProvider}\n * @see {@link BrowserHeadProvider}\n */\nexport class HeadProvider {\n protected readonly log = $logger();\n protected readonly seoExpander = $inject(SeoExpander);\n\n public global?: Array<Head | (() => Head)> = [];\n\n /**\n * Track if we've warned about page-level htmlAttributes to avoid spam.\n */\n protected warnedAboutHtmlAttributes = false;\n\n /**\n * Resolve global head configuration (from $head primitives only).\n *\n * This is used to get htmlAttributes early, before page loaders run.\n * Only htmlAttributes from global $head are allowed; page-level htmlAttributes\n * are ignored for early streaming optimization.\n *\n * @returns Merged global head with htmlAttributes\n */\n public resolveGlobalHead(): Head {\n const head: Head = {\n htmlAttributes: { lang: \"en\" },\n };\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n if (resolved.htmlAttributes) {\n head.htmlAttributes = {\n ...head.htmlAttributes,\n ...resolved.htmlAttributes,\n };\n }\n }\n\n return head;\n }\n\n /**\n * Fully resolve all global $head entries (functions re-evaluated, objects kept as-is).\n *\n * Unlike resolveGlobalHead() which only extracts htmlAttributes for streaming,\n * this resolves all head properties (meta, link, script, htmlAttributes, etc.).\n *\n * Used by BrowserHeadProvider.refreshGlobalHead() to re-apply global head to the DOM.\n */\n public resolveGlobal(): Head {\n let head: Head = {};\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n const { meta, link } = this.seoExpander.expand(resolved);\n head = {\n ...head,\n ...resolved,\n meta: [...(head.meta ?? []), ...meta, ...(resolved.meta ?? [])],\n link: [...(head.link ?? []), ...link, ...(resolved.link ?? [])],\n script: [...(head.script ?? []), ...(resolved.script ?? [])],\n };\n }\n\n return head;\n }\n\n public fillHead(state: HeadState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head = typeof h === \"function\" ? h() : h;\n this.mergeHead(state, head);\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n\n // Defaults if none were set by global $head or page head\n state.head.title ??= \"App\";\n state.head.htmlAttributes = {\n lang: \"en\",\n ...state.head.htmlAttributes,\n };\n }\n\n protected mergeHead(state: HeadState, head: Head): void {\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...meta, ...(head.meta ?? [])],\n link: [...(state.head.link ?? []), ...link, ...(head.link ?? [])],\n script: [...(state.head.script ?? []), ...(head.script ?? [])],\n };\n }\n\n protected fillHeadByPage(\n page: HeadRoute,\n state: HeadState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head.meta = [...(state.head.meta ?? []), ...meta];\n state.head.link = [...(state.head.link ?? []), ...link];\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n // htmlAttributes from pages are ignored for early streaming optimization.\n // Only global $head can set htmlAttributes.\n if (head.htmlAttributes && !this.warnedAboutHtmlAttributes) {\n this.warnedAboutHtmlAttributes = true;\n this.log.warn(\n \"Page-level htmlAttributes are ignored. Use global $head() for htmlAttributes instead, \" +\n \"as they are sent before page loaders run for early streaming optimization.\",\n );\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n\n if (head.link) {\n state.head.link = [...(state.head.link ?? []), ...(head.link ?? [])];\n }\n\n if (head.script) {\n state.head.script = [\n ...(state.head.script ?? []),\n ...(head.script ?? []),\n ];\n }\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimal route interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadRoute {\n head?: Head | ((props: Record<string, any>, previous?: Head) => Head);\n}\n\n/**\n * Minimal state interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadState {\n head: Head;\n layers: Array<{\n route?: HeadRoute;\n props?: Record<string, any>;\n error?: Error;\n }>;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [...(this.provider.global ?? []), this.options];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $inject, Alepha } from \"alepha\";\nimport type { Head, HeadMeta } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Browser-side head provider that manages document head elements.\n *\n * Used by ReactBrowserProvider and ReactBrowserRouterProvider to update\n * document title, meta tags, and other head elements during client-side\n * navigation.\n */\nexport class BrowserHeadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n /**\n * Fill head state from route configurations and render to document.\n * Combines fillHead from HeadProvider with renderHead to the DOM.\n *\n * Only runs in browser environment - no-op on server.\n */\n public fillAndRenderHead(state: { head: Head; layers: Array<any> }): void {\n // Skip on server-side\n if (!this.alepha.isBrowser()) {\n return;\n }\n\n this.headProvider.fillHead(state as any);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n }\n\n /**\n * Re-evaluate all global $head entries and apply the result to the DOM.\n *\n * Call this when something that affects global $head output changes at runtime\n * (e.g., theme switch). Page-level head (title, meta from routes) is not touched.\n */\n public refreshGlobalHead(): void {\n const head = this.headProvider.resolveGlobal();\n this.renderHead(this.document, head);\n }\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: HeadMeta[] = [];\n // Get meta tags with name attribute\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n // Get meta tags with property attribute (OpenGraph)\n for (const meta of document.head.querySelectorAll(\"meta[property]\")) {\n const property = meta.getAttribute(\"property\");\n const content = meta.getAttribute(\"content\");\n if (property && content) {\n metas.push({ property, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n this.renderMetaTag(document, it);\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n if (it.type) {\n link.setAttribute(\"type\", it.type);\n }\n if (it.as) {\n link.setAttribute(\"as\", it.as);\n }\n if (it.crossorigin != null) {\n link.setAttribute(\"crossorigin\", \"\");\n }\n if (it.media) {\n link.setAttribute(\"media\", it.media);\n }\n if (it.sizes) {\n link.setAttribute(\"sizes\", it.sizes);\n }\n if (it.hreflang) {\n link.setAttribute(\"hreflang\", it.hreflang);\n }\n document.head.appendChild(link);\n }\n }\n }\n\n if (head.script) {\n for (const it of head.script) {\n this.renderScriptTag(document, it);\n }\n }\n }\n\n protected renderScriptTag(\n document: Document,\n script:\n | string\n | (Record<string, string | boolean | undefined> & { content?: string }),\n ): void {\n // Plain string → inline script. Dedupe by exact content match against\n // any existing inline script (handles SSR-emitted globals that would\n // otherwise be re-appended on hydration).\n if (typeof script === \"string\") {\n if (this.findInlineScriptByContent(document, script)) return;\n const el = document.createElement(\"script\");\n el.textContent = script;\n document.head.appendChild(el);\n return;\n }\n\n const { content, ...attrs } = script;\n\n // src-based scripts: dedupe by src attribute (existing behaviour).\n if (attrs.src) {\n if (document.querySelector(`script[src=\"${attrs.src}\"]`)) return;\n } else if (typeof attrs.id === \"string\") {\n // id-based dedupe — single source of truth per id.\n if (document.querySelector(`script#${CSS.escape(attrs.id)}`)) return;\n } else if (content) {\n // Inline scripts with `content` and no src/id: fall back to content match.\n if (this.findInlineScriptByContent(document, content)) return;\n }\n\n const el = document.createElement(\"script\");\n for (const [key, value] of Object.entries(attrs)) {\n if (value === true) {\n el.setAttribute(key, \"\");\n } else if (value !== undefined && value !== false) {\n el.setAttribute(key, String(value));\n }\n }\n if (content) {\n el.textContent = content;\n }\n document.head.appendChild(el);\n }\n\n /**\n * Find an existing inline `<script>` tag (no `src`) with matching textContent.\n * Used to make `renderScriptTag` idempotent across hydration + navigation,\n * so SSR-emitted global scripts aren't re-appended client-side.\n */\n protected findInlineScriptByContent(\n document: Document,\n content: string,\n ): Element | null {\n for (const existing of document.head.querySelectorAll(\n \"script:not([src])\",\n )) {\n if (existing.textContent === content) return existing;\n }\n return null;\n }\n\n protected renderMetaTag(document: Document, meta: HeadMeta): void {\n const { content } = meta;\n\n // Handle OpenGraph tags (property attribute)\n if (meta.property) {\n const existing = document.querySelector(\n `meta[property=\"${meta.property}\"]`,\n );\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"property\", meta.property);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n return;\n }\n\n // Handle standard meta tags (name attribute)\n if (meta.name) {\n const existing = document.querySelector(`meta[name=\"${meta.name}\"]`);\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", meta.name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n}\n","import { Alepha } from \"alepha\";\nimport { useInject } from \"alepha/react\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const headProvider = alepha.inject(BrowserHeadProvider);\n const resolved =\n typeof head === \"function\"\n ? head(headProvider.getHead(window.document))\n : head || {};\n headProvider.renderHead(window.document, resolved);\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import { $module } from \"alepha\";\nimport { AlephaReact } from \"alepha/react\";\nimport { $head } from \"./primitives/$head.ts\";\nimport { BrowserHeadProvider } from \"./providers/BrowserHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./helpers/SeoExpander.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./primitives/$head.ts\";\nexport * from \"./providers/BrowserHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Alepha React Head Module\n *\n * @see {@link BrowserHeadProvider}\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [AlephaReact, BrowserHeadProvider],\n});\n"],"mappings":"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"}
@@ -1,6 +1,4 @@
1
- import * as _$alepha from "alepha";
2
1
  import { Alepha, KIND, Primitive } from "alepha";
3
- import * as _$alepha_logger0 from "alepha/logger";
4
2
 
5
3
  //#region ../../src/react/head/interfaces/Head.d.ts
6
4
  /**
@@ -237,7 +235,7 @@ type UseHeadReturn = [Head, (head?: Head | ((previous?: Head) => Head)) => void]
237
235
  * @see {@link BrowserHeadProvider}
238
236
  */
239
237
  declare class HeadProvider {
240
- protected readonly log: _$alepha_logger0.Logger;
238
+ protected readonly log: import("alepha/logger").Logger;
241
239
  protected readonly seoExpander: SeoExpander;
242
240
  global?: Array<Head | (() => Head)>;
243
241
  /**
@@ -381,7 +379,7 @@ declare class ServerHeadProvider {
381
379
  *
382
380
  * @module alepha.react.head
383
381
  */
384
- declare const AlephaReactHead: _$alepha.Service<_$alepha.Module>;
382
+ declare const AlephaReactHead: import("alepha").Service<import("alepha").Module>;
385
383
  //#endregion
386
384
  export { $head, AlephaReactHead, BrowserHeadProvider, Head, HeadMeta, HeadPrimitive, HeadPrimitiveOptions, Seo, SeoExpander, ServerHeadProvider, SimpleHead, UseHeadOptions, UseHeadReturn, useHead };
387
385
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/head/interfaces/Head.ts","../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/providers/ServerHeadProvider.ts","../../../src/react/head/index.ts"],"mappings":";;;;;;;;;;AAeA;;;;;AAMA;;;;;UANiB,IAAA,SAAa,UAAA,EAAY,GAAA;;;;;UAMzB,GAAA;EAoCf;;;EAhCA,WAAA;EAiDE;;;EA7CF,KAAA;EA+DA;;;EA3DA,GAAA;EAuEO;;AAIT;EAvEE,QAAA;;;;EAIA,MAAA;EAmFO;;;EA/EP,IAAA;EA0Gc;;;EAtGd,UAAA;EAiEA;;;EA7DA,WAAA;EAmEA;;;EA/DA,QAAA;EAmEa;;;EA9Db,OAAA;IAoEE;;;IAhEA,IAAA;IAwEA;;;IApEA,IAAA;IAiFO;;;IA7EP,OAAA;IAmFW;AAKf;;IApFI,KAAA;IAoFqB;;;IAhFrB,WAAA;IA4FK;;;IAxFL,KAAA;EAAA;ECjES;;;EDuEX,EAAA;ICrEQ;;;IDyEN,KAAA;ICU4B;;;IDN5B,WAAA;IC9EK;;;IDkFL,KAAA;EAAA;AAAA;AAAA,UAIa,UAAA;EACf,KAAA;EACA,cAAA;EC/CU;;;EDmDV,OAAA;ECnDsC;;;EDuDtC,QAAA;EACA,cAAA,GAAiB,MAAA;EACjB,cAAA,GAAiB,MAAA;ECdmC;;;EDkBpD,IAAA,GAAO,KAAA,CAAM,QAAA;;AErGf;;EFyGE,IAAA,GAAO,KAAA;IACL,GAAA;IACA,IAAA;IACA,IAAA;IACA,EAAA;IACA,WAAA;IE/EH;AAED;;;IFkFI,KAAA;IElF6C;;;IFsF7C,KAAA;IEtFyB;;;IF0FzB,QAAA;EAAA;EE1F0D;AAE9D;;EF6FE,MAAA,GAAS,KAAA,WAEJ,MAAA;IE9FL;;;IFkGM,OAAA;EAAA;AAAA;AAAA,UAKS,QAAA;EEtGP;;;EF0GR,IAAA;EE1GC;;;EF8GD,QAAA;;;AG5JF;EHgKE,OAAA;AAAA;;;;;;;AA/JF;;;;;AAMA;;;;;;;;;;cCAa,WAAA;EACJ,MAAA,CAAO,IAAA,EAAM,IAAA;IAClB,IAAA,EAAM,QAAA;IACN,IAAA,EAAM,KAAA;MAAQ,GAAA;MAAa,IAAA;IAAA;EAAA;EAAA,UAuCnB,eAAA,CAAgB,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,QAAA;EAAA,UA2ClC,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,QAAA;AAAA;;;;;;;AD3F5C;;;;;AAMA;;;;;;;;cEEa,OAAA,GAAW,OAAA,GAAU,cAAA,KAAiB,aAAA;AAAA,KAiCvC,cAAA,GAAiB,IAAA,KAAS,QAAA,GAAW,IAAA,KAAS,IAAA;AAAA,KAE9C,aAAA,IACV,IAAA,GACC,IAAA,GAAO,IAAA,KAAS,QAAA,GAAW,IAAA,KAAS,IAAA;;;;;;AF7CvC;;;;;AAMA;cGPa,YAAA;EAAA,mBACQ,GAAA,EADI,gBAAA,CACD,MAAA;EAAA,mBACH,WAAA,EAAW,WAAA;EAEvB,MAAA,GAAS,KAAA,CAAM,IAAA,UAAc,IAAA;EHWpC;;;EAAA,UGNU,yBAAA;EHsBV;;;;;;;;;EGXO,iBAAA,CAAA,GAAqB,IAAA;EHoD1B;;;;;;;AAsBJ;EGhDS,aAAA,CAAA,GAAiB,IAAA;EAkBjB,QAAA,CAAS,KAAA,EAAO,SAAA;EAAA,UAwBb,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,IAAA;EAAA,UAYlC,cAAA,CACR,IAAA,EAAM,SAAA,EACN,KAAA,EAAO,SAAA,EACP,KAAA,EAAO,MAAA;AAAA;;;;;UAsED,SAAA;EACR,IAAA,GAAO,IAAA,KAAS,KAAA,EAAO,MAAA,eAAqB,QAAA,GAAW,IAAA,KAAS,IAAA;AAAA;;;;;UAOxD,SAAA;EACR,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,KAAA;IACN,KAAA,GAAQ,SAAA;IACR,KAAA,GAAQ,MAAA;IACR,KAAA,GAAQ,KAAA;EAAA;AAAA;;;;;AHzLZ;cIRa,KAAA;EAAA,UAAkB,oBAAA,GAAoB,aAAA;EAAA;;KAMvC,oBAAA,GAAuB,IAAA,UAAc,IAAA;AAAA,cAIpC,aAAA,SAAsB,SAAA,CAAU,oBAAA;EAAA,mBACxB,QAAA,EAAQ,YAAA;EAAA,UACjB,MAAA,CAAA;AAAA;;;;;AJJZ;;;;;cKJa,mBAAA;EAAA,mBACQ,MAAA,EAAM,MAAA;EAAA,mBACN,YAAA,EAAY,YAAA;EAAA,cAEjB,QAAA,CAAA,GAAY,QAAA;ELU1B;;;;;;EKAO,iBAAA,CAAkB,KAAA;IAAS,IAAA,EAAM,IAAA;IAAM,MAAA,EAAQ,KAAA;EAAA;ELyCpD;;;;;;EKvBK,iBAAA,CAAA;EAKA,OAAA,CAAQ,QAAA,EAAU,QAAA,GAAW,IAAA;EA0C7B,UAAA,CAAW,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,IAAA;EAAA,UAqElC,eAAA,CACR,QAAA,EAAU,QAAA,EACV,MAAA,YAEK,MAAA;IAAiD,OAAA;EAAA;ELvDzC;;;;;EAAA,UKoGL,yBAAA,CACR,QAAA,EAAU,QAAA,EACV,OAAA,WACC,OAAA;EAAA,UASO,aAAA,CAAc,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,QAAA;AAAA;;;;;;AL7MpD;;;cMLa,kBAAA;EAAA,mBACQ,YAAA,EAAY,YAAA;ENUhB;;;;;;EMFR,iBAAA,CAAA,GAAqB,IAAA;ENkB5B;;;;EMVO,QAAA,CAAS,KAAA;IAAS,IAAA,EAAM,UAAA;IAAY,MAAA,EAAQ,KAAA;EAAA;AAAA;;;;;;;ANNrD;;;;;;cOQa,eAAA,EAAe,QAAA,CAAA,OAAA,CAU1B,QAAA,CAV0B,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/head/interfaces/Head.ts","../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/providers/ServerHeadProvider.ts","../../../src/react/head/index.ts"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/providers/ServerHeadProvider.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/index.ts"],"sourcesContent":["import type { Head, HeadMeta } from \"../interfaces/Head.ts\";\n\n/**\n * Expands Head configuration into SEO meta tags.\n *\n * Generates:\n * - `<meta name=\"description\">` from head.description\n * - `<meta property=\"og:*\">` OpenGraph tags\n * - `<meta name=\"twitter:*\">` Twitter Card tags\n *\n * @example\n * ```ts\n * const helper = new SeoExpander();\n * const { meta, link } = helper.expand({\n * title: \"My App\",\n * description: \"Build amazing apps\",\n * image: \"https://example.com/og.png\",\n * url: \"https://example.com/\",\n * });\n * ```\n */\nexport class SeoExpander {\n public expand(head: Head): {\n meta: HeadMeta[];\n link: Array<{ rel: string; href: string }>;\n } {\n const meta: HeadMeta[] = [];\n const link: Array<{ rel: string; href: string }> = [];\n\n // Only expand SEO if there's meaningful content beyond just title\n const hasSeoContent =\n head.description ||\n head.image ||\n head.url ||\n head.siteName ||\n head.locale ||\n head.type ||\n head.og ||\n head.twitter;\n\n if (!hasSeoContent) {\n return { meta, link };\n }\n\n // Base description\n if (head.description) {\n meta.push({ name: \"description\", content: head.description });\n }\n\n // Canonical URL\n if (head.url) {\n link.push({ rel: \"canonical\", href: head.url });\n }\n\n // OpenGraph tags\n this.expandOpenGraph(head, meta);\n\n // Twitter Card tags\n this.expandTwitter(head, meta);\n\n return { meta, link };\n }\n\n protected expandOpenGraph(head: Head, meta: HeadMeta[]): void {\n const ogTitle = head.og?.title ?? head.title;\n const ogDescription = head.og?.description ?? head.description;\n const ogImage = head.og?.image ?? head.image;\n\n if (head.type || ogTitle) {\n meta.push({ property: \"og:type\", content: head.type ?? \"website\" });\n }\n if (head.url) {\n meta.push({ property: \"og:url\", content: head.url });\n }\n if (ogTitle) {\n meta.push({ property: \"og:title\", content: ogTitle });\n }\n if (ogDescription) {\n meta.push({ property: \"og:description\", content: ogDescription });\n }\n if (ogImage) {\n meta.push({ property: \"og:image\", content: ogImage });\n if (head.imageWidth) {\n meta.push({\n property: \"og:image:width\",\n content: String(head.imageWidth),\n });\n }\n if (head.imageHeight) {\n meta.push({\n property: \"og:image:height\",\n content: String(head.imageHeight),\n });\n }\n if (head.imageAlt) {\n meta.push({ property: \"og:image:alt\", content: head.imageAlt });\n }\n }\n if (head.siteName) {\n meta.push({ property: \"og:site_name\", content: head.siteName });\n }\n if (head.locale) {\n meta.push({ property: \"og:locale\", content: head.locale });\n }\n }\n\n protected expandTwitter(head: Head, meta: HeadMeta[]): void {\n const twitterTitle = head.twitter?.title ?? head.title;\n const twitterDescription = head.twitter?.description ?? head.description;\n const twitterImage = head.twitter?.image ?? head.image;\n\n if (head.twitter?.card || twitterTitle || twitterImage) {\n meta.push({\n name: \"twitter:card\",\n content:\n head.twitter?.card ??\n (twitterImage ? \"summary_large_image\" : \"summary\"),\n });\n }\n if (head.url) {\n meta.push({ name: \"twitter:url\", content: head.url });\n }\n if (twitterTitle) {\n meta.push({ name: \"twitter:title\", content: twitterTitle });\n }\n if (twitterDescription) {\n meta.push({ name: \"twitter:description\", content: twitterDescription });\n }\n if (twitterImage) {\n meta.push({ name: \"twitter:image\", content: twitterImage });\n if (head.imageAlt) {\n meta.push({ name: \"twitter:image:alt\", content: head.imageAlt });\n }\n }\n if (head.twitter?.site) {\n meta.push({ name: \"twitter:site\", content: head.twitter.site });\n }\n if (head.twitter?.creator) {\n meta.push({ name: \"twitter:creator\", content: head.twitter.creator });\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { SeoExpander } from \"../helpers/SeoExpander.ts\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\n/**\n * Provides methods to fill and merge head information into the application state.\n *\n * Used both on server and client side to manage document head.\n *\n * @see {@link SeoExpander}\n * @see {@link ServerHeadProvider}\n * @see {@link BrowserHeadProvider}\n */\nexport class HeadProvider {\n protected readonly log = $logger();\n protected readonly seoExpander = $inject(SeoExpander);\n\n public global?: Array<Head | (() => Head)> = [];\n\n /**\n * Track if we've warned about page-level htmlAttributes to avoid spam.\n */\n protected warnedAboutHtmlAttributes = false;\n\n /**\n * Resolve global head configuration (from $head primitives only).\n *\n * This is used to get htmlAttributes early, before page loaders run.\n * Only htmlAttributes from global $head are allowed; page-level htmlAttributes\n * are ignored for early streaming optimization.\n *\n * @returns Merged global head with htmlAttributes\n */\n public resolveGlobalHead(): Head {\n const head: Head = {\n htmlAttributes: { lang: \"en\" },\n };\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n if (resolved.htmlAttributes) {\n head.htmlAttributes = {\n ...head.htmlAttributes,\n ...resolved.htmlAttributes,\n };\n }\n }\n\n return head;\n }\n\n /**\n * Fully resolve all global $head entries (functions re-evaluated, objects kept as-is).\n *\n * Unlike resolveGlobalHead() which only extracts htmlAttributes for streaming,\n * this resolves all head properties (meta, link, script, htmlAttributes, etc.).\n *\n * Used by BrowserHeadProvider.refreshGlobalHead() to re-apply global head to the DOM.\n */\n public resolveGlobal(): Head {\n let head: Head = {};\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n const { meta, link } = this.seoExpander.expand(resolved);\n head = {\n ...head,\n ...resolved,\n meta: [...(head.meta ?? []), ...meta, ...(resolved.meta ?? [])],\n link: [...(head.link ?? []), ...link, ...(resolved.link ?? [])],\n script: [...(head.script ?? []), ...(resolved.script ?? [])],\n };\n }\n\n return head;\n }\n\n public fillHead(state: HeadState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head = typeof h === \"function\" ? h() : h;\n this.mergeHead(state, head);\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n\n // Defaults if none were set by global $head or page head\n state.head.title ??= \"App\";\n state.head.htmlAttributes = {\n lang: \"en\",\n ...state.head.htmlAttributes,\n };\n }\n\n protected mergeHead(state: HeadState, head: Head): void {\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...meta, ...(head.meta ?? [])],\n link: [...(state.head.link ?? []), ...link, ...(head.link ?? [])],\n script: [...(state.head.script ?? []), ...(head.script ?? [])],\n };\n }\n\n protected fillHeadByPage(\n page: HeadRoute,\n state: HeadState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head.meta = [...(state.head.meta ?? []), ...meta];\n state.head.link = [...(state.head.link ?? []), ...link];\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n // htmlAttributes from pages are ignored for early streaming optimization.\n // Only global $head can set htmlAttributes.\n if (head.htmlAttributes && !this.warnedAboutHtmlAttributes) {\n this.warnedAboutHtmlAttributes = true;\n this.log.warn(\n \"Page-level htmlAttributes are ignored. Use global $head() for htmlAttributes instead, \" +\n \"as they are sent before page loaders run for early streaming optimization.\",\n );\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n\n if (head.link) {\n state.head.link = [...(state.head.link ?? []), ...(head.link ?? [])];\n }\n\n if (head.script) {\n state.head.script = [\n ...(state.head.script ?? []),\n ...(head.script ?? []),\n ];\n }\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimal route interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadRoute {\n head?: Head | ((props: Record<string, any>, previous?: Head) => Head);\n}\n\n/**\n * Minimal state interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadState {\n head: Head;\n layers: Array<{\n route?: HeadRoute;\n props?: Record<string, any>;\n error?: Error;\n }>;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [...(this.provider.global ?? []), this.options];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $inject, Alepha } from \"alepha\";\nimport type { Head, HeadMeta } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Browser-side head provider that manages document head elements.\n *\n * Used by ReactBrowserProvider and ReactBrowserRouterProvider to update\n * document title, meta tags, and other head elements during client-side\n * navigation.\n */\nexport class BrowserHeadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n /**\n * Fill head state from route configurations and render to document.\n * Combines fillHead from HeadProvider with renderHead to the DOM.\n *\n * Only runs in browser environment - no-op on server.\n */\n public fillAndRenderHead(state: { head: Head; layers: Array<any> }): void {\n // Skip on server-side\n if (!this.alepha.isBrowser()) {\n return;\n }\n\n this.headProvider.fillHead(state as any);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n }\n\n /**\n * Re-evaluate all global $head entries and apply the result to the DOM.\n *\n * Call this when something that affects global $head output changes at runtime\n * (e.g., theme switch). Page-level head (title, meta from routes) is not touched.\n */\n public refreshGlobalHead(): void {\n const head = this.headProvider.resolveGlobal();\n this.renderHead(this.document, head);\n }\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: HeadMeta[] = [];\n // Get meta tags with name attribute\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n // Get meta tags with property attribute (OpenGraph)\n for (const meta of document.head.querySelectorAll(\"meta[property]\")) {\n const property = meta.getAttribute(\"property\");\n const content = meta.getAttribute(\"content\");\n if (property && content) {\n metas.push({ property, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n this.renderMetaTag(document, it);\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n if (it.type) {\n link.setAttribute(\"type\", it.type);\n }\n if (it.as) {\n link.setAttribute(\"as\", it.as);\n }\n if (it.crossorigin != null) {\n link.setAttribute(\"crossorigin\", \"\");\n }\n if (it.media) {\n link.setAttribute(\"media\", it.media);\n }\n if (it.sizes) {\n link.setAttribute(\"sizes\", it.sizes);\n }\n if (it.hreflang) {\n link.setAttribute(\"hreflang\", it.hreflang);\n }\n document.head.appendChild(link);\n }\n }\n }\n\n if (head.script) {\n for (const it of head.script) {\n this.renderScriptTag(document, it);\n }\n }\n }\n\n protected renderScriptTag(\n document: Document,\n script:\n | string\n | (Record<string, string | boolean | undefined> & { content?: string }),\n ): void {\n // Plain string → inline script. Dedupe by exact content match against\n // any existing inline script (handles SSR-emitted globals that would\n // otherwise be re-appended on hydration).\n if (typeof script === \"string\") {\n if (this.findInlineScriptByContent(document, script)) return;\n const el = document.createElement(\"script\");\n el.textContent = script;\n document.head.appendChild(el);\n return;\n }\n\n const { content, ...attrs } = script;\n\n // src-based scripts: dedupe by src attribute (existing behaviour).\n if (attrs.src) {\n if (document.querySelector(`script[src=\"${attrs.src}\"]`)) return;\n } else if (typeof attrs.id === \"string\") {\n // id-based dedupe — single source of truth per id.\n if (document.querySelector(`script#${CSS.escape(attrs.id)}`)) return;\n } else if (content) {\n // Inline scripts with `content` and no src/id: fall back to content match.\n if (this.findInlineScriptByContent(document, content)) return;\n }\n\n const el = document.createElement(\"script\");\n for (const [key, value] of Object.entries(attrs)) {\n if (value === true) {\n el.setAttribute(key, \"\");\n } else if (value !== undefined && value !== false) {\n el.setAttribute(key, String(value));\n }\n }\n if (content) {\n el.textContent = content;\n }\n document.head.appendChild(el);\n }\n\n /**\n * Find an existing inline `<script>` tag (no `src`) with matching textContent.\n * Used to make `renderScriptTag` idempotent across hydration + navigation,\n * so SSR-emitted global scripts aren't re-appended client-side.\n */\n protected findInlineScriptByContent(\n document: Document,\n content: string,\n ): Element | null {\n for (const existing of document.head.querySelectorAll(\n \"script:not([src])\",\n )) {\n if (existing.textContent === content) return existing;\n }\n return null;\n }\n\n protected renderMetaTag(document: Document, meta: HeadMeta): void {\n const { content } = meta;\n\n // Handle OpenGraph tags (property attribute)\n if (meta.property) {\n const existing = document.querySelector(\n `meta[property=\"${meta.property}\"]`,\n );\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"property\", meta.property);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n return;\n }\n\n // Handle standard meta tags (name attribute)\n if (meta.name) {\n const existing = document.querySelector(`meta[name=\"${meta.name}\"]`);\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", meta.name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport type { Head, SimpleHead } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Server-side head provider that fills head content from route configurations.\n *\n * Used by ReactServerProvider to collect title, meta tags, and other head\n * elements which are then rendered by ReactServerTemplateProvider.\n */\nexport class ServerHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n\n /**\n * Resolve global head configuration (htmlAttributes only).\n *\n * Used for early streaming optimization - htmlAttributes can be sent\n * before page loaders run since they come from global $head only.\n */\n public resolveGlobalHead(): Head {\n return this.headProvider.resolveGlobalHead();\n }\n\n /**\n * Fill head state from route configurations.\n * Delegates to HeadProvider to merge head data from all route layers.\n */\n public fillHead(state: { head: SimpleHead; layers: Array<any> }): void {\n this.headProvider.fillHead(state as any);\n }\n}\n","import { Alepha } from \"alepha\";\nimport { useInject } from \"alepha/react\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const headProvider = alepha.inject(BrowserHeadProvider);\n const resolved =\n typeof head === \"function\"\n ? head(headProvider.getHead(window.document))\n : head || {};\n headProvider.renderHead(window.document, resolved);\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import { $module } from \"alepha\";\nimport { AlephaReact } from \"alepha/react\";\nimport { SeoExpander } from \"./helpers/SeoExpander.ts\";\nimport { $head } from \"./primitives/$head.ts\";\nimport { BrowserHeadProvider } from \"./providers/BrowserHeadProvider.ts\";\nimport { HeadProvider } from \"./providers/HeadProvider.ts\";\nimport { ServerHeadProvider } from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./helpers/SeoExpander.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./primitives/$head.ts\";\nexport * from \"./providers/BrowserHeadProvider.ts\";\nexport * from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * HTML head element management.\n *\n * **Features:**\n * - Title, meta tags, and links\n * - SEO optimization\n * - Social media tags\n *\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [\n AlephaReact,\n BrowserHeadProvider,\n HeadProvider,\n SeoExpander,\n ServerHeadProvider,\n ],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/head/helpers/SeoExpander.ts","../../../src/react/head/providers/HeadProvider.ts","../../../src/react/head/primitives/$head.ts","../../../src/react/head/providers/BrowserHeadProvider.ts","../../../src/react/head/providers/ServerHeadProvider.ts","../../../src/react/head/hooks/useHead.ts","../../../src/react/head/index.ts"],"sourcesContent":["import type { Head, HeadMeta } from \"../interfaces/Head.ts\";\n\n/**\n * Expands Head configuration into SEO meta tags.\n *\n * Generates:\n * - `<meta name=\"description\">` from head.description\n * - `<meta property=\"og:*\">` OpenGraph tags\n * - `<meta name=\"twitter:*\">` Twitter Card tags\n *\n * @example\n * ```ts\n * const helper = new SeoExpander();\n * const { meta, link } = helper.expand({\n * title: \"My App\",\n * description: \"Build amazing apps\",\n * image: \"https://example.com/og.png\",\n * url: \"https://example.com/\",\n * });\n * ```\n */\nexport class SeoExpander {\n public expand(head: Head): {\n meta: HeadMeta[];\n link: Array<{ rel: string; href: string }>;\n } {\n const meta: HeadMeta[] = [];\n const link: Array<{ rel: string; href: string }> = [];\n\n // Only expand SEO if there's meaningful content beyond just title\n const hasSeoContent =\n head.description ||\n head.image ||\n head.url ||\n head.siteName ||\n head.locale ||\n head.type ||\n head.og ||\n head.twitter;\n\n if (!hasSeoContent) {\n return { meta, link };\n }\n\n // Base description\n if (head.description) {\n meta.push({ name: \"description\", content: head.description });\n }\n\n // Canonical URL\n if (head.url) {\n link.push({ rel: \"canonical\", href: head.url });\n }\n\n // OpenGraph tags\n this.expandOpenGraph(head, meta);\n\n // Twitter Card tags\n this.expandTwitter(head, meta);\n\n return { meta, link };\n }\n\n protected expandOpenGraph(head: Head, meta: HeadMeta[]): void {\n const ogTitle = head.og?.title ?? head.title;\n const ogDescription = head.og?.description ?? head.description;\n const ogImage = head.og?.image ?? head.image;\n\n if (head.type || ogTitle) {\n meta.push({ property: \"og:type\", content: head.type ?? \"website\" });\n }\n if (head.url) {\n meta.push({ property: \"og:url\", content: head.url });\n }\n if (ogTitle) {\n meta.push({ property: \"og:title\", content: ogTitle });\n }\n if (ogDescription) {\n meta.push({ property: \"og:description\", content: ogDescription });\n }\n if (ogImage) {\n meta.push({ property: \"og:image\", content: ogImage });\n if (head.imageWidth) {\n meta.push({\n property: \"og:image:width\",\n content: String(head.imageWidth),\n });\n }\n if (head.imageHeight) {\n meta.push({\n property: \"og:image:height\",\n content: String(head.imageHeight),\n });\n }\n if (head.imageAlt) {\n meta.push({ property: \"og:image:alt\", content: head.imageAlt });\n }\n }\n if (head.siteName) {\n meta.push({ property: \"og:site_name\", content: head.siteName });\n }\n if (head.locale) {\n meta.push({ property: \"og:locale\", content: head.locale });\n }\n }\n\n protected expandTwitter(head: Head, meta: HeadMeta[]): void {\n const twitterTitle = head.twitter?.title ?? head.title;\n const twitterDescription = head.twitter?.description ?? head.description;\n const twitterImage = head.twitter?.image ?? head.image;\n\n if (head.twitter?.card || twitterTitle || twitterImage) {\n meta.push({\n name: \"twitter:card\",\n content:\n head.twitter?.card ??\n (twitterImage ? \"summary_large_image\" : \"summary\"),\n });\n }\n if (head.url) {\n meta.push({ name: \"twitter:url\", content: head.url });\n }\n if (twitterTitle) {\n meta.push({ name: \"twitter:title\", content: twitterTitle });\n }\n if (twitterDescription) {\n meta.push({ name: \"twitter:description\", content: twitterDescription });\n }\n if (twitterImage) {\n meta.push({ name: \"twitter:image\", content: twitterImage });\n if (head.imageAlt) {\n meta.push({ name: \"twitter:image:alt\", content: head.imageAlt });\n }\n }\n if (head.twitter?.site) {\n meta.push({ name: \"twitter:site\", content: head.twitter.site });\n }\n if (head.twitter?.creator) {\n meta.push({ name: \"twitter:creator\", content: head.twitter.creator });\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { SeoExpander } from \"../helpers/SeoExpander.ts\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\n/**\n * Provides methods to fill and merge head information into the application state.\n *\n * Used both on server and client side to manage document head.\n *\n * @see {@link SeoExpander}\n * @see {@link ServerHeadProvider}\n * @see {@link BrowserHeadProvider}\n */\nexport class HeadProvider {\n protected readonly log = $logger();\n protected readonly seoExpander = $inject(SeoExpander);\n\n public global?: Array<Head | (() => Head)> = [];\n\n /**\n * Track if we've warned about page-level htmlAttributes to avoid spam.\n */\n protected warnedAboutHtmlAttributes = false;\n\n /**\n * Resolve global head configuration (from $head primitives only).\n *\n * This is used to get htmlAttributes early, before page loaders run.\n * Only htmlAttributes from global $head are allowed; page-level htmlAttributes\n * are ignored for early streaming optimization.\n *\n * @returns Merged global head with htmlAttributes\n */\n public resolveGlobalHead(): Head {\n const head: Head = {\n htmlAttributes: { lang: \"en\" },\n };\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n if (resolved.htmlAttributes) {\n head.htmlAttributes = {\n ...head.htmlAttributes,\n ...resolved.htmlAttributes,\n };\n }\n }\n\n return head;\n }\n\n /**\n * Fully resolve all global $head entries (functions re-evaluated, objects kept as-is).\n *\n * Unlike resolveGlobalHead() which only extracts htmlAttributes for streaming,\n * this resolves all head properties (meta, link, script, htmlAttributes, etc.).\n *\n * Used by BrowserHeadProvider.refreshGlobalHead() to re-apply global head to the DOM.\n */\n public resolveGlobal(): Head {\n let head: Head = {};\n\n for (const h of this.global ?? []) {\n const resolved = typeof h === \"function\" ? h() : h;\n const { meta, link } = this.seoExpander.expand(resolved);\n head = {\n ...head,\n ...resolved,\n meta: [...(head.meta ?? []), ...meta, ...(resolved.meta ?? [])],\n link: [...(head.link ?? []), ...link, ...(resolved.link ?? [])],\n script: [...(head.script ?? []), ...(resolved.script ?? [])],\n };\n }\n\n return head;\n }\n\n public fillHead(state: HeadState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head = typeof h === \"function\" ? h() : h;\n this.mergeHead(state, head);\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n\n // Defaults if none were set by global $head or page head\n state.head.title ??= \"App\";\n state.head.htmlAttributes = {\n lang: \"en\",\n ...state.head.htmlAttributes,\n };\n }\n\n protected mergeHead(state: HeadState, head: Head): void {\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...meta, ...(head.meta ?? [])],\n link: [...(state.head.link ?? []), ...link, ...(head.link ?? [])],\n script: [...(state.head.script ?? []), ...(head.script ?? [])],\n };\n }\n\n protected fillHeadByPage(\n page: HeadRoute,\n state: HeadState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head.meta = [...(state.head.meta ?? []), ...meta];\n state.head.link = [...(state.head.link ?? []), ...link];\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n // htmlAttributes from pages are ignored for early streaming optimization.\n // Only global $head can set htmlAttributes.\n if (head.htmlAttributes && !this.warnedAboutHtmlAttributes) {\n this.warnedAboutHtmlAttributes = true;\n this.log.warn(\n \"Page-level htmlAttributes are ignored. Use global $head() for htmlAttributes instead, \" +\n \"as they are sent before page loaders run for early streaming optimization.\",\n );\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n\n if (head.link) {\n state.head.link = [...(state.head.link ?? []), ...(head.link ?? [])];\n }\n\n if (head.script) {\n state.head.script = [\n ...(state.head.script ?? []),\n ...(head.script ?? []),\n ];\n }\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimal route interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadRoute {\n head?: Head | ((props: Record<string, any>, previous?: Head) => Head);\n}\n\n/**\n * Minimal state interface for head processing.\n * Avoids circular dependency with alepha/react/router.\n */\ninterface HeadState {\n head: Head;\n layers: Array<{\n route?: HeadRoute;\n props?: Record<string, any>;\n error?: Error;\n }>;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [...(this.provider.global ?? []), this.options];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $inject, Alepha } from \"alepha\";\nimport type { Head, HeadMeta } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Browser-side head provider that manages document head elements.\n *\n * Used by ReactBrowserProvider and ReactBrowserRouterProvider to update\n * document title, meta tags, and other head elements during client-side\n * navigation.\n */\nexport class BrowserHeadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n /**\n * Fill head state from route configurations and render to document.\n * Combines fillHead from HeadProvider with renderHead to the DOM.\n *\n * Only runs in browser environment - no-op on server.\n */\n public fillAndRenderHead(state: { head: Head; layers: Array<any> }): void {\n // Skip on server-side\n if (!this.alepha.isBrowser()) {\n return;\n }\n\n this.headProvider.fillHead(state as any);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n }\n\n /**\n * Re-evaluate all global $head entries and apply the result to the DOM.\n *\n * Call this when something that affects global $head output changes at runtime\n * (e.g., theme switch). Page-level head (title, meta from routes) is not touched.\n */\n public refreshGlobalHead(): void {\n const head = this.headProvider.resolveGlobal();\n this.renderHead(this.document, head);\n }\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: HeadMeta[] = [];\n // Get meta tags with name attribute\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n // Get meta tags with property attribute (OpenGraph)\n for (const meta of document.head.querySelectorAll(\"meta[property]\")) {\n const property = meta.getAttribute(\"property\");\n const content = meta.getAttribute(\"content\");\n if (property && content) {\n metas.push({ property, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n this.renderMetaTag(document, it);\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n if (it.type) {\n link.setAttribute(\"type\", it.type);\n }\n if (it.as) {\n link.setAttribute(\"as\", it.as);\n }\n if (it.crossorigin != null) {\n link.setAttribute(\"crossorigin\", \"\");\n }\n if (it.media) {\n link.setAttribute(\"media\", it.media);\n }\n if (it.sizes) {\n link.setAttribute(\"sizes\", it.sizes);\n }\n if (it.hreflang) {\n link.setAttribute(\"hreflang\", it.hreflang);\n }\n document.head.appendChild(link);\n }\n }\n }\n\n if (head.script) {\n for (const it of head.script) {\n this.renderScriptTag(document, it);\n }\n }\n }\n\n protected renderScriptTag(\n document: Document,\n script:\n | string\n | (Record<string, string | boolean | undefined> & { content?: string }),\n ): void {\n // Plain string → inline script. Dedupe by exact content match against\n // any existing inline script (handles SSR-emitted globals that would\n // otherwise be re-appended on hydration).\n if (typeof script === \"string\") {\n if (this.findInlineScriptByContent(document, script)) return;\n const el = document.createElement(\"script\");\n el.textContent = script;\n document.head.appendChild(el);\n return;\n }\n\n const { content, ...attrs } = script;\n\n // src-based scripts: dedupe by src attribute (existing behaviour).\n if (attrs.src) {\n if (document.querySelector(`script[src=\"${attrs.src}\"]`)) return;\n } else if (typeof attrs.id === \"string\") {\n // id-based dedupe — single source of truth per id.\n if (document.querySelector(`script#${CSS.escape(attrs.id)}`)) return;\n } else if (content) {\n // Inline scripts with `content` and no src/id: fall back to content match.\n if (this.findInlineScriptByContent(document, content)) return;\n }\n\n const el = document.createElement(\"script\");\n for (const [key, value] of Object.entries(attrs)) {\n if (value === true) {\n el.setAttribute(key, \"\");\n } else if (value !== undefined && value !== false) {\n el.setAttribute(key, String(value));\n }\n }\n if (content) {\n el.textContent = content;\n }\n document.head.appendChild(el);\n }\n\n /**\n * Find an existing inline `<script>` tag (no `src`) with matching textContent.\n * Used to make `renderScriptTag` idempotent across hydration + navigation,\n * so SSR-emitted global scripts aren't re-appended client-side.\n */\n protected findInlineScriptByContent(\n document: Document,\n content: string,\n ): Element | null {\n for (const existing of document.head.querySelectorAll(\n \"script:not([src])\",\n )) {\n if (existing.textContent === content) return existing;\n }\n return null;\n }\n\n protected renderMetaTag(document: Document, meta: HeadMeta): void {\n const { content } = meta;\n\n // Handle OpenGraph tags (property attribute)\n if (meta.property) {\n const existing = document.querySelector(\n `meta[property=\"${meta.property}\"]`,\n );\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"property\", meta.property);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n return;\n }\n\n // Handle standard meta tags (name attribute)\n if (meta.name) {\n const existing = document.querySelector(`meta[name=\"${meta.name}\"]`);\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", meta.name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n}\n","import { $inject } from \"alepha\";\nimport type { Head, SimpleHead } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\n/**\n * Server-side head provider that fills head content from route configurations.\n *\n * Used by ReactServerProvider to collect title, meta tags, and other head\n * elements which are then rendered by ReactServerTemplateProvider.\n */\nexport class ServerHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n\n /**\n * Resolve global head configuration (htmlAttributes only).\n *\n * Used for early streaming optimization - htmlAttributes can be sent\n * before page loaders run since they come from global $head only.\n */\n public resolveGlobalHead(): Head {\n return this.headProvider.resolveGlobalHead();\n }\n\n /**\n * Fill head state from route configurations.\n * Delegates to HeadProvider to merge head data from all route layers.\n */\n public fillHead(state: { head: SimpleHead; layers: Array<any> }): void {\n this.headProvider.fillHead(state as any);\n }\n}\n","import { Alepha } from \"alepha\";\nimport { useInject } from \"alepha/react\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const headProvider = alepha.inject(BrowserHeadProvider);\n const resolved =\n typeof head === \"function\"\n ? head(headProvider.getHead(window.document))\n : head || {};\n headProvider.renderHead(window.document, resolved);\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import { $module } from \"alepha\";\nimport { AlephaReact } from \"alepha/react\";\nimport { SeoExpander } from \"./helpers/SeoExpander.ts\";\nimport { $head } from \"./primitives/$head.ts\";\nimport { BrowserHeadProvider } from \"./providers/BrowserHeadProvider.ts\";\nimport { HeadProvider } from \"./providers/HeadProvider.ts\";\nimport { ServerHeadProvider } from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./helpers/SeoExpander.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./primitives/$head.ts\";\nexport * from \"./providers/BrowserHeadProvider.ts\";\nexport * from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * HTML head element management.\n *\n * **Features:**\n * - Title, meta tags, and links\n * - SEO optimization\n * - Social media tags\n *\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [\n AlephaReact,\n BrowserHeadProvider,\n HeadProvider,\n SeoExpander,\n ServerHeadProvider,\n ],\n});\n"],"mappings":"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"}
@@ -1,9 +1,6 @@
1
- import * as _$alepha from "alepha";
2
1
  import { Alepha, Async, KIND, Primitive, TypeBoxError } from "alepha";
3
2
  import { DateTime, DateTimeProvider } from "alepha/datetime";
4
- import * as _$alepha_logger0 from "alepha/logger";
5
- import * as _$alepha_server_cookies0 from "alepha/server/cookies";
6
- import * as _$typebox from "typebox";
3
+ import { RouterLocaleProvider } from "alepha/react/router";
7
4
 
8
5
  //#region ../../src/react/i18n/components/Localize.d.ts
9
6
  interface LocalizeProps {
@@ -32,12 +29,52 @@ interface LocalizeProps {
32
29
  }
33
30
  declare const Localize: (props: LocalizeProps) => string | number;
34
31
  //#endregion
32
+ //#region ../../src/react/i18n/components/Translate.d.ts
33
+ interface TranslateProps {
34
+ /**
35
+ * Dictionary key to look up — the same key you would pass to `tr(...)`.
36
+ */
37
+ k: string;
38
+ /**
39
+ * Positional substitutions for `$1`, `$2`, … placeholders in the entry.
40
+ */
41
+ args?: string[];
42
+ /**
43
+ * Shown when the key is missing from every registered dictionary (otherwise
44
+ * the raw key is rendered, matching `tr`'s behaviour).
45
+ */
46
+ fallback?: string;
47
+ }
48
+ /**
49
+ * Renders a translated dictionary entry as a reactive text node.
50
+ *
51
+ * `tr(...)` is a hook, so it can only be called inside a component body. Use
52
+ * `<Translate>` wherever a *node* is expected instead — a prop, a `children`
53
+ * slot, or route metadata such as a nav-shell `label`. Because it subscribes to
54
+ * {@link useI18n} it re-renders on a language switch, unlike a string resolved
55
+ * once at module/initialisation time.
56
+ *
57
+ * Sibling of {@link Localize}: `Localize` formats a value (number, date,
58
+ * error); `Translate` looks up a key.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * nav: { label: <Translate k="admin.nav.users" /> }
63
+ * <Translate k="cart.items" args={[String(count)]} fallback="Items" />
64
+ * ```
65
+ */
66
+ declare const Translate: (props: TranslateProps) => import("react/jsx-runtime").JSX.Element;
67
+ /**
68
+ * Terse alias for {@link Translate} — handy in dense JSX such as nav labels.
69
+ */
70
+ declare const Tr: (props: TranslateProps) => import("react/jsx-runtime").JSX.Element;
71
+ //#endregion
35
72
  //#region ../../src/react/i18n/providers/I18nProvider.d.ts
36
73
  declare class I18nProvider<S extends object, K extends keyof ServiceDictionary<S>> {
37
- protected log: _$alepha_logger0.Logger;
74
+ protected log: import("alepha/logger").Logger;
38
75
  protected alepha: Alepha;
39
76
  protected dateTimeProvider: DateTimeProvider;
40
- protected cookie: _$alepha_server_cookies0.AbstractCookiePrimitive<_$typebox.TString>;
77
+ protected cookie: import("alepha/server/cookies").AbstractCookiePrimitive<import("typebox").TString>;
41
78
  readonly registry: Array<{
42
79
  target: string;
43
80
  name: string;
@@ -47,7 +84,17 @@ declare class I18nProvider<S extends object, K extends keyof ServiceDictionary<S
47
84
  }>;
48
85
  options: {
49
86
  fallbackLang: string;
87
+ autoDetect: boolean;
88
+ routing: "none" | "prefix";
50
89
  };
90
+ /**
91
+ * Lazily-resolved locale-prefix router integration. Present only when both
92
+ * the router module is registered AND `routing: "prefix"` was configured —
93
+ * otherwise i18n stays fully standalone.
94
+ */
95
+ protected localeProviderResolved: boolean;
96
+ protected localeProviderRef?: RouterLocaleProvider;
97
+ protected get localeProvider(): RouterLocaleProvider | undefined;
51
98
  dateFormat: {
52
99
  format: (value: Date) => string;
53
100
  };
@@ -56,11 +103,43 @@ declare class I18nProvider<S extends object, K extends keyof ServiceDictionary<S
56
103
  };
57
104
  get languages(): string[];
58
105
  constructor();
59
- protected readonly onRender: _$alepha.HookPrimitive<"server:onRequest">;
60
- protected readonly onStart: _$alepha.HookPrimitive<"start">;
106
+ /**
107
+ * Configure locale-prefix routing on the router, before the SSR routes are
108
+ * registered (`priority: "first"` runs ahead of the router's own `configure`
109
+ * hook). No-op unless `routing: "prefix"` and the router module is present.
110
+ */
111
+ protected readonly onConfigure: import("alepha").HookPrimitive<"configure">;
112
+ protected readonly onRender: import("alepha").HookPrimitive<"server:onRequest">;
113
+ /**
114
+ * Detects the language carried by the request URL when `routing: "prefix"` is
115
+ * active. Returns the locale for any URL (the prefixed one for `/fr/...`, the
116
+ * default for an unprefixed path), or `undefined` when prefix routing is off.
117
+ */
118
+ protected detectUrlLocale(pathname: string | undefined): string | undefined;
119
+ /**
120
+ * Resolves the UI language for an incoming server request.
121
+ *
122
+ * Priority:
123
+ * 0. the URL locale prefix (`routing: "prefix"`) — the URL is the source of
124
+ * truth and wins over everything, with no redirect;
125
+ * 1. the `lang` cookie — a language the user manually selected;
126
+ * 2. the `Accept-Language` header (when `autoDetect` is enabled) — but only
127
+ * when the detected language is actually registered, so we never switch to
128
+ * a locale we have no dictionary for. A region-qualified header (`en-US`)
129
+ * matches an exact registration first, then its base language (`en`);
130
+ * 3. `fallbackLang`.
131
+ */
132
+ protected resolveRequestLang(cookieLang: string | undefined, headerLang: string | undefined, urlLocale?: string): string;
133
+ protected readonly onStart: import("alepha").HookPrimitive<"start">;
61
134
  protected refreshLocale(): void;
135
+ /**
136
+ * Activates a language: lazily loads its dictionaries (browser), updates the
137
+ * lang state, and refreshes the locale-bound formatters. Does NOT persist a
138
+ * cookie or navigate — that is the caller's concern.
139
+ */
140
+ protected applyLang: (lang: string) => Promise<void>;
62
141
  setLang: (lang: string) => Promise<void>;
63
- protected readonly mutate: _$alepha.HookPrimitive<"state:mutate">;
142
+ protected readonly mutate: import("alepha").HookPrimitive<"state:mutate">;
64
143
  get fallbackLang(): string;
65
144
  get lang(): string;
66
145
  translate: (key: string, args?: string[]) => string;
@@ -173,7 +252,7 @@ declare module "alepha" {
173
252
  *
174
253
  * @module alepha.react.i18n
175
254
  */
176
- declare const AlephaReactI18n: _$alepha.Service<_$alepha.Module>;
255
+ declare const AlephaReactI18n: import("alepha").Service<import("alepha").Module>;
177
256
  //#endregion
178
- export { $dictionary, AlephaReactI18n, DictionaryPrimitive, DictionaryPrimitiveOptions, I18nLocalizeOptions, I18nLocalizeType, I18nProvider, Localize, type LocalizeProps, ServiceDictionary, useI18n };
257
+ export { $dictionary, AlephaReactI18n, DictionaryPrimitive, DictionaryPrimitiveOptions, I18nLocalizeOptions, I18nLocalizeType, I18nProvider, Localize, type LocalizeProps, ServiceDictionary, Tr, Translate, type TranslateProps, useI18n };
179
258
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/i18n/components/Localize.tsx","../../../src/react/i18n/providers/I18nProvider.ts","../../../src/react/i18n/primitives/$dictionary.ts","../../../src/react/i18n/hooks/useI18n.ts","../../../src/react/i18n/index.ts"],"mappings":";;;;;;;;UAIiB,aAAA;EACf,KAAA,oBAAyB,IAAA,GAAO,QAAA,GAAW,YAAA;;;;;EAK3C,MAAA,GAAS,IAAA,CAAK,mBAAA;EANc;;;;;;;;;EAgB5B,IAAA,wBAA4B,IAAA,CAAK,qBAAA;EAfR;;;;;EAqBzB,QAAA;AAAA;AAAA,cAGI,QAAA,GAAY,KAAA,EAAO,aAAA;;;cCvBZ,YAAA,mCAEK,iBAAA,CAAkB,CAAA;EAAA,UAExB,GAAA,EAFuB,gBAAA,CAEpB,MAAA;EAAA,UACH,MAAA,EAAM,MAAA;EAAA,UACN,gBAAA,EAAgB,gBAAA;EAAA,UAEhB,MAAA,EAAM,wBAAA,CAAA,uBAAA,CAFU,SAAA,CAEV,OAAA;EAAA,SAMA,QAAA,EAAU,KAAA;IACxB,MAAA;IACA,IAAA;IACA,IAAA;IACA,MAAA,QAAc,OAAA,CAAQ,MAAA;IACtB,YAAA,EAAc,MAAA;EAAA;EAGhB,OAAA;;;EAIO,UAAA;IAAc,MAAA,GAAS,KAAA,EAAO,IAAA;EAAA;EAG9B,YAAA;IAAgB,MAAA,GAAS,KAAA;EAAA;EAAA,IAGrB,SAAA,CAAA;;qBAcQ,QAAA,EApBsB,QAAA,CAoBd,aAAA;EAAA,mBAQR,OAAA,EARQ,QAAA,CAQD,aAAA;EAAA,UA6BhB,aAAA,CAAA;EAOH,OAAA,GAAiB,IAAA,aAAY,OAAA;EAAA,mBAiBjB,MAAA,EAjBiB,QAAA,CAiBX,aAAA;EAAA,IAwBd,YAAA,CAAA;EAAA,IASA,IAAA,CAAA;EAIJ,SAAA,GAAa,GAAA,UAAa,IAAA;EAAA,SAoBjB,CAAA,GACd,KAAA,EAAO,gBAAA,EACP,OAAA,GAAS,mBAAA;ED/IyB;;;;ACvBtC;;EDuBsC,SCiNpB,EAAA,GACd,GAAA,QAAW,iBAAA,CAAkB,CAAA,EAAG,CAAA,mBAChC,OAAA;IACE,IAAA;IACA,OAAA;EAAA;EAAA,UAUM,MAAA,CAAO,IAAA,UAAc,IAAA;AAAA;AAAA,KASrB,gBAAA,qBAAqC,IAAA,GAAO,QAAA,GAAW,YAAA;AAAA,UAElD,mBAAA;EA/OS;;;;EAoPxB,MAAA,GAAS,IAAA,CAAK,mBAAA;EA5O2B;;;;;;;;;EAsPzC,IAAA,wBAA4B,IAAA,CAAK,qBAAA;EAvCE;;;;;EA6CnC,QAAA;AAAA;;;;;;;;;ADxRF;;;;;;;;;;;;;;;;;;;;;;;AAuBC;;cEOY,WAAA;EAAA,WAAyB,MAAA,kBAAsB,OAAA,EACjD,0BAAA,CAA2B,CAAA,IACnC,mBAAA,CAAoB,CAAA;EAAA;;UAMN,0BAAA,WAAqC,MAAA;EACpD,IAAA;EACA,IAAA;EACA,IAAA,QAAY,KAAA;IAAQ,OAAA,EAAS,CAAA;EAAA;AAAA;AAAA,cAKlB,mBAAA,WACD,MAAA,0BACF,SAAA,CAAU,0BAAA,CAA2B,CAAA;EAAA,UACnC,QAAA,EAAQ,YAAA;EAAA,UACR,MAAA,CAAA;AAAA;;;;;;cC/CC,OAAA,qCAEK,iBAAA,CAAkB,CAAA,QAC/B,YAAA,CAAa,CAAA,EAAG,CAAA;AAAA,KAKT,iBAAA,mCACE,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,mBAAA,YAA+B,CAAA;;;;YCD3C,KAAA;IACf,wBAAA;EAAA;AAAA;;;;;;;;;;;cAgBS,eAAA,EAAe,QAAA,CAAA,OAAA,CAI1B,QAAA,CAJ0B,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/i18n/components/Localize.tsx","../../../src/react/i18n/components/Translate.tsx","../../../src/react/i18n/providers/I18nProvider.ts","../../../src/react/i18n/primitives/$dictionary.ts","../../../src/react/i18n/hooks/useI18n.ts","../../../src/react/i18n/index.ts"],"mappings":"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"}