alepha 0.15.0 → 0.15.2

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 (551) hide show
  1. package/README.md +43 -98
  2. package/dist/api/audits/index.d.ts +630 -653
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +12 -35
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +365 -358
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +12 -5
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +255 -248
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.browser.js +4 -4
  19. package/dist/api/notifications/index.browser.js.map +1 -1
  20. package/dist/api/notifications/index.d.ts +84 -78
  21. package/dist/api/notifications/index.d.ts.map +1 -1
  22. package/dist/api/notifications/index.js +14 -8
  23. package/dist/api/notifications/index.js.map +1 -1
  24. package/dist/api/parameters/index.d.ts +528 -535
  25. package/dist/api/parameters/index.d.ts.map +1 -1
  26. package/dist/api/parameters/index.js +30 -37
  27. package/dist/api/parameters/index.js.map +1 -1
  28. package/dist/api/users/index.d.ts +1221 -910
  29. package/dist/api/users/index.d.ts.map +1 -1
  30. package/dist/api/users/index.js +2556 -248
  31. package/dist/api/users/index.js.map +1 -1
  32. package/dist/api/verifications/index.d.ts +142 -136
  33. package/dist/api/verifications/index.d.ts.map +1 -1
  34. package/dist/api/verifications/index.js +12 -4
  35. package/dist/api/verifications/index.js.map +1 -1
  36. package/dist/batch/index.d.ts +142 -162
  37. package/dist/batch/index.d.ts.map +1 -1
  38. package/dist/batch/index.js +31 -44
  39. package/dist/batch/index.js.map +1 -1
  40. package/dist/bucket/index.d.ts +595 -171
  41. package/dist/bucket/index.d.ts.map +1 -1
  42. package/dist/bucket/index.js +1856 -12
  43. package/dist/bucket/index.js.map +1 -1
  44. package/dist/cache/core/index.d.ts +225 -53
  45. package/dist/cache/core/index.d.ts.map +1 -1
  46. package/dist/cache/core/index.js +213 -7
  47. package/dist/cache/core/index.js.map +1 -1
  48. package/dist/cache/redis/index.d.ts +1 -0
  49. package/dist/cache/redis/index.d.ts.map +1 -1
  50. package/dist/cache/redis/index.js +6 -2
  51. package/dist/cache/redis/index.js.map +1 -1
  52. package/dist/cli/index.d.ts +834 -226
  53. package/dist/cli/index.d.ts.map +1 -1
  54. package/dist/cli/index.js +2872 -417
  55. package/dist/cli/index.js.map +1 -1
  56. package/dist/command/index.d.ts +458 -310
  57. package/dist/command/index.d.ts.map +1 -1
  58. package/dist/command/index.js +2011 -76
  59. package/dist/command/index.js.map +1 -1
  60. package/dist/core/index.browser.js +309 -97
  61. package/dist/core/index.browser.js.map +1 -1
  62. package/dist/core/index.d.ts +796 -701
  63. package/dist/core/index.d.ts.map +1 -1
  64. package/dist/core/index.js +329 -97
  65. package/dist/core/index.js.map +1 -1
  66. package/dist/core/index.native.js +309 -97
  67. package/dist/core/index.native.js.map +1 -1
  68. package/dist/datetime/index.d.ts +59 -44
  69. package/dist/datetime/index.d.ts.map +1 -1
  70. package/dist/datetime/index.js +15 -0
  71. package/dist/datetime/index.js.map +1 -1
  72. package/dist/email/index.d.ts +314 -19
  73. package/dist/email/index.d.ts.map +1 -1
  74. package/dist/email/index.js +1852 -7
  75. package/dist/email/index.js.map +1 -1
  76. package/dist/fake/index.d.ts +5500 -5418
  77. package/dist/fake/index.d.ts.map +1 -1
  78. package/dist/fake/index.js +113 -42
  79. package/dist/fake/index.js.map +1 -1
  80. package/dist/lock/core/index.d.ts +219 -212
  81. package/dist/lock/core/index.d.ts.map +1 -1
  82. package/dist/lock/core/index.js +11 -4
  83. package/dist/lock/core/index.js.map +1 -1
  84. package/dist/lock/redis/index.d.ts.map +1 -1
  85. package/dist/logger/index.d.ts +41 -90
  86. package/dist/logger/index.d.ts.map +1 -1
  87. package/dist/logger/index.js +15 -68
  88. package/dist/logger/index.js.map +1 -1
  89. package/dist/mcp/index.d.ts +228 -230
  90. package/dist/mcp/index.d.ts.map +1 -1
  91. package/dist/mcp/index.js +32 -31
  92. package/dist/mcp/index.js.map +1 -1
  93. package/dist/orm/index.browser.js +12 -12
  94. package/dist/orm/index.browser.js.map +1 -1
  95. package/dist/orm/index.bun.js +90 -80
  96. package/dist/orm/index.bun.js.map +1 -1
  97. package/dist/orm/index.d.ts +1434 -1459
  98. package/dist/orm/index.d.ts.map +1 -1
  99. package/dist/orm/index.js +112 -130
  100. package/dist/orm/index.js.map +1 -1
  101. package/dist/queue/core/index.d.ts +262 -254
  102. package/dist/queue/core/index.d.ts.map +1 -1
  103. package/dist/queue/core/index.js +14 -6
  104. package/dist/queue/core/index.js.map +1 -1
  105. package/dist/queue/redis/index.d.ts.map +1 -1
  106. package/dist/react/auth/index.browser.js +108 -0
  107. package/dist/react/auth/index.browser.js.map +1 -0
  108. package/dist/react/auth/index.d.ts +100 -0
  109. package/dist/react/auth/index.d.ts.map +1 -0
  110. package/dist/react/auth/index.js +145 -0
  111. package/dist/react/auth/index.js.map +1 -0
  112. package/dist/react/core/index.d.ts +469 -0
  113. package/dist/react/core/index.d.ts.map +1 -0
  114. package/dist/react/core/index.js +464 -0
  115. package/dist/react/core/index.js.map +1 -0
  116. package/dist/react/form/index.d.ts +232 -0
  117. package/dist/react/form/index.d.ts.map +1 -0
  118. package/dist/react/form/index.js +432 -0
  119. package/dist/react/form/index.js.map +1 -0
  120. package/dist/react/head/index.browser.js +423 -0
  121. package/dist/react/head/index.browser.js.map +1 -0
  122. package/dist/react/head/index.d.ts +288 -0
  123. package/dist/react/head/index.d.ts.map +1 -0
  124. package/dist/react/head/index.js +465 -0
  125. package/dist/react/head/index.js.map +1 -0
  126. package/dist/react/i18n/index.d.ts +175 -0
  127. package/dist/react/i18n/index.d.ts.map +1 -0
  128. package/dist/react/i18n/index.js +224 -0
  129. package/dist/react/i18n/index.js.map +1 -0
  130. package/dist/react/router/index.browser.js +1980 -0
  131. package/dist/react/router/index.browser.js.map +1 -0
  132. package/dist/react/router/index.d.ts +2068 -0
  133. package/dist/react/router/index.d.ts.map +1 -0
  134. package/dist/react/router/index.js +4932 -0
  135. package/dist/react/router/index.js.map +1 -0
  136. package/dist/react/websocket/index.d.ts +117 -0
  137. package/dist/react/websocket/index.d.ts.map +1 -0
  138. package/dist/react/websocket/index.js +107 -0
  139. package/dist/react/websocket/index.js.map +1 -0
  140. package/dist/redis/index.bun.js +4 -0
  141. package/dist/redis/index.bun.js.map +1 -1
  142. package/dist/redis/index.d.ts +127 -130
  143. package/dist/redis/index.d.ts.map +1 -1
  144. package/dist/redis/index.js +16 -25
  145. package/dist/redis/index.js.map +1 -1
  146. package/dist/retry/index.d.ts +80 -71
  147. package/dist/retry/index.d.ts.map +1 -1
  148. package/dist/retry/index.js +11 -2
  149. package/dist/retry/index.js.map +1 -1
  150. package/dist/router/index.d.ts +6 -6
  151. package/dist/router/index.d.ts.map +1 -1
  152. package/dist/scheduler/index.d.ts +119 -28
  153. package/dist/scheduler/index.d.ts.map +1 -1
  154. package/dist/scheduler/index.js +404 -3
  155. package/dist/scheduler/index.js.map +1 -1
  156. package/dist/security/index.d.ts +642 -228
  157. package/dist/security/index.d.ts.map +1 -1
  158. package/dist/security/index.js +1579 -37
  159. package/dist/security/index.js.map +1 -1
  160. package/dist/server/auth/index.d.ts +1141 -111
  161. package/dist/server/auth/index.d.ts.map +1 -1
  162. package/dist/server/auth/index.js +1261 -25
  163. package/dist/server/auth/index.js.map +1 -1
  164. package/dist/server/cache/index.d.ts +63 -78
  165. package/dist/server/cache/index.d.ts.map +1 -1
  166. package/dist/server/cache/index.js +7 -22
  167. package/dist/server/cache/index.js.map +1 -1
  168. package/dist/server/compress/index.d.ts +13 -5
  169. package/dist/server/compress/index.d.ts.map +1 -1
  170. package/dist/server/compress/index.js +10 -2
  171. package/dist/server/compress/index.js.map +1 -1
  172. package/dist/server/cookies/index.d.ts +46 -22
  173. package/dist/server/cookies/index.d.ts.map +1 -1
  174. package/dist/server/cookies/index.js +7 -5
  175. package/dist/server/cookies/index.js.map +1 -1
  176. package/dist/server/core/index.d.ts +307 -196
  177. package/dist/server/core/index.d.ts.map +1 -1
  178. package/dist/server/core/index.js +271 -38
  179. package/dist/server/core/index.js.map +1 -1
  180. package/dist/server/cors/index.d.ts +24 -34
  181. package/dist/server/cors/index.d.ts.map +1 -1
  182. package/dist/server/cors/index.js +7 -21
  183. package/dist/server/cors/index.js.map +1 -1
  184. package/dist/server/health/index.d.ts +25 -19
  185. package/dist/server/health/index.d.ts.map +1 -1
  186. package/dist/server/health/index.js +8 -2
  187. package/dist/server/health/index.js.map +1 -1
  188. package/dist/server/helmet/index.d.ts +13 -5
  189. package/dist/server/helmet/index.d.ts.map +1 -1
  190. package/dist/server/helmet/index.js +11 -3
  191. package/dist/server/helmet/index.js.map +1 -1
  192. package/dist/server/links/index.browser.js +9 -1
  193. package/dist/server/links/index.browser.js.map +1 -1
  194. package/dist/server/links/index.d.ts +133 -128
  195. package/dist/server/links/index.d.ts.map +1 -1
  196. package/dist/server/links/index.js +24 -11
  197. package/dist/server/links/index.js.map +1 -1
  198. package/dist/server/metrics/index.d.ts +524 -4
  199. package/dist/server/metrics/index.d.ts.map +1 -1
  200. package/dist/server/metrics/index.js +4472 -7
  201. package/dist/server/metrics/index.js.map +1 -1
  202. package/dist/server/multipart/index.d.ts +15 -9
  203. package/dist/server/multipart/index.d.ts.map +1 -1
  204. package/dist/server/multipart/index.js +9 -3
  205. package/dist/server/multipart/index.js.map +1 -1
  206. package/dist/server/proxy/index.d.ts +110 -104
  207. package/dist/server/proxy/index.d.ts.map +1 -1
  208. package/dist/server/proxy/index.js +8 -2
  209. package/dist/server/proxy/index.js.map +1 -1
  210. package/dist/server/rate-limit/index.d.ts +46 -51
  211. package/dist/server/rate-limit/index.d.ts.map +1 -1
  212. package/dist/server/rate-limit/index.js +18 -55
  213. package/dist/server/rate-limit/index.js.map +1 -1
  214. package/dist/server/static/index.d.ts +181 -48
  215. package/dist/server/static/index.d.ts.map +1 -1
  216. package/dist/server/static/index.js +1848 -5
  217. package/dist/server/static/index.js.map +1 -1
  218. package/dist/server/swagger/index.d.ts +348 -53
  219. package/dist/server/swagger/index.d.ts.map +1 -1
  220. package/dist/server/swagger/index.js +1849 -6
  221. package/dist/server/swagger/index.js.map +1 -1
  222. package/dist/sms/index.d.ts +312 -18
  223. package/dist/sms/index.d.ts.map +1 -1
  224. package/dist/sms/index.js +1854 -10
  225. package/dist/sms/index.js.map +1 -1
  226. package/dist/system/index.browser.js +496 -0
  227. package/dist/system/index.browser.js.map +1 -0
  228. package/dist/system/index.d.ts +1158 -0
  229. package/dist/system/index.d.ts.map +1 -0
  230. package/dist/{file → system}/index.js +412 -20
  231. package/dist/system/index.js.map +1 -0
  232. package/dist/thread/index.d.ts +82 -73
  233. package/dist/thread/index.d.ts.map +1 -1
  234. package/dist/thread/index.js +13 -4
  235. package/dist/thread/index.js.map +1 -1
  236. package/dist/topic/core/index.d.ts +330 -323
  237. package/dist/topic/core/index.d.ts.map +1 -1
  238. package/dist/topic/core/index.js +12 -5
  239. package/dist/topic/core/index.js.map +1 -1
  240. package/dist/topic/redis/index.d.ts +6 -6
  241. package/dist/topic/redis/index.d.ts.map +1 -1
  242. package/dist/vite/index.d.ts +163 -5825
  243. package/dist/vite/index.d.ts.map +1 -1
  244. package/dist/vite/index.js +130 -477
  245. package/dist/vite/index.js.map +1 -1
  246. package/dist/websocket/index.browser.js +3 -3
  247. package/dist/websocket/index.browser.js.map +1 -1
  248. package/dist/websocket/index.d.ts +287 -283
  249. package/dist/websocket/index.d.ts.map +1 -1
  250. package/dist/websocket/index.js +15 -11
  251. package/dist/websocket/index.js.map +1 -1
  252. package/package.json +86 -17
  253. package/src/api/audits/index.ts +10 -33
  254. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  255. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  256. package/src/api/files/controllers/FileController.spec.ts +1 -1
  257. package/src/api/files/index.ts +10 -3
  258. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  259. package/src/api/files/services/FileService.spec.ts +1 -1
  260. package/src/api/jobs/index.ts +10 -3
  261. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  262. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  263. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  264. package/src/api/keys/index.ts +49 -0
  265. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  266. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  267. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  268. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  269. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  270. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  271. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  272. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  273. package/src/api/keys/services/ApiKeyService.ts +306 -0
  274. package/src/api/logs/TODO.md +52 -0
  275. package/src/api/notifications/index.ts +10 -4
  276. package/src/api/parameters/index.ts +9 -30
  277. package/src/api/parameters/primitives/$config.ts +12 -4
  278. package/src/api/parameters/services/ConfigStore.ts +9 -3
  279. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  280. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  281. package/src/api/users/index.ts +14 -3
  282. package/src/api/users/primitives/$realm.ts +33 -5
  283. package/src/api/users/providers/RealmProvider.ts +1 -12
  284. package/src/api/users/services/SessionService.ts +1 -11
  285. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  286. package/src/api/verifications/index.ts +10 -4
  287. package/src/batch/index.ts +9 -36
  288. package/src/batch/primitives/$batch.ts +0 -8
  289. package/src/batch/providers/BatchProvider.ts +29 -2
  290. package/src/bucket/__tests__/shared.ts +1 -1
  291. package/src/bucket/index.ts +13 -6
  292. package/src/bucket/primitives/$bucket.ts +1 -1
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  295. package/src/cache/core/__tests__/shared.ts +30 -0
  296. package/src/cache/core/index.ts +11 -6
  297. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  298. package/src/cache/core/providers/CacheProvider.ts +17 -0
  299. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  300. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  301. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  302. package/src/cli/apps/AlephaCli.ts +3 -16
  303. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
  304. package/src/cli/atoms/appEntryOptions.ts +13 -0
  305. package/src/cli/atoms/buildOptions.ts +1 -1
  306. package/src/cli/atoms/changelogOptions.ts +1 -1
  307. package/src/cli/commands/build.ts +64 -52
  308. package/src/cli/commands/db.ts +17 -11
  309. package/src/cli/commands/deploy.ts +1 -1
  310. package/src/cli/commands/dev.ts +13 -49
  311. package/src/cli/commands/gen/env.ts +6 -3
  312. package/src/cli/commands/gen/openapi.ts +5 -2
  313. package/src/cli/commands/init.spec.ts +544 -0
  314. package/src/cli/commands/init.ts +101 -58
  315. package/src/cli/commands/lint.ts +8 -2
  316. package/src/cli/commands/typecheck.ts +11 -0
  317. package/src/cli/defineConfig.ts +9 -0
  318. package/src/cli/index.ts +2 -1
  319. package/src/cli/providers/AppEntryProvider.ts +131 -0
  320. package/src/cli/providers/ViteBuildProvider.ts +40 -0
  321. package/src/cli/providers/ViteDevServerProvider.ts +378 -0
  322. package/src/cli/services/AlephaCliUtils.ts +39 -93
  323. package/src/cli/services/PackageManagerUtils.ts +140 -17
  324. package/src/cli/services/ProjectScaffolder.ts +169 -101
  325. package/src/cli/services/ViteUtils.ts +82 -0
  326. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
  327. package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
  328. package/src/cli/{assets → templates}/biomeJson.ts +2 -1
  329. package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
  330. package/src/cli/{assets → templates}/editorconfig.ts +2 -1
  331. package/src/cli/templates/gitignore.ts +39 -0
  332. package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
  333. package/src/cli/templates/mainCss.ts +33 -0
  334. package/src/cli/templates/mainServerTs.ts +33 -0
  335. package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
  336. package/src/cli/templates/webAppRouterTs.ts +50 -0
  337. package/src/cli/templates/webHelloComponentTsx.ts +20 -0
  338. package/src/command/helpers/Runner.spec.ts +4 -0
  339. package/src/command/helpers/Runner.ts +3 -21
  340. package/src/command/index.ts +12 -4
  341. package/src/command/providers/CliProvider.spec.ts +1067 -0
  342. package/src/command/providers/CliProvider.ts +203 -40
  343. package/src/core/Alepha.ts +3 -9
  344. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  345. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  346. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  347. package/src/core/index.shared.ts +1 -0
  348. package/src/core/index.ts +20 -0
  349. package/src/core/primitives/$module.ts +12 -0
  350. package/src/core/providers/EventManager.spec.ts +0 -71
  351. package/src/core/providers/EventManager.ts +3 -15
  352. package/src/core/providers/Json.ts +2 -14
  353. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
  354. package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
  355. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  356. package/src/datetime/index.ts +15 -0
  357. package/src/email/index.ts +10 -5
  358. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  359. package/src/email/providers/LocalEmailProvider.ts +1 -1
  360. package/src/fake/__tests__/keyName.example.ts +1 -1
  361. package/src/fake/__tests__/keyName.spec.ts +5 -5
  362. package/src/fake/index.ts +9 -6
  363. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  364. package/src/fake/providers/FakeProvider.ts +133 -19
  365. package/src/lock/core/index.ts +11 -4
  366. package/src/logger/index.ts +17 -66
  367. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  368. package/src/mcp/errors/McpError.ts +30 -0
  369. package/src/mcp/index.ts +13 -27
  370. package/src/mcp/transports/SseMcpTransport.ts +6 -7
  371. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  372. package/src/orm/index.browser.ts +2 -2
  373. package/src/orm/index.bun.ts +4 -2
  374. package/src/orm/index.ts +21 -47
  375. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  376. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
  377. package/src/orm/services/Repository.ts +18 -3
  378. package/src/queue/core/index.ts +14 -6
  379. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  380. package/src/react/auth/hooks/useAuth.ts +32 -0
  381. package/src/react/auth/index.browser.ts +13 -0
  382. package/src/react/auth/index.shared.ts +2 -0
  383. package/src/react/auth/index.ts +48 -0
  384. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  385. package/src/react/auth/services/ReactAuth.ts +135 -0
  386. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  387. package/src/react/core/components/ClientOnly.tsx +49 -0
  388. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  389. package/src/react/core/contexts/AlephaContext.ts +7 -0
  390. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  391. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  392. package/src/react/core/hooks/useAction.ts +480 -0
  393. package/src/react/core/hooks/useAlepha.ts +26 -0
  394. package/src/react/core/hooks/useClient.ts +17 -0
  395. package/src/react/core/hooks/useEvents.ts +51 -0
  396. package/src/react/core/hooks/useInject.ts +12 -0
  397. package/src/react/core/hooks/useStore.ts +52 -0
  398. package/src/react/core/index.ts +90 -0
  399. package/src/react/form/components/FormState.tsx +17 -0
  400. package/src/react/form/errors/FormValidationError.ts +18 -0
  401. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  402. package/src/react/form/hooks/useForm.ts +47 -0
  403. package/src/react/form/hooks/useFormState.ts +130 -0
  404. package/src/react/form/index.ts +44 -0
  405. package/src/react/form/services/FormModel.ts +614 -0
  406. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  407. package/src/react/head/helpers/SeoExpander.ts +142 -0
  408. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  409. package/src/react/head/hooks/useHead.ts +62 -0
  410. package/src/react/head/index.browser.ts +26 -0
  411. package/src/react/head/index.ts +44 -0
  412. package/src/react/head/interfaces/Head.ts +105 -0
  413. package/src/react/head/primitives/$head.ts +25 -0
  414. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  415. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  416. package/src/react/head/providers/HeadProvider.ts +168 -0
  417. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  418. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  419. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  420. package/src/react/i18n/components/Localize.tsx +35 -0
  421. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  422. package/src/react/i18n/hooks/useI18n.ts +18 -0
  423. package/src/react/i18n/index.ts +41 -0
  424. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  425. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  426. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  427. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  428. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  429. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  430. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  431. package/src/react/router/components/ErrorViewer.tsx +872 -0
  432. package/src/react/router/components/Link.tsx +23 -0
  433. package/src/react/router/components/NestedView.tsx +223 -0
  434. package/src/react/router/components/NotFound.tsx +30 -0
  435. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  436. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  437. package/src/react/router/errors/Redirection.ts +28 -0
  438. package/src/react/router/hooks/useActive.ts +52 -0
  439. package/src/react/router/hooks/useQueryParams.ts +63 -0
  440. package/src/react/router/hooks/useRouter.ts +20 -0
  441. package/src/react/router/hooks/useRouterState.ts +11 -0
  442. package/src/react/router/index.browser.ts +45 -0
  443. package/src/react/router/index.shared.ts +19 -0
  444. package/src/react/router/index.ts +142 -0
  445. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  446. package/src/react/router/primitives/$page.spec.tsx +708 -0
  447. package/src/react/router/primitives/$page.ts +497 -0
  448. package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
  449. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  450. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  451. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  452. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  453. package/src/react/router/providers/ReactServerProvider.ts +558 -0
  454. package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
  455. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  456. package/src/react/router/services/ReactPageServerService.ts +48 -0
  457. package/src/react/router/services/ReactPageService.ts +27 -0
  458. package/src/react/router/services/ReactRouter.ts +262 -0
  459. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  460. package/src/react/websocket/index.ts +7 -0
  461. package/src/redis/__tests__/redis.spec.ts +13 -0
  462. package/src/redis/index.ts +9 -25
  463. package/src/redis/providers/BunRedisProvider.ts +9 -0
  464. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  465. package/src/redis/providers/RedisProvider.ts +16 -0
  466. package/src/retry/index.ts +11 -2
  467. package/src/router/index.ts +15 -0
  468. package/src/scheduler/index.ts +11 -2
  469. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  470. package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
  471. package/src/security/index.ts +15 -10
  472. package/src/security/interfaces/IssuerResolver.ts +27 -0
  473. package/src/security/primitives/$issuer.ts +55 -0
  474. package/src/security/providers/SecurityProvider.ts +179 -0
  475. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  476. package/src/security/providers/ServerSecurityProvider.ts +36 -22
  477. package/src/server/auth/index.ts +12 -7
  478. package/src/server/cache/index.ts +7 -22
  479. package/src/server/compress/index.ts +10 -2
  480. package/src/server/cookies/index.ts +7 -5
  481. package/src/server/cookies/primitives/$cookie.ts +33 -11
  482. package/src/server/core/index.ts +17 -7
  483. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  484. package/src/server/core/primitives/$action.spec.ts +1 -1
  485. package/src/server/core/primitives/$action.ts +8 -3
  486. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  487. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  488. package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
  489. package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
  490. package/src/server/core/providers/ServerProvider.ts +9 -12
  491. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  492. package/src/server/core/services/ServerRequestParser.ts +306 -13
  493. package/src/server/cors/index.ts +7 -21
  494. package/src/server/cors/primitives/$cors.ts +6 -2
  495. package/src/server/health/index.ts +8 -2
  496. package/src/server/helmet/index.ts +11 -3
  497. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  498. package/src/server/links/index.browser.ts +2 -0
  499. package/src/server/links/index.ts +13 -6
  500. package/src/server/metrics/index.ts +10 -3
  501. package/src/server/multipart/index.ts +9 -3
  502. package/src/server/proxy/index.ts +8 -2
  503. package/src/server/rate-limit/index.ts +21 -25
  504. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  505. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  506. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  507. package/src/server/static/index.ts +8 -2
  508. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  509. package/src/server/swagger/index.ts +9 -4
  510. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  511. package/src/sms/index.ts +9 -5
  512. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  513. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  514. package/src/system/index.browser.ts +11 -0
  515. package/src/system/index.ts +62 -0
  516. package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
  517. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  518. package/src/system/providers/MemoryShellProvider.ts +164 -0
  519. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  520. package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
  521. package/src/system/providers/NodeShellProvider.ts +184 -0
  522. package/src/system/providers/ShellProvider.ts +74 -0
  523. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  524. package/src/thread/index.ts +11 -2
  525. package/src/topic/core/index.ts +12 -5
  526. package/src/vite/index.ts +3 -2
  527. package/src/vite/tasks/buildClient.ts +2 -8
  528. package/src/vite/tasks/buildServer.ts +84 -21
  529. package/src/vite/tasks/copyAssets.ts +5 -4
  530. package/src/vite/tasks/generateSitemap.ts +64 -23
  531. package/src/vite/tasks/index.ts +0 -2
  532. package/src/vite/tasks/prerenderPages.ts +49 -24
  533. package/src/websocket/index.ts +12 -8
  534. package/dist/file/index.d.ts +0 -839
  535. package/dist/file/index.d.ts.map +0 -1
  536. package/dist/file/index.js.map +0 -1
  537. package/src/cli/assets/indexHtml.ts +0 -15
  538. package/src/cli/assets/mainServerTs.ts +0 -24
  539. package/src/cli/assets/webAppRouterTs.ts +0 -15
  540. package/src/cli/assets/webHelloComponentTsx.ts +0 -16
  541. package/src/cli/commands/format.ts +0 -23
  542. package/src/file/index.ts +0 -43
  543. package/src/vite/helpers/boot.ts +0 -117
  544. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  545. package/src/vite/tasks/devServer.ts +0 -71
  546. package/src/vite/tasks/runAlepha.ts +0 -270
  547. /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
  548. /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
  549. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  550. /package/src/{file → system}/errors/FileError.ts +0 -0
  551. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -0,0 +1,726 @@
