alepha 0.15.1 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. package/README.md +68 -80
  2. package/dist/api/audits/index.d.ts +10 -33
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +10 -33
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +10 -3
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +10 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +162 -155
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.d.ts +10 -4
  19. package/dist/api/notifications/index.d.ts.map +1 -1
  20. package/dist/api/notifications/index.js +10 -4
  21. package/dist/api/notifications/index.js.map +1 -1
  22. package/dist/api/parameters/index.d.ts +43 -50
  23. package/dist/api/parameters/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.js +30 -37
  25. package/dist/api/parameters/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +1081 -760
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2539 -218
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts +138 -132
  31. package/dist/api/verifications/index.d.ts.map +1 -1
  32. package/dist/api/verifications/index.js +12 -4
  33. package/dist/api/verifications/index.js.map +1 -1
  34. package/dist/batch/index.d.ts +20 -40
  35. package/dist/batch/index.d.ts.map +1 -1
  36. package/dist/batch/index.js +31 -44
  37. package/dist/batch/index.js.map +1 -1
  38. package/dist/bucket/index.d.ts +440 -8
  39. package/dist/bucket/index.d.ts.map +1 -1
  40. package/dist/bucket/index.js +1861 -12
  41. package/dist/bucket/index.js.map +1 -1
  42. package/dist/cache/core/index.d.ts +179 -7
  43. package/dist/cache/core/index.d.ts.map +1 -1
  44. package/dist/cache/core/index.js +213 -7
  45. package/dist/cache/core/index.js.map +1 -1
  46. package/dist/cache/redis/index.d.ts +1 -0
  47. package/dist/cache/redis/index.d.ts.map +1 -1
  48. package/dist/cache/redis/index.js +4 -0
  49. package/dist/cache/redis/index.js.map +1 -1
  50. package/dist/cli/index.d.ts +638 -5645
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +2550 -368
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/command/index.d.ts +203 -45
  55. package/dist/command/index.d.ts.map +1 -1
  56. package/dist/command/index.js +2060 -71
  57. package/dist/command/index.js.map +1 -1
  58. package/dist/core/index.browser.js +70 -40
  59. package/dist/core/index.browser.js.map +1 -1
  60. package/dist/core/index.d.ts +34 -13
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +90 -40
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/index.native.js +70 -40
  65. package/dist/core/index.native.js.map +1 -1
  66. package/dist/datetime/index.d.ts +15 -0
  67. package/dist/datetime/index.d.ts.map +1 -1
  68. package/dist/datetime/index.js +15 -0
  69. package/dist/datetime/index.js.map +1 -1
  70. package/dist/email/index.d.ts +323 -20
  71. package/dist/email/index.d.ts.map +1 -1
  72. package/dist/email/index.js +1857 -7
  73. package/dist/email/index.js.map +1 -1
  74. package/dist/fake/index.d.ts +90 -8
  75. package/dist/fake/index.d.ts.map +1 -1
  76. package/dist/fake/index.js +91 -20
  77. package/dist/fake/index.js.map +1 -1
  78. package/dist/lock/core/index.d.ts +11 -4
  79. package/dist/lock/core/index.d.ts.map +1 -1
  80. package/dist/lock/core/index.js +11 -4
  81. package/dist/lock/core/index.js.map +1 -1
  82. package/dist/logger/index.d.ts +17 -66
  83. package/dist/logger/index.d.ts.map +1 -1
  84. package/dist/logger/index.js +14 -63
  85. package/dist/logger/index.js.map +1 -1
  86. package/dist/mcp/index.d.ts +10 -30
  87. package/dist/mcp/index.d.ts.map +1 -1
  88. package/dist/mcp/index.js +12 -35
  89. package/dist/mcp/index.js.map +1 -1
  90. package/dist/orm/index.browser.js +3 -3
  91. package/dist/orm/index.browser.js.map +1 -1
  92. package/dist/orm/index.bun.js +39 -20
  93. package/dist/orm/index.bun.js.map +1 -1
  94. package/dist/orm/index.d.ts +517 -540
  95. package/dist/orm/index.d.ts.map +1 -1
  96. package/dist/orm/index.js +58 -71
  97. package/dist/orm/index.js.map +1 -1
  98. package/dist/queue/core/index.d.ts +18 -10
  99. package/dist/queue/core/index.d.ts.map +1 -1
  100. package/dist/queue/core/index.js +14 -6
  101. package/dist/queue/core/index.js.map +1 -1
  102. package/dist/react/auth/index.browser.js +108 -0
  103. package/dist/react/auth/index.browser.js.map +1 -0
  104. package/dist/react/auth/index.d.ts +100 -0
  105. package/dist/react/auth/index.d.ts.map +1 -0
  106. package/dist/react/auth/index.js +145 -0
  107. package/dist/react/auth/index.js.map +1 -0
  108. package/dist/react/core/index.d.ts +469 -0
  109. package/dist/react/core/index.d.ts.map +1 -0
  110. package/dist/react/core/index.js +464 -0
  111. package/dist/react/core/index.js.map +1 -0
  112. package/dist/react/form/index.d.ts +232 -0
  113. package/dist/react/form/index.d.ts.map +1 -0
  114. package/dist/react/form/index.js +432 -0
  115. package/dist/react/form/index.js.map +1 -0
  116. package/dist/react/head/index.browser.js +423 -0
  117. package/dist/react/head/index.browser.js.map +1 -0
  118. package/dist/react/head/index.d.ts +288 -0
  119. package/dist/react/head/index.d.ts.map +1 -0
  120. package/dist/react/head/index.js +465 -0
  121. package/dist/react/head/index.js.map +1 -0
  122. package/dist/react/i18n/index.d.ts +175 -0
  123. package/dist/react/i18n/index.d.ts.map +1 -0
  124. package/dist/react/i18n/index.js +224 -0
  125. package/dist/react/i18n/index.js.map +1 -0
  126. package/dist/react/router/index.browser.js +1974 -0
  127. package/dist/react/router/index.browser.js.map +1 -0
  128. package/dist/react/router/index.d.ts +1956 -0
  129. package/dist/react/router/index.d.ts.map +1 -0
  130. package/dist/react/router/index.js +4722 -0
  131. package/dist/react/router/index.js.map +1 -0
  132. package/dist/react/websocket/index.d.ts +117 -0
  133. package/dist/react/websocket/index.d.ts.map +1 -0
  134. package/dist/react/websocket/index.js +107 -0
  135. package/dist/react/websocket/index.js.map +1 -0
  136. package/dist/redis/index.bun.js +4 -0
  137. package/dist/redis/index.bun.js.map +1 -1
  138. package/dist/redis/index.d.ts +41 -44
  139. package/dist/redis/index.d.ts.map +1 -1
  140. package/dist/redis/index.js +16 -25
  141. package/dist/redis/index.js.map +1 -1
  142. package/dist/retry/index.d.ts +11 -2
  143. package/dist/retry/index.d.ts.map +1 -1
  144. package/dist/retry/index.js +11 -2
  145. package/dist/retry/index.js.map +1 -1
  146. package/dist/scheduler/index.d.ts +11 -2
  147. package/dist/scheduler/index.d.ts.map +1 -1
  148. package/dist/scheduler/index.js +11 -2
  149. package/dist/scheduler/index.js.map +1 -1
  150. package/dist/security/index.d.ts +140 -49
  151. package/dist/security/index.d.ts.map +1 -1
  152. package/dist/security/index.js +164 -32
  153. package/dist/security/index.js.map +1 -1
  154. package/dist/server/auth/index.d.ts +12 -7
  155. package/dist/server/auth/index.d.ts.map +1 -1
  156. package/dist/server/auth/index.js +12 -7
  157. package/dist/server/auth/index.js.map +1 -1
  158. package/dist/server/cache/index.d.ts +7 -22
  159. package/dist/server/cache/index.d.ts.map +1 -1
  160. package/dist/server/cache/index.js +7 -22
  161. package/dist/server/cache/index.js.map +1 -1
  162. package/dist/server/compress/index.d.ts +10 -2
  163. package/dist/server/compress/index.d.ts.map +1 -1
  164. package/dist/server/compress/index.js +10 -2
  165. package/dist/server/compress/index.js.map +1 -1
  166. package/dist/server/cookies/index.d.ts +40 -16
  167. package/dist/server/cookies/index.d.ts.map +1 -1
  168. package/dist/server/cookies/index.js +7 -5
  169. package/dist/server/cookies/index.js.map +1 -1
  170. package/dist/server/core/index.d.ts +124 -23
  171. package/dist/server/core/index.d.ts.map +1 -1
  172. package/dist/server/core/index.js +231 -14
  173. package/dist/server/core/index.js.map +1 -1
  174. package/dist/server/cors/index.d.ts +13 -23
  175. package/dist/server/cors/index.d.ts.map +1 -1
  176. package/dist/server/cors/index.js +7 -21
  177. package/dist/server/cors/index.js.map +1 -1
  178. package/dist/server/health/index.d.ts +8 -2
  179. package/dist/server/health/index.d.ts.map +1 -1
  180. package/dist/server/health/index.js +8 -2
  181. package/dist/server/health/index.js.map +1 -1
  182. package/dist/server/helmet/index.d.ts +11 -3
  183. package/dist/server/helmet/index.d.ts.map +1 -1
  184. package/dist/server/helmet/index.js +11 -3
  185. package/dist/server/helmet/index.js.map +1 -1
  186. package/dist/server/links/index.d.ts +11 -6
  187. package/dist/server/links/index.d.ts.map +1 -1
  188. package/dist/server/links/index.js +11 -6
  189. package/dist/server/links/index.js.map +1 -1
  190. package/dist/server/metrics/index.d.ts +10 -3
  191. package/dist/server/metrics/index.d.ts.map +1 -1
  192. package/dist/server/metrics/index.js +10 -3
  193. package/dist/server/metrics/index.js.map +1 -1
  194. package/dist/server/multipart/index.d.ts +9 -3
  195. package/dist/server/multipart/index.d.ts.map +1 -1
  196. package/dist/server/multipart/index.js +9 -3
  197. package/dist/server/multipart/index.js.map +1 -1
  198. package/dist/server/proxy/index.d.ts +8 -2
  199. package/dist/server/proxy/index.d.ts.map +1 -1
  200. package/dist/server/proxy/index.js +8 -2
  201. package/dist/server/proxy/index.js.map +1 -1
  202. package/dist/server/rate-limit/index.d.ts +30 -35
  203. package/dist/server/rate-limit/index.d.ts.map +1 -1
  204. package/dist/server/rate-limit/index.js +18 -55
  205. package/dist/server/rate-limit/index.js.map +1 -1
  206. package/dist/server/static/index.d.ts +137 -4
  207. package/dist/server/static/index.d.ts.map +1 -1
  208. package/dist/server/static/index.js +1853 -5
  209. package/dist/server/static/index.js.map +1 -1
  210. package/dist/server/swagger/index.d.ts +309 -6
  211. package/dist/server/swagger/index.d.ts.map +1 -1
  212. package/dist/server/swagger/index.js +1854 -6
  213. package/dist/server/swagger/index.js.map +1 -1
  214. package/dist/sms/index.d.ts +309 -7
  215. package/dist/sms/index.d.ts.map +1 -1
  216. package/dist/sms/index.js +1856 -7
  217. package/dist/sms/index.js.map +1 -1
  218. package/dist/system/index.browser.js +1218 -0
  219. package/dist/system/index.browser.js.map +1 -0
  220. package/dist/{file → system}/index.d.ts +343 -16
  221. package/dist/system/index.d.ts.map +1 -0
  222. package/dist/{file → system}/index.js +419 -22
  223. package/dist/system/index.js.map +1 -0
  224. package/dist/thread/index.d.ts +11 -2
  225. package/dist/thread/index.d.ts.map +1 -1
  226. package/dist/thread/index.js +11 -2
  227. package/dist/thread/index.js.map +1 -1
  228. package/dist/topic/core/index.d.ts +12 -5
  229. package/dist/topic/core/index.d.ts.map +1 -1
  230. package/dist/topic/core/index.js +12 -5
  231. package/dist/topic/core/index.js.map +1 -1
  232. package/dist/vite/index.d.ts +5 -6272
  233. package/dist/vite/index.d.ts.map +1 -1
  234. package/dist/vite/index.js +23 -10
  235. package/dist/vite/index.js.map +1 -1
  236. package/dist/websocket/index.d.ts +12 -8
  237. package/dist/websocket/index.d.ts.map +1 -1
  238. package/dist/websocket/index.js +12 -8
  239. package/dist/websocket/index.js.map +1 -1
  240. package/package.json +82 -11
  241. package/src/api/audits/index.ts +10 -33
  242. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  243. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  244. package/src/api/files/controllers/FileController.spec.ts +1 -1
  245. package/src/api/files/index.ts +10 -3
  246. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  247. package/src/api/files/services/FileService.spec.ts +1 -1
  248. package/src/api/jobs/index.ts +10 -3
  249. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  250. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  251. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  252. package/src/api/keys/index.ts +49 -0
  253. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  254. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  255. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  256. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  257. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  258. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  259. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  260. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  261. package/src/api/keys/services/ApiKeyService.ts +306 -0
  262. package/src/api/logs/TODO.md +55 -0
  263. package/src/api/notifications/index.ts +10 -4
  264. package/src/api/parameters/index.ts +9 -30
  265. package/src/api/parameters/primitives/$config.ts +12 -4
  266. package/src/api/parameters/services/ConfigStore.ts +9 -3
  267. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  268. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  269. package/src/api/users/index.ts +14 -3
  270. package/src/api/users/primitives/$realm.ts +33 -5
  271. package/src/api/users/providers/RealmProvider.ts +1 -12
  272. package/src/api/users/services/SessionService.ts +1 -1
  273. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  274. package/src/api/verifications/index.ts +10 -4
  275. package/src/batch/index.ts +9 -36
  276. package/src/batch/primitives/$batch.ts +0 -8
  277. package/src/batch/providers/BatchProvider.ts +29 -2
  278. package/src/bucket/__tests__/shared.ts +1 -1
  279. package/src/bucket/index.ts +13 -6
  280. package/src/bucket/primitives/$bucket.ts +1 -1
  281. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  282. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  283. package/src/cache/core/__tests__/shared.ts +30 -0
  284. package/src/cache/core/index.ts +11 -6
  285. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  286. package/src/cache/core/providers/CacheProvider.ts +17 -0
  287. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  288. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  289. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  290. package/src/cli/apps/AlephaCli.ts +1 -14
  291. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
  292. package/src/cli/atoms/buildOptions.ts +99 -9
  293. package/src/cli/commands/build.ts +150 -37
  294. package/src/cli/commands/db.ts +22 -18
  295. package/src/cli/commands/deploy.ts +1 -1
  296. package/src/cli/commands/dev.ts +1 -20
  297. package/src/cli/commands/gen/env.ts +5 -2
  298. package/src/cli/commands/gen/openapi.ts +5 -2
  299. package/src/cli/commands/init.spec.ts +588 -0
  300. package/src/cli/commands/init.ts +115 -58
  301. package/src/cli/commands/lint.ts +7 -1
  302. package/src/cli/commands/typecheck.ts +11 -0
  303. package/src/cli/providers/AppEntryProvider.ts +1 -1
  304. package/src/cli/providers/ViteBuildProvider.ts +8 -50
  305. package/src/cli/providers/ViteDevServerProvider.ts +35 -16
  306. package/src/cli/services/AlephaCliUtils.ts +52 -121
  307. package/src/cli/services/PackageManagerUtils.ts +129 -11
  308. package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
  309. package/src/cli/services/ProjectScaffolder.ts +148 -81
  310. package/src/cli/services/ViteUtils.ts +82 -0
  311. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
  312. package/src/cli/templates/apiAppSecurityTs.ts +11 -0
  313. package/src/cli/templates/apiIndexTs.ts +30 -0
  314. package/src/cli/templates/gitignore.ts +39 -0
  315. package/src/cli/{assets → templates}/mainCss.ts +11 -2
  316. package/src/cli/templates/mainServerTs.ts +33 -0
  317. package/src/cli/templates/webAppRouterTs.ts +74 -0
  318. package/src/cli/templates/webHelloComponentTsx.ts +30 -0
  319. package/src/command/helpers/Runner.spec.ts +139 -0
  320. package/src/command/helpers/Runner.ts +7 -22
  321. package/src/command/index.ts +12 -4
  322. package/src/command/providers/CliProvider.spec.ts +1392 -0
  323. package/src/command/providers/CliProvider.ts +320 -47
  324. package/src/core/Alepha.ts +34 -27
  325. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  326. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  327. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  328. package/src/core/index.shared.ts +1 -0
  329. package/src/core/index.ts +20 -0
  330. package/src/core/providers/EventManager.spec.ts +0 -71
  331. package/src/core/providers/EventManager.ts +3 -15
  332. package/src/core/providers/Json.ts +2 -14
  333. package/src/datetime/index.ts +15 -0
  334. package/src/email/index.ts +10 -5
  335. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  336. package/src/email/providers/LocalEmailProvider.ts +1 -1
  337. package/src/fake/__tests__/keyName.example.ts +1 -1
  338. package/src/fake/__tests__/keyName.spec.ts +5 -5
  339. package/src/fake/index.ts +9 -6
  340. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  341. package/src/fake/providers/FakeProvider.ts +133 -19
  342. package/src/lock/core/index.ts +11 -4
  343. package/src/logger/index.ts +17 -66
  344. package/src/mcp/index.ts +10 -27
  345. package/src/mcp/transports/SseMcpTransport.ts +0 -11
  346. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  347. package/src/orm/index.browser.ts +2 -2
  348. package/src/orm/index.bun.ts +5 -3
  349. package/src/orm/index.ts +23 -53
  350. package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
  351. package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
  352. package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
  353. package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
  354. package/src/orm/services/Repository.ts +7 -3
  355. package/src/queue/core/index.ts +14 -6
  356. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  357. package/src/react/auth/hooks/useAuth.ts +32 -0
  358. package/src/react/auth/index.browser.ts +13 -0
  359. package/src/react/auth/index.shared.ts +2 -0
  360. package/src/react/auth/index.ts +48 -0
  361. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  362. package/src/react/auth/services/ReactAuth.ts +135 -0
  363. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  364. package/src/react/core/components/ClientOnly.tsx +49 -0
  365. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  366. package/src/react/core/contexts/AlephaContext.ts +7 -0
  367. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  368. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  369. package/src/react/core/hooks/useAction.ts +480 -0
  370. package/src/react/core/hooks/useAlepha.ts +26 -0
  371. package/src/react/core/hooks/useClient.ts +17 -0
  372. package/src/react/core/hooks/useEvents.ts +51 -0
  373. package/src/react/core/hooks/useInject.ts +12 -0
  374. package/src/react/core/hooks/useStore.ts +52 -0
  375. package/src/react/core/index.ts +90 -0
  376. package/src/react/form/components/FormState.tsx +17 -0
  377. package/src/react/form/errors/FormValidationError.ts +18 -0
  378. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  379. package/src/react/form/hooks/useForm.ts +47 -0
  380. package/src/react/form/hooks/useFormState.ts +130 -0
  381. package/src/react/form/index.ts +44 -0
  382. package/src/react/form/services/FormModel.ts +614 -0
  383. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  384. package/src/react/head/helpers/SeoExpander.ts +142 -0
  385. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  386. package/src/react/head/hooks/useHead.ts +62 -0
  387. package/src/react/head/index.browser.ts +26 -0
  388. package/src/react/head/index.ts +44 -0
  389. package/src/react/head/interfaces/Head.ts +105 -0
  390. package/src/react/head/primitives/$head.ts +25 -0
  391. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  392. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  393. package/src/react/head/providers/HeadProvider.ts +168 -0
  394. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  395. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  396. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  397. package/src/react/i18n/components/Localize.tsx +35 -0
  398. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  399. package/src/react/i18n/hooks/useI18n.ts +18 -0
  400. package/src/react/i18n/index.ts +41 -0
  401. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  402. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  403. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  404. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  405. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  406. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  407. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  408. package/src/react/router/components/ErrorViewer.tsx +872 -0
  409. package/src/react/router/components/Link.tsx +23 -0
  410. package/src/react/router/components/NestedView.tsx +223 -0
  411. package/src/react/router/components/NotFound.tsx +30 -0
  412. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  413. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  414. package/src/react/router/errors/Redirection.ts +28 -0
  415. package/src/react/router/hooks/useActive.ts +52 -0
  416. package/src/react/router/hooks/useQueryParams.ts +63 -0
  417. package/src/react/router/hooks/useRouter.ts +20 -0
  418. package/src/react/router/hooks/useRouterState.ts +11 -0
  419. package/src/react/router/index.browser.ts +45 -0
  420. package/src/react/router/index.shared.ts +19 -0
  421. package/src/react/router/index.ts +146 -0
  422. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  423. package/src/react/router/primitives/$page.spec.tsx +676 -0
  424. package/src/react/router/primitives/$page.ts +489 -0
  425. package/src/react/router/providers/ReactBrowserProvider.ts +312 -0
  426. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  427. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  428. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  429. package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
  430. package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
  431. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  432. package/src/react/router/providers/ReactServerProvider.ts +487 -0
  433. package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
  434. package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -0
  435. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  436. package/src/react/router/services/ReactPageServerService.ts +48 -0
  437. package/src/react/router/services/ReactPageService.ts +27 -0
  438. package/src/react/router/services/ReactRouter.ts +262 -0
  439. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  440. package/src/react/websocket/index.ts +7 -0
  441. package/src/redis/__tests__/redis.spec.ts +13 -0
  442. package/src/redis/index.ts +9 -25
  443. package/src/redis/providers/BunRedisProvider.ts +9 -0
  444. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  445. package/src/redis/providers/RedisProvider.ts +16 -0
  446. package/src/retry/index.ts +11 -2
  447. package/src/router/index.ts +15 -0
  448. package/src/scheduler/index.ts +11 -2
  449. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  450. package/src/security/__tests__/ServerSecurityProvider.spec.ts +90 -5
  451. package/src/security/index.ts +15 -10
  452. package/src/security/interfaces/IssuerResolver.ts +27 -0
  453. package/src/security/primitives/$issuer.ts +55 -0
  454. package/src/security/providers/SecurityProvider.ts +179 -0
  455. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  456. package/src/security/providers/ServerSecurityProvider.ts +63 -41
  457. package/src/server/auth/index.ts +12 -7
  458. package/src/server/cache/index.ts +7 -22
  459. package/src/server/compress/index.ts +10 -2
  460. package/src/server/cookies/index.ts +7 -5
  461. package/src/server/cookies/primitives/$cookie.ts +33 -11
  462. package/src/server/core/index.ts +16 -6
  463. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  464. package/src/server/core/primitives/$action.spec.ts +1 -1
  465. package/src/server/core/primitives/$action.ts +8 -3
  466. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
  467. package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
  468. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  469. package/src/server/core/services/ServerRequestParser.ts +306 -13
  470. package/src/server/cors/index.ts +7 -21
  471. package/src/server/cors/primitives/$cors.ts +6 -2
  472. package/src/server/health/index.ts +8 -2
  473. package/src/server/helmet/index.ts +11 -3
  474. package/src/server/links/index.ts +11 -6
  475. package/src/server/metrics/index.ts +10 -3
  476. package/src/server/multipart/index.ts +9 -3
  477. package/src/server/proxy/index.ts +8 -2
  478. package/src/server/rate-limit/index.ts +21 -25
  479. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  480. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  481. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  482. package/src/server/static/index.ts +8 -2
  483. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  484. package/src/server/swagger/index.ts +9 -4
  485. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  486. package/src/sms/index.ts +9 -5
  487. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  488. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  489. package/src/system/index.browser.ts +36 -0
  490. package/src/system/index.ts +62 -0
  491. package/src/system/index.workerd.ts +1 -0
  492. package/src/{file → system}/providers/FileSystemProvider.ts +24 -0
  493. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  494. package/src/system/providers/MemoryShellProvider.ts +164 -0
  495. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  496. package/src/{file → system}/providers/NodeFileSystemProvider.ts +47 -2
  497. package/src/system/providers/NodeShellProvider.ts +184 -0
  498. package/src/system/providers/ShellProvider.ts +74 -0
  499. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  500. package/src/thread/index.ts +11 -2
  501. package/src/topic/core/index.ts +12 -5
  502. package/src/vite/tasks/buildClient.ts +2 -7
  503. package/src/vite/tasks/buildServer.ts +19 -13
  504. package/src/vite/tasks/generateCloudflare.ts +10 -7
  505. package/src/vite/tasks/generateDocker.ts +4 -0
  506. package/src/websocket/index.ts +12 -8
  507. package/dist/file/index.d.ts.map +0 -1
  508. package/dist/file/index.js.map +0 -1
  509. package/src/cli/assets/apiIndexTs.ts +0 -16
  510. package/src/cli/assets/mainServerTs.ts +0 -24
  511. package/src/cli/assets/webAppRouterTs.ts +0 -16
  512. package/src/cli/assets/webHelloComponentTsx.ts +0 -20
  513. package/src/cli/providers/ViteTemplateProvider.ts +0 -27
  514. package/src/file/index.ts +0 -43
  515. /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
  516. /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
  517. /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
  518. /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
  519. /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
  520. /package/src/cli/{assets → templates}/tsconfigJson.ts +0 -0
  521. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  522. /package/src/{file → system}/errors/FileError.ts +0 -0
  523. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -0,0 +1,164 @@
