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,9 +1,37 @@
1
1
  import { $inject, Alepha } from "alepha";
2
2
  import type { RunnerMethod } from "alepha/command";
3
- import { FileSystemProvider } from "alepha/file";
4
3
  import { $logger } from "alepha/logger";
4
+ import alephaPackageJson from "alepha/package.json" with { type: "json" };
5
+ import { FileSystemProvider } from "alepha/system";
5
6
  import { version } from "../version.ts";
6
7
 
8
+ /**
9
+ * Context information about a workspace root.
10
+ * Used when initializing a package inside a monorepo.
11
+ */
12
+ export interface WorkspaceContext {
13
+ /**
14
+ * Whether we're inside a workspace package.
15
+ */
16
+ isPackage: boolean;
17
+ /**
18
+ * The workspace root directory (e.g., ../.. from packages/my-pkg).
19
+ */
20
+ workspaceRoot: string | null;
21
+ /**
22
+ * Package manager detected at workspace root.
23
+ */
24
+ packageManager: "yarn" | "pnpm" | "npm" | "bun" | null;
25
+ /**
26
+ * Config files present at workspace root.
27
+ */
28
+ config: {
29
+ biomeJson: boolean;
30
+ editorconfig: boolean;
31
+ tsconfigJson: boolean;
32
+ };
33
+ }
34
+
7
35
  /**
8
36
  * Utility service for package manager operations.
9
37
  *
@@ -23,12 +51,9 @@ export class PackageManagerUtils {
23
51
  */
