alepha 0.15.1 → 0.15.3

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 (523) hide show
  1. package/README.md +68 -80
  2. package/dist/api/audits/index.d.ts +10 -33
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +10 -33
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +10 -3
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +10 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +162 -155
  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.d.ts +10 -4
  19. package/dist/api/notifications/index.d.ts.map +1 -1
  20. package/dist/api/notifications/index.js +10 -4
  21. package/dist/api/notifications/index.js.map +1 -1
  22. package/dist/api/parameters/index.d.ts +43 -50
  23. package/dist/api/parameters/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.js +30 -37
  25. package/dist/api/parameters/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +1081 -760
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2539 -218
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts +138 -132
  31. package/dist/api/verifications/index.d.ts.map +1 -1
  32. package/dist/api/verifications/index.js +12 -4
  33. package/dist/api/verifications/index.js.map +1 -1
  34. package/dist/batch/index.d.ts +20 -40
  35. package/dist/batch/index.d.ts.map +1 -1
  36. package/dist/batch/index.js +31 -44
  37. package/dist/batch/index.js.map +1 -1
  38. package/dist/bucket/index.d.ts +440 -8
  39. package/dist/bucket/index.d.ts.map +1 -1
  40. package/dist/bucket/index.js +1861 -12
  41. package/dist/bucket/index.js.map +1 -1
  42. package/dist/cache/core/index.d.ts +179 -7
  43. package/dist/cache/core/index.d.ts.map +1 -1
  44. package/dist/cache/core/index.js +213 -7
  45. package/dist/cache/core/index.js.map +1 -1
  46. package/dist/cache/redis/index.d.ts +1 -0
  47. package/dist/cache/redis/index.d.ts.map +1 -1
  48. package/dist/cache/redis/index.js +4 -0
  49. package/dist/cache/redis/index.js.map +1 -1
  50. package/dist/cli/index.d.ts +638 -5645
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +2550 -368
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/command/index.d.ts +203 -45
  55. package/dist/command/index.d.ts.map +1 -1
  56. package/dist/command/index.js +2060 -71
  57. package/dist/command/index.js.map +1 -1
  58. package/dist/core/index.browser.js +70 -40
  59. package/dist/core/index.browser.js.map +1 -1
  60. package/dist/core/index.d.ts +34 -13
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +90 -40
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/index.native.js +70 -40
  65. package/dist/core/index.native.js.map +1 -1
  66. package/dist/datetime/index.d.ts +15 -0
  67. package/dist/datetime/index.d.ts.map +1 -1
  68. package/dist/datetime/index.js +15 -0
  69. package/dist/datetime/index.js.map +1 -1
  70. package/dist/email/index.d.ts +323 -20
  71. package/dist/email/index.d.ts.map +1 -1
  72. package/dist/email/index.js +1857 -7
  73. package/dist/email/index.js.map +1 -1
  74. package/dist/fake/index.d.ts +90 -8
  75. package/dist/fake/index.d.ts.map +1 -1
  76. package/dist/fake/index.js +91 -20
  77. package/dist/fake/index.js.map +1 -1
  78. package/dist/lock/core/index.d.ts +11 -4
  79. package/dist/lock/core/index.d.ts.map +1 -1
  80. package/dist/lock/core/index.js +11 -4
  81. package/dist/lock/core/index.js.map +1 -1
  82. package/dist/logger/index.d.ts +17 -66
  83. package/dist/logger/index.d.ts.map +1 -1
  84. package/dist/logger/index.js +14 -63
  85. package/dist/logger/index.js.map +1 -1
  86. package/dist/mcp/index.d.ts +10 -30
  87. package/dist/mcp/index.d.ts.map +1 -1
  88. package/dist/mcp/index.js +12 -35
  89. package/dist/mcp/index.js.map +1 -1
  90. package/dist/orm/index.browser.js +3 -3
  91. package/dist/orm/index.browser.js.map +1 -1
  92. package/dist/orm/index.bun.js +39 -20
  93. package/dist/orm/index.bun.js.map +1 -1
  94. package/dist/orm/index.d.ts +517 -540
  95. package/dist/orm/index.d.ts.map +1 -1
  96. package/dist/orm/index.js +58 -71
  97. package/dist/orm/index.js.map +1 -1
  98. package/dist/queue/core/index.d.ts +18 -10
  99. package/dist/queue/core/index.d.ts.map +1 -1
  100. package/dist/queue/core/index.js +14 -6
  101. package/dist/queue/core/index.js.map +1 -1
  102. package/dist/react/auth/index.browser.js +108 -0
  103. package/dist/react/auth/index.browser.js.map +1 -0
  104. package/dist/react/auth/index.d.ts +100 -0
  105. package/dist/react/auth/index.d.ts.map +1 -0
  106. package/dist/react/auth/index.js +145 -0
  107. package/dist/react/auth/index.js.map +1 -0
  108. package/dist/react/core/index.d.ts +469 -0
  109. package/dist/react/core/index.d.ts.map +1 -0
  110. package/dist/react/core/index.js +464 -0
  111. package/dist/react/core/index.js.map +1 -0
  112. package/dist/react/form/index.d.ts +232 -0
  113. package/dist/react/form/index.d.ts.map +1 -0
  114. package/dist/react/form/index.js +432 -0
  115. package/dist/react/form/index.js.map +1 -0
  116. package/dist/react/head/index.browser.js +423 -0
  117. package/dist/react/head/index.browser.js.map +1 -0
  118. package/dist/react/head/index.d.ts +288 -0
  119. package/dist/react/head/index.d.ts.map +1 -0
  120. package/dist/react/head/index.js +465 -0
  121. package/dist/react/head/index.js.map +1 -0
  122. package/dist/react/i18n/index.d.ts +175 -0
  123. package/dist/react/i18n/index.d.ts.map +1 -0
  124. package/dist/react/i18n/index.js +224 -0
  125. package/dist/react/i18n/index.js.map +1 -0
  126. package/dist/react/router/index.browser.js +1974 -0
  127. package/dist/react/router/index.browser.js.map +1 -0
  128. package/dist/react/router/index.d.ts +1956 -0
  129. package/dist/react/router/index.d.ts.map +1 -0
  130. package/dist/react/router/index.js +4722 -0
  131. package/dist/react/router/index.js.map +1 -0
  132. package/dist/react/websocket/index.d.ts +117 -0
  133. package/dist/react/websocket/index.d.ts.map +1 -0
  134. package/dist/react/websocket/index.js +107 -0
  135. package/dist/react/websocket/index.js.map +1 -0
  136. package/dist/redis/index.bun.js +4 -0
  137. package/dist/redis/index.bun.js.map +1 -1
  138. package/dist/redis/index.d.ts +41 -44
  139. package/dist/redis/index.d.ts.map +1 -1
  140. package/dist/redis/index.js +16 -25
  141. package/dist/redis/index.js.map +1 -1
  142. package/dist/retry/index.d.ts +11 -2
  143. package/dist/retry/index.d.ts.map +1 -1
  144. package/dist/retry/index.js +11 -2
  145. package/dist/retry/index.js.map +1 -1
  146. package/dist/scheduler/index.d.ts +11 -2
  147. package/dist/scheduler/index.d.ts.map +1 -1
  148. package/dist/scheduler/index.js +11 -2
  149. package/dist/scheduler/index.js.map +1 -1
  150. package/dist/security/index.d.ts +140 -49
  151. package/dist/security/index.d.ts.map +1 -1
  152. package/dist/security/index.js +164 -32
  153. package/dist/security/index.js.map +1 -1
  154. package/dist/server/auth/index.d.ts +12 -7
  155. package/dist/server/auth/index.d.ts.map +1 -1
  156. package/dist/server/auth/index.js +12 -7
  157. package/dist/server/auth/index.js.map +1 -1
  158. package/dist/server/cache/index.d.ts +7 -22
  159. package/dist/server/cache/index.d.ts.map +1 -1
  160. package/dist/server/cache/index.js +7 -22
  161. package/dist/server/cache/index.js.map +1 -1
  162. package/dist/server/compress/index.d.ts +10 -2
  163. package/dist/server/compress/index.d.ts.map +1 -1
  164. package/dist/server/compress/index.js +10 -2
  165. package/dist/server/compress/index.js.map +1 -1
  166. package/dist/server/cookies/index.d.ts +40 -16
  167. package/dist/server/cookies/index.d.ts.map +1 -1
  168. package/dist/server/cookies/index.js +7 -5
  169. package/dist/server/cookies/index.js.map +1 -1
  170. package/dist/server/core/index.d.ts +124 -23
  171. package/dist/server/core/index.d.ts.map +1 -1
  172. package/dist/server/core/index.js +231 -14
  173. package/dist/server/core/index.js.map +1 -1
  174. package/dist/server/cors/index.d.ts +13 -23
  175. package/dist/server/cors/index.d.ts.map +1 -1
  176. package/dist/server/cors/index.js +7 -21
  177. package/dist/server/cors/index.js.map +1 -1
  178. package/dist/server/health/index.d.ts +8 -2
  179. package/dist/server/health/index.d.ts.map +1 -1
  180. package/dist/server/health/index.js +8 -2
  181. package/dist/server/health/index.js.map +1 -1
  182. package/dist/server/helmet/index.d.ts +11 -3
  183. package/dist/server/helmet/index.d.ts.map +1 -1
  184. package/dist/server/helmet/index.js +11 -3
  185. package/dist/server/helmet/index.js.map +1 -1
  186. package/dist/server/links/index.d.ts +11 -6
  187. package/dist/server/links/index.d.ts.map +1 -1
  188. package/dist/server/links/index.js +11 -6
  189. package/dist/server/links/index.js.map +1 -1
  190. package/dist/server/metrics/index.d.ts +10 -3
  191. package/dist/server/metrics/index.d.ts.map +1 -1
  192. package/dist/server/metrics/index.js +10 -3
  193. package/dist/server/metrics/index.js.map +1 -1
  194. package/dist/server/multipart/index.d.ts +9 -3
  195. package/dist/server/multipart/index.d.ts.map +1 -1
  196. package/dist/server/multipart/index.js +9 -3
  197. package/dist/server/multipart/index.js.map +1 -1
  198. package/dist/server/proxy/index.d.ts +8 -2
  199. package/dist/server/proxy/index.d.ts.map +1 -1
  200. package/dist/server/proxy/index.js +8 -2
  201. package/dist/server/proxy/index.js.map +1 -1
  202. package/dist/server/rate-limit/index.d.ts +30 -35
  203. package/dist/server/rate-limit/index.d.ts.map +1 -1
  204. package/dist/server/rate-limit/index.js +18 -55
  205. package/dist/server/rate-limit/index.js.map +1 -1
  206. package/dist/server/static/index.d.ts +137 -4
  207. package/dist/server/static/index.d.ts.map +1 -1
  208. package/dist/server/static/index.js +1853 -5
  209. package/dist/server/static/index.js.map +1 -1
  210. package/dist/server/swagger/index.d.ts +309 -6
  211. package/dist/server/swagger/index.d.ts.map +1 -1
  212. package/dist/server/swagger/index.js +1854 -6
  213. package/dist/server/swagger/index.js.map +1 -1
  214. package/dist/sms/index.d.ts +309 -7
  215. package/dist/sms/index.d.ts.map +1 -1
  216. package/dist/sms/index.js +1856 -7
  217. package/dist/sms/index.js.map +1 -1
  218. package/dist/system/index.browser.js +1218 -0
  219. package/dist/system/index.browser.js.map +1 -0
  220. package/dist/{file → system}/index.d.ts +343 -16
  221. package/dist/system/index.d.ts.map +1 -0
  222. package/dist/{file → system}/index.js +419 -22
  223. package/dist/system/index.js.map +1 -0
  224. package/dist/thread/index.d.ts +11 -2
  225. package/dist/thread/index.d.ts.map +1 -1
  226. package/dist/thread/index.js +11 -2
  227. package/dist/thread/index.js.map +1 -1
  228. package/dist/topic/core/index.d.ts +12 -5
  229. package/dist/topic/core/index.d.ts.map +1 -1
  230. package/dist/topic/core/index.js +12 -5
  231. package/dist/topic/core/index.js.map +1 -1
  232. package/dist/vite/index.d.ts +5 -6272
  233. package/dist/vite/index.d.ts.map +1 -1
  234. package/dist/vite/index.js +23 -10
  235. package/dist/vite/index.js.map +1 -1
  236. package/dist/websocket/index.d.ts +12 -8
  237. package/dist/websocket/index.d.ts.map +1 -1
  238. package/dist/websocket/index.js +12 -8
  239. package/dist/websocket/index.js.map +1 -1
  240. package/package.json +82 -11
  241. package/src/api/audits/index.ts +10 -33
  242. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  243. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  244. package/src/api/files/controllers/FileController.spec.ts +1 -1
  245. package/src/api/files/index.ts +10 -3
  246. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  247. package/src/api/files/services/FileService.spec.ts +1 -1
  248. package/src/api/jobs/index.ts +10 -3
  249. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  250. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  251. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  252. package/src/api/keys/index.ts +49 -0
  253. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  254. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  255. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  256. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  257. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  258. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  259. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  260. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  261. package/src/api/keys/services/ApiKeyService.ts +306 -0
  262. package/src/api/logs/TODO.md +55 -0
  263. package/src/api/notifications/index.ts +10 -4
  264. package/src/api/parameters/index.ts +9 -30
  265. package/src/api/parameters/primitives/$config.ts +12 -4
  266. package/src/api/parameters/services/ConfigStore.ts +9 -3
  267. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  268. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  269. package/src/api/users/index.ts +14 -3
  270. package/src/api/users/primitives/$realm.ts +33 -5
  271. package/src/api/users/providers/RealmProvider.ts +1 -12
  272. package/src/api/users/services/SessionService.ts +1 -1
  273. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  274. package/src/api/verifications/index.ts +10 -4
  275. package/src/batch/index.ts +9 -36
  276. package/src/batch/primitives/$batch.ts +0 -8
  277. package/src/batch/providers/BatchProvider.ts +29 -2
  278. package/src/bucket/__tests__/shared.ts +1 -1
  279. package/src/bucket/index.ts +13 -6
  280. package/src/bucket/primitives/$bucket.ts +1 -1
  281. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  282. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  283. package/src/cache/core/__tests__/shared.ts +30 -0
  284. package/src/cache/core/index.ts +11 -6
  285. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  286. package/src/cache/core/providers/CacheProvider.ts +17 -0
  287. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  288. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  289. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  290. package/src/cli/apps/AlephaCli.ts +1 -14
  291. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
  292. package/src/cli/atoms/buildOptions.ts +99 -9
  293. package/src/cli/commands/build.ts +150 -37
  294. package/src/cli/commands/db.ts +22 -18
  295. package/src/cli/commands/deploy.ts +1 -1
  296. package/src/cli/commands/dev.ts +1 -20
  297. package/src/cli/commands/gen/env.ts +5 -2
  298. package/src/cli/commands/gen/openapi.ts +5 -2
  299. package/src/cli/commands/init.spec.ts +588 -0
  300. package/src/cli/commands/init.ts +115 -58
  301. package/src/cli/commands/lint.ts +7 -1
  302. package/src/cli/commands/typecheck.ts +11 -0
  303. package/src/cli/providers/AppEntryProvider.ts +1 -1
  304. package/src/cli/providers/ViteBuildProvider.ts +8 -50
  305. package/src/cli/providers/ViteDevServerProvider.ts +35 -16
  306. package/src/cli/services/AlephaCliUtils.ts +52 -121
  307. package/src/cli/services/PackageManagerUtils.ts +129 -11
  308. package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
  309. package/src/cli/services/ProjectScaffolder.ts +148 -81
  310. package/src/cli/services/ViteUtils.ts +82 -0
  311. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
  312. package/src/cli/templates/apiAppSecurityTs.ts +11 -0
  313. package/src/cli/templates/apiIndexTs.ts +30 -0
  314. package/src/cli/templates/gitignore.ts +39 -0
  315. package/src/cli/{assets → templates}/mainCss.ts +11 -2
  316. package/src/cli/templates/mainServerTs.ts +33 -0
  317. package/src/cli/templates/webAppRouterTs.ts +74 -0
  318. package/src/cli/templates/webHelloComponentTsx.ts +30 -0
  319. package/src/command/helpers/Runner.spec.ts +139 -0
  320. package/src/command/helpers/Runner.ts +7 -22
  321. package/src/command/index.ts +12 -4
  322. package/src/command/providers/CliProvider.spec.ts +1392 -0
  323. package/src/command/providers/CliProvider.ts +320 -47
  324. package/src/core/Alepha.ts +34 -27
  325. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  326. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  327. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  328. package/src/core/index.shared.ts +1 -0
  329. package/src/core/index.ts +20 -0
  330. package/src/core/providers/EventManager.spec.ts +0 -71
  331. package/src/core/providers/EventManager.ts +3 -15
  332. package/src/core/providers/Json.ts +2 -14
  333. package/src/datetime/index.ts +15 -0
  334. package/src/email/index.ts +10 -5
  335. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  336. package/src/email/providers/LocalEmailProvider.ts +1 -1
  337. package/src/fake/__tests__/keyName.example.ts +1 -1
  338. package/src/fake/__tests__/keyName.spec.ts +5 -5
  339. package/src/fake/index.ts +9 -6
  340. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  341. package/src/fake/providers/FakeProvider.ts +133 -19
  342. package/src/lock/core/index.ts +11 -4
  343. package/src/logger/index.ts +17 -66
  344. package/src/mcp/index.ts +10 -27
  345. package/src/mcp/transports/SseMcpTransport.ts +0 -11
  346. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  347. package/src/orm/index.browser.ts +2 -2
  348. package/src/orm/index.bun.ts +5 -3
  349. package/src/orm/index.ts +23 -53
  350. package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
  351. package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
  352. package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
  353. package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
  354. package/src/orm/services/Repository.ts +7 -3
  355. package/src/queue/core/index.ts +14 -6
  356. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  357. package/src/react/auth/hooks/useAuth.ts +32 -0
  358. package/src/react/auth/index.browser.ts +13 -0
  359. package/src/react/auth/index.shared.ts +2 -0
  360. package/src/react/auth/index.ts +48 -0
  361. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  362. package/src/react/auth/services/ReactAuth.ts +135 -0
  363. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  364. package/src/react/core/components/ClientOnly.tsx +49 -0
  365. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  366. package/src/react/core/contexts/AlephaContext.ts +7 -0
  367. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  368. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  369. package/src/react/core/hooks/useAction.ts +480 -0
  370. package/src/react/core/hooks/useAlepha.ts +26 -0
  371. package/src/react/core/hooks/useClient.ts +17 -0
  372. package/src/react/core/hooks/useEvents.ts +51 -0
  373. package/src/react/core/hooks/useInject.ts +12 -0
  374. package/src/react/core/hooks/useStore.ts +52 -0
  375. package/src/react/core/index.ts +90 -0
  376. package/src/react/form/components/FormState.tsx +17 -0
  377. package/src/react/form/errors/FormValidationError.ts +18 -0
  378. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  379. package/src/react/form/hooks/useForm.ts +47 -0
  380. package/src/react/form/hooks/useFormState.ts +130 -0
  381. package/src/react/form/index.ts +44 -0
  382. package/src/react/form/services/FormModel.ts +614 -0
  383. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  384. package/src/react/head/helpers/SeoExpander.ts +142 -0
  385. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  386. package/src/react/head/hooks/useHead.ts +62 -0
  387. package/src/react/head/index.browser.ts +26 -0
  388. package/src/react/head/index.ts +44 -0
  389. package/src/react/head/interfaces/Head.ts +105 -0
  390. package/src/react/head/primitives/$head.ts +25 -0
  391. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  392. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  393. package/src/react/head/providers/HeadProvider.ts +168 -0
  394. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  395. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  396. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  397. package/src/react/i18n/components/Localize.tsx +35 -0
  398. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  399. package/src/react/i18n/hooks/useI18n.ts +18 -0
  400. package/src/react/i18n/index.ts +41 -0
  401. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  402. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  403. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  404. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  405. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  406. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  407. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  408. package/src/react/router/components/ErrorViewer.tsx +872 -0
  409. package/src/react/router/components/Link.tsx +23 -0
  410. package/src/react/router/components/NestedView.tsx +223 -0
  411. package/src/react/router/components/NotFound.tsx +30 -0
  412. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  413. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  414. package/src/react/router/errors/Redirection.ts +28 -0
  415. package/src/react/router/hooks/useActive.ts +52 -0
  416. package/src/react/router/hooks/useQueryParams.ts +63 -0
  417. package/src/react/router/hooks/useRouter.ts +20 -0
  418. package/src/react/router/hooks/useRouterState.ts +11 -0
  419. package/src/react/router/index.browser.ts +45 -0
  420. package/src/react/router/index.shared.ts +19 -0
  421. package/src/react/router/index.ts +146 -0
  422. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  423. package/src/react/router/primitives/$page.spec.tsx +676 -0
  424. package/src/react/router/primitives/$page.ts +489 -0
  425. package/src/react/router/providers/ReactBrowserProvider.ts +312 -0
  426. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  427. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  428. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  429. package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
  430. package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
  431. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  432. package/src/react/router/providers/ReactServerProvider.ts +487 -0
  433. package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
  434. package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -0
  435. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  436. package/src/react/router/services/ReactPageServerService.ts +48 -0
  437. package/src/react/router/services/ReactPageService.ts +27 -0
  438. package/src/react/router/services/ReactRouter.ts +262 -0
  439. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  440. package/src/react/websocket/index.ts +7 -0
  441. package/src/redis/__tests__/redis.spec.ts +13 -0
  442. package/src/redis/index.ts +9 -25
  443. package/src/redis/providers/BunRedisProvider.ts +9 -0
  444. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  445. package/src/redis/providers/RedisProvider.ts +16 -0
  446. package/src/retry/index.ts +11 -2
  447. package/src/router/index.ts +15 -0
  448. package/src/scheduler/index.ts +11 -2
  449. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  450. package/src/security/__tests__/ServerSecurityProvider.spec.ts +90 -5
  451. package/src/security/index.ts +15 -10
  452. package/src/security/interfaces/IssuerResolver.ts +27 -0
  453. package/src/security/primitives/$issuer.ts +55 -0
  454. package/src/security/providers/SecurityProvider.ts +179 -0
  455. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  456. package/src/security/providers/ServerSecurityProvider.ts +63 -41
  457. package/src/server/auth/index.ts +12 -7
  458. package/src/server/cache/index.ts +7 -22
  459. package/src/server/compress/index.ts +10 -2
  460. package/src/server/cookies/index.ts +7 -5
  461. package/src/server/cookies/primitives/$cookie.ts +33 -11
  462. package/src/server/core/index.ts +16 -6
  463. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  464. package/src/server/core/primitives/$action.spec.ts +1 -1
  465. package/src/server/core/primitives/$action.ts +8 -3
  466. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
  467. package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
  468. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  469. package/src/server/core/services/ServerRequestParser.ts +306 -13
  470. package/src/server/cors/index.ts +7 -21
  471. package/src/server/cors/primitives/$cors.ts +6 -2
  472. package/src/server/health/index.ts +8 -2
  473. package/src/server/helmet/index.ts +11 -3
  474. package/src/server/links/index.ts +11 -6
  475. package/src/server/metrics/index.ts +10 -3
  476. package/src/server/multipart/index.ts +9 -3
  477. package/src/server/proxy/index.ts +8 -2
  478. package/src/server/rate-limit/index.ts +21 -25
  479. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  480. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  481. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  482. package/src/server/static/index.ts +8 -2
  483. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  484. package/src/server/swagger/index.ts +9 -4
  485. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  486. package/src/sms/index.ts +9 -5
  487. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  488. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  489. package/src/system/index.browser.ts +36 -0
  490. package/src/system/index.ts +62 -0
  491. package/src/system/index.workerd.ts +1 -0
  492. package/src/{file → system}/providers/FileSystemProvider.ts +24 -0
  493. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  494. package/src/system/providers/MemoryShellProvider.ts +164 -0
  495. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  496. package/src/{file → system}/providers/NodeFileSystemProvider.ts +47 -2
  497. package/src/system/providers/NodeShellProvider.ts +184 -0
  498. package/src/system/providers/ShellProvider.ts +74 -0
  499. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  500. package/src/thread/index.ts +11 -2
  501. package/src/topic/core/index.ts +12 -5
  502. package/src/vite/tasks/buildClient.ts +2 -7
  503. package/src/vite/tasks/buildServer.ts +19 -13
  504. package/src/vite/tasks/generateCloudflare.ts +10 -7
  505. package/src/vite/tasks/generateDocker.ts +4 -0
  506. package/src/websocket/index.ts +12 -8
  507. package/dist/file/index.d.ts.map +0 -1
  508. package/dist/file/index.js.map +0 -1
  509. package/src/cli/assets/apiIndexTs.ts +0 -16
  510. package/src/cli/assets/mainServerTs.ts +0 -24
  511. package/src/cli/assets/webAppRouterTs.ts +0 -16
  512. package/src/cli/assets/webHelloComponentTsx.ts +0 -20
  513. package/src/cli/providers/ViteTemplateProvider.ts +0 -27
  514. package/src/file/index.ts +0 -43
  515. /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
  516. /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
  517. /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
  518. /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
  519. /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
  520. /package/src/cli/{assets → templates}/tsconfigJson.ts +0 -0
  521. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  522. /package/src/{file → system}/errors/FileError.ts +0 -0
  523. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  import { $inject, t } from "alepha";
