alepha 0.18.2 → 0.18.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 (397) hide show
  1. package/assets/devtools-ui/200.html +2 -2
  2. package/assets/devtools-ui/200.html.br +0 -0
  3. package/assets/devtools-ui/404.html +2 -2
  4. package/assets/devtools-ui/404.html.br +0 -0
  5. package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
  6. package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
  7. package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
  8. package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
  9. package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
  10. package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
  11. package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
  12. package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
  13. package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
  14. package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
  15. package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
  16. package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
  17. package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
  18. package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
  19. package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
  20. package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
  21. package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
  22. package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
  23. package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
  24. package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
  25. package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
  26. package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
  27. package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
  28. package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
  29. package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
  30. package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
  31. package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
  32. package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
  33. package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
  34. package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
  35. package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
  36. package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
  37. package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
  38. package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
  39. package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
  40. package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
  41. package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
  42. package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
  43. package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
  44. package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
  45. package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
  46. package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
  47. package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
  48. package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
  49. package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
  50. package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
  51. package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
  52. package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
  53. package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
  54. package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
  55. package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
  56. package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
  57. package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
  58. package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
  59. package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
  60. package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
  61. package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
  62. package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
  63. package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
  64. package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
  65. package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
  66. package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
  67. package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
  68. package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
  69. package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
  70. package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
  71. package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
  72. package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
  73. package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
  74. package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
  75. package/assets/devtools-ui/index.html +2 -2
  76. package/assets/devtools-ui/index.html.br +0 -0
  77. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  78. package/assets/swagger-ui/swagger-ui.css +1 -1
  79. package/dist/api/audits/index.d.ts +61 -5
  80. package/dist/api/audits/index.d.ts.map +1 -1
  81. package/dist/api/files/index.d.ts +61 -5
  82. package/dist/api/files/index.d.ts.map +1 -1
  83. package/dist/api/jobs/index.d.ts +61 -5
  84. package/dist/api/jobs/index.d.ts.map +1 -1
  85. package/dist/api/jobs/index.js +4 -2
  86. package/dist/api/jobs/index.js.map +1 -1
  87. package/dist/api/keys/index.d.ts +5 -5
  88. package/dist/api/notifications/index.browser.js +44 -1
  89. package/dist/api/notifications/index.browser.js.map +1 -1
  90. package/dist/api/notifications/index.d.ts +187 -2
  91. package/dist/api/notifications/index.d.ts.map +1 -1
  92. package/dist/api/notifications/index.js +143 -8
  93. package/dist/api/notifications/index.js.map +1 -1
  94. package/dist/api/parameters/index.d.ts +61 -5
  95. package/dist/api/parameters/index.d.ts.map +1 -1
  96. package/dist/api/users/index.d.ts +330 -93
  97. package/dist/api/users/index.d.ts.map +1 -1
  98. package/dist/api/users/index.js +27 -36
  99. package/dist/api/users/index.js.map +1 -1
  100. package/dist/cli/config/index.d.ts +46 -0
  101. package/dist/cli/config/index.d.ts.map +1 -0
  102. package/dist/cli/config/index.js +20 -0
  103. package/dist/cli/config/index.js.map +1 -0
  104. package/dist/cli/core/index.d.ts +69 -66
  105. package/dist/cli/core/index.d.ts.map +1 -1
  106. package/dist/cli/core/index.js +329 -196
  107. package/dist/cli/core/index.js.map +1 -1
  108. package/dist/cli/platform/index.d.ts +302 -63
  109. package/dist/cli/platform/index.d.ts.map +1 -1
  110. package/dist/cli/platform/index.js +455 -25
  111. package/dist/cli/platform/index.js.map +1 -1
  112. package/dist/core/index.browser.js +125 -87
  113. package/dist/core/index.browser.js.map +1 -1
  114. package/dist/core/index.d.ts +62 -53
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/index.js +125 -87
  117. package/dist/core/index.js.map +1 -1
  118. package/dist/core/index.native.js +125 -87
  119. package/dist/core/index.native.js.map +1 -1
  120. package/dist/core/index.workerd.js +125 -87
  121. package/dist/core/index.workerd.js.map +1 -1
  122. package/dist/crypto/index.d.ts +18 -1
  123. package/dist/crypto/index.d.ts.map +1 -1
  124. package/dist/crypto/index.js +29 -3
  125. package/dist/crypto/index.js.map +1 -1
  126. package/dist/devtools/index.js +3 -12
  127. package/dist/devtools/index.js.map +1 -1
  128. package/dist/logger/index.d.ts +10 -1
  129. package/dist/logger/index.d.ts.map +1 -1
  130. package/dist/logger/index.js +19 -9
  131. package/dist/logger/index.js.map +1 -1
  132. package/dist/orm/core/index.browser.js +57 -1
  133. package/dist/orm/core/index.browser.js.map +1 -1
  134. package/dist/orm/core/index.bun.js +378 -19
  135. package/dist/orm/core/index.bun.js.map +1 -1
  136. package/dist/orm/core/index.d.ts +328 -9
  137. package/dist/orm/core/index.d.ts.map +1 -1
  138. package/dist/orm/core/index.js +384 -21
  139. package/dist/orm/core/index.js.map +1 -1
  140. package/dist/orm/postgres/index.bun.js +49 -17
  141. package/dist/orm/postgres/index.bun.js.map +1 -1
  142. package/dist/orm/postgres/index.d.ts +47 -21
  143. package/dist/orm/postgres/index.d.ts.map +1 -1
  144. package/dist/orm/postgres/index.js +52 -17
  145. package/dist/orm/postgres/index.js.map +1 -1
  146. package/dist/react/core/index.d.ts +1 -1
  147. package/dist/react/core/index.d.ts.map +1 -1
  148. package/dist/react/core/index.js +6 -1
  149. package/dist/react/core/index.js.map +1 -1
  150. package/dist/react/form/index.d.ts +28 -18
  151. package/dist/react/form/index.d.ts.map +1 -1
  152. package/dist/react/form/index.js +92 -56
  153. package/dist/react/form/index.js.map +1 -1
  154. package/dist/react/router/index.browser.js +448 -116
  155. package/dist/react/router/index.browser.js.map +1 -1
  156. package/dist/react/router/index.d.ts +102 -40
  157. package/dist/react/router/index.d.ts.map +1 -1
  158. package/dist/react/router/index.js +453 -92
  159. package/dist/react/router/index.js.map +1 -1
  160. package/dist/security/index.d.ts +3 -11
  161. package/dist/security/index.d.ts.map +1 -1
  162. package/dist/security/index.js +6 -11
  163. package/dist/security/index.js.map +1 -1
  164. package/dist/server/auth/index.d.ts +22 -24
  165. package/dist/server/auth/index.d.ts.map +1 -1
  166. package/dist/server/auth/index.js +102 -82
  167. package/dist/server/auth/index.js.map +1 -1
  168. package/dist/server/cookies/index.d.ts +7 -4
  169. package/dist/server/cookies/index.d.ts.map +1 -1
  170. package/dist/server/cookies/index.js +13 -12
  171. package/dist/server/cookies/index.js.map +1 -1
  172. package/dist/server/core/index.d.ts +288 -4
  173. package/dist/server/core/index.d.ts.map +1 -1
  174. package/dist/server/core/index.js +375 -2
  175. package/dist/server/core/index.js.map +1 -1
  176. package/dist/server/links/index.browser.js +10 -71
  177. package/dist/server/links/index.browser.js.map +1 -1
  178. package/dist/server/links/index.d.ts +32 -49
  179. package/dist/server/links/index.d.ts.map +1 -1
  180. package/dist/server/links/index.js +73 -100
  181. package/dist/server/links/index.js.map +1 -1
  182. package/dist/system/index.browser.js +221 -2
  183. package/dist/system/index.browser.js.map +1 -1
  184. package/dist/system/index.d.ts +63 -1
  185. package/dist/system/index.d.ts.map +1 -1
  186. package/dist/system/index.js +221 -1
  187. package/dist/system/index.js.map +1 -1
  188. package/dist/system/index.workerd.js +224 -4
  189. package/dist/system/index.workerd.js.map +1 -1
  190. package/package.json +10 -5
  191. package/src/api/jobs/providers/JobProvider.ts +6 -3
  192. package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
  193. package/src/api/notifications/index.browser.ts +3 -0
  194. package/src/api/notifications/index.ts +14 -2
  195. package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
  196. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
  197. package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
  198. package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
  199. package/src/api/notifications/services/NotificationSenderService.ts +15 -2
  200. package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
  201. package/src/api/users/buckets/UserBuckets.ts +1 -1
  202. package/src/api/users/jobs/UserJobs.ts +1 -1
  203. package/src/api/users/primitives/$realm.ts +8 -49
  204. package/src/api/users/providers/RealmProvider.ts +2 -3
  205. package/src/api/users/services/RegistrationService.spec.ts +7 -7
  206. package/src/api/users/services/RegistrationService.ts +3 -3
  207. package/src/api/users/services/SessionService.spec.ts +4 -4
  208. package/src/api/users/services/SessionService.ts +3 -3
  209. package/src/cli/{core → config}/defineConfig.ts +14 -20
  210. package/src/cli/config/index.ts +1 -0
  211. package/src/cli/core/commands/db.ts +65 -1
  212. package/src/cli/core/commands/dev.ts +1 -0
  213. package/src/cli/core/commands/init.ts +2 -192
  214. package/src/cli/core/index.ts +34 -11
  215. package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
  216. package/src/cli/core/services/PackageManagerUtils.ts +43 -21
  217. package/src/cli/core/services/ProjectScaffolder.ts +214 -2
  218. package/src/cli/core/services/ViteUtils.ts +57 -0
  219. package/src/cli/core/tasks/BuildClientTask.ts +7 -2
  220. package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
  221. package/src/cli/core/tasks/BuildServerTask.ts +2 -0
  222. package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
  223. package/src/cli/core/templates/alephaConfigTs.ts +1 -1
  224. package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
  225. package/src/cli/core/templates/tsconfigJson.ts +6 -1
  226. package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
  227. package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
  228. package/src/cli/platform/atoms/platformOptions.ts +21 -0
  229. package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
  230. package/src/cli/platform/commands/SecretsCommand.ts +283 -0
  231. package/src/cli/platform/commands/platform.ts +12 -0
  232. package/src/cli/platform/index.ts +14 -28
  233. package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
  234. package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
  235. package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
  236. package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
  237. package/src/cli/platform/schemas/cloudflare.ts +2 -0
  238. package/src/cli/platform/services/CloudflareApi.ts +5 -2
  239. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
  240. package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
  241. package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
  242. package/src/cli/platform/services/SecretFilterService.ts +54 -0
  243. package/src/core/Alepha.ts +94 -25
  244. package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
  245. package/src/core/primitives/$memoize.ts +38 -26
  246. package/src/core/providers/AlsProvider.ts +2 -0
  247. package/src/core/providers/EventManager.ts +4 -0
  248. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
  249. package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
  250. package/src/core/providers/SchemaValidator.spec.ts +36 -0
  251. package/src/core/providers/SchemaValidator.ts +9 -0
  252. package/src/crypto/index.ts +6 -1
  253. package/src/crypto/providers/SecretProvider.ts +36 -0
  254. package/src/devtools/providers/DevToolsProvider.ts +3 -12
  255. package/src/logger/index.ts +33 -6
  256. package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
  257. package/src/orm/__tests__/orm-next-tests.ts +492 -0
  258. package/src/orm/__tests__/orm-next.spec.ts +140 -0
  259. package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
  260. package/src/orm/core/index.bun.ts +3 -6
  261. package/src/orm/core/index.shared-server.ts +2 -0
  262. package/src/orm/core/index.shared.ts +2 -0
  263. package/src/orm/core/index.ts +5 -7
  264. package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
  265. package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
  266. package/src/orm/core/primitives/$entity.ts +8 -0
  267. package/src/orm/core/primitives/$repository.ts +6 -3
  268. package/src/orm/core/primitives/$view.ts +88 -0
  269. package/src/orm/core/providers/DbCacheProvider.ts +66 -0
  270. package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
  271. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
  272. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
  273. package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
  274. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
  275. package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
  276. package/src/orm/core/schemas/insertSchema.ts +13 -3
  277. package/src/orm/core/schemas/updateSchema.ts +14 -3
  278. package/src/orm/core/services/ModelBuilder.ts +26 -14
  279. package/src/orm/core/services/QueryManager.ts +13 -0
  280. package/src/orm/core/services/Repository.ts +307 -5
  281. package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
  282. package/src/orm/postgres/index.bun.ts +4 -7
  283. package/src/orm/postgres/index.ts +4 -7
  284. package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
  285. package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
  286. package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
  287. package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
  288. package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
  289. package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
  290. package/src/react/core/components/ErrorBoundary.tsx +5 -2
  291. package/src/react/form/hooks/useFieldValue.ts +34 -0
  292. package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
  293. package/src/react/form/hooks/useForm.ts +14 -2
  294. package/src/react/form/hooks/useFormState.ts +10 -10
  295. package/src/react/form/hooks/useFormValues.ts +29 -0
  296. package/src/react/form/index.ts +3 -1
  297. package/src/react/form/services/FormModel.ts +53 -122
  298. package/src/react/router/components/ErrorViewer.tsx +333 -34
  299. package/src/react/router/components/NestedView.tsx +10 -3
  300. package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
  301. package/src/react/router/primitives/$page.spec.tsx +20 -0
  302. package/src/react/router/primitives/$page.ts +24 -0
  303. package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
  304. package/src/react/router/providers/ReactPageProvider.ts +156 -73
  305. package/src/react/router/providers/ReactServerProvider.ts +40 -2
  306. package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
  307. package/src/security/providers/SecurityProvider.ts +5 -27
  308. package/src/server/auth/primitives/$auth.ts +52 -19
  309. package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
  310. package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
  311. package/src/server/core/index.ts +3 -1
  312. package/src/server/core/primitives/$sse.spec.ts +315 -0
  313. package/src/server/core/primitives/$sse.ts +715 -0
  314. package/src/server/links/index.browser.ts +1 -3
  315. package/src/server/links/index.ts +0 -3
  316. package/src/server/links/providers/LinkProvider.spec.ts +12 -21
  317. package/src/server/links/providers/LinkProvider.ts +20 -52
  318. package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
  319. package/src/server/links/providers/ServerLinksProvider.ts +113 -73
  320. package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
  321. package/src/server/links/services/BatchCollector.ts +5 -3
  322. package/src/system/index.browser.ts +1 -0
  323. package/src/system/index.ts +3 -0
  324. package/src/system/index.workerd.ts +39 -1
  325. package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
  326. package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
  327. package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
  328. package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
  329. package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
  330. package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
  331. package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
  332. package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
  333. package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
  334. package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
  335. package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
  336. package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
  337. package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
  338. package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
  339. package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
  340. package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
  341. package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
  342. package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
  343. package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
  344. package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
  345. package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
  346. package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
  347. package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
  348. package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
  349. package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
  350. package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
  351. package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
  352. package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
  353. package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
  354. package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
  355. package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
  356. package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
  357. package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
  358. package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
  359. package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
  360. package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
  361. package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
  362. package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
  363. package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
  364. package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
  365. package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
  366. package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
  367. package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
  368. package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
  369. package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
  370. package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
  371. package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
  372. package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
  373. package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
  374. package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
  375. package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
  376. package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
  377. package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
  378. package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
  379. package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
  380. package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
  381. package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
  382. package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
  383. package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
  384. package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
  385. package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
  386. package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
  387. package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
  388. package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
  389. package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
  390. package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
  391. package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
  392. package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
  393. package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
  394. package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
  395. package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
  396. package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
  397. package/src/server/links/services/DefinitionsPool.ts +0 -43
