@keboola/api-client 47.0.0 → 49.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.
- package/AGENTS.md +10 -4
- package/API-SURFACE.md +6 -3
- package/CHANGELOG.md +65 -0
- package/README.md +1 -1
- package/dist/{adminRoles-CvdIUkiC.d.ts → adminRoles-BX1gk3At.d.ts} +2 -2
- package/dist/{adminRoles-DGM8SuuF.d.cts → adminRoles-BbxFgfX-.d.cts} +2 -2
- package/dist/ai/index.cjs +0 -5
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.d.cts +2 -3
- package/dist/ai/index.d.ts +2 -3
- package/dist/ai/index.js +0 -5
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/types.d.cts +2 -2
- package/dist/ai/types.d.ts +2 -2
- package/dist/{appLogs-xW0-JQXg.d.ts → appLogs-DI2Y4imY.d.ts} +2 -2
- package/dist/{appLogs-Cxhm2Rkn.d.cts → appLogs-IhRA3xyv.d.cts} +2 -2
- package/dist/apps/index.cjs +3 -3
- package/dist/apps/index.cjs.map +1 -1
- package/dist/apps/index.d.cts +6 -3
- package/dist/apps/index.d.ts +6 -3
- package/dist/apps/index.js +3 -3
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/types.d.cts +2 -2
- package/dist/apps/types.d.ts +2 -2
- package/dist/assets/index.d.cts +1 -1
- package/dist/assets/index.d.ts +1 -1
- package/dist/auth/index.d.cts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/types.d.cts +1 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/{authClient-Bso5UaXS.d.ts → authClient-6Aau_4Zt.d.ts} +4 -4
- package/dist/{authClient-aud2dUZd.d.cts → authClient-B3P6WtWW.d.cts} +4 -4
- package/dist/billing/index.cjs +0 -1
- package/dist/billing/index.cjs.map +1 -1
- package/dist/billing/index.d.cts +27 -27
- package/dist/billing/index.d.ts +27 -27
- package/dist/billing/index.js +0 -1
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/types.d.cts +26 -22
- package/dist/billing/types.d.ts +26 -22
- package/dist/chat/index.d.cts +2 -2
- package/dist/chat/index.d.ts +2 -2
- package/dist/chat/types.d.cts +1 -1
- package/dist/chat/types.d.ts +1 -1
- package/dist/componentsMcp/index.d.cts +1 -1
- package/dist/componentsMcp/index.d.ts +1 -1
- package/dist/componentsMcp/types.d.cts +1 -1
- package/dist/componentsMcp/types.d.ts +1 -1
- package/dist/{configurations-DcpUlC8I.js → configurations-B44z6BSO.js} +2 -2
- package/dist/{configurations-DcpUlC8I.js.map → configurations-B44z6BSO.js.map} +1 -1
- package/dist/{configurations-Chg_JwJ1.js → configurations-CL0ouUMa.js} +3 -3
- package/dist/configurations-CL0ouUMa.js.map +1 -0
- package/dist/{configurations-BTRHVSRq.cjs → configurations-D9J3jh3g.cjs} +3 -3
- package/dist/configurations-D9J3jh3g.cjs.map +1 -0
- package/dist/{configurations-D_Rbs0Wl.cjs → configurations-Dkxsa3Uf.cjs} +2 -2
- package/dist/{configurations-D_Rbs0Wl.cjs.map → configurations-Dkxsa3Uf.cjs.map} +1 -1
- package/dist/constants/index.cjs +4 -1
- package/dist/constants/index.d.cts +4 -3
- package/dist/constants/index.d.ts +4 -3
- package/dist/constants/index.js +2 -2
- package/dist/{constants-a0jswUeK.cjs → constants-DErcRkWl.cjs} +95 -2
- package/dist/constants-DErcRkWl.cjs.map +1 -0
- package/dist/{constants-CA4UN2Xv.js → constants-VpSwBtCb.js} +78 -3
- package/dist/constants-VpSwBtCb.js.map +1 -0
- package/dist/dataScience/index.d.cts +2 -2
- package/dist/dataScience/index.d.ts +2 -2
- package/dist/dataScience/types.d.cts +2 -2
- package/dist/dataScience/types.d.ts +2 -2
- package/dist/developerPortal/index.d.cts +2 -2
- package/dist/developerPortal/index.d.ts +2 -2
- package/dist/developerPortal/types.d.cts +1 -1
- package/dist/developerPortal/types.d.ts +1 -1
- package/dist/domain/permissions/index.cjs +8 -43
- package/dist/domain/permissions/index.d.cts +7 -3
- package/dist/domain/permissions/index.d.ts +7 -3
- package/dist/domain/permissions/index.js +3 -39
- package/dist/domain/storageTable/index.d.cts +1 -1
- package/dist/domain/storageTable/index.d.ts +1 -1
- package/dist/editor/index.d.cts +2 -2
- package/dist/editor/index.d.ts +2 -2
- package/dist/editor/types.d.cts +1 -1
- package/dist/editor/types.d.ts +1 -1
- package/dist/encryption/index.d.cts +1 -1
- package/dist/encryption/index.d.ts +1 -1
- package/dist/encryption/types.d.cts +1 -1
- package/dist/encryption/types.d.ts +1 -1
- package/dist/import/index.d.cts +3 -3
- package/dist/import/index.d.ts +3 -3
- package/dist/{index-DTysQ_yn.d.cts → index-BM_fXKq5.d.cts} +5 -5
- package/dist/{index-XaPb6unB.d.cts → index-BPMr8PQJ.d.ts} +271 -35
- package/dist/{index-BnPmXDVP.d.ts → index-BT88-GpA.d.ts} +73 -3
- package/dist/{index-x_kS_5x_.d.cts → index-BVjhAkXW.d.cts} +4 -4
- package/dist/{index-CkwZ5x7E.d.cts → index-Be2dNJ_N.d.cts} +336 -169
- package/dist/{index-C2OAOK0s.d.ts → index-BiZR9BjN.d.ts} +4 -4
- package/dist/{index-B_MzjCeE.d.ts → index-C6oPUTWZ.d.ts} +3 -3
- package/dist/{index-r6YSe8B-.d.ts → index-CL4iKFic.d.cts} +271 -35
- package/dist/{index-URgNfi5L.d.cts → index-CbZQCDkD.d.cts} +3 -3
- package/dist/{index-XG5cO-4H.d.cts → index-CrrHvDiX.d.cts} +18 -13
- package/dist/{index-ZYvgoqgW.d.cts → index-CtQl-Iqw.d.cts} +4 -4
- package/dist/{index-BIP0PoMW.d.ts → index-D6JMbJ9b.d.ts} +18 -13
- package/dist/{index-Ds0tViQS.d.cts → index-DGKCTQkb.d.cts} +3 -3
- package/dist/{index-BeOd45XE.d.ts → index-DReKz9Zt.d.ts} +4 -4
- package/dist/{index-DUB0BwQv.d.cts → index-DYNVbgm8.d.cts} +4 -4
- package/dist/{index-DloFSSj3.d.ts → index-DhZTIejy.d.ts} +3 -3
- package/dist/{index-BGEuaZqI.d.cts → index-Dkb8CynB.d.cts} +21 -5
- package/dist/{index-_Va9wynk.d.ts → index-DorowSay.d.ts} +21 -5
- package/dist/{index-8ZjY7YD8.d.cts → index-PqJGDHHl.d.cts} +73 -3
- package/dist/{index-HSkjm3QW.d.ts → index-XcnkRVb0.d.ts} +5 -5
- package/dist/{index-Dp-a2DdI.d.ts → index-dgu6udMy.d.ts} +4 -4
- package/dist/{index-P1vR966i.d.ts → index-fMoM8SeH.d.cts} +4 -4
- package/dist/{index-P1vR966i.d.cts → index-fMoM8SeH.d.ts} +4 -4
- package/dist/{index-CAWy1qjR.d.ts → index-uGRdAORl.d.ts} +336 -169
- package/dist/index.cjs +458 -259
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +455 -260
- package/dist/index.js.map +1 -1
- package/dist/kaiAgent/index.cjs +1 -1
- package/dist/kaiAgent/index.d.cts +3 -3
- package/dist/kaiAgent/index.d.ts +3 -3
- package/dist/kaiAgent/index.js +1 -1
- package/dist/kaiAgent/types.d.cts +1 -1
- package/dist/kaiAgent/types.d.ts +1 -1
- package/dist/{kaiAgent-CBPbMwBh.js → kaiAgent-CYvrS8oZ.js} +12 -3
- package/dist/kaiAgent-CYvrS8oZ.js.map +1 -0
- package/dist/{kaiAgent-BmfUG8bB.cjs → kaiAgent-N2qbUFZm.cjs} +12 -3
- package/dist/kaiAgent-N2qbUFZm.cjs.map +1 -0
- package/dist/management/index.cjs +1 -1
- package/dist/management/index.d.cts +1 -1
- package/dist/management/index.d.ts +1 -1
- package/dist/management/index.js +1 -1
- package/dist/management/types.cjs +14 -0
- package/dist/management/types.cjs.map +1 -0
- package/dist/management/types.d.cts +2 -2
- package/dist/management/types.d.ts +2 -2
- package/dist/management/types.js +12 -1
- package/dist/management/types.js.map +1 -0
- package/dist/{management-BUGPJ1Bu.cjs → management-B1o6RpKF.cjs} +15 -14
- package/dist/management-B1o6RpKF.cjs.map +1 -0
- package/dist/{management-DAg2obYt.js → management-C9w3DNhs.js} +15 -14
- package/dist/management-C9w3DNhs.js.map +1 -0
- package/dist/metastore/index.d.cts +1 -1
- package/dist/metastore/index.d.ts +1 -1
- package/dist/metastore/types.d.cts +1 -1
- package/dist/metastore/types.d.ts +1 -1
- package/dist/microsoftGraph/index.d.cts +2 -2
- package/dist/microsoftGraph/index.d.ts +2 -2
- package/dist/microsoftGraph/types.d.cts +1 -1
- package/dist/microsoftGraph/types.d.ts +1 -1
- package/dist/{middleware-DU_5pFDW.cjs → middleware-CEP6uu_D.cjs} +4 -4
- package/dist/middleware-CEP6uu_D.cjs.map +1 -0
- package/dist/{middleware-CWaLMlG1.js → middleware-GOfx8Apu.js} +4 -4
- package/dist/middleware-GOfx8Apu.js.map +1 -0
- package/dist/notifications/index.d.cts +2 -2
- package/dist/notifications/index.d.ts +2 -2
- package/dist/notifications/types.d.cts +1 -1
- package/dist/notifications/types.d.ts +1 -1
- package/dist/oauth/index.d.cts +2 -2
- package/dist/oauth/index.d.ts +2 -2
- package/dist/oauth/types.d.cts +1 -1
- package/dist/oauth/types.d.ts +1 -1
- package/dist/omnisearch/index.d.cts +2 -2
- package/dist/omnisearch/index.d.ts +2 -2
- package/dist/omnisearch/types.d.cts +1 -1
- package/dist/omnisearch/types.d.ts +1 -1
- package/dist/project-ClH22nzH.js +86 -0
- package/dist/project-ClH22nzH.js.map +1 -0
- package/dist/{project-BMmfPhXg.d.ts → project-DTfBtIJs.d.ts} +4 -3
- package/dist/project-Rh4nXiWh.cjs +139 -0
- package/dist/project-Rh4nXiWh.cjs.map +1 -0
- package/dist/{project-dxCJbFay.d.cts → project-vOnvjo80.d.cts} +4 -3
- package/dist/queryService/index.d.cts +1 -1
- package/dist/queryService/index.d.ts +1 -1
- package/dist/queryService/types.d.cts +1 -1
- package/dist/queryService/types.d.ts +1 -1
- package/dist/queue/index.d.cts +3 -3
- package/dist/queue/index.d.ts +3 -3
- package/dist/queue/types.d.cts +1 -1
- package/dist/queue/types.d.ts +1 -1
- package/dist/scheduler/index.d.cts +2 -2
- package/dist/scheduler/index.d.ts +2 -2
- package/dist/scheduler/types.d.cts +1 -1
- package/dist/scheduler/types.d.ts +1 -1
- package/dist/sdk/configurations/index.cjs +1 -1
- package/dist/sdk/configurations/index.d.cts +2 -2
- package/dist/sdk/configurations/index.d.ts +2 -2
- package/dist/sdk/configurations/index.js +1 -1
- package/dist/sdk/developerPortal/index.cjs +1 -1
- package/dist/sdk/developerPortal/index.d.cts +3 -3
- package/dist/sdk/developerPortal/index.d.ts +3 -3
- package/dist/sdk/developerPortal/index.js +1 -1
- package/dist/sdk/kaiMemory/index.d.cts +1 -1
- package/dist/sdk/kaiMemory/index.d.ts +1 -1
- package/dist/sdk/kaiMemory/types.d.cts +1 -1
- package/dist/sdk/kaiMemory/types.d.ts +1 -1
- package/dist/sdk/queryService/index.d.cts +1 -1
- package/dist/sdk/queryService/index.d.ts +1 -1
- package/dist/sdk/semanticLayer/index.d.cts +1 -1
- package/dist/sdk/semanticLayer/index.d.ts +1 -1
- package/dist/sdk/semanticLayer/types.d.cts +1 -1
- package/dist/sdk/semanticLayer/types.d.ts +1 -1
- package/dist/sdk/tag/index.d.cts +2 -2
- package/dist/sdk/tag/index.d.ts +2 -2
- package/dist/sdk/tag/types.d.cts +1 -1
- package/dist/sdk/tag/types.d.ts +1 -1
- package/dist/sdk/vault/index.d.cts +1 -1
- package/dist/sdk/vault/index.d.ts +1 -1
- package/dist/status/index.d.cts +1 -1
- package/dist/status/index.d.ts +1 -1
- package/dist/storage/index.cjs +4 -1
- package/dist/storage/index.d.cts +3 -3
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +2 -2
- package/dist/storage/types.d.cts +6 -6
- package/dist/storage/types.d.ts +6 -6
- package/dist/{storage-DyR7hDdv.js → storage-CChfKlrb.js} +31 -3
- package/dist/storage-CChfKlrb.js.map +1 -0
- package/dist/{storage-yovv11k6.cjs → storage-Ci9gXgcw.cjs} +48 -2
- package/dist/storage-Ci9gXgcw.cjs.map +1 -0
- package/dist/stream/index.d.cts +2 -2
- package/dist/stream/index.d.ts +2 -2
- package/dist/stream/types.d.cts +1 -1
- package/dist/stream/types.d.ts +1 -1
- package/dist/syncActions/index.d.cts +2 -2
- package/dist/syncActions/index.d.ts +2 -2
- package/dist/syncActions/types.d.cts +1 -1
- package/dist/syncActions/types.d.ts +1 -1
- package/dist/telemetry/index.d.cts +2 -2
- package/dist/telemetry/index.d.ts +2 -2
- package/dist/telemetry/types.d.cts +1 -1
- package/dist/telemetry/types.d.ts +1 -1
- package/dist/{types-DHlXKVEM.d.ts → types-0R9-osUJ.d.ts} +3 -3
- package/dist/{types-CBrNIgEy.d.ts → types-302-NBaU.d.ts} +3 -3
- package/dist/{types-4HmtNuJf.d.ts → types-45O2dU2w.d.ts} +2 -2
- package/dist/{types-CZCPdPqv.d.cts → types-BAsYMltG.d.cts} +3 -3
- package/dist/{types-BiBBKcin.d.ts → types-BM6rri7-.d.ts} +3 -3
- package/dist/{types-BNPvFLgC.d.ts → types-BOT6TgOS.d.ts} +3 -4
- package/dist/{types-BiTn_JVW.d.cts → types-BT5e9TSQ.d.ts} +117 -37
- package/dist/{types-C2j6Jsie.d.ts → types-BUirSne-.d.ts} +3 -3
- package/dist/{types-BoH7NFCh.d.ts → types-BWzt1ju_.d.ts} +3 -3
- package/dist/{types-BjEiUOL6.d.ts → types-BXybSjn-.d.ts} +2 -2
- package/dist/{types-BIDKSQdc.d.ts → types-BZ--6pIt.d.ts} +169 -31
- package/dist/{types-B2ZLjagf.d.ts → types-BjwbzqJd.d.ts} +2 -2
- package/dist/{types-B6ozaDkl.d.cts → types-BnmsuDfH.d.cts} +2 -2
- package/dist/{types-Bx0TSdwF.d.cts → types-BrpIEj_N.d.ts} +2 -2
- package/dist/{types-BG0oWq8u.d.cts → types-C614wC5h.d.cts} +2 -2
- package/dist/{types-4CjbcUdD.d.cts → types-CTS2NSIb.d.cts} +2 -2
- package/dist/{types-BZBU3mwz.d.cts → types-CY8X39qv.d.cts} +3 -3
- package/dist/{types-Cw9UISvM.d.ts → types-CeqZuOEC.d.ts} +2 -2
- package/dist/{types-C3IQu1gV.d.ts → types-CfXqFz2e.d.ts} +5 -3
- package/dist/{types-BKIcow3B.d.cts → types-ChLWY8aU.d.cts} +2 -2
- package/dist/{types-B_3zoXA1.d.cts → types-CjNl7O7f.d.cts} +3 -3
- package/dist/{types-BwsE-pFo.d.cts → types-CkJxMoTk.d.cts} +2 -2
- package/dist/{types--qQPfxWt.d.cts → types-CpJhWBmH.d.cts} +2 -2
- package/dist/{types-DgIzXY-Y.d.ts → types-D2Pb_4FA.d.cts} +2 -2
- package/dist/{types-7DBpH7Rf.d.ts → types-D53zBV25.d.ts} +2 -2
- package/dist/{types-Dg8a7m7f.d.ts → types-D9ZKJYZk.d.ts} +2 -2
- package/dist/{types-BXgINefw.d.ts → types-DODAZKEm.d.ts} +2 -2
- package/dist/{types-BBbzWczQ.d.cts → types-DV7K07oX.d.cts} +3 -4
- package/dist/{types-TRJiPqJr.d.cts → types-DbXV0g8U.d.cts} +2 -2
- package/dist/{types-BcQ3j8xK.d.ts → types-DjadPty5.d.ts} +2 -2
- package/dist/{types-DWJVbskE.d.ts → types-DlhNay1n.d.ts} +2 -2
- package/dist/{types-DBJ8c3hN.d.cts → types-DmzSFOhK.d.cts} +2 -2
- package/dist/{types-B_1plf0y.d.cts → types-DpbrGDRf.d.cts} +2 -2
- package/dist/{types-ituiCs8g.d.ts → types-DqOxIujY.d.ts} +2 -2
- package/dist/{types-D8w9lyb8.d.cts → types-Duurgaqk.d.cts} +7 -3
- package/dist/{types-C7t_6FLh.d.ts → types-Dy6EdWPG.d.ts} +2 -2
- package/dist/{types-kbyIaA7p.d.cts → types-HmK8iKp5.d.cts} +3 -3
- package/dist/{types-BdF6NDvo.d.cts → types-JZ0Bdlpk.d.cts} +2 -2
- package/dist/{types-OkQWmonU.d.cts → types-O6XM48J8.d.cts} +2 -2
- package/dist/{types-CEw2IzWk.d.ts → types-RogkWzOu.d.ts} +2 -2
- package/dist/{types-C2JMisvL.d.ts → types-TmrPVMhy.d.cts} +117 -37
- package/dist/{types-ij6BpTzR.d.ts → types-_zKX6JmD.d.ts} +2 -2
- package/dist/{types-L50Y6ATu.d.cts → types-dn6MHur3.d.cts} +5 -3
- package/dist/{types-4bSZLxq3.d.cts → types-jN2KmMet.d.cts} +169 -31
- package/dist/{types-D51g4h9w.d.cts → types-jfPoUlO8.d.cts} +2 -2
- package/dist/{types-CMKIdreQ.d.cts → types-ptynVnkv.d.cts} +3 -3
- package/dist/{types-COQOzyac.d.ts → types-tdIo5FpR.d.ts} +7 -3
- package/dist/{types-DPDq8C4q.d.cts → types-vvw_H7wp.d.cts} +2 -2
- package/dist/vault/index.d.cts +1 -1
- package/dist/vault/index.d.ts +1 -1
- package/dist/vault/types.d.cts +1 -1
- package/dist/vault/types.d.ts +1 -1
- package/package.json +1 -1
- package/surface/ai.md +0 -1
- package/surface/apps.md +7 -7
- package/surface/billing.md +2 -2
- package/surface/kaiAgent.md +5 -4
- package/surface/management.md +3 -1
- package/surface/storage.md +3 -2
- package/dist/configurations-BTRHVSRq.cjs.map +0 -1
- package/dist/configurations-Chg_JwJ1.js.map +0 -1
- package/dist/constants-CA4UN2Xv.js.map +0 -1
- package/dist/constants-a0jswUeK.cjs.map +0 -1
- package/dist/domain/permissions/index.cjs.map +0 -1
- package/dist/domain/permissions/index.js.map +0 -1
- package/dist/kaiAgent-BmfUG8bB.cjs.map +0 -1
- package/dist/kaiAgent-CBPbMwBh.js.map +0 -1
- package/dist/management-BUGPJ1Bu.cjs.map +0 -1
- package/dist/management-DAg2obYt.js.map +0 -1
- package/dist/middleware-CWaLMlG1.js.map +0 -1
- package/dist/middleware-DU_5pFDW.cjs.map +0 -1
- package/dist/project-BXLFrWJ6.js +0 -45
- package/dist/project-BXLFrWJ6.js.map +0 -1
- package/dist/project-CpgplgCr.cjs +0 -62
- package/dist/project-CpgplgCr.cjs.map +0 -1
- package/dist/storage-DyR7hDdv.js.map +0 -1
- package/dist/storage-yovv11k6.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { t as createProject } from "./project-
|
|
1
|
+
import { t as createProject } from "./project-ClH22nzH.js";
|
|
2
2
|
import { t as collectByOffset } from "./collectByOffset-2XzJqmvr.js";
|
|
3
3
|
import { t as createAuthClient, v as collectByCursor, y as nextCursorOf } from "./authClient-2e8ZmzSP.js";
|
|
4
4
|
import { t as concurrent } from "./concurrent-BacWxPwi.js";
|
|
5
5
|
import { t as dedupe } from "./dedupe-Cky1gSUu.js";
|
|
6
6
|
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-B4iusp69.js";
|
|
7
7
|
import { n as createEmitter, t as createStore } from "./store-C9FQCHGe.js";
|
|
8
|
-
import { a as StorageJobError, c as
|
|
8
|
+
import { a as StorageJobError, c as retryAfterSeconds, d as manageErrorCode, f as series, l as readableReason, o as isStorageJobError, s as ServiceUnavailableError, t as createStorageClient, u as isManageError } from "./storage-CChfKlrb.js";
|
|
9
9
|
import { n as keboolaUID, t as createTagSdk } from "./tag-hh-1nhNr.js";
|
|
10
10
|
import { t as generateUUID } from "./generateUUID-Dr8l-aoc.js";
|
|
11
11
|
import { t as isPlainObject } from "./isPlainObject-LYW-03uB.js";
|
|
12
|
-
import { n as schemaGuidedMerge, r as isEmptyDeep, t as createConfigurationSdk } from "./configurations-
|
|
12
|
+
import { n as schemaGuidedMerge, r as isEmptyDeep, t as createConfigurationSdk } from "./configurations-B44z6BSO.js";
|
|
13
13
|
import { t as UserError } from "./UserError-By_Zckmc.js";
|
|
14
14
|
import { _ as KeboolaHttpHeader, a as isTimeoutError, d as normalizeBaseUrl, g as HttpStatus, i as isFetchClientError, m as CREDENTIAL_HEADERS, n as isAbortError, o as HttpContentType, p as ApiError, r as isApiError, s as HttpHeader, v as REDACTED, y as redactHeaders } from "./createFetchClient-CkHdS_IG.js";
|
|
15
15
|
import { n as HtmlResponseError, r as isHtmlResponseError } from "./validateConnectionStatus-DyrYpn0G.js";
|
|
@@ -20,8 +20,8 @@ import { n as isSyncActionError, t as SyncActionError } from "./SyncActionError-
|
|
|
20
20
|
import { i as parseOrThrow, n as formatValidationIssues, r as isValidationError, t as ValidationError } from "./ValidationError-DjhtNMfZ.js";
|
|
21
21
|
import { t as createGenericFetchClient } from "./createGenericFetchClient-CQdNcPC3.js";
|
|
22
22
|
import { t as createImportClient } from "./import-FWy_wQZ1.js";
|
|
23
|
-
import { n as isManagementClientAuthError, r as isManagementSessionMintError, t as createManagementClient } from "./management-
|
|
24
|
-
import {
|
|
23
|
+
import { n as isManagementClientAuthError, r as isManagementSessionMintError, t as createManagementClient } from "./management-C9w3DNhs.js";
|
|
24
|
+
import { l as ServiceId, u as ProjectFeature } from "./constants-VpSwBtCb.js";
|
|
25
25
|
import { t as createStorageTable } from "./storageTable-BldTNyEk.js";
|
|
26
26
|
import { i as createKaiMemorySdk } from "./kaiMemory-C9di17bd.js";
|
|
27
27
|
import { i as createSemanticLayerSdk } from "./semanticLayer-DvjS_nzo.js";
|
|
@@ -35,7 +35,7 @@ import { t as createComponentsMcpClient } from "./componentsMcp-CHobIsuU.js";
|
|
|
35
35
|
import { t as createDataScienceClient } from "./dataScience-AwPMeGfz.js";
|
|
36
36
|
import { createEditorClient } from "./editor/index.js";
|
|
37
37
|
import { createEncryptionClient } from "./encryption/index.js";
|
|
38
|
-
import { t as createKaiAgentClient } from "./kaiAgent-
|
|
38
|
+
import { t as createKaiAgentClient } from "./kaiAgent-CYvrS8oZ.js";
|
|
39
39
|
import { t as createMetastoreClient } from "./metastore-Ywq08DBz.js";
|
|
40
40
|
import { createNotificationsClient } from "./notifications/index.js";
|
|
41
41
|
import { t as createOauthClient } from "./oauth-GXmZ9agP.js";
|
|
@@ -47,7 +47,7 @@ import { createStreamClient } from "./stream/index.js";
|
|
|
47
47
|
import { t as createSyncActionsClient } from "./syncActions-DM8vP7p3.js";
|
|
48
48
|
import { createTelemetryClient } from "./telemetry/index.js";
|
|
49
49
|
import { createVaultClient } from "./vault/index.js";
|
|
50
|
-
import { n as isUnauthorized, t as createBearerAuthMiddleware } from "./middleware-
|
|
50
|
+
import { n as isUnauthorized, t as createBearerAuthMiddleware } from "./middleware-GOfx8Apu.js";
|
|
51
51
|
import { createQueryServiceSdk } from "./sdk/queryService/index.js";
|
|
52
52
|
import * as z$1 from "zod";
|
|
53
53
|
//#region src/utils/assert.ts
|
|
@@ -260,6 +260,47 @@ const createPollRegistry = ({ limit = DEFAULT_LIMIT } = {}) => {
|
|
|
260
260
|
};
|
|
261
261
|
};
|
|
262
262
|
//#endregion
|
|
263
|
+
//#region src/utils/async/queueSeries.ts
|
|
264
|
+
const isPromiseLike = (value) => (typeof value === "object" && value !== null || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
265
|
+
/**
|
|
266
|
+
* Queues tasks added over time so a slower earlier task cannot finish after and overwrite a later one.
|
|
267
|
+
* Each `add` returns its task's result; a rejection does not stop the remaining queue.
|
|
268
|
+
*/
|
|
269
|
+
const queueSeries = () => {
|
|
270
|
+
let tail = null;
|
|
271
|
+
const add = (task) => {
|
|
272
|
+
if (tail !== null) {
|
|
273
|
+
const result = tail.then(task);
|
|
274
|
+
tail = result.then(() => void 0, () => void 0);
|
|
275
|
+
return result;
|
|
276
|
+
}
|
|
277
|
+
let value;
|
|
278
|
+
try {
|
|
279
|
+
value = task();
|
|
280
|
+
} catch (error) {
|
|
281
|
+
return Promise.reject(error);
|
|
282
|
+
}
|
|
283
|
+
if (!isPromiseLike(value)) return Promise.resolve(value);
|
|
284
|
+
const result = Promise.resolve(value);
|
|
285
|
+
tail = result.then(() => void 0, () => void 0);
|
|
286
|
+
return result;
|
|
287
|
+
};
|
|
288
|
+
const onIdle = async () => {
|
|
289
|
+
while (tail !== null) {
|
|
290
|
+
const current = tail;
|
|
291
|
+
await current;
|
|
292
|
+
if (tail === current) {
|
|
293
|
+
tail = null;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
return {
|
|
299
|
+
add,
|
|
300
|
+
onIdle
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
//#endregion
|
|
263
304
|
//#region src/utils/deepMerge.ts
|
|
264
305
|
/**
|
|
265
306
|
* Recursively merge `patch` into `base`. Plain-object values are merged key-by-key; every
|
|
@@ -317,6 +358,10 @@ const createWebStorage = (pick) => {
|
|
|
317
358
|
},
|
|
318
359
|
removeItem: (key) => {
|
|
319
360
|
storage.removeItem(key);
|
|
361
|
+
},
|
|
362
|
+
withLock: async (name, task) => {
|
|
363
|
+
if (typeof navigator === "undefined" || !("locks" in navigator)) return task();
|
|
364
|
+
return navigator.locks.request(`keboola:${name}`, { mode: "exclusive" }, task);
|
|
320
365
|
}
|
|
321
366
|
};
|
|
322
367
|
};
|
|
@@ -325,62 +370,56 @@ const createSessionStorage = () => createWebStorage(() => "sessionStorage" in gl
|
|
|
325
370
|
//#endregion
|
|
326
371
|
//#region src/utils/persistor/persistor.ts
|
|
327
372
|
const createPersistor = ({ storage = createNullStorage(), key, schema, defaultValue, encode = JSON.stringify, decode = JSON.parse }) => {
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const hasPersistedValue = () => {
|
|
336
|
-
try {
|
|
337
|
-
return !!storage.getItem(key);
|
|
338
|
-
} catch (err) {
|
|
339
|
-
console.warn(`createPersistor: failed to read "${key}", assuming empty`, err);
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
const hydrate = () => {
|
|
344
|
-
let raw;
|
|
345
|
-
try {
|
|
346
|
-
raw = storage.getItem(key);
|
|
347
|
-
} catch (err) {
|
|
348
|
-
console.warn(`createPersistor: failed to read "${key}", using default`, err);
|
|
349
|
-
return defaultValue;
|
|
350
|
-
}
|
|
351
|
-
if (raw === null) return defaultValue;
|
|
373
|
+
const writes = queueSeries();
|
|
374
|
+
const _load = async () => {
|
|
375
|
+
const raw = await storage.getItem(key);
|
|
376
|
+
if (raw === null) return {
|
|
377
|
+
value: defaultValue,
|
|
378
|
+
corrupt: false
|
|
379
|
+
};
|
|
352
380
|
let decoded;
|
|
353
381
|
try {
|
|
354
382
|
decoded = decode(raw);
|
|
355
383
|
} catch (err) {
|
|
356
|
-
console.warn(`createPersistor: failed to decode "${key}"
|
|
357
|
-
|
|
358
|
-
|
|
384
|
+
console.warn(`createPersistor: failed to decode "${key}"`, err);
|
|
385
|
+
return {
|
|
386
|
+
value: defaultValue,
|
|
387
|
+
corrupt: true
|
|
388
|
+
};
|
|
359
389
|
}
|
|
360
390
|
const parsed = schema.safeParse(decoded);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
391
|
+
return parsed.success ? {
|
|
392
|
+
value: parsed.data,
|
|
393
|
+
corrupt: false
|
|
394
|
+
} : {
|
|
395
|
+
value: defaultValue,
|
|
396
|
+
corrupt: true
|
|
397
|
+
};
|
|
364
398
|
};
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
storage.setItem(key, raw);
|
|
375
|
-
} catch (err) {
|
|
376
|
-
console.warn(`createPersistor: failed to write "${key}"`, err);
|
|
377
|
-
}
|
|
399
|
+
const remove = () => writes.add(() => storage.removeItem(key));
|
|
400
|
+
const write = (value) => writes.add(() => storage.setItem(key, encode(value)));
|
|
401
|
+
const read = async () => {
|
|
402
|
+
await writes.onIdle();
|
|
403
|
+
const parsed = await _load();
|
|
404
|
+
if (parsed.corrupt) remove().catch((err) => {
|
|
405
|
+
console.warn(`createPersistor: failed to drop the corrupt "${key}"`, err);
|
|
406
|
+
});
|
|
407
|
+
return parsed.value;
|
|
378
408
|
};
|
|
409
|
+
const modify = (change) => writes.add(async () => {
|
|
410
|
+
const next = change((await _load()).value);
|
|
411
|
+
await storage.setItem(key, encode(next));
|
|
412
|
+
});
|
|
413
|
+
const cell = {
|
|
414
|
+
read,
|
|
415
|
+
write,
|
|
416
|
+
modify,
|
|
417
|
+
remove
|
|
418
|
+
};
|
|
419
|
+
const locked = (task) => storage.withLock ? storage.withLock(key, () => task(cell)) : task(cell);
|
|
379
420
|
return {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
clear,
|
|
383
|
-
hasPersistedValue
|
|
421
|
+
...cell,
|
|
422
|
+
locked
|
|
384
423
|
};
|
|
385
424
|
};
|
|
386
425
|
//#endregion
|
|
@@ -1072,159 +1111,6 @@ const createLegacyKeboola = (options = {}) => {
|
|
|
1072
1111
|
};
|
|
1073
1112
|
};
|
|
1074
1113
|
//#endregion
|
|
1075
|
-
//#region src/keboola/bearer/credentials/renewal.ts
|
|
1076
|
-
const renewalGrant = (credential) => credential.type === "token" ? {
|
|
1077
|
-
type: "token",
|
|
1078
|
-
refreshToken: credential.refreshToken
|
|
1079
|
-
} : {
|
|
1080
|
-
type: "cookie",
|
|
1081
|
-
sessionId: credential.sessionId
|
|
1082
|
-
};
|
|
1083
|
-
const renew = async (client, grant) => {
|
|
1084
|
-
if (grant.type === "cookie") {
|
|
1085
|
-
const { accessToken, expiresIn, sessionId } = await client.token.refreshWithSession({ sessionId: grant.sessionId });
|
|
1086
|
-
return {
|
|
1087
|
-
type: "cookie",
|
|
1088
|
-
accessToken,
|
|
1089
|
-
expiresIn,
|
|
1090
|
-
sessionId
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
const { accessToken, expiresIn, refreshToken } = await client.token.refreshWithToken({ refreshToken: grant.refreshToken });
|
|
1094
|
-
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
1095
|
-
return {
|
|
1096
|
-
type: "token",
|
|
1097
|
-
accessToken,
|
|
1098
|
-
expiresIn,
|
|
1099
|
-
refreshToken
|
|
1100
|
-
};
|
|
1101
|
-
};
|
|
1102
|
-
//#endregion
|
|
1103
|
-
//#region src/keboola/bearer/credentials/credentials.ts
|
|
1104
|
-
const DEFAULT_REFRESH_THRESHOLD = .9;
|
|
1105
|
-
const signInEnded = () => new KeboolaError(KeboolaErrorType.SignInEnded);
|
|
1106
|
-
const toRestoreStatus = (outcome) => {
|
|
1107
|
-
if (outcome === void 0 || outcome === "skipped") return "empty";
|
|
1108
|
-
if (outcome === "refused") return "expired";
|
|
1109
|
-
return outcome;
|
|
1110
|
-
};
|
|
1111
|
-
const createCredentials = ({ state, persistor, middlewares, refreshThreshold = DEFAULT_REFRESH_THRESHOLD, onSignedOut, onExpired }) => {
|
|
1112
|
-
const rotationMap = /* @__PURE__ */ new Map();
|
|
1113
|
-
const generations = /* @__PURE__ */ new Map();
|
|
1114
|
-
const generationOf = (baseUrl) => generations.get(baseUrl) ?? 0;
|
|
1115
|
-
const refresh = async (baseUrl, grant) => {
|
|
1116
|
-
const client = createAuthClient({
|
|
1117
|
-
baseUrl,
|
|
1118
|
-
middlewares
|
|
1119
|
-
});
|
|
1120
|
-
const epochBefore = Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1121
|
-
const generationBefore = generationOf(baseUrl);
|
|
1122
|
-
const refreshed = await Result.tryCatchAsync(() => renew(client, grant));
|
|
1123
|
-
return Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) === epochBefore && generationOf(baseUrl) === generationBefore ? refreshed : Result.failure(signInEnded());
|
|
1124
|
-
};
|
|
1125
|
-
/**
|
|
1126
|
-
* A stack's teardown, from the credential's side.
|
|
1127
|
-
*
|
|
1128
|
-
* - Bumps the generation, so an in-flight rotation can no longer write.
|
|
1129
|
-
* - Drops the deduped entry, so nothing joins that rotation.
|
|
1130
|
-
*/
|
|
1131
|
-
const forget = (baseUrl) => {
|
|
1132
|
-
generations.set(baseUrl, generationOf(baseUrl) + 1);
|
|
1133
|
-
rotationMap.delete(baseUrl);
|
|
1134
|
-
};
|
|
1135
|
-
/**
|
|
1136
|
-
* The rotation, and the one place a credential is declared dead.
|
|
1137
|
-
*
|
|
1138
|
-
* - Renews by the credential's own kind: the refresh token, or the session id with the cookie.
|
|
1139
|
-
* - A refused refresh token or session is unambiguous.
|
|
1140
|
-
* - The triggering 401 is not (an unreachable project answers the same), so never sign out on a replay.
|
|
1141
|
-
*/
|
|
1142
|
-
const rotateOnce = async (baseUrl) => {
|
|
1143
|
-
const credential = state.auth.requireCredential(baseUrl);
|
|
1144
|
-
if (!credential.success) return credential;
|
|
1145
|
-
const refreshed = await refresh(baseUrl, renewalGrant(credential.data));
|
|
1146
|
-
if (!refreshed.success) {
|
|
1147
|
-
if (isUnauthorized(refreshed.error)) expire(baseUrl);
|
|
1148
|
-
return refreshed;
|
|
1149
|
-
}
|
|
1150
|
-
return Result.map(state.auth.applyRefresh(baseUrl, refreshed.data), () => refreshed.data.accessToken);
|
|
1151
|
-
};
|
|
1152
|
-
const rotate = (baseUrl) => ensure(rotationMap, baseUrl, () => dedupe(() => rotateOnce(baseUrl)))();
|
|
1153
|
-
const restoreStack = async (baseUrl, grant) => {
|
|
1154
|
-
if (!state.auth.startRestore(baseUrl).success) return "unreachable";
|
|
1155
|
-
const refreshed = await refresh(baseUrl, grant);
|
|
1156
|
-
if (!refreshed.success) {
|
|
1157
|
-
state.auth.cancelRestore(baseUrl);
|
|
1158
|
-
return isUnauthorized(refreshed.error) ? "refused" : "unreachable";
|
|
1159
|
-
}
|
|
1160
|
-
state.auth.authenticate(baseUrl, refreshed.data);
|
|
1161
|
-
return "restored";
|
|
1162
|
-
};
|
|
1163
|
-
const restoreProjects = (baseUrl, projects) => {
|
|
1164
|
-
for (const { projectId } of projects) state.projects.open(baseUrl, projectId);
|
|
1165
|
-
};
|
|
1166
|
-
/**
|
|
1167
|
-
* Every persisted stack back into the table, with whatever credential it can hand back.
|
|
1168
|
-
*
|
|
1169
|
-
* - Never writes the scope. `lastActive` is what was scoped when the session was stored, for the
|
|
1170
|
-
* caller to select.
|
|
1171
|
-
* - `status` reports what became of `lastActive`'s credential; the client reads it to decide
|
|
1172
|
-
* when persistence may start.
|
|
1173
|
-
*/
|
|
1174
|
-
const restore = async () => {
|
|
1175
|
-
const { stacks, current } = persistor.hydrate();
|
|
1176
|
-
const scoped = stacks.find(({ baseUrl }) => baseUrl === current?.baseUrl);
|
|
1177
|
-
const restored = stacks.map(async ({ baseUrl, credential, projects }) => {
|
|
1178
|
-
state.stacks.ensure(baseUrl);
|
|
1179
|
-
if (!credential) return "unreachable";
|
|
1180
|
-
if (Result.unwrapOr(state.auth.getEpoch(baseUrl), 0) > 0) return "skipped";
|
|
1181
|
-
const outcome = await restoreStack(baseUrl, credential);
|
|
1182
|
-
if (outcome === "restored") restoreProjects(baseUrl, projects);
|
|
1183
|
-
return outcome;
|
|
1184
|
-
});
|
|
1185
|
-
const results = await Promise.all(restored);
|
|
1186
|
-
const scopedOutcome = scoped?.credential ? results[stacks.indexOf(scoped)] : void 0;
|
|
1187
|
-
return {
|
|
1188
|
-
lastActive: current,
|
|
1189
|
-
status: toRestoreStatus(scopedOutcome)
|
|
1190
|
-
};
|
|
1191
|
-
};
|
|
1192
|
-
const isStale = (baseUrl) => {
|
|
1193
|
-
const ageing = Result.map(state.auth.requireCredential(baseUrl), ({ issuedAt, expiresIn }) => Date.now() >= issuedAt + expiresIn * 1e3 * refreshThreshold);
|
|
1194
|
-
return Result.unwrapOr(ageing, false);
|
|
1195
|
-
};
|
|
1196
|
-
const signOut = (baseUrl) => {
|
|
1197
|
-
rotationMap.delete(baseUrl);
|
|
1198
|
-
const signedOut = state.auth.signOut(baseUrl);
|
|
1199
|
-
onSignedOut?.(baseUrl);
|
|
1200
|
-
return signedOut;
|
|
1201
|
-
};
|
|
1202
|
-
const expire = (baseUrl) => {
|
|
1203
|
-
if (!state.auth.notifyExpired(baseUrl)) return;
|
|
1204
|
-
signOut(baseUrl);
|
|
1205
|
-
onExpired?.(baseUrl);
|
|
1206
|
-
};
|
|
1207
|
-
const renewIfStale = async (baseUrl) => {
|
|
1208
|
-
if (isStale(baseUrl)) await rotate(baseUrl);
|
|
1209
|
-
};
|
|
1210
|
-
const middleware = (baseUrl) => createBearerAuthMiddleware({ getAccessToken: async ({ forceRefresh = false } = {}) => {
|
|
1211
|
-
if (forceRefresh) {
|
|
1212
|
-
if (!state.auth.requireCredential(baseUrl).success) return null;
|
|
1213
|
-
return Result.unwrap(await rotate(baseUrl));
|
|
1214
|
-
}
|
|
1215
|
-
await renewIfStale(baseUrl);
|
|
1216
|
-
return state.auth.getAccessToken(baseUrl);
|
|
1217
|
-
} });
|
|
1218
|
-
return {
|
|
1219
|
-
middleware,
|
|
1220
|
-
rotate,
|
|
1221
|
-
renewIfStale,
|
|
1222
|
-
restore,
|
|
1223
|
-
signOut,
|
|
1224
|
-
forget
|
|
1225
|
-
};
|
|
1226
|
-
};
|
|
1227
|
-
//#endregion
|
|
1228
1114
|
//#region src/keboola/bearer/state/factories.ts
|
|
1229
1115
|
/**
|
|
1230
1116
|
* Everything the table constructs: the entries themselves, and the failures reading them produces.
|
|
@@ -1242,10 +1128,17 @@ const authenticatedAuth = (credential) => ({
|
|
|
1242
1128
|
status: "authenticated",
|
|
1243
1129
|
credential
|
|
1244
1130
|
});
|
|
1245
|
-
const
|
|
1131
|
+
const credential = (input) => ({
|
|
1246
1132
|
...input,
|
|
1247
1133
|
issuedAt: Date.now()
|
|
1248
1134
|
});
|
|
1135
|
+
const grant = (credential) => credential.type === "token" ? {
|
|
1136
|
+
type: "token",
|
|
1137
|
+
refreshToken: credential.refreshToken
|
|
1138
|
+
} : {
|
|
1139
|
+
type: "cookie",
|
|
1140
|
+
sessionId: credential.sessionId
|
|
1141
|
+
};
|
|
1249
1142
|
const expiredCredential = (credential) => ({
|
|
1250
1143
|
...credential,
|
|
1251
1144
|
issuedAt: Date.now() - credential.expiresIn * 1e3
|
|
@@ -1254,7 +1147,8 @@ const stack = (baseUrl) => ({
|
|
|
1254
1147
|
baseUrl,
|
|
1255
1148
|
context: "idle",
|
|
1256
1149
|
epoch: 0,
|
|
1257
|
-
auth: anonymousAuth()
|
|
1150
|
+
auth: anonymousAuth(),
|
|
1151
|
+
retained: null
|
|
1258
1152
|
});
|
|
1259
1153
|
const project = (baseUrl, projectId) => ({
|
|
1260
1154
|
id: projectEntryId(baseUrl, projectId),
|
|
@@ -1286,7 +1180,8 @@ const Entry = {
|
|
|
1286
1180
|
anonymousAuth,
|
|
1287
1181
|
restoringAuth,
|
|
1288
1182
|
authenticatedAuth,
|
|
1289
|
-
|
|
1183
|
+
credential,
|
|
1184
|
+
grant,
|
|
1290
1185
|
expiredCredential
|
|
1291
1186
|
};
|
|
1292
1187
|
/**
|
|
@@ -1304,7 +1199,8 @@ const Errors = {
|
|
|
1304
1199
|
notReady: () => new KeboolaError(KeboolaErrorType.NotReady),
|
|
1305
1200
|
alreadyRestoring: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" is already being restored`),
|
|
1306
1201
|
notRestoring: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" is not being restored`),
|
|
1307
|
-
|
|
1202
|
+
grantTypeChanged: (from, to) => /* @__PURE__ */ new Error(`A ${from} grant cannot become ${to}`),
|
|
1203
|
+
nothingRetained: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" retains no credential`),
|
|
1308
1204
|
missingProject: (id) => /* @__PURE__ */ new Error(`No project "${id}"`)
|
|
1309
1205
|
};
|
|
1310
1206
|
const authenticated = (auth) => auth.status === "authenticated" ? Result.success(auth.credential) : Result.failure(Errors.notAuthenticated());
|
|
@@ -1349,25 +1245,37 @@ const createAuth = ({ stacks, projects, expiry }) => {
|
|
|
1349
1245
|
return stacks.set({
|
|
1350
1246
|
...stack,
|
|
1351
1247
|
epoch: stack.epoch + 1,
|
|
1352
|
-
auth: Entry.authenticatedAuth(Entry.
|
|
1248
|
+
auth: Entry.authenticatedAuth(Entry.credential(input)),
|
|
1249
|
+
retained: null
|
|
1353
1250
|
});
|
|
1354
1251
|
});
|
|
1355
|
-
const applyRefresh = (baseUrl, input) => Result.andThen(stacks.requireCredential(baseUrl), (credential) => credential.type !== input.type ? Result.failure(Errors.
|
|
1252
|
+
const applyRefresh = (baseUrl, input) => Result.andThen(stacks.requireCredential(baseUrl), (credential) => credential.type !== input.type ? Result.failure(Errors.grantTypeChanged(credential.type, input.type)) : Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1356
1253
|
...stack,
|
|
1357
|
-
auth: Entry.authenticatedAuth(Entry.
|
|
1254
|
+
auth: Entry.authenticatedAuth(Entry.credential(input))
|
|
1358
1255
|
})));
|
|
1359
1256
|
const forceExpire = (baseUrl) => Result.andThen(stacks.requireCredential(baseUrl), (credential) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1360
1257
|
...stack,
|
|
1361
1258
|
auth: Entry.authenticatedAuth(Entry.expiredCredential(credential))
|
|
1362
1259
|
})));
|
|
1363
|
-
const signOut = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => {
|
|
1260
|
+
const signOut = (baseUrl, { retain = false } = {}) => Result.map(stacks.get(baseUrl), (stack) => {
|
|
1364
1261
|
projects.closeAll(baseUrl);
|
|
1262
|
+
const retained = retain ? Result.unwrapOr(Result.map(authenticated(stack.auth), (credential) => ({ grant: Entry.grant(credential) })), stack.retained) : null;
|
|
1365
1263
|
return stacks.set({
|
|
1366
1264
|
...stack,
|
|
1367
1265
|
epoch: stack.epoch + 1,
|
|
1368
|
-
auth: Entry.anonymousAuth()
|
|
1266
|
+
auth: Entry.anonymousAuth(),
|
|
1267
|
+
retained
|
|
1369
1268
|
});
|
|
1370
1269
|
});
|
|
1270
|
+
const retain = (baseUrl, retained) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1271
|
+
...stack,
|
|
1272
|
+
retained
|
|
1273
|
+
}));
|
|
1274
|
+
const dropRetained = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1275
|
+
...stack,
|
|
1276
|
+
retained: null
|
|
1277
|
+
}));
|
|
1278
|
+
const requireRetained = (baseUrl) => Result.andThen(stacks.get(baseUrl), (stack) => stack.retained ? Result.success(stack.retained) : Result.failure(Errors.nothingRetained(baseUrl)));
|
|
1371
1279
|
const getEpoch = (baseUrl) => Result.map(stacks.get(baseUrl), (stack) => stack.epoch);
|
|
1372
1280
|
const getAccessToken = (baseUrl) => Result.unwrapOr(Result.map(stacks.requireCredential(baseUrl), ({ accessToken }) => accessToken), null);
|
|
1373
1281
|
return {
|
|
@@ -1377,6 +1285,9 @@ const createAuth = ({ stacks, projects, expiry }) => {
|
|
|
1377
1285
|
applyRefresh,
|
|
1378
1286
|
forceExpire,
|
|
1379
1287
|
signOut,
|
|
1288
|
+
retain,
|
|
1289
|
+
dropRetained,
|
|
1290
|
+
requireRetained,
|
|
1380
1291
|
notifyExpired: expiry.report,
|
|
1381
1292
|
requireCredential: stacks.requireCredential,
|
|
1382
1293
|
getEpoch,
|
|
@@ -1630,6 +1541,204 @@ const createState = (defaultBaseUrl) => {
|
|
|
1630
1541
|
};
|
|
1631
1542
|
};
|
|
1632
1543
|
//#endregion
|
|
1544
|
+
//#region src/keboola/bearer/credentials/renewal.ts
|
|
1545
|
+
const renew = async (client, grant) => {
|
|
1546
|
+
if (grant.type === "cookie") {
|
|
1547
|
+
const { accessToken, expiresIn, sessionId } = await client.token.refreshWithSession({ sessionId: grant.sessionId });
|
|
1548
|
+
return {
|
|
1549
|
+
type: "cookie",
|
|
1550
|
+
accessToken,
|
|
1551
|
+
expiresIn,
|
|
1552
|
+
sessionId
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
const { accessToken, expiresIn, refreshToken } = await client.token.refreshWithToken({ refreshToken: grant.refreshToken });
|
|
1556
|
+
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
1557
|
+
return {
|
|
1558
|
+
type: "token",
|
|
1559
|
+
accessToken,
|
|
1560
|
+
expiresIn,
|
|
1561
|
+
refreshToken
|
|
1562
|
+
};
|
|
1563
|
+
};
|
|
1564
|
+
//#endregion
|
|
1565
|
+
//#region src/keboola/bearer/credentials/credentials.ts
|
|
1566
|
+
const DEFAULT_REFRESH_THRESHOLD = .9;
|
|
1567
|
+
const signInEnded = () => new KeboolaError(KeboolaErrorType.SignInEnded);
|
|
1568
|
+
const toRestoreStatus = (outcome) => {
|
|
1569
|
+
if (outcome === void 0 || outcome === "skipped") return "empty";
|
|
1570
|
+
if (outcome === "refused") return "expired";
|
|
1571
|
+
return outcome;
|
|
1572
|
+
};
|
|
1573
|
+
const createCredentials = ({ state, persistor, middlewares, refreshThreshold = DEFAULT_REFRESH_THRESHOLD, onSignedOut, onExpired }) => {
|
|
1574
|
+
const rotationMap = /* @__PURE__ */ new Map();
|
|
1575
|
+
const generations = /* @__PURE__ */ new Map();
|
|
1576
|
+
const generationOf = (baseUrl) => generations.get(baseUrl) ?? 0;
|
|
1577
|
+
const refresh = async (baseUrl, grant) => {
|
|
1578
|
+
const client = createAuthClient({
|
|
1579
|
+
baseUrl,
|
|
1580
|
+
middlewares
|
|
1581
|
+
});
|
|
1582
|
+
const epochBefore = Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1583
|
+
const generationBefore = generationOf(baseUrl);
|
|
1584
|
+
const refreshed = await Result.tryCatchAsync(() => renew(client, grant));
|
|
1585
|
+
return Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) === epochBefore && generationOf(baseUrl) === generationBefore ? refreshed : Result.failure(signInEnded());
|
|
1586
|
+
};
|
|
1587
|
+
/**
|
|
1588
|
+
* A stack's teardown, from the credential's side.
|
|
1589
|
+
*
|
|
1590
|
+
* - Bumps the generation, so an in-flight rotation can no longer write.
|
|
1591
|
+
* - Drops the deduped entry, so nothing joins that rotation.
|
|
1592
|
+
*/
|
|
1593
|
+
const forget = (baseUrl) => {
|
|
1594
|
+
generations.set(baseUrl, generationOf(baseUrl) + 1);
|
|
1595
|
+
rotationMap.delete(baseUrl);
|
|
1596
|
+
};
|
|
1597
|
+
/**
|
|
1598
|
+
* The rotation, and the one place a credential is declared dead.
|
|
1599
|
+
*
|
|
1600
|
+
* - Renews by the credential's grant: the refresh token, or the session id with the cookie.
|
|
1601
|
+
* - A refused refresh token or session is unambiguous.
|
|
1602
|
+
* - The triggering 401 is not (an unreachable project answers the same), so never sign out on a replay.
|
|
1603
|
+
*/
|
|
1604
|
+
const getGrantForRotation = async (store, baseUrl, credential) => {
|
|
1605
|
+
const epochBefore = Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1606
|
+
const generationBefore = generationOf(baseUrl);
|
|
1607
|
+
const hydrated = await Result.tryCatchAsync(() => store.read());
|
|
1608
|
+
if (!hydrated.success) return hydrated;
|
|
1609
|
+
if (Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) !== epochBefore || generationOf(baseUrl) !== generationBefore) return Result.failure(signInEnded());
|
|
1610
|
+
const persistedStack = hydrated.data.stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
1611
|
+
if (persistedStack && persistedStack.credential === null) return Result.failure(signInEnded());
|
|
1612
|
+
return Result.success(persistedStack?.credential ?? Entry.grant(credential));
|
|
1613
|
+
};
|
|
1614
|
+
const rotateOnce = async (baseUrl) => persistor.locked(async (store) => {
|
|
1615
|
+
const credential = state.auth.requireCredential(baseUrl);
|
|
1616
|
+
if (!credential.success) return credential;
|
|
1617
|
+
const grant = await getGrantForRotation(store, baseUrl, credential.data);
|
|
1618
|
+
if (!grant.success) return grant;
|
|
1619
|
+
const refreshed = await refresh(baseUrl, grant.data);
|
|
1620
|
+
if (!refreshed.success) {
|
|
1621
|
+
if (isUnauthorized(refreshed.error)) await expire(baseUrl, store);
|
|
1622
|
+
return refreshed;
|
|
1623
|
+
}
|
|
1624
|
+
const accessToken = Result.map(state.auth.applyRefresh(baseUrl, refreshed.data), () => refreshed.data.accessToken);
|
|
1625
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1626
|
+
return accessToken;
|
|
1627
|
+
});
|
|
1628
|
+
const rotate = (baseUrl) => ensure(rotationMap, baseUrl, () => dedupe(() => rotateOnce(baseUrl)))();
|
|
1629
|
+
const restoreStack = async (baseUrl, grant, retained = false) => persistor.locked(async (store) => {
|
|
1630
|
+
const storedStack = (await store.read()).stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
1631
|
+
const latestGrant = retained ? storedStack?.retained?.grant : storedStack?.credential;
|
|
1632
|
+
if (storedStack && !latestGrant) return "skipped";
|
|
1633
|
+
if (!state.auth.startRestore(baseUrl).success) return "unreachable";
|
|
1634
|
+
const refreshed = await refresh(baseUrl, latestGrant ?? grant);
|
|
1635
|
+
if (!refreshed.success) {
|
|
1636
|
+
state.auth.cancelRestore(baseUrl);
|
|
1637
|
+
if (isUnauthorized(refreshed.error)) {
|
|
1638
|
+
if (retained) state.auth.dropRetained(baseUrl);
|
|
1639
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1640
|
+
return "refused";
|
|
1641
|
+
}
|
|
1642
|
+
return "unreachable";
|
|
1643
|
+
}
|
|
1644
|
+
state.auth.authenticate(baseUrl, refreshed.data);
|
|
1645
|
+
if (!state.auth.requireCredential(baseUrl).success) return "unreachable";
|
|
1646
|
+
if (retained) state.auth.dropRetained(baseUrl);
|
|
1647
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1648
|
+
return "restored";
|
|
1649
|
+
});
|
|
1650
|
+
const restoreProjects = (baseUrl, projects) => {
|
|
1651
|
+
for (const { projectId } of projects) state.projects.open(baseUrl, projectId);
|
|
1652
|
+
};
|
|
1653
|
+
/**
|
|
1654
|
+
* Every persisted stack back into the table, with whatever credential it can hand back.
|
|
1655
|
+
*
|
|
1656
|
+
* - Never writes the scope. `lastActive` is what was scoped when the session was stored, for the
|
|
1657
|
+
* caller to select.
|
|
1658
|
+
* - `status` reports what became of `lastActive`'s credential; the client reads it to decide
|
|
1659
|
+
* when persistence may start.
|
|
1660
|
+
*/
|
|
1661
|
+
const restore = async () => {
|
|
1662
|
+
const hydrated = await persistor.locked((store) => store.read()).catch((error) => {
|
|
1663
|
+
console.warn("createCredentials: the stored session could not be read", error);
|
|
1664
|
+
return null;
|
|
1665
|
+
});
|
|
1666
|
+
if (hydrated === null) return {
|
|
1667
|
+
lastActive: null,
|
|
1668
|
+
status: "unreachable"
|
|
1669
|
+
};
|
|
1670
|
+
const { stacks, current } = hydrated;
|
|
1671
|
+
const scoped = stacks.find(({ baseUrl }) => baseUrl === current?.baseUrl);
|
|
1672
|
+
const restored = stacks.map(async ({ baseUrl, credential, retained, projects }) => {
|
|
1673
|
+
state.stacks.ensure(baseUrl);
|
|
1674
|
+
if (!credential && !retained) return "unreachable";
|
|
1675
|
+
if (Result.unwrapOr(state.auth.getEpoch(baseUrl), 0) > 0) return "skipped";
|
|
1676
|
+
if (retained) state.auth.retain(baseUrl, retained);
|
|
1677
|
+
if (!credential) return "unreachable";
|
|
1678
|
+
const outcome = await restoreStack(baseUrl, credential);
|
|
1679
|
+
if (outcome === "restored") restoreProjects(baseUrl, projects);
|
|
1680
|
+
return outcome;
|
|
1681
|
+
});
|
|
1682
|
+
const results = await Promise.all(restored);
|
|
1683
|
+
const scopedOutcome = scoped?.credential ? results[stacks.indexOf(scoped)] : void 0;
|
|
1684
|
+
return {
|
|
1685
|
+
lastActive: current,
|
|
1686
|
+
status: toRestoreStatus(scopedOutcome)
|
|
1687
|
+
};
|
|
1688
|
+
};
|
|
1689
|
+
/**
|
|
1690
|
+
* Signs a retained stack back in from the grant it kept.
|
|
1691
|
+
*
|
|
1692
|
+
* - `restored` and `refused` empty the slot; `unreachable` keeps it for another try.
|
|
1693
|
+
* - Throws when the stack retains nothing.
|
|
1694
|
+
*/
|
|
1695
|
+
const restoreRetained = async (baseUrl) => {
|
|
1696
|
+
const { grant } = Result.unwrap(state.auth.requireRetained(baseUrl));
|
|
1697
|
+
return restoreStack(baseUrl, grant, true);
|
|
1698
|
+
};
|
|
1699
|
+
const isStale = (baseUrl) => {
|
|
1700
|
+
const ageing = Result.map(state.auth.requireCredential(baseUrl), ({ issuedAt, expiresIn }) => Date.now() >= issuedAt + expiresIn * 1e3 * refreshThreshold);
|
|
1701
|
+
return Result.unwrapOr(ageing, false);
|
|
1702
|
+
};
|
|
1703
|
+
/**
|
|
1704
|
+
* Drops the slot so the next sign-in's requests don't join the dying rotation.
|
|
1705
|
+
*
|
|
1706
|
+
* - Writes nothing: the caller persists the stack, under the lock it holds or takes.
|
|
1707
|
+
*/
|
|
1708
|
+
const signOut = (baseUrl, options) => {
|
|
1709
|
+
rotationMap.delete(baseUrl);
|
|
1710
|
+
const signedOut = state.auth.signOut(baseUrl, options);
|
|
1711
|
+
onSignedOut?.(baseUrl);
|
|
1712
|
+
return signedOut;
|
|
1713
|
+
};
|
|
1714
|
+
const expire = async (baseUrl, store) => {
|
|
1715
|
+
if (!state.auth.notifyExpired(baseUrl)) return;
|
|
1716
|
+
signOut(baseUrl);
|
|
1717
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1718
|
+
onExpired?.(baseUrl);
|
|
1719
|
+
};
|
|
1720
|
+
const renewIfStale = async (baseUrl) => {
|
|
1721
|
+
if (isStale(baseUrl)) await rotate(baseUrl);
|
|
1722
|
+
};
|
|
1723
|
+
const middleware = (baseUrl) => createBearerAuthMiddleware({ getAccessToken: async ({ forceRefresh = false } = {}) => {
|
|
1724
|
+
if (forceRefresh) {
|
|
1725
|
+
if (!state.auth.requireCredential(baseUrl).success) return null;
|
|
1726
|
+
return Result.unwrap(await rotate(baseUrl));
|
|
1727
|
+
}
|
|
1728
|
+
await renewIfStale(baseUrl);
|
|
1729
|
+
return state.auth.getAccessToken(baseUrl);
|
|
1730
|
+
} });
|
|
1731
|
+
return {
|
|
1732
|
+
middleware,
|
|
1733
|
+
rotate,
|
|
1734
|
+
renewIfStale,
|
|
1735
|
+
restore,
|
|
1736
|
+
restoreRetained,
|
|
1737
|
+
signOut,
|
|
1738
|
+
forget
|
|
1739
|
+
};
|
|
1740
|
+
};
|
|
1741
|
+
//#endregion
|
|
1633
1742
|
//#region src/keboola/bearer/context/resource.ts
|
|
1634
1743
|
/**
|
|
1635
1744
|
* Owns fetching one async value per key — a caller names what it needs and never orchestrates the
|
|
@@ -1758,6 +1867,7 @@ const createProjectContext = ({ state, credentials, stackContext }) => {
|
|
|
1758
1867
|
};
|
|
1759
1868
|
//#endregion
|
|
1760
1869
|
//#region src/keboola/bearer/context/stack.ts
|
|
1870
|
+
const STACK_INDEX_TIMEOUT_MS = 3e4;
|
|
1761
1871
|
const createStackContext = (state) => {
|
|
1762
1872
|
const resource = createResource({
|
|
1763
1873
|
key: (baseUrl) => baseUrl,
|
|
@@ -1767,7 +1877,7 @@ const createStackContext = (state) => {
|
|
|
1767
1877
|
type: "sapi-token",
|
|
1768
1878
|
token: ""
|
|
1769
1879
|
}
|
|
1770
|
-
}).getStackInfo({ exclude: "componentDetails" })
|
|
1880
|
+
}).getStackInfo({ exclude: "componentDetails" }, AbortSignal.timeout(STACK_INDEX_TIMEOUT_MS))
|
|
1771
1881
|
});
|
|
1772
1882
|
resource.subscribe(({ key, status }) => {
|
|
1773
1883
|
state.stacks.updateContext(key, status);
|
|
@@ -1946,14 +2056,16 @@ const createPerProject = ({ state, credentials, middlewareFor, stack, clientServ
|
|
|
1946
2056
|
*/
|
|
1947
2057
|
const SESSION_STORAGE_KEY = "keboola:session";
|
|
1948
2058
|
/**
|
|
1949
|
-
* What survives a reload, per
|
|
2059
|
+
* What survives a reload, per grant type.
|
|
2060
|
+
*
|
|
2061
|
+
* - Written under `credential`: the key every blob already stored carries.
|
|
1950
2062
|
*
|
|
1951
2063
|
* - `token`: the refresh token. It rotates, is single-use and is server-revocable, so a leaked
|
|
1952
2064
|
* snapshot has limited and revocable value. The access token is never written.
|
|
1953
2065
|
* - `cookie`: the session id. The session cookie is the durable half and the browser keeps it;
|
|
1954
2066
|
* the id alone renews nothing.
|
|
1955
2067
|
*/
|
|
1956
|
-
const
|
|
2068
|
+
const persistedGrantSchema = z$1.discriminatedUnion("type", [z$1.object({
|
|
1957
2069
|
type: z$1.literal("token"),
|
|
1958
2070
|
refreshToken: z$1.string()
|
|
1959
2071
|
}), z$1.object({
|
|
@@ -1962,32 +2074,68 @@ const persistedCredentialSchema = z$1.discriminatedUnion("type", [z$1.object({
|
|
|
1962
2074
|
})]);
|
|
1963
2075
|
/** A record per project rather than a bare id, so a project can grow a field without a migration. */
|
|
1964
2076
|
const persistedProjectSchema = z$1.object({ projectId: z$1.number() });
|
|
2077
|
+
const persistedStackSchema = z$1.object({
|
|
2078
|
+
baseUrl: z$1.string(),
|
|
2079
|
+
credential: persistedGrantSchema.nullable().catch(null),
|
|
2080
|
+
retained: z$1.object({ grant: persistedGrantSchema }).nullable().default(null).catch(null),
|
|
2081
|
+
projects: z$1.array(persistedProjectSchema)
|
|
2082
|
+
});
|
|
1965
2083
|
const persistedSessionSchema = z$1.object({
|
|
1966
2084
|
current: z$1.object({
|
|
1967
2085
|
baseUrl: z$1.string(),
|
|
1968
2086
|
projectId: z$1.number().nullable()
|
|
1969
2087
|
}).nullable(),
|
|
1970
|
-
stacks: z$1.array(
|
|
1971
|
-
baseUrl: z$1.string(),
|
|
1972
|
-
credential: persistedCredentialSchema.nullable().catch(null),
|
|
1973
|
-
projects: z$1.array(persistedProjectSchema)
|
|
1974
|
-
}))
|
|
2088
|
+
stacks: z$1.array(persistedStackSchema)
|
|
1975
2089
|
});
|
|
1976
2090
|
const EMPTY_PERSISTED_SESSION = {
|
|
1977
2091
|
current: null,
|
|
1978
2092
|
stacks: []
|
|
1979
2093
|
};
|
|
1980
|
-
const
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2094
|
+
const projectsOf = (projects, baseUrl) => Object.values(projects).filter((project) => project.baseUrl === baseUrl).map(({ projectId }) => ({ projectId }));
|
|
2095
|
+
const grantsOf = (stack) => ({
|
|
2096
|
+
credential: stack.auth.status === "authenticated" ? Entry.grant(stack.auth.credential) : null,
|
|
2097
|
+
retained: stack.retained
|
|
2098
|
+
});
|
|
2099
|
+
/**
|
|
2100
|
+
* The stored session, rewritten from the table except for the grants.
|
|
2101
|
+
*
|
|
2102
|
+
* - Scope, stack list and open projects come from memory.
|
|
2103
|
+
* - `credential` and `retained` stay as stored: a grant another document rotated must not be put
|
|
2104
|
+
* back by a snapshot of this one's older table.
|
|
2105
|
+
*/
|
|
2106
|
+
const mergeSnapshot = (stored, { active, stacks, projects }) => ({
|
|
2107
|
+
current: {
|
|
2108
|
+
baseUrl: active.baseUrl,
|
|
2109
|
+
projectId: active.projectId
|
|
2110
|
+
},
|
|
2111
|
+
stacks: Object.values(stacks).map(({ baseUrl }) => {
|
|
2112
|
+
const kept = stored.stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
2113
|
+
return {
|
|
2114
|
+
baseUrl,
|
|
2115
|
+
credential: kept?.credential ?? null,
|
|
2116
|
+
retained: kept?.retained ?? null,
|
|
2117
|
+
projects: projectsOf(projects, baseUrl)
|
|
2118
|
+
};
|
|
2119
|
+
})
|
|
2120
|
+
});
|
|
2121
|
+
const upsertStack = (stored, baseUrl, update) => {
|
|
2122
|
+
const index = stored.stacks.findIndex((stack) => stack.baseUrl === baseUrl);
|
|
2123
|
+
const stacks = [...stored.stacks];
|
|
2124
|
+
if (index < 0) stacks.push(update(void 0));
|
|
2125
|
+
else stacks[index] = update(stacks[index]);
|
|
2126
|
+
return {
|
|
2127
|
+
...stored,
|
|
2128
|
+
stacks
|
|
1989
2129
|
};
|
|
1990
2130
|
};
|
|
2131
|
+
/**
|
|
2132
|
+
* The stored session, reached in two ways.
|
|
2133
|
+
*
|
|
2134
|
+
* - `locked`: the only way to read, and the only way to a grant write. Rotation and restore hold
|
|
2135
|
+
* it across the refresh; sign-in, sign-out and the boot restore open it for one step.
|
|
2136
|
+
* - `snapshot`: the table minus its grants, under the lock, coalesced; what the store subscription
|
|
2137
|
+
* feeds, and what a scope change awaits before the document leaves.
|
|
2138
|
+
*/
|
|
1991
2139
|
const createSessionPersistor = (storage) => {
|
|
1992
2140
|
const persistor = createPersistor({
|
|
1993
2141
|
storage,
|
|
@@ -1995,20 +2143,35 @@ const createSessionPersistor = (storage) => {
|
|
|
1995
2143
|
schema: persistedSessionSchema,
|
|
1996
2144
|
defaultValue: EMPTY_PERSISTED_SESSION
|
|
1997
2145
|
});
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2146
|
+
const persistStack = (cell, baseUrl, { stacks, projects }) => {
|
|
2147
|
+
const stack = stacks[baseUrl];
|
|
2148
|
+
if (stack === void 0) return Promise.resolve();
|
|
2149
|
+
return cell.modify((stored) => upsertStack(stored, baseUrl, (existing) => ({
|
|
2150
|
+
baseUrl,
|
|
2151
|
+
...grantsOf(stack),
|
|
2152
|
+
projects: existing?.projects ?? projectsOf(projects, baseUrl)
|
|
2153
|
+
})));
|
|
2154
|
+
};
|
|
2155
|
+
const locked = (task) => persistor.locked((cell) => task({
|
|
2156
|
+
read: cell.read,
|
|
2157
|
+
persistStack: (baseUrl, state) => persistStack(cell, baseUrl, state)
|
|
2158
|
+
}));
|
|
2159
|
+
let latest = null;
|
|
2160
|
+
let pending = null;
|
|
2161
|
+
const snapshot = (state) => {
|
|
2162
|
+
latest = state;
|
|
2163
|
+
if (pending) return pending;
|
|
2164
|
+
const write = persistor.locked((cell) => {
|
|
2165
|
+
pending = null;
|
|
2166
|
+
const table = latest ?? state;
|
|
2167
|
+
return cell.modify((stored) => mergeSnapshot(stored, table));
|
|
2168
|
+
});
|
|
2169
|
+
pending = write;
|
|
2170
|
+
return write;
|
|
2171
|
+
};
|
|
2009
2172
|
return {
|
|
2010
|
-
|
|
2011
|
-
|
|
2173
|
+
locked,
|
|
2174
|
+
snapshot
|
|
2012
2175
|
};
|
|
2013
2176
|
};
|
|
2014
2177
|
//#endregion
|
|
@@ -2126,15 +2289,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2126
2289
|
await credentials.renewIfStale(project.baseUrl);
|
|
2127
2290
|
return headersFor(Result.unwrap(state.projects.get(project.id)));
|
|
2128
2291
|
};
|
|
2129
|
-
const
|
|
2130
|
-
|
|
2131
|
-
if (input.type !== "token") return Result.unwrap(state.auth.authenticate(stack.baseUrl, input));
|
|
2292
|
+
const toCredential = (input) => {
|
|
2293
|
+
if (input.type !== "token") return input;
|
|
2132
2294
|
const { refreshToken } = input;
|
|
2133
2295
|
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
2134
|
-
return
|
|
2296
|
+
return {
|
|
2135
2297
|
...input,
|
|
2136
2298
|
refreshToken
|
|
2137
|
-
}
|
|
2299
|
+
};
|
|
2300
|
+
};
|
|
2301
|
+
const authenticate = (input) => {
|
|
2302
|
+
const { baseUrl } = state.scope.getActiveStack();
|
|
2303
|
+
const signedIn = Result.unwrap(state.auth.authenticate(baseUrl, toCredential(input)));
|
|
2304
|
+
persistor.locked((store) => store.persistStack(baseUrl, state.store.get())).catch((error) => {
|
|
2305
|
+
console.warn("createKeboola: the sign-in could not be stored", error);
|
|
2306
|
+
});
|
|
2307
|
+
return signedIn;
|
|
2138
2308
|
};
|
|
2139
2309
|
/**
|
|
2140
2310
|
* The flat product surface: `auth` and `management` per stack, the rest per project.
|
|
@@ -2174,11 +2344,21 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2174
2344
|
Result.unwrapOr(state.projects.open(baseUrl, projectId), null);
|
|
2175
2345
|
return perProject.get(project).api;
|
|
2176
2346
|
};
|
|
2177
|
-
/**
|
|
2178
|
-
|
|
2347
|
+
/**
|
|
2348
|
+
* The scope's sign-in, or a named stack's — and everything that sign-in derived.
|
|
2349
|
+
*
|
|
2350
|
+
* - `retain` keeps the grant on the stack, persisted beside the sign-in it ended, for
|
|
2351
|
+
* `restoreRetained`; the next sign-in on the stack replaces it.
|
|
2352
|
+
* - The table is signed out on return; the promise resolves once that is stored, so a caller
|
|
2353
|
+
* leaving the document waits for it.
|
|
2354
|
+
*/
|
|
2355
|
+
const signOut = ({ baseUrl, ...options } = {}) => {
|
|
2179
2356
|
const target = requireStackUrl(baseUrl);
|
|
2180
|
-
|
|
2357
|
+
const signedOut = Result.unwrap(credentials.signOut(target, options));
|
|
2358
|
+
return persistor.locked((store) => store.persistStack(target, state.store.get())).then(() => signedOut);
|
|
2181
2359
|
};
|
|
2360
|
+
/** Signs a stack back in from what a retained sign-out kept; `unreachable` leaves it to retry. */
|
|
2361
|
+
const restoreRetained = (baseUrl) => credentials.restoreRetained(normalizeBaseUrl(baseUrl));
|
|
2182
2362
|
/**
|
|
2183
2363
|
* `input` replaces the active stack's sign-in, whatever it holds.
|
|
2184
2364
|
*
|
|
@@ -2215,16 +2395,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2215
2395
|
/**
|
|
2216
2396
|
* Persistence starts only once the restore has settled.
|
|
2217
2397
|
*
|
|
2218
|
-
* - Mid-hydration an unexchanged stack is `anonymous`;
|
|
2398
|
+
* - Mid-hydration an unexchanged stack is `anonymous`; the persistor would erase the
|
|
2219
2399
|
* refresh token the exchange is about to spend.
|
|
2220
2400
|
* - Writes the settled table once: the subscription fires only on the next change.
|
|
2221
2401
|
*/
|
|
2222
2402
|
const enablePersistence = () => {
|
|
2223
2403
|
if (persisting) return;
|
|
2224
2404
|
persisting = true;
|
|
2225
|
-
|
|
2226
|
-
state.store.subscribe(
|
|
2405
|
+
snapshot(state.store.get());
|
|
2406
|
+
state.store.subscribe(snapshot);
|
|
2407
|
+
};
|
|
2408
|
+
const snapshot = (table) => {
|
|
2409
|
+
persistor.snapshot(table).catch((error) => {
|
|
2410
|
+
console.warn("createKeboola: the session could not be stored", error);
|
|
2411
|
+
});
|
|
2227
2412
|
};
|
|
2413
|
+
const persistScope = () => persisting ? persistor.snapshot(state.store.get()) : Promise.resolve();
|
|
2228
2414
|
/**
|
|
2229
2415
|
* The same, deferred until a sign-in.
|
|
2230
2416
|
*
|
|
@@ -2278,14 +2464,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2278
2464
|
resume,
|
|
2279
2465
|
stack: {
|
|
2280
2466
|
getActive: getActiveStack,
|
|
2281
|
-
|
|
2467
|
+
/** Scoped on return; resolves once that is stored, for a caller leaving the document. */
|
|
2468
|
+
select: byCaller((baseUrl) => {
|
|
2469
|
+
const stack = selectStack(baseUrl);
|
|
2470
|
+
return persistScope().then(() => stack);
|
|
2471
|
+
}),
|
|
2282
2472
|
close: closeStack,
|
|
2283
2473
|
retryContext: perStack.context.retry,
|
|
2284
2474
|
getContext: (baseUrl) => perStack.context.get(requireStackUrl(baseUrl)),
|
|
2285
2475
|
getContextAsync: (baseUrl) => perStack.context.getAsync(requireStackUrl(baseUrl))
|
|
2286
2476
|
},
|
|
2287
2477
|
project: {
|
|
2288
|
-
|
|
2478
|
+
/** Scoped on return; resolves once that is stored, for a caller leaving the document. */
|
|
2479
|
+
select: byCaller((projectId) => {
|
|
2480
|
+
const project = selectProject(projectId);
|
|
2481
|
+
return persistScope().then(() => project);
|
|
2482
|
+
}),
|
|
2289
2483
|
close: closeProject,
|
|
2290
2484
|
deactivate: state.scope.deactivate,
|
|
2291
2485
|
retryContext: perProject.context.retry,
|
|
@@ -2296,6 +2490,7 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2296
2490
|
authenticate: byCaller(authenticate),
|
|
2297
2491
|
replace: byCaller(replace),
|
|
2298
2492
|
signOut: byCaller(signOut),
|
|
2493
|
+
restoreRetained: byCaller(restoreRetained),
|
|
2299
2494
|
/** Whether the active stack holds a credential — `restoring` is not one yet. */
|
|
2300
2495
|
isAuthenticated,
|
|
2301
2496
|
isAuthenticatedAsync: () => resume().then(isAuthenticated),
|
|
@@ -2489,6 +2684,6 @@ const createAdminAccount = ({ managementToken }) => {
|
|
|
2489
2684
|
};
|
|
2490
2685
|
};
|
|
2491
2686
|
//#endregion
|
|
2492
|
-
export { ApiError, HtmlResponseError, HttpContentType, HttpHeader, KeboolaError, KeboolaErrorType, KeboolaHttpHeader, ManagementClientAuthError, ManagementSessionMintError, QueryJobError, QueueJobError, Result, SESSION_STORAGE_KEY, ServiceUnavailableError, StorageJobError, SyncActionError, UserError, ValidationError, asError, assert, coalesce, collectByCursor, collectByOffset, concurrent, createAdminAccount, createDerivedAsyncStore, createDerivedStore, createEmitter, createGenericFetchClient, createKeboola, createLegacyKeboola, createLocalStorage, createLoggingMiddleware, createMemoryStorage, createNullStorage, createPersistor, createPollRegistry, createQueryServiceSdk, createRetryMiddleware, createSessionStorage, createStore, createUiVersionMiddleware, dedupe, deepMerge, delay, emitter, ensure, failureOf, formatValidationIssues, generateUUID, isAbortError, isApiError, isEmptyDeep, isFetchClientError, isHtmlResponseError, isKeboolaError, isManagementClientAuthError, isManagementSessionMintError, isPlainObject, isQueryJobError, isQueueJobError, isStorageJobError, isStorageTokenMutatingRequest, isSyncActionError, isTimeoutError, isValidationError, jobStatus, keboolaUID, lazy, nextCursorOf, parseLogLines, parseOrThrow, poller, readableReason, schemaGuidedMerge, series, shallowEqual };
|
|
2687
|
+
export { ApiError, HtmlResponseError, HttpContentType, HttpHeader, KeboolaError, KeboolaErrorType, KeboolaHttpHeader, ManagementClientAuthError, ManagementSessionMintError, QueryJobError, QueueJobError, Result, SESSION_STORAGE_KEY, ServiceUnavailableError, StorageJobError, SyncActionError, UserError, ValidationError, asError, assert, coalesce, collectByCursor, collectByOffset, concurrent, createAdminAccount, createDerivedAsyncStore, createDerivedStore, createEmitter, createGenericFetchClient, createKeboola, createLegacyKeboola, createLocalStorage, createLoggingMiddleware, createMemoryStorage, createNullStorage, createPersistor, createPollRegistry, 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, isStorageJobError, isStorageTokenMutatingRequest, isSyncActionError, isTimeoutError, isValidationError, jobStatus, keboolaUID, lazy, manageErrorCode, nextCursorOf, parseLogLines, parseOrThrow, poller, queueSeries, readableReason, retryAfterSeconds, schemaGuidedMerge, series, shallowEqual };
|
|
2493
2688
|
|
|
2494
2689
|
//# sourceMappingURL=index.js.map
|