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,1218 @@
1
+ import { $inject, $module, Json } from "alepha";
2
+ import { join } from "node:path";
3
+ import { Readable } from "node:stream";
4
+
5
+ //#region ../../src/system/providers/FileSystemProvider.ts
6
+ /**
7
+ * FileSystem interface providing utilities for working with files.
8
+ */
9
+ var FileSystemProvider = class {};
10
+
11
+ //#endregion
12
+ //#region ../../src/system/providers/MemoryFileSystemProvider.ts
13
+ /**
14
+ * In-memory implementation of FileSystemProvider for testing.
15
+ *
16
+ * This provider stores all files and directories in memory, making it ideal for
17
+ * unit tests that need to verify file operations without touching the real file system.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // In tests, substitute the real FileSystemProvider with MemoryFileSystemProvider
22
+ * const alepha = Alepha.create().with({
23
+ * provide: FileSystemProvider,
24
+ * use: MemoryFileSystemProvider,
25
+ * });
26
+ *
27
+ * // Run code that uses FileSystemProvider
28
+ * const service = alepha.inject(MyService);
29
+ * await service.saveFile("test.txt", "Hello World");
30
+ *
31
+ * // Verify the file was written
32
+ * const memoryFs = alepha.inject(MemoryFileSystemProvider);
33
+ * expect(memoryFs.files.get("test.txt")?.toString()).toBe("Hello World");
34
+ * ```
35
+ */
36
+ var MemoryFileSystemProvider = class {
37
+ json = $inject(Json);
38
+ /**
39
+ * In-memory storage for files (path -> content)
40
+ */
41
+ files = /* @__PURE__ */ new Map();
42
+ /**
43
+ * In-memory storage for directories
44
+ */
45
+ directories = /* @__PURE__ */ new Set();
46
+ /**
47
+ * Track mkdir calls for test assertions
48
+ */
49
+ mkdirCalls = [];
50
+ /**
51
+ * Track writeFile calls for test assertions
52
+ */
53
+ writeFileCalls = [];
54
+ /**
55
+ * Track readFile calls for test assertions
56
+ */
57
+ readFileCalls = [];
58
+ /**
59
+ * Track rm calls for test assertions
60
+ */
61
+ rmCalls = [];
62
+ /**
63
+ * Track join calls for test assertions
64
+ */
65
+ joinCalls = [];
66
+ /**
67
+ * Error to throw on mkdir (for testing error handling)
68
+ */
69
+ mkdirError = null;
70
+ /**
71
+ * Error to throw on writeFile (for testing error handling)
72
+ */
73
+ writeFileError = null;
74
+ /**
75
+ * Error to throw on readFile (for testing error handling)
76
+ */
77
+ readFileError = null;
78
+ constructor(options = {}) {
79
+ this.mkdirError = options.mkdirError ?? null;
80
+ this.writeFileError = options.writeFileError ?? null;
81
+ this.readFileError = options.readFileError ?? null;
82
+ }
83
+ /**
84
+ * Join path segments using forward slashes.
85
+ * Uses Node's path.join for proper normalization (handles .. and .)
86
+ */
87
+ join(...paths) {
88
+ this.joinCalls.push(paths);
89
+ return join(...paths);
90
+ }
91
+ /**
92
+ * Create a FileLike object from various sources.
93
+ */
94
+ createFile(options) {
95
+ if ("path" in options) {
96
+ const filePath = options.path;
97
+ const buffer = this.files.get(filePath);
98
+ if (buffer === void 0) throw new Error(`ENOENT: no such file or directory, open '${filePath}'`);
99
+ return {
100
+ name: options.name ?? filePath.split("/").pop() ?? "file",
101
+ type: options.type ?? "application/octet-stream",
102
+ size: buffer.byteLength,
103
+ lastModified: Date.now(),
104
+ stream: () => {
105
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
106
+ },
107
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
108
+ text: async () => buffer.toString("utf-8")
109
+ };
110
+ }
111
+ if ("buffer" in options) {
112
+ const buffer = options.buffer;
113
+ return {
114
+ name: options.name ?? "file",
115
+ type: options.type ?? "application/octet-stream",
116
+ size: buffer.byteLength,
117
+ lastModified: Date.now(),
118
+ stream: () => {
119
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
120
+ },
121
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
122
+ text: async () => buffer.toString("utf-8")
123
+ };
124
+ }
125
+ if ("text" in options) {
126
+ const buffer = Buffer.from(options.text, "utf-8");
127
+ return {
128
+ name: options.name ?? "file.txt",
129
+ type: options.type ?? "text/plain",
130
+ size: buffer.byteLength,
131
+ lastModified: Date.now(),
132
+ stream: () => {
133
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
134
+ },
135
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
136
+ text: async () => options.text
137
+ };
138
+ }
139
+ throw new Error("MemoryFileSystemProvider.createFile: unsupported options. Only buffer and text are supported.");
140
+ }
141
+ /**
142
+ * Remove a file or directory from memory.
143
+ */
144
+ async rm(path, options) {
145
+ this.rmCalls.push({
146
+ path,
147
+ options
148
+ });
149
+ if (!(this.files.has(path) || this.directories.has(path)) && !options?.force) throw new Error(`ENOENT: no such file or directory, rm '${path}'`);
150
+ if (this.directories.has(path)) if (options?.recursive) {
151
+ this.directories.delete(path);
152
+ for (const filePath of this.files.keys()) if (filePath.startsWith(`${path}/`)) this.files.delete(filePath);
153
+ for (const dirPath of this.directories) if (dirPath.startsWith(`${path}/`)) this.directories.delete(dirPath);
154
+ } else throw new Error(`EISDIR: illegal operation on a directory, rm '${path}'`);
155
+ else this.files.delete(path);
156
+ }
157
+ /**
158
+ * Copy a file or directory in memory.
159
+ */
160
+ async cp(src, dest, options) {
161
+ if (this.directories.has(src)) {
162
+ if (!options?.recursive) throw new Error(`Cannot copy directory without recursive option: ${src}`);
163
+ this.directories.add(dest);
164
+ for (const [filePath, content] of this.files) if (filePath.startsWith(`${src}/`)) {
165
+ const newPath = filePath.replace(src, dest);
166
+ this.files.set(newPath, Buffer.from(content));
167
+ }
168
+ } else if (this.files.has(src)) {
169
+ const content = this.files.get(src);
170
+ this.files.set(dest, Buffer.from(content));
171
+ } else throw new Error(`ENOENT: no such file or directory, cp '${src}'`);
172
+ }
173
+ /**
174
+ * Move/rename a file or directory in memory.
175
+ */
176
+ async mv(src, dest) {
177
+ if (this.directories.has(src)) {
178
+ this.directories.delete(src);
179
+ this.directories.add(dest);
180
+ for (const [filePath, content] of this.files) if (filePath.startsWith(`${src}/`)) {
181
+ const newPath = filePath.replace(src, dest);
182
+ this.files.delete(filePath);
183
+ this.files.set(newPath, content);
184
+ }
185
+ } else if (this.files.has(src)) {
186
+ const content = this.files.get(src);
187
+ this.files.delete(src);
188
+ this.files.set(dest, content);
189
+ } else throw new Error(`ENOENT: no such file or directory, mv '${src}'`);
190
+ }
191
+ /**
192
+ * Create a directory in memory.
193
+ */
194
+ async mkdir(path, options) {
195
+ this.mkdirCalls.push({
196
+ path,
197
+ options
198
+ });
199
+ if (this.mkdirError) throw this.mkdirError;
200
+ if (this.directories.has(path) && !options?.recursive) throw new Error(`EEXIST: file already exists, mkdir '${path}'`);
201
+ this.directories.add(path);
202
+ if (options?.recursive) {
203
+ const parts = path.split("/").filter(Boolean);
204
+ let current = "";
205
+ for (const part of parts) {
206
+ current = current ? `${current}/${part}` : part;
207
+ this.directories.add(current);
208
+ }
209
+ }
210
+ }
211
+ /**
212
+ * List files in a directory.
213
+ */
214
+ async ls(path, options) {
215
+ const normalizedPath = path.replace(/\/$/, "");
216
+ const entries = /* @__PURE__ */ new Set();
217
+ for (const filePath of this.files.keys()) if (filePath.startsWith(`${normalizedPath}/`)) {
218
+ const relativePath = filePath.slice(normalizedPath.length + 1);
219
+ const parts = relativePath.split("/");
220
+ if (options?.recursive) entries.add(relativePath);
221
+ else entries.add(parts[0]);
222
+ }
223
+ for (const dirPath of this.directories) if (dirPath.startsWith(`${normalizedPath}/`) && dirPath !== normalizedPath) {
224
+ const relativePath = dirPath.slice(normalizedPath.length + 1);
225
+ const parts = relativePath.split("/");
226
+ if (options?.recursive) entries.add(relativePath);
227
+ else if (parts.length === 1) entries.add(parts[0]);
228
+ }
229
+ let result = Array.from(entries);
230
+ if (!options?.hidden) result = result.filter((entry) => !entry.startsWith("."));
231
+ return result.sort();
232
+ }
233
+ /**
234
+ * Check if a file or directory exists in memory.
235
+ */
236
+ async exists(path) {
237
+ return this.files.has(path) || this.directories.has(path);
238
+ }
239
+ /**
240
+ * Read a file from memory.
241
+ */
242
+ async readFile(path) {
243
+ this.readFileCalls.push(path);
244
+ if (this.readFileError) throw this.readFileError;
245
+ const content = this.files.get(path);
246
+ if (!content) throw new Error(`ENOENT: no such file or directory, open '${path}'`);
247
+ return content;
248
+ }
249
+ /**
250
+ * Read a file from memory as text.
251
+ */
252
+ async readTextFile(path) {
253
+ return (await this.readFile(path)).toString("utf-8");
254
+ }
255
+ /**
256
+ * Read a file from memory as JSON.
257
+ */
258
+ async readJsonFile(path) {
259
+ const text = await this.readTextFile(path);
260
+ return this.json.parse(text);
261
+ }
262
+ /**
263
+ * Write a file to memory.
264
+ */
265
+ async writeFile(path, data) {
266
+ const dataStr = typeof data === "string" ? data : data instanceof Buffer || data instanceof Uint8Array ? data.toString("utf-8") : await data.text();
267
+ this.writeFileCalls.push({
268
+ path,
269
+ data: dataStr
270
+ });
271
+ if (this.writeFileError) throw this.writeFileError;
272
+ const buffer = typeof data === "string" ? Buffer.from(data, "utf-8") : data instanceof Buffer ? data : data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(await data.text(), "utf-8");
273
+ this.files.set(path, buffer);
274
+ }
275
+ /**
276
+ * Reset all in-memory state (useful between tests).
277
+ */
278
+ reset() {
279
+ this.files.clear();
280
+ this.directories.clear();
281
+ this.mkdirCalls = [];
282
+ this.writeFileCalls = [];
283
+ this.readFileCalls = [];
284
+ this.rmCalls = [];
285
+ this.joinCalls = [];
286
+ this.mkdirError = null;
287
+ this.writeFileError = null;
288
+ this.readFileError = null;
289
+ }
290
+ /**
291
+ * Check if a file was written during the test.
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * expect(fs.wasWritten("/project/tsconfig.json")).toBe(true);
296
+ * ```
297
+ */
298
+ wasWritten(path) {
299
+ return this.writeFileCalls.some((call) => call.path === path);
300
+ }
301
+ /**
302
+ * Check if a file was written with content matching a pattern.
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * expect(fs.wasWrittenMatching("/project/tsconfig.json", /extends/)).toBe(true);
307
+ * ```
308
+ */
309
+ wasWrittenMatching(path, pattern) {
310
+ const call = this.writeFileCalls.find((c) => c.path === path);
311
+ return call ? pattern.test(call.data) : false;
312
+ }
313
+ /**
314
+ * Check if a file was read during the test.
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * expect(fs.wasRead("/project/package.json")).toBe(true);
319
+ * ```
320
+ */
321
+ wasRead(path) {
322
+ return this.readFileCalls.includes(path);
323
+ }
324
+ /**
325
+ * Check if a file was deleted during the test.
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * expect(fs.wasDeleted("/project/old-file.txt")).toBe(true);
330
+ * ```
331
+ */
332
+ wasDeleted(path) {
333
+ return this.rmCalls.some((call) => call.path === path);
334
+ }
335
+ /**
336
+ * Get the content of a file as a string (convenience method for testing).
337
+ */
338
+ getFileContent(path) {
339
+ return this.files.get(path)?.toString("utf-8");
340
+ }
341
+ };
342
+
343
+ //#endregion
344
+ //#region ../../src/system/providers/MemoryShellProvider.ts
345
+ /**
346
+ * In-memory implementation of ShellProvider for testing.
347
+ *
348
+ * Records all commands that would be executed without actually running them.
349
+ * Can be configured to return specific outputs or throw errors for testing.
350
+ *
351
+ * @example
352
+ * ```typescript
353
+ * // In tests, substitute the real ShellProvider with MemoryShellProvider
354
+ * const alepha = Alepha.create().with({
355
+ * provide: ShellProvider,
356
+ * use: MemoryShellProvider,
357
+ * });
358
+ *
359
+ * // Configure mock behavior
360
+ * const shell = alepha.inject(MemoryShellProvider);
361
+ * shell.configure({
362
+ * outputs: { "echo hello": "hello\n" },
363
+ * errors: { "failing-cmd": "Command failed" },
364
+ * });
365
+ *
366
+ * // Or use the fluent API
367
+ * shell.outputs.set("another-cmd", "output");
368
+ * shell.errors.set("another-error", "Error message");
369
+ *
370
+ * // Run code that uses ShellProvider
371
+ * const service = alepha.inject(MyService);
372
+ * await service.doSomething();
373
+ *
374
+ * // Verify commands were called
375
+ * expect(shell.calls).toHaveLength(2);
376
+ * expect(shell.calls[0].command).toBe("yarn install");
377
+ * ```
378
+ */
379
+ var MemoryShellProvider = class {
380
+ /**
381
+ * All recorded shell calls.
382
+ */
383
+ calls = [];
384
+ /**
385
+ * Simulated outputs for specific commands.
386
+ */
387
+ outputs = /* @__PURE__ */ new Map();
388
+ /**
389
+ * Commands that should throw an error.
390
+ */
391
+ errors = /* @__PURE__ */ new Map();
392
+ /**
393
+ * Commands considered installed in the system PATH.
394
+ */
395
+ installedCommands = /* @__PURE__ */ new Set();
396
+ /**
397
+ * Configure the mock with predefined outputs, errors, and installed commands.
398
+ */
399
+ configure(options) {
400
+ if (options.outputs) for (const [cmd, output] of Object.entries(options.outputs)) this.outputs.set(cmd, output);
401
+ if (options.errors) for (const [cmd, error] of Object.entries(options.errors)) this.errors.set(cmd, error);
402
+ if (options.installedCommands) for (const cmd of options.installedCommands) this.installedCommands.add(cmd);
403
+ return this;
404
+ }
405
+ /**
406
+ * Record command and return simulated output.
407
+ */
408
+ async run(command, options = {}) {
409
+ this.calls.push({
410
+ command,
411
+ options
412
+ });
413
+ const errorMsg = this.errors.get(command);
414
+ if (errorMsg) throw new Error(errorMsg);
415
+ return this.outputs.get(command) ?? "";
416
+ }
417
+ /**
418
+ * Check if a specific command was called.
419
+ */
420
+ wasCalled(command) {
421
+ return this.calls.some((call) => call.command === command);
422
+ }
423
+ /**
424
+ * Check if a command matching a pattern was called.
425
+ */
426
+ wasCalledMatching(pattern) {
427
+ return this.calls.some((call) => pattern.test(call.command));
428
+ }
429
+ /**
430
+ * Get all calls matching a pattern.
431
+ */
432
+ getCallsMatching(pattern) {
433
+ return this.calls.filter((call) => pattern.test(call.command));
434
+ }
435
+ /**
436
+ * Check if a command is installed.
437
+ */
438
+ async isInstalled(command) {
439
+ return this.installedCommands.has(command);
440
+ }
441
+ /**
442
+ * Reset all recorded state.
443
+ */
444
+ reset() {
445
+ this.calls = [];
446
+ this.outputs.clear();
447
+ this.errors.clear();
448
+ this.installedCommands.clear();
449
+ }
450
+ };
451
+
452
+ //#endregion
453
+ //#region ../../src/system/providers/ShellProvider.ts
454
+ /**
455
+ * Abstract provider for executing shell commands and binaries.
456
+ *
457
+ * Implementations:
458
+ * - `NodeShellProvider` - Real shell execution using Node.js child_process
459
+ * - `MemoryShellProvider` - In-memory mock for testing
460
+ *
461
+ * @example
462
+ * ```typescript
463
+ * class MyService {
464
+ * protected readonly shell = $inject(ShellProvider);
465
+ *
466
+ * async build() {
467
+ * // Run shell command directly
468
+ * await this.shell.run("yarn install");
469
+ *
470
+ * // Run local binary with resolution
471
+ * await this.shell.run("vite build", { resolve: true });
472
+ *
473
+ * // Capture output
474
+ * const output = await this.shell.run("echo hello", { capture: true });
475
+ * }
476
+ * }
477
+ * ```
478
+ */
479
+ var ShellProvider = class {};
480
+
481
+ //#endregion
482
+ //#region ../../src/system/services/FileDetector.ts
483
+ /**
484
+ * Service for detecting file types and getting content types.
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * const detector = alepha.inject(FileDetector);
489
+ *
490
+ * // Get content type from filename
491
+ * const mimeType = detector.getContentType("image.png"); // "image/png"
492
+ *
493
+ * // Detect file type by magic bytes
494
+ * const stream = createReadStream('image.png');
495
+ * const result = await detector.detectFileType(stream, 'image.png');
496
+ * console.log(result.mimeType); // 'image/png'
497
+ * console.log(result.verified); // true if magic bytes match
498
+ * ```
499
+ */
500
+ var FileDetector = class FileDetector {
501
+ /**
502
+ * Magic byte signatures for common file formats.
503
+ * Each signature is represented as an array of bytes or null (wildcard).
504
+ */
505
+ static MAGIC_BYTES = {
506
+ png: [{
507
+ signature: [
508
+ 137,
509
+ 80,
510
+ 78,
511
+ 71,
512
+ 13,
513
+ 10,
514
+ 26,
515
+ 10
516
+ ],
517
+ mimeType: "image/png"
518
+ }],
519
+ jpg: [
520
+ {
521
+ signature: [
522
+ 255,
523
+ 216,
524
+ 255,
525
+ 224
526
+ ],
527
+ mimeType: "image/jpeg"
528
+ },
529
+ {
530
+ signature: [
531
+ 255,
532
+ 216,
533
+ 255,
534
+ 225
535
+ ],
536
+ mimeType: "image/jpeg"
537
+ },
538
+ {
539
+ signature: [
540
+ 255,
541
+ 216,
542
+ 255,
543
+ 226
544
+ ],
545
+ mimeType: "image/jpeg"
546
+ },
547
+ {
548
+ signature: [
549
+ 255,
550
+ 216,
551
+ 255,
552
+ 227
553
+ ],
554
+ mimeType: "image/jpeg"
555
+ },
556
+ {
557
+ signature: [
558
+ 255,
559
+ 216,
560
+ 255,
561
+ 232
562
+ ],
563
+ mimeType: "image/jpeg"
564
+ }
565
+ ],
566
+ jpeg: [
567
+ {
568
+ signature: [
569
+ 255,
570
+ 216,
571
+ 255,
572
+ 224
573
+ ],
574
+ mimeType: "image/jpeg"
575
+ },
576
+ {
577
+ signature: [
578
+ 255,
579
+ 216,
580
+ 255,
581
+ 225
582
+ ],
583
+ mimeType: "image/jpeg"
584
+ },
585
+ {
586
+ signature: [
587
+ 255,
588
+ 216,
589
+ 255,
590
+ 226
591
+ ],
592
+ mimeType: "image/jpeg"
593
+ },
594
+ {
595
+ signature: [
596
+ 255,
597
+ 216,
598
+ 255,
599
+ 227
600
+ ],
601
+ mimeType: "image/jpeg"
602
+ },
603
+ {
604
+ signature: [
605
+ 255,
606
+ 216,
607
+ 255,
608
+ 232
609
+ ],
610
+ mimeType: "image/jpeg"
611
+ }
612
+ ],
613
+ gif: [{
614
+ signature: [
615
+ 71,
616
+ 73,
617
+ 70,
618
+ 56,
619
+ 55,
620
+ 97
621
+ ],
622
+ mimeType: "image/gif"
623
+ }, {
624
+ signature: [
625
+ 71,
626
+ 73,
627
+ 70,
628
+ 56,
629
+ 57,
630
+ 97
631
+ ],
632
+ mimeType: "image/gif"
633
+ }],
634
+ webp: [{
635
+ signature: [
636
+ 82,
637
+ 73,
638
+ 70,
639
+ 70,
640
+ null,
641
+ null,
642
+ null,
643
+ null,
644
+ 87,
645
+ 69,
646
+ 66,
647
+ 80
648
+ ],
649
+ mimeType: "image/webp"
650
+ }],
651
+ bmp: [{
652
+ signature: [66, 77],
653
+ mimeType: "image/bmp"
654
+ }],
655
+ ico: [{
656
+ signature: [
657
+ 0,
658
+ 0,
659
+ 1,
660
+ 0
661
+ ],
662
+ mimeType: "image/x-icon"
663
+ }],
664
+ tiff: [{
665
+ signature: [
666
+ 73,
667
+ 73,
668
+ 42,
669
+ 0
670
+ ],
671
+ mimeType: "image/tiff"
672
+ }, {
673
+ signature: [
674
+ 77,
675
+ 77,
676
+ 0,
677
+ 42
678
+ ],
679
+ mimeType: "image/tiff"
680
+ }],
681
+ tif: [{
682
+ signature: [
683
+ 73,
684
+ 73,
685
+ 42,
686
+ 0
687
+ ],
688
+ mimeType: "image/tiff"
689
+ }, {
690
+ signature: [
691
+ 77,
692
+ 77,
693
+ 0,
694
+ 42
695
+ ],
696
+ mimeType: "image/tiff"
697
+ }],
698
+ pdf: [{
699
+ signature: [
700
+ 37,
701
+ 80,
702
+ 68,
703
+ 70,
704
+ 45
705
+ ],
706
+ mimeType: "application/pdf"
707
+ }],
708
+ zip: [
709
+ {
710
+ signature: [
711
+ 80,
712
+ 75,
713
+ 3,
714
+ 4
715
+ ],
716
+ mimeType: "application/zip"
717
+ },
718
+ {
719
+ signature: [
720
+ 80,
721
+ 75,
722
+ 5,
723
+ 6
724
+ ],
725
+ mimeType: "application/zip"
726
+ },
727
+ {
728
+ signature: [
729
+ 80,
730
+ 75,
731
+ 7,
732
+ 8
733
+ ],
734
+ mimeType: "application/zip"
735
+ }
736
+ ],
737
+ rar: [{
738
+ signature: [
739
+ 82,
740
+ 97,
741
+ 114,
742
+ 33,
743
+ 26,
744
+ 7
745
+ ],
746
+ mimeType: "application/vnd.rar"
747
+ }],
748
+ "7z": [{
749
+ signature: [
750
+ 55,
751
+ 122,
752
+ 188,
753
+ 175,
754
+ 39,
755
+ 28
756
+ ],
757
+ mimeType: "application/x-7z-compressed"
758
+ }],
759
+ tar: [{
760
+ signature: [
761
+ 117,
762
+ 115,
763
+ 116,
764
+ 97,
765
+ 114
766
+ ],
767
+ mimeType: "application/x-tar"
768
+ }],
769
+ gz: [{
770
+ signature: [31, 139],
771
+ mimeType: "application/gzip"
772
+ }],
773
+ tgz: [{
774
+ signature: [31, 139],
775
+ mimeType: "application/gzip"
776
+ }],
777
+ mp3: [
778
+ {
779
+ signature: [255, 251],
780
+ mimeType: "audio/mpeg"
781
+ },
782
+ {
783
+ signature: [255, 243],
784
+ mimeType: "audio/mpeg"
785
+ },
786
+ {
787
+ signature: [255, 242],
788
+ mimeType: "audio/mpeg"
789
+ },
790
+ {
791
+ signature: [
792
+ 73,
793
+ 68,
794
+ 51
795
+ ],
796
+ mimeType: "audio/mpeg"
797
+ }
798
+ ],
799
+ wav: [{
800
+ signature: [
801
+ 82,
802
+ 73,
803
+ 70,
804
+ 70,
805
+ null,
806
+ null,
807
+ null,
808
+ null,
809
+ 87,
810
+ 65,
811
+ 86,
812
+ 69
813
+ ],
814
+ mimeType: "audio/wav"
815
+ }],
816
+ ogg: [{
817
+ signature: [
818
+ 79,
819
+ 103,
820
+ 103,
821
+ 83
822
+ ],
823
+ mimeType: "audio/ogg"
824
+ }],
825
+ flac: [{
826
+ signature: [
827
+ 102,
828
+ 76,
829
+ 97,
830
+ 67
831
+ ],
832
+ mimeType: "audio/flac"
833
+ }],
834
+ mp4: [
835
+ {
836
+ signature: [
837
+ null,
838
+ null,
839
+ null,
840
+ null,
841
+ 102,
842
+ 116,
843
+ 121,
844
+ 112
845
+ ],
846
+ mimeType: "video/mp4"
847
+ },
848
+ {
849
+ signature: [
850
+ null,
851
+ null,
852
+ null,
853
+ null,
854
+ 102,
855
+ 116,
856
+ 121,
857
+ 112,
858
+ 105,
859
+ 115,
860
+ 111,
861
+ 109
862
+ ],
863
+ mimeType: "video/mp4"
864
+ },
865
+ {
866
+ signature: [
867
+ null,
868
+ null,
869
+ null,
870
+ null,
871
+ 102,
872
+ 116,
873
+ 121,
874
+ 112,
875
+ 109,
876
+ 112,
877
+ 52,
878
+ 50
879
+ ],
880
+ mimeType: "video/mp4"
881
+ }
882
+ ],
883
+ webm: [{
884
+ signature: [
885
+ 26,
886
+ 69,
887
+ 223,
888
+ 163
889
+ ],
890
+ mimeType: "video/webm"
891
+ }],
892
+ avi: [{
893
+ signature: [
894
+ 82,
895
+ 73,
896
+ 70,
897
+ 70,
898
+ null,
899
+ null,
900
+ null,
901
+ null,
902
+ 65,
903
+ 86,
904
+ 73,
905
+ 32
906
+ ],
907
+ mimeType: "video/x-msvideo"
908
+ }],
909
+ mov: [{
910
+ signature: [
911
+ null,
912
+ null,
913
+ null,
914
+ null,
915
+ 102,
916
+ 116,
917
+ 121,
918
+ 112,
919
+ 113,
920
+ 116,
921
+ 32,
922
+ 32
923
+ ],
924
+ mimeType: "video/quicktime"
925
+ }],
926
+ mkv: [{
927
+ signature: [
928
+ 26,
929
+ 69,
930
+ 223,
931
+ 163
932
+ ],
933
+ mimeType: "video/x-matroska"
934
+ }],
935
+ docx: [{
936
+ signature: [
937
+ 80,
938
+ 75,
939
+ 3,
940
+ 4
941
+ ],
942
+ mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
943
+ }],
944
+ xlsx: [{
945
+ signature: [
946
+ 80,
947
+ 75,
948
+ 3,
949
+ 4
950
+ ],
951
+ mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
952
+ }],
953
+ pptx: [{
954
+ signature: [
955
+ 80,
956
+ 75,
957
+ 3,
958
+ 4
959
+ ],
960
+ mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
961
+ }],
962
+ doc: [{
963
+ signature: [
964
+ 208,
965
+ 207,
966
+ 17,
967
+ 224,
968
+ 161,
969
+ 177,
970
+ 26,
971
+ 225
972
+ ],
973
+ mimeType: "application/msword"
974
+ }],
975
+ xls: [{
976
+ signature: [
977
+ 208,
978
+ 207,
979
+ 17,
980
+ 224,
981
+ 161,
982
+ 177,
983
+ 26,
984
+ 225
985
+ ],
986
+ mimeType: "application/vnd.ms-excel"
987
+ }],
988
+ ppt: [{
989
+ signature: [
990
+ 208,
991
+ 207,
992
+ 17,
993
+ 224,
994
+ 161,
995
+ 177,
996
+ 26,
997
+ 225
998
+ ],
999
+ mimeType: "application/vnd.ms-powerpoint"
1000
+ }]
1001
+ };
1002
+ /**
1003
+ * All possible format signatures for checking against actual file content
1004
+ */
1005
+ static ALL_SIGNATURES = Object.entries(FileDetector.MAGIC_BYTES).flatMap(([ext, signatures]) => signatures.map((sig) => ({
1006
+ ext,
1007
+ ...sig
1008
+ })));
1009
+ /**
1010
+ * MIME type map for file extensions.
1011
+ *
1012
+ * Can be used to get the content type of file based on its extension.
1013
+ * Feel free to add more mime types in your project!
1014
+ */
1015
+ static mimeMap = {
1016
+ json: "application/json",
1017
+ txt: "text/plain",
1018
+ html: "text/html",
1019
+ htm: "text/html",
1020
+ xml: "application/xml",
1021
+ csv: "text/csv",
1022
+ pdf: "application/pdf",
1023
+ md: "text/markdown",
1024
+ markdown: "text/markdown",
1025
+ rtf: "application/rtf",
1026
+ css: "text/css",
1027
+ js: "application/javascript",
1028
+ mjs: "application/javascript",
1029
+ ts: "application/typescript",
1030
+ jsx: "text/jsx",
1031
+ tsx: "text/tsx",
1032
+ zip: "application/zip",
1033
+ rar: "application/vnd.rar",
1034
+ "7z": "application/x-7z-compressed",
1035
+ tar: "application/x-tar",
1036
+ gz: "application/gzip",
1037
+ tgz: "application/gzip",
1038
+ png: "image/png",
1039
+ jpg: "image/jpeg",
1040
+ jpeg: "image/jpeg",
1041
+ gif: "image/gif",
1042
+ webp: "image/webp",
1043
+ svg: "image/svg+xml",
1044
+ bmp: "image/bmp",
1045
+ ico: "image/x-icon",
1046
+ tiff: "image/tiff",
1047
+ tif: "image/tiff",
1048
+ mp3: "audio/mpeg",
1049
+ wav: "audio/wav",
1050
+ ogg: "audio/ogg",
1051
+ m4a: "audio/mp4",
1052
+ aac: "audio/aac",
1053
+ flac: "audio/flac",
1054
+ mp4: "video/mp4",
1055
+ webm: "video/webm",
1056
+ avi: "video/x-msvideo",
1057
+ mov: "video/quicktime",
1058
+ wmv: "video/x-ms-wmv",
1059
+ flv: "video/x-flv",
1060
+ mkv: "video/x-matroska",
1061
+ doc: "application/msword",
1062
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1063
+ xls: "application/vnd.ms-excel",
1064
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1065
+ ppt: "application/vnd.ms-powerpoint",
1066
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1067
+ woff: "font/woff",
1068
+ woff2: "font/woff2",
1069
+ ttf: "font/ttf",
1070
+ otf: "font/otf",
1071
+ eot: "application/vnd.ms-fontobject"
1072
+ };
1073
+ /**
1074
+ * Reverse MIME type map for looking up extensions from MIME types.
1075
+ * Prefers shorter, more common extensions when multiple exist.
1076
+ */
1077
+ static reverseMimeMap = (() => {
1078
+ const reverse = {};
1079
+ for (const [ext, mimeType] of Object.entries(FileDetector.mimeMap)) if (!reverse[mimeType]) reverse[mimeType] = ext;
1080
+ return reverse;
1081
+ })();
1082
+ /**
1083
+ * Returns the file extension for a given MIME type.
1084
+ *
1085
+ * @param mimeType - The MIME type to look up
1086
+ * @returns The file extension (without dot), or "bin" if not found
1087
+ *
1088
+ * @example
1089
+ * ```typescript
1090
+ * const detector = alepha.inject(FileDetector);
1091
+ * const ext = detector.getExtensionFromMimeType("image/png"); // "png"
1092
+ * const ext2 = detector.getExtensionFromMimeType("application/octet-stream"); // "bin"
1093
+ * ```
1094
+ */
1095
+ getExtensionFromMimeType(mimeType) {
1096
+ return FileDetector.reverseMimeMap[mimeType] || "bin";
1097
+ }
1098
+ /**
1099
+ * Returns the content type of file based on its filename.
1100
+ *
1101
+ * @param filename - The filename to check
1102
+ * @returns The MIME type
1103
+ *
1104
+ * @example
1105
+ * ```typescript
1106
+ * const detector = alepha.inject(FileDetector);
1107
+ * const mimeType = detector.getContentType("image.png"); // "image/png"
1108
+ * ```
1109
+ */
1110
+ getContentType(filename) {
1111
+ const ext = filename.toLowerCase().split(".").pop() || "";
1112
+ return FileDetector.mimeMap[ext] || "application/octet-stream";
1113
+ }
1114
+ /**
1115
+ * Detects the file type by checking magic bytes against the stream content.
1116
+ *
1117
+ * @param stream - The readable stream to check
1118
+ * @param filename - The filename (used to get the extension)
1119
+ * @returns File type information including MIME type, extension, and verification status
1120
+ *
1121
+ * @example
1122
+ * ```typescript
1123
+ * const detector = alepha.inject(FileDetector);
1124
+ * const stream = createReadStream('image.png');
1125
+ * const result = await detector.detectFileType(stream, 'image.png');
1126
+ * console.log(result.mimeType); // 'image/png'
1127
+ * console.log(result.verified); // true if magic bytes match
1128
+ * ```
1129
+ */
1130
+ async detectFileType(stream, filename) {
1131
+ const expectedMimeType = this.getContentType(filename);
1132
+ const lastDotIndex = filename.lastIndexOf(".");
1133
+ const ext = lastDotIndex > 0 ? filename.substring(lastDotIndex + 1).toLowerCase() : "";
1134
+ const { buffer, stream: newStream } = await this.peekBytes(stream, 16);
1135
+ const expectedSignatures = FileDetector.MAGIC_BYTES[ext];
1136
+ if (expectedSignatures) {
1137
+ for (const { signature, mimeType } of expectedSignatures) if (this.matchesSignature(buffer, signature)) return {
1138
+ mimeType,
1139
+ extension: ext,
1140
+ verified: true,
1141
+ stream: newStream
1142
+ };
1143
+ }
1144
+ for (const { ext: detectedExt, signature, mimeType } of FileDetector.ALL_SIGNATURES) if (detectedExt !== ext && this.matchesSignature(buffer, signature)) return {
1145
+ mimeType,
1146
+ extension: detectedExt,
1147
+ verified: true,
1148
+ stream: newStream
1149
+ };
1150
+ return {
1151
+ mimeType: expectedMimeType,
1152
+ extension: ext,
1153
+ verified: false,
1154
+ stream: newStream
1155
+ };
1156
+ }
1157
+ /**
1158
+ * Reads all bytes from a stream and returns the first N bytes along with a new stream containing all data.
1159
+ * This approach reads the entire stream upfront to avoid complex async handling issues.
1160
+ *
1161
+ * @protected
1162
+ */
1163
+ async peekBytes(stream, numBytes) {
1164
+ const chunks = [];
1165
+ for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
1166
+ const allData = Buffer.concat(chunks);
1167
+ return {
1168
+ buffer: allData.subarray(0, numBytes),
1169
+ stream: Readable.from(allData)
1170
+ };
1171
+ }
1172
+ /**
1173
+ * Checks if a buffer matches a magic byte signature.
1174
+ *
1175
+ * @protected
1176
+ */
1177
+ matchesSignature(buffer, signature) {
1178
+ if (buffer.length < signature.length) return false;
1179
+ for (let i = 0; i < signature.length; i++) if (signature[i] !== null && buffer[i] !== signature[i]) return false;
1180
+ return true;
1181
+ }
1182
+ };
1183
+
1184
+ //#endregion
1185
+ //#region ../../src/system/errors/FileError.ts
1186
+ var FileError = class extends Error {
1187
+ constructor(message, cause) {
1188
+ super(message);
1189
+ this.name = "FileError";
1190
+ this.cause = cause;
1191
+ }
1192
+ };
1193
+
1194
+ //#endregion
1195
+ //#region ../../src/system/index.browser.ts
1196
+ const AlephaSystem = $module({
1197
+ name: "alepha.system",
1198
+ services: [
1199
+ FileDetector,
1200
+ FileSystemProvider,
1201
+ MemoryFileSystemProvider,
1202
+ ShellProvider,
1203
+ MemoryShellProvider
1204
+ ],
1205
+ register: (alepha) => alepha.with({
1206
+ optional: true,
1207
+ provide: FileSystemProvider,
1208
+ use: MemoryFileSystemProvider
1209
+ }).with({
1210
+ optional: true,
1211
+ provide: ShellProvider,
1212
+ use: MemoryShellProvider
1213
+ })
1214
+ });
1215
+
1216
+ //#endregion
1217
+ export { AlephaSystem, FileDetector, FileError, FileSystemProvider, MemoryFileSystemProvider, MemoryShellProvider, ShellProvider };
1218
+ //# sourceMappingURL=index.browser.js.map