1
+ import type { ShellProvider, ShellRunOptions } from "./ShellProvider.ts";
2
+
3
+ // ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ export interface MemoryShellCall {
6
+ command: string;
7
+ options: ShellRunOptions;
8
+ }
9
+
10
+ export interface MemoryShellProviderOptions {
11
+ /**
12
+ * Simulated outputs for specific commands.
13
+ * Key is the command string, value is the stdout to return.
14
+ */
15
+ outputs?: Record<string, string>;
16
+
17
+ /**
18
+ * Commands that should throw an error.
19
+ * Key is the command string, value is the error message.
20
+ */
21
+ errors?: Record<string, string>;
22
+
23
+ /**
24
+ * Commands that are considered "installed" in the system PATH.
25
+ */
26
+ installedCommands?: string[];
27
+ }
28
+
29
+ // ---------------------------------------------------------------------------------------------------------------------
30
+
31
+ /**
32
+ * In-memory implementation of ShellProvider for testing.
33
+ *
34
+ * Records all commands that would be executed without actually running them.
35
+ * Can be configured to return specific outputs or throw errors for testing.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // In tests, substitute the real ShellProvider with MemoryShellProvider
40
+ * const alepha = Alepha.create().with({
41
+ * provide: ShellProvider,
42
+ * use: MemoryShellProvider,
43
+ * });
44
+ *
45
+ * // Configure mock behavior
46
+ * const shell = alepha.inject(MemoryShellProvider);
47
+ * shell.configure({
48
+ * outputs: { "echo hello": "hello\n" },
49
+ * errors: { "failing-cmd": "Command failed" },
50
+ * });
51
+ *
52
+ * // Or use the fluent API
53
+ * shell.outputs.set("another-cmd", "output");
54
+ * shell.errors.set("another-error", "Error message");
55
+ *
56
+ * // Run code that uses ShellProvider
57
+ * const service = alepha.inject(MyService);
58
+ * await service.doSomething();
59
+ *
60
+ * // Verify commands were called
61
+ * expect(shell.calls).toHaveLength(2);
62
+ * expect(shell.calls[0].command).toBe("yarn install");
63
+ * ```
64
+ */
65
+ export class MemoryShellProvider implements ShellProvider {
66
+ /**
67
+ * All recorded shell calls.
68
+ */
69
+ public calls: MemoryShellCall[] = [];
70
+
71
+ /**
72
+ * Simulated outputs for specific commands.
73
+ */
74
+ public outputs = new Map<string, string>();
75
+
76
+ /**
77
+ * Commands that should throw an error.
78
+ */
79
+ public errors = new Map<string, string>();
80
+
81
+ /**
82
+ * Commands considered installed in the system PATH.
83
+ */
84
+ public installedCommands = new Set<string>();
85
+
86
+ /**
87
+ * Configure the mock with predefined outputs, errors, and installed commands.
88
+ */
89
+ public configure(options: MemoryShellProviderOptions): this {
90
+ if (options.outputs) {
91
+ for (const [cmd, output] of Object.entries(options.outputs)) {
92
+ this.outputs.set(cmd, output);
93
+ }
94
+ }
95
+ if (options.errors) {
96
+ for (const [cmd, error] of Object.entries(options.errors)) {
97
+ this.errors.set(cmd, error);
98
+ }
99
+ }
100
+ if (options.installedCommands) {
101
+ for (const cmd of options.installedCommands) {
102
+ this.installedCommands.add(cmd);
103
+ }
104
+ }
105
+ return this;
106
+ }
107
+
108
+ /**
109
+ * Record command and return simulated output.
110
+ */
111
+ public async run(
112
+ command: string,
113
+ options: ShellRunOptions = {},
114
+ ): Promise<string> {
115
+ this.calls.push({ command, options });
116
+
117
+ // Check for configured error
118
+ const errorMsg = this.errors.get(command);
119
+ if (errorMsg) {
120
+ throw new Error(errorMsg);
121
+ }
122
+
123
+ // Return configured output or empty string
124
+ return this.outputs.get(command) ?? "";
125
+ }
126
+
127
+ /**
128
+ * Check if a specific command was called.
129
+ */
130
+ public wasCalled(command: string): boolean {
131
+ return this.calls.some((call) => call.command === command);
132
+ }
133
+
134
+ /**
135
+ * Check if a command matching a pattern was called.
136
+ */
137
+ public wasCalledMatching(pattern: RegExp): boolean {
138
+ return this.calls.some((call) => pattern.test(call.command));
139
+ }
140
+
141
+ /**
142
+ * Get all calls matching a pattern.
143
+ */
144
+ public getCallsMatching(pattern: RegExp): MemoryShellCall[] {
145
+ return this.calls.filter((call) => pattern.test(call.command));
146
+ }
147
+
148
+ /**
149
+ * Check if a command is installed.
150
+ */
151
+ public async isInstalled(command: string): Promise<boolean> {
152
+ return this.installedCommands.has(command);
153
+ }
154
+
155
+ /**
156
+ * Reset all recorded state.
157
+ */
158
+ public reset(): void {
159
+ this.calls = [];
160
+ this.outputs.clear();
161
+ this.errors.clear();
162
+ this.installedCommands.clear();
163
+ }
164
+ }
@@ -1,14 +1,14 @@
1
1
  import { Readable } from "node:stream";
