@keboola/api-client 56.0.0 → 57.0.0

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 (345) hide show
  1. package/AGENTS.md +110 -229
  2. package/API-SURFACE.md +10 -2
  3. package/CHANGELOG.md +45 -0
  4. package/README.md +20 -133
  5. package/dist/{ManagementSessionMintError-Bc9bc7Ai.cjs → ManagementSessionMintError-BCOLLaJi.cjs} +3 -2
  6. package/dist/ManagementSessionMintError-BCOLLaJi.cjs.map +1 -0
  7. package/dist/{ManagementSessionMintError-BMHDcEqV.js → ManagementSessionMintError-KUX3utTV.js} +3 -2
  8. package/dist/ManagementSessionMintError-KUX3utTV.js.map +1 -0
  9. package/dist/{adminRoles-CUB0JddB.d.ts → adminRoles-CnfGDvjN.d.ts} +2 -2
  10. package/dist/{adminRoles-BFOPSedO.d.cts → adminRoles-D6AS9Bzx.d.cts} +2 -2
  11. package/dist/ai/index.d.cts +2 -2
  12. package/dist/ai/index.d.ts +2 -2
  13. package/dist/ai/types.d.cts +1 -1
  14. package/dist/ai/types.d.ts +1 -1
  15. package/dist/apps/index.cjs +1 -1
  16. package/dist/apps/index.d.cts +2 -2
  17. package/dist/apps/index.d.ts +2 -2
  18. package/dist/apps/index.js +1 -1
  19. package/dist/apps/types.d.cts +2 -2
  20. package/dist/apps/types.d.ts +2 -2
  21. package/dist/{apps-C1x5IKNQ.cjs → apps-BA9JRLAZ.cjs} +55 -1
  22. package/dist/apps-BA9JRLAZ.cjs.map +1 -0
  23. package/dist/{apps-BN7fWtSm.js → apps-DDcguJ1i.js} +55 -1
  24. package/dist/apps-DDcguJ1i.js.map +1 -0
  25. package/dist/assets/index.d.cts +1 -1
  26. package/dist/assets/index.d.ts +1 -1
  27. package/dist/auth/index.cjs +1 -1
  28. package/dist/auth/index.d.cts +1 -1
  29. package/dist/auth/index.d.ts +1 -1
  30. package/dist/auth/index.js +1 -1
  31. package/dist/auth/types.d.cts +2 -2
  32. package/dist/auth/types.d.ts +2 -2
  33. package/dist/{authClient-B_Mb4Vzs.js → authClient-BKGpJI5L.js} +13 -2
  34. package/dist/authClient-BKGpJI5L.js.map +1 -0
  35. package/dist/{authClient-C9QqhT2M.cjs → authClient-C3KG9hXw.cjs} +17 -6
  36. package/dist/authClient-C3KG9hXw.cjs.map +1 -0
  37. package/dist/{authClient-Dgyb0EFi.d.ts → authClient-CbWpMmdX.d.ts} +7 -4
  38. package/dist/{authClient-DOetdp2k.d.cts → authClient-UKeopxZZ.d.cts} +7 -4
  39. package/dist/billing/index.d.cts +1 -1
  40. package/dist/billing/index.d.ts +1 -1
  41. package/dist/billing/types.d.cts +1 -1
  42. package/dist/billing/types.d.ts +1 -1
  43. package/dist/chat/index.d.cts +2 -2
  44. package/dist/chat/index.d.ts +2 -2
  45. package/dist/chat/types.d.cts +1 -1
  46. package/dist/chat/types.d.ts +1 -1
  47. package/dist/componentsMcp/index.d.cts +1 -1
  48. package/dist/componentsMcp/index.d.ts +1 -1
  49. package/dist/componentsMcp/types.d.cts +1 -1
  50. package/dist/componentsMcp/types.d.ts +1 -1
  51. package/dist/constants/index.cjs +2 -2
  52. package/dist/constants/index.d.cts +3 -3
  53. package/dist/constants/index.d.ts +3 -3
  54. package/dist/constants/index.js +2 -2
  55. package/dist/{constants-HccvU5kx.js → constants-CxEaHCyt.js} +4 -3
  56. package/dist/constants-CxEaHCyt.js.map +1 -0
  57. package/dist/{constants-V9hAyPTo.cjs → constants-fiyOLyZE.cjs} +4 -3
  58. package/dist/constants-fiyOLyZE.cjs.map +1 -0
  59. package/dist/dataScience/index.d.cts +3 -3
  60. package/dist/dataScience/index.d.ts +3 -3
  61. package/dist/dataScience/types.d.cts +1 -1
  62. package/dist/dataScience/types.d.ts +1 -1
  63. package/dist/developerPortal/index.cjs +1 -1
  64. package/dist/developerPortal/index.d.cts +3 -3
  65. package/dist/developerPortal/index.d.ts +3 -3
  66. package/dist/developerPortal/index.js +1 -1
  67. package/dist/developerPortal/types.d.cts +2 -2
  68. package/dist/developerPortal/types.d.ts +2 -2
  69. package/dist/{developerPortalClient-CzCJ5sE3.js → developerPortalClient-3Q7049-4.js} +19 -1
  70. package/dist/developerPortalClient-3Q7049-4.js.map +1 -0
  71. package/dist/{developerPortalClient-BcK9F-Fs.cjs → developerPortalClient-Cj9bStCS.cjs} +19 -1
  72. package/dist/developerPortalClient-Cj9bStCS.cjs.map +1 -0
  73. package/dist/domain/permissions/index.d.cts +1 -1
  74. package/dist/domain/permissions/index.d.ts +1 -1
  75. package/dist/editor/index.d.cts +2 -2
  76. package/dist/editor/index.d.ts +2 -2
  77. package/dist/editor/types.d.cts +1 -1
  78. package/dist/editor/types.d.ts +1 -1
  79. package/dist/{emitter-raKkIqRp.d.ts → emitter-yaYzJOdh.d.cts} +1 -2
  80. package/dist/{emitter-raKkIqRp.d.cts → emitter-yaYzJOdh.d.ts} +1 -2
  81. package/dist/encryption/index.d.cts +1 -1
  82. package/dist/encryption/index.d.ts +1 -1
  83. package/dist/encryption/types.d.cts +1 -1
  84. package/dist/encryption/types.d.ts +1 -1
  85. package/dist/import/index.d.cts +3 -3
  86. package/dist/import/index.d.ts +3 -3
  87. package/dist/{index-DcKc3_Y1.d.cts → index-9p4O-clX.d.cts} +2033 -72
  88. package/dist/{index-DcKc3_Y1.d.ts → index-9p4O-clX.d.ts} +2033 -72
  89. package/dist/{index-CLqZfRpv.d.cts → index-B-HCh7LL.d.cts} +3 -3
  90. package/dist/{index-CxoJuIzB.d.cts → index-B0e42GnK.d.cts} +4 -3
  91. package/dist/{index-Bgu3hnMO.d.ts → index-BbXGsspe.d.ts} +4 -4
  92. package/dist/{index-B7Ogo2SK.d.ts → index-Bg9BWpIY.d.ts} +4 -3
  93. package/dist/{index-DPhGNQC5.d.cts → index-BgEu7wGk.d.cts} +2559 -7319
  94. package/dist/{index-C_A0JS9s.d.ts → index-Btft3BFn.d.ts} +29 -3
  95. package/dist/{index-DXNRd61K.d.cts → index-ByaAn_lm.d.cts} +4 -4
  96. package/dist/{index-A8udJCGv.d.ts → index-C92Ct6K5.d.ts} +178 -4
  97. package/dist/{index-B30dBBBH.d.ts → index-CBq59Aif.d.ts} +3 -3
  98. package/dist/{index-DAb1g6je.d.cts → index-CGUPsu_R.d.cts} +29 -3
  99. package/dist/{index-CLxvW_pn.d.ts → index-CIA6-x2Q.d.ts} +4 -4
  100. package/dist/{index-B2YNTI4p.d.ts → index-CeWVf3d1.d.ts} +4 -4
  101. package/dist/{index-GlHJ4j3a.d.ts → index-Cj0l_DL_.d.ts} +2559 -7319
  102. package/dist/{index-BUZ-vTRt.d.ts → index-Ck0UPKMM.d.ts} +2 -2
  103. package/dist/{index-B-HhOTVk.d.cts → index-D0ACg_Pp.d.cts} +7 -4
  104. package/dist/{index-Dx02AUpZ.d.cts → index-D8nMnVp1.d.cts} +4 -4
  105. package/dist/{index-24GpnYhn.d.cts → index-DENUPo51.d.cts} +2 -2
  106. package/dist/{index-RHYdFrfn.d.cts → index-DGjxLWZ-.d.cts} +3 -3
  107. package/dist/{index-BH1jo-bb.d.ts → index-Dse6Psvc.d.ts} +7 -4
  108. package/dist/{index-BaJ-GMa7.d.ts → index-DxcaEIhU.d.ts} +3 -3
  109. package/dist/{index-CpidrJQc.d.cts → index-OCEoQ1Y-.d.cts} +4 -4
  110. package/dist/{index-DxbqDi_0.d.cts → index-jR69kGUZ.d.cts} +178 -4
  111. package/dist/index.cjs +615 -867
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.cts +9 -9
  114. package/dist/index.d.ts +9 -9
  115. package/dist/index.js +611 -860
  116. package/dist/index.js.map +1 -1
  117. package/dist/kaiAgent/index.cjs +1 -1
  118. package/dist/kaiAgent/index.d.cts +2 -2
  119. package/dist/kaiAgent/index.d.ts +2 -2
  120. package/dist/kaiAgent/index.js +1 -1
  121. package/dist/kaiAgent/types.d.cts +2 -2
  122. package/dist/kaiAgent/types.d.ts +2 -2
  123. package/dist/{kaiAgent-De2T6G4G.cjs → kaiAgent-Q00g6S1v.cjs} +16 -1
  124. package/dist/kaiAgent-Q00g6S1v.cjs.map +1 -0
  125. package/dist/{kaiAgent-D0MoKqXe.js → kaiAgent-aqylPZHY.js} +16 -1
  126. package/dist/kaiAgent-aqylPZHY.js.map +1 -0
  127. package/dist/management/index.cjs +1 -1
  128. package/dist/management/index.d.cts +1 -1
  129. package/dist/management/index.d.ts +1 -1
  130. package/dist/management/index.js +1 -1
  131. package/dist/management/types.d.cts +1 -1
  132. package/dist/management/types.d.ts +1 -1
  133. package/dist/{management-BlMQnPNS.js → management-CIK5-Aq5.js} +14 -7
  134. package/dist/management-CIK5-Aq5.js.map +1 -0
  135. package/dist/{management-dIMrTTpI.cjs → management-Dqrc516s.cjs} +14 -7
  136. package/dist/management-Dqrc516s.cjs.map +1 -0
  137. package/dist/{metaObject-qWyZAD-5.d.ts → metaObject-AQ7wKDOu.d.ts} +2 -2
  138. package/dist/{metaObject-BsBMgWRt.d.cts → metaObject-I35_krxf.d.cts} +2 -2
  139. package/dist/metastore/index.d.cts +1 -1
  140. package/dist/metastore/index.d.ts +1 -1
  141. package/dist/metastore/types.d.cts +1 -1
  142. package/dist/metastore/types.d.ts +1 -1
  143. package/dist/microsoftGraph/index.d.cts +3 -3
  144. package/dist/microsoftGraph/index.d.ts +3 -3
  145. package/dist/microsoftGraph/types.d.cts +2 -2
  146. package/dist/microsoftGraph/types.d.ts +2 -2
  147. package/dist/{middleware-DxGv7DG8.js → middleware-DWmhthX0.js} +2 -2
  148. package/dist/middleware-DWmhthX0.js.map +1 -0
  149. package/dist/{middleware-vIaPDtQI.cjs → middleware-DYdDD4O6.cjs} +2 -2
  150. package/dist/middleware-DYdDD4O6.cjs.map +1 -0
  151. package/dist/notifications/index.d.cts +2 -2
  152. package/dist/notifications/index.d.ts +2 -2
  153. package/dist/notifications/types.d.cts +1 -1
  154. package/dist/notifications/types.d.ts +1 -1
  155. package/dist/oauth/index.d.cts +2 -2
  156. package/dist/oauth/index.d.ts +2 -2
  157. package/dist/oauth/types.d.cts +1 -1
  158. package/dist/oauth/types.d.ts +1 -1
  159. package/dist/omnisearch/index.d.cts +2 -2
  160. package/dist/omnisearch/index.d.ts +2 -2
  161. package/dist/omnisearch/types.d.cts +1 -1
  162. package/dist/omnisearch/types.d.ts +1 -1
  163. package/dist/{project-CmV1OhK4.d.ts → project-DwRvx_zN.d.ts} +3 -3
  164. package/dist/{project-F6eHCACz.d.cts → project-ERH0FTGW.d.cts} +3 -3
  165. package/dist/queryService/index.cjs +1 -1
  166. package/dist/queryService/index.d.cts +1 -1
  167. package/dist/queryService/index.d.ts +1 -1
  168. package/dist/queryService/index.js +1 -1
  169. package/dist/queryService/types.d.cts +1 -1
  170. package/dist/queryService/types.d.ts +1 -1
  171. package/dist/{queryService-C3BQ6GKW.cjs → queryService-CECWubS0.cjs} +2 -2
  172. package/dist/{queryService-C3BQ6GKW.cjs.map → queryService-CECWubS0.cjs.map} +1 -1
  173. package/dist/{queryService-DQHtHy2-.js → queryService-CIxb_mcP.js} +2 -2
  174. package/dist/{queryService-DQHtHy2-.js.map → queryService-CIxb_mcP.js.map} +1 -1
  175. package/dist/queue/index.cjs +1 -1
  176. package/dist/queue/index.d.cts +11 -4
  177. package/dist/queue/index.d.ts +11 -4
  178. package/dist/queue/index.js +1 -1
  179. package/dist/queue/types.d.cts +1 -1
  180. package/dist/queue/types.d.ts +1 -1
  181. package/dist/{queue-6cywDnA-.js → queue-BBihD5qQ.js} +2 -2
  182. package/dist/{queue-6cywDnA-.js.map → queue-BBihD5qQ.js.map} +1 -1
  183. package/dist/{queue-J2uXzXR9.cjs → queue-PmTfoniJ.cjs} +2 -2
  184. package/dist/{queue-J2uXzXR9.cjs.map → queue-PmTfoniJ.cjs.map} +1 -1
  185. package/dist/scheduler/index.d.cts +2 -2
  186. package/dist/scheduler/index.d.ts +2 -2
  187. package/dist/scheduler/types.d.cts +1 -1
  188. package/dist/scheduler/types.d.ts +1 -1
  189. package/dist/{schema-DLmBEgPM.d.cts → schema-CqzWi5cO.d.cts} +14 -4
  190. package/dist/{schema-DLmBEgPM.d.ts → schema-CqzWi5cO.d.ts} +14 -4
  191. package/dist/sdk/configurations/index.d.cts +2 -3
  192. package/dist/sdk/configurations/index.d.ts +2 -3
  193. package/dist/sdk/dataAppServer/index.cjs +3 -3
  194. package/dist/sdk/dataAppServer/index.d.cts +1 -1
  195. package/dist/sdk/dataAppServer/index.d.ts +1 -1
  196. package/dist/sdk/dataAppServer/index.js +3 -3
  197. package/dist/sdk/developerPortal/index.cjs +3 -3
  198. package/dist/sdk/developerPortal/index.cjs.map +1 -1
  199. package/dist/sdk/developerPortal/index.d.cts +178 -4
  200. package/dist/sdk/developerPortal/index.d.ts +178 -4
  201. package/dist/sdk/developerPortal/index.js +3 -3
  202. package/dist/sdk/developerPortal/index.js.map +1 -1
  203. package/dist/sdk/kaiMemory/index.d.cts +1 -1
  204. package/dist/sdk/kaiMemory/index.d.ts +1 -1
  205. package/dist/sdk/kaiMemory/types.d.cts +1 -1
  206. package/dist/sdk/kaiMemory/types.d.ts +1 -1
  207. package/dist/sdk/queryService/index.d.cts +1 -1
  208. package/dist/sdk/queryService/index.d.ts +1 -1
  209. package/dist/sdk/securityPolicy/index.d.cts +2 -2
  210. package/dist/sdk/securityPolicy/index.d.ts +2 -2
  211. package/dist/sdk/securityPolicy/types.d.cts +1 -1
  212. package/dist/sdk/securityPolicy/types.d.ts +1 -1
  213. package/dist/sdk/semanticLayer/index.d.cts +1 -1
  214. package/dist/sdk/semanticLayer/index.d.ts +1 -1
  215. package/dist/sdk/semanticLayer/types.d.cts +1 -1
  216. package/dist/sdk/semanticLayer/types.d.ts +1 -1
  217. package/dist/sdk/tag/index.d.cts +3 -3
  218. package/dist/sdk/tag/index.d.ts +3 -3
  219. package/dist/sdk/tag/types.d.cts +1 -1
  220. package/dist/sdk/tag/types.d.ts +1 -1
  221. package/dist/sdk/vault/index.d.cts +1 -1
  222. package/dist/sdk/vault/index.d.ts +1 -1
  223. package/dist/status/index.d.cts +1 -1
  224. package/dist/status/index.d.ts +1 -1
  225. package/dist/storage/index.cjs +5 -5
  226. package/dist/storage/index.d.cts +2 -3
  227. package/dist/storage/index.d.ts +2 -3
  228. package/dist/storage/index.js +3 -3
  229. package/dist/storage/types.d.cts +5 -5
  230. package/dist/storage/types.d.ts +5 -5
  231. package/dist/{storage-jLhVrKZh.cjs → storage-chxoWtAL.cjs} +44 -56
  232. package/dist/storage-chxoWtAL.cjs.map +1 -0
  233. package/dist/{storage-Bw-HSnPp.js → storage-o9teEKl_.js} +42 -54
  234. package/dist/storage-o9teEKl_.js.map +1 -0
  235. package/dist/{store-2OyH1XOP.cjs → store-7xlVu4qF.cjs} +3 -14
  236. package/dist/store-7xlVu4qF.cjs.map +1 -0
  237. package/dist/{store-HP0zRcLz.js → store-DDUzPeCm.js} +3 -14
  238. package/dist/store-DDUzPeCm.js.map +1 -0
  239. package/dist/stream/index.d.cts +2 -2
  240. package/dist/stream/index.d.ts +2 -2
  241. package/dist/stream/types.d.cts +1 -1
  242. package/dist/stream/types.d.ts +1 -1
  243. package/dist/syncActions/index.d.cts +2 -2
  244. package/dist/syncActions/index.d.ts +2 -2
  245. package/dist/syncActions/types.d.cts +1 -1
  246. package/dist/syncActions/types.d.ts +1 -1
  247. package/dist/telemetry/index.d.cts +2 -2
  248. package/dist/telemetry/index.d.ts +2 -2
  249. package/dist/telemetry/types.d.cts +1 -1
  250. package/dist/telemetry/types.d.ts +1 -1
  251. package/dist/{transientRetries-BORv47mH.js → transientRetries-dssygpwU.js} +2 -2
  252. package/dist/{transientRetries-BORv47mH.js.map → transientRetries-dssygpwU.js.map} +1 -1
  253. package/dist/{transientRetries-CBorl4Ue.cjs → transientRetries-yVaQgKqP.cjs} +2 -2
  254. package/dist/{transientRetries-CBorl4Ue.cjs.map → transientRetries-yVaQgKqP.cjs.map} +1 -1
  255. package/dist/{types-LOf_GCej.d.cts → types-B1kernzE.d.cts} +2 -2
  256. package/dist/{types-Cvbcjdgf.d.ts → types-BBmS7-IS.d.ts} +151 -4
  257. package/dist/{types-DaRxZt3v.d.ts → types-BJyWTgXX.d.ts} +2 -2
  258. package/dist/{types-CnKiVVb8.d.ts → types-BPNFTA63.d.cts} +21 -7
  259. package/dist/{types-BJRRAQ9R.d.cts → types-BPSExpye.d.cts} +244 -4
  260. package/dist/{types-Cg_66Toy.d.ts → types-BiXonOK6.d.ts} +2 -2
  261. package/dist/{types-CNDemlfn.d.cts → types-BimRBONo.d.cts} +3 -3
  262. package/dist/{types-CrXoqs8E.d.cts → types-BuEC58u3.d.cts} +2 -2
  263. package/dist/{types-BnkHyxdp.d.ts → types-BzHyi99r.d.cts} +5 -3
  264. package/dist/{types-2CMPwArl.d.ts → types-C4T_2JdN.d.cts} +40 -27
  265. package/dist/{types-lZRyNwOH.d.ts → types-C53aKnWt.d.ts} +2 -2
  266. package/dist/{types-6oLbURTK.d.cts → types-CEjgqmr2.d.cts} +2 -2
  267. package/dist/{types-BEEGI4aq.d.ts → types-CGtpwTJk.d.ts} +2 -2
  268. package/dist/{types-B_yv00AL.d.ts → types-CH1uguug.d.cts} +2 -163
  269. package/dist/{types-DMEl2iet.d.ts → types-CP8-CssY.d.ts} +2 -2
  270. package/dist/{types-DgAMVyiT.d.ts → types-CPQ6RkiZ.d.ts} +244 -4
  271. package/dist/{types-EdL0Eb0B.d.ts → types-CPwofeyq.d.ts} +3 -3
  272. package/dist/{types-CFuT8zr3.d.cts → types-CQAEOq-K.d.cts} +2 -2
  273. package/dist/{types-DslO1S5E.d.cts → types-CVWoP_PC.d.cts} +3 -3
  274. package/dist/{types-BqJycQNM.d.cts → types-CbM2MApW.d.cts} +2 -2
  275. package/dist/{types-BDGkMVWf.d.cts → types-CbOfT6lb.d.ts} +21 -7
  276. package/dist/{types-B6OG1lLf.d.cts → types-CcPpqVhm.d.cts} +2 -2
  277. package/dist/{types-D2J3SaoY.d.ts → types-CeqpzbBH.d.ts} +2 -2
  278. package/dist/{types-C_JO7FI9.d.cts → types-CjJYZaMO.d.cts} +2 -2
  279. package/dist/{types-D0Gqu-Xz.d.cts → types-CjP8RcFN.d.cts} +2 -2
  280. package/dist/{types-CUovU--e.d.ts → types-CjfsPtwk.d.ts} +2 -2
  281. package/dist/{types-DPFG6AAA.d.ts → types-CnSBLcZB.d.ts} +163 -3
  282. package/dist/{types-D4knWlwr.d.ts → types-CsXLdnfV.d.ts} +2 -2
  283. package/dist/{types-C3Kf_ggm.d.cts → types-CzAh5-0z.d.cts} +2 -2
  284. package/dist/{types-D6Fbf_y3.d.ts → types-D0F_c5KI.d.ts} +4 -4
  285. package/dist/{types-DykEfF2N.d.cts → types-D3L3CqKl.d.cts} +151 -4
  286. package/dist/{types--mz2z0Zm.d.cts → types-D4oIei5M.d.cts} +163 -3
  287. package/dist/{types-Cm1iOHE5.d.cts → types-D6ilG8sC.d.cts} +3 -3
  288. package/dist/{types-DtS7qAdz.d.cts → types-DEGkXcw2.d.ts} +5 -3
  289. package/dist/{types-DQguGTlM.d.cts → types-DEhAcO1Z.d.cts} +2 -2
  290. package/dist/{types-CuYaiy4R.d.cts → types-DaIfg9Mb.d.cts} +4 -4
  291. package/dist/{types-ByKSM08P.d.ts → types-DhofEmWy.d.ts} +2 -2
  292. package/dist/{types-B5FgsIiY.d.ts → types-Dp61pYgP.d.ts} +3 -3
  293. package/dist/{types-BhGr9OQ4.d.ts → types-Dteot3tT.d.ts} +757 -112
  294. package/dist/{types-3ZE32k8V.d.cts → types-K-JISUUI.d.cts} +757 -112
  295. package/dist/{types-CjqFLXVx.d.cts → types-TywAc1ow.d.ts} +40 -27
  296. package/dist/{types-DiXeO0yB.d.ts → types-UBpth6_9.d.ts} +2 -2
  297. package/dist/{types-D0BOES7q.d.cts → types-Vw-tduOH.d.ts} +2 -163
  298. package/dist/{types-CF5ZROX5.d.cts → types-ZyLTqgpa.d.cts} +2 -2
  299. package/dist/{types-BmcZyKgM.d.cts → types-aylD1zQz.d.cts} +3 -3
  300. package/dist/{types-CbPO9cGq.d.cts → types-fYY4q7dC.d.cts} +2 -2
  301. package/dist/{types-Foy0RnqF.d.ts → types-jYn3e3Du.d.ts} +3 -3
  302. package/dist/{types-p6UYqJo_.d.ts → types-qXqJRPHj.d.ts} +2 -2
  303. package/dist/{types-B452bFfS.d.ts → types-r-Qa3y8e.d.ts} +2 -2
  304. package/dist/{types-DhE7iY90.d.ts → types-z82j5aNW.d.ts} +3 -3
  305. package/dist/{collectByCursor-2-8SuJ-8.js → validateConnectionStatus-DgJwuEy9.js} +32 -22
  306. package/dist/validateConnectionStatus-DgJwuEy9.js.map +1 -0
  307. package/dist/{collectByCursor-D58__WD1.cjs → validateConnectionStatus-DpYRsU-e.cjs} +37 -21
  308. package/dist/validateConnectionStatus-DpYRsU-e.cjs.map +1 -0
  309. package/dist/vault/index.d.cts +1 -1
  310. package/dist/vault/index.d.ts +1 -1
  311. package/dist/vault/types.d.cts +1 -1
  312. package/dist/vault/types.d.ts +1 -1
  313. package/package.json +2 -2
  314. package/surface/apps.md +8 -3
  315. package/surface/auth.md +3 -2
  316. package/surface/chat.md +3 -3
  317. package/surface/dataScience.md +2 -2
  318. package/surface/kaiAgent.md +4 -3
  319. package/surface/management.md +4 -4
  320. package/surface/queue.md +7 -7
  321. package/surface/storage.md +27 -26
  322. package/dist/ManagementSessionMintError-BMHDcEqV.js.map +0 -1
  323. package/dist/ManagementSessionMintError-Bc9bc7Ai.cjs.map +0 -1
  324. package/dist/apps-BN7fWtSm.js.map +0 -1
  325. package/dist/apps-C1x5IKNQ.cjs.map +0 -1
  326. package/dist/authClient-B_Mb4Vzs.js.map +0 -1
  327. package/dist/authClient-C9QqhT2M.cjs.map +0 -1
  328. package/dist/collectByCursor-2-8SuJ-8.js.map +0 -1
  329. package/dist/collectByCursor-D58__WD1.cjs.map +0 -1
  330. package/dist/constants-HccvU5kx.js.map +0 -1
  331. package/dist/constants-V9hAyPTo.cjs.map +0 -1
  332. package/dist/developerPortalClient-BcK9F-Fs.cjs.map +0 -1
  333. package/dist/developerPortalClient-CzCJ5sE3.js.map +0 -1
  334. package/dist/index-C6FI_Lc7.d.ts +0 -10
  335. package/dist/index-CmtqbTse.d.cts +0 -10
  336. package/dist/kaiAgent-D0MoKqXe.js.map +0 -1
  337. package/dist/kaiAgent-De2T6G4G.cjs.map +0 -1
  338. package/dist/management-BlMQnPNS.js.map +0 -1
  339. package/dist/management-dIMrTTpI.cjs.map +0 -1
  340. package/dist/middleware-DxGv7DG8.js.map +0 -1
  341. package/dist/middleware-vIaPDtQI.cjs.map +0 -1
  342. package/dist/storage-Bw-HSnPp.js.map +0 -1
  343. package/dist/storage-jLhVrKZh.cjs.map +0 -1
  344. package/dist/store-2OyH1XOP.cjs.map +0 -1
  345. package/dist/store-HP0zRcLz.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,50 +1,50 @@