1
+ import {
2
+ $env,
3
+ $hook,
4
+ $inject,
5
+ Alepha,
6
+ AlephaError,
7
+ type Static,
8
+ type TSchema,
9
+ t,
10
+ } from "alepha";
11
+ import { $logger } from "alepha/logger";
12
+ import { AlephaContext, ClientOnly } from "alepha/react";
13
+ import type { Head } from "alepha/react/head";
14
+ import { createElement, type ReactNode, StrictMode } from "react";
15
+ import ErrorViewer from "../components/ErrorViewer.tsx";
16
+ import NestedView from "../components/NestedView.tsx";
17
+ import NotFoundPage from "../components/NotFound.tsx";
18
+ import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
19
+ import { Redirection } from "../errors/Redirection.ts";
20
+ import {
21
+ $page,
22
+ type ErrorHandler,
23
+ type PagePrimitive,
24
+ type PagePrimitiveOptions,
25
+ } from "../primitives/$page.ts";
26
+
27
+ const envSchema = t.object({
28
+ REACT_STRICT_MODE: t.boolean({ default: true }),
29
+ });
30
+
31
+ declare module "alepha" {
32
+ export interface Env extends Partial<Static<typeof envSchema>> {}
33
+ }
34
+
35
+ /**
36
+ * Handle page routes for React applications. (Browser and Server)
37
+ */
38
+ export class ReactPageProvider {
39
+ protected readonly log = $logger();
40
+ protected readonly env = $env(envSchema);
41
+ protected readonly alepha = $inject(Alepha);
42
+ protected readonly pages: PageRoute[] = [];
43
+
44
+ public getPages(): PageRoute[] {
45
+ return this.pages;
46
+ }
47
+
48
+ public getConcretePages(): ConcretePageRoute[] {
49
+ const pages: ConcretePageRoute[] = [];
50
+ for (const page of this.pages) {
51
+ if (page.children && page.children.length > 0) {
52
+ continue;
53
+ }
54
+
55
+ // check if the page has dynamic params
56
+ const fullPath = this.pathname(page.name);
57
+ if (fullPath.includes(":") || fullPath.includes("*")) {
58
+ if (typeof page.static === "object") {
59
+ const entries = page.static.entries;
60
+ if (entries && entries.length > 0) {
61
+ for (const entry of entries) {
62
+ const params = entry.params as Record<string, string>;
63
+ const path = this.compile(page.path ?? "", params);
64
+ if (!path.includes(":") && !path.includes("*")) {
65
+ pages.push({
66
+ ...page,
67
+ name: params[Object.keys(params)[0]],
68
+ staticName: page.name,
69
+ path,
70
+ ...entry,
71
+ });
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ continue;
78
+ }
79
+
80
+ pages.push(page);
81
+ }
82
+ return pages;
83
+ }
84
+
85
+ public page(name: string): PageRoute {
86
+ for (const page of this.pages) {
87
+ if (page.name === name) {
88
+ return page;
89
+ }
90
+ }
91
+
92
+ throw new AlephaError(`Page '${name}' not found`);
93
+ }
94
+
95
+ public pathname(
96
+ name: string,
97
+ options: {
98
+ params?: Record<string, string>;
99
+ query?: Record<string, string>;
100
+ } = {},
101
+ ) {
102
+ const page = this.page(name);
103
+ if (!page) {
104
+ throw new Error(`Page ${name} not found`);
105
+ }
106
+
107
+ let url = page.path ?? "";
108
+ let parent = page.parent;
109
+ while (parent) {
110
+ url = `${parent.path ?? ""}/${url}`;
111
+ parent = parent.parent;
112
+ }
113
+
114
+ url = this.compile(url, options.params ?? {});
115
+
116
+ if (options.query) {
117
+ const query = new URLSearchParams(options.query);
118
+ if (query.toString()) {
119
+ url += `?${query.toString()}`;
120
+ }
121
+ }
122
+
123
+ return url.replace(/\/\/+/g, "/") || "/";
124
+ }
125
+
126
+ public url(
127
+ name: string,
128
+ options: { params?: Record<string, string>; host?: string } = {},
129
+ ): URL {
130
+ return new URL(
131
+ this.pathname(name, options),
132
+ // use provided base or default to http://localhost
133
+ options.host ?? `http://localhost`,
134
+ );
135
+ }
136
+
137
+ public root(state: ReactRouterState): ReactNode {
138
+ const root = createElement(
139
+ AlephaContext.Provider,
140
+ { value: this.alepha },
141
+ createElement(NestedView, {}, state.layers[0]?.element),
142
+ );
143
+
144
+ if (this.env.REACT_STRICT_MODE) {
145
+ return createElement(StrictMode, {}, root);
146
+ }
147
+
148
+ return root;
149
+ }
150
+
151
+ protected convertStringObjectToObject = (
152
+ schema?: TSchema,
153
+ value?: any,
154
+ ): any => {
155
+ if (t.schema.isObject(schema) && typeof value === "object") {
156
+ for (const key in schema.properties) {
157
+ if (
158
+ t.schema.isObject(schema.properties[key]) &&
159
+ typeof value[key] === "string"
160
+ ) {
161
+ try {
162
+ value[key] = this.alepha.codec.decode(
163
+ schema.properties[key],
164
+ decodeURIComponent(value[key]),
165
+ );
166
+ } catch (e) {
167
+ // ignore
168
+ }
169
+ }
170
+ }
171
+ }
172
+ return value;
173
+ };
174
+
175
+ /**
176
+ * Create a new RouterState based on a given route and request.
177
+ * This method resolves the layers for the route, applying any query and params schemas defined in the route.
178
+ * It also handles errors and redirects.
179
+ */
180
+ public async createLayers(
181
+ route: PageRoute,
182
+ state: ReactRouterState,
183
+ previous: PreviousLayerData[] = [],
184
+ ): Promise<CreateLayersResult> {
185
+ let context: Record<string, any> = {}; // all props
186
+ const stack: Array<RouterStackItem> = [{ route }]; // stack of routes
187
+
188
+ let parent = route.parent;
189
+ while (parent) {
190
+ stack.unshift({ route: parent });
191
+ parent = parent.parent;
192
+ }
193
+
194
+ let forceRefresh = false;
195
+
196
+ for (let i = 0; i < stack.length; i++) {
197
+ const it = stack[i];
198
+ const route = it.route;
199
+ const config: Record<string, any> = {};
200
+
201
+ try {
202
+ this.convertStringObjectToObject(route.schema?.query, state.query);
203
+ config.query = route.schema?.query
204
+ ? this.alepha.codec.decode(route.schema.query, state.query)
205
+ : {};
206
+ } catch (e) {
207
+ it.error = e as Error;
208
+ break;
209
+ }
210
+
211
+ try {
212
+ config.params = route.schema?.params
213
+ ? this.alepha.codec.decode(route.schema.params, state.params)
214
+ : {};
215
+ } catch (e) {
216
+ it.error = e as Error;
217
+ break;
218
+ }
219
+
220
+ // save config
221
+ it.config = {
222
+ ...config,
223
+ };
224
+
225
+ // check if previous layer is the same, reuse if possible
226
+ if (previous?.[i] && !forceRefresh && previous[i].name === route.name) {
227
+ const url = (str?: string) => (str ? str.replace(/\/\/+/g, "/") : "/");
228
+
229
+ const prev = JSON.stringify({
230
+ part: url(previous[i].part),
231
+ params: previous[i].config?.params ?? {},
232
+ });
233
+
234
+ const curr = JSON.stringify({
235
+ part: url(route.path),
236
+ params: config.params ?? {},
237
+ });
238
+
239
+ if (prev === curr) {
240
+ // part is the same, reuse previous layer
241
+ it.props = previous[i].props;
242
+ it.error = previous[i].error;
243
+ it.cache = true;
244
+ context = {
245
+ ...context,
246
+ ...it.props,
247
+ };
248
+ continue;
249
+ }
250
+
251
+ // part is different, force refresh of next layers
252
+ forceRefresh = true;
253
+ }
254
+
255
+ // no loader, render a basic view by default
256
+ if (!route.loader) {
257
+ continue;
258
+ }
259
+
260
+ try {
261
+ const args = Object.create(state);
262
+ Object.assign(args, config, context);
263
+ const props = (await route.loader?.(args)) ?? {};
264
+
265
+ // save props
266
+ it.props = {
267
+ ...props,
268
+ };
269
+
270
+ // add props to context
271
+ context = {
272
+ ...context,
273
+ ...props,
274
+ };
275
+ } catch (e) {
276
+ // check if we need to redirect
277
+ if (e instanceof Redirection) {
278
+ return {
279
+ redirect: e.redirect,
280
+ };
281
+ }
282
+
283
+ this.log.error("Page loader has failed", e);
284
+
285
+ it.error = e as Error;
286
+ break;
287
+ }
288
+ }
289
+
290
+ let acc = "";
291
+ for (let i = 0; i < stack.length; i++) {
292
+ const it = stack[i];
293
+ const props = it.props ?? {};
294
+
295
+ const params = { ...it.config?.params };
296
+ for (const key of Object.keys(params)) {
297
+ params[key] = String(params[key]);
298
+ }
299
+
300
+ acc += "/";
301
+ acc += it.route.path ? this.compile(it.route.path, params) : "";
302
+ const path = acc.replace(/\/+/, "/");
303
+ const localErrorHandler = this.getErrorHandler(it.route);
304
+ if (localErrorHandler) {
305
+ const onErrorParent = state.onError;
306
+ state.onError = (error, context) => {
307
+ const result = localErrorHandler(error, context);
308
+ // if nothing happen, call the parent
309
+ if (result === undefined) {
310
+ return onErrorParent(error, context);
311
+ }
312
+ return result;
313
+ };
314
+ }
315
+
316
+ // normal use case
317
+ if (!it.error) {
318
+ try {
319
+ const element = await this.createElement(it.route, {
320
+ // default props attached to page
321
+ ...(it.route.props ? it.route.props() : {}),
322
+ // resolved props
323
+ ...props,
324
+ // context props (from previous layers)
325
+ ...context,
326
+ });
327
+
328
+ state.layers.push({
329
+ name: it.route.name,
330
+ props,
331
+ part: it.route.path,
332
+ config: it.config,
333
+ element: this.renderView(i + 1, path, element, it.route),
334
+ index: i + 1,
335
+ path,
336
+ route: it.route,
337
+ cache: it.cache,
338
+ });
339
+ } catch (e) {
340
+ it.error = e as Error;
341
+ }
342
+ }
343
+
344
+ // handler has thrown an error, render an error view
345
+ if (it.error) {
346
+ try {
347
+ let element: ReactNode | Redirection | undefined =
348
+ await state.onError(it.error, state);
349
+
350
+ if (element === undefined) {
351
+ throw it.error;
352
+ }
353
+
354
+ if (element instanceof Redirection) {
355
+ return {
356
+ redirect: element.redirect,
357
+ };
358
+ }
359
+
360
+ if (element === null) {
361
+ element = this.renderError(it.error);
362
+ }
363
+
364
+ state.layers.push({
365
+ props,
366
+ error: it.error,
367
+ name: it.route.name,
368
+ part: it.route.path,
369
+ config: it.config,
370
+ element: this.renderView(i + 1, path, element, it.route),
371
+ index: i + 1,
372
+ path,
373
+ route: it.route,
374
+ });
375
+ break;
376
+ } catch (e) {
377
+ if (e instanceof Redirection) {
378
+ return {
379
+ redirect: e.redirect,
380
+ };
381
+ }
382
+ throw e;
383
+ }
384
+ }
385
+ }
386
+
387
+ return { state };
388
+ }
389
+
390
+ protected getErrorHandler(route: PageRoute): ErrorHandler | undefined {
391
+ if (route.errorHandler) return route.errorHandler;
392
+ let parent = route.parent;
393
+ while (parent) {
394
+ if (parent.errorHandler) return parent.errorHandler;
395
+ parent = parent.parent;
396
+ }
397
+ }
398
+
399
+ protected async createElement(
400
+ page: PageRoute,
401
+ props: Record<string, any>,
402
+ ): Promise<ReactNode> {
403
+ if (page.lazy && page.component) {
404
+ this.log.warn(
405
+ `Page ${page.name} has both lazy and component options, lazy will be used`,
406
+ );
407
+ }
408
+
409
+ if (page.lazy) {
410
+ const component = await page.lazy(); // load component
411
+ return createElement(component.default, props);
412
+ }
413
+
414
+ if (page.component) {
415
+ return createElement(page.component, props);
416
+ }
417
+
418
+ return undefined;
419
+ }
420
+
421
+ public renderError(error: Error): ReactNode {
422
+ return createElement(ErrorViewer, { error, alepha: this.alepha });
423
+ }
424
+
425
+ public renderEmptyView(): ReactNode {
426
+ return createElement(NestedView, {});
427
+ }
428
+
429
+ public href(
430
+ page: { options: { name?: string } },
431
+ params: Record<string, any> = {},
432
+ ): string {
433
+ const found = this.pages.find((it) => it.name === page.options.name);
434
+ if (!found) {
435
+ throw new AlephaError(`Page ${page.options.name} not found`);
436
+ }
437
+
438
+ let url = found.path ?? "";
439
+ let parent = found.parent;
440
+ while (parent) {
441
+ url = `${parent.path ?? ""}/${url}`;
442
+ parent = parent.parent;
443
+ }
444
+
445
+ url = this.compile(url, params);
446
+
447
+ return url.replace(/\/\/+/g, "/") || "/";
448
+ }
449
+
450
+ public compile(path: string, params: Record<string, string> = {}) {
451
+ for (const [key, value] of Object.entries(params)) {
452
+ path = path.replace(`:${key}`, value);
453
+ }
454
+ return path;
455
+ }
456
+
457
+ protected renderView(
458
+ index: number,
459
+ path: string,
460
+ view: ReactNode | undefined,
461
+ page: PageRoute,
462
+ ): ReactNode {
463
+ view ??= this.renderEmptyView();
464
+
465
+ const element = page.client
466
+ ? createElement(
467
+ ClientOnly,
468
+ typeof page.client === "object" ? page.client : {},
469
+ view,
470
+ )
471
+ : view;
472
+
473
+ return createElement(
474
+ RouterLayerContext.Provider,
475
+ {
476
+ value: {
477
+ index,
478
+ path,
479
+ onError:
480
+ this.getErrorHandler(page) ?? ((error) => this.renderError(error)),
481
+ },
482
+ },
483
+ element,
484
+ );
485
+ }
486
+
487
+ protected readonly configure = $hook({
488
+ on: "configure",
489
+ handler: () => {
490
+ let hasNotFoundHandler = false;
491
+ const pages = this.alepha.primitives($page);
492
+
493
+ const hasParent = (it: PagePrimitive) => {
494
+ if (it.options.parent) {
495
+ return true;
496
+ }
497
+
498
+ for (const page of pages) {
499
+ const children = page.options.children
500
+ ? Array.isArray(page.options.children)
501
+ ? page.options.children
502
+ : page.options.children()
503
+ : [];
504
+ if (children.includes(it)) {
505
+ return true;
506
+ }
507
+ }
508
+ };
509
+
510
+ for (const page of pages) {
511
+ if (page.options.path === "/*") {
512
+ hasNotFoundHandler = true;
513
+ }
514
+
515
+ // skip children, we only want root pages
516
+ if (hasParent(page)) {
517
+ continue;
518
+ }
519
+
520
+ this.add(this.map(pages, page));
521
+ }
522
+
523
+ if (!hasNotFoundHandler && pages.length > 0) {
524
+ // add a default 404 page if not already defined
525
+ this.add({
526
+ path: "/*",
527
+ name: "notFound",
528
+ cache: true,
529
+ component: NotFoundPage,
530
+ onServerResponse: ({ reply }) => {
531
+ reply.status = 404;
532
+ },
533
+ });
534
+ }
535
+ },
536
+ });
537
+
538
+ protected map(
539
+ pages: Array<PagePrimitive>,
540
+ target: PagePrimitive,
541
+ ): PageRouteEntry {
542
+ const children = target.options.children
543
+ ? Array.isArray(target.options.children)
544
+ ? target.options.children
545
+ : target.options.children()
546
+ : [];
547
+
548
+ const getChildrenFromParent = (it: PagePrimitive): PagePrimitive[] => {
549
+ const children = [];
550
+ for (const page of pages) {
551
+ if (page.options.parent === it) {
552
+ children.push(page);
553
+ }
554
+ }
555
+ return children;
556
+ };
557
+
558
+ children.push(...getChildrenFromParent(target));
559
+
560
+ return {
561
+ ...target.options,
562
+ name: target.name,
563
+ parent: undefined,
564
+ children: children.map((it) => this.map(pages, it)),
565
+ } as PageRoute;
566
+ }
567
+
568
+ public add(entry: PageRouteEntry) {
569
+ if (this.alepha.isReady()) {
570
+ throw new AlephaError("Router is already initialized");
571
+ }
572
+
573
+ entry.name ??= this.nextId();
574
+ const page = entry as PageRoute;
575
+
576
+ page.match = this.createMatch(page);
577
+ this.pages.push(page);
578
+
579
+ if (page.children) {
580
+ for (const child of page.children) {
581
+ (child as PageRoute).parent = page;
582
+ this.add(child);
583
+ }
584
+ }
585
+ }
586
+
587
+ protected createMatch(page: PageRoute): string {
588
+ let url = page.path ?? "/";
589
+ let target = page.parent;
590
+ while (target) {
591
+ url = `${target.path ?? ""}/${url}`;
592
+ target = target.parent;
593
+ }
594
+
595
+ let path = url.replace(/\/\/+/g, "/");
596
+
597
+ if (path.endsWith("/") && path !== "/") {
598
+ // remove trailing slash
599
+ path = path.slice(0, -1);
600
+ }
601
+
602
+ return path;
603
+ }
604
+
605
+ protected _next = 0;
606
+
607
+ protected nextId(): string {
608
+ this._next += 1;
609
+ return `P${this._next}`;
610
+ }
611
+ }
612
+
613
+ export const isPageRoute = (it: any): it is PageRoute => {
614
+ return (
615
+ it &&
616
+ typeof it === "object" &&
617
+ typeof it.path === "string" &&
618
+ typeof it.page === "object"
619
+ );
620
+ };
621
+
622
+ export interface PageRouteEntry
623
+ extends Omit<PagePrimitiveOptions, "children" | "parent"> {
624
+ children?: PageRouteEntry[];
625
+ }
626
+
627
+ export interface ConcretePageRoute extends PageRoute {
628
+ /**
629
+ * When exported, static routes can be split into multiple pages with different params.
630
+ * We replace 'name' by the new name for each static entry, and old 'name' becomes 'staticName'.
631
+ */
632
+ staticName?: string;
633
+
634
+ params?: Record<string, string>;
635
+ }
636
+
637
+ export interface PageRoute extends PageRouteEntry {
638
+ type: "page";
639
+ name: string;
640
+ parent?: PageRoute;
641
+ match: string;
642
+ }
643
+
644
+ export interface Layer {
645
+ config?: {
646
+ query?: Record<string, any>;
647
+ params?: Record<string, any>;
648
+ // stack of resolved props
649
+ context?: Record<string, any>;
650
+ };
651
+
652
+ name: string;
653
+ props?: Record<string, any>;
654
+ error?: Error;
655
+ part?: string;
656
+ element: ReactNode;
657
+ index: number;
658
+ path: string;
659
+ route?: PageRoute;
660
+ cache?: boolean;
661
+ }
662
+
663
+ export type PreviousLayerData = Omit<Layer, "element" | "index" | "path">;
664
+
665
+ export interface AnchorProps {
666
+ href: string;
667
+ onClick: (ev?: any) => any;
668
+ }
669
+
670
+ export interface ReactRouterState {
671
+ /**
672
+ * Stack of layers for the current page.
673
+ */
674
+ layers: Array<Layer>;
675
+
676
+ /**
677
+ * URL of the current page.
678
+ */
679
+ url: URL;
680
+
681
+ /**
682
+ * Error handler for the current page.
683
+ */
684
+ onError: ErrorHandler;
685
+
686
+ /**
687
+ * Params extracted from the URL for the current page.
688
+ */
689
+ params: Record<string, any>;
690
+
691
+ /**
692
+ * Query parameters extracted from the URL for the current page.
693
+ */
694
+ query: Record<string, string>;
695
+
696
+ /**
697
+ * Optional meta information associated with the current page.
698
+ */
699
+ meta: Record<string, any>;
700
+
701
+ /**
702
+ * Head configuration for the current page (title, meta tags, etc.).
703
+ * Populated by HeadProvider during SSR.
704
+ */
705
+ head: Head;
706
+
707
+ //
708
+ name?: string;
709
+ }
710
+
711
+ export interface RouterStackItem {
712
+ route: PageRoute;
713
+ config?: Record<string, any>;
714
+ props?: Record<string, any>;
715
+ error?: Error;
716
+ cache?: boolean;
717
+ }
718
+
719
+ export interface TransitionOptions {
720
+ previous?: PreviousLayerData[];
721
+ }
722
+
723
+ export interface CreateLayersResult {
724
+ redirect?: string;
725
+ state?: ReactRouterState;
726
+ }