2
2
  import { Alepha } from "alepha";
3
3
  import { beforeEach, describe, it } from "vitest";
4
- import { AlephaFile } from "../index.ts";
4
+ import { AlephaSystem } from "../index.ts";
5
5
  import { NodeFileSystemProvider } from "../providers/NodeFileSystemProvider.ts";
6
6
 
7
7
  describe("NodeFileSystem", () => {
8
8
  let fs: NodeFileSystemProvider;
9
9
 
10
10
  beforeEach(() => {
11
- const alepha = Alepha.create().with(AlephaFile);
11
+ const alepha = Alepha.create().with(AlephaSystem);
12
12
  fs = alepha.inject(NodeFileSystemProvider);
13
13
  });
14
14
 
@@ -20,6 +20,7 @@ import {
20
20
  AlephaError,
21
21
  type FileLike,
22
22
  isFileLike,
23
+ Json,
23
24
  type StreamLike,
24
25
  } from "alepha";
25
26
  import { FileDetector } from "../services/FileDetector.ts";
@@ -58,6 +59,7 @@ import type {
58
59
  */
59
60
  export class NodeFileSystemProvider implements FileSystemProvider {
60
61
  protected detector = $inject(FileDetector);
62
+ protected json = $inject(Json);
61
63
 
62
64
  public join(...paths: string[]): string {
63
65
  return join(...paths);
@@ -289,8 +291,17 @@ export class NodeFileSystemProvider implements FileSystemProvider {
289
291
  * await fs.mkdir("/tmp/mydir", { mode: 0o755 });
290
292
  * ```
291
293
  */
292
- async mkdir(path: string, options?: MkdirOptions): Promise<void> {
293
- await fsMkdir(path, options);
294
+ async mkdir(path: string, options: MkdirOptions = {}): Promise<void> {
295
+ const p = fsMkdir(path, {
296
+ recursive: options.recursive ?? true,
297
+ mode: options.mode,
298
+ });
299
+
300
+ if (options.force === false) {
301
+ await p;
302
+ } else {
303
+ await p.catch(() => {});
304
+ }
294
305
  }
295
306
 
296
307
  /**
@@ -418,6 +429,40 @@ export class NodeFileSystemProvider implements FileSystemProvider {
418
429
  await fsWriteFile(path, data);
419
430
  }
420
431
 
432
+ /**
433
+ * Reads the content of a file as a string.
434
+ *
435
+ * @param path - The file path to read
436
+ * @returns The file content as a string
437
+ *
438
+ * @example
439
+ * ```typescript
440
+ * const fs = alepha.inject(NodeFileSystemProvider);
441
+ * const content = await fs.readTextFile("/tmp/file.txt");
442
+ * ```
443
+ */
444
+ async readTextFile(path: string): Promise<string> {
445
+ const buffer = await this.readFile(path);
446
+ return buffer.toString("utf-8");
447
+ }
448
+
449
+ /**
450
+ * Reads the content of a file as JSON.
451
+ *
452
+ * @param path - The file path to read
453
+ * @returns The parsed JSON content
454
+ *
455
+ * @example
456
+ * ```typescript
457
+ * const fs = alepha.inject(NodeFileSystemProvider);
458
+ * const config = await fs.readJsonFile<{ name: string }>("/tmp/config.json");
459
+ * ```
460
+ */
461
+ async readJsonFile<T = unknown>(path: string): Promise<T> {
462
+ const text = await this.readTextFile(path);
463
+ return this.json.parse(text) as T;
464
+ }
465
+
421
466
  /**
422
467
  * Creates a FileLike object from a Web File.
423
468
  *
@@ -0,0 +1,184 @@
1
+ import { exec, spawn } from "node:child_process";
2
+ import { $inject, AlephaError } from "alepha";
3
+ import { $logger } from "alepha/logger";
4
+ import { FileSystemProvider } from "./FileSystemProvider.ts";
5
+ import type { ShellProvider, ShellRunOptions } from "./ShellProvider.ts";
6
+
7
+ // ---------------------------------------------------------------------------------------------------------------------
8
+
9
+ /**
10
+ * Node.js implementation of ShellProvider.
11
+ *
12
+ * Executes shell commands using Node.js child_process module.
13
+ * Supports binary resolution from node_modules/.bin for local packages.
14
+ */
15
+ export class NodeShellProvider implements ShellProvider {
16
+ protected readonly log = $logger();
17
+ protected readonly fs = $inject(FileSystemProvider);
18
+
19
+ /**
20
+ * Run a shell command or binary.
21
+ */
22
+ public async run(
23
+ command: string,
24
+ options: ShellRunOptions = {},
25
+ ): Promise<string> {
26
+ const { resolve = false, capture = false, root, env } = options;
27
+ const cwd = root ?? process.cwd();
28
+
29
+ this.log.debug(`Shell: ${command}`, { cwd, resolve, capture });
30
+
31
+ let executable: string;
32
+ let args: string[];
33
+
34
+ if (resolve) {
35
+ const [bin, ...rest] = command.split(" ");
36
+ executable = await this.resolveExecutable(bin, cwd);
37
+ args = rest;
38
+ } else {
39
+ [executable, ...args] = command.split(" ");
40
+ }
41
+
42
+ if (capture) {
43
+ return this.execCapture(command, { cwd, env });
44
+ }
45
+
46
+ return this.execInherit(executable, args, { cwd, env });
47
+ }
48
+
49
+ /**
50
+ * Execute command with inherited stdio (streams to terminal).
51
+ */
52
+ protected async execInherit(
53
+ executable: string,
54
+ args: string[],
55
+ options: { cwd: string; env?: Record<string, string> },
56
+ ): Promise<string> {
57
+ const proc = spawn(executable, args, {
58
+ stdio: "inherit",
59
+ cwd: options.cwd,
60
+ env: {
61
+ ...process.env,
62
+ ...options.env,
63
+ },
64
+ });
65
+
66
+ return new Promise<string>((resolve, reject) => {
67
+ proc.on("exit", (code) => {
68
+ if (code === 0 || code === null) {
69
+ resolve("");
70
+ } else {
71
+ reject(new AlephaError(`Command exited with code ${code}`));
72
+ }
73
+ });
74
+ proc.on("error", reject);
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Execute command and capture stdout.
80
+ */
81
+ protected execCapture(
82
+ command: string,
83
+ options: { cwd: string; env?: Record<string, string> },
84
+ ): Promise<string> {
85
+ return new Promise<string>((resolve, reject) => {
86
+ exec(
87
+ command,
88
+ {
89
+ cwd: options.cwd,
90
+ env: {
91
+ ...process.env,
92
+ LOG_FORMAT: "pretty",
93
+ ...options.env,
94
+ },
95
+ },
96
+ (err, stdout) => {
97
+ if (err) {
98
+ (err as any).stdout = stdout;
99
+ reject(err);
100
+ } else {
101
+ resolve(stdout);
102
+ }
103
+ },
104
+ );
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Resolve executable path from node_modules/.bin.
110
+ *
111
+ * Search order:
112
+ * 1. Local: node_modules/.bin/
113
+ * 2. Pnpm nested: node_modules/alepha/node_modules/.bin/
114
+ * 3. Monorepo: Walk up to 3 parent directories
115
+ */
116
+ protected async resolveExecutable(
117
+ name: string,
118
+ root: string,
119
+ ): Promise<string> {
120
+ const suffix = process.platform === "win32" ? ".cmd" : "";
121
+
122
+ // 1. Local node_modules
123
+ let execPath = await this.findExecutable(
124
+ root,
125
+ `node_modules/.bin/${name}${suffix}`,
126
+ );
127
+
128
+ // 2. Pnpm nested (alepha's own node_modules)
129
+ if (!execPath) {
130
+ execPath = await this.findExecutable(
131
+ root,
132
+ `node_modules/alepha/node_modules/.bin/${name}${suffix}`,
133
+ );
134
+ }
135
+
136
+ // 3. Monorepo: check parent directories (up to 3 levels)
137
+ if (!execPath) {
138
+ let parentDir = this.fs.join(root, "..");
139
+ for (let i = 0; i < 3; i++) {
140
+ execPath = await this.findExecutable(
141
+ parentDir,
142
+ `node_modules/.bin/${name}${suffix}`,
143
+ );
144
+ if (execPath) break;
145
+ parentDir = this.fs.join(parentDir, "..");
146
+ }
147
+ }
148
+
149
+ if (!execPath) {
150
+ throw new AlephaError(
151
+ `Could not find executable for '${name}'. Make sure the package is installed.`,
152
+ );
153
+ }
154
+
155
+ return execPath;
156
+ }
157
+
158
+ /**
159
+ * Check if executable exists at path.
160
+ */
161
+ protected async findExecutable(
162
+ root: string,
163
+ relativePath: string,
164
+ ): Promise<string | undefined> {
165
+ const fullPath = this.fs.join(root, relativePath);
166
+ if (await this.fs.exists(fullPath)) {
167
+ return fullPath;
168
+ }
169
+ return undefined;
170
+ }
171
+
172
+ /**
173
+ * Check if a command is installed and available in the system PATH.
174
+ */
175
+ public isInstalled(command: string): Promise<boolean> {
176
+ return new Promise((resolve) => {
177
+ const check =
178
+ process.platform === "win32"
179
+ ? `where ${command}`
180
+ : `command -v ${command}`;
181
+ exec(check, (error) => resolve(!error));
182
+ });
183
+ }
184
+ }
@@ -0,0 +1,74 @@
1
+ // ---------------------------------------------------------------------------------------------------------------------
2
+
3
+ export interface ShellRunOptions {
4
+ /**
5
+ * Working directory for the command.
6
+ */
7
+ root?: string;
8
+
9
+ /**
10
+ * Additional environment variables.
11
+ */
12
+ env?: Record<string, string>;
13
+
14
+ /**
15
+ * Resolve the executable from node_modules/.bin.
16
+ * Supports local project, pnpm nested, and monorepo structures.
17
+ * @default false
18
+ */
19
+ resolve?: boolean;
20
+
21
+ /**
22
+ * Capture stdout instead of inheriting stdio.
23
+ * When true, returns stdout as string.
24
+ * When false, streams output to terminal.
25
+ * @default false
26
+ */
27
+ capture?: boolean;
28
+ }
29
+
30
+ // ---------------------------------------------------------------------------------------------------------------------
31
+
32
+ /**
33
+ * Abstract provider for executing shell commands and binaries.
34
+ *
35
+ * Implementations:
36
+ * - `NodeShellProvider` - Real shell execution using Node.js child_process
37
+ * - `MemoryShellProvider` - In-memory mock for testing
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * class MyService {
42
+ * protected readonly shell = $inject(ShellProvider);
43
+ *
44
+ * async build() {
45
+ * // Run shell command directly
46
+ * await this.shell.run("yarn install");
47
+ *
48
+ * // Run local binary with resolution
49
+ * await this.shell.run("vite build", { resolve: true });
50
+ *
51
+ * // Capture output
52
+ * const output = await this.shell.run("echo hello", { capture: true });
53
+ * }
54
+ * }
55
+ * ```
56
+ */
57
+ export abstract class ShellProvider {
58
+ /**
59
+ * Run a shell command or binary.
60
+ *
61
+ * @param command - The command to run
62
+ * @param options - Execution options
63
+ * @returns stdout if capture is true, empty string otherwise
64
+ */
65
+ abstract run(command: string, options?: ShellRunOptions): Promise<string>;
66
+
67
+ /**
68
+ * Check if a command is installed and available in the system PATH.
69
+ *
70
+ * @param command - The command name to check
71
+ * @returns true if the command is available
72
+ */
73
+ abstract isInstalled(command: string): Promise<boolean>;
74
+ }
@@ -1,7 +1,7 @@
1
1
  import { Readable } from "node:stream";
2
2
  import { Alepha } from "alepha";
3
3
  import { beforeEach, describe, expect, it } from "vitest";
4
- import { AlephaFile } from "../index.ts";
4
+ import { AlephaSystem } from "../index.ts";
5
5
  import { FileDetector } from "../services/FileDetector.ts";
6
6
 
7
7
  /**
@@ -26,7 +26,7 @@ describe("FileDetector", () => {
26
26
  let detector: FileDetector;
27
27
 
28
28
  beforeEach(() => {
29
- const alepha = Alepha.create().with(AlephaFile);
29
+ const alepha = Alepha.create().with(AlephaSystem);
30
30
  detector = alepha.inject(FileDetector);
31
31
  });
32
32
 
@@ -22,9 +22,18 @@ Alepha.prototype.isWorkerThread = function (this: Alepha): boolean {
22
22
  // ---------------------------------------------------------------------------------------------------------------------
23
23
 
24
24
  /**
25
- * Simple interface for managing worker threads in Alepha.
25
+ * | type | quality | stability |
26
+ * |------|---------|-----------|
27
+ * | backend | standard | experimental |
28
+ *
29
+ * Multi-threading support.
30
+ *
31
+ * **Features:**
32
+ * - Worker thread definitions
33
+ * - Worker thread management
34
+ * - Message passing
35
+ * - Worker pools
26
36
  *
27
- * @see {@link $thread}
28
37
  * @module alepha.thread
29
38
  */
30
39
  export const AlephaThread = $module({
@@ -15,12 +15,19 @@ export * from "./providers/TopicProvider.ts";
15
15
  // ---------------------------------------------------------------------------------------------------------------------
16
16
 
17
17
  /**
18
- * Generic interface for pub/sub messaging.
19
- * Gives you the ability to create topics and subscribers.
20
- * This module provides only a memory implementation of the topic provider.
18
+ * | type | quality | stability |
19
+ * |------|---------|-----------|
20
+ * | backend | rare | stable |
21
+ *
22
+ * Publish/subscribe messaging for event-driven architectures.
23
+ *
24
+ * **Features:**
25
+ * - Pub/sub topics with type-safe messages
26
+ * - Topic subscription handlers
27
+ * - Multiple subscriber support
28
+ * - Message filtering and routing
29
+ * - Providers: Memory (dev), Redis (production)
21
30
  *
22
- * @see {@link $topic}
23
- * @see {@link $subscriber}
24
31
  * @module alepha.topic
25
32
  */
26
33
  export const AlephaTopic = $module({
@@ -36,11 +36,6 @@ export interface BuildClientOptions {
36
36
  hostname: string;
37
37
  };
38
38
 
39
- /**
40
- * Override Vite config options.
41
- */
42
- config?: UserConfig;
43
-
44
39
  /**
45
40
  * If true, generate build stats report.
46
41
  */
@@ -61,7 +56,7 @@ export interface BuildClientOptions {
61
56
  * including code splitting, minification, and optional compression.
62
57
  */
63
58
  export async function buildClient(opts: BuildClientOptions): Promise<void> {
64
- const { build: viteBuild, mergeConfig } = await importVite();
59
+ const { build: viteBuild } = await importVite();
65
60
  const plugins: any[] = [];
66
61
 
67
62
  const viteReact = await importViteReact();
@@ -117,7 +112,7 @@ export async function buildClient(opts: BuildClientOptions): Promise<void> {
117
112
  };
118
113
 
119
114
  try {
120
- await viteBuild(mergeConfig(viteBuildClientConfig, opts.config ?? {}));
115
+ await viteBuild(viteBuildClientConfig);
121
116
  } catch (error) {
122
117
  // Flush buffered logs on failure so user can see what happened
123
118
  logger?.flush();
@@ -23,7 +23,7 @@ export interface BuildServerOptions {
23
23
 
24
24
  /**
25
25
  * Optional client directory name (relative to distDir).
26
- * If provided, the client template will be embedded in the server output.
26
+ * If provided, the SSR manifest will be embedded in the server output.
27
27
  */
28
28
  clientDir?: string;
29
29
 
@@ -61,6 +61,7 @@ export interface BuildServerResult {
61
61
  * Can be used to set in alepha store for pre-rendering.
62
62
  */
63
63
  manifest?: {
64
+ base?: string;
64
65
  client?: Record<string, any>;
65
66
  preload?: Record<string, string>;
66
67
  };
@@ -166,21 +167,15 @@ export async function buildServer(
166
167
 
167
168
  const entryFile = extractEntryFromBundle(opts.entry, result);
168
169
 
169
- // Embed client template if client was built
170
- let template = "";
171
- if (opts.clientDir) {
172
- const index = await readFile(
173
- `${opts.distDir}/${opts.clientDir}/index.html`,
174
- "utf-8",
175
- );
176
- template = `__alepha.set("alepha.react.server.template", \`${index.replace(/>\s*</g, "><").trim()}\`);\n`;
177
- }
178
-
179
170
  // Embed SSR manifests if client was built
180
171
  // This bundles all manifest data into index.js for serverless deployments
181
172
  let manifest = "";
182
173
  let manifestData:
183
- | { client?: Record<string, any>; preload?: Record<string, string> }
174
+ | {
175
+ base?: string;
176
+ client?: Record<string, any>;
177
+ preload?: Record<string, string>;
178
+ }
184
179
  | undefined;
185
180
 
186
181
  if (opts.clientDir) {
@@ -193,7 +188,18 @@ export async function buildServer(
193
188
  // Strip unused fields from client manifest to reduce bundle size
194
189
  const strippedClientManifest = stripClientManifest(clientManifest);
195
190
 
191
+ // Get base path from resolved config (defaults to "/" if not set)
192
+ // Normalize: ensure it starts with "/" and doesn't end with "/" (unless it's just "/")
193
+ let base = resolvedConfig.base || "/";
194
+ if (!base.startsWith("/")) {
195
+ base = `/${base}`;
196
+ }
197
+ if (base.length > 1 && base.endsWith("/")) {
198
+ base = base.slice(0, -1);
199
+ }
200
+
196
201
  manifestData = {
202
+ base: base !== "/" ? base : undefined, // Only include if not default
197
203
  client: strippedClientManifest,
198
204
  preload: preloadManifest,
199
205
  };
@@ -214,7 +220,7 @@ export async function buildServer(
214
220
 
215
221
  await writeFile(
216
222
  `${opts.distDir}/index.js`,
217
- `${warning}\n${template}${manifest}import './server/${entryFile}';\n`.trim(),
223
+ `${warning}\n${manifest}import './server/${entryFile}';\n`.trim(),
218
224
  );
219
225
 
220
226
  return { entryFile, manifest: manifestData };