1
1
  import { t as UserError } from "./UserError-BxoOJJ_u.js";
2
2
  import { _ as HttpStatus, a as isTimeoutError, d as normalizeBaseUrl, h as CREDENTIAL_HEADERS, i as isFetchClientError, n as isAbortError, o as HttpContentType, p as ApiError, r as isApiError, s as HttpHeader, v as KeboolaHttpHeader, x as redactHeaders, y as REDACTED } from "./createFetchClient-Dc_ZMuq7.js";
3
- import { a as isHtmlResponseError, i as HtmlResponseError, n as nextCursorOf, t as collectByCursor } from "./collectByCursor-2-8SuJ-8.js";
4
- import { a as series, c as ServiceUnavailableError, d as isManageError, f as manageErrorCode, l as retryAfterSeconds, o as StorageJobError, s as isStorageJobError, t as createStorageClient, u as readableReason } from "./storage-Bw-HSnPp.js";
5
- import { n as ManagementClientAuthError, t as ManagementSessionMintError } from "./ManagementSessionMintError-BMHDcEqV.js";
3
+ import { a as HtmlResponseError, i as nextCursorOf, n as collectByCursor, o as isHtmlResponseError, r as iterateByCursor } from "./validateConnectionStatus-DgJwuEy9.js";
4
+ import { a as series, c as ServiceUnavailableError, d as isManageError, f as manageErrorCode, l as retryAfterSeconds, o as StorageJobError, s as isStorageJobError, t as createStorageClient, u as readableReason } from "./storage-o9teEKl_.js";
5
+ import { n as ManagementClientAuthError, t as ManagementSessionMintError } from "./ManagementSessionMintError-KUX3utTV.js";
6
6
  import { i as isQueryJobError, n as isRowLevelSecurityError, r as QueryJobError, t as RowLevelSecurityError } from "./RowLevelSecurityError-CObFqj3E.js";
