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