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
@@ -5,7 +5,6 @@ import { $client } from "./primitives/$client.ts";
5
5
  import { $remote } from "./primitives/$remote.ts";
6
6
  import { LinkProvider } from "./providers/LinkProvider.ts";
7
7
  import { BatchCollector } from "./services/BatchCollector.ts";
8
- import { DefinitionsPool } from "./services/DefinitionsPool.ts";
9
8
 
10
9
  // ---------------------------------------------------------------------------------------------------------------------
11
10
 
@@ -16,7 +15,6 @@ export * from "./primitives/$remote.ts";
16
15
  export * from "./providers/LinkProvider.ts";
17
16
  export * from "./schemas/apiLinksResponseSchema.ts";
18
17
  export * from "./services/BatchCollector.ts";
19
- export * from "./services/DefinitionsPool.ts";
20
18
 
21
19
  // ---------------------------------------------------------------- -----------------------------------------------------
22
20
 
@@ -24,5 +22,5 @@ export const AlephaServerLinks = $module({
24
22
  name: "alepha.server.links",
25
23
  atoms: [apiLinksAtom, linkOptionsAtom],
26
24
  primitives: [$remote, $client],
27
- services: [LinkProvider, BatchCollector, DefinitionsPool],
25
+ services: [LinkProvider, BatchCollector],
28
26
  });
@@ -9,7 +9,6 @@ import { RemotePrimitiveProvider } from "./providers/RemotePrimitiveProvider.ts"
9
9
  import { ServerLinksProvider } from "./providers/ServerLinksProvider.ts";
10
10
  import type { ApiRegistryResponse } from "./schemas/apiLinksResponseSchema.ts";
11
11
  import { BatchCollector } from "./services/BatchCollector.ts";
12
- import { DefinitionsPool } from "./services/DefinitionsPool.ts";
13
12
 
14
13
  // ---------------------------------------------------------------------------------------------------------------------
15
14
 
@@ -22,7 +21,6 @@ export * from "./providers/RemotePrimitiveProvider.ts";
22
21
  export * from "./providers/ServerLinksProvider.ts";
23
22
  export * from "./schemas/apiLinksResponseSchema.ts";
24
23
  export * from "./services/BatchCollector.ts";
25
- export * from "./services/DefinitionsPool.ts";
26
24
 
27
25
  // ---------------------------------------------------------------------------------------------------------------------
28
26
 
@@ -69,6 +67,5 @@ export const AlephaServerLinks = $module({
69
67
  RemotePrimitiveProvider,
70
68
  LinkProvider,
71
69
  BatchCollector,
72
- DefinitionsPool,
73
70
  ],
74
71
  });
