alepha 0.15.1 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. package/README.md +68 -80
  2. package/dist/api/audits/index.d.ts +10 -33
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +10 -33
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +10 -3
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +10 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +162 -155
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.d.ts +10 -4
  19. package/dist/api/notifications/index.d.ts.map +1 -1
  20. package/dist/api/notifications/index.js +10 -4
  21. package/dist/api/notifications/index.js.map +1 -1
  22. package/dist/api/parameters/index.d.ts +43 -50
  23. package/dist/api/parameters/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.js +30 -37
  25. package/dist/api/parameters/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +1081 -760
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2539 -218
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts +138 -132
  31. package/dist/api/verifications/index.d.ts.map +1 -1
  32. package/dist/api/verifications/index.js +12 -4
  33. package/dist/api/verifications/index.js.map +1 -1
  34. package/dist/batch/index.d.ts +20 -40
  35. package/dist/batch/index.d.ts.map +1 -1
  36. package/dist/batch/index.js +31 -44
  37. package/dist/batch/index.js.map +1 -1
  38. package/dist/bucket/index.d.ts +440 -8
  39. package/dist/bucket/index.d.ts.map +1 -1
  40. package/dist/bucket/index.js +1861 -12
  41. package/dist/bucket/index.js.map +1 -1
  42. package/dist/cache/core/index.d.ts +179 -7
  43. package/dist/cache/core/index.d.ts.map +1 -1
  44. package/dist/cache/core/index.js +213 -7
  45. package/dist/cache/core/index.js.map +1 -1
  46. package/dist/cache/redis/index.d.ts +1 -0
  47. package/dist/cache/redis/index.d.ts.map +1 -1
  48. package/dist/cache/redis/index.js +4 -0
  49. package/dist/cache/redis/index.js.map +1 -1
  50. package/dist/cli/index.d.ts +638 -5645
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +2550 -368
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/command/index.d.ts +203 -45
  55. package/dist/command/index.d.ts.map +1 -1
  56. package/dist/command/index.js +2060 -71
  57. package/dist/command/index.js.map +1 -1
  58. package/dist/core/index.browser.js +70 -40
  59. package/dist/core/index.browser.js.map +1 -1
  60. package/dist/core/index.d.ts +34 -13
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +90 -40
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/index.native.js +70 -40
  65. package/dist/core/index.native.js.map +1 -1
  66. package/dist/datetime/index.d.ts +15 -0
  67. package/dist/datetime/index.d.ts.map +1 -1
  68. package/dist/datetime/index.js +15 -0
  69. package/dist/datetime/index.js.map +1 -1
  70. package/dist/email/index.d.ts +323 -20
  71. package/dist/email/index.d.ts.map +1 -1
  72. package/dist/email/index.js +1857 -7
  73. package/dist/email/index.js.map +1 -1
  74. package/dist/fake/index.d.ts +90 -8
  75. package/dist/fake/index.d.ts.map +1 -1
  76. package/dist/fake/index.js +91 -20
  77. package/dist/fake/index.js.map +1 -1
  78. package/dist/lock/core/index.d.ts +11 -4
  79. package/dist/lock/core/index.d.ts.map +1 -1
  80. package/dist/lock/core/index.js +11 -4
  81. package/dist/lock/core/index.js.map +1 -1
  82. package/dist/logger/index.d.ts +17 -66
  83. package/dist/logger/index.d.ts.map +1 -1
  84. package/dist/logger/index.js +14 -63
  85. package/dist/logger/index.js.map +1 -1
  86. package/dist/mcp/index.d.ts +10 -30
  87. package/dist/mcp/index.d.ts.map +1 -1
  88. package/dist/mcp/index.js +12 -35
  89. package/dist/mcp/index.js.map +1 -1
  90. package/dist/orm/index.browser.js +3 -3
  91. package/dist/orm/index.browser.js.map +1 -1
  92. package/dist/orm/index.bun.js +39 -20
  93. package/dist/orm/index.bun.js.map +1 -1
  94. package/dist/orm/index.d.ts +517 -540
  95. package/dist/orm/index.d.ts.map +1 -1
  96. package/dist/orm/index.js +58 -71
  97. package/dist/orm/index.js.map +1 -1
  98. package/dist/queue/core/index.d.ts +18 -10
  99. package/dist/queue/core/index.d.ts.map +1 -1
  100. package/dist/queue/core/index.js +14 -6
  101. package/dist/queue/core/index.js.map +1 -1
  102. package/dist/react/auth/index.browser.js +108 -0
  103. package/dist/react/auth/index.browser.js.map +1 -0
  104. package/dist/react/auth/index.d.ts +100 -0
  105. package/dist/react/auth/index.d.ts.map +1 -0
  106. package/dist/react/auth/index.js +145 -0
  107. package/dist/react/auth/index.js.map +1 -0
  108. package/dist/react/core/index.d.ts +469 -0
  109. package/dist/react/core/index.d.ts.map +1 -0
  110. package/dist/react/core/index.js +464 -0
  111. package/dist/react/core/index.js.map +1 -0
  112. package/dist/react/form/index.d.ts +232 -0
  113. package/dist/react/form/index.d.ts.map +1 -0
  114. package/dist/react/form/index.js +432 -0
  115. package/dist/react/form/index.js.map +1 -0
  116. package/dist/react/head/index.browser.js +423 -0
  117. package/dist/react/head/index.browser.js.map +1 -0
  118. package/dist/react/head/index.d.ts +288 -0
  119. package/dist/react/head/index.d.ts.map +1 -0
  120. package/dist/react/head/index.js +465 -0
  121. package/dist/react/head/index.js.map +1 -0
  122. package/dist/react/i18n/index.d.ts +175 -0
  123. package/dist/react/i18n/index.d.ts.map +1 -0
  124. package/dist/react/i18n/index.js +224 -0
  125. package/dist/react/i18n/index.js.map +1 -0
  126. package/dist/react/router/index.browser.js +1974 -0
  127. package/dist/react/router/index.browser.js.map +1 -0
  128. package/dist/react/router/index.d.ts +1956 -0
  129. package/dist/react/router/index.d.ts.map +1 -0
  130. package/dist/react/router/index.js +4722 -0
  131. package/dist/react/router/index.js.map +1 -0
  132. package/dist/react/websocket/index.d.ts +117 -0
  133. package/dist/react/websocket/index.d.ts.map +1 -0
  134. package/dist/react/websocket/index.js +107 -0
  135. package/dist/react/websocket/index.js.map +1 -0
  136. package/dist/redis/index.bun.js +4 -0
  137. package/dist/redis/index.bun.js.map +1 -1
  138. package/dist/redis/index.d.ts +41 -44
  139. package/dist/redis/index.d.ts.map +1 -1
  140. package/dist/redis/index.js +16 -25
  141. package/dist/redis/index.js.map +1 -1
  142. package/dist/retry/index.d.ts +11 -2
  143. package/dist/retry/index.d.ts.map +1 -1
  144. package/dist/retry/index.js +11 -2
  145. package/dist/retry/index.js.map +1 -1
  146. package/dist/scheduler/index.d.ts +11 -2
  147. package/dist/scheduler/index.d.ts.map +1 -1
  148. package/dist/scheduler/index.js +11 -2
  149. package/dist/scheduler/index.js.map +1 -1
  150. package/dist/security/index.d.ts +140 -49
  151. package/dist/security/index.d.ts.map +1 -1
  152. package/dist/security/index.js +164 -32
  153. package/dist/security/index.js.map +1 -1
  154. package/dist/server/auth/index.d.ts +12 -7
  155. package/dist/server/auth/index.d.ts.map +1 -1
  156. package/dist/server/auth/index.js +12 -7
  157. package/dist/server/auth/index.js.map +1 -1
  158. package/dist/server/cache/index.d.ts +7 -22
  159. package/dist/server/cache/index.d.ts.map +1 -1
  160. package/dist/server/cache/index.js +7 -22
  161. package/dist/server/cache/index.js.map +1 -1
  162. package/dist/server/compress/index.d.ts +10 -2
  163. package/dist/server/compress/index.d.ts.map +1 -1
  164. package/dist/server/compress/index.js +10 -2
  165. package/dist/server/compress/index.js.map +1 -1
  166. package/dist/server/cookies/index.d.ts +40 -16
  167. package/dist/server/cookies/index.d.ts.map +1 -1
  168. package/dist/server/cookies/index.js +7 -5
  169. package/dist/server/cookies/index.js.map +1 -1
  170. package/dist/server/core/index.d.ts +124 -23
  171. package/dist/server/core/index.d.ts.map +1 -1
  172. package/dist/server/core/index.js +231 -14
  173. package/dist/server/core/index.js.map +1 -1
  174. package/dist/server/cors/index.d.ts +13 -23
  175. package/dist/server/cors/index.d.ts.map +1 -1
  176. package/dist/server/cors/index.js +7 -21
  177. package/dist/server/cors/index.js.map +1 -1
  178. package/dist/server/health/index.d.ts +8 -2
  179. package/dist/server/health/index.d.ts.map +1 -1
  180. package/dist/server/health/index.js +8 -2
  181. package/dist/server/health/index.js.map +1 -1
  182. package/dist/server/helmet/index.d.ts +11 -3
  183. package/dist/server/helmet/index.d.ts.map +1 -1
  184. package/dist/server/helmet/index.js +11 -3
  185. package/dist/server/helmet/index.js.map +1 -1
  186. package/dist/server/links/index.d.ts +11 -6
  187. package/dist/server/links/index.d.ts.map +1 -1
  188. package/dist/server/links/index.js +11 -6
  189. package/dist/server/links/index.js.map +1 -1
  190. package/dist/server/metrics/index.d.ts +10 -3
  191. package/dist/server/metrics/index.d.ts.map +1 -1
  192. package/dist/server/metrics/index.js +10 -3
  193. package/dist/server/metrics/index.js.map +1 -1
  194. package/dist/server/multipart/index.d.ts +9 -3
  195. package/dist/server/multipart/index.d.ts.map +1 -1
  196. package/dist/server/multipart/index.js +9 -3
  197. package/dist/server/multipart/index.js.map +1 -1
  198. package/dist/server/proxy/index.d.ts +8 -2
  199. package/dist/server/proxy/index.d.ts.map +1 -1
  200. package/dist/server/proxy/index.js +8 -2
  201. package/dist/server/proxy/index.js.map +1 -1
  202. package/dist/server/rate-limit/index.d.ts +30 -35
  203. package/dist/server/rate-limit/index.d.ts.map +1 -1
  204. package/dist/server/rate-limit/index.js +18 -55
  205. package/dist/server/rate-limit/index.js.map +1 -1
  206. package/dist/server/static/index.d.ts +137 -4
  207. package/dist/server/static/index.d.ts.map +1 -1
  208. package/dist/server/static/index.js +1853 -5
  209. package/dist/server/static/index.js.map +1 -1
  210. package/dist/server/swagger/index.d.ts +309 -6
  211. package/dist/server/swagger/index.d.ts.map +1 -1
  212. package/dist/server/swagger/index.js +1854 -6
  213. package/dist/server/swagger/index.js.map +1 -1
  214. package/dist/sms/index.d.ts +309 -7
  215. package/dist/sms/index.d.ts.map +1 -1
  216. package/dist/sms/index.js +1856 -7
  217. package/dist/sms/index.js.map +1 -1
  218. package/dist/system/index.browser.js +1218 -0
  219. package/dist/system/index.browser.js.map +1 -0
  220. package/dist/{file → system}/index.d.ts +343 -16
  221. package/dist/system/index.d.ts.map +1 -0
  222. package/dist/{file → system}/index.js +419 -22
  223. package/dist/system/index.js.map +1 -0
  224. package/dist/thread/index.d.ts +11 -2
  225. package/dist/thread/index.d.ts.map +1 -1
  226. package/dist/thread/index.js +11 -2
  227. package/dist/thread/index.js.map +1 -1
  228. package/dist/topic/core/index.d.ts +12 -5
  229. package/dist/topic/core/index.d.ts.map +1 -1
  230. package/dist/topic/core/index.js +12 -5
  231. package/dist/topic/core/index.js.map +1 -1
  232. package/dist/vite/index.d.ts +5 -6272
  233. package/dist/vite/index.d.ts.map +1 -1
  234. package/dist/vite/index.js +23 -10
  235. package/dist/vite/index.js.map +1 -1
  236. package/dist/websocket/index.d.ts +12 -8
  237. package/dist/websocket/index.d.ts.map +1 -1
  238. package/dist/websocket/index.js +12 -8
  239. package/dist/websocket/index.js.map +1 -1
  240. package/package.json +82 -11
  241. package/src/api/audits/index.ts +10 -33
  242. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  243. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  244. package/src/api/files/controllers/FileController.spec.ts +1 -1
  245. package/src/api/files/index.ts +10 -3
  246. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  247. package/src/api/files/services/FileService.spec.ts +1 -1
  248. package/src/api/jobs/index.ts +10 -3
  249. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  250. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  251. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  252. package/src/api/keys/index.ts +49 -0
  253. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  254. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  255. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  256. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  257. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  258. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  259. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  260. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  261. package/src/api/keys/services/ApiKeyService.ts +306 -0
  262. package/src/api/logs/TODO.md +55 -0
  263. package/src/api/notifications/index.ts +10 -4
  264. package/src/api/parameters/index.ts +9 -30
  265. package/src/api/parameters/primitives/$config.ts +12 -4
  266. package/src/api/parameters/services/ConfigStore.ts +9 -3
  267. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  268. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  269. package/src/api/users/index.ts +14 -3
  270. package/src/api/users/primitives/$realm.ts +33 -5
  271. package/src/api/users/providers/RealmProvider.ts +1 -12
  272. package/src/api/users/services/SessionService.ts +1 -1
  273. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  274. package/src/api/verifications/index.ts +10 -4
  275. package/src/batch/index.ts +9 -36
  276. package/src/batch/primitives/$batch.ts +0 -8
  277. package/src/batch/providers/BatchProvider.ts +29 -2
  278. package/src/bucket/__tests__/shared.ts +1 -1
  279. package/src/bucket/index.ts +13 -6
  280. package/src/bucket/primitives/$bucket.ts +1 -1
  281. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  282. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  283. package/src/cache/core/__tests__/shared.ts +30 -0
  284. package/src/cache/core/index.ts +11 -6
  285. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  286. package/src/cache/core/providers/CacheProvider.ts +17 -0
  287. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  288. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  289. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  290. package/src/cli/apps/AlephaCli.ts +1 -14
  291. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
  292. package/src/cli/atoms/buildOptions.ts +99 -9
  293. package/src/cli/commands/build.ts +150 -37
  294. package/src/cli/commands/db.ts +22 -18
  295. package/src/cli/commands/deploy.ts +1 -1
  296. package/src/cli/commands/dev.ts +1 -20
  297. package/src/cli/commands/gen/env.ts +5 -2
  298. package/src/cli/commands/gen/openapi.ts +5 -2
  299. package/src/cli/commands/init.spec.ts +588 -0
  300. package/src/cli/commands/init.ts +115 -58
  301. package/src/cli/commands/lint.ts +7 -1
  302. package/src/cli/commands/typecheck.ts +11 -0
  303. package/src/cli/providers/AppEntryProvider.ts +1 -1
  304. package/src/cli/providers/ViteBuildProvider.ts +8 -50
  305. package/src/cli/providers/ViteDevServerProvider.ts +35 -16
  306. package/src/cli/services/AlephaCliUtils.ts +52 -121
  307. package/src/cli/services/PackageManagerUtils.ts +129 -11
  308. package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
  309. package/src/cli/services/ProjectScaffolder.ts +148 -81
  310. package/src/cli/services/ViteUtils.ts +82 -0
  311. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
  312. package/src/cli/templates/apiAppSecurityTs.ts +11 -0
  313. package/src/cli/templates/apiIndexTs.ts +30 -0
  314. package/src/cli/templates/gitignore.ts +39 -0
  315. package/src/cli/{assets → templates}/mainCss.ts +11 -2
  316. package/src/cli/templates/mainServerTs.ts +33 -0
  317. package/src/cli/templates/webAppRouterTs.ts +74 -0
  318. package/src/cli/templates/webHelloComponentTsx.ts +30 -0
  319. package/src/command/helpers/Runner.spec.ts +139 -0
  320. package/src/command/helpers/Runner.ts +7 -22
  321. package/src/command/index.ts +12 -4
  322. package/src/command/providers/CliProvider.spec.ts +1392 -0
  323. package/src/command/providers/CliProvider.ts +320 -47
  324. package/src/core/Alepha.ts +34 -27
  325. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  326. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  327. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  328. package/src/core/index.shared.ts +1 -0
  329. package/src/core/index.ts +20 -0
  330. package/src/core/providers/EventManager.spec.ts +0 -71
  331. package/src/core/providers/EventManager.ts +3 -15
  332. package/src/core/providers/Json.ts +2 -14
  333. package/src/datetime/index.ts +15 -0
  334. package/src/email/index.ts +10 -5
  335. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  336. package/src/email/providers/LocalEmailProvider.ts +1 -1
  337. package/src/fake/__tests__/keyName.example.ts +1 -1
  338. package/src/fake/__tests__/keyName.spec.ts +5 -5
  339. package/src/fake/index.ts +9 -6
  340. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  341. package/src/fake/providers/FakeProvider.ts +133 -19
  342. package/src/lock/core/index.ts +11 -4
  343. package/src/logger/index.ts +17 -66
  344. package/src/mcp/index.ts +10 -27
  345. package/src/mcp/transports/SseMcpTransport.ts +0 -11
  346. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  347. package/src/orm/index.browser.ts +2 -2
  348. package/src/orm/index.bun.ts +5 -3
  349. package/src/orm/index.ts +23 -53
  350. package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
  351. package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
  352. package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
  353. package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
  354. package/src/orm/services/Repository.ts +7 -3
  355. package/src/queue/core/index.ts +14 -6
  356. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  357. package/src/react/auth/hooks/useAuth.ts +32 -0
  358. package/src/react/auth/index.browser.ts +13 -0
  359. package/src/react/auth/index.shared.ts +2 -0
  360. package/src/react/auth/index.ts +48 -0
  361. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  362. package/src/react/auth/services/ReactAuth.ts +135 -0
  363. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  364. package/src/react/core/components/ClientOnly.tsx +49 -0
  365. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  366. package/src/react/core/contexts/AlephaContext.ts +7 -0
  367. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  368. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  369. package/src/react/core/hooks/useAction.ts +480 -0
  370. package/src/react/core/hooks/useAlepha.ts +26 -0
  371. package/src/react/core/hooks/useClient.ts +17 -0
  372. package/src/react/core/hooks/useEvents.ts +51 -0
  373. package/src/react/core/hooks/useInject.ts +12 -0
  374. package/src/react/core/hooks/useStore.ts +52 -0
  375. package/src/react/core/index.ts +90 -0
  376. package/src/react/form/components/FormState.tsx +17 -0
  377. package/src/react/form/errors/FormValidationError.ts +18 -0
  378. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  379. package/src/react/form/hooks/useForm.ts +47 -0
  380. package/src/react/form/hooks/useFormState.ts +130 -0
  381. package/src/react/form/index.ts +44 -0
  382. package/src/react/form/services/FormModel.ts +614 -0
  383. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  384. package/src/react/head/helpers/SeoExpander.ts +142 -0
  385. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  386. package/src/react/head/hooks/useHead.ts +62 -0
  387. package/src/react/head/index.browser.ts +26 -0
  388. package/src/react/head/index.ts +44 -0
  389. package/src/react/head/interfaces/Head.ts +105 -0
  390. package/src/react/head/primitives/$head.ts +25 -0
  391. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  392. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  393. package/src/react/head/providers/HeadProvider.ts +168 -0
  394. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  395. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  396. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  397. package/src/react/i18n/components/Localize.tsx +35 -0
  398. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  399. package/src/react/i18n/hooks/useI18n.ts +18 -0
  400. package/src/react/i18n/index.ts +41 -0
  401. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  402. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  403. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  404. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  405. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  406. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  407. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  408. package/src/react/router/components/ErrorViewer.tsx +872 -0
  409. package/src/react/router/components/Link.tsx +23 -0
  410. package/src/react/router/components/NestedView.tsx +223 -0
  411. package/src/react/router/components/NotFound.tsx +30 -0
  412. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  413. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  414. package/src/react/router/errors/Redirection.ts +28 -0
  415. package/src/react/router/hooks/useActive.ts +52 -0
  416. package/src/react/router/hooks/useQueryParams.ts +63 -0
  417. package/src/react/router/hooks/useRouter.ts +20 -0
  418. package/src/react/router/hooks/useRouterState.ts +11 -0
  419. package/src/react/router/index.browser.ts +45 -0
  420. package/src/react/router/index.shared.ts +19 -0
  421. package/src/react/router/index.ts +146 -0
  422. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  423. package/src/react/router/primitives/$page.spec.tsx +676 -0
  424. package/src/react/router/primitives/$page.ts +489 -0
  425. package/src/react/router/providers/ReactBrowserProvider.ts +312 -0
  426. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  427. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  428. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  429. package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
  430. package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
  431. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  432. package/src/react/router/providers/ReactServerProvider.ts +487 -0
  433. package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
  434. package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -0
  435. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  436. package/src/react/router/services/ReactPageServerService.ts +48 -0
  437. package/src/react/router/services/ReactPageService.ts +27 -0
  438. package/src/react/router/services/ReactRouter.ts +262 -0
  439. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  440. package/src/react/websocket/index.ts +7 -0
  441. package/src/redis/__tests__/redis.spec.ts +13 -0
  442. package/src/redis/index.ts +9 -25
  443. package/src/redis/providers/BunRedisProvider.ts +9 -0
  444. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  445. package/src/redis/providers/RedisProvider.ts +16 -0
  446. package/src/retry/index.ts +11 -2
  447. package/src/router/index.ts +15 -0
  448. package/src/scheduler/index.ts +11 -2
  449. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  450. package/src/security/__tests__/ServerSecurityProvider.spec.ts +90 -5
  451. package/src/security/index.ts +15 -10
  452. package/src/security/interfaces/IssuerResolver.ts +27 -0
  453. package/src/security/primitives/$issuer.ts +55 -0
  454. package/src/security/providers/SecurityProvider.ts +179 -0
  455. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  456. package/src/security/providers/ServerSecurityProvider.ts +63 -41
  457. package/src/server/auth/index.ts +12 -7
  458. package/src/server/cache/index.ts +7 -22
  459. package/src/server/compress/index.ts +10 -2
  460. package/src/server/cookies/index.ts +7 -5
  461. package/src/server/cookies/primitives/$cookie.ts +33 -11
  462. package/src/server/core/index.ts +16 -6
  463. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  464. package/src/server/core/primitives/$action.spec.ts +1 -1
  465. package/src/server/core/primitives/$action.ts +8 -3
  466. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
  467. package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
  468. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  469. package/src/server/core/services/ServerRequestParser.ts +306 -13
  470. package/src/server/cors/index.ts +7 -21
  471. package/src/server/cors/primitives/$cors.ts +6 -2
  472. package/src/server/health/index.ts +8 -2
  473. package/src/server/helmet/index.ts +11 -3
  474. package/src/server/links/index.ts +11 -6
  475. package/src/server/metrics/index.ts +10 -3
  476. package/src/server/multipart/index.ts +9 -3
  477. package/src/server/proxy/index.ts +8 -2
  478. package/src/server/rate-limit/index.ts +21 -25
  479. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  480. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  481. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  482. package/src/server/static/index.ts +8 -2
  483. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  484. package/src/server/swagger/index.ts +9 -4
  485. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  486. package/src/sms/index.ts +9 -5
  487. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  488. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  489. package/src/system/index.browser.ts +36 -0
  490. package/src/system/index.ts +62 -0
  491. package/src/system/index.workerd.ts +1 -0
  492. package/src/{file → system}/providers/FileSystemProvider.ts +24 -0
  493. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  494. package/src/system/providers/MemoryShellProvider.ts +164 -0
  495. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  496. package/src/{file → system}/providers/NodeFileSystemProvider.ts +47 -2
  497. package/src/system/providers/NodeShellProvider.ts +184 -0
  498. package/src/system/providers/ShellProvider.ts +74 -0
  499. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  500. package/src/thread/index.ts +11 -2
  501. package/src/topic/core/index.ts +12 -5
  502. package/src/vite/tasks/buildClient.ts +2 -7
  503. package/src/vite/tasks/buildServer.ts +19 -13
  504. package/src/vite/tasks/generateCloudflare.ts +10 -7
  505. package/src/vite/tasks/generateDocker.ts +4 -0
  506. package/src/websocket/index.ts +12 -8
  507. package/dist/file/index.d.ts.map +0 -1
  508. package/dist/file/index.js.map +0 -1
  509. package/src/cli/assets/apiIndexTs.ts +0 -16
  510. package/src/cli/assets/mainServerTs.ts +0 -24
  511. package/src/cli/assets/webAppRouterTs.ts +0 -16
  512. package/src/cli/assets/webHelloComponentTsx.ts +0 -20
  513. package/src/cli/providers/ViteTemplateProvider.ts +0 -27
  514. package/src/file/index.ts +0 -43
  515. /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
  516. /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
  517. /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
  518. /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
  519. /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
  520. /package/src/cli/{assets → templates}/tsconfigJson.ts +0 -0
  521. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  522. /package/src/{file → system}/errors/FileError.ts +0 -0
  523. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -1,18 +1,20 @@
