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,12 +1,15 @@
1
1
  import { AlephaSecurity } from "alepha/security";
2
- import { $atom, $hook, $inject, $module, $use, Alepha, KIND, Primitive, createPrimitive, isTypeFile, t } from "alepha";
2
+ import { $atom, $hook, $inject, $module, $use, Alepha, AlephaError, Json, KIND, Primitive, createPrimitive, isFileLike, isTypeFile, t } from "alepha";
3
3
  import { $action, AlephaServer, ServerProvider, ServerRouterProvider } from "alepha/server";
4
4
  import { AlephaServerCache } from "alepha/server/cache";
5
5
  import { AlephaServerStatic, ServerStaticProvider } from "alepha/server/static";
6
6
  import { join } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
- import { FileSystemProvider } from "alepha/file";
9
8
  import { $logger } from "alepha/logger";
9
+ import { createReadStream } from "node:fs";
10
+ import { access, copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
11
+ import { PassThrough, Readable } from "node:stream";
12
+ import { exec, spawn } from "node:child_process";
10
13
 
11
14
  //#region ../../src/server/swagger/primitives/$swagger.ts
12
15
  /**
@@ -38,6 +41,1846 @@ const $swagger = (options = {}) => {
38
41
  var SwaggerPrimitive = class extends Primitive {};
39
42
  $swagger[KIND] = SwaggerPrimitive;
40
43
 
44
+ //#endregion
45
+ //#region ../../src/system/providers/FileSystemProvider.ts
46
+ /**
47
+ * FileSystem interface providing utilities for working with files.
48
+ */
49
+ var FileSystemProvider = class {};
50
+
51
+ //#endregion
52
+ //#region ../../src/system/providers/MemoryFileSystemProvider.ts
53
+ /**
54
+ * In-memory implementation of FileSystemProvider for testing.
55
+ *
56
+ * This provider stores all files and directories in memory, making it ideal for
57
+ * unit tests that need to verify file operations without touching the real file system.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // In tests, substitute the real FileSystemProvider with MemoryFileSystemProvider
62
+ * const alepha = Alepha.create().with({
63
+ * provide: FileSystemProvider,
64
+ * use: MemoryFileSystemProvider,
65
+ * });
66
+ *
67
+ * // Run code that uses FileSystemProvider
68
+ * const service = alepha.inject(MyService);
69
+ * await service.saveFile("test.txt", "Hello World");
70
+ *
71
+ * // Verify the file was written
72
+ * const memoryFs = alepha.inject(MemoryFileSystemProvider);
73
+ * expect(memoryFs.files.get("test.txt")?.toString()).toBe("Hello World");
74
+ * ```
75
+ */
76
+ var MemoryFileSystemProvider = class {
77
+ json = $inject(Json);
78
+ /**
79
+ * In-memory storage for files (path -> content)
80
+ */
81
+ files = /* @__PURE__ */ new Map();
82
+ /**
83
+ * In-memory storage for directories
84
+ */
85
+ directories = /* @__PURE__ */ new Set();
86
+ /**
87
+ * Track mkdir calls for test assertions
88
+ */
89
+ mkdirCalls = [];
90
+ /**
91
+ * Track writeFile calls for test assertions
92
+ */
93
+ writeFileCalls = [];
94
+ /**
95
+ * Track readFile calls for test assertions
96
+ */
97
+ readFileCalls = [];
98
+ /**
99
+ * Track rm calls for test assertions
100
+ */
101
+ rmCalls = [];
102
+ /**
103
+ * Track join calls for test assertions
104
+ */
105
+ joinCalls = [];
106
+ /**
107
+ * Error to throw on mkdir (for testing error handling)
108
+ */
109
+ mkdirError = null;
110
+ /**
111
+ * Error to throw on writeFile (for testing error handling)
112
+ */
113
+ writeFileError = null;
114
+ /**
115
+ * Error to throw on readFile (for testing error handling)
116
+ */
117
+ readFileError = null;
118
+ constructor(options = {}) {
119
+ this.mkdirError = options.mkdirError ?? null;
120
+ this.writeFileError = options.writeFileError ?? null;
121
+ this.readFileError = options.readFileError ?? null;
122
+ }
123
+ /**
124
+ * Join path segments using forward slashes.
125
+ * Uses Node's path.join for proper normalization (handles .. and .)
126
+ */
127
+ join(...paths) {
128
+ this.joinCalls.push(paths);
129
+ return join(...paths);
130
+ }
131
+ /**
132
+ * Create a FileLike object from various sources.
133
+ */
134
+ createFile(options) {
135
+ if ("path" in options) {
136
+ const filePath = options.path;
137
+ const buffer = this.files.get(filePath);
138
+ if (buffer === void 0) throw new Error(`ENOENT: no such file or directory, open '${filePath}'`);
139
+ return {
140
+ name: options.name ?? filePath.split("/").pop() ?? "file",
141
+ type: options.type ?? "application/octet-stream",
142
+ size: buffer.byteLength,
143
+ lastModified: Date.now(),
144
+ stream: () => {
145
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
146
+ },
147
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
148
+ text: async () => buffer.toString("utf-8")
149
+ };
150
+ }
151
+ if ("buffer" in options) {
152
+ const buffer = options.buffer;
153
+ return {
154
+ name: options.name ?? "file",
155
+ type: options.type ?? "application/octet-stream",
156
+ size: buffer.byteLength,
157
+ lastModified: Date.now(),
158
+ stream: () => {
159
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
160
+ },
161
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
162
+ text: async () => buffer.toString("utf-8")
163
+ };
164
+ }
165
+ if ("text" in options) {
166
+ const buffer = Buffer.from(options.text, "utf-8");
167
+ return {
168
+ name: options.name ?? "file.txt",
169
+ type: options.type ?? "text/plain",
170
+ size: buffer.byteLength,
171
+ lastModified: Date.now(),
172
+ stream: () => {
173
+ throw new Error("Stream not implemented in MemoryFileSystemProvider");
174
+ },
175
+ arrayBuffer: async () => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength),
176
+ text: async () => options.text
177
+ };
178
+ }
179
+ throw new Error("MemoryFileSystemProvider.createFile: unsupported options. Only buffer and text are supported.");
180
+ }
181
+ /**
182
+ * Remove a file or directory from memory.
183
+ */
184
+ async rm(path, options) {
185
+ this.rmCalls.push({
186
+ path,
187
+ options
188
+ });
189
+ if (!(this.files.has(path) || this.directories.has(path)) && !options?.force) throw new Error(`ENOENT: no such file or directory, rm '${path}'`);
190
+ if (this.directories.has(path)) if (options?.recursive) {
191
+ this.directories.delete(path);
192
+ for (const filePath of this.files.keys()) if (filePath.startsWith(`${path}/`)) this.files.delete(filePath);
193
+ for (const dirPath of this.directories) if (dirPath.startsWith(`${path}/`)) this.directories.delete(dirPath);
194
+ } else throw new Error(`EISDIR: illegal operation on a directory, rm '${path}'`);
195
+ else this.files.delete(path);
196
+ }
197
+ /**
198
+ * Copy a file or directory in memory.
199
+ */
200
+ async cp(src, dest, options) {
201
+ if (this.directories.has(src)) {
202
+ if (!options?.recursive) throw new Error(`Cannot copy directory without recursive option: ${src}`);
203
+ this.directories.add(dest);
204
+ for (const [filePath, content] of this.files) if (filePath.startsWith(`${src}/`)) {
205
+ const newPath = filePath.replace(src, dest);
206
+ this.files.set(newPath, Buffer.from(content));
207
+ }
208
+ } else if (this.files.has(src)) {
209
+ const content = this.files.get(src);
210
+ this.files.set(dest, Buffer.from(content));
211
+ } else throw new Error(`ENOENT: no such file or directory, cp '${src}'`);
212
+ }
213
+ /**
214
+ * Move/rename a file or directory in memory.
215
+ */
216
+ async mv(src, dest) {
217
+ if (this.directories.has(src)) {
218
+ this.directories.delete(src);
219
+ this.directories.add(dest);
220
+ for (const [filePath, content] of this.files) if (filePath.startsWith(`${src}/`)) {
221
+ const newPath = filePath.replace(src, dest);
222
+ this.files.delete(filePath);
223
+ this.files.set(newPath, content);
224
+ }
225
+ } else if (this.files.has(src)) {
226
+ const content = this.files.get(src);
227
+ this.files.delete(src);
228
+ this.files.set(dest, content);
229
+ } else throw new Error(`ENOENT: no such file or directory, mv '${src}'`);
230
+ }
231
+ /**
232
+ * Create a directory in memory.
233
+ */
234
+ async mkdir(path, options) {
235
+ this.mkdirCalls.push({
236
+ path,
237
+ options
238
+ });
239
+ if (this.mkdirError) throw this.mkdirError;
240
+ if (this.directories.has(path) && !options?.recursive) throw new Error(`EEXIST: file already exists, mkdir '${path}'`);
241
+ this.directories.add(path);
242
+ if (options?.recursive) {
243
+ const parts = path.split("/").filter(Boolean);
244
+ let current = "";
245
+ for (const part of parts) {
246
+ current = current ? `${current}/${part}` : part;
247
+ this.directories.add(current);
248
+ }
249
+ }
250
+ }
251
+ /**
252
+ * List files in a directory.
253
+ */
254
+ async ls(path, options) {
255
+ const normalizedPath = path.replace(/\/$/, "");
256
+ const entries = /* @__PURE__ */ new Set();
257
+ for (const filePath of this.files.keys()) if (filePath.startsWith(`${normalizedPath}/`)) {
258
+ const relativePath = filePath.slice(normalizedPath.length + 1);
259
+ const parts = relativePath.split("/");
260
+ if (options?.recursive) entries.add(relativePath);
261
+ else entries.add(parts[0]);
262
+ }
263
+ for (const dirPath of this.directories) if (dirPath.startsWith(`${normalizedPath}/`) && dirPath !== normalizedPath) {
264
+ const relativePath = dirPath.slice(normalizedPath.length + 1);
265
+ const parts = relativePath.split("/");
266
+ if (options?.recursive) entries.add(relativePath);
267
+ else if (parts.length === 1) entries.add(parts[0]);
268
+ }
269
+ let result = Array.from(entries);
270
+ if (!options?.hidden) result = result.filter((entry) => !entry.startsWith("."));
271
+ return result.sort();
272
+ }
273
+ /**
274
+ * Check if a file or directory exists in memory.
275
+ */
276
+ async exists(path) {
277
+ return this.files.has(path) || this.directories.has(path);
278
+ }
279
+ /**
280
+ * Read a file from memory.
281
+ */
282
+ async readFile(path) {
283
+ this.readFileCalls.push(path);
284
+ if (this.readFileError) throw this.readFileError;
285
+ const content = this.files.get(path);
286
+ if (!content) throw new Error(`ENOENT: no such file or directory, open '${path}'`);
287
+ return content;
288
+ }
289
+ /**
290
+ * Read a file from memory as text.
291
+ */
292
+ async readTextFile(path) {
293
+ return (await this.readFile(path)).toString("utf-8");
294
+ }
295
+ /**
296
+ * Read a file from memory as JSON.
297
+ */
298
+ async readJsonFile(path) {
299
+ const text = await this.readTextFile(path);
300
+ return this.json.parse(text);
301
+ }
302
+ /**
303
+ * Write a file to memory.
304
+ */
305
+ async writeFile(path, data) {
306
+ const dataStr = typeof data === "string" ? data : data instanceof Buffer || data instanceof Uint8Array ? data.toString("utf-8") : await data.text();
307
+ this.writeFileCalls.push({
308
+ path,
309
+ data: dataStr
310
+ });
311
+ if (this.writeFileError) throw this.writeFileError;
312
+ 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");
313
+ this.files.set(path, buffer);
314
+ }
315
+ /**
316
+ * Reset all in-memory state (useful between tests).
317
+ */
318
+ reset() {
319
+ this.files.clear();
320
+ this.directories.clear();
321
+ this.mkdirCalls = [];
322
+ this.writeFileCalls = [];
323
+ this.readFileCalls = [];
324
+ this.rmCalls = [];
325
+ this.joinCalls = [];
326
+ this.mkdirError = null;
327
+ this.writeFileError = null;
328
+ this.readFileError = null;
329
+ }
330
+ /**
331
+ * Check if a file was written during the test.
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * expect(fs.wasWritten("/project/tsconfig.json")).toBe(true);
336
+ * ```
337
+ */
338
+ wasWritten(path) {
339
+ return this.writeFileCalls.some((call) => call.path === path);
340
+ }
341
+ /**
342
+ * Check if a file was written with content matching a pattern.
343
+ *
344
+ * @example
345
+ * ```typescript
346
+ * expect(fs.wasWrittenMatching("/project/tsconfig.json", /extends/)).toBe(true);
347
+ * ```
348
+ */
349
+ wasWrittenMatching(path, pattern) {
350
+ const call = this.writeFileCalls.find((c) => c.path === path);
351
+ return call ? pattern.test(call.data) : false;
352
+ }
353
+ /**
354
+ * Check if a file was read during the test.
355
+ *
356
+ * @example
357
+ * ```typescript
358
+ * expect(fs.wasRead("/project/package.json")).toBe(true);
359
+ * ```
360
+ */
361
+ wasRead(path) {
362
+ return this.readFileCalls.includes(path);
363
+ }
364
+ /**
365
+ * Check if a file was deleted during the test.
366
+ *
367
+ * @example
368
+ * ```typescript
369
+ * expect(fs.wasDeleted("/project/old-file.txt")).toBe(true);
370
+ * ```
371
+ */
372
+ wasDeleted(path) {
373
+ return this.rmCalls.some((call) => call.path === path);
374
+ }
375
+ /**
376
+ * Get the content of a file as a string (convenience method for testing).
377
+ */
378
+ getFileContent(path) {
379
+ return this.files.get(path)?.toString("utf-8");
380
+ }
381
+ };
382
+
383
+ //#endregion
384
+ //#region ../../src/system/providers/MemoryShellProvider.ts
385
+ /**
386
+ * In-memory implementation of ShellProvider for testing.
387
+ *
388
+ * Records all commands that would be executed without actually running them.
389
+ * Can be configured to return specific outputs or throw errors for testing.
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * // In tests, substitute the real ShellProvider with MemoryShellProvider
394
+ * const alepha = Alepha.create().with({
395
+ * provide: ShellProvider,
396
+ * use: MemoryShellProvider,
397
+ * });
398
+ *
399
+ * // Configure mock behavior
400
+ * const shell = alepha.inject(MemoryShellProvider);
401
+ * shell.configure({
402
+ * outputs: { "echo hello": "hello\n" },
403
+ * errors: { "failing-cmd": "Command failed" },
404
+ * });
405
+ *
406
+ * // Or use the fluent API
407
+ * shell.outputs.set("another-cmd", "output");
408
+ * shell.errors.set("another-error", "Error message");
409
+ *
410
+ * // Run code that uses ShellProvider
411
+ * const service = alepha.inject(MyService);
412
+ * await service.doSomething();
413
+ *
414
+ * // Verify commands were called
415
+ * expect(shell.calls).toHaveLength(2);
416
+ * expect(shell.calls[0].command).toBe("yarn install");
417
+ * ```
418
+ */
419
+ var MemoryShellProvider = class {
420
+ /**
421
+ * All recorded shell calls.
422
+ */
423
+ calls = [];
424
+ /**
425
+ * Simulated outputs for specific commands.
426
+ */
427
+ outputs = /* @__PURE__ */ new Map();
428
+ /**
429
+ * Commands that should throw an error.
430
+ */
431
+ errors = /* @__PURE__ */ new Map();
432
+ /**
433
+ * Commands considered installed in the system PATH.
434
+ */
435
+ installedCommands = /* @__PURE__ */ new Set();
436
+ /**
437
+ * Configure the mock with predefined outputs, errors, and installed commands.
438
+ */
439
+ configure(options) {
440
+ if (options.outputs) for (const [cmd, output] of Object.entries(options.outputs)) this.outputs.set(cmd, output);
441
+ if (options.errors) for (const [cmd, error] of Object.entries(options.errors)) this.errors.set(cmd, error);
442
+ if (options.installedCommands) for (const cmd of options.installedCommands) this.installedCommands.add(cmd);
443
+ return this;
444
+ }
445
+ /**
446
+ * Record command and return simulated output.
447
+ */
448
+ async run(command, options = {}) {
449
+ this.calls.push({
450
+ command,
451
+ options
452
+ });
453
+ const errorMsg = this.errors.get(command);
454
+ if (errorMsg) throw new Error(errorMsg);
455
+ return this.outputs.get(command) ?? "";
456
+ }
457
+ /**
458
+ * Check if a specific command was called.
459
+ */
460
+ wasCalled(command) {
461
+ return this.calls.some((call) => call.command === command);
462
+ }
463
+ /**
464
+ * Check if a command matching a pattern was called.
465
+ */
466
+ wasCalledMatching(pattern) {
467
+ return this.calls.some((call) => pattern.test(call.command));
468
+ }
469
+ /**
470
+ * Get all calls matching a pattern.
471
+ */
472
+ getCallsMatching(pattern) {
473
+ return this.calls.filter((call) => pattern.test(call.command));
474
+ }
475
+ /**
476
+ * Check if a command is installed.
477
+ */
478
+ async isInstalled(command) {
479
+ return this.installedCommands.has(command);
480
+ }
481
+ /**
482
+ * Reset all recorded state.
483
+ */
484
+ reset() {
485
+ this.calls = [];
486
+ this.outputs.clear();
487
+ this.errors.clear();
488
+ this.installedCommands.clear();
489
+ }
490
+ };
491
+
492
+ //#endregion
493
+ //#region ../../src/system/services/FileDetector.ts
494
+ /**
495
+ * Service for detecting file types and getting content types.
496
+ *
497
+ * @example
498
+ * ```typescript
499
+ * const detector = alepha.inject(FileDetector);
500
+ *
501
+ * // Get content type from filename
502
+ * const mimeType = detector.getContentType("image.png"); // "image/png"
503
+ *
504
+ * // Detect file type by magic bytes
505
+ * const stream = createReadStream('image.png');
506
+ * const result = await detector.detectFileType(stream, 'image.png');
507
+ * console.log(result.mimeType); // 'image/png'
508
+ * console.log(result.verified); // true if magic bytes match
509
+ * ```
510
+ */
511
+ var FileDetector = class FileDetector {
512
+ /**
513
+ * Magic byte signatures for common file formats.
514
+ * Each signature is represented as an array of bytes or null (wildcard).
515
+ */
516
+ static MAGIC_BYTES = {
517
+ png: [{
518
+ signature: [
519
+ 137,
520
+ 80,
521
+ 78,
522
+ 71,
523
+ 13,
524
+ 10,
525
+ 26,
526
+ 10
527
+ ],
528
+ mimeType: "image/png"
529
+ }],
530
+ jpg: [
531
+ {
532
+ signature: [
533
+ 255,
534
+ 216,
535
+ 255,
536
+ 224
537
+ ],
538
+ mimeType: "image/jpeg"
539
+ },
540
+ {
541
+ signature: [
542
+ 255,
543
+ 216,
544
+ 255,
545
+ 225
546
+ ],
547
+ mimeType: "image/jpeg"
548
+ },
549
+ {
550
+ signature: [
551
+ 255,
552
+ 216,
553
+ 255,
554
+ 226
555
+ ],
556
+ mimeType: "image/jpeg"
557
+ },
558
+ {
559
+ signature: [
560
+ 255,
561
+ 216,
562
+ 255,
563
+ 227
564
+ ],
565
+ mimeType: "image/jpeg"
566
+ },
567
+ {
568
+ signature: [
569
+ 255,
570
+ 216,
571
+ 255,
572
+ 232
573
+ ],
574
+ mimeType: "image/jpeg"
575
+ }
576
+ ],
577
+ jpeg: [
578
+ {
579
+ signature: [
580
+ 255,
581
+ 216,
582
+ 255,
583
+ 224
584
+ ],
585
+ mimeType: "image/jpeg"
586
+ },
587
+ {
588
+ signature: [
589
+ 255,
590
+ 216,
591
+ 255,
592
+ 225
593
+ ],
594
+ mimeType: "image/jpeg"
595
+ },
596
+ {
597
+ signature: [
598
+ 255,
599
+ 216,
600
+ 255,
601
+ 226
602
+ ],
603
+ mimeType: "image/jpeg"
604
+ },
605
+ {
606
+ signature: [
607
+ 255,
608
+ 216,
609
+ 255,
610
+ 227
611
+ ],
612
+ mimeType: "image/jpeg"
613
+ },
614
+ {
615
+ signature: [
616
+ 255,
617
+ 216,
618
+ 255,
619
+ 232
620
+ ],
621
+ mimeType: "image/jpeg"
622
+ }
623
+ ],
624
+ gif: [{
625
+ signature: [
626
+ 71,
627
+ 73,
628
+ 70,
629
+ 56,
630
+ 55,
631
+ 97
632
+ ],
633
+ mimeType: "image/gif"
634
+ }, {
635
+ signature: [
636
+ 71,
637
+ 73,
638
+ 70,
639
+ 56,
640
+ 57,
641
+ 97
642
+ ],
643
+ mimeType: "image/gif"
644
+ }],
645
+ webp: [{
646
+ signature: [
647
+ 82,
648
+ 73,
649
+ 70,
650
+ 70,
651
+ null,
652
+ null,
653
+ null,
654
+ null,
655
+ 87,
656
+ 69,
657
+ 66,
658
+ 80
659
+ ],
660
+ mimeType: "image/webp"
661
+ }],
662
+ bmp: [{
663
+ signature: [66, 77],
664
+ mimeType: "image/bmp"
665
+ }],
666
+ ico: [{
667
+ signature: [
668
+ 0,
669
+ 0,
670
+ 1,
671
+ 0
672
+ ],
673
+ mimeType: "image/x-icon"
674
+ }],
675
+ tiff: [{
676
+ signature: [
677
+ 73,
678
+ 73,
679
+ 42,
680
+ 0
681
+ ],
682
+ mimeType: "image/tiff"
683
+ }, {
684
+ signature: [
685
+ 77,
686
+ 77,
687
+ 0,
688
+ 42
689
+ ],
690
+ mimeType: "image/tiff"
691
+ }],
692
+ tif: [{
693
+ signature: [
694
+ 73,
695
+ 73,
696
+ 42,
697
+ 0
698
+ ],
699
+ mimeType: "image/tiff"
700
+ }, {
701
+ signature: [
702
+ 77,
703
+ 77,
704
+ 0,
705
+ 42
706
+ ],
707
+ mimeType: "image/tiff"
708
+ }],
709
+ pdf: [{
710
+ signature: [
711
+ 37,
712
+ 80,
713
+ 68,
714
+ 70,
715
+ 45
716
+ ],
717
+ mimeType: "application/pdf"
718
+ }],
719
+ zip: [
720
+ {
721
+ signature: [
722
+ 80,
723
+ 75,
724
+ 3,
725
+ 4
726
+ ],
727
+ mimeType: "application/zip"
728
+ },
729
+ {
730
+ signature: [
731
+ 80,
732
+ 75,
733
+ 5,
734
+ 6
735
+ ],
736
+ mimeType: "application/zip"
737
+ },
738
+ {
739
+ signature: [
740
+ 80,
741
+ 75,
742
+ 7,
743
+ 8
744
+ ],
745
+ mimeType: "application/zip"
746
+ }
747
+ ],
748
+ rar: [{
749
+ signature: [
750
+ 82,
751
+ 97,
752
+ 114,
753
+ 33,
754
+ 26,
755
+ 7
756
+ ],
757
+ mimeType: "application/vnd.rar"
758
+ }],
759
+ "7z": [{
760
+ signature: [
761
+ 55,
762
+ 122,
763
+ 188,
764
+ 175,
765
+ 39,
766
+ 28
767
+ ],
768
+ mimeType: "application/x-7z-compressed"
769
+ }],
770
+ tar: [{
771
+ signature: [
772
+ 117,
773
+ 115,
774
+ 116,
775
+ 97,
776
+ 114
777
+ ],
778
+ mimeType: "application/x-tar"
779
+ }],
780
+ gz: [{
781
+ signature: [31, 139],
782
+ mimeType: "application/gzip"
783
+ }],
784
+ tgz: [{
785
+ signature: [31, 139],
786
+ mimeType: "application/gzip"
787
+ }],
788
+ mp3: [
789
+ {
790
+ signature: [255, 251],
791
+ mimeType: "audio/mpeg"
792
+ },
793
+ {
794
+ signature: [255, 243],
795
+ mimeType: "audio/mpeg"
796
+ },
797
+ {
798
+ signature: [255, 242],
799
+ mimeType: "audio/mpeg"
800
+ },
801
+ {
802
+ signature: [
803
+ 73,
804
+ 68,
805
+ 51
806
+ ],
807
+ mimeType: "audio/mpeg"
808
+ }
809
+ ],
810
+ wav: [{
811
+ signature: [
812
+ 82,
813
+ 73,
814
+ 70,
815
+ 70,
816
+ null,
817
+ null,
818
+ null,
819
+ null,
820
+ 87,
821
+ 65,
822
+ 86,
823
+ 69
824
+ ],
825
+ mimeType: "audio/wav"
826
+ }],
827
+ ogg: [{
828
+ signature: [
829
+ 79,
830
+ 103,
831
+ 103,
832
+ 83
833
+ ],
834
+ mimeType: "audio/ogg"
835
+ }],
836
+ flac: [{
837
+ signature: [
838
+ 102,
839
+ 76,
840
+ 97,
841
+ 67
842
+ ],
843
+ mimeType: "audio/flac"
844
+ }],
845
+ mp4: [
846
+ {
847
+ signature: [
848
+ null,
849
+ null,
850
+ null,
851
+ null,
852
+ 102,
853
+ 116,
854
+ 121,
855
+ 112
856
+ ],
857
+ mimeType: "video/mp4"
858
+ },
859
+ {
860
+ signature: [
861
+ null,
862
+ null,
863
+ null,
864
+ null,
865
+ 102,
866
+ 116,
867
+ 121,
868
+ 112,
869
+ 105,
870
+ 115,
871
+ 111,
872
+ 109
873
+ ],
874
+ mimeType: "video/mp4"
875
+ },
876
+ {
877
+ signature: [
878
+ null,
879
+ null,
880
+ null,
881
+ null,
882
+ 102,
883
+ 116,
884
+ 121,
885
+ 112,
886
+ 109,
887
+ 112,
888
+ 52,
889
+ 50
890
+ ],
891
+ mimeType: "video/mp4"
892
+ }
893
+ ],
894
+ webm: [{
895
+ signature: [
896
+ 26,
897
+ 69,
898
+ 223,
899
+ 163
900
+ ],
901
+ mimeType: "video/webm"
902
+ }],
903
+ avi: [{
904
+ signature: [
905
+ 82,
906
+ 73,
907
+ 70,
908
+ 70,
909
+ null,
910
+ null,
911
+ null,
912
+ null,
913
+ 65,
914
+ 86,
915
+ 73,
916
+ 32
917
+ ],
918
+ mimeType: "video/x-msvideo"
919
+ }],
920
+ mov: [{
921
+ signature: [
922
+ null,
923
+ null,
924
+ null,
925
+ null,
926
+ 102,
927
+ 116,
928
+ 121,
929
+ 112,
930
+ 113,
931
+ 116,
932
+ 32,
933
+ 32
934
+ ],
935
+ mimeType: "video/quicktime"
936
+ }],
937
+ mkv: [{
938
+ signature: [
939
+ 26,
940
+ 69,
941
+ 223,
942
+ 163
943
+ ],
944
+ mimeType: "video/x-matroska"
945
+ }],
946
+ docx: [{
947
+ signature: [
948
+ 80,
949
+ 75,
950
+ 3,
951
+ 4
952
+ ],
953
+ mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
954
+ }],
955
+ xlsx: [{
956
+ signature: [
957
+ 80,
958
+ 75,
959
+ 3,
960
+ 4
961
+ ],
962
+ mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
963
+ }],
964
+ pptx: [{
965
+ signature: [
966
+ 80,
967
+ 75,
968
+ 3,
969
+ 4
970
+ ],
971
+ mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
972
+ }],
973
+ doc: [{
974
+ signature: [
975
+ 208,
976
+ 207,
977
+ 17,
978
+ 224,
979
+ 161,
980
+ 177,
981
+ 26,
982
+ 225
983
+ ],
984
+ mimeType: "application/msword"
985
+ }],
986
+ xls: [{
987
+ signature: [
988
+ 208,
989
+ 207,
990
+ 17,
991
+ 224,
992
+ 161,
993
+ 177,
994
+ 26,
995
+ 225
996
+ ],
997
+ mimeType: "application/vnd.ms-excel"
998
+ }],
999
+ ppt: [{
1000
+ signature: [
1001
+ 208,
1002
+ 207,
1003
+ 17,
1004
+ 224,
1005
+ 161,
1006
+ 177,
1007
+ 26,
1008
+ 225
1009
+ ],
1010
+ mimeType: "application/vnd.ms-powerpoint"
1011
+ }]
1012
+ };
1013
+ /**
1014
+ * All possible format signatures for checking against actual file content
1015
+ */
1016
+ static ALL_SIGNATURES = Object.entries(FileDetector.MAGIC_BYTES).flatMap(([ext, signatures]) => signatures.map((sig) => ({
1017
+ ext,
1018
+ ...sig
1019
+ })));
1020
+ /**
1021
+ * MIME type map for file extensions.
1022
+ *
1023
+ * Can be used to get the content type of file based on its extension.
1024
+ * Feel free to add more mime types in your project!
1025
+ */
1026
+ static mimeMap = {
1027
+ json: "application/json",
1028
+ txt: "text/plain",
1029
+ html: "text/html",
1030
+ htm: "text/html",
1031
+ xml: "application/xml",
1032
+ csv: "text/csv",
1033
+ pdf: "application/pdf",
1034
+ md: "text/markdown",
1035
+ markdown: "text/markdown",
1036
+ rtf: "application/rtf",
1037
+ css: "text/css",
1038
+ js: "application/javascript",
1039
+ mjs: "application/javascript",
1040
+ ts: "application/typescript",
1041
+ jsx: "text/jsx",
1042
+ tsx: "text/tsx",
1043
+ zip: "application/zip",
1044
+ rar: "application/vnd.rar",
1045
+ "7z": "application/x-7z-compressed",
1046
+ tar: "application/x-tar",
1047
+ gz: "application/gzip",
1048
+ tgz: "application/gzip",
1049
+ png: "image/png",
1050
+ jpg: "image/jpeg",
1051
+ jpeg: "image/jpeg",
1052
+ gif: "image/gif",
1053
+ webp: "image/webp",
1054
+ svg: "image/svg+xml",
1055
+ bmp: "image/bmp",
1056
+ ico: "image/x-icon",
1057
+ tiff: "image/tiff",
1058
+ tif: "image/tiff",
1059
+ mp3: "audio/mpeg",
1060
+ wav: "audio/wav",
1061
+ ogg: "audio/ogg",
1062
+ m4a: "audio/mp4",
1063
+ aac: "audio/aac",
1064
+ flac: "audio/flac",
1065
+ mp4: "video/mp4",
1066
+ webm: "video/webm",
1067
+ avi: "video/x-msvideo",
1068
+ mov: "video/quicktime",
1069
+ wmv: "video/x-ms-wmv",
1070
+ flv: "video/x-flv",
1071
+ mkv: "video/x-matroska",
1072
+ doc: "application/msword",
1073
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1074
+ xls: "application/vnd.ms-excel",
1075
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1076
+ ppt: "application/vnd.ms-powerpoint",
1077
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1078
+ woff: "font/woff",
1079
+ woff2: "font/woff2",
1080
+ ttf: "font/ttf",
1081
+ otf: "font/otf",
1082
+ eot: "application/vnd.ms-fontobject"
1083
+ };
1084
+ /**
1085
+ * Reverse MIME type map for looking up extensions from MIME types.
1086
+ * Prefers shorter, more common extensions when multiple exist.
1087
+ */
1088
+ static reverseMimeMap = (() => {
1089
+ const reverse = {};
1090
+ for (const [ext, mimeType] of Object.entries(FileDetector.mimeMap)) if (!reverse[mimeType]) reverse[mimeType] = ext;
1091
+ return reverse;
1092
+ })();
1093
+ /**
1094
+ * Returns the file extension for a given MIME type.
1095
+ *
1096
+ * @param mimeType - The MIME type to look up
1097
+ * @returns The file extension (without dot), or "bin" if not found
1098
+ *
1099
+ * @example
1100
+ * ```typescript
1101
+ * const detector = alepha.inject(FileDetector);
1102
+ * const ext = detector.getExtensionFromMimeType("image/png"); // "png"
1103
+ * const ext2 = detector.getExtensionFromMimeType("application/octet-stream"); // "bin"
1104
+ * ```
1105
+ */
1106
+ getExtensionFromMimeType(mimeType) {
1107
+ return FileDetector.reverseMimeMap[mimeType] || "bin";
1108
+ }
1109
+ /**
1110
+ * Returns the content type of file based on its filename.
1111
+ *
1112
+ * @param filename - The filename to check
1113
+ * @returns The MIME type
1114
+ *
1115
+ * @example
1116
+ * ```typescript
1117
+ * const detector = alepha.inject(FileDetector);
1118
+ * const mimeType = detector.getContentType("image.png"); // "image/png"
1119
+ * ```
1120
+ */
1121
+ getContentType(filename) {
1122
+ const ext = filename.toLowerCase().split(".").pop() || "";
1123
+ return FileDetector.mimeMap[ext] || "application/octet-stream";
1124
+ }
1125
+ /**
1126
+ * Detects the file type by checking magic bytes against the stream content.
1127
+ *
1128
+ * @param stream - The readable stream to check
1129
+ * @param filename - The filename (used to get the extension)
1130
+ * @returns File type information including MIME type, extension, and verification status
1131
+ *
1132
+ * @example
1133
+ * ```typescript
1134
+ * const detector = alepha.inject(FileDetector);
1135
+ * const stream = createReadStream('image.png');
1136
+ * const result = await detector.detectFileType(stream, 'image.png');
1137
+ * console.log(result.mimeType); // 'image/png'
1138
+ * console.log(result.verified); // true if magic bytes match
1139
+ * ```
1140
+ */
1141
+ async detectFileType(stream, filename) {
1142
+ const expectedMimeType = this.getContentType(filename);
1143
+ const lastDotIndex = filename.lastIndexOf(".");
1144
+ const ext = lastDotIndex > 0 ? filename.substring(lastDotIndex + 1).toLowerCase() : "";
1145
+ const { buffer, stream: newStream } = await this.peekBytes(stream, 16);
1146
+ const expectedSignatures = FileDetector.MAGIC_BYTES[ext];
1147
+ if (expectedSignatures) {
1148
+ for (const { signature, mimeType } of expectedSignatures) if (this.matchesSignature(buffer, signature)) return {
1149
+ mimeType,
1150
+ extension: ext,
1151
+ verified: true,
1152
+ stream: newStream
1153
+ };
1154
+ }
1155
+ for (const { ext: detectedExt, signature, mimeType } of FileDetector.ALL_SIGNATURES) if (detectedExt !== ext && this.matchesSignature(buffer, signature)) return {
1156
+ mimeType,
1157
+ extension: detectedExt,
1158
+ verified: true,
1159
+ stream: newStream
1160
+ };
1161
+ return {
1162
+ mimeType: expectedMimeType,
1163
+ extension: ext,
1164
+ verified: false,
1165
+ stream: newStream
1166
+ };
1167
+ }
1168
+ /**
1169
+ * Reads all bytes from a stream and returns the first N bytes along with a new stream containing all data.
1170
+ * This approach reads the entire stream upfront to avoid complex async handling issues.
1171
+ *
1172
+ * @protected
1173
+ */
1174
+ async peekBytes(stream, numBytes) {
1175
+ const chunks = [];
1176
+ for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
1177
+ const allData = Buffer.concat(chunks);
1178
+ return {
1179
+ buffer: allData.subarray(0, numBytes),
1180
+ stream: Readable.from(allData)
1181
+ };
1182
+ }
1183
+ /**
1184
+ * Checks if a buffer matches a magic byte signature.
1185
+ *
1186
+ * @protected
1187
+ */
1188
+ matchesSignature(buffer, signature) {
1189
+ if (buffer.length < signature.length) return false;
1190
+ for (let i = 0; i < signature.length; i++) if (signature[i] !== null && buffer[i] !== signature[i]) return false;
1191
+ return true;
1192
+ }
1193
+ };
1194
+
1195
+ //#endregion
1196
+ //#region ../../src/system/providers/NodeFileSystemProvider.ts
1197
+ /**
1198
+ * Node.js implementation of FileSystem interface.
1199
+ *
1200
+ * @example
1201
+ * ```typescript
1202
+ * const fs = alepha.inject(NodeFileSystemProvider);
1203
+ *
1204
+ * // Create from URL
1205
+ * const file1 = fs.createFile({ url: "file:///path/to/file.png" });
1206
+ *
1207
+ * // Create from Buffer
1208
+ * const file2 = fs.createFile({ buffer: Buffer.from("hello"), name: "hello.txt" });
1209
+ *
1210
+ * // Create from text
1211
+ * const file3 = fs.createFile({ text: "Hello, world!", name: "greeting.txt" });
1212
+ *
1213
+ * // File operations
1214
+ * await fs.mkdir("/tmp/mydir", { recursive: true });
1215
+ * await fs.cp("/src/file.txt", "/dest/file.txt");
1216
+ * await fs.mv("/old/path.txt", "/new/path.txt");
1217
+ * const files = await fs.ls("/tmp");
1218
+ * await fs.rm("/tmp/file.txt");
1219
+ * ```
1220
+ */
1221
+ var NodeFileSystemProvider = class {
1222
+ detector = $inject(FileDetector);
1223
+ json = $inject(Json);
1224
+ join(...paths) {
1225
+ return join(...paths);
1226
+ }
1227
+ /**
1228
+ * Creates a FileLike object from various sources.
1229
+ *
1230
+ * @param options - Options for creating the file
1231
+ * @returns A FileLike object
1232
+ *
1233
+ * @example
1234
+ * ```typescript
1235
+ * const fs = alepha.inject(NodeFileSystemProvider);
1236
+ *
1237
+ * // From URL
1238
+ * const file1 = fs.createFile({ url: "https://example.com/image.png" });
1239
+ *
1240
+ * // From Buffer
1241
+ * const file2 = fs.createFile({
1242
+ * buffer: Buffer.from("hello"),
1243
+ * name: "hello.txt",
1244
+ * type: "text/plain"
1245
+ * });
1246
+ *
1247
+ * // From text
1248
+ * const file3 = fs.createFile({ text: "Hello!", name: "greeting.txt" });
1249
+ *
1250
+ * // From stream with detection
1251
+ * const stream = createReadStream("/path/to/file.png");
1252
+ * const file4 = fs.createFile({ stream, name: "image.png" });
1253
+ * ```
1254
+ */
1255
+ createFile(options) {
1256
+ if ("path" in options) {
1257
+ const path = options.path;
1258
+ const filename = path.split("/").pop() || "file";
1259
+ return this.createFileFromUrl(`file://${path}`, {
1260
+ type: options.type,
1261
+ name: options.name || filename
1262
+ });
1263
+ }
1264
+ if ("url" in options) return this.createFileFromUrl(options.url, {
1265
+ type: options.type,
1266
+ name: options.name
1267
+ });
1268
+ if ("response" in options) {
1269
+ if (!options.response.body) throw new AlephaError("Response has no body stream");
1270
+ const res = options.response;
1271
+ const sizeHeader = res.headers.get("content-length");
1272
+ const size = sizeHeader ? parseInt(sizeHeader, 10) : void 0;
1273
+ let name = options.name;
1274
+ const contentDisposition = res.headers.get("content-disposition");
1275
+ if (contentDisposition && !name) {
1276
+ const match = contentDisposition.match(/filename="?([^"]+)"?/);
1277
+ if (match) name = match[1];
1278
+ }
1279
+ const type = options.type || res.headers.get("content-type") || void 0;
1280
+ return this.createFileFromStream(options.response.body, {
1281
+ type,
1282
+ name,
1283
+ size
1284
+ });
1285
+ }
1286
+ if ("file" in options) return this.createFileFromWebFile(options.file, {
1287
+ type: options.type,
1288
+ name: options.name,
1289
+ size: options.size
1290
+ });
1291
+ if ("buffer" in options) return this.createFileFromBuffer(options.buffer, {
1292
+ type: options.type,
1293
+ name: options.name
1294
+ });
1295
+ if ("arrayBuffer" in options) return this.createFileFromBuffer(Buffer.from(options.arrayBuffer), {
1296
+ type: options.type,
1297
+ name: options.name
1298
+ });
1299
+ if ("text" in options) return this.createFileFromBuffer(Buffer.from(options.text, "utf-8"), {
1300
+ type: options.type || "text/plain",
1301
+ name: options.name || "file.txt"
1302
+ });
1303
+ if ("stream" in options) return this.createFileFromStream(options.stream, {
1304
+ type: options.type,
1305
+ name: options.name,
1306
+ size: options.size
1307
+ });
1308
+ throw new AlephaError("Invalid createFile options: no valid source provided");
1309
+ }
1310
+ /**
1311
+ * Removes a file or directory.
1312
+ *
1313
+ * @param path - The path to remove
1314
+ * @param options - Remove options
1315
+ *
1316
+ * @example
1317
+ * ```typescript
1318
+ * const fs = alepha.inject(NodeFileSystemProvider);
1319
+ *
1320
+ * // Remove a file
1321
+ * await fs.rm("/tmp/file.txt");
1322
+ *
1323
+ * // Remove a directory recursively
1324
+ * await fs.rm("/tmp/mydir", { recursive: true });
1325
+ *
1326
+ * // Remove with force (no error if doesn't exist)
1327
+ * await fs.rm("/tmp/maybe-exists.txt", { force: true });
1328
+ * ```
1329
+ */
1330
+ async rm(path, options) {
1331
+ await rm(path, options);
1332
+ }
1333
+ /**
1334
+ * Copies a file or directory.
1335
+ *
1336
+ * @param src - Source path
1337
+ * @param dest - Destination path
1338
+ * @param options - Copy options
1339
+ *
1340
+ * @example
1341
+ * ```typescript
1342
+ * const fs = alepha.inject(NodeFileSystemProvider);
1343
+ *
1344
+ * // Copy a file
1345
+ * await fs.cp("/src/file.txt", "/dest/file.txt");
1346
+ *
1347
+ * // Copy a directory recursively
1348
+ * await fs.cp("/src/dir", "/dest/dir", { recursive: true });
1349
+ *
1350
+ * // Copy with force (overwrite existing)
1351
+ * await fs.cp("/src/file.txt", "/dest/file.txt", { force: true });
1352
+ * ```
1353
+ */
1354
+ async cp(src, dest, options) {
1355
+ if ((await stat(src)).isDirectory()) {
1356
+ if (!options?.recursive) throw new Error(`Cannot copy directory without recursive option: ${src}`);
1357
+ await cp(src, dest, {
1358
+ recursive: true,
1359
+ force: options?.force ?? false
1360
+ });
1361
+ } else await copyFile(src, dest);
1362
+ }
1363
+ /**
1364
+ * Moves/renames a file or directory.
1365
+ *
1366
+ * @param src - Source path
1367
+ * @param dest - Destination path
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * const fs = alepha.inject(NodeFileSystemProvider);
1372
+ *
1373
+ * // Move/rename a file
1374
+ * await fs.mv("/old/path.txt", "/new/path.txt");
1375
+ *
1376
+ * // Move a directory
1377
+ * await fs.mv("/old/dir", "/new/dir");
1378
+ * ```
1379
+ */
1380
+ async mv(src, dest) {
1381
+ await rename(src, dest);
1382
+ }
1383
+ /**
1384
+ * Creates a directory.
1385
+ *
1386
+ * @param path - The directory path to create
1387
+ * @param options - Mkdir options
1388
+ *
1389
+ * @example
1390
+ * ```typescript
1391
+ * const fs = alepha.inject(NodeFileSystemProvider);
1392
+ *
1393
+ * // Create a directory
1394
+ * await fs.mkdir("/tmp/mydir");
1395
+ *
1396
+ * // Create nested directories
1397
+ * await fs.mkdir("/tmp/path/to/dir", { recursive: true });
1398
+ *
1399
+ * // Create with specific permissions
1400
+ * await fs.mkdir("/tmp/mydir", { mode: 0o755 });
1401
+ * ```
1402
+ */
1403
+ async mkdir(path, options = {}) {
1404
+ const p = mkdir(path, {
1405
+ recursive: options.recursive ?? true,
1406
+ mode: options.mode
1407
+ });
1408
+ if (options.force === false) await p;
1409
+ else await p.catch(() => {});
1410
+ }
1411
+ /**
1412
+ * Lists files in a directory.
1413
+ *
1414
+ * @param path - The directory path to list
1415
+ * @param options - List options
1416
+ * @returns Array of filenames
1417
+ *
1418
+ * @example
1419
+ * ```typescript
1420
+ * const fs = alepha.inject(NodeFileSystemProvider);
1421
+ *
1422
+ * // List files in a directory
1423
+ * const files = await fs.ls("/tmp");
1424
+ * console.log(files); // ["file1.txt", "file2.txt", "subdir"]
1425
+ *
1426
+ * // List with hidden files
1427
+ * const allFiles = await fs.ls("/tmp", { hidden: true });
1428
+ *
1429
+ * // List recursively
1430
+ * const allFilesRecursive = await fs.ls("/tmp", { recursive: true });
1431
+ * ```
1432
+ */
1433
+ async ls(path, options) {
1434
+ const entries = await readdir(path);
1435
+ const filteredEntries = options?.hidden ? entries : entries.filter((e) => !e.startsWith("."));
1436
+ if (options?.recursive) {
1437
+ const allFiles = [];
1438
+ for (const entry of filteredEntries) {
1439
+ const fullPath = join(path, entry);
1440
+ if ((await stat(fullPath)).isDirectory()) {
1441
+ allFiles.push(entry);
1442
+ const subFiles = await this.ls(fullPath, options);
1443
+ allFiles.push(...subFiles.map((f) => join(entry, f)));
1444
+ } else allFiles.push(entry);
1445
+ }
1446
+ return allFiles;
1447
+ }
1448
+ return filteredEntries;
1449
+ }
1450
+ /**
1451
+ * Checks if a file or directory exists.
1452
+ *
1453
+ * @param path - The path to check
1454
+ * @returns True if the path exists, false otherwise
1455
+ *
1456
+ * @example
1457
+ * ```typescript
1458
+ * const fs = alepha.inject(NodeFileSystemProvider);
1459
+ *
1460
+ * if (await fs.exists("/tmp/file.txt")) {
1461
+ * console.log("File exists");
1462
+ * }
1463
+ * ```
1464
+ */
1465
+ async exists(path) {
1466
+ try {
1467
+ await access(path);
1468
+ return true;
1469
+ } catch {
1470
+ return false;
1471
+ }
1472
+ }
1473
+ /**
1474
+ * Reads the content of a file.
1475
+ *
1476
+ * @param path - The file path to read
1477
+ * @returns The file content as a Buffer
1478
+ *
1479
+ * @example
1480
+ * ```typescript
1481
+ * const fs = alepha.inject(NodeFileSystemProvider);
1482
+ *
1483
+ * const buffer = await fs.readFile("/tmp/file.txt");
1484
+ * console.log(buffer.toString("utf-8"));
1485
+ * ```
1486
+ */
1487
+ async readFile(path) {
1488
+ return await readFile(path);
1489
+ }
1490
+ /**
1491
+ * Writes data to a file.
1492
+ *
1493
+ * @param path - The file path to write to
1494
+ * @param data - The data to write (Buffer or string)
1495
+ *
1496
+ * @example
1497
+ * ```typescript
1498
+ * const fs = alepha.inject(NodeFileSystemProvider);
1499
+ *
1500
+ * // Write string
1501
+ * await fs.writeFile("/tmp/file.txt", "Hello, world!");
1502
+ *
1503
+ * // Write Buffer
1504
+ * await fs.writeFile("/tmp/file.bin", Buffer.from([0x01, 0x02, 0x03]));
1505
+ * ```
1506
+ */
1507
+ async writeFile(path, data) {
1508
+ if (isFileLike(data)) {
1509
+ await writeFile(path, Readable.from(data.stream()));
1510
+ return;
1511
+ }
1512
+ await writeFile(path, data);
1513
+ }
1514
+ /**
1515
+ * Reads the content of a file as a string.
1516
+ *
1517
+ * @param path - The file path to read
1518
+ * @returns The file content as a string
1519
+ *
1520
+ * @example
1521
+ * ```typescript
1522
+ * const fs = alepha.inject(NodeFileSystemProvider);
1523
+ * const content = await fs.readTextFile("/tmp/file.txt");
1524
+ * ```
1525
+ */
1526
+ async readTextFile(path) {
1527
+ return (await this.readFile(path)).toString("utf-8");
1528
+ }
1529
+ /**
1530
+ * Reads the content of a file as JSON.
1531
+ *
1532
+ * @param path - The file path to read
1533
+ * @returns The parsed JSON content
1534
+ *
1535
+ * @example
1536
+ * ```typescript
1537
+ * const fs = alepha.inject(NodeFileSystemProvider);
1538
+ * const config = await fs.readJsonFile<{ name: string }>("/tmp/config.json");
1539
+ * ```
1540
+ */
1541
+ async readJsonFile(path) {
1542
+ const text = await this.readTextFile(path);
1543
+ return this.json.parse(text);
1544
+ }
1545
+ /**
1546
+ * Creates a FileLike object from a Web File.
1547
+ *
1548
+ * @protected
1549
+ */
1550
+ createFileFromWebFile(source, options = {}) {
1551
+ const name = options.name ?? source.name;
1552
+ return {
1553
+ name,
1554
+ type: options.type ?? (source.type || this.detector.getContentType(name)),
1555
+ size: options.size ?? source.size ?? 0,
1556
+ lastModified: source.lastModified || Date.now(),
1557
+ stream: () => source.stream(),
1558
+ arrayBuffer: async () => {
1559
+ return await source.arrayBuffer();
1560
+ },
1561
+ text: async () => {
1562
+ return await source.text();
1563
+ }
1564
+ };
1565
+ }
1566
+ /**
1567
+ * Creates a FileLike object from a Buffer.
1568
+ *
1569
+ * @protected
1570
+ */
1571
+ createFileFromBuffer(source, options = {}) {
1572
+ const name = options.name ?? "file";
1573
+ return {
1574
+ name,
1575
+ type: options.type ?? this.detector.getContentType(options.name ?? name),
1576
+ size: source.byteLength,
1577
+ lastModified: Date.now(),
1578
+ stream: () => Readable.from(source),
1579
+ arrayBuffer: async () => {
1580
+ return this.bufferToArrayBuffer(source);
1581
+ },
1582
+ text: async () => {
1583
+ return source.toString("utf-8");
1584
+ }
1585
+ };
1586
+ }
1587
+ /**
1588
+ * Creates a FileLike object from a stream.
1589
+ *
1590
+ * @protected
1591
+ */
1592
+ createFileFromStream(source, options = {}) {
1593
+ let buffer = null;
1594
+ return {
1595
+ name: options.name ?? "file",
1596
+ type: options.type ?? this.detector.getContentType(options.name ?? "file"),
1597
+ size: options.size ?? 0,
1598
+ lastModified: Date.now(),
1599
+ stream: () => source,
1600
+ _buffer: null,
1601
+ arrayBuffer: async () => {
1602
+ buffer ??= await this.streamToBuffer(source);
1603
+ return this.bufferToArrayBuffer(buffer);
1604
+ },
1605
+ text: async () => {
1606
+ buffer ??= await this.streamToBuffer(source);
1607
+ return buffer.toString("utf-8");
1608
+ }
1609
+ };
1610
+ }
1611
+ /**
1612
+ * Creates a FileLike object from a URL.
1613
+ *
1614
+ * @protected
1615
+ */
1616
+ createFileFromUrl(url, options = {}) {
1617
+ const parsedUrl = new URL(url);
1618
+ const filename = options.name || parsedUrl.pathname.split("/").pop() || "file";
1619
+ let buffer = null;
1620
+ return {
1621
+ name: filename,
1622
+ type: options.type ?? this.detector.getContentType(filename),
1623
+ size: 0,
1624
+ lastModified: Date.now(),
1625
+ stream: () => this.createStreamFromUrl(url),
1626
+ arrayBuffer: async () => {
1627
+ buffer ??= await this.loadFromUrl(url);
1628
+ return this.bufferToArrayBuffer(buffer);
1629
+ },
1630
+ text: async () => {
1631
+ buffer ??= await this.loadFromUrl(url);
1632
+ return buffer.toString("utf-8");
1633
+ },
1634
+ filepath: url
1635
+ };
1636
+ }
1637
+ /**
1638
+ * Gets a streaming response from a URL.
1639
+ *
1640
+ * @protected
1641
+ */
1642
+ getStreamingResponse(url) {
1643
+ const stream = new PassThrough();
1644
+ fetch(url).then((res) => Readable.fromWeb(res.body).pipe(stream)).catch((err) => stream.destroy(err));
1645
+ return stream;
1646
+ }
1647
+ /**
1648
+ * Loads data from a URL.
1649
+ *
1650
+ * @protected
1651
+ */
1652
+ async loadFromUrl(url) {
1653
+ const parsedUrl = new URL(url);
1654
+ if (parsedUrl.protocol === "file:") return await readFile(fileURLToPath(url));
1655
+ else if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
1656
+ const response = await fetch(url);
1657
+ if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
1658
+ const arrayBuffer = await response.arrayBuffer();
1659
+ return Buffer.from(arrayBuffer);
1660
+ } else throw new Error(`Unsupported protocol: ${parsedUrl.protocol}`);
1661
+ }
1662
+ /**
1663
+ * Creates a stream from a URL.
1664
+ *
1665
+ * @protected
1666
+ */
1667
+ createStreamFromUrl(url) {
1668
+ const parsedUrl = new URL(url);
1669
+ if (parsedUrl.protocol === "file:") return createReadStream(fileURLToPath(url));
1670
+ else if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") return this.getStreamingResponse(url);
1671
+ else throw new AlephaError(`Unsupported protocol: ${parsedUrl.protocol}`);
1672
+ }
1673
+ /**
1674
+ * Converts a stream-like object to a Buffer.
1675
+ *
1676
+ * @protected
1677
+ */
1678
+ async streamToBuffer(streamLike) {
1679
+ const stream = streamLike instanceof Readable ? streamLike : Readable.fromWeb(streamLike);
1680
+ return new Promise((resolve, reject) => {
1681
+ const buffer = [];
1682
+ stream.on("data", (chunk) => buffer.push(Buffer.from(chunk)));
1683
+ stream.on("end", () => resolve(Buffer.concat(buffer)));
1684
+ stream.on("error", (err) => reject(new AlephaError("Error converting stream", { cause: err })));
1685
+ });
1686
+ }
1687
+ /**
1688
+ * Converts a Node.js Buffer to an ArrayBuffer.
1689
+ *
1690
+ * @protected
1691
+ */
1692
+ bufferToArrayBuffer(buffer) {
1693
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
1694
+ }
1695
+ };
1696
+
1697
+ //#endregion
1698
+ //#region ../../src/system/providers/NodeShellProvider.ts
1699
+ /**
1700
+ * Node.js implementation of ShellProvider.
1701
+ *
1702
+ * Executes shell commands using Node.js child_process module.
1703
+ * Supports binary resolution from node_modules/.bin for local packages.
1704
+ */
1705
+ var NodeShellProvider = class {
1706
+ log = $logger();
1707
+ fs = $inject(FileSystemProvider);
1708
+ /**
1709
+ * Run a shell command or binary.
1710
+ */
1711
+ async run(command, options = {}) {
1712
+ const { resolve = false, capture = false, root, env } = options;
1713
+ const cwd = root ?? process.cwd();
1714
+ this.log.debug(`Shell: ${command}`, {
1715
+ cwd,
1716
+ resolve,
1717
+ capture
1718
+ });
1719
+ let executable;
1720
+ let args;
1721
+ if (resolve) {
1722
+ const [bin, ...rest] = command.split(" ");
1723
+ executable = await this.resolveExecutable(bin, cwd);
1724
+ args = rest;
1725
+ } else [executable, ...args] = command.split(" ");
1726
+ if (capture) return this.execCapture(command, {
1727
+ cwd,
1728
+ env
1729
+ });
1730
+ return this.execInherit(executable, args, {
1731
+ cwd,
1732
+ env
1733
+ });
1734
+ }
1735
+ /**
1736
+ * Execute command with inherited stdio (streams to terminal).
1737
+ */
1738
+ async execInherit(executable, args, options) {
1739
+ const proc = spawn(executable, args, {
1740
+ stdio: "inherit",
1741
+ cwd: options.cwd,
1742
+ env: {
1743
+ ...process.env,
1744
+ ...options.env
1745
+ }
1746
+ });
1747
+ return new Promise((resolve, reject) => {
1748
+ proc.on("exit", (code) => {
1749
+ if (code === 0 || code === null) resolve("");
1750
+ else reject(new AlephaError(`Command exited with code ${code}`));
1751
+ });
1752
+ proc.on("error", reject);
1753
+ });
1754
+ }
1755
+ /**
1756
+ * Execute command and capture stdout.
1757
+ */
1758
+ execCapture(command, options) {
1759
+ return new Promise((resolve, reject) => {
1760
+ exec(command, {
1761
+ cwd: options.cwd,
1762
+ env: {
1763
+ ...process.env,
1764
+ LOG_FORMAT: "pretty",
1765
+ ...options.env
1766
+ }
1767
+ }, (err, stdout) => {
1768
+ if (err) {
1769
+ err.stdout = stdout;
1770
+ reject(err);
1771
+ } else resolve(stdout);
1772
+ });
1773
+ });
1774
+ }
1775
+ /**
1776
+ * Resolve executable path from node_modules/.bin.
1777
+ *
1778
+ * Search order:
1779
+ * 1. Local: node_modules/.bin/
1780
+ * 2. Pnpm nested: node_modules/alepha/node_modules/.bin/
1781
+ * 3. Monorepo: Walk up to 3 parent directories
1782
+ */
1783
+ async resolveExecutable(name, root) {
1784
+ const suffix = process.platform === "win32" ? ".cmd" : "";
1785
+ let execPath = await this.findExecutable(root, `node_modules/.bin/${name}${suffix}`);
1786
+ if (!execPath) execPath = await this.findExecutable(root, `node_modules/alepha/node_modules/.bin/${name}${suffix}`);
1787
+ if (!execPath) {
1788
+ let parentDir = this.fs.join(root, "..");
1789
+ for (let i = 0; i < 3; i++) {
1790
+ execPath = await this.findExecutable(parentDir, `node_modules/.bin/${name}${suffix}`);
1791
+ if (execPath) break;
1792
+ parentDir = this.fs.join(parentDir, "..");
1793
+ }
1794
+ }
1795
+ if (!execPath) throw new AlephaError(`Could not find executable for '${name}'. Make sure the package is installed.`);
1796
+ return execPath;
1797
+ }
1798
+ /**
1799
+ * Check if executable exists at path.
1800
+ */
1801
+ async findExecutable(root, relativePath) {
1802
+ const fullPath = this.fs.join(root, relativePath);
1803
+ if (await this.fs.exists(fullPath)) return fullPath;
1804
+ }
1805
+ /**
1806
+ * Check if a command is installed and available in the system PATH.
1807
+ */
1808
+ isInstalled(command) {
1809
+ return new Promise((resolve) => {
1810
+ exec(process.platform === "win32" ? `where ${command}` : `command -v ${command}`, (error) => resolve(!error));
1811
+ });
1812
+ }
1813
+ };
1814
+
1815
+ //#endregion
1816
+ //#region ../../src/system/providers/ShellProvider.ts
1817
+ /**
1818
+ * Abstract provider for executing shell commands and binaries.
1819
+ *
1820
+ * Implementations:
1821
+ * - `NodeShellProvider` - Real shell execution using Node.js child_process
1822
+ * - `MemoryShellProvider` - In-memory mock for testing
1823
+ *
1824
+ * @example
1825
+ * ```typescript
1826
+ * class MyService {
1827
+ * protected readonly shell = $inject(ShellProvider);
1828
+ *
1829
+ * async build() {
1830
+ * // Run shell command directly
1831
+ * await this.shell.run("yarn install");
1832
+ *
1833
+ * // Run local binary with resolution
1834
+ * await this.shell.run("vite build", { resolve: true });
1835
+ *
1836
+ * // Capture output
1837
+ * const output = await this.shell.run("echo hello", { capture: true });
1838
+ * }
1839
+ * }
1840
+ * ```
1841
+ */
1842
+ var ShellProvider = class {};
1843
+
1844
+ //#endregion
1845
+ //#region ../../src/system/index.ts
1846
+ /**
1847
+ * | type | quality | stability |
1848
+ * |------|---------|-----------|
1849
+ * | tooling | standard | stable |
1850
+ *
1851
+ * System-level abstractions for portable code across runtimes.
1852
+ *
1853
+ * **Features:**
1854
+ * - File system operations (read, write, exists, etc.)
1855
+ * - Shell command execution
1856
+ * - File type detection and MIME utilities
1857
+ * - Memory implementations for testing
1858
+ *
1859
+ * @module alepha.system
1860
+ */
1861
+ const AlephaSystem = $module({
1862
+ name: "alepha.system",
1863
+ primitives: [],
1864
+ services: [
1865
+ FileDetector,
1866
+ FileSystemProvider,
1867
+ MemoryFileSystemProvider,
1868
+ NodeFileSystemProvider,
1869
+ ShellProvider,
1870
+ MemoryShellProvider,
1871
+ NodeShellProvider
1872
+ ],
1873
+ register: (alepha) => alepha.with({
1874
+ optional: true,
1875
+ provide: FileSystemProvider,
1876
+ use: NodeFileSystemProvider
1877
+ }).with({
1878
+ optional: true,
1879
+ provide: ShellProvider,
1880
+ use: alepha.isTest() ? MemoryShellProvider : NodeShellProvider
1881
+ })
1882
+ });
1883
+
41
1884
  //#endregion
42
1885
  //#region ../../src/server/swagger/providers/ServerSwaggerProvider.ts
43
1886
  /**
@@ -292,11 +2135,16 @@ window.onload = function() {
292
2135
  //#endregion
293
2136
  //#region ../../src/server/swagger/index.ts
294
2137
  /**
295
- * Plugin for Alepha Server that provides Swagger documentation capabilities.
296
- * It generates OpenAPI v3 documentation for the server's endpoints ($action).
297
- * It also provides a Swagger UI for interactive API documentation.
2138
+ * | type | quality | stability |
2139
+ * |------|---------|-----------|
2140
+ * | backend | standard | stable |
2141
+ *
2142
+ * Automatic API documentation generation.
2143
+ *
2144
+ * **Features:**
2145
+ * - Swagger/OpenAPI configuration
2146
+ * - Routes: `GET /swagger/ui`, `GET /swagger.json`
298
2147
  *
299
- * @see {@link ServerSwaggerProvider}
300
2148
  * @module alepha.server.swagger
301
2149
  */
302
2150
  const AlephaServerSwagger = $module({