@@ -0,0 +1,715 @@
1
+ import {
2
+ $inject,
3
+ $use,
4
+ AlephaError,
5
+ type Async,
6
+ createPrimitive,
7
+ KIND,
8
+ PipelinePrimitive,
9
+ type PipelinePrimitiveOptions,
10
+ type Static,
11
+ type TObject,
12
+ type TSchema,
13
+ } from "alepha";
14
+ import { $logger } from "alepha/logger";
15
+ import type { RouteMethod } from "../constants/routeMethods.ts";
16
+ import { ServerReply } from "../helpers/ServerReply.ts";
17
+ import type {
18
+ RequestConfigSchema,
19
+ ServerRequest,
20
+ } from "../interfaces/ServerRequest.ts";
21
+ import { ServerProvider } from "../providers/ServerProvider.ts";
22
+ import { ServerRouterProvider } from "../providers/ServerRouterProvider.ts";
23
+ import { serverApiOptions } from "./$action.ts";
24
+
25
+ // ----------------------------------------------------------------------------------------------------------
26
+
27
+ /**
28
+ * Schema configuration for an SSE endpoint.
29
+ */
30
+ export interface SseConfigSchema {
31
+ /**
32
+ * Request body schema.
33
+ */
34
+ body?: TObject;
35
+
36
+ /**
37
+ * Path parameters schema.
38
+ */
39
+ params?: TObject;
40
+
41
+ /**
42
+ * Query parameters schema.
43
+ */
44
+ query?: TObject;
45
+
46
+ /**
47
+ * Request headers schema.
48
+ */
49
+ headers?: TObject;
50
+
51
+ /**
52
+ * Schema for the data payload of each SSE event.
53
+ */
54
+ data?: TSchema;
55
+ }
56
+
57
+ // ----------------------------------------------------------------------------------------------------------
58
+
59
+ /**
60
+ * Context object passed to the SSE handler function.
61
+ */
62
+ export interface SseHandlerContext<TConfig extends SseConfigSchema> {
63
+ /**
64
+ * Parsed request body.
65
+ */
66
+ body: TConfig["body"] extends TObject ? Static<TConfig["body"]> : any;
67
+
68
+ /**
69
+ * Parsed path parameters.
70
+ */
71
+ params: TConfig["params"] extends TObject
72
+ ? Static<TConfig["params"]>
73
+ : Record<string, string>;
74
+
75
+ /**
76
+ * Parsed query parameters.
77
+ */
78
+ query: TConfig["query"] extends TObject
79
+ ? Partial<Static<TConfig["query"]>>
80
+ : Record<string, any>;
81
+
82
+ /**
83
+ * Parsed request headers.
84
+ */
85
+ headers: TConfig["headers"] extends TObject
86
+ ? Static<TConfig["headers"]>
87
+ : Record<string, string>;
88
+
89
+ /**
90
+ * The underlying server request object.
91
+ */
92
+ request: ServerRequest;
93
+
94
+ /**
95
+ * Emit an SSE event to the client.
96
+ */
97
+ emit: (
98
+ data: TConfig["data"] extends TSchema ? Static<TConfig["data"]> : any,
99
+ ) => void;
100
+
101
+ /**
102
+ * Close the SSE stream.
103
+ */
104
+ close: () => void;
105
+ }
106
+
107
+ /**
108
+ * Handler function type for SSE endpoints.
109
+ */
110
+ export type SseHandler<TConfig extends SseConfigSchema = SseConfigSchema> = (
111
+ context: SseHandlerContext<TConfig>,
112
+ ) => Async<void>;
113
+
114
+ // ----------------------------------------------------------------------------------------------------------
115
+
116
+ /**
117
+ * Options for the $sse primitive.
118
+ */
119
+ export interface SsePrimitiveOptions<TConfig extends SseConfigSchema>
120
+ extends PipelinePrimitiveOptions {
121
+ /**
122
+ * Name of the SSE endpoint.
123
+ */
124
+ name?: string;
125
+
126
+ /**
127
+ * Group SSE endpoints together.
128
+ */
129
+ group?: string;
130
+
131
+ /**
132
+ * Pathname of the route. If not provided, property key is used.
133
+ */
134
+ path?: string;
135
+
136
+ /**
137
+ * The config schema for the SSE endpoint.
138
+ */
139
+ schema?: TConfig;
140
+
141
+ /**
142
+ * A short description of the endpoint. Used for documentation purposes.
143
+ */
144
+ description?: string;
145
+
146
+ /**
147
+ * Disable the SSE endpoint.
148
+ */
149
+ disabled?: boolean;
150
+
151
+ /**
152
+ * Main SSE handler. Receives context with emit/close functions.
153
+ */
154
+ handler: SseHandler<TConfig>;
155
+ }
156
+
157
+ // ----------------------------------------------------------------------------------------------------------
158
+
159
+ /**
160
+ * Async iterable stream of SSE events.
161
+ *
162
+ * Supports push-based event delivery via `push()`, error propagation
163
+ * via `fail()`, and clean termination via `end()`.
164
+ */
165
+ export class SseStream<T> implements AsyncIterable<T> {
166
+ protected queue: T[] = [];
167
+ protected error: Error | null = null;
168
+ protected done = false;
169
+ protected resolve: (() => void) | null = null;
170
+ protected listeners: Array<(data: T) => void> = [];
171
+
172
+ /**
173
+ * Push a new event into the stream.
174
+ */
175
+ public push(data: T): void {
176
+ if (this.done) return;
177
+ this.queue.push(data);
178
+ for (const listener of this.listeners) {
179
+ listener(data);
180
+ }
181
+ if (this.resolve) {
182
+ this.resolve();
183
+ this.resolve = null;
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Signal an error on the stream.
189
+ */
190
+ public fail(error: Error): void {
191
+ this.error = error;
192
+ this.done = true;
193
+ if (this.resolve) {
194
+ this.resolve();
195
+ this.resolve = null;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * End the stream gracefully.
201
+ */
202
+ public end(): void {
203
+ this.done = true;
204
+ if (this.resolve) {
205
+ this.resolve();
206
+ this.resolve = null;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Subscribe to new events as they arrive.
212
+ */
213
+ public subscribe(listener: (data: T) => void): () => void {
214
+ this.listeners.push(listener);
215
+ return () => {
216
+ const idx = this.listeners.indexOf(listener);
217
+ if (idx >= 0) this.listeners.splice(idx, 1);
218
+ };
219
+ }
220
+
221
+ async *[Symbol.asyncIterator](): AsyncIterator<T> {
222
+ while (true) {
223
+ while (this.queue.length > 0) {
224
+ yield this.queue.shift()!;
225
+ }
226
+ if (this.error) {
227
+ throw this.error;
228
+ }
229
+ if (this.done) {
230
+ return;
231
+ }
232
+ await new Promise<void>((r) => {
233
+ this.resolve = r;
234
+ });
235
+ }
236
+ }
237
+ }
238
+
239
+ // ----------------------------------------------------------------------------------------------------------
240
+
241
+ /**
242
+ * Response wrapper for SSE fetch requests.
243
+ *
244
+ * Wraps a standard `Response` and parses the `text/event-stream` body
245
+ * into an async iterable of typed events.
246
+ */
247
+ export class SseFetchResponse<T> implements AsyncIterable<T> {
248
+ public readonly response: Response;
249
+
250
+ constructor(response: Response) {
251
+ this.response = response;
252
+ }
253
+
254
+ /**
255
+ * HTTP status code of the response.
256
+ */
257
+ public get status(): number {
258
+ return this.response.status;
259
+ }
260
+
261
+ /**
262
+ * HTTP status text of the response.
263
+ */
264
+ public get statusText(): string {
265
+ return this.response.statusText;
266
+ }
267
+
268
+ /**
269
+ * Response headers.
270
+ */
271
+ public get headers(): Headers {
272
+ return this.response.headers;
273
+ }
274
+
275
+ async *[Symbol.asyncIterator](): AsyncIterator<T> {
276
+ const reader = this.response.body?.getReader();
277
+ if (!reader) return;
278
+
279
+ const decoder = new TextDecoder();
280
+ let buffer = "";
281
+
282
+ try {
283
+ while (true) {
284
+ const { done, value } = await reader.read();
285
+ if (done) break;
286
+
287
+ buffer += decoder.decode(value, { stream: true });
288
+
289
+ const lines = buffer.split("\n");
290
+ buffer = lines.pop() ?? "";
291
+
292
+ for (const line of lines) {
293
+ if (line.startsWith("data: ")) {
294
+ const data = line.slice(6);
295
+ try {
296
+ yield JSON.parse(data) as T;
297
+ } catch {
298
+ // skip non-JSON data lines
299
+ }
300
+ }
301
+ }
302
+ }
303
+
304
+ // process remaining buffer
305
+ if (buffer.startsWith("data: ")) {
306
+ const data = buffer.slice(6);
307
+ try {
308
+ yield JSON.parse(data) as T;
309
+ } catch {
310
+ // skip non-JSON data lines
311
+ }
312
+ }
313
+ } finally {
314
+ reader.releaseLock();
315
+ }
316
+ }
317
+ }
318
+
319
+ // ----------------------------------------------------------------------------------------------------------
320
+
321
+ /**
322
+ * Creates a Server-Sent Events (SSE) primitive for streaming typed events to clients.
323
+ *
324
+ * SSE endpoints provide a unidirectional stream from server to client over HTTP,
325
+ * with full type safety for event data. The handler receives `emit()` and `close()`
326
+ * functions to control the stream.
327
+ *
328
+ * **Key Features**
329
+ * - Full TypeScript inference for event data types
330
+ * - Automatic schema validation using TypeBox
331
+ * - Convention-based URL generation with customizable paths
332
+ * - Direct invocation (`run()`) returns an `SseStream` async iterable
333
+ * - HTTP requests (`fetch()`) returns an `SseFetchResponse` async iterable
334
+ * - Built-in `text/event-stream` content-type handling
335
+ *
336
+ * **URL Generation**
337
+ *
338
+ * All `$sse` paths are automatically prefixed with `/api`.
339
+ *
340
+ * ```ts
341
+ * $sse({ path: "/events" }) // POST /api/events
342
+ * $sse({ path: "/feed/:id" }) // POST /api/feed/:id
343
+ * ```
344
+ *
345
+ * The HTTP method is always POST.
346
+ *
347
+ * @example
348
+ * ```ts
349
+ * class NotificationController {
350
+ * events = $sse({
351
+ * schema: {
352
+ * data: t.object({
353
+ * type: t.text(),
354
+ * message: t.text(),
355
+ * }),
356
+ * },
357
+ * handler: async ({ emit, close }) => {
358
+ * emit({ type: "welcome", message: "Connected!" });
359
+ * // ... stream events ...
360
+ * close();
361
+ * },
362
+ * });
363
+ * }
364
+ * ```
365
+ */
366
+ export const $sse = <TConfig extends SseConfigSchema>(
367
+ options: SsePrimitiveOptions<TConfig>,
368
+ ): SsePrimitiveFn<TConfig> => {
369
+ const instance = createPrimitive(SsePrimitive<TConfig>, options);
370
+ const fn = (
371
+ config?: SseRequestEntry<TConfig>,
372
+ ): SseStream<SseEventData<TConfig>> => {
373
+ return instance.run(config);
374
+ };
375
+ Object.defineProperty(fn, "name", {
376
+ get(): string {
377
+ return instance.options.name || instance.config.propertyKey;
378
+ },
379
+ });
380
+ return Object.setPrototypeOf(fn, instance) as SsePrimitiveFn<TConfig>;
381
+ };
382
+
383
+ // ----------------------------------------------------------------------------------------------------------
384
+
385
+ /**
386
+ * The SSE primitive class extending PipelinePrimitive.
387
+ *
388
+ * Registers a POST route that streams `text/event-stream` responses.
389
+ * Supports direct invocation via `run()` and HTTP via `fetch()`.
390
+ */
391
+ export class SsePrimitive<
392
+ TConfig extends SseConfigSchema,
393
+ > extends PipelinePrimitive<SsePrimitiveOptions<TConfig>> {
394
+ protected readonly log = $logger();
395
+ protected readonly settings = $use(serverApiOptions);
396
+ protected readonly serverProvider = $inject(ServerProvider);
397
+ protected readonly serverRouterProvider = $inject(ServerRouterProvider);
398
+
399
+ protected onInit() {
400
+ if (this.options.disabled) {
401
+ this.log.debug(
402
+ `SSE endpoint '${this.name}' is disabled. It won't be available in the API.`,
403
+ );
404
+ return;
405
+ }
406
+ this.serverRouterProvider.createRoute({
407
+ method: this.method,
408
+ path: `${this.prefix}${this.path}`,
409
+ schema: this.requestConfigSchema,
410
+ handler: (request: ServerRequest) => this.httpHandler(request),
411
+ });
412
+ }
413
+
414
+ /**
415
+ * Returns the /api prefix.
416
+ */
417
+ public get prefix(): string {
418
+ return this.settings.prefix;
419
+ }
420
+
421
+ /**
422
+ * Returns the name of the SSE endpoint.
423
+ */
424
+ public get name(): string {
425
+ return this.options.name || this.config.propertyKey;
426
+ }
427
+
428
+ /**
429
+ * Returns the group of the SSE endpoint.
430
+ */
431
+ public get group(): string {
432
+ return this.options.group || this.config.service.name;
433
+ }
434
+
435
+ /**
436
+ * Returns the HTTP method. SSE always uses POST.
437
+ */
438
+ public get method(): RouteMethod {
439
+ return "POST";
440
+ }
441
+
442
+ /**
443
+ * Returns the path of the SSE endpoint.
444
+ */
445
+ public get path(): string {
446
+ if (this.options.path) {
447
+ return this.options.path;
448
+ }
449
+
450
+ let path = `/${this.name}`;
451
+
452
+ if (this.options.schema?.params) {
453
+ for (const [key] of Object.entries(
454
+ this.options.schema.params.properties,
455
+ )) {
456
+ path += `/:${key}`;
457
+ }
458
+ }
459
+
460
+ return path;
461
+ }
462
+
463
+ /**
464
+ * Returns the schema configuration.
465
+ */
466
+ public get schema(): TConfig | undefined {
467
+ return this.options.schema;
468
+ }
469
+
470
+ /**
471
+ * Constructs a RequestConfigSchema from the SSE config for route registration.
472
+ */
473
+ protected get requestConfigSchema(): RequestConfigSchema | undefined {
474
+ if (!this.options.schema) return undefined;
475
+ return {
476
+ body: this.options.schema.body,
477
+ params: this.options.schema.params,
478
+ query: this.options.schema.query,
479
+ headers: this.options.schema.headers,
480
+ };
481
+ }
482
+
483
+ /**
484
+ * Call the SSE handler directly and return a typed async iterable stream.
485
+ * There is no HTTP layer involved.
486
+ */
487
+ public run(
488
+ config?: SseRequestEntry<TConfig>,
489
+ ): SseStream<SseEventData<TConfig>> {
490
+ if (this.options.disabled) {
491
+ throw new AlephaError(`SSE endpoint '${this.name}' is disabled.`);
492
+ }
493
+
494
+ const stream = new SseStream<SseEventData<TConfig>>();
495
+ const {
496
+ body,
497
+ params = {},
498
+ query = {},
499
+ headers = {},
500
+ } = (config ?? {}) as SseRequestEntryContainer<SseConfigSchema>;
501
+
502
+ const url = new URL(`http://localhost${this.path ?? ""}`);
503
+ const reply = new ServerReply();
504
+
505
+ const serverRequest: Partial<ServerRequest> = {
506
+ method: this.method,
507
+ url,
508
+ body,
509
+ params,
510
+ query,
511
+ headers,
512
+ reply,
513
+ metadata: {
514
+ routePath: `${this.prefix}${this.path}`,
515
+ routeMethod: this.method,
516
+ },
517
+ };
518
+
519
+ const context: SseHandlerContext<TConfig> = {
520
+ body: body as any,
521
+ params: params as any,
522
+ query: query as any,
523
+ headers: headers as any,
524
+ request: serverRequest as ServerRequest,
525
+ emit: (data: SseEventData<TConfig>) => stream.push(data),
526
+ close: () => stream.end(),
527
+ };
528
+
529
+ const handlerFn = this.handler.run.bind(this.handler);
530
+
531
+ // run handler async, errors propagate to stream
532
+ Promise.resolve()
533
+ .then(() => handlerFn(context))
534
+ .then(() => {
535
+ // auto-close stream when handler finishes without calling close()
536
+ stream.end();
537
+ })
538
+ .catch((error: Error) => {
539
+ stream.fail(error);
540
+ });
541
+
542
+ return stream;
543
+ }
544
+
545
+ /**
546
+ * Works like `run`, but always fetches (http request) the route.
547
+ * Returns an `SseFetchResponse` that can be async-iterated for typed events.
548
+ */
549
+ public async fetch(
550
+ config?: SseRequestEntry<TConfig>,
551
+ ): Promise<SseFetchResponse<SseEventData<TConfig>>> {
552
+ const host = this.serverProvider.hostname;
553
+ const url = this.buildFetchUrl(host, config);
554
+ const { body, headers: configHeaders = {} } = (config ??
555
+ {}) as SseRequestEntryContainer<SseConfigSchema>;
556
+
557
+ const requestInit: RequestInit = {
558
+ method: "POST",
559
+ headers: {
560
+ accept: "text/event-stream",
561
+ "content-type": "application/json",
562
+ ...configHeaders,
563
+ },
564
+ };
565
+
566
+ if (body !== undefined) {
567
+ requestInit.body = JSON.stringify(body);
568
+ }
569
+
570
+ const response = await fetch(url, requestInit);
571
+ return new SseFetchResponse<SseEventData<TConfig>>(response);
572
+ }
573
+
574
+ /**
575
+ * HTTP handler for the registered route.
576
+ * Returns a ReadableStream with SSE-formatted events.
577
+ */
578
+ protected httpHandler(request: ServerRequest): ReadableStream {
579
+ const reply = request.reply;
580
+ reply.setHeader("content-type", "text/event-stream");
581
+ reply.setHeader("cache-control", "no-cache");
582
+ reply.setHeader("connection", "keep-alive");
583
+
584
+ const handlerFn = this.handler.run.bind(this.handler);
585
+
586
+ return new ReadableStream({
587
+ start: (controller) => {
588
+ const encoder = new TextEncoder();
589
+ const context: SseHandlerContext<TConfig> = {
590
+ body: request.body as any,
591
+ params: request.params as any,
592
+ query: request.query as any,
593
+ headers: request.headers as any,
594
+ request,
595
+ emit: (data: SseEventData<TConfig>) => {
596
+ try {
597
+ controller.enqueue(
598
+ encoder.encode(`data: ${JSON.stringify(data)}\n\n`),
599
+ );
600
+ } catch {
601
+ // stream may already be closed
602
+ }
603
+ },
604
+ close: () => {
605
+ try {
606
+ controller.close();
607
+ } catch {
608
+ // stream may already be closed
609
+ }
610
+ },
611
+ };
612
+
613
+ Promise.resolve()
614
+ .then(() => handlerFn(context))
615
+ .then(() => {
616
+ try {
617
+ controller.close();
618
+ } catch {
619
+ // already closed
620
+ }
621
+ })
622
+ .catch((error: Error) => {
623
+ try {
624
+ controller.error(error);
625
+ } catch {
626
+ // already closed
627
+ }
628
+ });
629
+ },
630
+ });
631
+ }
632
+
633
+ /**
634
+ * Build the fetch URL with path variables and query params.
635
+ */
636
+ protected buildFetchUrl(
637
+ host: string,
638
+ config?: SseRequestEntry<TConfig>,
639
+ ): string {
640
+ let url = `${host}${this.prefix}${this.path}`;
641
+
642
+ const { params, query } = (config ??
643
+ {}) as SseRequestEntryContainer<SseConfigSchema>;
644
+
645
+ if (params && typeof params === "object") {
646
+ for (const [key, value] of Object.entries(params)) {
647
+ url = url.replace(`:${key}`, String(value));
648
+ }
649
+ }
650
+
651
+ if (query && typeof query === "object") {
652
+ const searchParams = new URLSearchParams();
653
+ for (const [key, value] of Object.entries(query)) {
654
+ if (value !== undefined) {
655
+ searchParams.set(key, String(value));
656
+ }
657
+ }
658
+ const qs = searchParams.toString();
659
+ if (qs) {
660
+ url += `?${qs}`;
661
+ }
662
+ }
663
+
664
+ return url;
665
+ }
666
+ }
667
+
668
+ // ----------------------------------------------------------------------------------------------------------
669
+
670
+ /**
671
+ * Combined callable + SsePrimitive interface.
672
+ */
673
+ export interface SsePrimitiveFn<TConfig extends SseConfigSchema>
674
+ extends SsePrimitive<TConfig> {
675
+ (config?: SseRequestEntry<TConfig>): SseStream<SseEventData<TConfig>>;
676
+ }
677
+
678
+ $sse[KIND] = SsePrimitive;
679
+
680
+ // ----------------------------------------------------------------------------------------------------------
681
+
682
+ /**
683
+ * Infer the event data type from an SSE config schema.
684
+ */
685
+ export type SseEventData<TConfig extends SseConfigSchema> =
686
+ TConfig["data"] extends TSchema ? Static<TConfig["data"]> : any;
687
+
688
+ /**
689
+ * Request entry type for SSE endpoints (body, params, query, headers).
690
+ */
691
+ export type SseRequestEntry<
692
+ TConfig extends SseConfigSchema,
693
+ T = SseRequestEntryContainer<TConfig>,
694
+ > = {
695
+ [K in keyof T as T[K] extends undefined ? never : K]: T[K];
696
+ };
697
+
698
+ /**
699
+ * Full container type for SSE request entries.
700
+ */
701
+ export type SseRequestEntryContainer<TConfig extends SseConfigSchema> = {
702
+ body: TConfig["body"] extends TObject ? Static<TConfig["body"]> : undefined;
703
+
704
+ params: TConfig["params"] extends TObject
705
+ ? Static<TConfig["params"]>
706
+ : undefined;
707
+
708
+ headers?: TConfig["headers"] extends TObject
709
+ ? Static<TConfig["headers"]>
710
+ : Record<string, string>;
711
+
712
+ query?: TConfig["query"] extends TObject
713
+ ? Partial<Static<TConfig["query"]>>
714
+ : Record<string, string>;
715
+ };