2
2
  import { $command } from "alepha/command";
3
- import { FileSystemProvider } from "alepha/file";
3
+ import { FileSystemProvider } from "alepha/system";
4
4
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
5
5
  import { PackageManagerUtils } from "../services/PackageManagerUtils.ts";
6
6
  import { ProjectScaffolder } from "../services/ProjectScaffolder.ts";
@@ -26,26 +26,45 @@ export class InitCommand {
26
26
  }),
27
27
  ),
28
28
  flags: t.object({
29
- agent: t.optional(
29
+ ai: t.optional(
30
30
  t.boolean({
31
- aliases: ["a"],
32
- description: "Add CLAUDE.md for Claude Code AI assistant",
31
+ description:
32
+ "Add AI agent instructions (CLAUDE.md if claude CLI installed, else AGENTS.md)",
33
+ }),
34
+ ),
35
+ pm: t.optional(
36
+ t.enum(["yarn", "npm", "pnpm", "bun"], {
37
+ description: "Package manager to use",
38
+ }),
39
+ ),
40
+ // choose which modules to scaffold
41
+ api: t.optional(
42
+ t.boolean({
43
+ description: "Include API module structure (src/api/)",
33
44
  }),
34
45
  ),
35
- // choose package manager
36
- yarn: t.optional(t.boolean({ description: "Use Yarn package manager" })),
37
- pnpm: t.optional(t.boolean({ description: "Use pnpm package manager" })),
38
- npm: t.optional(t.boolean({ description: "Use npm package manager" })),
39
- bun: t.optional(t.boolean({ description: "Use Bun package manager" })),
40
- // choose which dependencies to add
41
46
  react: t.optional(
42
47
  t.boolean({
43
48
  aliases: ["r"],
44
- description: "Include Alepha React dependencies",
49
+ description: "Include React dependencies and web module (src/web/)",
45
50
  }),
46
51
  ),
47
52
  ui: t.optional(
48
- t.boolean({ description: "Include Alepha UI dependencies" }),
53
+ t.boolean({
54
+ description:
55
+ "Include @alepha/ui (components, auth portal, admin portal)",
56
+ }),
57
+ ),
58
+ auth: t.optional(
59
+ t.boolean({
60
+ description:
61
+ "Include authentication (AppSecurity, $uiAuth). Implies --api --ui --react",
62
+ }),
63
+ ),
64
+ admin: t.optional(
65
+ t.boolean({
66
+ description: "Include admin portal ($uiAdmin). Implies --auth",
67
+ }),
49
68
  ),
50
69
  test: t.optional(
51
70
  t.boolean({ description: "Include Vitest and create test directory" }),
@@ -58,13 +77,31 @@ export class InitCommand {
58
77
  ),
59
78
  }),
60
79
  handler: async ({ run, flags, root, args }) => {
61
- if (flags.react) {
80
+ if (args) {
81
+ root = this.fs.join(root, args);
82
+ await this.fs.mkdir(root, { force: true });
83
+ }
84
+
85
+ // Flag cascading: --admin → --auth → --ui → --react, --api
86
+ if (flags.admin) {
87
+ flags.auth = true;
88
+ }
89
+ if (flags.auth) {
90
+ flags.api = true;
62
91
  flags.ui = true;
63
92
  }
93
+ if (flags.ui) {
94
+ flags.react = true;
95
+ }
64
96
 
65
- if (args) {
66
- root = this.fs.join(root, args);
67
- await this.fs.mkdir(root);
97
+ // Detect workspace context (are we inside packages/ or apps/ of a monorepo?)
98
+ const workspace = await this.pm.getWorkspaceContext(root);
99
+
100
+ // Detect agent type: claude CLI → CLAUDE.md, else → AGENTS.md
101
+ let agentType: "claude" | "agents" | false = false;
102
+ if (flags.ai) {
103
+ const hasClaudeCli = await this.utils.isInstalledAsync("claude");
104
+ agentType = hasClaudeCli ? "claude" : "agents";
68
105
  }
69
106
 
70
107
  const isExpo = await this.pm.hasExpo(root);
@@ -76,69 +113,89 @@ export class InitCommand {
76
113
  handler: async () => {
77
114
  await this.scaffolder.ensureConfig(root, {
78
115
  force,
79
- tsconfigJson: true,
80
- packageJson: flags,
81
- biomeJson: true,
82
- editorconfig: true,
83
- indexHtml: !!flags.react && !isExpo,
84
- claudeMd: flags.agent
85
- ? { react: !!flags.react, ui: !!flags.ui }
116
+ tsconfigJson: !workspace.config.tsconfigJson,
117
+ packageJson: { ...flags, isPackage: workspace.isPackage },
118
+ // Skip workspace-level configs if they exist at workspace root
119
+ biomeJson: !workspace.config.biomeJson,
120
+ editorconfig: !workspace.config.editorconfig,
121
+ agentMd: agentType
122
+ ? { type: agentType, react: !!flags.react, ui: !!flags.ui }
86
123
  : false,
87
124
  });
88
125
 
89
- // Create API project structure if not React
90
- if (!flags.react) {
91
- await this.scaffolder.ensureApiProject(root, { force });
126
+ // Create project structure based on flags
127
+ await this.scaffolder.ensureMainServerTs(root, {
128
+ api: !!flags.api,
129
+ react: !!flags.react && !isExpo,
130
+ force,
131
+ });
132
+ if (flags.api) {
133
+ await this.scaffolder.ensureApiProject(root, {
134
+ auth: !!flags.auth,
135
+ force,
136
+ });
137
+ }
138
+ if (flags.react && !isExpo) {
139
+ await this.scaffolder.ensureWebProject(root, {
140
+ api: !!flags.api,
141
+ ui: !!flags.ui,
142
+ auth: !!flags.auth,
143
+ admin: !!flags.admin,
144
+ force,
145
+ });
92
146
  }
93
147
  },
94
148
  });
95
149
 
96
- // TODO: check if all alepha dependencies are same version
150
+ // Use workspace PM if detected, otherwise detect from current root
151
+ const pmName = await this.pm.getPackageManager(
152
+ workspace.workspaceRoot ?? root,
153
+ flags.pm ?? workspace.packageManager ?? undefined,
154
+ );
97
155
 
98
- const pmName = await this.pm.getPackageManager(root, flags);
99
- if (pmName === "yarn") {
100
- await this.pm.ensureYarn(root);
101
- await run("yarn set version stable", { root });
102
- } else if (pmName === "bun") {
103
- await this.pm.ensureBun(root);
104
- } else if (pmName === "pnpm") {
105
- await this.pm.ensurePnpm(root);
106
- } else {
107
- await this.pm.ensureNpm(root);
156
+ // Only setup PM files if not in a workspace package
157
+ if (!workspace.isPackage) {
158
+ if (pmName === "yarn") {
159
+ await this.pm.ensureYarn(root);
160
+ await run("yarn set version stable", { root });
161
+ } else if (pmName === "bun") {
162
+ await this.pm.ensureBun(root);
163
+ } else if (pmName === "pnpm") {
164
+ await this.pm.ensurePnpm(root);
165
+ } else {
166
+ await this.pm.ensureNpm(root);
167
+ }
108
168
  }
109
169
 
170
+ // Run install from workspace root if in a package, otherwise from current root
171
+ const installRoot = workspace.workspaceRoot ?? root;
110
172
  await run(`${pmName} install`, {
111
173
  alias: `installing dependencies with ${pmName}`,
112
- root,
174
+ root: installRoot,
113
175
  });
114
176
 
115
- if (!isExpo) {
116
- await this.pm.ensureDependency(root, "vite", {
117
- run,
118
- exec: (cmd, opts) => this.utils.exec(cmd, opts),
119
- });
120
- }
121
-
122
- await this.pm.ensureDependency(root, "@biomejs/biome", {
123
- run,
124
- exec: (cmd, opts) => this.utils.exec(cmd, opts),
125
- });
126
-
127
- // Install vitest and create test directory if --test flag is set
177
+ // Create test directory if --test flag is set (vitest is in package.json)
128
178
  if (flags.test) {
129
179
  await this.scaffolder.ensureTestDir(root);
130
- await run(
131
- `${pmName} ${pmName === "yarn" ? "add" : "install"} -D vitest`,
132
- {
133
- alias: "setup testing with Vitest",
134
- },
135
- );
136
180
  }
137
181
 
138
182
  await run(`${pmName} run lint`, {
139
183
  alias: "running linter",
140
- root,
184
+ root: installRoot,
141
185
  });
186
+
187
+ // Initialize git repository if not in a workspace package
188
+ if (!workspace.isPackage) {
189
+ const gitInitialized = await this.scaffolder.ensureGitRepo(root, {
190
+ force,
191
+ });
192
+ if (gitInitialized) {
193
+ await run("git add .", {
194
+ alias: "staging generated files",
195
+ root,
196
+ });
197
+ }
198
+ }
142
199
  },
143
200
  });
144
201
  }
@@ -13,10 +13,16 @@ export class LintCommand {
13
13
  name: "lint",
14
14
  description: "Run linter across the codebase using Biome",
15
15
  handler: async ({ root }) => {
16
- await this.scaffolder.ensureConfig(root, { biomeJson: true });
16
+ await this.scaffolder.ensureConfig(root, {
17
+ biomeJson: true,
18
+ checkWorkspace: true,
19
+ });
20
+
17
21
  await this.pm.ensureDependency(root, "@biomejs/biome", {
22
+ checkWorkspace: true,
18
23
  exec: (cmd, opts) => this.utils.exec(cmd, opts),
19
24
  });
25
+
20
26
  await this.utils.exec("biome check --fix");
21
27
  },
22
28
  });
@@ -3,11 +3,13 @@ import { $command } from "alepha/command";
3
3
  import { $logger } from "alepha/logger";
4
4
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
5
5
  import { PackageManagerUtils } from "../services/PackageManagerUtils.ts";
6
+ import { ProjectScaffolder } from "../services/ProjectScaffolder.ts";
6
7
 
7
8
  export class TypecheckCommand {
8
9
  protected readonly utils = $inject(AlephaCliUtils);
9
10
  protected readonly pm = $inject(PackageManagerUtils);
10
11
  protected readonly log = $logger();
12
+ protected readonly scaffolder = $inject(ProjectScaffolder);
11
13
 
12
14
  /**
13
15
  * Run TypeScript type checking across the codebase with no emit.
@@ -18,10 +20,19 @@ export class TypecheckCommand {
18
20
  description: "Check TypeScript types across the codebase",
19
21
  handler: async ({ root }) => {
20
22
  this.log.info("Starting TypeScript type checking...");
23
+
24
+ await this.scaffolder.ensureConfig(root, {
25
+ tsconfigJson: true,
26
+ checkWorkspace: true,
27
+ });
28
+
21
29
  await this.pm.ensureDependency(root, "typescript", {
30
+ checkWorkspace: true,
22
31
  exec: (cmd, opts) => this.utils.exec(cmd, opts),
23
32
  });
33
+
24
34
  await this.utils.exec("tsc --noEmit");
35
+
25
36
  this.log.info("TypeScript type checking completed successfully.");
26
37
  },
27
38
  });
@@ -1,5 +1,5 @@
1
1
  import { $inject, $use, AlephaError } from "alepha";
2
- import { FileSystemProvider } from "alepha/file";
2
+ import { FileSystemProvider } from "alepha/system";
3
3
  import { appEntryOptions } from "../atoms/appEntryOptions.ts";
4
4
 
5
5
  /**
@@ -1,59 +1,17 @@
1
- import { $hook, $inject, type Alepha, AlephaError } from "alepha";
2
- import { importVite } from "alepha/vite";
3
- import type { InlineConfig, ViteDevServer } from "vite";
1
+ import { $inject, type Alepha, AlephaError } from "alepha";
2
+ import { ViteUtils } from "../services/ViteUtils.ts";
4
3
  import type { AppEntry } from "./AppEntryProvider.ts";
5
- import { ViteTemplateProvider } from "./ViteTemplateProvider.ts";
6
4
 
7
5
  export class ViteBuildProvider {
8
6
  protected alepha?: Alepha;
9
7
  protected appEntry?: AppEntry;
10
- protected viteDevServer?: ViteDevServer;
11
- protected readonly templateProvider = $inject(ViteTemplateProvider);
12
-
13
- /**
14
- * We need to close the Vite dev server after build is done.
15
- */
16
- protected onReady = $hook({
17
- on: "ready",
18
- priority: "last",
19
- handler: async () => {
20
- await this.viteDevServer?.close();
21
- },
22
- });
23
- protected onStop = $hook({
24
- on: "stop",
25
- handler: async () => {
26
- await this.viteDevServer?.close();
27
- },
28
- });
8
+ protected readonly viteUtils = $inject(ViteUtils);
29
9
 
30
10
  public async init(opts: { entry: AppEntry }) {
31
- const { createServer } = await importVite();
32
-
33
- process.env.ALEPHA_CLI_IMPORT = "true"; // signal Alepha App about CLI import, run(alepha) won't start server
34
- process.env.NODE_ENV = "production"; // force Alepha App in production mode for getting "production" metadata
35
- process.env.LOG_LEVEL ??= "warn"; // reduce log noise
36
-
37
- /**
38
- * 01/26 Vite 7
39
- * "runnerImport" doesn't work as expected here. (e.g. build docs fail)
40
- * -> We still use devServer and ssrLoadModule for now.
41
- * -> This is clearly a bad stuff, we need to find better way.
42
- */
43
- this.viteDevServer = await createServer({
44
- server: { middlewareMode: true },
45
- appType: "custom",
46
- logLevel: "silent",
47
- } satisfies InlineConfig);
48
-
49
- await this.viteDevServer.ssrLoadModule(opts.entry.server);
50
-
51
- const alepha: Alepha = (globalThis as any).__alepha;
52
- if (!alepha) {
53
- throw new AlephaError(
54
- "Alepha instance not found after loading entry module",
55
- );
56
- }
11
+ const alepha = await this.viteUtils.runAlepha({
12
+ entry: opts.entry,
13
+ mode: "production",
14
+ });
57
15
 
58
16
  this.alepha = alepha;
59
17
  this.appEntry = opts.entry;
@@ -77,6 +35,6 @@ export class ViteBuildProvider {
77
35
  if (!this.appEntry) {
78
36
  throw new AlephaError("ViteBuildProvider not initialized");
79
37
  }
80
- return this.templateProvider.generateIndexHtml(this.appEntry);
38
+ return this.viteUtils.generateIndexHtml(this.appEntry);
81
39
  }
82
40
  }
@@ -1,10 +1,9 @@
1
1
  import { $inject, type Alepha, AlephaError } from "alepha";
2
- import { FileSystemProvider } from "alepha/file";
3
2
  import { $logger } from "alepha/logger";
3
+ import { FileSystemProvider } from "alepha/system";
4
4
  import { importVite, importViteReact, viteAlephaSsrPreload } from "alepha/vite";
5
5
  import type { InlineConfig, Plugin, ViteDevServer } from "vite";
6
6
  import type { AppEntry } from "./AppEntryProvider.ts";
7
- import { ViteTemplateProvider } from "./ViteTemplateProvider.ts";
8
7
 
9
8
  export interface ViteDevServerOptions {
10
9
  /**
@@ -49,7 +48,6 @@ export interface ViteDevServerOptions {
49
48
  export class ViteDevServerProvider {
50
49
  protected readonly log = $logger();
51
50
  protected readonly fs = $inject(FileSystemProvider);
52
- protected readonly templateProvider = $inject(ViteTemplateProvider);
53
51
  protected server!: ViteDevServer;
54
52
  protected options!: ViteDevServerOptions;
55
53
  protected alepha: Alepha | null = null;
@@ -176,6 +174,11 @@ export class ViteDevServerProvider {
176
174
  const mode = process.env.NODE_ENV || "development";
177
175
  const env = loadEnv(mode, this.options.root, "");
178
176
 
177
+ // Merge into process.env (only set if not already defined)
178
+ for (const [key, value] of Object.entries(env)) {
179
+ process.env[key] ??= value;
180
+ }
181
+
179
182
  process.env.NODE_ENV ??= "development";
180
183
  process.env.VITE_ALEPHA_DEV = "true";
181
184
  process.env.SERVER_HOST ??= this.options.host?.toString() ?? "localhost";
@@ -183,11 +186,6 @@ export class ViteDevServerProvider {
183
186
  this.options.port ??
184
187
  (process.env.SERVER_PORT ? Number(process.env.SERVER_PORT) : 3000),
185
188
  );
186
-
187
- // Merge into process.env (only set if not already defined)
188
- for (const [key, value] of Object.entries(env)) {
189
- process.env[key] ??= value;
190
- }
191
189
  }
192
190
 
193
191
  /**
@@ -240,20 +238,13 @@ export class ViteDevServerProvider {
240
238
  }
241
239
 
242
240
  /**
243
- * Setup Alepha instance with Vite middleware and template.
241
+ * Setup Alepha instance with Vite middleware.
244
242
  */
245
243
  protected async setupAlepha(): Promise<void> {
246
244
  if (!this.alepha || !this.hasReact()) {
247
245
  return;
248
246
  }
249
247
 
250
- const template = await this.server.transformIndexHtml(
251
- "/",
252
- this.templateProvider.generateIndexHtml(this.options.entry),
253
- );
254
-
255
- this.alepha.store.set("alepha.react.server.template", template);
256
-
257
248
  this.alepha.events.on("server:onRequest", {
258
249
  priority: "first",
259
250
  callback: async ({ request }) => {
@@ -299,6 +290,11 @@ export class ViteDevServerProvider {
299
290
  res: any,
300
291
  ctx: { metadata: any },
301
292
  ): Promise<boolean> {
293
+ // Skip if response already started
294
+ if (res.headersSent || res.writableEnded) {
295
+ return false;
296
+ }
297
+
302
298
  return new Promise((resolve) => {
303
299
  let resolved = false;
304
300
 
@@ -309,6 +305,29 @@ export class ViteDevServerProvider {
309
305
  resolve(handled);
310
306
  };
311
307
 
308
+ // Wrap response to prevent writes after we've resolved
309
+ const originalSetHeader = res.setHeader.bind(res);
310
+ const originalWriteHead = res.writeHead?.bind(res);
311
+ const originalWrite = res.write.bind(res);
312
+ const originalEnd = res.end.bind(res);
313
+
314
+ const guardedCall = <T>(fn: (...args: any[]) => T, ...args: any[]): T => {
315
+ if (resolved && !ctx.metadata.vite) {
316
+ // Vite didn't handle this request, silently ignore late writes
317
+ return undefined as T;
318
+ }
319
+ return fn(...args);
320
+ };
321
+
322
+ res.setHeader = (...args: any[]) =>
323
+ guardedCall(originalSetHeader, ...args);
324
+ if (originalWriteHead) {
325
+ res.writeHead = (...args: any[]) =>
326
+ guardedCall(originalWriteHead, ...args);
327
+ }
328
+ res.write = (...args: any[]) => guardedCall(originalWrite, ...args);
329
+ res.end = (...args: any[]) => guardedCall(originalEnd, ...args);
330
+
312
331
  res.on("finish", () => done(true));
313
332
  res.on("close", () => res.headersSent && done(true));
314
333