1
- import { $inject, $module, AlephaError, isFileLike } from "alepha";
1
+ import { $inject, $module, AlephaError, Json, isFileLike } from "alepha";
2
+ import { join } from "node:path";
2
3
  import { createReadStream } from "node:fs";
3
4
  import { access, copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
4
- import { join } from "node:path";
5
5
  import { PassThrough, Readable } from "node:stream";
6
6
  import { fileURLToPath } from "node:url";
7
+ import { exec, spawn } from "node:child_process";
8
+ import { $logger } from "alepha/logger";
7
9
 
8
- //#region ../../src/file/providers/FileSystemProvider.ts
10
+ //#region ../../src/system/providers/FileSystemProvider.ts
9
11
  /**
10
12
  * FileSystem interface providing utilities for working with files.
11
13
  */
12
14
  var FileSystemProvider = class {};
13
15
 
14
16
  //#endregion
15
- //#region ../../src/file/providers/MemoryFileSystemProvider.ts
17
+ //#region ../../src/system/providers/MemoryFileSystemProvider.ts
16
18
  /**
17
19
  * In-memory implementation of FileSystemProvider for testing.
18
20
  *
@@ -37,6 +39,7 @@ var FileSystemProvider = class {};
37
39
  * ```
38
40
  */
39
41
  var MemoryFileSystemProvider = class {
42
+ json = $inject(Json);
40
43
  /**
41
44
  * In-memory storage for files (path -> content)
42
45
  */
@@ -54,6 +57,14 @@ var MemoryFileSystemProvider = class {
54
57
  */
55
58
  writeFileCalls = [];
56
59
  /**
60
+ * Track readFile calls for test assertions
61
+ */
62
+ readFileCalls = [];
63
+ /**
64
+ * Track rm calls for test assertions
65
+ */
66
+ rmCalls = [];
67
+ /**
57
68
  * Track join calls for test assertions
58
69
  */
59
70
  joinCalls = [];
@@ -76,15 +87,32 @@ var MemoryFileSystemProvider = class {
76
87
  }
77
88
  /**
78
89
  * Join path segments using forward slashes.
90
+ * Uses Node's path.join for proper normalization (handles .. and .)
79
91
  */
80
92
  join(...paths) {
81
93
  this.joinCalls.push(paths);
82
- return paths.filter(Boolean).join("/").replace(/\/+/g, "/");
94
+ return join(...paths);
83
95
  }
84
96
  /**
85
97
  * Create a FileLike object from various sources.
86
98
  */
87
99
  createFile(options) {
100
+ if ("path" in options) {
101
+ const filePath = options.path;
102
+ const buffer = this.files.get(filePath);
103
+ if (buffer === void 0) throw new Error(`ENOENT: no such file or directory, open '${filePath}'`);
104
+ return {
105
+ name: options.name ?? filePath.split("/").pop() ?? "file",
106
+ type: options.type ?? "application/octet-stream",
107
+ size: buffer.byteLength,
108
+ lastModified: Date.now(),
109
+ stream: () => {
110
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
111
+ },
112
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
113
+ text: async () => buffer.toString("utf-8")
114
+ };
115
+ }
88
116
  if ("buffer" in options) {
89
117
  const buffer = options.buffer;
90
118
  return {
@@ -119,6 +147,10 @@ var MemoryFileSystemProvider = class {
119
147
  * Remove a file or directory from memory.
120
148
  */
121
149
  async rm(path, options) {
150
+ this.rmCalls.push({
151
+ path,
152
+ options
153
+ });
122
154
  if (!(this.files.has(path) || this.directories.has(path)) && !options?.force) throw new Error(`ENOENT: no such file or directory, rm '${path}'`);
123
155
  if (this.directories.has(path)) if (options?.recursive) {
124
156
  this.directories.delete(path);
@@ -213,12 +245,26 @@ var MemoryFileSystemProvider = class {
213
245
  * Read a file from memory.
214
246
  */
215
247
  async readFile(path) {
248
+ this.readFileCalls.push(path);
216
249
  if (this.readFileError) throw this.readFileError;
217
250
  const content = this.files.get(path);
218
251
  if (!content) throw new Error(`ENOENT: no such file or directory, open '${path}'`);
219
252
  return content;
220
253
  }
221
254
  /**
255
+ * Read a file from memory as text.
256
+ */
257
+ async readTextFile(path) {
258
+ return (await this.readFile(path)).toString("utf-8");
259
+ }
260
+ /**
261
+ * Read a file from memory as JSON.
262
+ */
263
+ async readJsonFile(path) {
264
+ const text = await this.readTextFile(path);
265
+ return this.json.parse(text);
266
+ }
267
+ /**
222
268
  * Write a file to memory.
223
269
  */
224
270
  async writeFile(path, data) {
@@ -239,12 +285,59 @@ var MemoryFileSystemProvider = class {
239
285
  this.directories.clear();
240
286
  this.mkdirCalls = [];
241
287
  this.writeFileCalls = [];
288
+ this.readFileCalls = [];
289
+ this.rmCalls = [];
242
290
  this.joinCalls = [];
243
291
  this.mkdirError = null;
244
292
  this.writeFileError = null;
245
293
  this.readFileError = null;
246
294
  }
247
295
  /**
296
+ * Check if a file was written during the test.
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * expect(fs.wasWritten("/project/tsconfig.json")).toBe(true);
301
+ * ```
302
+ */
303
+ wasWritten(path) {
304
+ return this.writeFileCalls.some((call) => call.path === path);
305
+ }
306
+ /**
307
+ * Check if a file was written with content matching a pattern.
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * expect(fs.wasWrittenMatching("/project/tsconfig.json", /extends/)).toBe(true);
312
+ * ```
313
+ */
314
+ wasWrittenMatching(path, pattern) {
315
+ const call = this.writeFileCalls.find((c) => c.path === path);
316
+ return call ? pattern.test(call.data) : false;
317
+ }
318
+ /**
319
+ * Check if a file was read during the test.
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * expect(fs.wasRead("/project/package.json")).toBe(true);
324
+ * ```
325
+ */
326
+ wasRead(path) {
327
+ return this.readFileCalls.includes(path);
328
+ }
329
+ /**
330
+ * Check if a file was deleted during the test.
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * expect(fs.wasDeleted("/project/old-file.txt")).toBe(true);
335
+ * ```
336
+ */
337
+ wasDeleted(path) {
338
+ return this.rmCalls.some((call) => call.path === path);
339
+ }
340
+ /**
248
341
  * Get the content of a file as a string (convenience method for testing).
249
342
  */
250
343
  getFileContent(path) {
@@ -253,7 +346,116 @@ var MemoryFileSystemProvider = class {
253
346
  };
254
347
 
255
348
  //#endregion
256
- //#region ../../src/file/services/FileDetector.ts
349
+ //#region ../../src/system/providers/MemoryShellProvider.ts
350
+ /**
351
+ * In-memory implementation of ShellProvider for testing.
352
+ *
353
+ * Records all commands that would be executed without actually running them.
354
+ * Can be configured to return specific outputs or throw errors for testing.
355
+ *
356
+ * @example
357
+ * ```typescript
358
+ * // In tests, substitute the real ShellProvider with MemoryShellProvider
359
+ * const alepha = Alepha.create().with({
360
+ * provide: ShellProvider,
361
+ * use: MemoryShellProvider,
362
+ * });
363
+ *
364
+ * // Configure mock behavior
365
+ * const shell = alepha.inject(MemoryShellProvider);
366
+ * shell.configure({
367
+ * outputs: { "echo hello": "hello\n" },
368
+ * errors: { "failing-cmd": "Command failed" },
369
+ * });
370
+ *
371
+ * // Or use the fluent API
372
+ * shell.outputs.set("another-cmd", "output");
373
+ * shell.errors.set("another-error", "Error message");
374
+ *
375
+ * // Run code that uses ShellProvider
376
+ * const service = alepha.inject(MyService);
377
+ * await service.doSomething();
378
+ *
379
+ * // Verify commands were called
380
+ * expect(shell.calls).toHaveLength(2);
381
+ * expect(shell.calls[0].command).toBe("yarn install");
382
+ * ```
383
+ */
384
+ var MemoryShellProvider = class {
385
+ /**
386
+ * All recorded shell calls.
387
+ */
388
+ calls = [];
389
+ /**
390
+ * Simulated outputs for specific commands.
391
+ */
392
+ outputs = /* @__PURE__ */ new Map();
393
+ /**
394
+ * Commands that should throw an error.
395
+ */
396
+ errors = /* @__PURE__ */ new Map();
397
+ /**
398
+ * Commands considered installed in the system PATH.
399
+ */
400
+ installedCommands = /* @__PURE__ */ new Set();
401
+ /**
402
+ * Configure the mock with predefined outputs, errors, and installed commands.
403
+ */
404
+ configure(options) {
405
+ if (options.outputs) for (const [cmd, output] of Object.entries(options.outputs)) this.outputs.set(cmd, output);
406
+ if (options.errors) for (const [cmd, error] of Object.entries(options.errors)) this.errors.set(cmd, error);
407
+ if (options.installedCommands) for (const cmd of options.installedCommands) this.installedCommands.add(cmd);
408
+ return this;
409
+ }
410
+ /**
411
+ * Record command and return simulated output.
412
+ */
413
+ async run(command, options = {}) {
414
+ this.calls.push({
415
+ command,
416
+ options
417
+ });
418
+ const errorMsg = this.errors.get(command);
419
+ if (errorMsg) throw new Error(errorMsg);
420
+ return this.outputs.get(command) ?? "";
421
+ }
422
+ /**
423
+ * Check if a specific command was called.
424
+ */
425
+ wasCalled(command) {
426
+ return this.calls.some((call) => call.command === command);
427
+ }
428
+ /**
429
+ * Check if a command matching a pattern was called.
430
+ */
431
+ wasCalledMatching(pattern) {
432
+ return this.calls.some((call) => pattern.test(call.command));
433
+ }
434
+ /**
435
+ * Get all calls matching a pattern.
436
+ */
437
+ getCallsMatching(pattern) {
438
+ return this.calls.filter((call) => pattern.test(call.command));
439
+ }
440
+ /**
441
+ * Check if a command is installed.
442
+ */
443
+ async isInstalled(command) {
444
+ return this.installedCommands.has(command);
445
+ }
446
+ /**
447
+ * Reset all recorded state.
448
+ */
449
+ reset() {
450
+ this.calls = [];
451
+ this.outputs.clear();
452
+ this.errors.clear();
453
+ this.installedCommands.clear();
454
+ }
455
+ };
456
+
457
+ //#endregion
458
+ //#region ../../src/system/services/FileDetector.ts
257
459
  /**
258
460
  * Service for detecting file types and getting content types.
259
461
  *
@@ -956,7 +1158,7 @@ var FileDetector = class FileDetector {
956
1158
  };
957
1159
 
958
1160
  //#endregion
959
- //#region ../../src/file/providers/NodeFileSystemProvider.ts
1161
+ //#region ../../src/system/providers/NodeFileSystemProvider.ts
960
1162
  /**
961
1163
  * Node.js implementation of FileSystem interface.
962
1164
  *
@@ -983,6 +1185,7 @@ var FileDetector = class FileDetector {
983
1185
  */
984
1186
  var NodeFileSystemProvider = class {
985
1187
  detector = $inject(FileDetector);
1188
+ json = $inject(Json);
986
1189
  join(...paths) {
987
1190
  return join(...paths);
988
1191
  }
@@ -1162,8 +1365,13 @@ var NodeFileSystemProvider = class {
1162
1365
  * await fs.mkdir("/tmp/mydir", { mode: 0o755 });
1163
1366
  * ```
1164
1367
  */
1165
- async mkdir(path, options) {
1166
- await mkdir(path, options);
1368
+ async mkdir(path, options = {}) {
1369
+ const p = mkdir(path, {
1370
+ recursive: options.recursive ?? true,
1371
+ mode: options.mode
1372
+ });
1373
+ if (options.force === false) await p;
1374
+ else await p.catch(() => {});
1167
1375
  }
1168
1376
  /**
1169
1377
  * Lists files in a directory.
@@ -1269,6 +1477,37 @@ var NodeFileSystemProvider = class {
1269
1477
  await writeFile(path, data);
1270
1478
  }
1271
1479
  /**
1480
+ * Reads the content of a file as a string.
1481
+ *
1482
+ * @param path - The file path to read
1483
+ * @returns The file content as a string
1484
+ *
1485
+ * @example
1486
+ * ```typescript
1487
+ * const fs = alepha.inject(NodeFileSystemProvider);
1488
+ * const content = await fs.readTextFile("/tmp/file.txt");
1489
+ * ```
1490
+ */
1491
+ async readTextFile(path) {
1492
+ return (await this.readFile(path)).toString("utf-8");
1493
+ }
1494
+ /**
1495
+ * Reads the content of a file as JSON.
1496
+ *
1497
+ * @param path - The file path to read
1498
+ * @returns The parsed JSON content
1499
+ *
1500
+ * @example
1501
+ * ```typescript
1502
+ * const fs = alepha.inject(NodeFileSystemProvider);
1503
+ * const config = await fs.readJsonFile<{ name: string }>("/tmp/config.json");
1504
+ * ```
1505
+ */
1506
+ async readJsonFile(path) {
1507
+ const text = await this.readTextFile(path);
1508
+ return this.json.parse(text);
1509
+ }
1510
+ /**
1272
1511
  * Creates a FileLike object from a Web File.
1273
1512
  *
1274
1513
  * @protected
@@ -1421,7 +1660,154 @@ var NodeFileSystemProvider = class {
1421
1660
  };
1422
1661
 
1423
1662
  //#endregion
1424
- //#region ../../src/file/errors/FileError.ts
1663
+ //#region ../../src/system/providers/NodeShellProvider.ts
1664
+ /**
1665
+ * Node.js implementation of ShellProvider.
1666
+ *
1667
+ * Executes shell commands using Node.js child_process module.
1668
+ * Supports binary resolution from node_modules/.bin for local packages.
1669
+ */
1670
+ var NodeShellProvider = class {
1671
+ log = $logger();
1672
+ fs = $inject(FileSystemProvider);
1673
+ /**
1674
+ * Run a shell command or binary.
1675
+ */
1676
+ async run(command, options = {}) {
1677
+ const { resolve = false, capture = false, root, env } = options;
1678
+ const cwd = root ?? process.cwd();
1679
+ this.log.debug(`Shell: ${command}`, {
1680
+ cwd,
1681
+ resolve,
1682
+ capture
1683
+ });
1684
+ let executable;
1685
+ let args;
1686
+ if (resolve) {
1687
+ const [bin, ...rest] = command.split(" ");
1688
+ executable = await this.resolveExecutable(bin, cwd);
1689
+ args = rest;
1690
+ } else [executable, ...args] = command.split(" ");
1691
+ if (capture) return this.execCapture(command, {
1692
+ cwd,
1693
+ env
1694
+ });
1695
+ return this.execInherit(executable, args, {
1696
+ cwd,
1697
+ env
1698
+ });
1699
+ }
1700
+ /**
1701
+ * Execute command with inherited stdio (streams to terminal).
1702
+ */
1703
+ async execInherit(executable, args, options) {
1704
+ const proc = spawn(executable, args, {
1705
+ stdio: "inherit",
1706
+ cwd: options.cwd,
1707
+ env: {
1708
+ ...process.env,
1709
+ ...options.env
1710
+ }
1711
+ });
1712
+ return new Promise((resolve, reject) => {
1713
+ proc.on("exit", (code) => {
1714
+ if (code === 0 || code === null) resolve("");
1715
+ else reject(new AlephaError(`Command exited with code ${code}`));
1716
+ });
1717
+ proc.on("error", reject);
1718
+ });
1719
+ }
1720
+ /**
1721
+ * Execute command and capture stdout.
1722
+ */
1723
+ execCapture(command, options) {
1724
+ return new Promise((resolve, reject) => {
1725
+ exec(command, {
1726
+ cwd: options.cwd,
1727
+ env: {
1728
+ ...process.env,
1729
+ LOG_FORMAT: "pretty",
1730
+ ...options.env
1731
+ }
1732
+ }, (err, stdout) => {
1733
+ if (err) {
1734
+ err.stdout = stdout;
1735
+ reject(err);
1736
+ } else resolve(stdout);
1737
+ });
1738
+ });
1739
+ }
1740
+ /**
1741
+ * Resolve executable path from node_modules/.bin.
1742
+ *
1743
+ * Search order:
1744
+ * 1. Local: node_modules/.bin/
1745
+ * 2. Pnpm nested: node_modules/alepha/node_modules/.bin/
1746
+ * 3. Monorepo: Walk up to 3 parent directories
1747
+ */
1748
+ async resolveExecutable(name, root) {
1749
+ const suffix = process.platform === "win32" ? ".cmd" : "";
1750
+ let execPath = await this.findExecutable(root, `node_modules/.bin/${name}${suffix}`);
1751
+ if (!execPath) execPath = await this.findExecutable(root, `node_modules/alepha/node_modules/.bin/${name}${suffix}`);
1752
+ if (!execPath) {
1753
+ let parentDir = this.fs.join(root, "..");
1754
+ for (let i = 0; i < 3; i++) {
1755
+ execPath = await this.findExecutable(parentDir, `node_modules/.bin/${name}${suffix}`);
1756
+ if (execPath) break;
1757
+ parentDir = this.fs.join(parentDir, "..");
1758
+ }
1759
+ }
1760
+ if (!execPath) throw new AlephaError(`Could not find executable for '${name}'. Make sure the package is installed.`);
1761
+ return execPath;
1762
+ }
1763
+ /**
1764
+ * Check if executable exists at path.
1765
+ */
1766
+ async findExecutable(root, relativePath) {
1767
+ const fullPath = this.fs.join(root, relativePath);
1768
+ if (await this.fs.exists(fullPath)) return fullPath;
1769
+ }
1770
+ /**
1771
+ * Check if a command is installed and available in the system PATH.
1772
+ */
1773
+ isInstalled(command) {
1774
+ return new Promise((resolve) => {
1775
+ exec(process.platform === "win32" ? `where ${command}` : `command -v ${command}`, (error) => resolve(!error));
1776
+ });
1777
+ }
1778
+ };
1779
+
1780
+ //#endregion
1781
+ //#region ../../src/system/providers/ShellProvider.ts
1782
+ /**
1783
+ * Abstract provider for executing shell commands and binaries.
1784
+ *
1785
+ * Implementations:
1786
+ * - `NodeShellProvider` - Real shell execution using Node.js child_process
1787
+ * - `MemoryShellProvider` - In-memory mock for testing
1788
+ *
1789
+ * @example
1790
+ * ```typescript
1791
+ * class MyService {
1792
+ * protected readonly shell = $inject(ShellProvider);
1793
+ *
1794
+ * async build() {
1795
+ * // Run shell command directly
1796
+ * await this.shell.run("yarn install");
1797
+ *
1798
+ * // Run local binary with resolution
1799
+ * await this.shell.run("vite build", { resolve: true });
1800
+ *
1801
+ * // Capture output
1802
+ * const output = await this.shell.run("echo hello", { capture: true });
1803
+ * }
1804
+ * }
1805
+ * ```
1806
+ */
1807
+ var ShellProvider = class {};
1808
+
1809
+ //#endregion
1810
+ //#region ../../src/system/errors/FileError.ts
1425
1811
  var FileError = class extends Error {
1426
1812
  constructor(message, cause) {
1427
1813
  super(message);
@@ -1431,34 +1817,45 @@ var FileError = class extends Error {
1431
1817
  };
1432
1818
 
1433
1819
  //#endregion
1434
- //#region ../../src/file/index.ts
1820
+ //#region ../../src/system/index.ts
1435
1821
  /**
1436
- * Provides file system capabilities for Alepha applications with support for multiple file sources and operations.
1822
+ * | type | quality | stability |
1823
+ * |------|---------|-----------|
1824
+ * | tooling | standard | stable |
1437
1825
  *
1438
- * The file module enables working with files from various sources (URLs, buffers, streams) and provides
1439
- * utilities for file type detection, content type determination, and common file system operations.
1826
+ * System-level abstractions for portable code across runtimes.
1440
1827
  *
1441
- * @see {@link FileDetector}
1442
- * @see {@link FileSystemProvider}
1443
- * @see {@link NodeFileSystemProvider}
1444
- * @module alepha.file
1828
+ * **Features:**
1829
+ * - File system operations (read, write, exists, etc.)
1830
+ * - Shell command execution
1831
+ * - File type detection and MIME utilities
1832
+ * - Memory implementations for testing
1833
+ *
1834
+ * @module alepha.system
1445
1835
  */
1446
- const AlephaFile = $module({
1447
- name: "alepha.file",
1836
+ const AlephaSystem = $module({
1837
+ name: "alepha.system",
1448
1838
  primitives: [],
1449
1839
  services: [
1450
1840
  FileDetector,
1451
1841
  FileSystemProvider,
1452
1842
  MemoryFileSystemProvider,
1453
- NodeFileSystemProvider
1843
+ NodeFileSystemProvider,
1844
+ ShellProvider,
1845
+ MemoryShellProvider,
1846
+ NodeShellProvider
1454
1847
  ],
1455
1848
  register: (alepha) => alepha.with({
1456
1849
  optional: true,
1457
1850
  provide: FileSystemProvider,
1458
1851
  use: NodeFileSystemProvider
1852
+ }).with({
1853
+ optional: true,
1854
+ provide: ShellProvider,
1855
+ use: alepha.isTest() ? MemoryShellProvider : NodeShellProvider
1459
1856
  })
1460
1857
  });
1461
1858
 
1462
1859
  //#endregion
1463
- export { AlephaFile, FileDetector, FileError, FileSystemProvider, MemoryFileSystemProvider, NodeFileSystemProvider };
1860
+ export { AlephaSystem, FileDetector, FileError, FileSystemProvider, MemoryFileSystemProvider, MemoryShellProvider, NodeFileSystemProvider, NodeShellProvider, ShellProvider };
1464
1861
  //# sourceMappingURL=index.js.map