24
52
  public async getPackageManager(
25
53
  root: string,
26
- flags?: { yarn?: boolean; pnpm?: boolean; npm?: boolean; bun?: boolean },
54
+ pm?: "yarn" | "pnpm" | "npm" | "bun",
27
55
  ): Promise<"yarn" | "pnpm" | "npm" | "bun"> {
28
- if (flags?.yarn) return "yarn";
29
- if (flags?.pnpm) return "pnpm";
30
- if (flags?.npm) return "npm";
31
- if (flags?.bun) return "bun";
56
+ if (pm) return pm;
32
57
  if (this.alepha.isBun()) return "bun";
33
58
  if (await this.fs.exists(this.fs.join(root, "bun.lock"))) return "bun";
34
59
  if (await this.fs.exists(this.fs.join(root, "yarn.lock"))) return "yarn";
@@ -37,6 +62,60 @@ export class PackageManagerUtils {
37
62
  return "npm";
38
63
  }
39
64
 
65
+ /**
66
+ * Detect workspace context when inside a monorepo package.
67
+ *
68
+ * Checks if we're inside a workspace package (e.g., packages/my-pkg or apps/my-app)
69
+ * by looking 2 levels up for workspace indicators like lockfiles and config files.
70
+ *
71
+ * @param root - The current package directory
72
+ * @returns Workspace context with root path, PM, and config presence
73
+ */
74
+ public async getWorkspaceContext(root: string): Promise<WorkspaceContext> {
75
+ // Workspace root is 2 levels up (e.g., packages/my-pkg → ..)
76
+ const workspaceRoot = this.fs.join(root, "..", "..");
77
+
78
+ // Check for lockfiles to detect PM
79
+ const [hasYarnLock, hasPnpmLock, hasNpmLock, hasBunLock] =
80
+ await Promise.all([
81
+ this.fs.exists(this.fs.join(workspaceRoot, "yarn.lock")),
82
+ this.fs.exists(this.fs.join(workspaceRoot, "pnpm-lock.yaml")),
83
+ this.fs.exists(this.fs.join(workspaceRoot, "package-lock.json")),
84
+ this.fs.exists(this.fs.join(workspaceRoot, "bun.lock")),
85
+ ]);
86
+
87
+ // Check for config files
88
+ const [hasBiome, hasEditorConfig, hasTsConfig, hasWorkspacePackageJson] =
89
+ await Promise.all([
90
+ this.fs.exists(this.fs.join(workspaceRoot, "biome.json")),
91
+ this.fs.exists(this.fs.join(workspaceRoot, ".editorconfig")),
92
+ this.fs.exists(this.fs.join(workspaceRoot, "tsconfig.json")),
93
+ this.fs.exists(this.fs.join(workspaceRoot, "package.json")),
94
+ ]);
95
+
96
+ // Determine if this looks like a workspace root
97
+ const hasLockfile = hasYarnLock || hasPnpmLock || hasNpmLock || hasBunLock;
98
+ const isPackage = hasLockfile && hasWorkspacePackageJson;
99
+
100
+ // Detect package manager from lockfile
101
+ let packageManager: "yarn" | "pnpm" | "npm" | "bun" | null = null;
102
+ if (hasYarnLock) packageManager = "yarn";
103
+ else if (hasPnpmLock) packageManager = "pnpm";
104
+ else if (hasBunLock) packageManager = "bun";
105
+ else if (hasNpmLock) packageManager = "npm";
106
+
107
+ return {
108
+ isPackage,
109
+ workspaceRoot: isPackage ? workspaceRoot : null,
110
+ packageManager,
111
+ config: {
112
+ biomeJson: hasBiome,
113
+ editorconfig: hasEditorConfig,
114
+ tsconfigJson: hasTsConfig,
115
+ },
116
+ };
117
+ }
118
+
40
119
  /**
41
120
  * Get the install command for a package.
42
121
  */
@@ -98,12 +177,17 @@ export class PackageManagerUtils {
98
177
 
99
178
  /**
100
179
  * Install a dependency if it's missing from the project.
180
+ * Optionally checks workspace root for the dependency in monorepo setups.
101
181
  */
102
182
  public async ensureDependency(
103
183
  root: string,
104
184
  packageName: string,
105
185
  options: {
106
186
  dev?: boolean;
187
+ /**
188
+ * Also check workspace root for the dependency (for monorepo setups).
189
+ */
190
+ checkWorkspace?: boolean;
107
191
  run?: RunnerMethod;
108
192
  exec?: (
109
193
  cmd: string,
@@ -111,13 +195,27 @@ export class PackageManagerUtils {
111
195
  ) => Promise<void>;
112
196
  } = {},
113
197
  ): Promise<void> {
114
- const { dev = true } = options;
198
+ const { dev = true, checkWorkspace = false } = options;
115
199
 
200
+ // Check current package
116
201
  if (await this.hasDependency(root, packageName)) {
117
202
  this.log.debug(`Dependency '${packageName}' is already installed`);
118
203
  return;
119
204
  }
120
205
 
206
+ // Check workspace root (for monorepo setups)
207
+ if (checkWorkspace) {
208
+ const workspace = await this.getWorkspaceContext(root);
209
+ if (workspace.workspaceRoot) {
210
+ if (await this.hasDependency(workspace.workspaceRoot, packageName)) {
211
+ this.log.debug(
212
+ `Dependency '${packageName}' is already installed in workspace root`,
213
+ );
214
+ return;
215
+ }
216
+ }
217
+ }
218
+
121
219
  const cmd = await this.getInstallCommand(root, packageName, dev);
122
220
 
123
221
  if (options.run) {
@@ -254,12 +352,22 @@ export class PackageManagerUtils {
254
352
  scripts: Record<string, string>;
255
353
  type: "module";
256
354
  } {
355
+ const alephaDeps = alephaPackageJson.devDependencies;
356
+
257
357
  const dependencies: Record<string, string> = {
258
358
  alepha: `^${version}`,
259
359
  };
260
360
 
261
361
  const devDependencies: Record<string, string> = {};
262
362
 
363
+ // Add biome/vitest only if not a workspace package (workspace root has them)
364
+ if (!modes.isPackage) {
365
+ devDependencies["@biomejs/biome"] = alephaDeps["@biomejs/biome"];
366
+ if (modes.test) {
367
+ devDependencies.vitest = alephaDeps.vitest;
368
+ }
369
+ }
370
+
263
371
  const scripts: Record<string, string> = {
264
372
  dev: "alepha dev",
265
373
  build: "alepha build",
@@ -268,16 +376,19 @@ export class PackageManagerUtils {
268
376
  verify: "alepha verify",
269
377
  };
270
378
 
379
+ if (modes.test) {
380
+ scripts.test = "vitest run";
381
+ }
382
+
271
383
  if (modes.ui) {
272
384
  dependencies["@alepha/ui"] = `^${version}`;
273
385
  modes.react = true;
274
386
  }
275
387
 
276
388
  if (modes.react) {
277
- dependencies["@alepha/react"] = `^${version}`;
278
- dependencies.react = "^19.2.0";
279
- dependencies["react-dom"] = "^19.2.0";
280
- devDependencies["@types/react"] = "^19.2.0";
389
+ dependencies.react = alephaDeps.react;
390
+ dependencies["react-dom"] = alephaDeps["react-dom"];
391
+ devDependencies["@types/react"] = alephaDeps["@types/react"];
281
392
  }
282
393
 
283
394
  return {
@@ -305,4 +416,9 @@ export interface DependencyModes {
305
416
  react?: boolean;
306
417
  ui?: boolean;
307
418
  expo?: boolean;
419
+ test?: boolean;
420
+ /**
421
+ * Skip biome/vitest when inside a workspace package (they're at root).
422
+ */
423
+ isPackage?: boolean;
308
424
  }
@@ -1,20 +1,26 @@
1
1
  import { basename, dirname } from "node:path";
2
2
  import { $inject } from "alepha";
3
- import { FileSystemProvider } from "alepha/file";
4
3
  import { $logger } from "alepha/logger";
5
- import { apiHelloControllerTs } from "../assets/apiHelloControllerTs.ts";
6
- import { apiIndexTs } from "../assets/apiIndexTs.ts";
7
- import { biomeJson } from "../assets/biomeJson.ts";
8
- import { type ClaudeMdOptions, claudeMd } from "../assets/claudeMd.ts";
9
- import { dummySpecTs } from "../assets/dummySpecTs.ts";
10
- import { editorconfig } from "../assets/editorconfig.ts";
11
- import { mainBrowserTs } from "../assets/mainBrowserTs.ts";
12
- import { mainCss } from "../assets/mainCss.ts";
13
- import { mainServerTs } from "../assets/mainServerTs.ts";
14
- import { tsconfigJson } from "../assets/tsconfigJson.ts";
15
- import { webAppRouterTs } from "../assets/webAppRouterTs.ts";
16
- import { webHelloComponentTsx } from "../assets/webHelloComponentTsx.ts";
17
- import { webIndexTs } from "../assets/webIndexTs.ts";
4
+ import { FileSystemProvider } from "alepha/system";
5
+ import {
6
+ type AgentMdOptions,
7
+ type AgentMdType,
8
+ agentMd,
9
+ } from "../templates/agentMd.ts";
10
+ import { apiHelloControllerTs } from "../templates/apiHelloControllerTs.ts";
11
+ import { apiIndexTs } from "../templates/apiIndexTs.ts";
12
+ import { biomeJson } from "../templates/biomeJson.ts";
13
+ import { dummySpecTs } from "../templates/dummySpecTs.ts";
14
+ import { editorconfig } from "../templates/editorconfig.ts";
15
+ import { gitignore } from "../templates/gitignore.ts";
16
+ import { mainBrowserTs } from "../templates/mainBrowserTs.ts";
17
+ import { mainCss } from "../templates/mainCss.ts";
18
+ import { mainServerTs } from "../templates/mainServerTs.ts";
19
+ import { tsconfigJson } from "../templates/tsconfigJson.ts";
20
+ import { webAppRouterTs } from "../templates/webAppRouterTs.ts";
21
+ import { webHelloComponentTsx } from "../templates/webHelloComponentTsx.ts";
22
+ import { webIndexTs } from "../templates/webIndexTs.ts";
23
+ import { AlephaCliUtils } from "./AlephaCliUtils.ts";
18
24
  import {
19
25
  type DependencyModes,
20
26
  PackageManagerUtils,
@@ -33,6 +39,7 @@ export class ProjectScaffolder {
33
39
  protected readonly log = $logger();
34
40
  protected readonly fs = $inject(FileSystemProvider);
35
41
  protected readonly pm = $inject(PackageManagerUtils);
42
+ protected readonly utils = $inject(AlephaCliUtils);
36
43
 
37
44
  /**
38
45
  * Get the app name from the directory name.
@@ -55,16 +62,20 @@ export class ProjectScaffolder {
55
62
  root: string,
56
63
  opts: {
57
64
  force?: boolean;
65
+ /**
66
+ * Check workspace root for existing config files.
67
+ */
68
+ checkWorkspace?: boolean;
58
69
  packageJson?: boolean | DependencyModes;
59
70
  tsconfigJson?: boolean;
60
- indexHtml?: boolean;
61
71
  biomeJson?: boolean;
62
72
  editorconfig?: boolean;
63
- claudeMd?: boolean | ClaudeMdOptions;
73
+ agentMd?: false | (AgentMdOptions & { type: AgentMdType });
64
74
  },
65
75
  ): Promise<void> {
66
76
  const tasks: Promise<void>[] = [];
67
77
  const force = opts.force ?? false;
78
+ const checkWorkspace = opts.checkWorkspace ?? false;
68
79
 
69
80
  if (opts.packageJson) {
70
81
  tasks.push(
@@ -79,24 +90,14 @@ export class ProjectScaffolder {
79
90
  if (opts.tsconfigJson) {
80
91
  tasks.push(this.ensureTsConfig(root, { force }));
81
92
  }
82
- if (opts.indexHtml) {
83
- tasks.push(this.ensureReactProject(root, { force }));
84
- }
85
93
  if (opts.biomeJson) {
86
- tasks.push(this.ensureBiomeConfig(root, { force }));
94
+ tasks.push(this.ensureBiomeConfig(root, { force, checkWorkspace }));
87
95
  }
88
96
  if (opts.editorconfig) {
89
- tasks.push(this.ensureEditorConfig(root, { force }));
97
+ tasks.push(this.ensureEditorConfig(root, { force, checkWorkspace }));
90
98
  }
91
- if (opts.claudeMd) {
92
- tasks.push(
93
- this.ensureClaudeMd(
94
- root,
95
- typeof opts.claudeMd === "boolean"
96
- ? { force }
97
- : { ...opts.claudeMd, force },
98
- ),
99
- );
99
+ if (opts.agentMd) {
100
+ tasks.push(this.ensureAgentMd(root, { ...opts.agentMd, force }));
100
101
  }
101
102
 
102
103
  await Promise.all(tasks);
@@ -122,23 +123,95 @@ export class ProjectScaffolder {
122
123
 
123
124
  public async ensureBiomeConfig(
124
125
  root: string,
125
- opts: { force?: boolean } = {},
126
+ opts: { force?: boolean; checkWorkspace?: boolean } = {},
126
127
  ): Promise<void> {
128
+ if (
129
+ !opts.force &&
130
+ opts.checkWorkspace &&
131
+ (await this.existsInParents(root, "biome.json"))
132
+ ) {
133
+ return;
134
+ }
127
135
  await this.ensureFile(root, "biome.json", biomeJson(), opts.force);
128
136
  }
129
137
 
130
138
  public async ensureEditorConfig(
131
139
  root: string,
132
- opts: { force?: boolean } = {},
140
+ opts: { force?: boolean; checkWorkspace?: boolean } = {},
133
141
  ): Promise<void> {
142
+ if (
143
+ !opts.force &&
144
+ opts.checkWorkspace &&
145
+ (await this.existsInParents(root, ".editorconfig"))
146
+ ) {
147
+ return;
148
+ }
134
149
  await this.ensureFile(root, ".editorconfig", editorconfig(), opts.force);
135
150
  }
136
151
 
137
- public async ensureClaudeMd(
152
+ /**
153
+ * Ensure git repository is initialized with .gitignore.
154
+ *
155
+ * @returns true if git was initialized, false if already exists or git unavailable
156
+ */
157
+ public async ensureGitRepo(
138
158
  root: string,
139
- options: ClaudeMdOptions & { force?: boolean } = {},
159
+ opts: { force?: boolean } = {},
160
+ ): Promise<boolean> {
161
+ const gitDir = this.fs.join(root, ".git");
162
+
163
+ // Skip if .git already exists
164
+ if (!opts.force && (await this.fs.exists(gitDir))) {
165
+ return false;
166
+ }
167
+
168
+ // Check if git is available
169
+ const hasGit = await this.utils.isInstalledAsync("git");
170
+ if (!hasGit) {
171
+ return false;
172
+ }
173
+
174
+ // Initialize git repository
175
+ await this.utils.exec("git init", { root, global: true });
176
+
177
+ // Write .gitignore
178
+ await this.ensureFile(root, ".gitignore", gitignore(), opts.force);
179
+
180
+ return true;
181
+ }
182
+
183
+ public async ensureAgentMd(
184
+ root: string,
185
+ options: AgentMdOptions & { type: AgentMdType; force?: boolean },
140
186
  ): Promise<void> {
141
- await this.ensureFile(root, "CLAUDE.md", claudeMd(options), options.force);
187
+ const filename = options.type === "claude" ? "CLAUDE.md" : "AGENTS.md";
188
+ await this.ensureFile(
189
+ root,
190
+ filename,
191
+ agentMd(options.type, options),
192
+ options.force,
193
+ );
194
+ }
195
+
196
+ // ===========================================
197
+ // Minimal Project Structure
198
+ // ===========================================
199
+
200
+ /**
201
+ * Ensure src/main.server.ts exists with correct module imports.
202
+ */
203
+ public async ensureMainServerTs(
204
+ root: string,
205
+ opts: { api?: boolean; react?: boolean; force?: boolean } = {},
206
+ ): Promise<void> {
207
+ const srcDir = this.fs.join(root, "src");
208
+ await this.fs.mkdir(srcDir, { recursive: true });
209
+ await this.ensureFile(
210
+ srcDir,
211
+ "main.server.ts",
212
+ mainServerTs({ api: opts.api, react: opts.react }),
213
+ opts.force,
214
+ );
142
215
  }
143
216
 
144
217
  // ===========================================
@@ -146,10 +219,9 @@ export class ProjectScaffolder {
146
219
  // ===========================================
147
220
 
148
221
  /**
149
- * Ensure src/main.server.ts exists with full API structure.
222
+ * Ensure API module structure exists.
150
223
  *
151
224
  * Creates:
152
- * - src/main.server.ts (entry point)
153
225
  * - src/api/index.ts (API module)
154
226
  * - src/api/controllers/HelloController.ts (example controller)
155
227
  */
@@ -157,14 +229,6 @@ export class ProjectScaffolder {
157
229
  root: string,
158
230
  opts: { force?: boolean } = {},
159
231
  ): Promise<void> {
160
- const srcDir = this.fs.join(root, "src");
161
-
162
- // Don't overwrite existing content unless force is set
163
- if (!opts.force && (await this.fs.exists(srcDir))) {
164
- const files = await this.fs.ls(srcDir);
165
- if (files.length > 0) return;
166
- }
167
-
168
232
  const appName = this.getAppName(root);
169
233
 
170
234
  // Create directories
@@ -173,67 +237,48 @@ export class ProjectScaffolder {
173
237
  });
174
238
 
175
239
  // Create files
176
- await this.ensureFile(srcDir, "main.server.ts", mainServerTs(), opts.force);
177
240
  await this.ensureFile(
178
- srcDir,
179
- "api/index.ts",
241
+ root,
242
+ "src/api/index.ts",
180
243
  apiIndexTs({ appName }),
181
244
  opts.force,
182
245
  );
183
246
  await this.ensureFile(
184
- srcDir,
185
- "api/controllers/HelloController.ts",
247
+ root,
248
+ "src/api/controllers/HelloController.ts",
186
249
  apiHelloControllerTs(),
187
250
  opts.force,
188
251
  );
189
252
  }
190
253
 
191
254
  // ===========================================
192
- // React Project Structure
255
+ // Web Project Structure
193
256
  // ===========================================
194
257
 
195
258
  /**
196
- * Ensure full React project structure exists.
259
+ * Ensure web/React project structure exists.
197
260
  *
198
261
  * Creates:
199
- * - src/main.server.ts, src/main.browser.ts
200
- * - src/api/index.ts, src/api/controllers/HelloController.ts
262
+ * - src/main.browser.ts
263
+ * - src/main.css
201
264
  * - src/web/index.ts, src/web/AppRouter.ts, src/web/components/Hello.tsx
202
265
  */
203
- public async ensureReactProject(
266
+ public async ensureWebProject(
204
267
  root: string,
205
- opts: { force?: boolean } = {},
268
+ opts: { api?: boolean; ui?: boolean; force?: boolean } = {},
206
269
  ): Promise<void> {
207
270
  const appName = this.getAppName(root);
208
271
 
209
272
  // Create directories
210
- await this.fs.mkdir(this.fs.join(root, "src/api/controllers"), {
211
- recursive: true,
212
- });
213
273
  await this.fs.mkdir(this.fs.join(root, "src/web/components"), {
214
274
  recursive: true,
215
275
  });
216
276
 
217
277
  // src/main.css
218
- await this.ensureFile(root, "src/main.css", mainCss(), opts.force);
219
-
220
- // API structure
221
- await this.ensureFile(
222
- root,
223
- "src/api/index.ts",
224
- apiIndexTs({ appName }),
225
- opts.force,
226
- );
227
- await this.ensureFile(
228
- root,
229
- "src/api/controllers/HelloController.ts",
230
- apiHelloControllerTs(),
231
- opts.force,
232
- );
233
278
  await this.ensureFile(
234
279
  root,
235
- "src/main.server.ts",
236
- mainServerTs({ react: true }),
280
+ "src/main.css",
281
+ mainCss({ ui: opts.ui }),
237
282
  opts.force,
238
283
  );
239
284
 
@@ -247,7 +292,7 @@ export class ProjectScaffolder {
247
292
  await this.ensureFile(
248
293
  root,
249
294
  "src/web/AppRouter.ts",
250
- webAppRouterTs(),
295
+ webAppRouterTs({ api: opts.api, ui: opts.ui }),
251
296
  opts.force,
252
297
  );
253
298
  await this.ensureFile(
@@ -0,0 +1,82 @@
1
+ import { $hook, $inject, type Alepha, AlephaError } from "alepha";
2
+ import { importVite } from "alepha/vite";
3
+ import type { InlineConfig, ViteDevServer } from "vite";
4
+ import { FileSystemProvider } from "../../system/index.ts";
5
+ import type { AppEntry } from "../providers/AppEntryProvider.ts";
6
+
7
+ export class ViteUtils {
8
+ protected readonly fs = $inject(FileSystemProvider);
9
+ protected viteDevServer?: ViteDevServer;
10
+
11
+ public generateIndexHtml(entry: AppEntry): string {
12
+ const style = entry.style;
13
+ const browser = entry.browser ?? entry.server;
14
+ return `
15
+ <!DOCTYPE html>
16
+ <html lang="en">
17
+ <head>
18
+ <meta charset="UTF-8" />
19
+ <title>App</title>
20
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
21
+ ${style ? `<link rel="stylesheet" href="/${style}" />` : ""}
22
+ </head>
23
+ <body>
24
+ <div id="root"></div>
25
+ <script type="module" src="/${browser}"></script>
26
+ </body>
27
+ </html>
28
+ `.trim();
29
+ }
30
+
31
+ /**
32
+ * We need to close the Vite dev server after build is done.
33
+ */
34
+ protected onReady = $hook({
35
+ on: "ready",
36
+ priority: "last",
37
+ handler: async () => {
38
+ await this.viteDevServer?.close();
39
+ },
40
+ });
41
+
42
+ protected onStop = $hook({
43
+ on: "stop",
44
+ handler: async () => {
45
+ await this.viteDevServer?.close();
46
+ },
47
+ });
48
+
49
+ public async runAlepha(opts: {
50
+ entry: AppEntry;
51
+ mode: "production" | "development";
52
+ }): Promise<Alepha> {
53
+ const { createServer } = await importVite();
54
+
55
+ process.env.NODE_ENV = opts.mode;
56
+ process.env.ALEPHA_CLI_IMPORT = "true"; // signal Alepha App about CLI import, run(alepha) won't start server
57
+ process.env.LOG_LEVEL ??= "warn"; // reduce log noise
58
+
59
+ /**
60
+ * 01/26 Vite 7
61
+ * "runnerImport" doesn't work as expected here. (e.g. build docs fail)
62
+ * -> We still use devServer and ssrLoadModule for now.
63
+ * -> This is clearly a bad stuff, we need to find better way.
64
+ */
65
+ this.viteDevServer = await createServer({
66
+ server: { middlewareMode: true },
67
+ appType: "custom",
68
+ logLevel: "silent",
69
+ } satisfies InlineConfig);
70
+
71
+ await this.viteDevServer.ssrLoadModule(opts.entry.server);
72
+
73
+ const alepha: Alepha = (globalThis as any).__alepha;
74
+ if (!alepha) {
75
+ throw new AlephaError(
76
+ "Alepha instance not found after loading entry module",
77
+ );
78
+ }
79
+
80
+ return alepha;
81
+ }
82
+ }