alepha 0.19.1 → 0.19.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 (531) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -9
  3. package/dist/api/audits/index.d.ts +378 -346
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/files/index.d.ts +216 -184
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/jobs/index.d.ts +534 -502
  8. package/dist/api/jobs/index.d.ts.map +1 -1
  9. package/dist/api/jobs/index.js +13 -7
  10. package/dist/api/jobs/index.js.map +1 -1
  11. package/dist/api/keys/index.d.ts +202 -202
  12. package/dist/api/keys/index.d.ts.map +1 -1
  13. package/dist/api/notifications/index.d.ts +152 -152
  14. package/dist/api/notifications/index.d.ts.map +1 -1
  15. package/dist/api/organizations/index.browser.js +48 -0
  16. package/dist/api/organizations/index.browser.js.map +1 -0
  17. package/dist/api/organizations/index.d.ts +516 -0
  18. package/dist/api/organizations/index.d.ts.map +1 -0
  19. package/dist/api/organizations/index.js +202 -0
  20. package/dist/api/organizations/index.js.map +1 -0
  21. package/dist/api/parameters/index.d.ts +391 -358
  22. package/dist/api/parameters/index.d.ts.map +1 -1
  23. package/dist/api/parameters/index.js +5 -1
  24. package/dist/api/parameters/index.js.map +1 -1
  25. package/dist/api/users/index.browser.js +7 -5
  26. package/dist/api/users/index.browser.js.map +1 -1
  27. package/dist/api/users/index.d.ts +986 -931
  28. package/dist/api/users/index.d.ts.map +1 -1
  29. package/dist/api/users/index.js +160 -112
  30. package/dist/api/users/index.js.map +1 -1
  31. package/dist/api/verifications/index.d.ts +137 -137
  32. package/dist/api/verifications/index.d.ts.map +1 -1
  33. package/dist/api/verifications/index.js +2 -2
  34. package/dist/api/verifications/index.js.map +1 -1
  35. package/dist/batch/index.d.ts +6 -6
  36. package/dist/batch/index.d.ts.map +1 -1
  37. package/dist/billing/index.d.ts +1048 -0
  38. package/dist/billing/index.d.ts.map +1 -0
  39. package/dist/billing/index.js +713 -0
  40. package/dist/billing/index.js.map +1 -0
  41. package/dist/bin/index.js +0 -2
  42. package/dist/bin/index.js.map +1 -1
  43. package/dist/bucket/index.d.ts +10 -10
  44. package/dist/bucket/index.d.ts.map +1 -1
  45. package/dist/bucket/index.js +2 -2
  46. package/dist/bucket/index.js.map +1 -1
  47. package/dist/cache/core/index.d.ts +9 -9
  48. package/dist/cache/core/index.d.ts.map +1 -1
  49. package/dist/cache/core/index.js +2 -2
  50. package/dist/cache/core/index.js.map +1 -1
  51. package/dist/cache/core/index.workerd.js +2 -2
  52. package/dist/cache/core/index.workerd.js.map +1 -1
  53. package/dist/cache/redis/index.d.ts +6 -6
  54. package/dist/cache/redis/index.d.ts.map +1 -1
  55. package/dist/cache/redis/index.js +2 -2
  56. package/dist/cache/redis/index.js.map +1 -1
  57. package/dist/cli/config/index.d.ts +6 -18
  58. package/dist/cli/config/index.d.ts.map +1 -1
  59. package/dist/cli/config/index.js +5 -6
  60. package/dist/cli/config/index.js.map +1 -1
  61. package/dist/cli/core/index.d.ts +11811 -323
  62. package/dist/cli/core/index.d.ts.map +1 -1
  63. package/dist/cli/core/index.js +324 -98
  64. package/dist/cli/core/index.js.map +1 -1
  65. package/dist/cli/devtools/index.d.ts +50 -0
  66. package/dist/cli/devtools/index.d.ts.map +1 -0
  67. package/dist/cli/devtools/index.js +174 -0
  68. package/dist/cli/devtools/index.js.map +1 -0
  69. package/dist/cli/platform/index.d.ts +438 -542
  70. package/dist/cli/platform/index.d.ts.map +1 -1
  71. package/dist/cli/platform/index.js +46 -511
  72. package/dist/cli/platform/index.js.map +1 -1
  73. package/dist/cli/vendor/index.d.ts +201 -0
  74. package/dist/cli/vendor/index.d.ts.map +1 -0
  75. package/dist/cli/vendor/index.js +388 -0
  76. package/dist/cli/vendor/index.js.map +1 -0
  77. package/dist/command/index.d.ts +18 -18
  78. package/dist/command/index.d.ts.map +1 -1
  79. package/dist/command/index.js +2 -2
  80. package/dist/command/index.js.map +1 -1
  81. package/dist/core/index.browser.js +4 -4
  82. package/dist/core/index.browser.js.map +1 -1
  83. package/dist/core/index.d.ts +10 -10
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/core/index.js +8 -4
  86. package/dist/core/index.js.map +1 -1
  87. package/dist/core/index.native.js +8 -4
  88. package/dist/core/index.native.js.map +1 -1
  89. package/dist/core/index.workerd.js +8 -4
  90. package/dist/core/index.workerd.js.map +1 -1
  91. package/dist/crypto/index.d.ts +7 -7
  92. package/dist/crypto/index.d.ts.map +1 -1
  93. package/dist/datetime/index.d.ts +4 -4
  94. package/dist/datetime/index.d.ts.map +1 -1
  95. package/dist/email/brevo/index.d.ts +4 -4
  96. package/dist/email/brevo/index.d.ts.map +1 -1
  97. package/dist/email/core/index.d.ts +15 -11
  98. package/dist/email/core/index.d.ts.map +1 -1
  99. package/dist/email/core/index.js +12 -35
  100. package/dist/email/core/index.js.map +1 -1
  101. package/dist/email/smtp/index.d.ts +12 -12
  102. package/dist/email/smtp/index.d.ts.map +1 -1
  103. package/dist/email/smtp/index.js +7 -4
  104. package/dist/email/smtp/index.js.map +1 -1
  105. package/dist/fake/index.d.ts +4 -8
  106. package/dist/fake/index.d.ts.map +1 -1
  107. package/dist/fake/index.js +55 -889
  108. package/dist/fake/index.js.map +1 -1
  109. package/dist/lock/core/index.d.ts +13 -13
  110. package/dist/lock/core/index.d.ts.map +1 -1
  111. package/dist/lock/core/index.js +2 -2
  112. package/dist/lock/core/index.js.map +1 -1
  113. package/dist/lock/redis/index.d.ts +4 -4
  114. package/dist/lock/redis/index.d.ts.map +1 -1
  115. package/dist/logger/index.d.ts +16 -15
  116. package/dist/logger/index.d.ts.map +1 -1
  117. package/dist/logger/index.js +6 -3
  118. package/dist/logger/index.js.map +1 -1
  119. package/dist/mcp/index.d.ts +11 -11
  120. package/dist/mcp/index.d.ts.map +1 -1
  121. package/dist/mcp/index.js +2 -2
  122. package/dist/mcp/index.js.map +1 -1
  123. package/dist/orm/core/index.browser.js +11 -1
  124. package/dist/orm/core/index.browser.js.map +1 -1
  125. package/dist/orm/core/index.bun.js +78 -72
  126. package/dist/orm/core/index.bun.js.map +1 -1
  127. package/dist/orm/core/index.d.ts +103 -69
  128. package/dist/orm/core/index.d.ts.map +1 -1
  129. package/dist/orm/core/index.js +80 -70
  130. package/dist/orm/core/index.js.map +1 -1
  131. package/dist/orm/postgres/index.d.ts +19 -17
  132. package/dist/orm/postgres/index.d.ts.map +1 -1
  133. package/dist/queue/core/index.d.ts +14 -14
  134. package/dist/queue/core/index.d.ts.map +1 -1
  135. package/dist/queue/core/index.js +2 -2
  136. package/dist/queue/core/index.js.map +1 -1
  137. package/dist/queue/core/index.workerd.js +2 -2
  138. package/dist/queue/core/index.workerd.js.map +1 -1
  139. package/dist/queue/redis/index.d.ts +4 -4
  140. package/dist/queue/redis/index.d.ts.map +1 -1
  141. package/dist/queue/redis/index.js +2 -2
  142. package/dist/queue/redis/index.js.map +1 -1
  143. package/dist/react/auth/index.d.ts +9 -9
  144. package/dist/react/auth/index.d.ts.map +1 -1
  145. package/dist/react/core/index.d.ts +6 -6
  146. package/dist/react/core/index.d.ts.map +1 -1
  147. package/dist/react/core/index.js +5 -4
  148. package/dist/react/core/index.js.map +1 -1
  149. package/dist/react/form/index.d.ts +4 -4
  150. package/dist/react/form/index.d.ts.map +1 -1
  151. package/dist/react/head/index.d.ts +4 -4
  152. package/dist/react/head/index.d.ts.map +1 -1
  153. package/dist/react/i18n/index.d.ts +9 -9
  154. package/dist/react/i18n/index.d.ts.map +1 -1
  155. package/dist/react/intro/index.d.ts +2 -2
  156. package/dist/react/intro/index.d.ts.map +1 -1
  157. package/dist/react/intro/index.js +1 -1
  158. package/dist/react/intro/index.js.map +1 -1
  159. package/dist/react/router/index.browser.js +4 -5
  160. package/dist/react/router/index.browser.js.map +1 -1
  161. package/dist/react/router/index.d.ts +215 -215
  162. package/dist/react/router/index.d.ts.map +1 -1
  163. package/dist/react/router/index.js +6 -7
  164. package/dist/react/router/index.js.map +1 -1
  165. package/dist/react/testing/index.d.ts +2 -2
  166. package/dist/react/testing/index.d.ts.map +1 -1
  167. package/dist/react/testing/index.js +2 -4
  168. package/dist/react/testing/index.js.map +1 -1
  169. package/dist/redis/index.d.ts +19 -19
  170. package/dist/redis/index.d.ts.map +1 -1
  171. package/dist/retry/index.d.ts +4 -4
  172. package/dist/retry/index.d.ts.map +1 -1
  173. package/dist/scheduler/index.d.ts +13 -13
  174. package/dist/scheduler/index.d.ts.map +1 -1
  175. package/dist/scheduler/index.js +2 -2
  176. package/dist/scheduler/index.js.map +1 -1
  177. package/dist/scheduler/index.workerd.js +2 -2
  178. package/dist/scheduler/index.workerd.js.map +1 -1
  179. package/dist/security/index.browser.js +1 -1
  180. package/dist/security/index.browser.js.map +1 -1
  181. package/dist/security/index.d.ts +47 -47
  182. package/dist/security/index.d.ts.map +1 -1
  183. package/dist/security/index.js +9 -12
  184. package/dist/security/index.js.map +1 -1
  185. package/dist/server/auth/index.d.ts +170 -169
  186. package/dist/server/auth/index.d.ts.map +1 -1
  187. package/dist/server/auth/index.js +16 -2
  188. package/dist/server/auth/index.js.map +1 -1
  189. package/dist/server/cookies/index.d.ts +7 -7
  190. package/dist/server/cookies/index.d.ts.map +1 -1
  191. package/dist/server/core/index.d.ts +76 -76
  192. package/dist/server/core/index.d.ts.map +1 -1
  193. package/dist/server/core/index.js +23 -17
  194. package/dist/server/core/index.js.map +1 -1
  195. package/dist/server/cors/index.d.ts +13 -13
  196. package/dist/server/cors/index.d.ts.map +1 -1
  197. package/dist/server/cors/index.js +2 -2
  198. package/dist/server/cors/index.js.map +1 -1
  199. package/dist/server/etag/index.d.ts +9 -9
  200. package/dist/server/etag/index.d.ts.map +1 -1
  201. package/dist/server/health/index.d.ts +20 -20
  202. package/dist/server/health/index.d.ts.map +1 -1
  203. package/dist/server/links/index.browser.js +2 -2
  204. package/dist/server/links/index.browser.js.map +1 -1
  205. package/dist/server/links/index.d.ts +66 -66
  206. package/dist/server/links/index.d.ts.map +1 -1
  207. package/dist/server/links/index.js +4 -4
  208. package/dist/server/links/index.js.map +1 -1
  209. package/dist/server/metrics/index.d.ts +7 -7
  210. package/dist/server/metrics/index.d.ts.map +1 -1
  211. package/dist/server/proxy/index.d.ts +5 -5
  212. package/dist/server/proxy/index.d.ts.map +1 -1
  213. package/dist/server/rate-limit/index.d.ts +12 -12
  214. package/dist/server/rate-limit/index.d.ts.map +1 -1
  215. package/dist/server/rate-limit/index.js +2 -2
  216. package/dist/server/rate-limit/index.js.map +1 -1
  217. package/dist/server/static/index.d.ts +5 -5
  218. package/dist/server/static/index.d.ts.map +1 -1
  219. package/dist/server/swagger/index.d.ts +7 -7
  220. package/dist/server/swagger/index.d.ts.map +1 -1
  221. package/dist/server/swagger/index.js +2 -2
  222. package/dist/server/swagger/index.js.map +1 -1
  223. package/dist/sms/index.d.ts +11 -7
  224. package/dist/sms/index.d.ts.map +1 -1
  225. package/dist/sms/index.js +9 -15
  226. package/dist/sms/index.js.map +1 -1
  227. package/dist/system/index.d.ts +4 -4
  228. package/dist/system/index.d.ts.map +1 -1
  229. package/dist/topic/core/index.d.ts +6 -6
  230. package/dist/topic/core/index.d.ts.map +1 -1
  231. package/dist/topic/redis/index.d.ts +7 -7
  232. package/dist/topic/redis/index.d.ts.map +1 -1
  233. package/dist/topic/redis/index.js +2 -2
  234. package/dist/topic/redis/index.js.map +1 -1
  235. package/dist/websocket/index.d.ts +36 -36
  236. package/dist/websocket/index.d.ts.map +1 -1
  237. package/dist/websocket/index.js +2 -2
  238. package/dist/websocket/index.js.map +1 -1
  239. package/package.json +37 -15
  240. package/src/api/jobs/{services → __tests__}/JobService.spec.ts +1 -1
  241. package/src/api/jobs/providers/JobProvider.ts +13 -9
  242. package/src/api/keys/{services → __tests__}/ApiKeyService.spec.ts +1 -1
  243. package/src/api/organizations/__tests__/OrganizationService.spec.ts +193 -0
  244. package/src/api/organizations/controllers/AdminOrganizationController.ts +103 -0
  245. package/src/api/organizations/entities/organizations.ts +20 -0
  246. package/src/api/organizations/index.browser.ts +10 -0
  247. package/src/api/organizations/index.ts +31 -0
  248. package/src/api/organizations/schemas/createOrganizationSchema.ts +10 -0
  249. package/src/api/organizations/schemas/organizationQuerySchema.ts +10 -0
  250. package/src/api/organizations/schemas/organizationResourceSchema.ts +6 -0
  251. package/src/api/organizations/schemas/updateOrganizationSchema.ts +7 -0
  252. package/src/api/organizations/services/OrganizationService.ts +75 -0
  253. package/src/api/parameters/services/ParameterProvider.ts +6 -1
  254. package/src/api/users/{services → __tests__}/SessionService.spec.ts +67 -0
  255. package/src/api/users/{jobs → __tests__}/UserJobs.spec.ts +1 -1
  256. package/src/api/users/entities/users.ts +9 -3
  257. package/src/api/users/index.ts +23 -4
  258. package/src/api/users/primitives/$realm.ts +6 -4
  259. package/src/api/users/providers/RealmProvider.ts +1 -1
  260. package/src/api/users/services/RegistrationService.ts +1 -1
  261. package/src/api/users/services/SessionService.ts +92 -5
  262. package/src/api/users/services/UserService.ts +1 -1
  263. package/src/api/verifications/{jobs → __tests__}/VerificationJobs.spec.ts +4 -2
  264. package/src/api/verifications/parameters/VerificationParameters.ts +2 -2
  265. package/src/billing/__tests__/BillingService.spec.ts +136 -0
  266. package/src/billing/__tests__/PaymentMethodService.spec.ts +78 -0
  267. package/src/billing/controllers/AdminBillingController.ts +149 -0
  268. package/src/billing/controllers/BillingController.ts +108 -0
  269. package/src/billing/entities/paymentIntents.ts +34 -0
  270. package/src/billing/entities/paymentMethods.ts +24 -0
  271. package/src/billing/entities/refunds.ts +22 -0
  272. package/src/billing/errors/BillingError.ts +5 -0
  273. package/src/billing/index.ts +76 -0
  274. package/src/billing/providers/BillingProvider.ts +79 -0
  275. package/src/billing/providers/MemoryBillingProvider.ts +139 -0
  276. package/src/billing/schemas/intentSchemas.ts +60 -0
  277. package/src/billing/schemas/paymentMethodSchemas.ts +13 -0
  278. package/src/billing/schemas/refundSchemas.ts +6 -0
  279. package/src/billing/services/BillingService.ts +325 -0
  280. package/src/billing/services/PaymentMethodService.ts +82 -0
  281. package/src/bin/index.ts +0 -2
  282. package/src/bucket/providers/LocalFileStorageProvider.ts +2 -2
  283. package/src/cache/core/{primitives → __tests__}/$cache.middleware.spec.ts +1 -1
  284. package/src/cache/core/{providers → __tests__}/MemoryCacheProvider.spec.ts +1 -1
  285. package/src/cache/core/primitives/$cache.ts +2 -2
  286. package/src/cache/redis/providers/RedisCacheProvider.ts +2 -2
  287. package/src/cli/config/defineConfig.ts +17 -26
  288. package/src/cli/core/{services → __tests__}/ProjectScaffolder.spec.ts +1 -1
  289. package/src/cli/core/{commands/gen → __tests__}/changelog.spec.ts +1 -1
  290. package/src/cli/core/{commands → __tests__}/init.spec.ts +2 -8
  291. package/src/cli/core/atoms/devOptions.ts +0 -5
  292. package/src/cli/core/commands/build.ts +2 -2
  293. package/src/cli/core/commands/dev.ts +165 -30
  294. package/src/cli/core/commands/gen/changelog.ts +2 -2
  295. package/src/cli/core/commands/init.ts +2 -7
  296. package/src/cli/core/commands/verify.ts +0 -1
  297. package/src/cli/core/providers/AppEntryProvider.ts +2 -2
  298. package/src/cli/core/providers/ViteDevServerProvider.ts +99 -69
  299. package/src/cli/core/services/PackageManagerUtils.ts +8 -1
  300. package/src/cli/core/services/ProjectScaffolder.ts +23 -23
  301. package/src/cli/core/tasks/BuildClientTask.ts +8 -0
  302. package/src/cli/core/tasks/BuildServerTask.ts +17 -4
  303. package/src/cli/core/templates/agentMd.ts +14 -5
  304. package/src/cli/core/templates/alephaConfigTs.ts +0 -6
  305. package/src/cli/core/templates/webAdminDashboardTsx.ts +17 -0
  306. package/src/cli/core/templates/webAppRouterTs.ts +85 -2
  307. package/src/cli/devtools/atoms/devtoolsOptions.ts +26 -0
  308. package/src/cli/devtools/index.ts +214 -0
  309. package/src/cli/platform/{adapters → __tests__}/CloudflareAdapter.spec.ts +2 -2
  310. package/src/cli/platform/{providers → __tests__}/GitHubSecretStore.spec.ts +1 -1
  311. package/src/cli/platform/{services → __tests__}/NamingService.spec.ts +1 -1
  312. package/src/cli/platform/{providers → __tests__}/PlatformCacheProvider.spec.ts +1 -1
  313. package/src/cli/platform/{services → __tests__}/PlatformInspector.spec.ts +1 -1
  314. package/src/cli/platform/{services → __tests__}/PlatformOrchestrator.spec.ts +3 -3
  315. package/src/cli/platform/{services → __tests__}/SecretFilterService.spec.ts +1 -1
  316. package/src/cli/platform/{commands → __tests__}/SecretsCommand.spec.ts +1 -1
  317. package/src/cli/platform/{adapters → __tests__}/VercelAdapter.spec.ts +2 -2
  318. package/src/cli/platform/atoms/platformOptions.ts +2 -10
  319. package/src/cli/platform/commands/SecretsCommand.ts +2 -2
  320. package/src/cli/platform/commands/platform.ts +2 -11
  321. package/src/cli/platform/index.ts +55 -11
  322. package/src/cli/platform/services/PlatformInspector.ts +2 -2
  323. package/src/cli/platform/services/PlatformOrchestrator.ts +0 -9
  324. package/src/cli/vendor/__tests__/VendorService.spec.ts +407 -0
  325. package/src/cli/vendor/atoms/vendorOptions.ts +41 -0
  326. package/src/cli/vendor/commands/VendorCommand.ts +204 -0
  327. package/src/cli/vendor/index.ts +60 -0
  328. package/src/cli/vendor/services/VendorService.ts +338 -0
  329. package/src/command/{providers → __tests__}/CliProvider.spec.ts +1 -1
  330. package/src/command/{helpers → __tests__}/EnvUtils.spec.ts +1 -1
  331. package/src/command/providers/CliProvider.ts +2 -2
  332. package/src/core/Alepha.ts +10 -0
  333. package/src/core/{primitives → __tests__}/$atom.spec.ts +2 -2
  334. package/src/core/{primitives → __tests__}/$memoize.spec.ts +1 -1
  335. package/src/core/{primitives → __tests__}/$mode.spec.ts +1 -1
  336. package/src/core/{primitives → __tests__}/$pipeline.spec.ts +1 -1
  337. package/src/core/{primitives → __tests__}/$scope.spec.ts +2 -2
  338. package/src/core/{providers → __tests__}/KeylessJsonSchemaCodec.spec.ts +1 -1
  339. package/src/core/{providers → __tests__}/SchemaValidator.spec.ts +1 -1
  340. package/src/core/{helpers → __tests__}/jsonSchemaToTypeBox.spec.ts +1 -1
  341. package/src/core/index.shared.ts +1 -1
  342. package/src/core/primitives/{$use.ts → $state.ts} +4 -4
  343. package/src/crypto/{providers → __tests__}/BrowserCryptoProvider.browser.spec.ts +1 -1
  344. package/src/crypto/{providers → __tests__}/CryptoProvider.spec.ts +1 -1
  345. package/src/datetime/{primitives → __tests__}/$debounce.spec.ts +1 -1
  346. package/src/datetime/{primitives → __tests__}/$throttle.spec.ts +1 -1
  347. package/src/datetime/{primitives → __tests__}/$timeout.spec.ts +1 -1
  348. package/src/email/brevo/{providers → __tests__}/BrevoEmailProvider.spec.ts +1 -1
  349. package/src/email/core/{providers → __tests__}/LocalEmailProvider.spec.ts +39 -150
  350. package/src/email/core/providers/LocalEmailProvider.ts +13 -51
  351. package/src/email/smtp/providers/NodemailerEmailProvider.ts +2 -2
  352. package/src/lock/core/{primitives → __tests__}/$lock.middleware.spec.ts +1 -1
  353. package/src/lock/core/primitives/$lock.ts +2 -2
  354. package/src/logger/index.ts +16 -5
  355. package/src/mcp/transports/SseMcpTransport.ts +2 -2
  356. package/src/orm/__tests__/ModelBuilder-tests.ts +53 -0
  357. package/src/orm/__tests__/ModelBuilder.spec.ts +80 -0
  358. package/src/orm/__tests__/organization-tests.ts +200 -0
  359. package/src/orm/__tests__/organization.spec.ts +103 -0
  360. package/src/orm/core/{providers/drivers → __tests__}/BunSqliteProvider.bun.spec.ts +5 -2
  361. package/src/orm/core/constants/PG_SYMBOLS.ts +2 -0
  362. package/src/orm/core/index.shared.ts +1 -0
  363. package/src/orm/core/primitives/$entity.ts +31 -0
  364. package/src/orm/core/providers/DatabaseTypeProvider.ts +11 -0
  365. package/src/orm/core/providers/DrizzleKitProvider.ts +57 -106
  366. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -2
  367. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +3 -3
  368. package/src/orm/core/services/ModelBuilder.ts +11 -0
  369. package/src/orm/core/services/QueryManager.ts +16 -2
  370. package/src/orm/core/services/Repository.ts +70 -10
  371. package/src/orm/postgres/{providers → __tests__}/BunPostgresProvider.bun.spec.ts +1 -1
  372. package/src/queue/core/providers/WorkerProvider.ts +2 -2
  373. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -2
  374. package/src/react/core/{hooks → __tests__}/useAction.browser.spec.tsx +1 -1
  375. package/src/react/core/hooks/useAction.ts +7 -6
  376. package/src/react/head/{providers → __tests__}/BrowserHeadProvider.browser.spec.ts +1 -1
  377. package/src/react/head/{helpers → __tests__}/SeoExpander.spec.ts +1 -1
  378. package/src/react/i18n/{providers → __tests__}/I18nProvider.spec.ts +1 -1
  379. package/src/react/i18n/{hooks → __tests__}/useI18n.browser.spec.tsx +1 -1
  380. package/src/react/intro/components/GettingStartedDevtoolsSlide.tsx +1 -1
  381. package/src/react/router/{providers → __tests__}/ReactBrowserProvider.browser.spec.ts +1 -1
  382. package/src/react/router/providers/ReactBrowserProvider.ts +2 -2
  383. package/src/react/router/providers/ReactPageProvider.ts +2 -2
  384. package/src/react/router/providers/ReactServerProvider.ts +3 -3
  385. package/src/redis/{providers → __tests__}/BunRedisProvider.bun.spec.ts +4 -4
  386. package/src/retry/{primitives → __tests__}/$retry.middleware.spec.ts +1 -1
  387. package/src/router/{TemplatedPathParser.spec.ts → __tests__/TemplatedPathParser.spec.ts} +1 -1
  388. package/src/scheduler/primitives/$scheduler.ts +2 -2
  389. package/src/security/{primitives → __tests__}/$secure-browser.spec.ts +1 -1
  390. package/src/security/{primitives → __tests__}/$secure.spec.ts +1 -1
  391. package/src/security/primitives/$issuer.ts +1 -1
  392. package/src/security/providers/JwtProvider.ts +6 -10
  393. package/src/security/providers/SecurityProvider.ts +6 -11
  394. package/src/security/schemas/userAccountInfoSchema.ts +3 -3
  395. package/src/server/auth/providers/ServerAuthProvider.ts +24 -2
  396. package/src/server/cookies/{services → __tests__}/CookieParser.spec.ts +1 -1
  397. package/src/server/core/{primitives → __tests__}/$circuit.spec.ts +1 -1
  398. package/src/server/core/{providers → __tests__}/NodeHttpServerProvider.spec.ts +1 -1
  399. package/src/server/core/{providers → __tests__}/ServerBodyParserProvider.spec.ts +31 -1
  400. package/src/server/core/{providers → __tests__}/ServerCompressProvider.spec.ts +1 -1
  401. package/src/server/core/{providers → __tests__}/ServerHelmetProvider.spec.ts +4 -1
  402. package/src/server/core/{providers → __tests__}/ServerMultipartProvider.spec.ts +1 -1
  403. package/src/server/core/{services → __tests__}/ServerRequestParser.spec.ts +1 -1
  404. package/src/server/core/primitives/$action.ts +2 -2
  405. package/src/server/core/primitives/$sse.ts +2 -2
  406. package/src/server/core/providers/ServerBodyParserProvider.ts +21 -12
  407. package/src/server/core/providers/ServerCompressProvider.ts +2 -2
  408. package/src/server/core/providers/ServerHelmetProvider.ts +2 -2
  409. package/src/server/core/providers/ServerMultipartProvider.ts +2 -2
  410. package/src/server/core/providers/ServerRouterProvider.ts +1 -5
  411. package/src/server/cors/{primitives → __tests__}/$cors.spec.ts +1 -1
  412. package/src/server/cors/providers/ServerCorsProvider.ts +2 -2
  413. package/src/server/links/{services → __tests__}/BatchCollector.spec.ts +1 -1
  414. package/src/server/links/providers/LinkProvider.ts +2 -2
  415. package/src/server/links/providers/RemotePrimitiveProvider.ts +2 -2
  416. package/src/server/links/providers/ServerLinksProvider.ts +2 -2
  417. package/src/server/rate-limit/{primitives → __tests__}/$rateLimit.spec.ts +1 -1
  418. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +2 -2
  419. package/src/server/swagger/providers/ServerSwaggerProvider.ts +2 -2
  420. package/src/sms/{providers → __tests__}/LocalSmsProvider.spec.ts +35 -29
  421. package/src/sms/providers/LocalSmsProvider.ts +13 -24
  422. package/src/system/{providers → __tests__}/MemoryFileSystemProvider.spec.ts +1 -1
  423. package/src/system/{providers → __tests__}/MemoryShellProvider.spec.ts +1 -1
  424. package/src/topic/redis/providers/RedisTopicProvider.ts +2 -2
  425. package/src/websocket/{services → __tests__}/RoomManager.spec.ts +1 -1
  426. package/src/websocket/providers/NodeWebSocketServerProvider.ts +2 -2
  427. package/src/cli/platform/adapters/DockerAdapter.spec.ts +0 -378
  428. package/src/cli/platform/adapters/DockerAdapter.ts +0 -417
  429. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +0 -490
  430. package/src/cli/platform/services/DockerComposeGenerator.ts +0 -353
  431. package/src/cli/platform/services/DockerSshService.spec.ts +0 -47
  432. package/src/cli/platform/services/DockerSshService.ts +0 -61
  433. /package/src/api/audits/{primitives → __tests__}/$audit.spec.ts +0 -0
  434. /package/src/api/audits/{services → __tests__}/AuditService.spec.ts +0 -0
  435. /package/src/api/files/{controllers → __tests__}/AdminFileStatsController.spec.ts +0 -0
  436. /package/src/api/files/{controllers → __tests__}/FileController.spec.ts +0 -0
  437. /package/src/api/files/{jobs → __tests__}/FileJobs.spec.ts +0 -0
  438. /package/src/api/files/{services → __tests__}/FileService.spec.ts +0 -0
  439. /package/src/api/jobs/{primitives → __tests__}/$job-middleware.spec.ts +0 -0
  440. /package/src/api/parameters/{primitives → __tests__}/$parameter.spec.ts +0 -0
  441. /package/src/api/users/{primitives → __tests__}/$realm.spec.ts +0 -0
  442. /package/src/api/users/{controllers → __tests__}/AdminIdentityController.spec.ts +0 -0
  443. /package/src/api/users/{controllers → __tests__}/AdminSessionController.spec.ts +0 -0
  444. /package/src/api/users/{controllers → __tests__}/AdminUserController.spec.ts +0 -0
  445. /package/src/api/users/{services → __tests__}/CredentialService.spec.ts +0 -0
  446. /package/src/api/users/{providers → __tests__}/RealmProvider.spec.ts +0 -0
  447. /package/src/api/users/{services → __tests__}/RegistrationService.spec.ts +0 -0
  448. /package/src/batch/{primitives → __tests__}/$batch.spec.ts +0 -0
  449. /package/src/batch/{providers → __tests__}/BatchProvider.spec.ts +0 -0
  450. /package/src/bucket/{primitives → __tests__}/$bucket.spec.ts +0 -0
  451. /package/src/bucket/{providers → __tests__}/FileStorageProvider.spec.ts +0 -0
  452. /package/src/bucket/{providers → __tests__}/LocalFileStorageProvider.spec.ts +0 -0
  453. /package/src/bucket/{providers → __tests__}/MemoryFileStorageProvider.spec.ts +0 -0
  454. /package/src/cache/core/{primitives → __tests__}/$cache.spec.ts +0 -0
  455. /package/src/cache/redis/{providers → __tests__}/RedisCacheProvider.spec.ts +0 -0
  456. /package/src/command/{primitives → __tests__}/$command.spec.ts +0 -0
  457. /package/src/command/{helpers → __tests__}/Asker.spec.ts +0 -0
  458. /package/src/command/{helpers → __tests__}/Runner.spec.ts +0 -0
  459. /package/src/core/{primitives → __tests__}/$context.spec.ts +0 -0
  460. /package/src/core/{primitives → __tests__}/$env.spec.ts +0 -0
  461. /package/src/core/{primitives → __tests__}/$hook.spec.ts +0 -0
  462. /package/src/core/{primitives → __tests__}/$inject.spec.ts +0 -0
  463. /package/src/core/{primitives → __tests__}/$module.spec.ts +0 -0
  464. /package/src/core/{providers → __tests__}/CodecManager.spec.ts +0 -0
  465. /package/src/core/{providers → __tests__}/EventManager.spec.ts +0 -0
  466. /package/src/core/{providers → __tests__}/StateManager.spec.ts +0 -0
  467. /package/src/core/{providers → __tests__}/TypeProvider.spec.ts +0 -0
  468. /package/src/datetime/{primitives → __tests__}/$interval.spec.ts +0 -0
  469. /package/src/datetime/{providers → __tests__}/DateTimeProvider.spec.ts +0 -0
  470. /package/src/email/core/{primitives → __tests__}/$email.spec.ts +0 -0
  471. /package/src/fake/{providers → __tests__}/FakeProvider.spec.ts +0 -0
  472. /package/src/lock/core/{providers → __tests__}/MemoryLockProvider.spec.ts +0 -0
  473. /package/src/lock/redis/{providers → __tests__}/RedisLockProvider.spec.ts +0 -0
  474. /package/src/logger/{primitives → __tests__}/$logger.spec.ts +0 -0
  475. /package/src/logger/{services → __tests__}/Logger.spec.ts +0 -0
  476. /package/src/mcp/{primitives → __tests__}/$prompt.spec.ts +0 -0
  477. /package/src/mcp/{primitives → __tests__}/$resource.spec.ts +0 -0
  478. /package/src/mcp/{primitives → __tests__}/$tool.spec.ts +0 -0
  479. /package/src/mcp/{providers → __tests__}/McpServerProvider.spec.ts +0 -0
  480. /package/src/mcp/{helpers → __tests__}/jsonrpc.spec.ts +0 -0
  481. /package/src/orm/core/{helpers → __tests__}/parseQueryString.spec.ts +0 -0
  482. /package/src/queue/core/{primitives → __tests__}/$consumer.spec.ts +0 -0
  483. /package/src/queue/core/{providers → __tests__}/MemoryQueueProvider.spec.ts +0 -0
  484. /package/src/queue/core/{providers → __tests__}/WorkerProvider.spec.ts +0 -0
  485. /package/src/queue/redis/{providers → __tests__}/RedisQueueProvider.spec.ts +0 -0
  486. /package/src/react/form/{hooks → __tests__}/useForm.browser.spec.tsx +0 -0
  487. /package/src/react/head/{hooks → __tests__}/useHead.spec.tsx +0 -0
  488. /package/src/react/i18n/{components → __tests__}/Localize.spec.tsx +0 -0
  489. /package/src/react/router/{primitives → __tests__}/$page.browser.spec.tsx +0 -0
  490. /package/src/react/router/{primitives → __tests__}/$page.middleware.spec.tsx +0 -0
  491. /package/src/react/router/{primitives → __tests__}/$page.spec.tsx +0 -0
  492. /package/src/react/router/{providers → __tests__}/ReactPreloadProvider.spec.ts +0 -0
  493. /package/src/react/router/{providers → __tests__}/ReactServerProvider.spec.tsx +0 -0
  494. /package/src/react/router/{providers → __tests__}/ReactServerTemplateProvider.spec.ts +0 -0
  495. /package/src/retry/{primitives → __tests__}/$retry.spec.ts +0 -0
  496. /package/src/retry/{providers → __tests__}/RetryProvider.spec.ts +0 -0
  497. /package/src/router/{providers → __tests__}/RouterProvider.spec.ts +0 -0
  498. /package/src/security/{primitives → __tests__}/$issuer.spec.ts +0 -0
  499. /package/src/security/{primitives → __tests__}/$permission.spec.ts +0 -0
  500. /package/src/security/{primitives → __tests__}/$role.spec.ts +0 -0
  501. /package/src/security/{primitives → __tests__}/$serviceAccount.spec.ts +0 -0
  502. /package/src/security/{providers → __tests__}/SecurityProvider.spec.ts +0 -0
  503. /package/src/server/cookies/{providers → __tests__}/ServerCookiesProvider.spec.ts +0 -0
  504. /package/src/server/core/{primitives → __tests__}/$action.spec.ts +0 -0
  505. /package/src/server/core/{primitives → __tests__}/$middleware.spec.ts +0 -0
  506. /package/src/server/core/{primitives → __tests__}/$route.spec.ts +0 -0
  507. /package/src/server/core/{primitives → __tests__}/$sse.spec.ts +0 -0
  508. /package/src/server/core/{providers → __tests__}/BunHttpServerProvider.bun.spec.ts +0 -0
  509. /package/src/server/core/{services → __tests__}/HttpClient.spec.ts +0 -0
  510. /package/src/server/core/{providers → __tests__}/ServerLoggerProvider.spec.ts +0 -0
  511. /package/src/server/core/{services → __tests__}/UserAgentParser.spec.ts +0 -0
  512. /package/src/server/cors/{providers → __tests__}/ServerCorsProvider.spec.ts +0 -0
  513. /package/src/server/etag/{providers → __tests__}/ServerEtagProvider.spec.ts +0 -0
  514. /package/src/server/health/{providers → __tests__}/ServerHealthProvider.spec.ts +0 -0
  515. /package/src/server/links/{primitives → __tests__}/$remote.spec.ts +0 -0
  516. /package/src/server/links/{services → __tests__}/BatchEndpoint.spec.ts +0 -0
  517. /package/src/server/links/{providers → __tests__}/LinkProvider.spec.ts +0 -0
  518. /package/src/server/links/{providers → __tests__}/ServerLinksProvider.spec.ts +0 -0
  519. /package/src/server/metrics/{providers → __tests__}/ServerMetricsProvider.spec.ts +0 -0
  520. /package/src/server/proxy/{primitives → __tests__}/$proxy.spec.ts +0 -0
  521. /package/src/server/rate-limit/{providers → __tests__}/ServerRateLimitProvider.spec.ts +0 -0
  522. /package/src/server/static/{primitives → __tests__}/$serve.spec.ts +0 -0
  523. /package/src/server/swagger/{primitives → __tests__}/$swagger.spec.ts +0 -0
  524. /package/src/sms/{primitives → __tests__}/$sms.spec.ts +0 -0
  525. /package/src/sms/{providers → __tests__}/MemorySmsProvider.spec.ts +0 -0
  526. /package/src/system/{services → __tests__}/FileDetector.spec.ts +0 -0
  527. /package/src/system/{providers → __tests__}/NodeFileSystemProvider.spec.ts +0 -0
  528. /package/src/topic/core/{primitives → __tests__}/$subscriber.spec.ts +0 -0
  529. /package/src/topic/core/{providers → __tests__}/MemoryTopicProvider.spec.ts +0 -0
  530. /package/src/topic/redis/{providers → __tests__}/RedisTopicProvider.spec.ts +0 -0
  531. /package/src/websocket/{primitives → __tests__}/$channel.spec.ts +0 -0