7
7
  import { n as isQueueJobError, t as QueueJobError } from "./QueueJobError-BJNUINXW.js";
8
8
  import { n as isSyncActionError, t as SyncActionError } from "./SyncActionError-DuGcDbkd.js";
9
9
  import { i as parseOrThrow, n as formatValidationIssues, r as isValidationError, t as ValidationError } from "./ValidationError-BsdFDGY2.js";
10
10
  import { t as createGenericFetchClient } from "./createGenericFetchClient-Ba4E4T-Y.js";
11
11
  import { t as createImportClient } from "./import-DxN6CJzJ.js";
12
- import { t as createAuthClient } from "./authClient-B_Mb4Vzs.js";
13
12
  import { t as collectByOffset } from "./collectByOffset-i8Tdoze7.js";
14
13
  import { t as concurrent } from "./concurrent-BtsT10Xe.js";
15
14
  import { t as dedupe } from "./dedupe-Bu0d2i_w.js";
16
- import { a as poller, c as Result, d as delay, i as failureOf, l as asError, n as jobStatus, o as clamp, r as emitter, s as finiteOr, u as lazy } from "./transientRetries-BORv47mH.js";
17
- import { n as createEmitter, t as createStore } from "./store-HP0zRcLz.js";
15
+ import { a as poller, c as Result, d as delay, i as failureOf, l as asError, n as jobStatus, o as clamp, r as emitter, s as finiteOr, u as lazy } from "./transientRetries-dssygpwU.js";
16
+ import { n as createEmitter, t as createStore } from "./store-DDUzPeCm.js";
18
17
  import { n as keboolaUID, t as createTagSdk } from "./tag-BwjbG3tT.js";
19
18
  import { t as generateUUID } from "./generateUUID-DE9sNyJF.js";
20
19
  import { t as isPlainObject } from "./isPlainObject-BxsT8_t2.js";
21
20
  import { n as isEmptyDeep, t as schemaGuidedMerge } from "./schemaGuidedMerge-DFNqj9Nz.js";
22
- import { n as isManagementClientAuthError, r as isManagementSessionMintError, t as createManagementClient } from "./management-BlMQnPNS.js";
23
- import { t as ServiceId } from "./serviceIds-RAVtP4nK.js";
21
+ import { t as createAuthClient } from "./authClient-BKGpJI5L.js";
22
+ import { n as isUnauthorized, t as createBearerAuthMiddleware } from "./middleware-DWmhthX0.js";
24
23
  import { i as createKaiMemorySdk } from "./kaiMemory-B1wIwH8Y.js";
25
24
  import { i as createSemanticLayerSdk } from "./semanticLayer-Btj1Qy9O.js";
26
25
  import { createVaultSdk } from "./sdk/vault/index.js";
27
26
  import { createAiClient } from "./ai/index.js";
28
- import { n as parseLogLines, t as createAppsClient } from "./apps-BN7fWtSm.js";
27
+ import { n as parseLogLines, t as createAppsClient } from "./apps-DDcguJ1i.js";
29
28
  import { createBillingClient } from "./billing/index.js";
30
29
  import { createChatClient } from "./chat/index.js";
31
30
  import { t as createComponentsMcpClient } from "./componentsMcp-CAmrCpzV.js";
32
31
  import { createDataScienceClient } from "./dataScience/index.js";
33
32
  import { createEditorClient } from "./editor/index.js";
34
33
  import { createEncryptionClient } from "./encryption/index.js";
35
- import { t as createKaiAgentClient } from "./kaiAgent-D0MoKqXe.js";
34
+ import { t as createKaiAgentClient } from "./kaiAgent-aqylPZHY.js";
36
35
  import { t as createMetastoreClient } from "./metastore-CkqFnEfu.js";
37
36
  import { createNotificationsClient } from "./notifications/index.js";
38
37
  import { n as createOauthClient } from "./oauth-Fri6IthS.js";
39
38
  import { createOmnisearchClient } from "./omnisearch/index.js";
40
- import { t as createQueryServiceClient } from "./queryService-DQHtHy2-.js";
41
- import { t as createQueueClient } from "./queue-6cywDnA-.js";
39
+ import { t as createQueryServiceClient } from "./queryService-CIxb_mcP.js";
40
+ import { t as createQueueClient } from "./queue-BBihD5qQ.js";
42
41
  import { createSchedulerClient } from "./scheduler/index.js";
43
42
  import { createStreamClient } from "./stream/index.js";
44
43
  import { t as createSyncActionsClient } from "./syncActions-W98Jme2Z.js";
44
+ import { t as ServiceId } from "./serviceIds-RAVtP4nK.js";
45
45
  import { createTelemetryClient } from "./telemetry/index.js";
46
46
  import { createVaultClient } from "./vault/index.js";
47
- import { n as isUnauthorized, t as createBearerAuthMiddleware } from "./middleware-DxGv7DG8.js";
47
+ import { n as isManagementClientAuthError, r as isManagementSessionMintError, t as createManagementClient } from "./management-CIK5-Aq5.js";
48
48
  import { t as createProject } from "./project-aAVAOcmx.js";
49
49
  import { n as createQueryServiceSdk } from "./queryService-DE_yE_S4.js";
50
50
  import * as z$1 from "zod";
@@ -58,24 +58,14 @@ const KeboolaErrorType = {
58
58
  NotAuthenticated: "not-authenticated",
59
59
  SignInEnded: "sign-in-ended",
60
60
  AlreadyAuthenticated: "already-authenticated",
61
- NoStorageToken: "no-storage-token",
62
- NoManagementToken: "no-management-token",
63
- MissingProject: "missing-project",
64
- NotBearer: "not-bearer",
65
- NotReady: "not-ready",
66
- InvalidBuildTransition: "invalid-build-transition"
61
+ NotReady: "not-ready"
67
62
  };
68
63
  const MESSAGES = {
69
- [KeboolaErrorType.Unconfigured]: "The session is not configured — set a baseUrl first.",
64
+ [KeboolaErrorType.Unconfigured]: "This stack has not been selected — call session.stack.select(baseUrl) first.",
70
65
  [KeboolaErrorType.NotAuthenticated]: "The session is not authenticated — sign in first.",
71
66
  [KeboolaErrorType.SignInEnded]: "The sign-in this operation started under has ended — its result belongs to nobody.",
72
- [KeboolaErrorType.AlreadyAuthenticated]: "The session is already authenticated — reset before authenticating again.",
73
- [KeboolaErrorType.NoStorageToken]: "No storage token — authenticate the storage realm first.",
74
- [KeboolaErrorType.NoManagementToken]: "No management token — authenticate the management realm first.",
75
- [KeboolaErrorType.MissingProject]: "A bearer storage session requires a project — call setProject(projectId) first.",
76
- [KeboolaErrorType.NotBearer]: "This operation requires a bearer (OAuth) session.",
77
- [KeboolaErrorType.NotReady]: "The client is not ready — authenticate the storage realm first.",
78
- [KeboolaErrorType.InvalidBuildTransition]: "Invalid storage build transition — the build goes idle → initializing → ready | failed."
67
+ [KeboolaErrorType.AlreadyAuthenticated]: "This stack is already signed in — sign out or use auth.replace first.",
68
+ [KeboolaErrorType.NotReady]: "The stack index has not loaded yet."
79
69
  };
80
70
  var KeboolaError = class KeboolaError extends Error {
81
71
  type;
@@ -140,109 +130,6 @@ const coalesce = (task) => {
140
130
  return waiter.promise;
141
131
  };
142
132
  };
143
- // src/utils/store/derivedStore.ts
144
- const isPlainObjectOrArray = (value) => {
145
- if (Array.isArray(value)) return true;
146
- const proto = Object.getPrototypeOf(value);
147
- return proto === Object.prototype || proto === null;
148
- };
149
- const shallowEqual = (a, b) => {
150
- if (Object.is(a, b)) return true;
151
- if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
152
- if (!isPlainObjectOrArray(a) || !isPlainObjectOrArray(b)) return false;
153
- const aKeys = Object.keys(a);
154
- const bKeys = Object.keys(b);
155
- return aKeys.length === bKeys.length && aKeys.every((key) => Object.is(a[key], b[key]));
156
- };
157
- const createDerivedStore = ({ source, dependsOn, build, keyEquals = shallowEqual }) => {
158
- let key = dependsOn(source.get());
159
- const store = createStore(build(key));
160
- const unsubscribe = source.subscribe((state) => {
161
- const next = dependsOn(state);
162
- if (keyEquals(key, next)) return;
163
- key = next;
164
- store.set(build(next));
165
- });
166
- const get = store.get;
167
- const subscribe = store.subscribe;
168
- const dispose = () => {
169
- unsubscribe();
170
- store.dispose();
171
- };
172
- return {
173
- get,
174
- subscribe,
175
- dispose
176
- };
177
- };
178
- // src/utils/store/derivedAsyncStore.ts
179
- const createDerivedAsyncStore = ({ source, dependsOn, build, keyEquals = shallowEqual }) => {
180
- const store = createStore({ state: "idle" });
181
- let currentKey = null;
182
- let generation = 0;
183
- let controller = null;
184
- const run = (key) => {
185
- controller?.abort();
186
- controller = new AbortController();
187
- const runGeneration = ++generation;
188
- store.set({ state: "pending" });
189
- build(key, controller.signal).then((value) => {
190
- if (runGeneration === generation) store.set({
191
- state: "ready",
192
- value
193
- });
194
- }, (error) => {
195
- if (runGeneration === generation) store.set({
196
- state: "errored",
197
- error
198
- });
199
- });
200
- };
201
- const sync = (state) => {
202
- const next = dependsOn(state);
203
- if (next === null) {
204
- if (currentKey === null) return;
205
- controller?.abort();
206
- controller = null;
207
- generation += 1;
208
- currentKey = null;
209
- store.set({ state: "idle" });
210
- return;
211
- }
212
- if (currentKey !== null && keyEquals(currentKey, next)) return;
213
- currentKey = next;
214
- run(next);
215
- };
216
- sync(source.get());
217
- const unsubscribe = source.subscribe(sync);
218
- const get = store.get;
219
- const subscribe = store.subscribe;
220
- const dispose = () => {
221
- controller?.abort();
222
- unsubscribe();
223
- store.dispose();
224
- };
225
- const readable = {
226
- get,
227
- subscribe,
228
- dispose
229
- };
230
- const settled = () => new Promise((resolve) => {
231
- let unsubscribeSettled = () => {};
232
- const check = (state) => {
233
- if (state.state === "ready" || state.state === "errored") {
234
- unsubscribeSettled();
235
- resolve(state);
236
- }
237
- };
238
- unsubscribeSettled = store.subscribe(check);
239
- check(store.get());
240
- });
241
- return {
242
- store: readable,
243
- settled
244
- };
245
- };
246
133
  // src/utils/async/poll/registry.ts
247
134
  const DEFAULT_LIMIT = 50;
248
135
  const isFinished = ({ snapshot }) => snapshot.state !== "idle" && snapshot.state !== "requesting" && snapshot.state !== "polling";