@@ -40,13 +40,9 @@ describe("LinkProvider", () => {
40
40
 
41
41
  expect(data).toStrictEqual({
42
42
  prefix: "/api",
43
- definitions: {
44
- $0: '{"type":"object","required":["pong"],"properties":{"pong":{"type":"boolean"}},"additionalProperties":false}',
45
- },
46
43
  actions: {
47
44
  ping: {
48
45
  path: "/ping",
49
- response: "$0",
50
46
  },
51
47
  },
52
48
  });
@@ -114,13 +110,13 @@ describe("LinkProvider", () => {
114
110
  expect(data.actions.createUser.method).toBe("POST");
115
111
  });
116
112
 
117
- it("should deduplicate schemas in definitions pool", async ({ expect }) => {
118
- const responseSchema = t.object({ id: t.integer(), name: t.text() });
119
-
120
- class DedupeApp {
113
+ it("should not include definitions or schema refs in registry", async ({
114
+ expect,
115
+ }) => {
116
+ class SchemaApp {
121
117
  getUser = $action({
122
118
  path: "/users/:id",
123
- schema: { response: responseSchema },
119
+ schema: { response: t.object({ id: t.integer(), name: t.text() }) },
124
120
  handler: () => ({ id: 1, name: "John" }),
125
121
  });
126
122
  updateUser = $action({
@@ -128,13 +124,13 @@ describe("LinkProvider", () => {
128
124
  path: "/users/:id",
129
125
  schema: {
130
126
  body: t.object({ name: t.text() }),
131
- response: responseSchema,
127
+ response: t.object({ id: t.integer(), name: t.text() }),
132
128
  },
133
129
  handler: () => ({ id: 1, name: "John" }),
134
130
  });
135
131
  }
136
132
 
137
- const alepha = Alepha.create().with(DedupeApp).with(ServerLinksProvider);
133
+ const alepha = Alepha.create().with(SchemaApp).with(ServerLinksProvider);
138
134
  await alepha.start();
139
135
 
140
136
  const res = await fetch(
@@ -142,16 +138,11 @@ describe("LinkProvider", () => {
142
138
  );
143
139
  const data = await res.json();
144
140
 
145
- // Both actions should reference the same definition for response
146
- expect(data.actions.getUser.response).toBe(
147
- data.actions.updateUser.response,
148
- );
149
-
150
- // The body schema is different, so it gets a separate definition
151
- expect(data.actions.updateUser.body).toBeDefined();
152
- expect(data.actions.updateUser.body).not.toBe(
153
- data.actions.updateUser.response,
154
- );
141
+ expect(data.definitions).toBeUndefined();
142
+ expect(data.actions.getUser.body).toBeUndefined();
143
+ expect(data.actions.getUser.response).toBeUndefined();
144
+ expect(data.actions.updateUser.body).toBeUndefined();
145
+ expect(data.actions.updateUser.response).toBeUndefined();
155
146
  });
156
147
 
157
148
  it("should not include group or rawSchema in wire format", async ({
@@ -1,12 +1,4 @@
1
- import {
2
- $inject,
3
- $use,
4
- Alepha,
5
- AlephaError,
6
- type Async,
7
- jsonSchemaToTypeBox,
8
- t,
9
- } from "alepha";
1
+ import { $inject, $use, Alepha, AlephaError, type Async, t } from "alepha";
10
2
  import { $logger } from "alepha/logger";
11
3
  import type { SecureOptions } from "alepha/security";
12
4
  import {
@@ -21,7 +13,11 @@ import {
21
13
  type ServerRequest,
22
14
  type ServerRequestConfigEntry,
23
15
  type ServerResponseBody,
24
- type TRequestBody,
16
+ type SseConfigSchema,
17
+ type SseEventData,
18
+ type SsePrimitive,
19
+ type SseRequestEntry,
20
+ type SseStream,
25
21
  UnauthorizedError,
26
22
  } from "alepha/server";
27
23
  import { linkOptionsAtom } from "../atoms/linkOptionsAtom.ts";
@@ -49,7 +45,6 @@ export class LinkProvider {
49
45
  // Browser/SSR: parsed from the registry response
50
46
  protected actionMap = new Map<string, HttpClientLink>();
51
47
  protected permissions = new Set<string>();
52
- protected definitions: Record<string, string> = {};
53
48
  protected lastLoadedRegistry: ApiRegistryResponse | null = null;
54
49
 
55
50
  // Browser-only: batch collector for coalescing multiple calls
@@ -106,7 +101,6 @@ export class LinkProvider {
106
101
  */
107
102
  protected loadRegistry(registry: ApiRegistryResponse): void {
108
103
  this.lastLoadedRegistry = registry;
109
- this.definitions = registry.definitions ?? {};
110
104
  this.permissions.clear();
111
105
  this.actionMap.clear();
112
106
 
@@ -114,12 +108,10 @@ export class LinkProvider {
114
108
  this.actionMap.set(name, {
115
109
  name,
116
110
  path: action.path,
111
+ kind: action.kind,
117
112
  method: action.method,
118
113
  contentType: action.contentType,
119
114
  service: action.service,
120
- // Store definition refs for lazy schema resolution
121
- bodyRef: action.body,
122
- responseRef: action.response,
123
115
  });
124
116
  }
125
117
 
@@ -320,36 +312,6 @@ export class LinkProvider {
320
312
  return this.can(name);
321
313
  };
322
314
 
323
- $.schema = () => {
324
- const link = this.links.find((l) => l.name === name);
325
- if (!link) {
326
- throw new AlephaError(`Link ${name} not found.`);
327
- }
328
-
329
- // If schema is already resolved (server-side), return it
330
- if (link.schema) {
331
- return link.schema as { body: any; response: any };
332
- }
333
-
334
- // Lazy resolve from definition refs (browser-side)
335
- const resolved: RequestConfigSchema = {};
336
- if (link.bodyRef && this.definitions[link.bodyRef]) {
337
- resolved.body = jsonSchemaToTypeBox(
338
- JSON.parse(this.definitions[link.bodyRef]),
339
- ) as TRequestBody;
340
- }
341
- if (link.responseRef && this.definitions[link.responseRef]) {
342
- resolved.response = jsonSchemaToTypeBox(
343
- JSON.parse(this.definitions[link.responseRef]),
344
- ) as TRequestBody;
345
- }
346
-
347
- // Cache for next access
348
- link.schema = resolved;
349
-
350
- return resolved as { body: any; response: any };
351
- };
352
-
353
315
  return $;
354
316
  }
355
317
 
@@ -441,6 +403,7 @@ export interface HttpClientLink {
441
403
  name: string;
442
404
  path: string;
443
405
  method?: string;
406
+ kind?: string;
444
407
  contentType?: string;
445
408
  service?: string;
446
409
  secured?: boolean | SecureOptions;
@@ -453,9 +416,6 @@ export interface HttpClientLink {
453
416
  request: ServerRequest,
454
417
  options: ClientRequestOptions,
455
418
  ) => Async<ServerResponseBody>;
456
- // -- browser only (definition refs for lazy schema resolution) --
457
- bodyRef?: string;
458
- responseRef?: string;
459
419
  }
460
420
 
461
421
  export interface ClientScope {
@@ -469,6 +429,12 @@ export type HttpVirtualClient<T> = {
469
429
  : never]: T[K] extends ActionPrimitive<infer Schema>
470
430
  ? VirtualAction<Schema>
471
431
  : never;
432
+ } & {
433
+ [K in keyof T as T[K] extends SsePrimitive<SseConfigSchema>
434
+ ? K
435
+ : never]: T[K] extends SsePrimitive<infer Schema>
436
+ ? VirtualSse<Schema>
437
+ : never;
472
438
  };
473
439
 
474
440
  export interface VirtualAction<T extends RequestConfigSchema>
@@ -478,8 +444,10 @@ export interface VirtualAction<T extends RequestConfigSchema>
478
444
  opts?: ClientRequestOptions,
479
445
  ): Promise<ClientRequestResponse<T>>;
480
446
  can: () => boolean;
481
- schema: () => {
482
- body: T["body"];
483
- response: T["response"];
484
- };
447
+ }
448
+
449
+ export interface VirtualSse<T extends SseConfigSchema> {
450
+ (config?: SseRequestEntry<T>): Promise<SseStream<SseEventData<T>>>;
451
+ name: string;
452
+ can: () => boolean;
485
453
  }
@@ -366,6 +366,112 @@ describe("ServerLinksProvider", () => {
366
366
  });
367
367
  });
368
368
 
369
+ describe("schemas endpoint", () => {
370
+ it("should return schemas for requested actions", async ({ expect }) => {
371
+ class App {
372
+ ping = $action({
373
+ schema: {
374
+ body: t.object({ message: t.text() }),
375
+ response: t.object({ pong: t.boolean() }),
376
+ },
377
+ handler: () => ({ pong: true }),
378
+ });
379
+ }
380
+
381
+ const alepha = Alepha.create().with(App).with(ServerLinksProvider);
382
+ await alepha.start();
383
+
384
+ const res = await fetch(
385
+ `${alepha.inject(ServerProvider).hostname}/api/_links/schemas`,
386
+ {
387
+ method: "POST",
388
+ headers: { "content-type": "application/json" },
389
+ body: JSON.stringify({ actions: ["ping"] }),
390
+ },
391
+ );
392
+
393
+ const data = await res.json();
394
+
395
+ expect(data.ping).toBeDefined();
396
+ expect(data.ping.body).toBeDefined();
397
+ expect(data.ping.response).toBeDefined();
398
+ expect(JSON.parse(data.ping.body).type).toBe("object");
399
+ expect(JSON.parse(data.ping.response).type).toBe("object");
400
+ });
401
+
402
+ it("should return empty for unknown actions", async ({ expect }) => {
403
+ class App {
404
+ ping = $action({
405
+ schema: { response: t.text() },
406
+ handler: () => "pong",
407
+ });
408
+ }
409
+
410
+ const alepha = Alepha.create().with(App).with(ServerLinksProvider);
411
+ await alepha.start();
412
+
413
+ const res = await fetch(
414
+ `${alepha.inject(ServerProvider).hostname}/api/_links/schemas`,
415
+ {
416
+ method: "POST",
417
+ headers: { "content-type": "application/json" },
418
+ body: JSON.stringify({ actions: ["nonexistent"] }),
419
+ },
420
+ );
421
+
422
+ const data = await res.json();
423
+
424
+ expect(data.nonexistent).toBeUndefined();
425
+ });
426
+
427
+ it("should filter based on user permissions", async ({ expect }) => {
428
+ class App {
429
+ publicAction = $action({
430
+ schema: {
431
+ body: t.object({ name: t.text() }),
432
+ response: t.text(),
433
+ },
434
+ handler: () => "PUBLIC",
435
+ });
436
+ securedAction = $action({
437
+ use: [$secure()],
438
+ schema: {
439
+ body: t.object({ secret: t.text() }),
440
+ response: t.text(),
441
+ },
442
+ handler: () => "SECURED",
443
+ });
444
+ issuer = $issuer({
445
+ secret: "test",
446
+ roles: [{ name: "user", permissions: [{ name: "*" }] }],
447
+ });
448
+ }
449
+
450
+ const alepha = Alepha.create()
451
+ .with(App)
452
+ .with(ServerLinksProvider)
453
+ .with(AlephaSecurity);
454
+ await alepha.start();
455
+
456
+ // Unauthenticated request — should only get public schema
457
+ const res = await fetch(
458
+ `${alepha.inject(ServerProvider).hostname}/api/_links/schemas`,
459
+ {
460
+ method: "POST",
461
+ headers: { "content-type": "application/json" },
462
+ body: JSON.stringify({
463
+ actions: ["publicAction", "securedAction"],
464
+ }),
465
+ },
466
+ );
467
+
468
+ const data = await res.json();
469
+
470
+ expect(data.publicAction).toBeDefined();
471
+ expect(data.securedAction).toBeUndefined();
472
+ });
473
+ });
474
+
369
475
  describe("caching and ETag", () => {
370
476
  it("should return ETag header on first request", async ({ expect }) => {
371
477
  class App {
@@ -5,6 +5,7 @@ import type { SecurityProvider, UserAccountToken } from "alepha/security";
5
5
  import {
6
6
  $action,
7
7
  $route,
8
+ $sse,
8
9
  type ClientRequestEntry,
9
10
  type ClientRequestOptions,
10
11
  type RequestConfigSchema,
@@ -12,8 +13,7 @@ import {
12
13
  serverApiOptions,
13
14
  } from "alepha/server";
14
15
  import type { ApiRegistryResponse } from "../schemas/apiLinksResponseSchema.ts";
15
- import { DefinitionsPool } from "../services/DefinitionsPool.ts";
16
- import { LinkProvider } from "./LinkProvider.ts";
16
+ import { type HttpClientLink, LinkProvider } from "./LinkProvider.ts";
17
17
  import { RemotePrimitiveProvider } from "./RemotePrimitiveProvider.ts";
18
18
 
19
19
  export class ServerLinksProvider {
@@ -68,6 +68,24 @@ export class ServerLinksProvider {
68
68
  ) => action.run(config, options),
69
69
  });
70
70
  }
71
+
72
+ // convert all $sse to local links
73
+ for (const sse of this.alepha.primitives($sse)) {
74
+ this.linkProvider.registerLink({
75
+ name: sse.name,
76
+ group: sse.group,
77
+ kind: "sse",
78
+ schema: {
79
+ body: sse.schema?.body,
80
+ },
81
+ method: "POST",
82
+ prefix: sse.prefix,
83
+ path: sse.path,
84
+ handler: async (config) => {
85
+ return sse.run(config as any) as any;
86
+ },
87
+ });
88
+ }
71
89
  },
72
90
  });
73
91
 
@@ -127,6 +145,51 @@ export class ServerLinksProvider {
127
145
  },
128
146
  });
129
147
 
148
+ /**
149
+ * On-demand schemas endpoint — returns JSON Schemas for requested actions.
150
+ *
151
+ * Schemas are filtered by the user's permissions (same logic as the registry).
152
+ */
153
+ public readonly schemas = $route({
154
+ method: "POST",
155
+ path: "/api/_links/schemas",
156
+ schema: {
157
+ body: t.object({
158
+ actions: t.array(t.text()),
159
+ }),
160
+ response: t.record(
161
+ t.text(),
162
+ t.object({
163
+ body: t.optional(t.string()),
164
+ response: t.optional(t.string()),
165
+ }),
166
+ ),
167
+ },
168
+ handler: async ({ body, user }) => {
169
+ const result: Record<string, { body?: string; response?: string }> = {};
170
+
171
+ for (const name of body.actions) {
172
+ const link = this.linkProvider
173
+ .getServerLinks()
174
+ .find((l) => l.name === name && !l.host);
175
+
176
+ if (!link) continue;
177
+ if (!this.isLinkAccessible(link, user)) continue;
178
+
179
+ const entry: { body?: string; response?: string } = {};
180
+ if (link.schema?.body) {
181
+ entry.body = JSON.stringify(link.schema.body);
182
+ }
183
+ if (link.schema?.response) {
184
+ entry.response = JSON.stringify(link.schema.response);
185
+ }
186
+ result[name] = entry;
187
+ }
188
+
189
+ return result as any;
190
+ },
191
+ });
192
+
130
193
  /**
131
194
  * Batch endpoint — execute multiple actions in a single HTTP request.
132
195
  * Each sub-request is independent: errors in one don't affect others.
@@ -208,7 +271,6 @@ export class ServerLinksProvider {
208
271
  ? securityProvider.getPermissions(user)
209
272
  : undefined;
210
273
 
211
- const pool = new DefinitionsPool();
212
274
  const actions: Record<string, any> = {};
213
275
  const permissions: string[] = [];
214
276
 
@@ -228,56 +290,12 @@ export class ServerLinksProvider {
228
290
  for (const link of this.linkProvider.getServerLinks()) {
229
291
  // SKIP REMOTE LINKS, remote links are handled separately for security
230
292
  if (link.host) continue;
231
-
232
- if (securityProvider && link.secured) {
233
- // skip secured links if user is not provided
234
- if (!user) {
235
- continue;
236
- }
237
-
238
- if (typeof link.secured === "object") {
239
- // issuer check
240
- if (
241
- link.secured.issuers?.length &&
242
- (!user.realm || !link.secured.issuers.includes(user.realm))
243
- ) {
244
- continue;
245
- }
246
-
247
- // role check
248
- if (link.secured.roles?.length) {
249
- const hasRole = link.secured.roles.some((role: string) =>
250
- user.roles?.includes(role),
251
- );
252
- if (!hasRole) continue;
253
- }
254
-
255
- // explicit permission check
256
- if (link.secured.permissions?.length) {
257
- const perms = link.secured.permissions;
258
-
259
- let allowed = true;
260
- for (const perm of perms) {
261
- const result = securityProvider.checkPermission(
262
- perm,
263
- ...(user.roles ?? []),
264
- );
265
- if (!result.isAuthorized) {
266
- allowed = false;
267
- break;
268
- }
269
- }
270
- if (!allowed) continue;
271
- }
272
- }
273
- // link.secured === true → auth only, user is already checked above
274
- }
293
+ if (!this.isLinkAccessible(link, user)) continue;
275
294
 
276
295
  actions[link.name] = {
277
296
  path: link.path,
278
297
  method: link.method || undefined,
279
- body: pool.ref(link.schema?.body),
280
- response: pool.ref(link.schema?.response),
298
+ kind: link.kind,
281
299
  contentType: link.contentType,
282
300
  service: link.service,
283
301
  };
@@ -298,20 +316,6 @@ export class ServerLinksProvider {
298
316
  for (const { remote, registry } of remoteResults) {
299
317
  const remotePrefix = registry.prefix ?? "/api";
300
318
 
301
- // Merge remote definitions into our pool
302
- const remoteDefMap = new Map<string, string>();
303
- if (registry.definitions) {
304
- for (const [refKey, jsonString] of Object.entries(
305
- registry.definitions,
306
- )) {
307
- const schema = JSON.parse(jsonString);
308
- const newRef = pool.ref(schema);
309
- if (newRef) {
310
- remoteDefMap.set(refKey, newRef);
311
- }
312
- }
313
- }
314
-
315
319
  // Merge remote actions
316
320
  for (const [name, action] of Object.entries(registry.actions)) {
317
321
  let path = action.path.replace(remotePrefix, "");
@@ -322,12 +326,6 @@ export class ServerLinksProvider {
322
326
  actions[name] = {
323
327
  path,
324
328
  method: action.method,
325
- body: action.body
326
- ? (remoteDefMap.get(action.body) ?? action.body)
327
- : undefined,
328
- response: action.response
329
- ? (remoteDefMap.get(action.response) ?? action.response)
330
- : undefined,
331
329
  contentType: action.contentType,
332
330
  service: remote.name,
333
331
  };
@@ -341,16 +339,58 @@ export class ServerLinksProvider {
341
339
 
342
340
  this.serverTimingProvider.endTiming("fetchRemoteLinks");
343
341
 
344
- const definitions = pool.toJSON();
345
-
346
342
  return {
347
343
  prefix: this.serverApi.prefix,
348
- definitions:
349
- Object.keys(definitions).length > 0 ? definitions : undefined,
350
344
  actions,
351
345
  permissions: permissions.length > 0 ? permissions : undefined,
352
346
  };
353
347
  }
348
+
349
+ /**
350
+ * Check if a link is accessible by the given user based on security rules.
351
+ */
352
+ protected isLinkAccessible(
353
+ link: HttpClientLink,
354
+ user?: UserAccountToken,
355
+ ): boolean {
356
+ const { securityProvider } = this;
357
+
358
+ if (securityProvider && link.secured) {
359
+ if (!user) return false;
360
+
361
+ if (typeof link.secured === "object") {
362
+ // issuer check
363
+ if (
364
+ link.secured.issuers?.length &&
365
+ (!user.realm || !link.secured.issuers.includes(user.realm))
366
+ ) {
367
+ return false;
368
+ }
369
+
370
+ // role check
371
+ if (link.secured.roles?.length) {
372
+ const hasRole = link.secured.roles.some((role: string) =>
373
+ user.roles?.includes(role),
374
+ );
375
+ if (!hasRole) return false;
376
+ }
377
+
378
+ // explicit permission check
379
+ if (link.secured.permissions?.length) {
380
+ for (const perm of link.secured.permissions) {
381
+ const result = securityProvider.checkPermission(
382
+ perm,
383
+ ...(user.roles ?? []),
384
+ );
385
+ if (!result.isAuthorized) return false;
386
+ }
387
+ }
388
+ }
389
+ // link.secured === true → auth only, user is already checked above
390
+ }
391
+
392
+ return true;
393
+ }
354
394
  }
355
395
 
356
396
  export interface GetApiLinksOptions {
@@ -13,24 +13,17 @@ export const apiActionSchema = t.object({
13
13
  }),
14
14
  ),
15
15
 
16
- body: t.optional(
17
- t.text({
18
- description:
19
- "Reference to a definitions pool entry (e.g. '$0') for the request body JSON Schema.",
20
- }),
21
- ),
22
-
23
- response: t.optional(
16
+ contentType: t.optional(
24
17
  t.text({
25
18
  description:
26
- "Reference to a definitions pool entry (e.g. '$0') for the response JSON Schema.",
19
+ "Content type for the request body. Only present for non-JSON types (e.g. 'multipart/form-data'). When absent, defaults to application/json.",
27
20
  }),
28
21
  ),
29
22
 
30
- contentType: t.optional(
23
+ kind: t.optional(
31
24
  t.text({
32
25
  description:
33
- "Content type for the request body. Only present for non-JSON types (e.g. 'multipart/form-data'). When absent, defaults to application/json.",
26
+ "Action kind. Used to distinguish special action types (e.g. 'sse' for Server-Sent Events streams).",
34
27
  }),
35
28
  ),
36
29
 
@@ -45,16 +38,6 @@ export const apiActionSchema = t.object({
45
38
  export const apiRegistryResponseSchema = t.object({
46
39
  prefix: t.optional(t.text()),
47
40
 
48
- definitions: t.optional(
49
- t.record(
50
- t.text(),
51
- t.string({
52
- description:
53
- "Pre-stringified JSON Schema. Values can be 2KB+, so t.string() (no maxLength) is used instead of t.text().",
54
- }),
55
- ),
56
- ),
57
-
58
41
  actions: t.record(t.text(), apiActionSchema),
59
42
 
60
43
  permissions: t.optional(t.array(t.text())),
@@ -1,4 +1,5 @@
1
1
  import { $inject } from "alepha";
2
+ import { $logger } from "alepha/logger";
2
3
  import { HttpClient, HttpError } from "alepha/server";
3
4
 
4
5
  /**
@@ -15,6 +16,7 @@ import { HttpClient, HttpError } from "alepha/server";
15
16
  export class BatchCollector {
16
17
  protected static readonly MAX_BATCH_SIZE = 20;
17
18
 
19
+ protected readonly log = $logger();
18
20
  protected readonly httpClient = $inject(HttpClient);
19
21
 
20
22
  protected pending: PendingBatchEntry[] = [];
@@ -29,10 +31,10 @@ export class BatchCollector {
29
31
 
30
32
  if (!this.scheduled) {
31
33
  this.scheduled = true;
32
- queueMicrotask(() => {
34
+ setTimeout(() => {
33
35
  this.scheduled = false;
34
- this.flush();
35
- });
36
+ this.flush().catch((err) => this.log.error(err));
37
+ }, 10);
36
38
  }
37
39
  });
38
40
  }