@@ -1,18 +1,18 @@
1
- import * as alepha from "alepha";
1
+ import * as _$alepha from "alepha";
2
2
  import { Middleware, Static } from "alepha";
3
- import * as alepha_logger0 from "alepha/logger";
3
+ import * as _$alepha_logger0 from "alepha/logger";
4
4
  import { ServerRouterProvider } from "alepha/server";
5
5
 
6
6
  //#region ../../src/server/cors/providers/ServerCorsProvider.d.ts
7
7
  /**
8
8
  * CORS configuration atom (global defaults)
9
9
  */
10
- declare const corsOptions: alepha.Atom<alepha.TObject<{
11
- origin: alepha.TOptional<alepha.TString>;
12
- methods: alepha.TArray<alepha.TString>;
13
- headers: alepha.TArray<alepha.TString>;
14
- credentials: alepha.TOptional<alepha.TBoolean>;
15
- maxAge: alepha.TOptional<alepha.TNumber>;
10
+ declare const corsOptions: _$alepha.Atom<_$alepha.TObject<{
11
+ origin: _$alepha.TOptional<_$alepha.TString>;
12
+ methods: _$alepha.TArray<_$alepha.TString>;
13
+ headers: _$alepha.TArray<_$alepha.TString>;
14
+ credentials: _$alepha.TOptional<_$alepha.TBoolean>;
15
+ maxAge: _$alepha.TOptional<_$alepha.TNumber>;
16
16
  }>, "alepha.server.cors.options">;
17
17
  type CorsOptions = Static<typeof corsOptions.schema>;
18
18
  declare module "alepha" {
@@ -31,7 +31,7 @@ interface CorsRegistration extends Partial<CorsOptions> {
31
31
  paths?: string[];
32
32
  }
33
33
  declare class ServerCorsProvider {
34
- protected readonly log: alepha_logger0.Logger;
34
+ protected readonly log: _$alepha_logger0.Logger;
35
35
  protected readonly serverRouterProvider: ServerRouterProvider;
36
36
  protected readonly globalOptions: Readonly<{
37
37
  origin?: string | undefined;
@@ -48,7 +48,7 @@ declare class ServerCorsProvider {
48
48
  * Register a CORS configuration (called by primitives)
49
49
  */
50
50
  registerCors(config: CorsRegistration): void;
51
- protected readonly onStart: alepha.HookPrimitive<"start">;
51
+ protected readonly onStart: _$alepha.HookPrimitive<"start">;
52
52
  /**
53
53
  * Build complete CORS options by merging with global defaults
54
54
  */
@@ -64,8 +64,8 @@ declare class ServerCorsProvider {
64
64
  setHeader: (name: string, value: string) => void;
65
65
  };
66
66
  }, options: CorsOptions): void;
67
- protected readonly configure: alepha.HookPrimitive<"start">;
68
- protected readonly onRequest: alepha.HookPrimitive<"server:onRequest">;
67
+ protected readonly configure: _$alepha.HookPrimitive<"start">;
68
+ protected readonly onRequest: _$alepha.HookPrimitive<"server:onRequest">;
69
69
  isOriginAllowed(origin: string | undefined, allowed: CorsOptions["origin"]): boolean;
70
70
  }
71
71
  type ServerCorsProviderOptions = CorsOptions;
@@ -112,7 +112,7 @@ declare module "alepha/server" {
112
112
  *
113
113
  * @module alepha.server.cors
114
114
  */
115
- declare const AlephaServerCors: alepha.Service<alepha.Module>;
115
+ declare const AlephaServerCors: _$alepha.Service<_$alepha.Module>;
116
116
  //#endregion
117
117
  export { $cors, AlephaServerCors, CorsOptions, CorsRegistration, ServerCorsProvider, ServerCorsProviderOptions, corsOptions };
118
118
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/cors/providers/ServerCorsProvider.ts","../../../src/server/cors/primitives/$cors.ts","../../../src/server/cors/index.ts"],"mappings":";;;;;;;;;cASa,WAAA,EAAW,MAAA,CAAA,IAAA,QAAA,OAAA;2BAoCtB,MAAA,CAAA,OAAA;;;;;;KAEU,WAAA,GAAc,MAAA,QAAc,WAAA,CAAY,MAAA;AAAA;EAAA,UAGxC,KAAA;IAAA,CACP,WAAA,CAAY,GAAA,GAAM,WAAA;EAAA;AAAA;AAAA,UAMN,gBAAA,SAAyB,OAAA,CAAQ,WAAA;;;;EAIhD,IAAA;EApDsB;;;EAwDtB,KAAA;AAAA;AAAA,cAGW,kBAAA;EAAA,mBACQ,GAAA,EADU,cAAA,CACP,MAAA;EAAA,mBACH,oBAAA,EAAoB,oBAAA;EAAA,mBACpB,aAAA,EAAa,QAAA;;;;;;;;;;WAKhB,iBAAA,EAAmB,gBAAA;EA7BzB;;;EAkCH,YAAA,CAAa,MAAA,EAAQ,gBAAA;EAAA,mBAIT,OAAA,EAJyB,MAAA,CAIlB,aAAA;EAtCY;;;EAgE/B,gBAAA,CAAiB,MAAA,EAAQ,OAAA,CAAQ,WAAA,IAAe,WAAA;EAhEG;;;EA6EnD,gBAAA,CACL,OAAA;IACE,OAAA;MAAW,MAAA;IAAA;IACX,KAAA;MAAS,SAAA,GAAY,IAAA,UAAc,KAAA;IAAA;EAAA,GAErC,OAAA,EAAS,WAAA;EAAA,mBAqBQ,SAAA,EArBG,MAAA,CAqBM,aAAA;EAAA,mBAwBT,SAAA,EAxBS,MAAA,CAwBA,aAAA;EASrB,eAAA,CACL,MAAA,sBACA,OAAA,EAAS,WAAA;AAAA;AAAA,KAWD,yBAAA,GAA4B,WAAA;;;;;;;AA3LxC;;;;;;;;;;;;;;;;;cCkBa,KAAA,GAAS,OAAA,GAAU,OAAA,CAAQ,WAAA,MAAe,UAAA;;;;YCb3C,WAAA;;AFLZ;;;IEUI,IAAA,GAAO,WAAA;EAAA;AAAA;;;;;;;;;cAcE,gBAAA,EAAgB,MAAA,CAAA,OAAA,CAG3B,MAAA,CAH2B,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/cors/providers/ServerCorsProvider.ts","../../../src/server/cors/primitives/$cors.ts","../../../src/server/cors/index.ts"],"mappings":";;;;;;;;;cASa,WAAA,EAAW,QAAA,CAAA,IAAA,UAAA,OAAA;6BAoCtB,QAAA,CAAA,OAAA;;;;;;KAEU,WAAA,GAAc,MAAA,QAAc,WAAA,CAAY,MAAA;AAAA;EAAA,UAGxC,KAAA;IAAA,CACP,WAAA,CAAY,GAAA,GAAM,WAAA;EAAA;AAAA;AAAA,UAMN,gBAAA,SAAyB,OAAA,CAAQ,WAAA;;;;EAIhD,IAAA;EApDsB;;;EAwDtB,KAAA;AAAA;AAAA,cAGW,kBAAA;EAAA,mBACQ,GAAA,EADU,gBAAA,CACP,MAAA;EAAA,mBACH,oBAAA,EAAoB,oBAAA;EAAA,mBACpB,aAAA,EAAa,QAAA;;;;;;;;;;WAKhB,iBAAA,EAAmB,gBAAA;EA7BzB;;;EAkCH,YAAA,CAAa,MAAA,EAAQ,gBAAA;EAAA,mBAIT,OAAA,EAJyB,QAAA,CAIlB,aAAA;EAtCY;;;EAgE/B,gBAAA,CAAiB,MAAA,EAAQ,OAAA,CAAQ,WAAA,IAAe,WAAA;EAhEG;;;EA6EnD,gBAAA,CACL,OAAA;IACE,OAAA;MAAW,MAAA;IAAA;IACX,KAAA;MAAS,SAAA,GAAY,IAAA,UAAc,KAAA;IAAA;EAAA,GAErC,OAAA,EAAS,WAAA;EAAA,mBAqBQ,SAAA,EArBG,QAAA,CAqBM,aAAA;EAAA,mBAwBT,SAAA,EAxBS,QAAA,CAwBA,aAAA;EASrB,eAAA,CACL,MAAA,sBACA,OAAA,EAAS,WAAA;AAAA;AAAA,KAWD,yBAAA,GAA4B,WAAA;;;;;;;AA3LxC;;;;;;;;;;;;;;;;;cCkBa,KAAA,GAAS,OAAA,GAAU,OAAA,CAAQ,WAAA,MAAe,UAAA;;;;YCb3C,WAAA;;AFLZ;;;IEUI,IAAA,GAAO,WAAA;EAAA;AAAA;;;;;;;;;cAcE,gBAAA,EAAgB,QAAA,CAAA,OAAA,CAG3B,QAAA,CAH2B,MAAA"}
@@ -1,4 +1,4 @@
1
- import { $atom, $hook, $inject, $module, $use, AlephaError, createMiddleware, t } from "alepha";
1
+ import { $atom, $hook, $inject, $module, $state, AlephaError, createMiddleware, t } from "alepha";
2
2
  import { $logger } from "alepha/logger";
3
3
  import { ServerRouterProvider } from "alepha/server";
4
4
  //#region ../../src/server/cors/providers/ServerCorsProvider.ts
@@ -50,7 +50,7 @@ const corsOptions = $atom({
50
50
  var ServerCorsProvider = class {
51
51
  log = $logger();
52
52
  serverRouterProvider = $inject(ServerRouterProvider);
53
- globalOptions = $use(corsOptions);
53
+ globalOptions = $state(corsOptions);
54
54
  /**
55
55
  * Registered CORS configurations with their path patterns
56
56
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cors/providers/ServerCorsProvider.ts","../../../src/server/cors/primitives/$cors.ts","../../../src/server/cors/index.ts"],"sourcesContent":["import { $atom, $hook, $inject, $use, type Static, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerRouterProvider } from \"alepha/server\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * CORS configuration atom (global defaults)\n */\nexport const corsOptions = $atom({\n name: \"alepha.server.cors.options\",\n schema: t.object({\n origin: t.optional(\n t.string({\n description:\n \"Allowed origins (* for all, string for single, comma-separated for multiple)\",\n default: \"*\",\n }),\n ),\n methods: t.array(t.string(), {\n description: \"Allowed HTTP methods\",\n default: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n }),\n headers: t.array(t.string(), {\n description: \"Allowed headers\",\n default: [\"Content-Type\", \"Authorization\"],\n }),\n credentials: t.optional(\n t.boolean({\n description: \"Allow credentials\",\n default: false,\n }),\n ),\n maxAge: t.optional(\n t.number({\n description: \"Preflight cache duration in seconds\",\n }),\n ),\n }),\n default: {\n origin: \"*\",\n methods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n headers: [\"Content-Type\", \"Authorization\"],\n credentials: false,\n },\n});\n\nexport type CorsOptions = Static<typeof corsOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [corsOptions.key]: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CorsRegistration extends Partial<CorsOptions> {\n /**\n * Name identifier for this CORS config.\n */\n name?: string;\n /**\n * Path patterns to match (supports wildcards like /api/*).\n */\n paths?: string[];\n}\n\nexport class ServerCorsProvider {\n protected readonly log = $logger();\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly globalOptions = $use(corsOptions);\n\n /**\n * Registered CORS configurations with their path patterns\n */\n public readonly registeredConfigs: CorsRegistration[] = [];\n\n /**\n * Register a CORS configuration (called by primitives)\n */\n public registerCors(config: CorsRegistration): void {\n this.registeredConfigs.push(config);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Apply path-specific CORS configs to routes\n for (const config of this.registeredConfigs) {\n if (config.paths) {\n for (const pattern of config.paths) {\n const matchedRoutes = this.serverRouterProvider.getRoutes(pattern);\n for (const route of matchedRoutes) {\n route.cors = this.buildCorsOptions(config);\n }\n }\n }\n }\n\n if (this.registeredConfigs.length > 0) {\n this.log.info(\n `Initialized with ${this.registeredConfigs.length} registered CORS configurations.`,\n );\n }\n },\n });\n\n /**\n * Build complete CORS options by merging with global defaults\n */\n public buildCorsOptions(config: Partial<CorsOptions>): CorsOptions {\n return {\n origin: config.origin ?? this.globalOptions.origin,\n methods: config.methods ?? this.globalOptions.methods,\n headers: config.headers ?? this.globalOptions.headers,\n credentials: config.credentials ?? this.globalOptions.credentials,\n maxAge: config.maxAge ?? this.globalOptions.maxAge,\n };\n }\n\n /**\n * Apply CORS headers to the response\n */\n public applyCorsHeaders(\n request: {\n headers: { origin?: string };\n reply: { setHeader: (name: string, value: string) => void };\n },\n options: CorsOptions,\n ): void {\n const reqOrigin = request.headers.origin;\n const { origin, methods, headers, credentials, maxAge } = options;\n\n if (reqOrigin && this.isOriginAllowed(reqOrigin, origin)) {\n request.reply.setHeader(\"Access-Control-Allow-Origin\", reqOrigin);\n }\n\n if (credentials) {\n request.reply.setHeader(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n request.reply.setHeader(\"Access-Control-Allow-Methods\", methods.join(\", \"));\n request.reply.setHeader(\"Access-Control-Allow-Headers\", headers.join(\", \"));\n\n if (maxAge != null) {\n request.reply.setHeader(\"Access-Control-Max-Age\", String(maxAge));\n }\n }\n\n protected readonly configure = $hook({\n on: \"start\",\n handler: () => {\n const routes = this.serverRouterProvider.getRoutes();\n for (const route of routes) {\n if (\n !route.method ||\n route.method === \"GET\" ||\n route.method === \"OPTIONS\"\n ) {\n continue;\n }\n\n this.serverRouterProvider.createRoute({\n path: route.path,\n method: \"OPTIONS\",\n handler: ({ reply }) => {\n reply.setStatus(204);\n },\n });\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ route, request }) => {\n // Use route-specific CORS if defined, otherwise use global options\n const corsConfig = route.cors ?? this.globalOptions;\n this.applyCorsHeaders(request, corsConfig);\n },\n });\n\n public isOriginAllowed(\n origin: string | undefined,\n allowed: CorsOptions[\"origin\"],\n ): boolean {\n if (!allowed) return false;\n if (allowed === \"*\") return true;\n return allowed\n .split(\",\")\n .map((o) => o.trim())\n .includes(origin ?? \"\");\n }\n}\n\nexport type ServerCorsProviderOptions = CorsOptions;\n","import { AlephaError, createMiddleware, type Middleware } from \"alepha\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"../providers/ServerCorsProvider.ts\";\n\n/**\n * Middleware that applies CORS headers to the response and handles OPTIONS preflight.\n *\n * Reads the request from the ALS context and applies the configured\n * CORS headers via `ServerCorsProvider`. Options are merged with\n * global CORS defaults.\n *\n * For OPTIONS preflight requests, the middleware short-circuits with a 204 response\n * and skips the handler entirely.\n *\n * **Route middleware** — requires a request context (`$action`). Throws if used outside one.\n *\n * ```typescript\n * class ApiController {\n * getOrders = $action({\n * use: [$cors({ origin: \"https://app.example.com\", credentials: true })],\n * handler: async ({ query }) => { ... },\n * });\n * }\n * ```\n */\nexport const $cors = (options?: Partial<CorsOptions>): Middleware => {\n return createMiddleware({\n name: \"$cors\",\n options: options as unknown as Record<string, unknown>,\n handler: ({ alepha, next }) => {\n const corsProvider = alepha.inject(ServerCorsProvider);\n\n return async (...args) => {\n const request = alepha.get(\"alepha.http.request\");\n\n if (!request) {\n throw new AlephaError(\n \"$cors requires a request context (use inside $action)\",\n );\n }\n\n const corsConfig = corsProvider.buildCorsOptions(options ?? {});\n corsProvider.applyCorsHeaders(request, corsConfig);\n\n // OPTIONS preflight → respond immediately, skip handler\n if (request.method === \"OPTIONS\") {\n request.reply.setStatus(204);\n return;\n }\n\n return next(...args);\n };\n },\n });\n};\n","import { $module } from \"alepha\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$cors.ts\";\nexport * from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Route-specific CORS configuration.\n * If set, overrides the global CORS options for this route.\n */\n cors?: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cross-Origin Resource Sharing configuration.\n *\n * **Features:**\n * - CORS policy definition\n *\n * @module alepha.server.cors\n */\nexport const AlephaServerCors = $module({\n name: \"alepha.server.cors\",\n services: [ServerCorsProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cors/providers/ServerCorsProvider.ts","../../../src/server/cors/primitives/$cors.ts","../../../src/server/cors/index.ts"],"sourcesContent":["import { $atom, $hook, $inject, $state, type Static, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerRouterProvider } from \"alepha/server\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * CORS configuration atom (global defaults)\n */\nexport const corsOptions = $atom({\n name: \"alepha.server.cors.options\",\n schema: t.object({\n origin: t.optional(\n t.string({\n description:\n \"Allowed origins (* for all, string for single, comma-separated for multiple)\",\n default: \"*\",\n }),\n ),\n methods: t.array(t.string(), {\n description: \"Allowed HTTP methods\",\n default: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n }),\n headers: t.array(t.string(), {\n description: \"Allowed headers\",\n default: [\"Content-Type\", \"Authorization\"],\n }),\n credentials: t.optional(\n t.boolean({\n description: \"Allow credentials\",\n default: false,\n }),\n ),\n maxAge: t.optional(\n t.number({\n description: \"Preflight cache duration in seconds\",\n }),\n ),\n }),\n default: {\n origin: \"*\",\n methods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n headers: [\"Content-Type\", \"Authorization\"],\n credentials: false,\n },\n});\n\nexport type CorsOptions = Static<typeof corsOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [corsOptions.key]: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CorsRegistration extends Partial<CorsOptions> {\n /**\n * Name identifier for this CORS config.\n */\n name?: string;\n /**\n * Path patterns to match (supports wildcards like /api/*).\n */\n paths?: string[];\n}\n\nexport class ServerCorsProvider {\n protected readonly log = $logger();\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly globalOptions = $state(corsOptions);\n\n /**\n * Registered CORS configurations with their path patterns\n */\n public readonly registeredConfigs: CorsRegistration[] = [];\n\n /**\n * Register a CORS configuration (called by primitives)\n */\n public registerCors(config: CorsRegistration): void {\n this.registeredConfigs.push(config);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Apply path-specific CORS configs to routes\n for (const config of this.registeredConfigs) {\n if (config.paths) {\n for (const pattern of config.paths) {\n const matchedRoutes = this.serverRouterProvider.getRoutes(pattern);\n for (const route of matchedRoutes) {\n route.cors = this.buildCorsOptions(config);\n }\n }\n }\n }\n\n if (this.registeredConfigs.length > 0) {\n this.log.info(\n `Initialized with ${this.registeredConfigs.length} registered CORS configurations.`,\n );\n }\n },\n });\n\n /**\n * Build complete CORS options by merging with global defaults\n */\n public buildCorsOptions(config: Partial<CorsOptions>): CorsOptions {\n return {\n origin: config.origin ?? this.globalOptions.origin,\n methods: config.methods ?? this.globalOptions.methods,\n headers: config.headers ?? this.globalOptions.headers,\n credentials: config.credentials ?? this.globalOptions.credentials,\n maxAge: config.maxAge ?? this.globalOptions.maxAge,\n };\n }\n\n /**\n * Apply CORS headers to the response\n */\n public applyCorsHeaders(\n request: {\n headers: { origin?: string };\n reply: { setHeader: (name: string, value: string) => void };\n },\n options: CorsOptions,\n ): void {\n const reqOrigin = request.headers.origin;\n const { origin, methods, headers, credentials, maxAge } = options;\n\n if (reqOrigin && this.isOriginAllowed(reqOrigin, origin)) {\n request.reply.setHeader(\"Access-Control-Allow-Origin\", reqOrigin);\n }\n\n if (credentials) {\n request.reply.setHeader(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n request.reply.setHeader(\"Access-Control-Allow-Methods\", methods.join(\", \"));\n request.reply.setHeader(\"Access-Control-Allow-Headers\", headers.join(\", \"));\n\n if (maxAge != null) {\n request.reply.setHeader(\"Access-Control-Max-Age\", String(maxAge));\n }\n }\n\n protected readonly configure = $hook({\n on: \"start\",\n handler: () => {\n const routes = this.serverRouterProvider.getRoutes();\n for (const route of routes) {\n if (\n !route.method ||\n route.method === \"GET\" ||\n route.method === \"OPTIONS\"\n ) {\n continue;\n }\n\n this.serverRouterProvider.createRoute({\n path: route.path,\n method: \"OPTIONS\",\n handler: ({ reply }) => {\n reply.setStatus(204);\n },\n });\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ route, request }) => {\n // Use route-specific CORS if defined, otherwise use global options\n const corsConfig = route.cors ?? this.globalOptions;\n this.applyCorsHeaders(request, corsConfig);\n },\n });\n\n public isOriginAllowed(\n origin: string | undefined,\n allowed: CorsOptions[\"origin\"],\n ): boolean {\n if (!allowed) return false;\n if (allowed === \"*\") return true;\n return allowed\n .split(\",\")\n .map((o) => o.trim())\n .includes(origin ?? \"\");\n }\n}\n\nexport type ServerCorsProviderOptions = CorsOptions;\n","import { AlephaError, createMiddleware, type Middleware } from \"alepha\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"../providers/ServerCorsProvider.ts\";\n\n/**\n * Middleware that applies CORS headers to the response and handles OPTIONS preflight.\n *\n * Reads the request from the ALS context and applies the configured\n * CORS headers via `ServerCorsProvider`. Options are merged with\n * global CORS defaults.\n *\n * For OPTIONS preflight requests, the middleware short-circuits with a 204 response\n * and skips the handler entirely.\n *\n * **Route middleware** — requires a request context (`$action`). Throws if used outside one.\n *\n * ```typescript\n * class ApiController {\n * getOrders = $action({\n * use: [$cors({ origin: \"https://app.example.com\", credentials: true })],\n * handler: async ({ query }) => { ... },\n * });\n * }\n * ```\n */\nexport const $cors = (options?: Partial<CorsOptions>): Middleware => {\n return createMiddleware({\n name: \"$cors\",\n options: options as unknown as Record<string, unknown>,\n handler: ({ alepha, next }) => {\n const corsProvider = alepha.inject(ServerCorsProvider);\n\n return async (...args) => {\n const request = alepha.get(\"alepha.http.request\");\n\n if (!request) {\n throw new AlephaError(\n \"$cors requires a request context (use inside $action)\",\n );\n }\n\n const corsConfig = corsProvider.buildCorsOptions(options ?? {});\n corsProvider.applyCorsHeaders(request, corsConfig);\n\n // OPTIONS preflight → respond immediately, skip handler\n if (request.method === \"OPTIONS\") {\n request.reply.setStatus(204);\n return;\n }\n\n return next(...args);\n };\n },\n });\n};\n","import { $module } from \"alepha\";\nimport {\n type CorsOptions,\n ServerCorsProvider,\n} from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$cors.ts\";\nexport * from \"./providers/ServerCorsProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Route-specific CORS configuration.\n * If set, overrides the global CORS options for this route.\n */\n cors?: CorsOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cross-Origin Resource Sharing configuration.\n *\n * **Features:**\n * - CORS policy definition\n *\n * @module alepha.server.cors\n */\nexport const AlephaServerCors = $module({\n name: \"alepha.server.cors\",\n services: [ServerCorsProvider],\n});\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import * as alepha from "alepha";
1
+ import * as _$alepha from "alepha";
2
2
  import { Alepha, Middleware } from "alepha";
3
- import * as alepha_cache0 from "alepha/cache";
3
+ import * as _$alepha_cache0 from "alepha/cache";
4
4
  import { CachePrimitiveOptions } from "alepha/cache";
5
5
  import { CryptoProvider } from "alepha/crypto";
6
6
  import { DateTimeProvider, DurationLike } from "alepha/datetime";
7
- import * as alepha_logger0 from "alepha/logger";
7
+ import * as _$alepha_logger0 from "alepha/logger";
8
8
  import { ServerRequest, ServerRoute } from "alepha/server";
9
9
 
10
10
  //#region ../../src/server/etag/primitives/$etag.d.ts
@@ -138,11 +138,11 @@ interface EtagMiddlewareOptionsResolved {
138
138
  //#endregion
139
139
  //#region ../../src/server/etag/providers/ServerEtagProvider.d.ts
140
140
  declare class ServerEtagProvider {
141
- protected readonly log: alepha_logger0.Logger;
141
+ protected readonly log: _$alepha_logger0.Logger;
142
142
  protected readonly alepha: Alepha;
143
143
  protected readonly crypto: CryptoProvider;
144
144
  protected readonly time: DateTimeProvider;
145
- protected readonly cache: alepha_cache0.CacheMiddlewareFn<RouteCacheEntry>;
145
+ protected readonly cache: _$alepha_cache0.CacheMiddlewareFn<RouteCacheEntry>;
146
146
  generateETag(content: string | Buffer): string;
147
147
  invalidate(route: ServerRoute): Promise<void>;
148
148
  /**
@@ -153,16 +153,16 @@ declare class ServerEtagProvider {
153
153
  /**
154
154
  * After an action response, store it in cache if store is enabled.
155
155
  */
156
- protected readonly onActionResponse: alepha.HookPrimitive<"action:onResponse">;
156
+ protected readonly onActionResponse: _$alepha.HookPrimitive<"action:onResponse">;
157
157
  /**
158
158
  * Before sending the response, check ETag for etag-only routes.
159
159
  * This handles the case where etag is enabled but store is not.
160
160
  */
161
- protected readonly onSend: alepha.HookPrimitive<"server:onSend">;
161
+ protected readonly onSend: _$alepha.HookPrimitive<"server:onSend">;
162
162
  /**
163
163
  * After the response is generated, store it and set ETag headers.
164
164
  */
165
- protected readonly onResponse: alepha.HookPrimitive<"server:onResponse">;
165
+ protected readonly onResponse: _$alepha.HookPrimitive<"server:onResponse">;
166
166
  buildCacheControlHeader(options?: EtagMiddlewareOptionsResolved): string | undefined;
167
167
  shouldStore(options?: EtagMiddlewareOptionsResolved): boolean;
168
168
  shouldUseEtag(options?: EtagMiddlewareOptionsResolved): boolean;
@@ -194,7 +194,7 @@ interface RouteCacheEntry {
194
194
  *
195
195
  * @module alepha.server.etag
196
196
  */
197
- declare const AlephaServerEtag: alepha.Service<alepha.Module>;
197
+ declare const AlephaServerEtag: _$alepha.Service<_$alepha.Module>;
198
198
  //#endregion
199
199
  export { $etag, AlephaServerEtag, EtagMiddlewareOptions, EtagMiddlewareOptionsResolved, ServerEtagProvider, resolveEtagOptions };
200
200
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/etag/primitives/$etag.ts","../../../src/server/etag/providers/ServerEtagProvider.ts","../../../src/server/etag/index.ts"],"mappings":";;;;;;;;;;;;;;;;;AAyCA;;;;;;;;;AAsCA;;;;;;;;;AAgBA;;;;;;;;;cAtDa,KAAA,GAAS,OAAA,GAAU,qBAAA,KAAwB,UAAA;AAAA,iBAsCxC,kBAAA,CACd,OAAA,GAAU,qBAAA,GACT,6BAAA;AAAA,KAcS,qBAAA;;;;;;;;;EAsDkB;;;;;;;EAtCxB,KAAA,UAAe,YAAA,GAAe,qBAAA;EA6DoB;;AAIxD;;;EA1DM,IAAA;EA2D0B;;;;;EApD1B,OAAA;IAoDJ;;;IA7CU,MAAA;IA+CV;;;IA3CU,OAAA;IAkDJ;;;IA9CI,OAAA;IAgDe;;;IA5Cf,OAAA;IAgDJ;;;;IA3CI,MAAA,YAAkB,YAAA;;;AC3I9B;;IDgJY,OAAA,YAAmB,YAAA;IChJA;;;IDoJnB,cAAA;IC/Ic;;;IDmJd,eAAA;ICzIgC;;;ID6IhC,SAAA;IClIA;;;;;IDwIA,oBAAA,YAAgC,YAAA;EAAA;AAAA;AAAA,UAI3B,6BAAA;EACf,KAAA,UAAe,YAAA,GAAe,qBAAA;EAC9B,IAAA;EACA,OAAA;IAIM,MAAA;IACA,OAAA;IACA,OAAA;IACA,OAAA;IACA,MAAA,YAAkB,YAAA;IAClB,OAAA,YAAmB,YAAA;IACnB,cAAA;IACA,eAAA;IACA,SAAA;IACA,oBAAA,YAAgC,YAAA;EAAA;AAAA;;;cCtL3B,kBAAA;EAAA,mBACQ,GAAA,EADU,cAAA,CACP,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,mBACN,MAAA,EAAM,cAAA;EAAA,mBACN,IAAA,EAAI,gBAAA;EAAA,mBACJ,KAAA,EAAK,aAAA,CAAA,iBAAA,CAAA,eAAA;EAKjB,YAAA,CAAa,OAAA,WAAkB,MAAA;EAKzB,UAAA,CAAW,KAAA,EAAO,WAAA,GAAW,OAAA;EDkD3C;;;;EC1Cc,UAAA,CACX,OAAA,EAAS,aAAA,EACT,OAAA,EAAS,6BAAA,GACR,OAAA;EDuCJ;AAID;;EAJC,mBCuCoB,gBAAA,EA9ET,MAAA,CA8EyB,aAAA;EDjCL;;;;EAAA,mBC0FX,MAAA,EAzDgB,MAAA,CAyDV,aAAA;ED1FK;AAchC;;EAdgC,mBCqIX,UAAA,EA3CM,MAAA,CA2CI,aAAA;EA0GtB,uBAAA,CACL,OAAA,GAAU,6BAAA;EA6DL,WAAA,CAAY,OAAA,GAAU,6BAAA;EAMtB,aAAA,CAAc,OAAA,GAAU,6BAAA;EAAA,UAUrB,iBAAA,CAAkB,QAAA,WAAmB,YAAA;EAAA,UAQrC,cAAA,CAAe,KAAA,EAAO,WAAA,EAAa,MAAA,GAAS,aAAA;ED1OA;;;;EAAA,UC0PtC,qBAAA,CACd,MAAA,EAAQ,cAAA,CAAe,UAAA,GACvB,GAAA,UACA,MAAA,sBACA,WAAA,sBACA,YAAA,YACC,OAAA;AAAA;AAAA,UAwCK,eAAA;EACR,WAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA;EACA,IAAA;AAAA;;;;;;;;;;;ADhbF;;;cElBa,gBAAA,EAAgB,MAAA,CAAA,OAAA,CAG3B,MAAA,CAH2B,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/etag/primitives/$etag.ts","../../../src/server/etag/providers/ServerEtagProvider.ts","../../../src/server/etag/index.ts"],"mappings":";;;;;;;;;;;;;;;;;AAyCA;;;;;;;;;AAsCA;;;;;;;;;AAgBA;;;;;;;;;cAtDa,KAAA,GAAS,OAAA,GAAU,qBAAA,KAAwB,UAAA;AAAA,iBAsCxC,kBAAA,CACd,OAAA,GAAU,qBAAA,GACT,6BAAA;AAAA,KAcS,qBAAA;;;;;;;;;EAsDkB;;;;;;;EAtCxB,KAAA,UAAe,YAAA,GAAe,qBAAA;EA6DoB;;AAIxD;;;EA1DM,IAAA;EA2D0B;;;;;EApD1B,OAAA;IAoDJ;;;IA7CU,MAAA;IA+CV;;;IA3CU,OAAA;IAkDJ;;;IA9CI,OAAA;IAgDe;;;IA5Cf,OAAA;IAgDJ;;;;IA3CI,MAAA,YAAkB,YAAA;;;AC3I9B;;IDgJY,OAAA,YAAmB,YAAA;IChJA;;;IDoJnB,cAAA;IC/Ic;;;IDmJd,eAAA;ICzIgC;;;ID6IhC,SAAA;IClIA;;;;;IDwIA,oBAAA,YAAgC,YAAA;EAAA;AAAA;AAAA,UAI3B,6BAAA;EACf,KAAA,UAAe,YAAA,GAAe,qBAAA;EAC9B,IAAA;EACA,OAAA;IAIM,MAAA;IACA,OAAA;IACA,OAAA;IACA,OAAA;IACA,MAAA,YAAkB,YAAA;IAClB,OAAA,YAAmB,YAAA;IACnB,cAAA;IACA,eAAA;IACA,SAAA;IACA,oBAAA,YAAgC,YAAA;EAAA;AAAA;;;cCtL3B,kBAAA;EAAA,mBACQ,GAAA,EADU,gBAAA,CACP,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,mBACN,MAAA,EAAM,cAAA;EAAA,mBACN,IAAA,EAAI,gBAAA;EAAA,mBACJ,KAAA,EAAK,eAAA,CAAA,iBAAA,CAAA,eAAA;EAKjB,YAAA,CAAa,OAAA,WAAkB,MAAA;EAKzB,UAAA,CAAW,KAAA,EAAO,WAAA,GAAW,OAAA;EDkD3C;;;;EC1Cc,UAAA,CACX,OAAA,EAAS,aAAA,EACT,OAAA,EAAS,6BAAA,GACR,OAAA;EDuCJ;AAID;;EAJC,mBCuCoB,gBAAA,EA9ET,QAAA,CA8EyB,aAAA;EDjCL;;;;EAAA,mBC0FX,MAAA,EAzDgB,QAAA,CAyDV,aAAA;ED1FK;AAchC;;EAdgC,mBCqIX,UAAA,EA3CM,QAAA,CA2CI,aAAA;EA0GtB,uBAAA,CACL,OAAA,GAAU,6BAAA;EA6DL,WAAA,CAAY,OAAA,GAAU,6BAAA;EAMtB,aAAA,CAAc,OAAA,GAAU,6BAAA;EAAA,UAUrB,iBAAA,CAAkB,QAAA,WAAmB,YAAA;EAAA,UAQrC,cAAA,CAAe,KAAA,EAAO,WAAA,EAAa,MAAA,GAAS,aAAA;ED1OA;;;;EAAA,UC0PtC,qBAAA,CACd,MAAA,EAAQ,cAAA,CAAe,UAAA,GACvB,GAAA,UACA,MAAA,sBACA,WAAA,sBACA,YAAA,YACC,OAAA;AAAA;AAAA,UAwCK,eAAA;EACR,WAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA;EACA,IAAA;AAAA;;;;;;;;;;;ADhbF;;;cElBa,gBAAA,EAAgB,QAAA,CAAA,OAAA,CAG3B,QAAA,CAH2B,MAAA"}
@@ -1,6 +1,6 @@
1
- import * as alepha from "alepha";
1
+ import * as _$alepha from "alepha";
2
2
  import { Alepha } from "alepha";
3
- import * as alepha_server0 from "alepha/server";
3
+ import * as _$alepha_server0 from "alepha/server";
4
4
  import { DateTimeProvider } from "alepha/datetime";
5
5
 
6
6
  //#region ../../src/server/health/providers/ServerHealthProvider.d.ts
@@ -12,20 +12,20 @@ import { DateTimeProvider } from "alepha/datetime";
12
12
  declare class ServerHealthProvider {
13
13
  protected readonly time: DateTimeProvider;
14
14
  protected readonly alepha: Alepha;
15
- readonly health: alepha_server0.RoutePrimitive<{
16
- response: alepha.TObject<{
17
- message: alepha.TString;
18
- uptime: alepha.TNumber;
19
- date: alepha.TString;
20
- ready: alepha.TBoolean;
15
+ readonly health: _$alepha_server0.RoutePrimitive<{
16
+ response: _$alepha.TObject<{
17
+ message: _$alepha.TString;
18
+ uptime: _$alepha.TNumber;
19
+ date: _$alepha.TString;
20
+ ready: _$alepha.TBoolean;
21
21
  }>;
22
22
  }>;
23
- readonly healthz: alepha_server0.RoutePrimitive<{
24
- response: alepha.TObject<{
25
- message: alepha.TString;
26
- uptime: alepha.TNumber;
27
- date: alepha.TString;
28
- ready: alepha.TBoolean;
23
+ readonly healthz: _$alepha_server0.RoutePrimitive<{
24
+ response: _$alepha.TObject<{
25
+ message: _$alepha.TString;
26
+ uptime: _$alepha.TNumber;
27
+ date: _$alepha.TString;
28
+ ready: _$alepha.TBoolean;
29
29
  }>;
30
30
  }>;
31
31
  protected healthCheck(): {
@@ -37,11 +37,11 @@ declare class ServerHealthProvider {
37
37
  }
38
38
  //#endregion
39
39
  //#region ../../src/server/health/schemas/healthSchema.d.ts
40
- declare const healthSchema: alepha.TObject<{
41
- message: alepha.TString;
42
- uptime: alepha.TNumber;
43
- date: alepha.TString;
44
- ready: alepha.TBoolean;
40
+ declare const healthSchema: _$alepha.TObject<{
41
+ message: _$alepha.TString;
42
+ uptime: _$alepha.TNumber;
43
+ date: _$alepha.TString;
44
+ ready: _$alepha.TBoolean;
45
45
  }>;
46
46
  //#endregion
47
47
  //#region ../../src/server/health/index.d.ts
@@ -53,7 +53,7 @@ declare const healthSchema: alepha.TObject<{
53
53
  *
54
54
  * @module alepha.server.health
55
55
  */
56
- declare const AlephaServerHealth: alepha.Service<alepha.Module>;
56
+ declare const AlephaServerHealth: _$alepha.Service<_$alepha.Module>;
57
57
  //#endregion
58
58
  export { AlephaServerHealth, ServerHealthProvider, healthSchema };
59
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/health/providers/ServerHealthProvider.ts","../../../src/server/health/schemas/healthSchema.ts","../../../src/server/health/index.ts"],"mappings":";;;;;;;;;;AAUA;cAAa,oBAAA;EAAA,mBACQ,IAAA,EAAM,gBAAA;EAAA,mBACN,MAAA,EAAM,MAAA;EAAA,SAET,MAAA,iBAAM,cAAA;;eAFG,MAAA,CAAA,OAAA;;;;;;WAWT,OAAA,iBAAO,cAAA;;eATD,MAAA,CAAA,OAAA;;;;;;YAkBZ,WAAA,CAAA;;;;;;;;;cC9BC,YAAA,SAAY,OAAA;WAKvB,MAAA,CAAA,OAAA;;;;;;;;;;;ADGF;;;;cESa,kBAAA,EAAkB,MAAA,CAAA,OAAA,CAG7B,MAAA,CAH6B,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/health/providers/ServerHealthProvider.ts","../../../src/server/health/schemas/healthSchema.ts","../../../src/server/health/index.ts"],"mappings":";;;;;;;;;;AAUA;cAAa,oBAAA;EAAA,mBACQ,IAAA,EAAM,gBAAA;EAAA,mBACN,MAAA,EAAM,MAAA;EAAA,SAET,MAAA,mBAAM,cAAA;;eAFG,QAAA,CAAA,OAAA;;;;;;WAWT,OAAA,mBAAO,cAAA;;eATD,QAAA,CAAA,OAAA;;;;;;YAkBZ,WAAA,CAAA;;;;;;;;;cC9BC,YAAA,WAAY,OAAA;WAKvB,QAAA,CAAA,OAAA;;;;;;;;;;;ADGF;;;;cESa,kBAAA,EAAkB,QAAA,CAAA,OAAA,CAG7B,QAAA,CAH6B,MAAA"}
@@ -1,4 +1,4 @@
1
- import { $atom, $inject, $module, $use, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
1
+ import { $atom, $inject, $module, $state, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
2
2
  import { $logger } from "alepha/logger";
3
3
  import { HttpClient, HttpError, ServerReply, UnauthorizedError } from "alepha/server";
4
4
  //#region ../../src/server/links/schemas/apiLinksResponseSchema.ts
@@ -159,7 +159,7 @@ var LinkProvider = class LinkProvider {
159
159
  permissions = /* @__PURE__ */ new Set();
160
160
  lastLoadedRegistry = null;
161
161
  batchCollector;
162
- options = $use(linkOptionsAtom);
162
+ options = $state(linkOptionsAtom);
163
163
  /**
164
164
  * Get applicative links registered on the server.
165
165
  * This does not include lazy-loaded remote links.
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/server/links/schemas/apiLinksResponseSchema.ts","../../../src/server/links/atoms/apiLinksAtom.ts","../../../src/server/links/atoms/linkOptionsAtom.ts","../../../src/server/links/services/BatchCollector.ts","../../../src/server/links/providers/LinkProvider.ts","../../../src/server/links/primitives/$client.ts","../../../src/server/links/primitives/$remote.ts","../../../src/server/links/index.browser.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const apiActionSchema = t.object({\n path: t.text({\n description: \"Pathname used to access the action.\",\n }),\n\n method: t.optional(\n t.text({\n description:\n \"HTTP method. Omitted when GET (the default for ~75% of actions).\",\n }),\n ),\n\n contentType: t.optional(\n t.text({\n description:\n \"Content type for the request body. Only present for non-JSON types (e.g. 'multipart/form-data'). When absent, defaults to application/json.\",\n }),\n ),\n\n kind: t.optional(\n t.text({\n description:\n \"Action kind. Used to distinguish special action types (e.g. 'sse' for Server-Sent Events streams).\",\n }),\n ),\n\n service: t.optional(\n t.text({\n description:\n \"Service name associated with the action, used for service discovery and routing.\",\n }),\n ),\n});\n\nexport const apiRegistryResponseSchema = t.object({\n prefix: t.optional(t.text()),\n\n actions: t.record(t.text(), apiActionSchema),\n\n permissions: t.optional(t.array(t.text())),\n});\n\nexport type ApiRegistryResponse = Static<typeof apiRegistryResponseSchema>;\nexport type ApiAction = Static<typeof apiActionSchema>;\n\n/**\n * @deprecated Use `apiRegistryResponseSchema` and `ApiRegistryResponse` instead.\n */\nexport const apiLinksResponseSchema = apiRegistryResponseSchema;\n\n/**\n * @deprecated Use `ApiRegistryResponse` instead.\n */\nexport type ApiLinksResponse = ApiRegistryResponse;\n\n/**\n * @deprecated Use `ApiAction` instead.\n */\nexport type ApiLink = ApiAction;\n","import { $atom, t } from \"alepha\";\nimport { apiRegistryResponseSchema } from \"../schemas/apiLinksResponseSchema.ts\";\n\nexport const apiLinksAtom = $atom({\n name: \"alepha.server.request.apiLinks\",\n schema: t.optional(apiRegistryResponseSchema),\n});\n","import { $atom, t } from \"alepha\";\n\nexport const linkOptionsAtom = $atom({\n name: \"alepha.server.links.options\",\n description: \"Configuration options for the links module.\",\n schema: t.object({\n batch: t.boolean({\n description: \"Enable batch collection for browser-side calls.\",\n default: true,\n }),\n }),\n default: {\n batch: true,\n },\n});\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { HttpClient, HttpError } from \"alepha/server\";\n\n/**\n * Collects browser-side action calls within a microtask and\n * sends them as a single `POST /api/_batch` request.\n *\n * Key behaviors:\n * - Single call in the window → direct HTTP call (no batch overhead)\n * - Multiple calls → coalesced into one batch request\n * - Same action + same params/query/body → deduplicated, result shared\n * - Exceeding MAX_BATCH_SIZE → split into multiple batch calls\n * - Transport failure → all pending promises reject\n */\nexport class BatchCollector {\n protected static readonly MAX_BATCH_SIZE = 20;\n\n protected readonly log = $logger();\n protected readonly httpClient = $inject(HttpClient);\n\n protected pending: PendingBatchEntry[] = [];\n protected scheduled = false;\n\n /**\n * Add an action call to the batch. Returns the result when the batch resolves.\n */\n public add(entry: BatchEntry): Promise<any> {\n return new Promise((resolve, reject) => {\n this.pending.push({ entry, resolve, reject });\n\n if (!this.scheduled) {\n this.scheduled = true;\n setTimeout(() => {\n this.scheduled = false;\n this.flush().catch((err) => this.log.error(err));\n }, 10);\n }\n });\n }\n\n protected async flush(): Promise<void> {\n const batch = this.pending.splice(0);\n\n if (batch.length === 0) return;\n\n // Single request — skip batching, call directly via follow\n if (batch.length === 1) {\n const item = batch[0];\n try {\n const result = await item.entry.directCall();\n item.resolve(result);\n } catch (error) {\n item.reject(error);\n }\n return;\n }\n\n // Deduplicate: same action + same params → share result\n const { unique, indexMap } = this.dedupe(batch);\n\n // Split into chunks of MAX_BATCH_SIZE\n const chunks = this.chunk(unique, BatchCollector.MAX_BATCH_SIZE);\n\n try {\n const allResults = (\n await Promise.all(\n chunks.map((chunk) => {\n const actions = [...new Set(chunk.map((b) => b.entry.action))].join(\n \",\",\n );\n\n return this.httpClient\n .fetch(`/api/_batch?actions=${actions}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(\n chunk.map((b) => ({\n action: b.entry.action,\n params: b.entry.params,\n query: b.entry.query,\n body: b.entry.body,\n })),\n ),\n })\n .then((res) => res.data as BatchResponse[]);\n }),\n )\n ).flat();\n\n // Distribute results back (including deduped slots)\n for (let i = 0; i < batch.length; i++) {\n const result = allResults[indexMap[i]];\n if (result.status >= 400) {\n batch[i].reject(\n new HttpError({\n message:\n result.error ?? `${result.action} failed (${result.status})`,\n status: result.status,\n }),\n );\n } else {\n batch[i].resolve(result.data);\n }\n }\n } catch (error) {\n // Transport-level failure — reject all pending promises\n for (const item of batch) {\n item.reject(error);\n }\n }\n }\n\n protected dedupe(batch: PendingBatchEntry[]): {\n unique: PendingBatchEntry[];\n indexMap: number[];\n } {\n const seen = new Map<string, number>();\n const unique: PendingBatchEntry[] = [];\n const indexMap: number[] = [];\n\n for (const item of batch) {\n const key = `${item.entry.action}:${JSON.stringify({\n params: item.entry.params,\n query: item.entry.query,\n body: item.entry.body,\n })}`;\n\n const existing = seen.get(key);\n if (existing !== undefined) {\n indexMap.push(existing);\n } else {\n const idx = unique.length;\n seen.set(key, idx);\n unique.push(item);\n indexMap.push(idx);\n }\n }\n\n return { unique, indexMap };\n }\n\n protected chunk<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n }\n}\n\n// ---\n\nexport interface BatchEntry {\n action: string;\n params?: Record<string, any>;\n query?: Record<string, any>;\n body?: Record<string, any>;\n directCall: () => Promise<any>;\n}\n\ninterface PendingBatchEntry {\n entry: BatchEntry;\n resolve: (value: any) => void;\n reject: (reason: any) => void;\n}\n\ninterface BatchResponse {\n action: string;\n status: number;\n data?: any;\n error?: string;\n}\n","import { $inject, $use, Alepha, AlephaError, type Async, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { SecureOptions } from \"alepha/security\";\nimport {\n type ActionPrimitive,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type ClientRequestResponse,\n type FetchResponse,\n HttpClient,\n type RequestConfigSchema,\n ServerReply,\n type ServerRequest,\n type ServerRequestConfigEntry,\n type ServerResponseBody,\n type SseConfigSchema,\n type SseEventData,\n type SsePrimitive,\n type SseRequestEntry,\n type SseStream,\n UnauthorizedError,\n} from \"alepha/server\";\nimport { linkOptionsAtom } from \"../atoms/linkOptionsAtom.ts\";\nimport {\n type ApiRegistryResponse,\n apiRegistryResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\nimport { BatchCollector } from \"../services/BatchCollector.ts\";\n\n/**\n * Browser, SSR friendly, service to handle links.\n */\nexport class LinkProvider {\n static path = {\n apiLinks: \"/api/_links\",\n };\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n\n // Server-side: all registered links (local + remote), keyed by name\n protected serverLinkMap = new Map<string, HttpClientLink>();\n\n // Browser/SSR: parsed from the registry response\n protected actionMap = new Map<string, HttpClientLink>();\n protected permissions = new Set<string>();\n protected lastLoadedRegistry: ApiRegistryResponse | null = null;\n\n // Browser-only: batch collector for coalescing multiple calls\n protected batchCollector?: BatchCollector;\n\n protected readonly options = $use(linkOptionsAtom);\n\n /**\n * Get applicative links registered on the server.\n * This does not include lazy-loaded remote links.\n */\n public getServerLinks(): HttpClientLink[] {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Getting server links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return [];\n }\n\n return [...this.serverLinkMap.values()];\n }\n\n /**\n * Register a new link for the application.\n */\n public registerLink(link: HttpClientLink): void {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Registering links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return;\n }\n\n if (!link.handler && !link.host) {\n throw new AlephaError(\n \"Can't create link - 'handler' or 'host' is required\",\n );\n }\n\n // Detect duplicate local actions (programming error)\n const existing = this.serverLinkMap.get(link.name);\n if (existing?.handler && link.handler) {\n throw new AlephaError(\n `Duplicate action name \"${link.name}\". Each action must have a unique name.`,\n );\n }\n\n this.serverLinkMap.set(link.name, link);\n }\n\n /**\n * Load the registry response into internal stores (actionMap, permissions, definitions).\n * Called when storing from atom/fetch/SSR.\n */\n protected loadRegistry(registry: ApiRegistryResponse): void {\n this.lastLoadedRegistry = registry;\n this.permissions.clear();\n this.actionMap.clear();\n\n for (const [name, action] of Object.entries(registry.actions)) {\n this.actionMap.set(name, {\n name,\n path: action.path,\n kind: action.kind,\n method: action.method,\n contentType: action.contentType,\n service: action.service,\n });\n }\n\n if (registry.permissions) {\n for (const p of registry.permissions) {\n this.permissions.add(p);\n }\n }\n }\n\n public get links(): HttpClientLink[] {\n const registry = this.alepha.store.get(\"alepha.server.request.apiLinks\");\n\n if (registry) {\n if (this.alepha.isBrowser()) {\n // Browser side: use the parsed action map\n // Reload when registry changes (e.g. after login provides new authenticated links)\n if (this.actionMap.size === 0 || registry !== this.lastLoadedRegistry) {\n this.loadRegistry(registry);\n }\n return [...this.actionMap.values()];\n }\n\n // SSR side: map registry actions back to full server links\n const links: HttpClientLink[] = [];\n for (const name of Object.keys(registry.actions)) {\n const originalLink = this.serverLinkMap.get(name);\n if (originalLink) {\n links.push(originalLink);\n }\n }\n return links;\n }\n\n return [...this.serverLinkMap.values()];\n }\n\n /**\n * Force browser to refresh links from the server.\n */\n public async fetchLinks(): Promise<HttpClientLink[]> {\n const { data } = await this.httpClient.fetch(\n `${LinkProvider.path.apiLinks}`,\n {\n method: \"GET\",\n schema: {\n response: apiRegistryResponseSchema,\n },\n },\n );\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data);\n this.loadRegistry(data);\n\n return [...this.actionMap.values()];\n }\n\n /**\n * Create a virtual client that can be used to call actions.\n *\n * Use js Proxy under the hood.\n */\n public client<T extends object>(\n scope: ClientScope = {},\n ): HttpVirtualClient<T> {\n return new Proxy<HttpVirtualClient<T>>({} as HttpVirtualClient<T>, {\n get: (_, prop) => {\n if (typeof prop !== \"string\") {\n return;\n }\n\n return this.createVirtualAction<RequestConfigSchema>(prop, scope);\n },\n });\n }\n\n /**\n * Check if a link with the given name exists or a permission matches.\n *\n * Action names never contain colons. Permission names always do.\n * - `can(\"getUsers\")` → O(1) map lookup\n * - `can(\"admin:*\")` → wildcard match against permissions set\n * - `can(\"admin:user:read\")` → O(1) set lookup\n */\n public can(name: string): boolean {\n // Action check — O(1) map lookup\n if (this.actionMap.size > 0) {\n if (this.actionMap.has(name)) return true;\n } else {\n // Fallback for server-side where actionMap may not be populated\n if (this.serverLinkMap.has(name)) return true;\n // Also check links getter (for SSR with atom)\n if (this.links.some((link) => link.name === name)) return true;\n }\n\n // Permission check — wildcard matching\n if (name.includes(\":\")) {\n if (name.endsWith(\"*\")) {\n const prefix = name.slice(0, -1);\n for (const p of this.permissions) {\n if (p.startsWith(prefix)) return true;\n }\n return false;\n }\n return this.permissions.has(name);\n }\n\n return false;\n }\n\n /**\n * Resolve a link by its name and call it.\n * - If link is local, it will call the local handler.\n * - If link is remote, it will make a fetch request to the remote server.\n */\n public async follow(\n name: string,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions & ClientScope = {},\n ): Promise<any> {\n this.log.trace(\"Following link\", { name, config, options });\n const link = await this.getLinkByName(name, options);\n\n // if a handler is defined, use it (ssr)\n if (link.handler && !options.request) {\n this.log.trace(\"Local link found\", { name });\n return link.handler(\n {\n method: link.method,\n url: new URL(`http://localhost${link.path}`),\n query: config.query ?? {},\n body: config.body ?? {},\n params: config.params ?? {},\n headers: config.headers ?? {},\n metadata: {},\n reply: new ServerReply(),\n } as Partial<ServerRequest> as ServerRequest,\n options,\n );\n }\n\n this.log.trace(\"Remote link found\", {\n name,\n host: link.host,\n service: link.service,\n });\n\n // Browser-only: use batch collector for calls without explicit host\n if (this.options.batch && this.alepha.isBrowser() && !link.host) {\n this.batchCollector ??= this.alepha.inject(BatchCollector);\n return this.batchCollector.add({\n action: name,\n params: config.params as any,\n query: config.query as any,\n body: config.body as any,\n directCall: () =>\n this.followRemote(link, config, options).then((r) => r.data),\n });\n }\n\n return this.followRemote(link, config, options).then(\n (response) => response.data,\n );\n }\n\n protected createVirtualAction<T extends RequestConfigSchema>(\n name: string,\n scope: ClientScope = {},\n ): VirtualAction<T> {\n const $: VirtualAction<T> = async (\n config: any = {},\n options: ClientRequestOptions = {},\n ) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n Object.defineProperty($, \"name\", {\n value: name,\n writable: false,\n });\n\n $.run = async (config: any = {}, options: ClientRequestOptions = {}) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n $.fetch = async (config: any = {}, options: ClientRequestOptions = {}) => {\n const link = await this.getLinkByName(name, scope);\n return this.followRemote(link, config, options);\n };\n\n $.can = () => {\n return this.can(name);\n };\n\n return $;\n }\n\n protected async followRemote(\n link: HttpClientLink,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions = {},\n ): Promise<FetchResponse> {\n options.request ??= {};\n options.request.headers = new Headers(options.request.headers);\n\n const als = this.alepha.store.get(\"alepha.http.request\");\n if (als?.headers.authorization) {\n options.request.headers.set(\"authorization\", als.headers.authorization);\n }\n\n const context = this.alepha.context.get(\"context\");\n if (typeof context === \"string\") {\n options.request.headers.set(\"x-request-id\", context);\n }\n\n const action = {\n ...link,\n // schema is not used in the client,\n // we assume that TypeScript will check\n schema: {\n body: t.any(),\n response: t.any(),\n },\n };\n\n // prefix with service when host is not defined (e.g. browser)\n if (!link.host && link.service) {\n action.path = `/${link.service}${action.path}`;\n }\n\n action.path = `${action.prefix ?? \"/api\"}${action.path}`;\n action.prefix = undefined; // prefix is not used in the client\n\n // else, make a request\n return this.httpClient.fetchAction({\n host: link.host,\n config,\n options,\n action: action as any, // schema.body TAny is not accepted\n });\n }\n\n protected async getLinkByName(\n name: string,\n options: ClientScope = {},\n ): Promise<HttpClientLink> {\n if (\n this.alepha.isBrowser() &&\n !this.alepha.store.get(\"alepha.server.request.apiLinks\")\n ) {\n await this.fetchLinks();\n }\n\n const link = this.links.find(\n (a) =>\n a.name === name && (!options.service || options.service === a.service),\n );\n\n if (!link) {\n const error = new UnauthorizedError(`Action ${name} not found.`);\n // mimic http error handling\n await this.alepha.events.emit(\"client:onError\", {\n route: link,\n error,\n });\n throw error;\n }\n\n if (options.hostname) {\n return {\n ...link,\n host: options.hostname,\n };\n }\n\n return link;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface HttpClientLink {\n name: string;\n path: string;\n method?: string;\n kind?: string;\n contentType?: string;\n service?: string;\n secured?: boolean | SecureOptions;\n prefix?: string;\n group?: string;\n // -- server only --\n host?: string;\n schema?: RequestConfigSchema;\n handler?: (\n request: ServerRequest,\n options: ClientRequestOptions,\n ) => Async<ServerResponseBody>;\n}\n\nexport interface ClientScope {\n service?: string;\n hostname?: string;\n}\n\nexport type HttpVirtualClient<T> = {\n [K in keyof T as T[K] extends ActionPrimitive<RequestConfigSchema>\n ? K\n : never]: T[K] extends ActionPrimitive<infer Schema>\n ? VirtualAction<Schema>\n : never;\n} & {\n [K in keyof T as T[K] extends SsePrimitive<SseConfigSchema>\n ? K\n : never]: T[K] extends SsePrimitive<infer Schema>\n ? VirtualSse<Schema>\n : never;\n};\n\nexport interface VirtualAction<T extends RequestConfigSchema>\n extends Pick<ActionPrimitive<T>, \"name\" | \"run\" | \"fetch\"> {\n (\n config?: ClientRequestEntry<T>,\n opts?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<T>>;\n can: () => boolean;\n}\n\nexport interface VirtualSse<T extends SseConfigSchema> {\n (config?: SseRequestEntry<T>): Promise<SseStream<SseEventData<T>>>;\n name: string;\n can: () => boolean;\n}\n","import { $inject, KIND } from \"alepha\";\nimport {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"../providers/LinkProvider.ts\";\n\n/**\n * Create a new client.\n */\nexport const $client = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n return $inject(LinkProvider).client<T>(scope);\n};\n\n$client[KIND] = \"$client\";\n","import { createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { ServiceAccountPrimitive } from \"alepha/security\";\nimport type { ProxyPrimitiveOptions } from \"alepha/server/proxy\";\n\n/**\n * $remote is a primitive that allows you to define remote service access.\n *\n * Use it only when you have 2 or more services that need to communicate with each other.\n *\n * All remote services can be exposed as actions, ... or not.\n *\n * You can add a service account if you want to use a security layer.\n */\nexport const $remote = (options: RemotePrimitiveOptions) => {\n return createPrimitive(RemotePrimitive, options);\n};\n\nexport interface RemotePrimitiveOptions {\n /**\n * The URL of the remote service.\n * You can use a function to generate the URL dynamically.\n * You probably should use $env(env) to get the URL from the environment.\n *\n * @example\n * ```ts\n * import { $remote } from \"alepha/server\";\n * import { $inject, t } from \"alepha\";\n *\n * class App {\n * env = $env(t.object({\n * REMOTE_URL: t.text({default: \"http://localhost:3000\"}),\n * }));\n * remote = $remote({\n * url: this.env.REMOTE_URL,\n * });\n * }\n * ```\n */\n url: string | (() => string);\n\n /**\n * The name of the remote service.\n *\n * @default Member of the class containing the remote service.\n */\n name?: string;\n\n /**\n * If true, all methods of the remote service will be exposed as actions in this context.\n * > Note: Proxy will never use the service account, it just... proxies the request.\n */\n proxy?:\n | boolean\n | Partial<\n ProxyPrimitiveOptions & {\n /**\n * If true, the remote service won't be available internally, only through the proxy.\n */\n noInternal: boolean;\n }\n >;\n\n /**\n * For communication between the server and the remote service with a security layer.\n * This will be used for internal communication and will not be exposed to the client.\n */\n serviceAccount?: ServiceAccountPrimitive;\n}\n\nexport class RemotePrimitive extends Primitive<RemotePrimitiveOptions> {\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n}\n\n$remote[KIND] = RemotePrimitive;\n","import { $module } from \"alepha\";\nimport { apiLinksAtom } from \"./atoms/apiLinksAtom.ts\";\nimport { linkOptionsAtom } from \"./atoms/linkOptionsAtom.ts\";\nimport { $client } from \"./primitives/$client.ts\";\nimport { $remote } from \"./primitives/$remote.ts\";\nimport { LinkProvider } from \"./providers/LinkProvider.ts\";\nimport { BatchCollector } from \"./services/BatchCollector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./atoms/apiLinksAtom.ts\";\nexport * from \"./atoms/linkOptionsAtom.ts\";\nexport * from \"./primitives/$client.ts\";\nexport * from \"./primitives/$remote.ts\";\nexport * from \"./providers/LinkProvider.ts\";\nexport * from \"./schemas/apiLinksResponseSchema.ts\";\nexport * from \"./services/BatchCollector.ts\";\n\n// ---------------------------------------------------------------- -----------------------------------------------------\n\nexport const AlephaServerLinks = $module({\n name: \"alepha.server.links\",\n atoms: [apiLinksAtom, linkOptionsAtom],\n primitives: [$remote, $client],\n services: [LinkProvider, BatchCollector],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/server/links/schemas/apiLinksResponseSchema.ts","../../../src/server/links/atoms/apiLinksAtom.ts","../../../src/server/links/atoms/linkOptionsAtom.ts","../../../src/server/links/services/BatchCollector.ts","../../../src/server/links/providers/LinkProvider.ts","../../../src/server/links/primitives/$client.ts","../../../src/server/links/primitives/$remote.ts","../../../src/server/links/index.browser.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const apiActionSchema = t.object({\n path: t.text({\n description: \"Pathname used to access the action.\",\n }),\n\n method: t.optional(\n t.text({\n description:\n \"HTTP method. Omitted when GET (the default for ~75% of actions).\",\n }),\n ),\n\n contentType: t.optional(\n t.text({\n description:\n \"Content type for the request body. Only present for non-JSON types (e.g. 'multipart/form-data'). When absent, defaults to application/json.\",\n }),\n ),\n\n kind: t.optional(\n t.text({\n description:\n \"Action kind. Used to distinguish special action types (e.g. 'sse' for Server-Sent Events streams).\",\n }),\n ),\n\n service: t.optional(\n t.text({\n description:\n \"Service name associated with the action, used for service discovery and routing.\",\n }),\n ),\n});\n\nexport const apiRegistryResponseSchema = t.object({\n prefix: t.optional(t.text()),\n\n actions: t.record(t.text(), apiActionSchema),\n\n permissions: t.optional(t.array(t.text())),\n});\n\nexport type ApiRegistryResponse = Static<typeof apiRegistryResponseSchema>;\nexport type ApiAction = Static<typeof apiActionSchema>;\n\n/**\n * @deprecated Use `apiRegistryResponseSchema` and `ApiRegistryResponse` instead.\n */\nexport const apiLinksResponseSchema = apiRegistryResponseSchema;\n\n/**\n * @deprecated Use `ApiRegistryResponse` instead.\n */\nexport type ApiLinksResponse = ApiRegistryResponse;\n\n/**\n * @deprecated Use `ApiAction` instead.\n */\nexport type ApiLink = ApiAction;\n","import { $atom, t } from \"alepha\";\nimport { apiRegistryResponseSchema } from \"../schemas/apiLinksResponseSchema.ts\";\n\nexport const apiLinksAtom = $atom({\n name: \"alepha.server.request.apiLinks\",\n schema: t.optional(apiRegistryResponseSchema),\n});\n","import { $atom, t } from \"alepha\";\n\nexport const linkOptionsAtom = $atom({\n name: \"alepha.server.links.options\",\n description: \"Configuration options for the links module.\",\n schema: t.object({\n batch: t.boolean({\n description: \"Enable batch collection for browser-side calls.\",\n default: true,\n }),\n }),\n default: {\n batch: true,\n },\n});\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { HttpClient, HttpError } from \"alepha/server\";\n\n/**\n * Collects browser-side action calls within a microtask and\n * sends them as a single `POST /api/_batch` request.\n *\n * Key behaviors:\n * - Single call in the window → direct HTTP call (no batch overhead)\n * - Multiple calls → coalesced into one batch request\n * - Same action + same params/query/body → deduplicated, result shared\n * - Exceeding MAX_BATCH_SIZE → split into multiple batch calls\n * - Transport failure → all pending promises reject\n */\nexport class BatchCollector {\n protected static readonly MAX_BATCH_SIZE = 20;\n\n protected readonly log = $logger();\n protected readonly httpClient = $inject(HttpClient);\n\n protected pending: PendingBatchEntry[] = [];\n protected scheduled = false;\n\n /**\n * Add an action call to the batch. Returns the result when the batch resolves.\n */\n public add(entry: BatchEntry): Promise<any> {\n return new Promise((resolve, reject) => {\n this.pending.push({ entry, resolve, reject });\n\n if (!this.scheduled) {\n this.scheduled = true;\n setTimeout(() => {\n this.scheduled = false;\n this.flush().catch((err) => this.log.error(err));\n }, 10);\n }\n });\n }\n\n protected async flush(): Promise<void> {\n const batch = this.pending.splice(0);\n\n if (batch.length === 0) return;\n\n // Single request — skip batching, call directly via follow\n if (batch.length === 1) {\n const item = batch[0];\n try {\n const result = await item.entry.directCall();\n item.resolve(result);\n } catch (error) {\n item.reject(error);\n }\n return;\n }\n\n // Deduplicate: same action + same params → share result\n const { unique, indexMap } = this.dedupe(batch);\n\n // Split into chunks of MAX_BATCH_SIZE\n const chunks = this.chunk(unique, BatchCollector.MAX_BATCH_SIZE);\n\n try {\n const allResults = (\n await Promise.all(\n chunks.map((chunk) => {\n const actions = [...new Set(chunk.map((b) => b.entry.action))].join(\n \",\",\n );\n\n return this.httpClient\n .fetch(`/api/_batch?actions=${actions}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(\n chunk.map((b) => ({\n action: b.entry.action,\n params: b.entry.params,\n query: b.entry.query,\n body: b.entry.body,\n })),\n ),\n })\n .then((res) => res.data as BatchResponse[]);\n }),\n )\n ).flat();\n\n // Distribute results back (including deduped slots)\n for (let i = 0; i < batch.length; i++) {\n const result = allResults[indexMap[i]];\n if (result.status >= 400) {\n batch[i].reject(\n new HttpError({\n message:\n result.error ?? `${result.action} failed (${result.status})`,\n status: result.status,\n }),\n );\n } else {\n batch[i].resolve(result.data);\n }\n }\n } catch (error) {\n // Transport-level failure — reject all pending promises\n for (const item of batch) {\n item.reject(error);\n }\n }\n }\n\n protected dedupe(batch: PendingBatchEntry[]): {\n unique: PendingBatchEntry[];\n indexMap: number[];\n } {\n const seen = new Map<string, number>();\n const unique: PendingBatchEntry[] = [];\n const indexMap: number[] = [];\n\n for (const item of batch) {\n const key = `${item.entry.action}:${JSON.stringify({\n params: item.entry.params,\n query: item.entry.query,\n body: item.entry.body,\n })}`;\n\n const existing = seen.get(key);\n if (existing !== undefined) {\n indexMap.push(existing);\n } else {\n const idx = unique.length;\n seen.set(key, idx);\n unique.push(item);\n indexMap.push(idx);\n }\n }\n\n return { unique, indexMap };\n }\n\n protected chunk<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n }\n}\n\n// ---\n\nexport interface BatchEntry {\n action: string;\n params?: Record<string, any>;\n query?: Record<string, any>;\n body?: Record<string, any>;\n directCall: () => Promise<any>;\n}\n\ninterface PendingBatchEntry {\n entry: BatchEntry;\n resolve: (value: any) => void;\n reject: (reason: any) => void;\n}\n\ninterface BatchResponse {\n action: string;\n status: number;\n data?: any;\n error?: string;\n}\n","import { $inject, $state, Alepha, AlephaError, type Async, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { SecureOptions } from \"alepha/security\";\nimport {\n type ActionPrimitive,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type ClientRequestResponse,\n type FetchResponse,\n HttpClient,\n type RequestConfigSchema,\n ServerReply,\n type ServerRequest,\n type ServerRequestConfigEntry,\n type ServerResponseBody,\n type SseConfigSchema,\n type SseEventData,\n type SsePrimitive,\n type SseRequestEntry,\n type SseStream,\n UnauthorizedError,\n} from \"alepha/server\";\nimport { linkOptionsAtom } from \"../atoms/linkOptionsAtom.ts\";\nimport {\n type ApiRegistryResponse,\n apiRegistryResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\nimport { BatchCollector } from \"../services/BatchCollector.ts\";\n\n/**\n * Browser, SSR friendly, service to handle links.\n */\nexport class LinkProvider {\n static path = {\n apiLinks: \"/api/_links\",\n };\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n\n // Server-side: all registered links (local + remote), keyed by name\n protected serverLinkMap = new Map<string, HttpClientLink>();\n\n // Browser/SSR: parsed from the registry response\n protected actionMap = new Map<string, HttpClientLink>();\n protected permissions = new Set<string>();\n protected lastLoadedRegistry: ApiRegistryResponse | null = null;\n\n // Browser-only: batch collector for coalescing multiple calls\n protected batchCollector?: BatchCollector;\n\n protected readonly options = $state(linkOptionsAtom);\n\n /**\n * Get applicative links registered on the server.\n * This does not include lazy-loaded remote links.\n */\n public getServerLinks(): HttpClientLink[] {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Getting server links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return [];\n }\n\n return [...this.serverLinkMap.values()];\n }\n\n /**\n * Register a new link for the application.\n */\n public registerLink(link: HttpClientLink): void {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Registering links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return;\n }\n\n if (!link.handler && !link.host) {\n throw new AlephaError(\n \"Can't create link - 'handler' or 'host' is required\",\n );\n }\n\n // Detect duplicate local actions (programming error)\n const existing = this.serverLinkMap.get(link.name);\n if (existing?.handler && link.handler) {\n throw new AlephaError(\n `Duplicate action name \"${link.name}\". Each action must have a unique name.`,\n );\n }\n\n this.serverLinkMap.set(link.name, link);\n }\n\n /**\n * Load the registry response into internal stores (actionMap, permissions, definitions).\n * Called when storing from atom/fetch/SSR.\n */\n protected loadRegistry(registry: ApiRegistryResponse): void {\n this.lastLoadedRegistry = registry;\n this.permissions.clear();\n this.actionMap.clear();\n\n for (const [name, action] of Object.entries(registry.actions)) {\n this.actionMap.set(name, {\n name,\n path: action.path,\n kind: action.kind,\n method: action.method,\n contentType: action.contentType,\n service: action.service,\n });\n }\n\n if (registry.permissions) {\n for (const p of registry.permissions) {\n this.permissions.add(p);\n }\n }\n }\n\n public get links(): HttpClientLink[] {\n const registry = this.alepha.store.get(\"alepha.server.request.apiLinks\");\n\n if (registry) {\n if (this.alepha.isBrowser()) {\n // Browser side: use the parsed action map\n // Reload when registry changes (e.g. after login provides new authenticated links)\n if (this.actionMap.size === 0 || registry !== this.lastLoadedRegistry) {\n this.loadRegistry(registry);\n }\n return [...this.actionMap.values()];\n }\n\n // SSR side: map registry actions back to full server links\n const links: HttpClientLink[] = [];\n for (const name of Object.keys(registry.actions)) {\n const originalLink = this.serverLinkMap.get(name);\n if (originalLink) {\n links.push(originalLink);\n }\n }\n return links;\n }\n\n return [...this.serverLinkMap.values()];\n }\n\n /**\n * Force browser to refresh links from the server.\n */\n public async fetchLinks(): Promise<HttpClientLink[]> {\n const { data } = await this.httpClient.fetch(\n `${LinkProvider.path.apiLinks}`,\n {\n method: \"GET\",\n schema: {\n response: apiRegistryResponseSchema,\n },\n },\n );\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data);\n this.loadRegistry(data);\n\n return [...this.actionMap.values()];\n }\n\n /**\n * Create a virtual client that can be used to call actions.\n *\n * Use js Proxy under the hood.\n */\n public client<T extends object>(\n scope: ClientScope = {},\n ): HttpVirtualClient<T> {\n return new Proxy<HttpVirtualClient<T>>({} as HttpVirtualClient<T>, {\n get: (_, prop) => {\n if (typeof prop !== \"string\") {\n return;\n }\n\n return this.createVirtualAction<RequestConfigSchema>(prop, scope);\n },\n });\n }\n\n /**\n * Check if a link with the given name exists or a permission matches.\n *\n * Action names never contain colons. Permission names always do.\n * - `can(\"getUsers\")` → O(1) map lookup\n * - `can(\"admin:*\")` → wildcard match against permissions set\n * - `can(\"admin:user:read\")` → O(1) set lookup\n */\n public can(name: string): boolean {\n // Action check — O(1) map lookup\n if (this.actionMap.size > 0) {\n if (this.actionMap.has(name)) return true;\n } else {\n // Fallback for server-side where actionMap may not be populated\n if (this.serverLinkMap.has(name)) return true;\n // Also check links getter (for SSR with atom)\n if (this.links.some((link) => link.name === name)) return true;\n }\n\n // Permission check — wildcard matching\n if (name.includes(\":\")) {\n if (name.endsWith(\"*\")) {\n const prefix = name.slice(0, -1);\n for (const p of this.permissions) {\n if (p.startsWith(prefix)) return true;\n }\n return false;\n }\n return this.permissions.has(name);\n }\n\n return false;\n }\n\n /**\n * Resolve a link by its name and call it.\n * - If link is local, it will call the local handler.\n * - If link is remote, it will make a fetch request to the remote server.\n */\n public async follow(\n name: string,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions & ClientScope = {},\n ): Promise<any> {\n this.log.trace(\"Following link\", { name, config, options });\n const link = await this.getLinkByName(name, options);\n\n // if a handler is defined, use it (ssr)\n if (link.handler && !options.request) {\n this.log.trace(\"Local link found\", { name });\n return link.handler(\n {\n method: link.method,\n url: new URL(`http://localhost${link.path}`),\n query: config.query ?? {},\n body: config.body ?? {},\n params: config.params ?? {},\n headers: config.headers ?? {},\n metadata: {},\n reply: new ServerReply(),\n } as Partial<ServerRequest> as ServerRequest,\n options,\n );\n }\n\n this.log.trace(\"Remote link found\", {\n name,\n host: link.host,\n service: link.service,\n });\n\n // Browser-only: use batch collector for calls without explicit host\n if (this.options.batch && this.alepha.isBrowser() && !link.host) {\n this.batchCollector ??= this.alepha.inject(BatchCollector);\n return this.batchCollector.add({\n action: name,\n params: config.params as any,\n query: config.query as any,\n body: config.body as any,\n directCall: () =>\n this.followRemote(link, config, options).then((r) => r.data),\n });\n }\n\n return this.followRemote(link, config, options).then(\n (response) => response.data,\n );\n }\n\n protected createVirtualAction<T extends RequestConfigSchema>(\n name: string,\n scope: ClientScope = {},\n ): VirtualAction<T> {\n const $: VirtualAction<T> = async (\n config: any = {},\n options: ClientRequestOptions = {},\n ) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n Object.defineProperty($, \"name\", {\n value: name,\n writable: false,\n });\n\n $.run = async (config: any = {}, options: ClientRequestOptions = {}) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n $.fetch = async (config: any = {}, options: ClientRequestOptions = {}) => {\n const link = await this.getLinkByName(name, scope);\n return this.followRemote(link, config, options);\n };\n\n $.can = () => {\n return this.can(name);\n };\n\n return $;\n }\n\n protected async followRemote(\n link: HttpClientLink,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions = {},\n ): Promise<FetchResponse> {\n options.request ??= {};\n options.request.headers = new Headers(options.request.headers);\n\n const als = this.alepha.store.get(\"alepha.http.request\");\n if (als?.headers.authorization) {\n options.request.headers.set(\"authorization\", als.headers.authorization);\n }\n\n const context = this.alepha.context.get(\"context\");\n if (typeof context === \"string\") {\n options.request.headers.set(\"x-request-id\", context);\n }\n\n const action = {\n ...link,\n // schema is not used in the client,\n // we assume that TypeScript will check\n schema: {\n body: t.any(),\n response: t.any(),\n },\n };\n\n // prefix with service when host is not defined (e.g. browser)\n if (!link.host && link.service) {\n action.path = `/${link.service}${action.path}`;\n }\n\n action.path = `${action.prefix ?? \"/api\"}${action.path}`;\n action.prefix = undefined; // prefix is not used in the client\n\n // else, make a request\n return this.httpClient.fetchAction({\n host: link.host,\n config,\n options,\n action: action as any, // schema.body TAny is not accepted\n });\n }\n\n protected async getLinkByName(\n name: string,\n options: ClientScope = {},\n ): Promise<HttpClientLink> {\n if (\n this.alepha.isBrowser() &&\n !this.alepha.store.get(\"alepha.server.request.apiLinks\")\n ) {\n await this.fetchLinks();\n }\n\n const link = this.links.find(\n (a) =>\n a.name === name && (!options.service || options.service === a.service),\n );\n\n if (!link) {\n const error = new UnauthorizedError(`Action ${name} not found.`);\n // mimic http error handling\n await this.alepha.events.emit(\"client:onError\", {\n route: link,\n error,\n });\n throw error;\n }\n\n if (options.hostname) {\n return {\n ...link,\n host: options.hostname,\n };\n }\n\n return link;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface HttpClientLink {\n name: string;\n path: string;\n method?: string;\n kind?: string;\n contentType?: string;\n service?: string;\n secured?: boolean | SecureOptions;\n prefix?: string;\n group?: string;\n // -- server only --\n host?: string;\n schema?: RequestConfigSchema;\n handler?: (\n request: ServerRequest,\n options: ClientRequestOptions,\n ) => Async<ServerResponseBody>;\n}\n\nexport interface ClientScope {\n service?: string;\n hostname?: string;\n}\n\nexport type HttpVirtualClient<T> = {\n [K in keyof T as T[K] extends ActionPrimitive<RequestConfigSchema>\n ? K\n : never]: T[K] extends ActionPrimitive<infer Schema>\n ? VirtualAction<Schema>\n : never;\n} & {\n [K in keyof T as T[K] extends SsePrimitive<SseConfigSchema>\n ? K\n : never]: T[K] extends SsePrimitive<infer Schema>\n ? VirtualSse<Schema>\n : never;\n};\n\nexport interface VirtualAction<T extends RequestConfigSchema>\n extends Pick<ActionPrimitive<T>, \"name\" | \"run\" | \"fetch\"> {\n (\n config?: ClientRequestEntry<T>,\n opts?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<T>>;\n can: () => boolean;\n}\n\nexport interface VirtualSse<T extends SseConfigSchema> {\n (config?: SseRequestEntry<T>): Promise<SseStream<SseEventData<T>>>;\n name: string;\n can: () => boolean;\n}\n","import { $inject, KIND } from \"alepha\";\nimport {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"../providers/LinkProvider.ts\";\n\n/**\n * Create a new client.\n */\nexport const $client = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n return $inject(LinkProvider).client<T>(scope);\n};\n\n$client[KIND] = \"$client\";\n","import { createPrimitive, KIND, Primitive } from \"alepha\";\nimport type { ServiceAccountPrimitive } from \"alepha/security\";\nimport type { ProxyPrimitiveOptions } from \"alepha/server/proxy\";\n\n/**\n * $remote is a primitive that allows you to define remote service access.\n *\n * Use it only when you have 2 or more services that need to communicate with each other.\n *\n * All remote services can be exposed as actions, ... or not.\n *\n * You can add a service account if you want to use a security layer.\n */\nexport const $remote = (options: RemotePrimitiveOptions) => {\n return createPrimitive(RemotePrimitive, options);\n};\n\nexport interface RemotePrimitiveOptions {\n /**\n * The URL of the remote service.\n * You can use a function to generate the URL dynamically.\n * You probably should use $env(env) to get the URL from the environment.\n *\n * @example\n * ```ts\n * import { $remote } from \"alepha/server\";\n * import { $inject, t } from \"alepha\";\n *\n * class App {\n * env = $env(t.object({\n * REMOTE_URL: t.text({default: \"http://localhost:3000\"}),\n * }));\n * remote = $remote({\n * url: this.env.REMOTE_URL,\n * });\n * }\n * ```\n */\n url: string | (() => string);\n\n /**\n * The name of the remote service.\n *\n * @default Member of the class containing the remote service.\n */\n name?: string;\n\n /**\n * If true, all methods of the remote service will be exposed as actions in this context.\n * > Note: Proxy will never use the service account, it just... proxies the request.\n */\n proxy?:\n | boolean\n | Partial<\n ProxyPrimitiveOptions & {\n /**\n * If true, the remote service won't be available internally, only through the proxy.\n */\n noInternal: boolean;\n }\n >;\n\n /**\n * For communication between the server and the remote service with a security layer.\n * This will be used for internal communication and will not be exposed to the client.\n */\n serviceAccount?: ServiceAccountPrimitive;\n}\n\nexport class RemotePrimitive extends Primitive<RemotePrimitiveOptions> {\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n}\n\n$remote[KIND] = RemotePrimitive;\n","import { $module } from \"alepha\";\nimport { apiLinksAtom } from \"./atoms/apiLinksAtom.ts\";\nimport { linkOptionsAtom } from \"./atoms/linkOptionsAtom.ts\";\nimport { $client } from \"./primitives/$client.ts\";\nimport { $remote } from \"./primitives/$remote.ts\";\nimport { LinkProvider } from \"./providers/LinkProvider.ts\";\nimport { BatchCollector } from \"./services/BatchCollector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./atoms/apiLinksAtom.ts\";\nexport * from \"./atoms/linkOptionsAtom.ts\";\nexport * from \"./primitives/$client.ts\";\nexport * from \"./primitives/$remote.ts\";\nexport * from \"./providers/LinkProvider.ts\";\nexport * from \"./schemas/apiLinksResponseSchema.ts\";\nexport * from \"./services/BatchCollector.ts\";\n\n// ---------------------------------------------------------------- -----------------------------------------------------\n\nexport const AlephaServerLinks = $module({\n name: \"alepha.server.links\",\n atoms: [apiLinksAtom, linkOptionsAtom],\n primitives: [$remote, $client],\n services: [LinkProvider, BatchCollector],\n});\n"],"mappings":"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"}