@@ -454,721 +341,175 @@ const createPersistor = ({ storage = createNullStorage(), key, schema, defaultVa
454
341
  locked
455
342
  };
456
343
  };
457
- // src/serviceClientRegistry/utils.ts
458
- const isBuiltInProperty = (property) => typeof property === "symbol" || property === "then" || property === "constructor" || property === "toString" || property === "valueOf";
459
- /**
460
- * Creates a dummy client that intercepts method calls and invokes the provided onCall callback.
461
- */
462
- const createDummyClient = ({ onCall }) => {
463
- const createProxy = (path = []) => new Proxy(() => {}, {
464
- get: (_target, prop) => {
465
- if (isBuiltInProperty(prop)) return void 0;
466
- return createProxy([...path, prop]);
467
- },
468
- apply: (_target, _thisArgs, args) => onCall(path, args)
469
- });
470
- return createProxy();
471
- };
472
- // src/serviceClientRegistry/createServiceClientRegistry.ts
473
- const createServiceClientRegistry = () => ({ getServiceBaseUrl, onUnavailable }) => {
474
- const dummy = (serviceId, clientName) => createDummyClient({ onCall: (path, args) => {
475
- onUnavailable?.({
476
- serviceId,
477
- path,
478
- args,
479
- clientName
480
- });
481
- } });
482
- const configs = [];
483
- const resolveClient = ({ serviceId, clientFn, clientName }) => {
484
- const serviceBaseUrl = getServiceBaseUrl(serviceId);
485
- return serviceBaseUrl ? clientFn(serviceBaseUrl) : dummy(serviceId, clientName);
486
- };
487
- const registry = {
488
- add: (config) => {
489
- configs.push(config);
490
- return registry;
491
- },
492
- build: () => {
493
- const clientMap = {};
494
- const clientMeta = [];
495
- configs.forEach((config) => {
496
- clientMap[config.clientName] = resolveClient(config);
497
- clientMeta.push({
498
- clientName: config.clientName,
499
- serviceId: config.serviceId,
500
- isAvailable: !!getServiceBaseUrl(config.serviceId)
501
- });
502
- });
503
- return {
504
- client: clientMap,
505
- meta: clientMeta
506
- };
507
- }
508
- };
509
- return registry;
510
- };
511
- // src/keboola/createApi.ts
512
- const createApi = (state) => new Proxy({}, { get(_target, property) {
513
- if (isBuiltInProperty(property)) return void 0;
514
- if (property === "auth") {
515
- const authClient = state.getAuthClient();
516
- assert$1(authClient, KeboolaErrorType.Unconfigured);
517
- return authClient;
518
- }
519
- if (property === "management") {
520
- const management = state.getManagementClient();
521
- assert$1(management, KeboolaErrorType.NoManagementToken);
522
- return management;
523
- }
524
- const clients = state.getProjectClients();
525
- assert$1(clients, KeboolaErrorType.NotReady);
526
- return clients[property];
527
- } });
528
344
  // src/keboola/createMiddlewareFor.ts
529
345
  const createMiddlewareFor = (middlewares) => {
530
346
  return (target, baseline = []) => {
531
347
  if (Array.isArray(middlewares)) return [...baseline, ...middlewares];
532
- const all = middlewares?.all ?? [];
533
- const targeted = middlewares?.[target] ?? [];
534
- return [
535
- ...baseline,
536
- ...all,
537
- ...targeted
538
- ];
348
+ return [...baseline, ...middlewares?.[target] ?? []];
539
349
  };
540
350
  };
541
- // src/keboola/legacy/createConfig.ts
542
- const createConfig = () => {
543
- const store = createStore({
544
- baseUrl: null,
545
- sapiToken: null,
546
- managementToken: null
547
- });
548
- const setBaseUrl = (baseUrl) => {
549
- store.set({
550
- ...store.get(),
551
- baseUrl
351
+ // src/keboola/state/auth.ts
352
+ const grantOf = (credential) => credential.type === "token" ? {
353
+ type: "token",
354
+ refreshToken: credential.refreshToken
355
+ } : {
356
+ type: "cookie",
357
+ sessionId: credential.sessionId
358
+ };
359
+ const stamped = (input) => ({
360
+ ...input,
361
+ issuedAt: Date.now()
362
+ });
363
+ const credentialOf = (auth) => auth.status === "authenticated" ? Result.success(auth.credential) : Result.failure(new KeboolaError(KeboolaErrorType.NotAuthenticated));
364
+ /**
365
+ * The stack's credential and its sign-in pin.
366
+ *
367
+ * - `epoch` moves on `authenticate` and `signOut` and never on a rotation, so it is exactly "which
368
+ * sign-in is this" — what an in-flight exchange compares itself against.
369
+ */
370
+ const createAuth = (stacks) => {
371
+ const expired = /* @__PURE__ */ new Set();
372
+ const requireCredential = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => credentialOf(stack.auth));
373
+ const requireUnauthenticated = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.auth.status === "authenticated" ? Result.failure(new KeboolaError(KeboolaErrorType.AlreadyAuthenticated)) : Result.success(stack));
374
+ const requireAnonymous = (baseUrl) => Result.andThen(requireUnauthenticated(baseUrl), (stack) => stack.auth.status === "restoring" ? Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" is already being restored`)) : Result.success(stack));
375
+ const requireRestoring = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.auth.status === "restoring" ? Result.success(stack) : Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" is not being restored`)));
376
+ const startRestore = (baseUrl) => Result.map(requireAnonymous(baseUrl), (stack) => stacks.set({
377
+ ...stack,
378
+ auth: { status: "restoring" }
379
+ }));
380
+ const cancelRestore = (baseUrl) => Result.map(requireRestoring(baseUrl), (stack) => stacks.set({
381
+ ...stack,
382
+ auth: { status: "anonymous" }
383
+ }));
384
+ const authenticate = (baseUrl, input) => Result.map(requireUnauthenticated(baseUrl), (stack) => {
385
+ expired.delete(baseUrl);
386
+ return stacks.set({
387
+ ...stack,
388
+ epoch: stack.epoch + 1,
389
+ auth: {
390
+ status: "authenticated",
391
+ credential: stamped(input)
392
+ },
393
+ retained: null
552
394
  });
553
- };
554
- const authenticate = (tokens) => {
555
- const current = store.get();
556
- store.set({
557
- ...current,
558
- sapiToken: tokens.sapiToken ?? current.sapiToken,
559
- managementToken: tokens.managementToken ?? current.managementToken
395
+ });
396
+ const applyRefresh = (baseUrl, input) => Result.andThen(requireCredential(baseUrl), (credential) => credential.type !== input.type ? Result.failure(/* @__PURE__ */ new Error(`A ${credential.type} grant cannot become ${input.type}`)) : Result.map(stacks.get(baseUrl), (stack) => stacks.set({
397
+ ...stack,
398
+ auth: {
399
+ status: "authenticated",
400
+ credential: stamped(input)
401
+ }
402
+ })));
403
+ const forceExpire = (baseUrl) => Result.andThen(requireCredential(baseUrl), (credential) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
404
+ ...stack,
405
+ auth: {
406
+ status: "authenticated",
407
+ credential: {
408
+ ...credential,
409
+ issuedAt: Date.now() - credential.expiresIn * 1e3
410
+ }
411
+ }
412
+ })));
413
+ const signOut = (baseUrl, { retain = false } = {}) => Result.map(stacks.get(baseUrl), (stack) => {
414
+ const retained = retain ? Result.unwrapOr(Result.map(credentialOf(stack.auth), (credential) => ({ grant: grantOf(credential) })), stack.retained) : null;
415
+ return stacks.set({
416
+ ...stack,
417
+ epoch: stack.epoch + 1,
418
+ auth: { status: "anonymous" },
419
+ retained
560
420
  });
561
- };
562
- const getStorageToken = () => store.get().sapiToken ?? "";
563
- const setStorageToken = (sapiToken) => store.set({
564
- ...store.get(),
565
- sapiToken
566
421
  });
567
- /** Current state, for diagnostics. */
568
- const debug = () => store.get();
422
+ const retain = (baseUrl, retained) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
423
+ ...stack,
424
+ retained
425
+ }));
426
+ const dropRetained = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
427
+ ...stack,
428
+ retained: null
429
+ }));
430
+ const requireRetained = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.retained ? Result.success(stack.retained) : Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" retains no credential`)));
431
+ const notifyExpired = (baseUrl) => {
432
+ if (expired.has(baseUrl)) return false;
433
+ expired.add(baseUrl);
434
+ return true;
435
+ };
436
+ const getEpoch = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stack.epoch);
437
+ const getAccessToken = (baseUrl) => Result.unwrapOr(Result.map(requireCredential(baseUrl), ({ accessToken }) => accessToken), null);
569
438
  return {
570
- store,
571
- setBaseUrl,
439
+ startRestore,
440
+ cancelRestore,
572
441
  authenticate,
573
- getStorageToken,
574
- setStorageToken,
575
- debug
442
+ applyRefresh,
443
+ forceExpire,
444
+ signOut,
445
+ retain,
446
+ dropRetained,
447
+ requireRetained,
448
+ notifyExpired,
449
+ requireCredential,
450
+ getEpoch,
451
+ getAccessToken
576
452
  };
577
453
  };
578
- // src/domain/stack.ts
579
- const isServiceId = (id) => Object.values(ServiceId).includes(id);
580
- const SERVICE_URL_OVERRIDES = { "kai-assistant": (url) => `${url}/api` };
581
- const createStack = ({ stackInfo, clientServiceUrls }) => {
582
- const { services, components, features, ...infoRest } = stackInfo;
583
- const serviceMap = new Map(services.map((service) => {
584
- if (!isServiceId(service.id)) return [service.id, service.url];
585
- const devOverride = clientServiceUrls?.[service.id]?.(service.url);
586
- const prodOverride = SERVICE_URL_OVERRIDES[service.id]?.(service.url);
587
- const url = devOverride ?? prodOverride ?? service.url;
588
- return [service.id, url];
589
- }));
590
- const componentMap = new Map(components.map((component) => [component.id, component]));
591
- const featureSet = new Set(features);
592
- const hasFeature = (...feature) => {
593
- if (feature.length === 0) return false;
594
- return feature.every((x) => featureSet.has(x));
454
+ // src/keboola/state/stacks.ts
455
+ const newStack = (baseUrl) => ({
456
+ baseUrl,
457
+ context: "idle",
458
+ epoch: 0,
459
+ auth: { status: "anonymous" },
460
+ retained: null
461
+ });
462
+ /** One entry per stack, and the verbs that open and select them. */
463
+ const createStacks = (store) => {
464
+ const get = (baseUrl) => {
465
+ const stack = store.get().stacks[baseUrl];
466
+ return stack ? Result.success(stack) : Result.failure(new KeboolaError(KeboolaErrorType.Unconfigured));
595
467
  };
596
- const hasComponent = (...componentId) => {
597
- if (componentId.length === 0) return false;
598
- return componentId.every((x) => componentMap.has(x));
468
+ const set = (stack) => {
469
+ const state = store.get();
470
+ store.set({
471
+ ...state,
472
+ stacks: {
473
+ ...state.stacks,
474
+ [stack.baseUrl]: stack
475
+ }
476
+ });
477
+ return stack;
599
478
  };
600
- const getComponent = (componentId) => componentMap.get(componentId) ?? null;
601
- const hasService = (serviceId) => serviceMap.has(serviceId);
602
- const getServiceUrl = (serviceId) => serviceMap.get(serviceId) ?? null;
479
+ const ensure = (baseUrl) => {
480
+ const existing = get(baseUrl);
481
+ if (existing.success) return existing.data;
482
+ return set(newStack(baseUrl));
483
+ };
484
+ const getActive = () => {
485
+ const { active } = store.get();
486
+ const stack = get(active);
487
+ if (!stack.success) throw new Error(`The active stack has no row: ${active}`);
488
+ return stack.data;
489
+ };
490
+ const select = (baseUrl) => {
491
+ const stack = ensure(baseUrl);
492
+ const state = store.get();
493
+ if (state.active !== baseUrl) store.set({
494
+ ...state,
495
+ active: baseUrl
496
+ });
497
+ return stack;
498
+ };
499
+ const updateContext = (baseUrl, context) => Result.map(get(baseUrl), (stack) => set({
500
+ ...stack,
501
+ context
502
+ }));
603
503
  return {
604
- ...infoRest,
605
- services,
606
- features,
607
- components,
608
- hasFeature,
609
- getServiceUrl,
610
- hasService,
611
- getComponent,
612
- hasComponent
504
+ get,
505
+ set,
506
+ ensure,
507
+ getActive,
508
+ select,
509
+ updateContext
613
510
  };
614
511
  };
615
- // src/sdks/variables/variablesSdk.ts
616
- const VARIABLES_COMPONENT_ID = "keboola.variables";
617
- /** Union the definitions by name; on a name conflict the target's definition is kept. */
618
- const mergeVariableDefinitions = (target, source) => {
619
- const targetNames = new Set(target.map((definition) => definition.name));
620
- return [...target, ...source.filter((definition) => !targetNames.has(definition.name))];
621
- };
622
- /** Add values missing in the target; on a name conflict the value is updated to the source's. */
623
- const mergeVariableValues = (target, source) => {
624
- const sourceByName = new Map(source.map((value) => [value.name, value.value]));
625
- const targetNames = new Set(target.map((value) => value.name));
626
- return [...target.map((value) => sourceByName.has(value.name) ? {
627
- ...value,
628
- value: sourceByName.get(value.name)
629
- } : value), ...source.filter((value) => !targetNames.has(value.name))];
630
- };
631
- /**
632
- * Orchestration for `keboola.variables` configs: copy a config, or merge two configs into a fresh
633
- * one (union definitions, upsert values — source wins on a name conflict). Each result is a brand
634
- * new config + values row, so the caller can reference it without sharing lineage with the source.
635
- */
636
- const createVariablesSdk = ({ storageClient }) => {
637
- const configs = storageClient.configurations;
638
- const rows = storageClient.configurationRows;
639
- const readVariables = async (configId, valuesRowId, branchId) => {
640
- const config = await configs.getConfiguration({
641
- componentId: VARIABLES_COMPONENT_ID,
642
- configId,
643
- branchId
644
- });
645
- const row = config.rows.find((candidate) => candidate.id === valuesRowId) ?? config.rows[0];
646
- const rawDefinitions = config.configuration?.variables;
647
- const rawValues = row?.configuration?.values;
648
- return {
649
- definitions: Array.isArray(rawDefinitions) ? rawDefinitions : [],
650
- values: Array.isArray(rawValues) ? rawValues : []
651
- };
652
- };
653
- const createVariables = async (definitions, values, branchId) => {
654
- const config = await configs.createConfiguration({
655
- branchId,
656
- componentId: VARIABLES_COMPONENT_ID,
657
- name: "Variables definition",
658
- configuration: { variables: definitions }
659
- });
660
- try {
661
- const row = await rows.createConfigurationRow({
662
- branchId: String(branchId),
663
- componentId: VARIABLES_COMPONENT_ID,
664
- configurationId: config.id,
665
- name: "Default values",
666
- configuration: { values }
667
- });
668
- return {
669
- variablesId: config.id,
670
- variablesValuesId: row.id
671
- };
672
- } catch (error) {
673
- await configs.deleteConfiguration({
674
- branchId,
675
- componentId: VARIABLES_COMPONENT_ID,
676
- configId: config.id
677
- }).catch((cleanupError) => {
678
- if (error instanceof Error && error.cause === void 0) error.cause = cleanupError;
679
- });
680
- throw error;
681
- }
682
- };
683
- return {
684
- /** Copy a variables config into a fresh, independent config + values row. */
685
- copy: async ({ variablesId, variablesValuesId, branchId = "default" }) => {
686
- const { definitions, values } = await readVariables(variablesId, variablesValuesId, branchId);
687
- return createVariables(definitions, values, branchId);
688
- },
689
- /** Merge the source's variables into the target's and create a fresh merged config + values row. */
690
- merge: async ({ targetVariablesId, targetValuesId, sourceVariablesId, sourceValuesId, branchId = "default" }) => {
691
- const [target, source] = await Promise.all([readVariables(targetVariablesId, targetValuesId, branchId), readVariables(sourceVariablesId, sourceValuesId, branchId)]);
692
- return createVariables(mergeVariableDefinitions(target.definitions, source.definitions), mergeVariableValues(target.values, source.values), branchId);
693
- }
694
- };
695
- };
696
- // src/keboola/createSdk.ts
697
- const createSdk = ({ storage, services }) => ({
698
- tag: createTagSdk({ metastoreClient: services.metastore }),
699
- semanticLayer: createSemanticLayerSdk({ metastoreClient: services.metastore }),
700
- kaiMemory: createKaiMemorySdk({ metastoreClient: services.metastore }),
701
- vault: createVaultSdk({
702
- vaultClient: services.vault,
703
- encryptionClient: services.encryption
704
- }),
705
- variables: createVariablesSdk({ storageClient: storage })
706
- });
707
- // src/keboola/createServiceClients.ts
708
- const withPath = (serviceBaseUrl, path) => typeof serviceBaseUrl === "string" ? `${serviceBaseUrl}${path}` : async () => `${await serviceBaseUrl()}${path}`;
709
- const createServiceClients = ({ baseUrl, auth, getServiceBaseUrl, middlewareFor, attachTokenMiddleware }) => createServiceClientRegistry()({
710
- getServiceBaseUrl,
711
- onUnavailable: ({ serviceId, path, clientName }) => {
712
- throw new ServiceUnavailableError(serviceId, path, clientName);
713
- }
714
- }).add({
715
- serviceId: "vault",
716
- clientName: "vault",
717
- clientFn: (serviceBaseUrl) => createVaultClient({
718
- baseUrl: serviceBaseUrl,
719
- middlewares: middlewareFor("vault", [attachTokenMiddleware]),
720
- auth
721
- })
722
- }).add({
723
- serviceId: "data-science",
724
- clientName: "dataScience",
725
- clientFn: (serviceBaseUrl) => createDataScienceClient({
726
- baseUrl: serviceBaseUrl,
727
- middlewares: middlewareFor("dataScience", [attachTokenMiddleware]),
728
- auth
729
- })
730
- }).add({
731
- serviceId: "data-science",
732
- clientName: "apps",
733
- clientFn: (serviceBaseUrl) => createAppsClient({
734
- baseUrl: withPath(serviceBaseUrl, "/v2"),
735
- middlewares: middlewareFor("apps", [attachTokenMiddleware]),
736
- auth
737
- })
738
- }).add({
739
- serviceId: "encryption",
740
- clientName: "encryption",
741
- clientFn: (serviceBaseUrl) => createEncryptionClient({
742
- baseUrl: serviceBaseUrl,
743
- middlewares: middlewareFor("encryption")
744
- })
745
- }).add({
746
- serviceId: "editor",
747
- clientName: "editor",
748
- clientFn: (serviceBaseUrl) => createEditorClient({
749
- baseUrl: serviceBaseUrl,
750
- middlewares: middlewareFor("editor", [attachTokenMiddleware]),
751
- auth
752
- })
753
- }).add({
754
- serviceId: "sync-actions",
755
- clientName: "syncActions",
756
- clientFn: (serviceBaseUrl) => createSyncActionsClient({
757
- baseUrl: serviceBaseUrl,
758
- middlewares: middlewareFor("syncActions", [attachTokenMiddleware]),
759
- auth
760
- })
761
- }).add({
762
- serviceId: "telemetry",
763
- clientName: "telemetry",
764
- clientFn: (serviceBaseUrl) => createTelemetryClient({
765
- baseUrl: serviceBaseUrl,
766
- middlewares: middlewareFor("telemetry", [attachTokenMiddleware]),
767
- auth
768
- })
769
- }).add({
770
- serviceId: "query",
771
- clientName: "queryService",
772
- clientFn: (serviceBaseUrl) => createQueryServiceClient({
773
- baseUrl: serviceBaseUrl,
774
- middlewares: middlewareFor("queryService", [attachTokenMiddleware]),
775
- auth
776
- })
777
- }).add({
778
- serviceId: "queue",
779
- clientName: "queue",
780
- clientFn: (serviceBaseUrl) => createQueueClient({
781
- baseUrl: serviceBaseUrl,
782
- middlewares: middlewareFor("queue", [attachTokenMiddleware]),
783
- auth
784
- })
785
- }).add({
786
- serviceId: "kai-assistant",
787
- clientName: "chat",
788
- clientFn: (serviceBaseUrl) => createChatClient({
789
- storageApiUrl: baseUrl,
790
- baseUrl: serviceBaseUrl,
791
- middlewares: middlewareFor("chat", [attachTokenMiddleware]),
792
- auth
793
- })
794
- }).add({
795
- serviceId: "ai",
796
- clientName: "ai",
797
- clientFn: (serviceBaseUrl) => createAiClient({
798
- baseUrl: serviceBaseUrl,
799
- middlewares: middlewareFor("ai", [attachTokenMiddleware]),
800
- auth
801
- })
802
- }).add({
803
- serviceId: "ai",
804
- clientName: "omnisearch",
805
- clientFn: (serviceBaseUrl) => createOmnisearchClient({
806
- baseUrl: withPath(serviceBaseUrl, "/omnisearch"),
807
- middlewares: middlewareFor("omnisearch", [attachTokenMiddleware]),
808
- auth
809
- })
810
- }).add({
811
- serviceId: "import",
812
- clientName: "import",
813
- clientFn: (serviceBaseUrl) => createImportClient({
814
- baseUrl: serviceBaseUrl,
815
- middlewares: middlewareFor("import", [attachTokenMiddleware]),
816
- auth
817
- })
818
- }).add({
819
- serviceId: "kai-agent",
820
- clientName: "kaiAgent",
821
- clientFn: (serviceBaseUrl) => createKaiAgentClient({
822
- baseUrl: serviceBaseUrl,
823
- middlewares: middlewareFor("kaiAgent", [attachTokenMiddleware]),
824
- auth
825
- })
826
- }).add({
827
- serviceId: "components-mcp",
828
- clientName: "componentsMcp",
829
- clientFn: (serviceBaseUrl) => createComponentsMcpClient({
830
- baseUrl: serviceBaseUrl,
831
- middlewares: middlewareFor("componentsMcp", [attachTokenMiddleware]),
832
- auth
833
- })
834
- }).add({
835
- serviceId: "oauth",
836
- clientName: "oauth",
837
- clientFn: (serviceBaseUrl) => createOauthClient({
838
- baseUrl: serviceBaseUrl,
839
- middlewares: middlewareFor("oauth", [attachTokenMiddleware]),
840
- auth
841
- })
842
- }).add({
843
- serviceId: "scheduler",
844
- clientName: "scheduler",
845
- clientFn: (serviceBaseUrl) => createSchedulerClient({
846
- baseUrl: serviceBaseUrl,
847
- middlewares: middlewareFor("scheduler", [attachTokenMiddleware]),
848
- auth
849
- })
850
- }).add({
851
- serviceId: "stream",
852
- clientName: "stream",
853
- clientFn: (serviceBaseUrl) => createStreamClient({
854
- baseUrl: serviceBaseUrl,
855
- middlewares: middlewareFor("stream", [attachTokenMiddleware]),
856
- auth
857
- })
858
- }).add({
859
- serviceId: "notification",
860
- clientName: "notifications",
861
- clientFn: (serviceBaseUrl) => createNotificationsClient({
862
- baseUrl: serviceBaseUrl,
863
- middlewares: middlewareFor("notifications", [attachTokenMiddleware]),
864
- auth
865
- })
866
- }).add({
867
- serviceId: "billing",
868
- clientName: "billing",
869
- clientFn: (serviceBaseUrl) => createBillingClient({
870
- baseUrl: serviceBaseUrl,
871
- middlewares: middlewareFor("billing", [attachTokenMiddleware]),
872
- auth
873
- })
874
- }).add({
875
- serviceId: "metastore",
876
- clientName: "metastore",
877
- clientFn: (serviceBaseUrl) => createMetastoreClient({
878
- baseUrl: serviceBaseUrl,
879
- middlewares: middlewareFor("metastore", [attachTokenMiddleware]),
880
- auth
881
- })
882
- }).build();
883
- // src/keboola/legacy/createProjectClients.ts
884
- const createAttachStorageToken = (getToken) => (next) => (request) => {
885
- request.request.headers.set(KeboolaHttpHeader.STORAGE_API_TOKEN, getToken());
886
- return next(request);
887
- };
888
- const createProjectClients = async ({ baseUrl, getStorageToken, onStorageTokenRefreshed, middlewareFor, clientServiceUrls }) => {
889
- const auth = {
890
- type: "sapi-token",
891
- token: getStorageToken()
892
- };
893
- const attach = createAttachStorageToken(getStorageToken);
894
- const stackInfo = await createStorageClient({
895
- baseUrl,
896
- auth,
897
- middlewares: [attach]
898
- }).getStackInfo({ exclude: "componentDetails" });
899
- const stack = createStack({
900
- stackInfo,
901
- clientServiceUrls
902
- });
903
- const storage = createStorageClient({
904
- baseUrl,
905
- auth,
906
- middlewares: middlewareFor("storage", []),
907
- onRefreshToken: onStorageTokenRefreshed
908
- });
909
- const { client: services, meta: serviceMeta } = createServiceClients({
910
- baseUrl,
911
- auth,
912
- getServiceBaseUrl: stack.getServiceUrl,
913
- middlewareFor,
914
- attachTokenMiddleware: attach
915
- });
916
- return {
917
- baseUrl: normalizeBaseUrl(baseUrl),
918
- stack,
919
- serviceMeta,
920
- storage,
921
- ...services,
922
- sdk: createSdk({
923
- storage,
924
- services
925
- })
926
- };
927
- };
928
- // src/keboola/legacy/keboola.ts
929
- const createLegacyKeboola = (options = {}) => {
930
- const config = createConfig();
931
- const middlewareFor = createMiddlewareFor(options.middlewares);
932
- const authClient = createDerivedStore({
933
- source: config.store,
934
- dependsOn: (state) => state.baseUrl,
935
- build: (baseUrl) => baseUrl ? createAuthClient({
936
- baseUrl,
937
- middlewares: middlewareFor("auth", [])
938
- }) : null
939
- });
940
- const management = createDerivedStore({
941
- source: config.store,
942
- dependsOn: (state) => ({
943
- baseUrl: state.baseUrl,
944
- token: state.managementToken
945
- }),
946
- build: ({ baseUrl, token }) => baseUrl ? createManagementClient({
947
- baseUrl,
948
- auth: token ? {
949
- type: "management-token",
950
- token
951
- } : { type: "management-token" },
952
- middlewares: middlewareFor("management", [])
953
- }) : null
954
- });
955
- const build = createDerivedAsyncStore({
956
- source: config.store,
957
- dependsOn: (state) => state.sapiToken && state.baseUrl ? state.baseUrl : null,
958
- build: (baseUrl) => createProjectClients({
959
- baseUrl,
960
- getStorageToken: config.getStorageToken,
961
- onStorageTokenRefreshed: config.setStorageToken,
962
- middlewareFor,
963
- clientServiceUrls: options.clientServiceUrls
964
- })
965
- });
966
- if (options.baseUrl) config.setBaseUrl(options.baseUrl);
967
- const debug = () => {
968
- const info = config.debug();
969
- return {
970
- type: "Sapi",
971
- config: info,
972
- authReady: authClient.get() !== null,
973
- managementReady: !!info.managementToken,
974
- storage: build.store.get().state
975
- };
976
- };
977
- const session = {
978
- setBaseUrl: config.setBaseUrl,
979
- isStorageReady: () => build.store.get().state === "ready",
980
- authenticateStorage: (sapiToken) => config.authenticate({ sapiToken }),
981
- authenticateStorageAsync: async (sapiToken) => {
982
- config.authenticate({ sapiToken });
983
- await build.settled();
984
- },
985
- authenticateManagement: (managementToken) => config.authenticate({ managementToken }),
986
- subscribe: (listener) => {
987
- const unsubscribeConfig = config.store.subscribe(() => listener(debug()));
988
- const unsubscribeBuild = build.store.subscribe(() => listener(debug()));
989
- return () => {
990
- unsubscribeConfig();
991
- unsubscribeBuild();
992
- };
993
- },
994
- debug
995
- };
996
- return {
997
- api: createApi({
998
- getAuthClient: () => authClient.get(),
999
- getManagementClient: () => management.get(),
1000
- getProjectClients: () => {
1001
- const state = build.store.get();
1002
- return state.state === "ready" ? state.value : null;
1003
- }
1004
- }),
1005
- session
1006
- };
1007
- };
1008
- // src/keboola/bearer/state/auth.ts
1009
- const grantOf = (credential) => credential.type === "token" ? {
1010
- type: "token",
1011
- refreshToken: credential.refreshToken
1012
- } : {
1013
- type: "cookie",
1014
- sessionId: credential.sessionId
1015
- };
1016
- const stamped = (input) => ({
1017
- ...input,
1018
- issuedAt: Date.now()
1019
- });
1020
- const credentialOf = (auth) => auth.status === "authenticated" ? Result.success(auth.credential) : Result.failure(new KeboolaError(KeboolaErrorType.NotAuthenticated));
1021
- /**
1022
- * The stack's credential and its sign-in pin.
1023
- *
1024
- * - `epoch` moves on `authenticate` and `signOut` and never on a rotation, so it is exactly "which
1025
- * sign-in is this" — what an in-flight exchange compares itself against.
1026
- */
1027
- const createAuth = (stacks) => {
1028
- const expired = /* @__PURE__ */ new Set();
1029
- const requireCredential = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => credentialOf(stack.auth));
1030
- const requireUnauthenticated = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.auth.status === "authenticated" ? Result.failure(new KeboolaError(KeboolaErrorType.AlreadyAuthenticated)) : Result.success(stack));
1031
- const requireAnonymous = (baseUrl) => Result.andThen(requireUnauthenticated(baseUrl), (stack) => stack.auth.status === "restoring" ? Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" is already being restored`)) : Result.success(stack));
1032
- const requireRestoring = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.auth.status === "restoring" ? Result.success(stack) : Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" is not being restored`)));
1033
- const startRestore = (baseUrl) => Result.map(requireAnonymous(baseUrl), (stack) => stacks.set({
1034
- ...stack,
1035
- auth: { status: "restoring" }
1036
- }));
1037
- const cancelRestore = (baseUrl) => Result.map(requireRestoring(baseUrl), (stack) => stacks.set({
1038
- ...stack,
1039
- auth: { status: "anonymous" }
1040
- }));
1041
- const authenticate = (baseUrl, input) => Result.map(requireUnauthenticated(baseUrl), (stack) => {
1042
- expired.delete(baseUrl);
1043
- return stacks.set({
1044
- ...stack,
1045
- epoch: stack.epoch + 1,
1046
- auth: {
1047
- status: "authenticated",
1048
- credential: stamped(input)
1049
- },
1050
- retained: null
1051
- });
1052
- });
1053
- const applyRefresh = (baseUrl, input) => Result.andThen(requireCredential(baseUrl), (credential) => credential.type !== input.type ? Result.failure(/* @__PURE__ */ new Error(`A ${credential.type} grant cannot become ${input.type}`)) : Result.map(stacks.get(baseUrl), (stack) => stacks.set({
1054
- ...stack,
1055
- auth: {
1056
- status: "authenticated",
1057
- credential: stamped(input)
1058
- }
1059
- })));
1060
- const forceExpire = (baseUrl) => Result.andThen(requireCredential(baseUrl), (credential) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
1061
- ...stack,
1062
- auth: {
1063
- status: "authenticated",
1064
- credential: {
1065
- ...credential,
1066
- issuedAt: Date.now() - credential.expiresIn * 1e3
1067
- }
1068
- }
1069
- })));
1070
- const signOut = (baseUrl, { retain = false } = {}) => Result.map(stacks.get(baseUrl), (stack) => {
1071
- const retained = retain ? Result.unwrapOr(Result.map(credentialOf(stack.auth), (credential) => ({ grant: grantOf(credential) })), stack.retained) : null;
1072
- return stacks.set({
1073
- ...stack,
1074
- epoch: stack.epoch + 1,
1075
- auth: { status: "anonymous" },
1076
- retained
1077
- });
1078
- });
1079
- const retain = (baseUrl, retained) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
1080
- ...stack,
1081
- retained
1082
- }));
1083
- const dropRetained = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
1084
- ...stack,
1085
- retained: null
1086
- }));
1087
- const requireRetained = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.retained ? Result.success(stack.retained) : Result.failure(/* @__PURE__ */ new Error(`Stack "${baseUrl}" retains no credential`)));
1088
- const notifyExpired = (baseUrl) => {
1089
- if (expired.has(baseUrl)) return false;
1090
- expired.add(baseUrl);
1091
- return true;
1092
- };
1093
- const getEpoch = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stack.epoch);
1094
- const getAccessToken = (baseUrl) => Result.unwrapOr(Result.map(requireCredential(baseUrl), ({ accessToken }) => accessToken), null);
1095
- return {
1096
- startRestore,
1097
- cancelRestore,
1098
- authenticate,
1099
- applyRefresh,
1100
- forceExpire,
1101
- signOut,
1102
- retain,
1103
- dropRetained,
1104
- requireRetained,
1105
- notifyExpired,
1106
- requireCredential,
1107
- getEpoch,
1108
- getAccessToken
1109
- };
1110
- };
1111
- // src/keboola/bearer/state/stacks.ts
1112
- const newStack = (baseUrl) => ({
1113
- baseUrl,
1114
- context: "idle",
1115
- epoch: 0,
1116
- auth: { status: "anonymous" },
1117
- retained: null
1118
- });
1119
- /** One entry per stack, and the verbs that open and select them. */
1120
- const createStacks = (store) => {
1121
- const get = (baseUrl) => {
1122
- const stack = store.get().stacks[baseUrl];
1123
- return stack ? Result.success(stack) : Result.failure(new KeboolaError(KeboolaErrorType.Unconfigured));
1124
- };
1125
- const set = (stack) => {
1126
- const state = store.get();
1127
- store.set({
1128
- ...state,
1129
- stacks: {
1130
- ...state.stacks,
1131
- [stack.baseUrl]: stack
1132
- }
1133
- });
1134
- return stack;
1135
- };
1136
- const update = (baseUrl, updater) => Result.map(get(baseUrl), (stack) => set(updater(stack)));
1137
- const ensure = (baseUrl) => {
1138
- const existing = get(baseUrl);
1139
- if (existing.success) return existing.data;
1140
- return set(newStack(baseUrl));
1141
- };
1142
- const getActive = () => {
1143
- const { active } = store.get();
1144
- const stack = get(active);
1145
- if (!stack.success) throw new Error(`The active stack has no row: ${active}`);
1146
- return stack.data;
1147
- };
1148
- const select = (baseUrl) => {
1149
- const stack = ensure(baseUrl);
1150
- const state = store.get();
1151
- if (state.active !== baseUrl) store.set({
1152
- ...state,
1153
- active: baseUrl
1154
- });
1155
- return stack;
1156
- };
1157
- const updateContext = (baseUrl, context) => update(baseUrl, (stack) => ({
1158
- ...stack,
1159
- context
1160
- }));
1161
- return {
1162
- get,
1163
- set,
1164
- update,
1165
- ensure,
1166
- getActive,
1167
- select,
1168
- updateContext
1169
- };
1170
- };
1171
- // src/keboola/bearer/state/state.ts
512
+ // src/keboola/state/state.ts
1172
513
  /**
1173
514
  * The stack table and the rules over it, one namespace per concern.
1174
515
  *
@@ -1187,8 +528,9 @@ const createState = (defaultBaseUrl) => {
1187
528
  auth
1188
529
  };
1189
530
  };
1190
- // src/keboola/bearer/credentials/credentials.ts
531
+ // src/keboola/credentials/credentials.ts
1191
532
  const DEFAULT_REFRESH_THRESHOLD = .9;
533
+ const END_SESSION_TIMEOUT_MS = 1e4;
1192
534
  const signInEnded = () => new KeboolaError(KeboolaErrorType.SignInEnded);
1193
535
  const toRestoreStatus = (outcome) => {
1194
536
  if (outcome === void 0 || outcome === "skipped") return "empty";
@@ -1229,13 +571,18 @@ const createCredentials = ({ state, persistor, middlewares, refreshThreshold = D
1229
571
  const refreshed = await Result.tryCatchAsync(() => renew(client, grant));
1230
572
  return isSameSignIn() ? refreshed : Result.failure(signInEnded());
1231
573
  };
574
+ /**
575
+ * The grant to rotate, or the sign-out another tab stored.
576
+ *
577
+ * - `{ retained }`: the stored sign-in ended; `retained` is what a retained sign-out kept.
578
+ */
1232
579
  const getGrantForRotation = async (store, baseUrl, credential) => {
1233
580
  const isSameSignIn = markSignIn(baseUrl);
1234
581
  const hydrated = await Result.tryCatchAsync(() => store.read());
1235
582
  if (!hydrated.success) return hydrated;
1236
583
  if (!isSameSignIn()) return Result.failure(signInEnded());
1237
584
  const persistedStack = hydrated.data.stacks.find((stack) => stack.baseUrl === baseUrl);
1238
- if (persistedStack && persistedStack.credential === null) return Result.failure(signInEnded());
585
+ if (persistedStack && persistedStack.credential === null) return Result.success({ retained: persistedStack.retained ?? null });
1239
586
  return Result.success(persistedStack?.credential ?? grantOf(credential));
1240
587
  };
1241
588
  const rotateOnce = async (baseUrl) => persistor.locked(async (store) => {
@@ -1243,6 +590,10 @@ const createCredentials = ({ state, persistor, middlewares, refreshThreshold = D
1243
590
  if (!credential.success) return credential;
1244
591
  const grant = await getGrantForRotation(store, baseUrl, credential.data);
1245
592
  if (!grant.success) return grant;
593
+ if ("retained" in grant.data) {
594
+ await expire(baseUrl, store, grant.data.retained);
595
+ return Result.failure(signInEnded());
596
+ }
1246
597
  const refreshed = await refresh(baseUrl, grant.data);
1247
598
  if (!refreshed.success) {
1248
599
  if (isUnauthorized(refreshed.error)) await expire(baseUrl, store);
@@ -1314,9 +665,10 @@ const createCredentials = ({ state, persistor, middlewares, refreshThreshold = D
1314
665
  onSignedOut?.(baseUrl);
1315
666
  return signedOut;
1316
667
  };
1317
- const expire = async (baseUrl, store) => {
668
+ const expire = async (baseUrl, store, retained = null) => {
1318
669
  if (!state.auth.notifyExpired(baseUrl)) return;
1319
670
  signOut(baseUrl);
671
+ if (retained) state.auth.retain(baseUrl, retained);
1320
672
  await store.persistStack(baseUrl, state.store.get());
1321
673
  onExpired?.(baseUrl);
1322
674
  };
@@ -1329,19 +681,360 @@ const createCredentials = ({ state, persistor, middlewares, refreshThreshold = D
1329
681
  if (!state.auth.requireCredential(baseUrl).success) return null;
1330
682
  return Result.unwrap(await rotate(baseUrl));
1331
683
  }
1332
- await renewIfStale(baseUrl);
1333
- return state.auth.getAccessToken(baseUrl);
1334
- } });
684
+ await renewIfStale(baseUrl);
685
+ return state.auth.getAccessToken(baseUrl);
686
+ } });
687
+ /**
688
+ * Ends a signed-out grant's server session: its refresh, derived PATs and paired browser session.
689
+ *
690
+ * 1. `token`: revokes the refresh token; the server also takes the one before the last rotation.
691
+ * 2. `cookie`: renews off the session cookie, then revokes that fresh access token.
692
+ * - Never an access token held from before: one rotation later the server no longer knows it.
693
+ * - Best effort, bounded by `END_SESSION_TIMEOUT_MS`: a failure is logged, the sign-out stands.
694
+ */
695
+ const endSession = async (baseUrl, grant) => {
696
+ const client = createAuthClient({
697
+ baseUrl,
698
+ middlewares
699
+ });
700
+ const signal = AbortSignal.timeout(END_SESSION_TIMEOUT_MS);
701
+ try {
702
+ const body = grant.type === "token" ? {
703
+ token: grant.refreshToken,
704
+ tokenTypeHint: "refreshToken"
705
+ } : {
706
+ token: (await client.token.refreshWithSession({ sessionId: grant.sessionId }, signal)).accessToken,
707
+ tokenTypeHint: "accessToken"
708
+ };
709
+ await client.token.revoke(body, signal);
710
+ } catch (error) {
711
+ console.warn("createCredentials: the session could not be ended", error);
712
+ }
713
+ };
714
+ return {
715
+ middleware,
716
+ rotate,
717
+ renewIfStale,
718
+ restore,
719
+ restoreRetained,
720
+ signOut,
721
+ endSession
722
+ };
723
+ };
724
+ // src/serviceClientRegistry/utils.ts
725
+ const isBuiltInProperty = (property) => typeof property === "symbol" || property === "then" || property === "constructor" || property === "toString" || property === "valueOf";
726
+ /**
727
+ * Creates a dummy client that intercepts method calls and invokes the provided onCall callback.
728
+ */
729
+ const createDummyClient = ({ onCall }) => {
730
+ const createProxy = (path = []) => new Proxy(() => {}, {
731
+ get: (_target, prop) => {
732
+ if (isBuiltInProperty(prop)) return void 0;
733
+ return createProxy([...path, prop]);
734
+ },
735
+ apply: (_target, _thisArgs, args) => onCall(path, args)
736
+ });
737
+ return createProxy();
738
+ };
739
+ // src/serviceClientRegistry/createServiceClientRegistry.ts
740
+ const createServiceClientRegistry = () => ({ getServiceBaseUrl, onUnavailable }) => {
741
+ const dummy = (serviceId, clientName) => createDummyClient({ onCall: (path, args) => {
742
+ onUnavailable?.({
743
+ serviceId,
744
+ path,
745
+ args,
746
+ clientName
747
+ });
748
+ } });
749
+ const configs = [];
750
+ const resolveClient = ({ serviceId, clientFn, clientName }) => {
751
+ const serviceBaseUrl = getServiceBaseUrl(serviceId);
752
+ return serviceBaseUrl ? clientFn(serviceBaseUrl) : dummy(serviceId, clientName);
753
+ };
754
+ const registry = {
755
+ add: (config) => {
756
+ configs.push(config);
757
+ return registry;
758
+ },
759
+ build: () => {
760
+ const clientMap = {};
761
+ configs.forEach((config) => {
762
+ clientMap[config.clientName] = resolveClient(config);
763
+ });
764
+ return { client: clientMap };
765
+ }
766
+ };
767
+ return registry;
768
+ };
769
+ // src/sdks/variables/variablesSdk.ts
770
+ const VARIABLES_COMPONENT_ID = "keboola.variables";
771
+ /** Union the definitions by name; on a name conflict the target's definition is kept. */
772
+ const mergeVariableDefinitions = (target, source) => {
773
+ const targetNames = new Set(target.map((definition) => definition.name));
774
+ return [...target, ...source.filter((definition) => !targetNames.has(definition.name))];
775
+ };
776
+ /** Add values missing in the target; on a name conflict the value is updated to the source's. */
777
+ const mergeVariableValues = (target, source) => {
778
+ const sourceByName = new Map(source.map((value) => [value.name, value.value]));
779
+ const targetNames = new Set(target.map((value) => value.name));
780
+ return [...target.map((value) => sourceByName.has(value.name) ? {
781
+ ...value,
782
+ value: sourceByName.get(value.name)
783
+ } : value), ...source.filter((value) => !targetNames.has(value.name))];
784
+ };
785
+ /**
786
+ * Orchestration for `keboola.variables` configs: copy a config, or merge two configs into a fresh
787
+ * one (union definitions, upsert values — source wins on a name conflict). Each result is a brand
788
+ * new config + values row, so the caller can reference it without sharing lineage with the source.
789
+ */
790
+ const createVariablesSdk = ({ storageClient }) => {
791
+ const configs = storageClient.configurations;
792
+ const rows = storageClient.configurationRows;
793
+ const readVariables = async (configId, valuesRowId, branchId) => {
794
+ const config = await configs.getConfiguration({
795
+ componentId: VARIABLES_COMPONENT_ID,
796
+ configId,
797
+ branchId
798
+ });
799
+ const row = config.rows.find((candidate) => candidate.id === valuesRowId) ?? config.rows[0];
800
+ const rawDefinitions = config.configuration?.variables;
801
+ const rawValues = row?.configuration?.values;
802
+ return {
803
+ definitions: Array.isArray(rawDefinitions) ? rawDefinitions : [],
804
+ values: Array.isArray(rawValues) ? rawValues : []
805
+ };
806
+ };
807
+ const createVariables = async (definitions, values, branchId) => {
808
+ const config = await configs.createConfiguration({
809
+ branchId,
810
+ componentId: VARIABLES_COMPONENT_ID,
811
+ name: "Variables definition",
812
+ configuration: { variables: definitions }
813
+ });
814
+ try {
815
+ const row = await rows.createConfigurationRow({
816
+ branchId: String(branchId),
817
+ componentId: VARIABLES_COMPONENT_ID,
818
+ configurationId: config.id,
819
+ name: "Default values",
820
+ configuration: { values }
821
+ });
822
+ return {
823
+ variablesId: config.id,
824
+ variablesValuesId: row.id
825
+ };
826
+ } catch (error) {
827
+ await configs.deleteConfiguration({
828
+ branchId,
829
+ componentId: VARIABLES_COMPONENT_ID,
830
+ configId: config.id
831
+ }).catch((cleanupError) => {
832
+ if (error instanceof Error && error.cause === void 0) error.cause = cleanupError;
833
+ });
834
+ throw error;
835
+ }
836
+ };
1335
837
  return {
1336
- middleware,
1337
- rotate,
1338
- renewIfStale,
1339
- restore,
1340
- restoreRetained,
1341
- signOut
838
+ /** Copy a variables config into a fresh, independent config + values row. */
839
+ copy: async ({ variablesId, variablesValuesId, branchId = "default" }) => {
840
+ const { definitions, values } = await readVariables(variablesId, variablesValuesId, branchId);
841
+ return createVariables(definitions, values, branchId);
842
+ },
843
+ /** Merge the source's variables into the target's and create a fresh merged config + values row. */
844
+ merge: async ({ targetVariablesId, targetValuesId, sourceVariablesId, sourceValuesId, branchId = "default" }) => {
845
+ const [target, source] = await Promise.all([readVariables(targetVariablesId, targetValuesId, branchId), readVariables(sourceVariablesId, sourceValuesId, branchId)]);
846
+ return createVariables(mergeVariableDefinitions(target.definitions, source.definitions), mergeVariableValues(target.values, source.values), branchId);
847
+ }
1342
848
  };
1343
849
  };
1344
- // src/keboola/bearer/perProject.ts
850
+ // src/keboola/createSdk.ts
851
+ const createSdk = ({ storage, services }) => ({
852
+ tag: createTagSdk({ metastoreClient: services.metastore }),
853
+ semanticLayer: createSemanticLayerSdk({ metastoreClient: services.metastore }),
854
+ kaiMemory: createKaiMemorySdk({ metastoreClient: services.metastore }),
855
+ vault: createVaultSdk({
856
+ vaultClient: services.vault,
857
+ encryptionClient: services.encryption
858
+ }),
859
+ variables: createVariablesSdk({ storageClient: storage })
860
+ });
861
+ // src/keboola/createServiceClients.ts
862
+ const withPath = (serviceBaseUrl, path) => typeof serviceBaseUrl === "string" ? `${serviceBaseUrl}${path}` : async () => `${await serviceBaseUrl()}${path}`;
863
+ const createServiceClients = ({ baseUrl, auth, getServiceBaseUrl, middlewareFor, attachTokenMiddleware }) => createServiceClientRegistry()({
864
+ getServiceBaseUrl,
865
+ onUnavailable: ({ serviceId, path, clientName }) => {
866
+ throw new ServiceUnavailableError(serviceId, path, clientName);
867
+ }
868
+ }).add({
869
+ serviceId: "vault",
870
+ clientName: "vault",
871
+ clientFn: (serviceBaseUrl) => createVaultClient({
872
+ baseUrl: serviceBaseUrl,
873
+ middlewares: middlewareFor("vault", [attachTokenMiddleware]),
874
+ auth
875
+ })
876
+ }).add({
877
+ serviceId: "data-science",
878
+ clientName: "dataScience",
879
+ clientFn: (serviceBaseUrl) => createDataScienceClient({
880
+ baseUrl: serviceBaseUrl,
881
+ middlewares: middlewareFor("dataScience", [attachTokenMiddleware]),
882
+ auth
883
+ })
884
+ }).add({
885
+ serviceId: "data-science",
886
+ clientName: "apps",
887
+ clientFn: (serviceBaseUrl) => createAppsClient({
888
+ baseUrl: withPath(serviceBaseUrl, "/v2"),
889
+ middlewares: middlewareFor("apps", [attachTokenMiddleware]),
890
+ auth
891
+ })
892
+ }).add({
893
+ serviceId: "encryption",
894
+ clientName: "encryption",
895
+ clientFn: (serviceBaseUrl) => createEncryptionClient({
896
+ baseUrl: serviceBaseUrl,
897
+ middlewares: middlewareFor("encryption")
898
+ })
899
+ }).add({
900
+ serviceId: "editor",
901
+ clientName: "editor",
902
+ clientFn: (serviceBaseUrl) => createEditorClient({
903
+ baseUrl: serviceBaseUrl,
904
+ middlewares: middlewareFor("editor", [attachTokenMiddleware]),
905
+ auth
906
+ })
907
+ }).add({
908
+ serviceId: "sync-actions",
909
+ clientName: "syncActions",
910
+ clientFn: (serviceBaseUrl) => createSyncActionsClient({
911
+ baseUrl: serviceBaseUrl,
912
+ middlewares: middlewareFor("syncActions", [attachTokenMiddleware]),
913
+ auth
914
+ })
915
+ }).add({
916
+ serviceId: "telemetry",
917
+ clientName: "telemetry",
918
+ clientFn: (serviceBaseUrl) => createTelemetryClient({
919
+ baseUrl: serviceBaseUrl,
920
+ middlewares: middlewareFor("telemetry", [attachTokenMiddleware]),
921
+ auth
922
+ })
923
+ }).add({
924
+ serviceId: "query",
925
+ clientName: "queryService",
926
+ clientFn: (serviceBaseUrl) => createQueryServiceClient({
927
+ baseUrl: serviceBaseUrl,
928
+ middlewares: middlewareFor("queryService", [attachTokenMiddleware]),
929
+ auth
930
+ })
931
+ }).add({
932
+ serviceId: "queue",
933
+ clientName: "queue",
934
+ clientFn: (serviceBaseUrl) => createQueueClient({
935
+ baseUrl: serviceBaseUrl,
936
+ middlewares: middlewareFor("queue", [attachTokenMiddleware]),
937
+ auth
938
+ })
939
+ }).add({
940
+ serviceId: "kai-assistant",
941
+ clientName: "chat",
942
+ clientFn: (serviceBaseUrl) => createChatClient({
943
+ storageApiUrl: baseUrl,
944
+ baseUrl: serviceBaseUrl,
945
+ middlewares: middlewareFor("chat", [attachTokenMiddleware]),
946
+ auth
947
+ })
948
+ }).add({
949
+ serviceId: "ai",
950
+ clientName: "ai",
951
+ clientFn: (serviceBaseUrl) => createAiClient({
952
+ baseUrl: serviceBaseUrl,
953
+ middlewares: middlewareFor("ai", [attachTokenMiddleware]),
954
+ auth
955
+ })
956
+ }).add({
957
+ serviceId: "ai",
958
+ clientName: "omnisearch",
959
+ clientFn: (serviceBaseUrl) => createOmnisearchClient({
960
+ baseUrl: withPath(serviceBaseUrl, "/omnisearch"),
961
+ middlewares: middlewareFor("omnisearch", [attachTokenMiddleware]),
962
+ auth
963
+ })
964
+ }).add({
965
+ serviceId: "import",
966
+ clientName: "import",
967
+ clientFn: (serviceBaseUrl) => createImportClient({
968
+ baseUrl: serviceBaseUrl,
969
+ middlewares: middlewareFor("import", [attachTokenMiddleware]),
970
+ auth
971
+ })
972
+ }).add({
973
+ serviceId: "kai-agent",
974
+ clientName: "kaiAgent",
975
+ clientFn: (serviceBaseUrl) => createKaiAgentClient({
976
+ baseUrl: serviceBaseUrl,
977
+ middlewares: middlewareFor("kaiAgent", [attachTokenMiddleware]),
978
+ auth
979
+ })
980
+ }).add({
981
+ serviceId: "components-mcp",
982
+ clientName: "componentsMcp",
983
+ clientFn: (serviceBaseUrl) => createComponentsMcpClient({
984
+ baseUrl: serviceBaseUrl,
985
+ middlewares: middlewareFor("componentsMcp", [attachTokenMiddleware]),
986
+ auth
987
+ })
988
+ }).add({
989
+ serviceId: "oauth",
990
+ clientName: "oauth",
991
+ clientFn: (serviceBaseUrl) => createOauthClient({
992
+ baseUrl: serviceBaseUrl,
993
+ middlewares: middlewareFor("oauth", [attachTokenMiddleware]),
994
+ auth
995
+ })
996
+ }).add({
997
+ serviceId: "scheduler",
998
+ clientName: "scheduler",
999
+ clientFn: (serviceBaseUrl) => createSchedulerClient({
1000
+ baseUrl: serviceBaseUrl,
1001
+ middlewares: middlewareFor("scheduler", [attachTokenMiddleware]),
1002
+ auth
1003
+ })
1004
+ }).add({
1005
+ serviceId: "stream",
1006
+ clientName: "stream",
1007
+ clientFn: (serviceBaseUrl) => createStreamClient({
1008
+ baseUrl: serviceBaseUrl,
1009
+ middlewares: middlewareFor("stream", [attachTokenMiddleware]),
1010
+ auth
1011
+ })
1012
+ }).add({
1013
+ serviceId: "notification",
1014
+ clientName: "notifications",
1015
+ clientFn: (serviceBaseUrl) => createNotificationsClient({
1016
+ baseUrl: serviceBaseUrl,
1017
+ middlewares: middlewareFor("notifications", [attachTokenMiddleware]),
1018
+ auth
1019
+ })
1020
+ }).add({
1021
+ serviceId: "billing",
1022
+ clientName: "billing",
1023
+ clientFn: (serviceBaseUrl) => createBillingClient({
1024
+ baseUrl: serviceBaseUrl,
1025
+ middlewares: middlewareFor("billing", [attachTokenMiddleware]),
1026
+ auth
1027
+ })
1028
+ }).add({
1029
+ serviceId: "metastore",
1030
+ clientName: "metastore",
1031
+ clientFn: (serviceBaseUrl) => createMetastoreClient({
1032
+ baseUrl: serviceBaseUrl,
1033
+ middlewares: middlewareFor("metastore", [attachTokenMiddleware]),
1034
+ auth
1035
+ })
1036
+ }).build();
1037
+ // src/keboola/perProject.ts
1345
1038
  const projectKey = ({ baseUrl, projectId }) => `${baseUrl}#${projectId}`;
1346
1039
  /**
1347
1040
  * One handle per project, and the one call that drops it.
@@ -1376,12 +1069,12 @@ const createPerProject = ({ state, credentials, middlewareFor, stack }) => {
1376
1069
  auth: authFor(project),
1377
1070
  middlewares: middlewareFor("storage", [attach])
1378
1071
  });
1379
- const { client, meta } = createServiceClients({
1072
+ const { client } = createServiceClients({
1380
1073
  baseUrl: project.baseUrl,
1381
1074
  auth: authFor(project),
1382
1075
  getServiceBaseUrl: (serviceId) => async () => {
1383
1076
  const serviceUrl = (await stack.context.getAsync(project.baseUrl)).getServiceUrl(serviceId);
1384
- assert$1(serviceUrl, KeboolaErrorType.NotReady);
1077
+ if (!serviceUrl) throw new ServiceUnavailableError(serviceId);
1385
1078
  return serviceUrl;
1386
1079
  },
1387
1080
  middlewareFor,
@@ -1400,7 +1093,6 @@ const createPerProject = ({ state, credentials, middlewareFor, stack }) => {
1400
1093
  if (property === "stack" || property === "auth" || property === "management") return stack.get(project.baseUrl)[property];
1401
1094
  if (property === "storage") return storage;
1402
1095
  if (property === "sdk") return sdk;
1403
- if (property === "serviceMeta") return meta;
1404
1096
  return client[property];
1405
1097
  } }),
1406
1098
  end: () => {
@@ -1422,13 +1114,13 @@ const createPerProject = ({ state, credentials, middlewareFor, stack }) => {
1422
1114
  forgetUnder
1423
1115
  };
1424
1116
  };
1425
- // src/keboola/bearer/persistor.ts
1117
+ // src/keboola/persistor.ts
1426
1118
  /**
1427
1119
  * Where a bearer session is persisted, under whichever adapter the client was given.
1428
1120
  *
1429
1121
  * Exported because a consumer sometimes has to drop a session a client cannot reach: the adapter is
1430
1122
  * chosen at construction, so a client built without one holds no handle to the storage its own
1431
- * session is sitting in. `AppAuthStrategy` in kbc-ui is that case.
1123
+ * session is sitting in.
1432
1124
  */
1433
1125
  const SESSION_STORAGE_KEY = "keboola:session";
1434
1126
  /**
@@ -1555,7 +1247,44 @@ const createSessionPersistor = (storage) => {
1555
1247
  snapshot
1556
1248
  };
1557
1249
  };
1558
- // src/keboola/bearer/context.ts
1250
+ // src/domain/stack.ts
1251
+ const isServiceId = (id) => Object.values(ServiceId).includes(id);
1252
+ const SERVICE_URL_OVERRIDES = { "kai-assistant": (url) => `${url}/api` };
1253
+ const createStack = ({ stackInfo, clientServiceUrls }) => {
1254
+ const { services, components, features, ...infoRest } = stackInfo;
1255
+ const serviceMap = new Map(services.map((service) => {
1256
+ if (!isServiceId(service.id)) return [service.id, service.url];
1257
+ const devOverride = clientServiceUrls?.[service.id]?.(service.url);
1258
+ const prodOverride = SERVICE_URL_OVERRIDES[service.id]?.(service.url);
1259
+ const url = devOverride ?? prodOverride ?? service.url;
1260
+ return [service.id, url];
1261
+ }));
1262
+ const componentMap = new Map(components.map((component) => [component.id, component]));
1263
+ const featureSet = new Set(features);
1264
+ const hasFeature = (...feature) => {
1265
+ if (feature.length === 0) return false;
1266
+ return feature.every((x) => featureSet.has(x));
1267
+ };
1268
+ const hasComponent = (...componentId) => {
1269
+ if (componentId.length === 0) return false;
1270
+ return componentId.every((x) => componentMap.has(x));
1271
+ };
1272
+ const getComponent = (componentId) => componentMap.get(componentId) ?? null;
1273
+ const hasService = (serviceId) => serviceMap.has(serviceId);
1274
+ const getServiceUrl = (serviceId) => serviceMap.get(serviceId) ?? null;
1275
+ return {
1276
+ ...infoRest,
1277
+ services,
1278
+ features,
1279
+ components,
1280
+ hasFeature,
1281
+ getServiceUrl,
1282
+ hasService,
1283
+ getComponent,
1284
+ hasComponent
1285
+ };
1286
+ };
1287
+ // src/keboola/context.ts
1559
1288
  const STACK_INDEX_TIMEOUT_MS = 3e4;
1560
1289
  /**
1561
1290
  * One parsed stack index per stack; `createStack` applies the dev and production overrides.
@@ -1621,7 +1350,7 @@ const createStackContext = ({ state, clientServiceUrls }) => {
1621
1350
  getAsync
1622
1351
  };
1623
1352
  };
1624
- // src/keboola/bearer/perStack.ts
1353
+ // src/keboola/perStack.ts
1625
1354
  /**
1626
1355
  * Everything one stack derives.
1627
1356
  *
@@ -1659,7 +1388,7 @@ const createPerStack = ({ state, credentials, middlewareFor, clientServiceUrls }
1659
1388
  get
1660
1389
  };
1661
1390
  };
1662
- // src/keboola/bearer/keboola.ts
1391
+ // src/keboola/keboola.ts
1663
1392
  /**
1664
1393
  * The bearer client: the session table, its two scopes, and the surface they back.
1665
1394
  *
@@ -1747,20 +1476,39 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
1747
1476
  return active().management;
1748
1477
  }
1749
1478
  };
1750
- const getStackApi = () => stackApi;
1751
- const getProjectApi = (projectId) => perProject.get(onActiveStack(projectId));
1479
+ const projectApi = (projectId) => perProject.get(onActiveStack(projectId));
1752
1480
  /**
1753
1481
  * The scope's sign-in, or a named stack's — and everything that sign-in derived.
1754
1482
  *
1483
+ * - Ends the server session too (`credentials.endSession`).
1755
1484
  * - `retain` keeps the grant on the stack, persisted beside the sign-in it ended, for
1756
- * `restoreRetained`; the next sign-in on the stack replaces it.
1757
- * - The table is signed out on return; the promise resolves once that is stored, so a caller
1758
- * leaving the document waits for it.
1485
+ * `restoreRetained`, and so leaves the server session live; the next sign-in replaces it.
1486
+ * - The table is signed out on return; the promise resolves once that is stored and the
1487
+ * session's end was attempted, so a caller leaving the document waits for both.
1759
1488
  */
1760
- const signOut = ({ baseUrl, ...options } = {}) => {
1761
- const target = requireStackUrl(baseUrl);
1489
+ const signOut = ({ baseUrl, ...options } = {}) => endSignIn(requireStackUrl(baseUrl), options, !options.retain);
1490
+ const endingSessions = /* @__PURE__ */ new Map();
1491
+ /** `signOut`; `endSession: false` leaves the server session alone. */
1492
+ const endSignIn = (target, options, endSession) => {
1493
+ const held = endSession ? Result.unwrapOr(state.auth.requireCredential(target), null) : null;
1762
1494
  const signedOut = Result.unwrap(credentials.signOut(target, options));
1763
- return persistor.locked((store) => store.persistStack(target, state.store.get())).then(() => signedOut);
1495
+ let newest = held && grantOf(held);
1496
+ const ended = persistor.locked(async (store) => {
1497
+ if (held !== null) newest = (await store.read()).stacks.find((stack) => stack.baseUrl === target)?.credential ?? newest;
1498
+ await store.persistStack(target, state.store.get());
1499
+ }).then(() => newest ? credentials.endSession(target, newest) : void 0, async (error) => {
1500
+ if (newest) await credentials.endSession(target, newest);
1501
+ throw error;
1502
+ });
1503
+ const earlier = endingSessions.get(target);
1504
+ if (held !== null) {
1505
+ endingSessions.set(target, ended);
1506
+ const forget = () => {
1507
+ if (endingSessions.get(target) === ended) endingSessions.delete(target);
1508
+ };
1509
+ ended.then(forget, forget);
1510
+ }
1511
+ return Promise.all([ended, earlier]).then(() => signedOut);
1764
1512
  };
1765
1513
  /** Signs a stack back in from what a retained sign-out kept; `unreachable` leaves it to retry. */
1766
1514
  const restoreRetained = (baseUrl) => credentials.restoreRetained(normalizeBaseUrl(baseUrl));
@@ -1769,9 +1517,12 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
1769
1517
  *
1770
1518
  * - Signs out first, always: a sign-out moves the epoch even on an anonymous stack, so a stored
1771
1519
  * session still being restored cannot land on top of this one.
1520
+ * - Locally only: the replaced sign-in can share a browser session with `input`.
1772
1521
  */
1773
1522
  const replace = (input) => {
1774
- signOut();
1523
+ endSignIn(requireStackUrl(), {}, false).catch((error) => {
1524
+ console.warn("createKeboola: the replaced sign-in could not be stored", error);
1525
+ });
1775
1526
  return authenticate(input);
1776
1527
  };
1777
1528
  let persisting = false;
@@ -1837,8 +1588,8 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
1837
1588
  return verb(...args);
1838
1589
  };
1839
1590
  return {
1840
- getStackApi,
1841
- getProjectApi,
1591
+ stackApi,
1592
+ projectApi,
1842
1593
  session: {
1843
1594
  getState: state.store.get,
1844
1595
  subscribe: state.store.subscribe,
@@ -2061,6 +1812,6 @@ const createBranchRefs = ({ devBranches }) => {
2061
1812
  resolve: (ref) => getType(ref) === "default" ? defaultBranch.id : Number(ref)
2062
1813
  };
2063
1814
  };
2064
- export { ApiError, HtmlResponseError, HttpContentType, HttpHeader, KeboolaError, KeboolaErrorType, KeboolaHttpHeader, ManagementClientAuthError, ManagementSessionMintError, QueryJobError, QueueJobError, Result, RowLevelSecurityError, SESSION_STORAGE_KEY, ServiceUnavailableError, StorageJobError, SyncActionError, UserError, ValidationError, asError, assert, coalesce, collectByCursor, collectByOffset, concurrent, createAdminAccount, createBranchRefs, createDerivedAsyncStore, createDerivedStore, createEmitter, createGenericFetchClient, createKeboola, createLegacyKeboola, createLocalStorage, createLoggingMiddleware, createMemoryStorage, createNullStorage, createPersistor, createPollRegistry, createProject, createQueryServiceSdk, createRetryMiddleware, createSessionStorage, createStore, createUiVersionMiddleware, dedupe, deepMerge, delay, emitter, ensure, failureOf, formatValidationIssues, generateUUID, isAbortError, isApiError, isEmptyDeep, isFetchClientError, isHtmlResponseError, isKeboolaError, isManageError, isManagementClientAuthError, isManagementSessionMintError, isPlainObject, isQueryJobError, isQueueJobError, isRowLevelSecurityError, isStorageJobError, isSyncActionError, isTimeoutError, isValidationError, jobStatus, keboolaUID, lazy, manageErrorCode, nextCursorOf, parseLogLines, parseOrThrow, poller, queueSeries, readableReason, retryAfterSeconds, schemaGuidedMerge, series, shallowEqual };
1815
+ export { ApiError, HtmlResponseError, HttpContentType, HttpHeader, KeboolaError, KeboolaErrorType, KeboolaHttpHeader, ManagementClientAuthError, ManagementSessionMintError, QueryJobError, QueueJobError, Result, RowLevelSecurityError, SESSION_STORAGE_KEY, ServiceUnavailableError, StorageJobError, SyncActionError, UserError, ValidationError, asError, assert, coalesce, collectByCursor, collectByOffset, concurrent, createAdminAccount, createBranchRefs, createEmitter, createGenericFetchClient, createKeboola, createLocalStorage, createLoggingMiddleware, createMemoryStorage, createNullStorage, createPersistor, createPollRegistry, createProject, createQueryServiceSdk, createRetryMiddleware, createSessionStorage, createStore, createUiVersionMiddleware, dedupe, deepMerge, delay, emitter, ensure, failureOf, formatValidationIssues, generateUUID, isAbortError, isApiError, isEmptyDeep, isFetchClientError, isHtmlResponseError, isKeboolaError, isManageError, isManagementClientAuthError, isManagementSessionMintError, isPlainObject, isQueryJobError, isQueueJobError, isRowLevelSecurityError, isStorageJobError, isSyncActionError, isTimeoutError, isValidationError, iterateByCursor, jobStatus, keboolaUID, lazy, manageErrorCode, nextCursorOf, parseLogLines, parseOrThrow, poller, queueSeries, readableReason, retryAfterSeconds, schemaGuidedMerge, series };
2065
1816
 
2066
1817
  //# sourceMappingURL=index.js.map