@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.cjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
3
|
-
const require_project = require("./project-
|
|
3
|
+
const require_project = require("./project-Rh4nXiWh.cjs");
|
|
4
4
|
const require_collectByOffset = require("./collectByOffset-DQsqtmJg.cjs");
|
|
5
5
|
const require_authClient = require("./authClient-DfkKlc-2.cjs");
|
|
6
6
|
const require_concurrent = require("./concurrent-CdVfR1N5.cjs");
|
|
7
7
|
const require_dedupe = require("./dedupe-OSnnst2u.cjs");
|
|
8
8
|
const require_transientRetries = require("./transientRetries-DdJfH9QK.cjs");
|
|
9
9
|
const require_store = require("./store-xS-Cu_VS.cjs");
|
|
10
|
-
const require_storage = require("./storage-
|
|
10
|
+
const require_storage = require("./storage-Ci9gXgcw.cjs");
|
|
11
11
|
const require_tag = require("./tag-DHS_soa7.cjs");
|
|
12
12
|
const require_generateUUID = require("./generateUUID-C6qKBPIv.cjs");
|
|
13
13
|
const require_isPlainObject = require("./isPlainObject-BB3iy87C.cjs");
|
|
14
|
-
const require_configurations = require("./configurations-
|
|
14
|
+
const require_configurations = require("./configurations-Dkxsa3Uf.cjs");
|
|
15
15
|
const require_UserError = require("./UserError-CSGO1qII.cjs");
|
|
16
16
|
const require_createFetchClient = require("./createFetchClient-lZ_93Yrb.cjs");
|
|
17
17
|
const require_validateConnectionStatus = require("./validateConnectionStatus-BalWEyRk.cjs");
|
|
@@ -22,8 +22,8 @@ const require_SyncActionError = require("./SyncActionError-BG0zwchi.cjs");
|
|
|
22
22
|
const require_ValidationError = require("./ValidationError-D65QU0uq.cjs");
|
|
23
23
|
const require_createGenericFetchClient = require("./createGenericFetchClient-MOx97wi-.cjs");
|
|
24
24
|
const require_import = require("./import-BahNYv91.cjs");
|
|
25
|
-
const require_management = require("./management-
|
|
26
|
-
const require_constants = require("./constants-
|
|
25
|
+
const require_management = require("./management-B1o6RpKF.cjs");
|
|
26
|
+
const require_constants = require("./constants-DErcRkWl.cjs");
|
|
27
27
|
const require_storageTable = require("./storageTable-BNOR2FCh.cjs");
|
|
28
28
|
const require_kaiMemory = require("./kaiMemory-Qch09f-m.cjs");
|
|
29
29
|
const require_semanticLayer = require("./semanticLayer-7BejcMj_.cjs");
|
|
@@ -37,7 +37,7 @@ const require_componentsMcp = require("./componentsMcp-pG-PcQrg.cjs");
|
|
|
37
37
|
const require_dataScience = require("./dataScience-BjS1p8WO.cjs");
|
|
38
38
|
const require_editor_index = require("./editor/index.cjs");
|
|
39
39
|
const require_encryption_index = require("./encryption/index.cjs");
|
|
40
|
-
const require_kaiAgent = require("./kaiAgent-
|
|
40
|
+
const require_kaiAgent = require("./kaiAgent-N2qbUFZm.cjs");
|
|
41
41
|
const require_metastore = require("./metastore-BXHg33ku.cjs");
|
|
42
42
|
const require_notifications_index = require("./notifications/index.cjs");
|
|
43
43
|
const require_oauth = require("./oauth-DKZPuUlt.cjs");
|
|
@@ -49,7 +49,7 @@ const require_stream_index = require("./stream/index.cjs");
|
|
|
49
49
|
const require_syncActions = require("./syncActions-C1rE4R3f.cjs");
|
|
50
50
|
const require_telemetry_index = require("./telemetry/index.cjs");
|
|
51
51
|
const require_vault_index = require("./vault/index.cjs");
|
|
52
|
-
const require_middleware = require("./middleware-
|
|
52
|
+
const require_middleware = require("./middleware-CEP6uu_D.cjs");
|
|
53
53
|
const require_sdk_queryService_index = require("./sdk/queryService/index.cjs");
|
|
54
54
|
let zod = require("zod");
|
|
55
55
|
zod = require_rolldown_runtime.__toESM(zod, 1);
|
|
@@ -263,6 +263,47 @@ const createPollRegistry = ({ limit = DEFAULT_LIMIT } = {}) => {
|
|
|
263
263
|
};
|
|
264
264
|
};
|
|
265
265
|
//#endregion
|
|
266
|
+
//#region src/utils/async/queueSeries.ts
|
|
267
|
+
const isPromiseLike = (value) => (typeof value === "object" && value !== null || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
268
|
+
/**
|
|
269
|
+
* Queues tasks added over time so a slower earlier task cannot finish after and overwrite a later one.
|
|
270
|
+
* Each `add` returns its task's result; a rejection does not stop the remaining queue.
|
|
271
|
+
*/
|
|
272
|
+
const queueSeries = () => {
|
|
273
|
+
let tail = null;
|
|
274
|
+
const add = (task) => {
|
|
275
|
+
if (tail !== null) {
|
|
276
|
+
const result = tail.then(task);
|
|
277
|
+
tail = result.then(() => void 0, () => void 0);
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
let value;
|
|
281
|
+
try {
|
|
282
|
+
value = task();
|
|
283
|
+
} catch (error) {
|
|
284
|
+
return Promise.reject(error);
|
|
285
|
+
}
|
|
286
|
+
if (!isPromiseLike(value)) return Promise.resolve(value);
|
|
287
|
+
const result = Promise.resolve(value);
|
|
288
|
+
tail = result.then(() => void 0, () => void 0);
|
|
289
|
+
return result;
|
|
290
|
+
};
|
|
291
|
+
const onIdle = async () => {
|
|
292
|
+
while (tail !== null) {
|
|
293
|
+
const current = tail;
|
|
294
|
+
await current;
|
|
295
|
+
if (tail === current) {
|
|
296
|
+
tail = null;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
return {
|
|
302
|
+
add,
|
|
303
|
+
onIdle
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
//#endregion
|
|
266
307
|
//#region src/utils/deepMerge.ts
|
|
267
308
|
/**
|
|
268
309
|
* Recursively merge `patch` into `base`. Plain-object values are merged key-by-key; every
|
|
@@ -320,6 +361,10 @@ const createWebStorage = (pick) => {
|
|
|
320
361
|
},
|
|
321
362
|
removeItem: (key) => {
|
|
322
363
|
storage.removeItem(key);
|
|
364
|
+
},
|
|
365
|
+
withLock: async (name, task) => {
|
|
366
|
+
if (typeof navigator === "undefined" || !("locks" in navigator)) return task();
|
|
367
|
+
return navigator.locks.request(`keboola:${name}`, { mode: "exclusive" }, task);
|
|
323
368
|
}
|
|
324
369
|
};
|
|
325
370
|
};
|
|
@@ -328,62 +373,56 @@ const createSessionStorage = () => createWebStorage(() => "sessionStorage" in gl
|
|
|
328
373
|
//#endregion
|
|
329
374
|
//#region src/utils/persistor/persistor.ts
|
|
330
375
|
const createPersistor = ({ storage = createNullStorage(), key, schema, defaultValue, encode = JSON.stringify, decode = JSON.parse }) => {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const hasPersistedValue = () => {
|
|
339
|
-
try {
|
|
340
|
-
return !!storage.getItem(key);
|
|
341
|
-
} catch (err) {
|
|
342
|
-
console.warn(`createPersistor: failed to read "${key}", assuming empty`, err);
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
const hydrate = () => {
|
|
347
|
-
let raw;
|
|
348
|
-
try {
|
|
349
|
-
raw = storage.getItem(key);
|
|
350
|
-
} catch (err) {
|
|
351
|
-
console.warn(`createPersistor: failed to read "${key}", using default`, err);
|
|
352
|
-
return defaultValue;
|
|
353
|
-
}
|
|
354
|
-
if (raw === null) return defaultValue;
|
|
376
|
+
const writes = queueSeries();
|
|
377
|
+
const _load = async () => {
|
|
378
|
+
const raw = await storage.getItem(key);
|
|
379
|
+
if (raw === null) return {
|
|
380
|
+
value: defaultValue,
|
|
381
|
+
corrupt: false
|
|
382
|
+
};
|
|
355
383
|
let decoded;
|
|
356
384
|
try {
|
|
357
385
|
decoded = decode(raw);
|
|
358
386
|
} catch (err) {
|
|
359
|
-
console.warn(`createPersistor: failed to decode "${key}"
|
|
360
|
-
|
|
361
|
-
|
|
387
|
+
console.warn(`createPersistor: failed to decode "${key}"`, err);
|
|
388
|
+
return {
|
|
389
|
+
value: defaultValue,
|
|
390
|
+
corrupt: true
|
|
391
|
+
};
|
|
362
392
|
}
|
|
363
393
|
const parsed = schema.safeParse(decoded);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
394
|
+
return parsed.success ? {
|
|
395
|
+
value: parsed.data,
|
|
396
|
+
corrupt: false
|
|
397
|
+
} : {
|
|
398
|
+
value: defaultValue,
|
|
399
|
+
corrupt: true
|
|
400
|
+
};
|
|
367
401
|
};
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
storage.setItem(key, raw);
|
|
378
|
-
} catch (err) {
|
|
379
|
-
console.warn(`createPersistor: failed to write "${key}"`, err);
|
|
380
|
-
}
|
|
402
|
+
const remove = () => writes.add(() => storage.removeItem(key));
|
|
403
|
+
const write = (value) => writes.add(() => storage.setItem(key, encode(value)));
|
|
404
|
+
const read = async () => {
|
|
405
|
+
await writes.onIdle();
|
|
406
|
+
const parsed = await _load();
|
|
407
|
+
if (parsed.corrupt) remove().catch((err) => {
|
|
408
|
+
console.warn(`createPersistor: failed to drop the corrupt "${key}"`, err);
|
|
409
|
+
});
|
|
410
|
+
return parsed.value;
|
|
381
411
|
};
|
|
412
|
+
const modify = (change) => writes.add(async () => {
|
|
413
|
+
const next = change((await _load()).value);
|
|
414
|
+
await storage.setItem(key, encode(next));
|
|
415
|
+
});
|
|
416
|
+
const cell = {
|
|
417
|
+
read,
|
|
418
|
+
write,
|
|
419
|
+
modify,
|
|
420
|
+
remove
|
|
421
|
+
};
|
|
422
|
+
const locked = (task) => storage.withLock ? storage.withLock(key, () => task(cell)) : task(cell);
|
|
382
423
|
return {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
clear,
|
|
386
|
-
hasPersistedValue
|
|
424
|
+
...cell,
|
|
425
|
+
locked
|
|
387
426
|
};
|
|
388
427
|
};
|
|
389
428
|
//#endregion
|
|
@@ -1075,159 +1114,6 @@ const createLegacyKeboola = (options = {}) => {
|
|
|
1075
1114
|
};
|
|
1076
1115
|
};
|
|
1077
1116
|
//#endregion
|
|
1078
|
-
//#region src/keboola/bearer/credentials/renewal.ts
|
|
1079
|
-
const renewalGrant = (credential) => credential.type === "token" ? {
|
|
1080
|
-
type: "token",
|
|
1081
|
-
refreshToken: credential.refreshToken
|
|
1082
|
-
} : {
|
|
1083
|
-
type: "cookie",
|
|
1084
|
-
sessionId: credential.sessionId
|
|
1085
|
-
};
|
|
1086
|
-
const renew = async (client, grant) => {
|
|
1087
|
-
if (grant.type === "cookie") {
|
|
1088
|
-
const { accessToken, expiresIn, sessionId } = await client.token.refreshWithSession({ sessionId: grant.sessionId });
|
|
1089
|
-
return {
|
|
1090
|
-
type: "cookie",
|
|
1091
|
-
accessToken,
|
|
1092
|
-
expiresIn,
|
|
1093
|
-
sessionId
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
const { accessToken, expiresIn, refreshToken } = await client.token.refreshWithToken({ refreshToken: grant.refreshToken });
|
|
1097
|
-
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
1098
|
-
return {
|
|
1099
|
-
type: "token",
|
|
1100
|
-
accessToken,
|
|
1101
|
-
expiresIn,
|
|
1102
|
-
refreshToken
|
|
1103
|
-
};
|
|
1104
|
-
};
|
|
1105
|
-
//#endregion
|
|
1106
|
-
//#region src/keboola/bearer/credentials/credentials.ts
|
|
1107
|
-
const DEFAULT_REFRESH_THRESHOLD = .9;
|
|
1108
|
-
const signInEnded = () => new KeboolaError(KeboolaErrorType.SignInEnded);
|
|
1109
|
-
const toRestoreStatus = (outcome) => {
|
|
1110
|
-
if (outcome === void 0 || outcome === "skipped") return "empty";
|
|
1111
|
-
if (outcome === "refused") return "expired";
|
|
1112
|
-
return outcome;
|
|
1113
|
-
};
|
|
1114
|
-
const createCredentials = ({ state, persistor, middlewares, refreshThreshold = DEFAULT_REFRESH_THRESHOLD, onSignedOut, onExpired }) => {
|
|
1115
|
-
const rotationMap = /* @__PURE__ */ new Map();
|
|
1116
|
-
const generations = /* @__PURE__ */ new Map();
|
|
1117
|
-
const generationOf = (baseUrl) => generations.get(baseUrl) ?? 0;
|
|
1118
|
-
const refresh = async (baseUrl, grant) => {
|
|
1119
|
-
const client = require_authClient.createAuthClient({
|
|
1120
|
-
baseUrl,
|
|
1121
|
-
middlewares
|
|
1122
|
-
});
|
|
1123
|
-
const epochBefore = require_transientRetries.Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1124
|
-
const generationBefore = generationOf(baseUrl);
|
|
1125
|
-
const refreshed = await require_transientRetries.Result.tryCatchAsync(() => renew(client, grant));
|
|
1126
|
-
return require_transientRetries.Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) === epochBefore && generationOf(baseUrl) === generationBefore ? refreshed : require_transientRetries.Result.failure(signInEnded());
|
|
1127
|
-
};
|
|
1128
|
-
/**
|
|
1129
|
-
* A stack's teardown, from the credential's side.
|
|
1130
|
-
*
|
|
1131
|
-
* - Bumps the generation, so an in-flight rotation can no longer write.
|
|
1132
|
-
* - Drops the deduped entry, so nothing joins that rotation.
|
|
1133
|
-
*/
|
|
1134
|
-
const forget = (baseUrl) => {
|
|
1135
|
-
generations.set(baseUrl, generationOf(baseUrl) + 1);
|
|
1136
|
-
rotationMap.delete(baseUrl);
|
|
1137
|
-
};
|
|
1138
|
-
/**
|
|
1139
|
-
* The rotation, and the one place a credential is declared dead.
|
|
1140
|
-
*
|
|
1141
|
-
* - Renews by the credential's own kind: the refresh token, or the session id with the cookie.
|
|
1142
|
-
* - A refused refresh token or session is unambiguous.
|
|
1143
|
-
* - The triggering 401 is not (an unreachable project answers the same), so never sign out on a replay.
|
|
1144
|
-
*/
|
|
1145
|
-
const rotateOnce = async (baseUrl) => {
|
|
1146
|
-
const credential = state.auth.requireCredential(baseUrl);
|
|
1147
|
-
if (!credential.success) return credential;
|
|
1148
|
-
const refreshed = await refresh(baseUrl, renewalGrant(credential.data));
|
|
1149
|
-
if (!refreshed.success) {
|
|
1150
|
-
if (require_middleware.isUnauthorized(refreshed.error)) expire(baseUrl);
|
|
1151
|
-
return refreshed;
|
|
1152
|
-
}
|
|
1153
|
-
return require_transientRetries.Result.map(state.auth.applyRefresh(baseUrl, refreshed.data), () => refreshed.data.accessToken);
|
|
1154
|
-
};
|
|
1155
|
-
const rotate = (baseUrl) => ensure(rotationMap, baseUrl, () => require_dedupe.dedupe(() => rotateOnce(baseUrl)))();
|
|
1156
|
-
const restoreStack = async (baseUrl, grant) => {
|
|
1157
|
-
if (!state.auth.startRestore(baseUrl).success) return "unreachable";
|
|
1158
|
-
const refreshed = await refresh(baseUrl, grant);
|
|
1159
|
-
if (!refreshed.success) {
|
|
1160
|
-
state.auth.cancelRestore(baseUrl);
|
|
1161
|
-
return require_middleware.isUnauthorized(refreshed.error) ? "refused" : "unreachable";
|
|
1162
|
-
}
|
|
1163
|
-
state.auth.authenticate(baseUrl, refreshed.data);
|
|
1164
|
-
return "restored";
|
|
1165
|
-
};
|
|
1166
|
-
const restoreProjects = (baseUrl, projects) => {
|
|
1167
|
-
for (const { projectId } of projects) state.projects.open(baseUrl, projectId);
|
|
1168
|
-
};
|
|
1169
|
-
/**
|
|
1170
|
-
* Every persisted stack back into the table, with whatever credential it can hand back.
|
|
1171
|
-
*
|
|
1172
|
-
* - Never writes the scope. `lastActive` is what was scoped when the session was stored, for the
|
|
1173
|
-
* caller to select.
|
|
1174
|
-
* - `status` reports what became of `lastActive`'s credential; the client reads it to decide
|
|
1175
|
-
* when persistence may start.
|
|
1176
|
-
*/
|
|
1177
|
-
const restore = async () => {
|
|
1178
|
-
const { stacks, current } = persistor.hydrate();
|
|
1179
|
-
const scoped = stacks.find(({ baseUrl }) => baseUrl === current?.baseUrl);
|
|
1180
|
-
const restored = stacks.map(async ({ baseUrl, credential, projects }) => {
|
|
1181
|
-
state.stacks.ensure(baseUrl);
|
|
1182
|
-
if (!credential) return "unreachable";
|
|
1183
|
-
if (require_transientRetries.Result.unwrapOr(state.auth.getEpoch(baseUrl), 0) > 0) return "skipped";
|
|
1184
|
-
const outcome = await restoreStack(baseUrl, credential);
|
|
1185
|
-
if (outcome === "restored") restoreProjects(baseUrl, projects);
|
|
1186
|
-
return outcome;
|
|
1187
|
-
});
|
|
1188
|
-
const results = await Promise.all(restored);
|
|
1189
|
-
const scopedOutcome = scoped?.credential ? results[stacks.indexOf(scoped)] : void 0;
|
|
1190
|
-
return {
|
|
1191
|
-
lastActive: current,
|
|
1192
|
-
status: toRestoreStatus(scopedOutcome)
|
|
1193
|
-
};
|
|
1194
|
-
};
|
|
1195
|
-
const isStale = (baseUrl) => {
|
|
1196
|
-
const ageing = require_transientRetries.Result.map(state.auth.requireCredential(baseUrl), ({ issuedAt, expiresIn }) => Date.now() >= issuedAt + expiresIn * 1e3 * refreshThreshold);
|
|
1197
|
-
return require_transientRetries.Result.unwrapOr(ageing, false);
|
|
1198
|
-
};
|
|
1199
|
-
const signOut = (baseUrl) => {
|
|
1200
|
-
rotationMap.delete(baseUrl);
|
|
1201
|
-
const signedOut = state.auth.signOut(baseUrl);
|
|
1202
|
-
onSignedOut?.(baseUrl);
|
|
1203
|
-
return signedOut;
|
|
1204
|
-
};
|
|
1205
|
-
const expire = (baseUrl) => {
|
|
1206
|
-
if (!state.auth.notifyExpired(baseUrl)) return;
|
|
1207
|
-
signOut(baseUrl);
|
|
1208
|
-
onExpired?.(baseUrl);
|
|
1209
|
-
};
|
|
1210
|
-
const renewIfStale = async (baseUrl) => {
|
|
1211
|
-
if (isStale(baseUrl)) await rotate(baseUrl);
|
|
1212
|
-
};
|
|
1213
|
-
const middleware = (baseUrl) => require_middleware.createBearerAuthMiddleware({ getAccessToken: async ({ forceRefresh = false } = {}) => {
|
|
1214
|
-
if (forceRefresh) {
|
|
1215
|
-
if (!state.auth.requireCredential(baseUrl).success) return null;
|
|
1216
|
-
return require_transientRetries.Result.unwrap(await rotate(baseUrl));
|
|
1217
|
-
}
|
|
1218
|
-
await renewIfStale(baseUrl);
|
|
1219
|
-
return state.auth.getAccessToken(baseUrl);
|
|
1220
|
-
} });
|
|
1221
|
-
return {
|
|
1222
|
-
middleware,
|
|
1223
|
-
rotate,
|
|
1224
|
-
renewIfStale,
|
|
1225
|
-
restore,
|
|
1226
|
-
signOut,
|
|
1227
|
-
forget
|
|
1228
|
-
};
|
|
1229
|
-
};
|
|
1230
|
-
//#endregion
|
|
1231
1117
|
//#region src/keboola/bearer/state/factories.ts
|
|
1232
1118
|
/**
|
|
1233
1119
|
* Everything the table constructs: the entries themselves, and the failures reading them produces.
|
|
@@ -1245,10 +1131,17 @@ const authenticatedAuth = (credential) => ({
|
|
|
1245
1131
|
status: "authenticated",
|
|
1246
1132
|
credential
|
|
1247
1133
|
});
|
|
1248
|
-
const
|
|
1134
|
+
const credential = (input) => ({
|
|
1249
1135
|
...input,
|
|
1250
1136
|
issuedAt: Date.now()
|
|
1251
1137
|
});
|
|
1138
|
+
const grant = (credential) => credential.type === "token" ? {
|
|
1139
|
+
type: "token",
|
|
1140
|
+
refreshToken: credential.refreshToken
|
|
1141
|
+
} : {
|
|
1142
|
+
type: "cookie",
|
|
1143
|
+
sessionId: credential.sessionId
|
|
1144
|
+
};
|
|
1252
1145
|
const expiredCredential = (credential) => ({
|
|
1253
1146
|
...credential,
|
|
1254
1147
|
issuedAt: Date.now() - credential.expiresIn * 1e3
|
|
@@ -1257,7 +1150,8 @@ const stack = (baseUrl) => ({
|
|
|
1257
1150
|
baseUrl,
|
|
1258
1151
|
context: "idle",
|
|
1259
1152
|
epoch: 0,
|
|
1260
|
-
auth: anonymousAuth()
|
|
1153
|
+
auth: anonymousAuth(),
|
|
1154
|
+
retained: null
|
|
1261
1155
|
});
|
|
1262
1156
|
const project = (baseUrl, projectId) => ({
|
|
1263
1157
|
id: projectEntryId(baseUrl, projectId),
|
|
@@ -1289,7 +1183,8 @@ const Entry = {
|
|
|
1289
1183
|
anonymousAuth,
|
|
1290
1184
|
restoringAuth,
|
|
1291
1185
|
authenticatedAuth,
|
|
1292
|
-
|
|
1186
|
+
credential,
|
|
1187
|
+
grant,
|
|
1293
1188
|
expiredCredential
|
|
1294
1189
|
};
|
|
1295
1190
|
/**
|
|
@@ -1307,7 +1202,8 @@ const Errors = {
|
|
|
1307
1202
|
notReady: () => new KeboolaError(KeboolaErrorType.NotReady),
|
|
1308
1203
|
alreadyRestoring: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" is already being restored`),
|
|
1309
1204
|
notRestoring: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" is not being restored`),
|
|
1310
|
-
|
|
1205
|
+
grantTypeChanged: (from, to) => /* @__PURE__ */ new Error(`A ${from} grant cannot become ${to}`),
|
|
1206
|
+
nothingRetained: (baseUrl) => /* @__PURE__ */ new Error(`Stack "${baseUrl}" retains no credential`),
|
|
1311
1207
|
missingProject: (id) => /* @__PURE__ */ new Error(`No project "${id}"`)
|
|
1312
1208
|
};
|
|
1313
1209
|
const authenticated = (auth) => auth.status === "authenticated" ? require_transientRetries.Result.success(auth.credential) : require_transientRetries.Result.failure(Errors.notAuthenticated());
|
|
@@ -1352,25 +1248,37 @@ const createAuth = ({ stacks, projects, expiry }) => {
|
|
|
1352
1248
|
return stacks.set({
|
|
1353
1249
|
...stack,
|
|
1354
1250
|
epoch: stack.epoch + 1,
|
|
1355
|
-
auth: Entry.authenticatedAuth(Entry.
|
|
1251
|
+
auth: Entry.authenticatedAuth(Entry.credential(input)),
|
|
1252
|
+
retained: null
|
|
1356
1253
|
});
|
|
1357
1254
|
});
|
|
1358
|
-
const applyRefresh = (baseUrl, input) => require_transientRetries.Result.andThen(stacks.requireCredential(baseUrl), (credential) => credential.type !== input.type ? require_transientRetries.Result.failure(Errors.
|
|
1255
|
+
const applyRefresh = (baseUrl, input) => require_transientRetries.Result.andThen(stacks.requireCredential(baseUrl), (credential) => credential.type !== input.type ? require_transientRetries.Result.failure(Errors.grantTypeChanged(credential.type, input.type)) : require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1359
1256
|
...stack,
|
|
1360
|
-
auth: Entry.authenticatedAuth(Entry.
|
|
1257
|
+
auth: Entry.authenticatedAuth(Entry.credential(input))
|
|
1361
1258
|
})));
|
|
1362
1259
|
const forceExpire = (baseUrl) => require_transientRetries.Result.andThen(stacks.requireCredential(baseUrl), (credential) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1363
1260
|
...stack,
|
|
1364
1261
|
auth: Entry.authenticatedAuth(Entry.expiredCredential(credential))
|
|
1365
1262
|
})));
|
|
1366
|
-
const signOut = (baseUrl) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => {
|
|
1263
|
+
const signOut = (baseUrl, { retain = false } = {}) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => {
|
|
1367
1264
|
projects.closeAll(baseUrl);
|
|
1265
|
+
const retained = retain ? require_transientRetries.Result.unwrapOr(require_transientRetries.Result.map(authenticated(stack.auth), (credential) => ({ grant: Entry.grant(credential) })), stack.retained) : null;
|
|
1368
1266
|
return stacks.set({
|
|
1369
1267
|
...stack,
|
|
1370
1268
|
epoch: stack.epoch + 1,
|
|
1371
|
-
auth: Entry.anonymousAuth()
|
|
1269
|
+
auth: Entry.anonymousAuth(),
|
|
1270
|
+
retained
|
|
1372
1271
|
});
|
|
1373
1272
|
});
|
|
1273
|
+
const retain = (baseUrl, retained) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1274
|
+
...stack,
|
|
1275
|
+
retained
|
|
1276
|
+
}));
|
|
1277
|
+
const dropRetained = (baseUrl) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => stacks.set({
|
|
1278
|
+
...stack,
|
|
1279
|
+
retained: null
|
|
1280
|
+
}));
|
|
1281
|
+
const requireRetained = (baseUrl) => require_transientRetries.Result.andThen(stacks.get(baseUrl), (stack) => stack.retained ? require_transientRetries.Result.success(stack.retained) : require_transientRetries.Result.failure(Errors.nothingRetained(baseUrl)));
|
|
1374
1282
|
const getEpoch = (baseUrl) => require_transientRetries.Result.map(stacks.get(baseUrl), (stack) => stack.epoch);
|
|
1375
1283
|
const getAccessToken = (baseUrl) => require_transientRetries.Result.unwrapOr(require_transientRetries.Result.map(stacks.requireCredential(baseUrl), ({ accessToken }) => accessToken), null);
|
|
1376
1284
|
return {
|
|
@@ -1380,6 +1288,9 @@ const createAuth = ({ stacks, projects, expiry }) => {
|
|
|
1380
1288
|
applyRefresh,
|
|
1381
1289
|
forceExpire,
|
|
1382
1290
|
signOut,
|
|
1291
|
+
retain,
|
|
1292
|
+
dropRetained,
|
|
1293
|
+
requireRetained,
|
|
1383
1294
|
notifyExpired: expiry.report,
|
|
1384
1295
|
requireCredential: stacks.requireCredential,
|
|
1385
1296
|
getEpoch,
|
|
@@ -1633,6 +1544,204 @@ const createState = (defaultBaseUrl) => {
|
|
|
1633
1544
|
};
|
|
1634
1545
|
};
|
|
1635
1546
|
//#endregion
|
|
1547
|
+
//#region src/keboola/bearer/credentials/renewal.ts
|
|
1548
|
+
const renew = async (client, grant) => {
|
|
1549
|
+
if (grant.type === "cookie") {
|
|
1550
|
+
const { accessToken, expiresIn, sessionId } = await client.token.refreshWithSession({ sessionId: grant.sessionId });
|
|
1551
|
+
return {
|
|
1552
|
+
type: "cookie",
|
|
1553
|
+
accessToken,
|
|
1554
|
+
expiresIn,
|
|
1555
|
+
sessionId
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
const { accessToken, expiresIn, refreshToken } = await client.token.refreshWithToken({ refreshToken: grant.refreshToken });
|
|
1559
|
+
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
1560
|
+
return {
|
|
1561
|
+
type: "token",
|
|
1562
|
+
accessToken,
|
|
1563
|
+
expiresIn,
|
|
1564
|
+
refreshToken
|
|
1565
|
+
};
|
|
1566
|
+
};
|
|
1567
|
+
//#endregion
|
|
1568
|
+
//#region src/keboola/bearer/credentials/credentials.ts
|
|
1569
|
+
const DEFAULT_REFRESH_THRESHOLD = .9;
|
|
1570
|
+
const signInEnded = () => new KeboolaError(KeboolaErrorType.SignInEnded);
|
|
1571
|
+
const toRestoreStatus = (outcome) => {
|
|
1572
|
+
if (outcome === void 0 || outcome === "skipped") return "empty";
|
|
1573
|
+
if (outcome === "refused") return "expired";
|
|
1574
|
+
return outcome;
|
|
1575
|
+
};
|
|
1576
|
+
const createCredentials = ({ state, persistor, middlewares, refreshThreshold = DEFAULT_REFRESH_THRESHOLD, onSignedOut, onExpired }) => {
|
|
1577
|
+
const rotationMap = /* @__PURE__ */ new Map();
|
|
1578
|
+
const generations = /* @__PURE__ */ new Map();
|
|
1579
|
+
const generationOf = (baseUrl) => generations.get(baseUrl) ?? 0;
|
|
1580
|
+
const refresh = async (baseUrl, grant) => {
|
|
1581
|
+
const client = require_authClient.createAuthClient({
|
|
1582
|
+
baseUrl,
|
|
1583
|
+
middlewares
|
|
1584
|
+
});
|
|
1585
|
+
const epochBefore = require_transientRetries.Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1586
|
+
const generationBefore = generationOf(baseUrl);
|
|
1587
|
+
const refreshed = await require_transientRetries.Result.tryCatchAsync(() => renew(client, grant));
|
|
1588
|
+
return require_transientRetries.Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) === epochBefore && generationOf(baseUrl) === generationBefore ? refreshed : require_transientRetries.Result.failure(signInEnded());
|
|
1589
|
+
};
|
|
1590
|
+
/**
|
|
1591
|
+
* A stack's teardown, from the credential's side.
|
|
1592
|
+
*
|
|
1593
|
+
* - Bumps the generation, so an in-flight rotation can no longer write.
|
|
1594
|
+
* - Drops the deduped entry, so nothing joins that rotation.
|
|
1595
|
+
*/
|
|
1596
|
+
const forget = (baseUrl) => {
|
|
1597
|
+
generations.set(baseUrl, generationOf(baseUrl) + 1);
|
|
1598
|
+
rotationMap.delete(baseUrl);
|
|
1599
|
+
};
|
|
1600
|
+
/**
|
|
1601
|
+
* The rotation, and the one place a credential is declared dead.
|
|
1602
|
+
*
|
|
1603
|
+
* - Renews by the credential's grant: the refresh token, or the session id with the cookie.
|
|
1604
|
+
* - A refused refresh token or session is unambiguous.
|
|
1605
|
+
* - The triggering 401 is not (an unreachable project answers the same), so never sign out on a replay.
|
|
1606
|
+
*/
|
|
1607
|
+
const getGrantForRotation = async (store, baseUrl, credential) => {
|
|
1608
|
+
const epochBefore = require_transientRetries.Result.unwrap(state.auth.getEpoch(baseUrl));
|
|
1609
|
+
const generationBefore = generationOf(baseUrl);
|
|
1610
|
+
const hydrated = await require_transientRetries.Result.tryCatchAsync(() => store.read());
|
|
1611
|
+
if (!hydrated.success) return hydrated;
|
|
1612
|
+
if (require_transientRetries.Result.unwrapOr(state.auth.getEpoch(baseUrl), -1) !== epochBefore || generationOf(baseUrl) !== generationBefore) return require_transientRetries.Result.failure(signInEnded());
|
|
1613
|
+
const persistedStack = hydrated.data.stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
1614
|
+
if (persistedStack && persistedStack.credential === null) return require_transientRetries.Result.failure(signInEnded());
|
|
1615
|
+
return require_transientRetries.Result.success(persistedStack?.credential ?? Entry.grant(credential));
|
|
1616
|
+
};
|
|
1617
|
+
const rotateOnce = async (baseUrl) => persistor.locked(async (store) => {
|
|
1618
|
+
const credential = state.auth.requireCredential(baseUrl);
|
|
1619
|
+
if (!credential.success) return credential;
|
|
1620
|
+
const grant = await getGrantForRotation(store, baseUrl, credential.data);
|
|
1621
|
+
if (!grant.success) return grant;
|
|
1622
|
+
const refreshed = await refresh(baseUrl, grant.data);
|
|
1623
|
+
if (!refreshed.success) {
|
|
1624
|
+
if (require_middleware.isUnauthorized(refreshed.error)) await expire(baseUrl, store);
|
|
1625
|
+
return refreshed;
|
|
1626
|
+
}
|
|
1627
|
+
const accessToken = require_transientRetries.Result.map(state.auth.applyRefresh(baseUrl, refreshed.data), () => refreshed.data.accessToken);
|
|
1628
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1629
|
+
return accessToken;
|
|
1630
|
+
});
|
|
1631
|
+
const rotate = (baseUrl) => ensure(rotationMap, baseUrl, () => require_dedupe.dedupe(() => rotateOnce(baseUrl)))();
|
|
1632
|
+
const restoreStack = async (baseUrl, grant, retained = false) => persistor.locked(async (store) => {
|
|
1633
|
+
const storedStack = (await store.read()).stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
1634
|
+
const latestGrant = retained ? storedStack?.retained?.grant : storedStack?.credential;
|
|
1635
|
+
if (storedStack && !latestGrant) return "skipped";
|
|
1636
|
+
if (!state.auth.startRestore(baseUrl).success) return "unreachable";
|
|
1637
|
+
const refreshed = await refresh(baseUrl, latestGrant ?? grant);
|
|
1638
|
+
if (!refreshed.success) {
|
|
1639
|
+
state.auth.cancelRestore(baseUrl);
|
|
1640
|
+
if (require_middleware.isUnauthorized(refreshed.error)) {
|
|
1641
|
+
if (retained) state.auth.dropRetained(baseUrl);
|
|
1642
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1643
|
+
return "refused";
|
|
1644
|
+
}
|
|
1645
|
+
return "unreachable";
|
|
1646
|
+
}
|
|
1647
|
+
state.auth.authenticate(baseUrl, refreshed.data);
|
|
1648
|
+
if (!state.auth.requireCredential(baseUrl).success) return "unreachable";
|
|
1649
|
+
if (retained) state.auth.dropRetained(baseUrl);
|
|
1650
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1651
|
+
return "restored";
|
|
1652
|
+
});
|
|
1653
|
+
const restoreProjects = (baseUrl, projects) => {
|
|
1654
|
+
for (const { projectId } of projects) state.projects.open(baseUrl, projectId);
|
|
1655
|
+
};
|
|
1656
|
+
/**
|
|
1657
|
+
* Every persisted stack back into the table, with whatever credential it can hand back.
|
|
1658
|
+
*
|
|
1659
|
+
* - Never writes the scope. `lastActive` is what was scoped when the session was stored, for the
|
|
1660
|
+
* caller to select.
|
|
1661
|
+
* - `status` reports what became of `lastActive`'s credential; the client reads it to decide
|
|
1662
|
+
* when persistence may start.
|
|
1663
|
+
*/
|
|
1664
|
+
const restore = async () => {
|
|
1665
|
+
const hydrated = await persistor.locked((store) => store.read()).catch((error) => {
|
|
1666
|
+
console.warn("createCredentials: the stored session could not be read", error);
|
|
1667
|
+
return null;
|
|
1668
|
+
});
|
|
1669
|
+
if (hydrated === null) return {
|
|
1670
|
+
lastActive: null,
|
|
1671
|
+
status: "unreachable"
|
|
1672
|
+
};
|
|
1673
|
+
const { stacks, current } = hydrated;
|
|
1674
|
+
const scoped = stacks.find(({ baseUrl }) => baseUrl === current?.baseUrl);
|
|
1675
|
+
const restored = stacks.map(async ({ baseUrl, credential, retained, projects }) => {
|
|
1676
|
+
state.stacks.ensure(baseUrl);
|
|
1677
|
+
if (!credential && !retained) return "unreachable";
|
|
1678
|
+
if (require_transientRetries.Result.unwrapOr(state.auth.getEpoch(baseUrl), 0) > 0) return "skipped";
|
|
1679
|
+
if (retained) state.auth.retain(baseUrl, retained);
|
|
1680
|
+
if (!credential) return "unreachable";
|
|
1681
|
+
const outcome = await restoreStack(baseUrl, credential);
|
|
1682
|
+
if (outcome === "restored") restoreProjects(baseUrl, projects);
|
|
1683
|
+
return outcome;
|
|
1684
|
+
});
|
|
1685
|
+
const results = await Promise.all(restored);
|
|
1686
|
+
const scopedOutcome = scoped?.credential ? results[stacks.indexOf(scoped)] : void 0;
|
|
1687
|
+
return {
|
|
1688
|
+
lastActive: current,
|
|
1689
|
+
status: toRestoreStatus(scopedOutcome)
|
|
1690
|
+
};
|
|
1691
|
+
};
|
|
1692
|
+
/**
|
|
1693
|
+
* Signs a retained stack back in from the grant it kept.
|
|
1694
|
+
*
|
|
1695
|
+
* - `restored` and `refused` empty the slot; `unreachable` keeps it for another try.
|
|
1696
|
+
* - Throws when the stack retains nothing.
|
|
1697
|
+
*/
|
|
1698
|
+
const restoreRetained = async (baseUrl) => {
|
|
1699
|
+
const { grant } = require_transientRetries.Result.unwrap(state.auth.requireRetained(baseUrl));
|
|
1700
|
+
return restoreStack(baseUrl, grant, true);
|
|
1701
|
+
};
|
|
1702
|
+
const isStale = (baseUrl) => {
|
|
1703
|
+
const ageing = require_transientRetries.Result.map(state.auth.requireCredential(baseUrl), ({ issuedAt, expiresIn }) => Date.now() >= issuedAt + expiresIn * 1e3 * refreshThreshold);
|
|
1704
|
+
return require_transientRetries.Result.unwrapOr(ageing, false);
|
|
1705
|
+
};
|
|
1706
|
+
/**
|
|
1707
|
+
* Drops the slot so the next sign-in's requests don't join the dying rotation.
|
|
1708
|
+
*
|
|
1709
|
+
* - Writes nothing: the caller persists the stack, under the lock it holds or takes.
|
|
1710
|
+
*/
|
|
1711
|
+
const signOut = (baseUrl, options) => {
|
|
1712
|
+
rotationMap.delete(baseUrl);
|
|
1713
|
+
const signedOut = state.auth.signOut(baseUrl, options);
|
|
1714
|
+
onSignedOut?.(baseUrl);
|
|
1715
|
+
return signedOut;
|
|
1716
|
+
};
|
|
1717
|
+
const expire = async (baseUrl, store) => {
|
|
1718
|
+
if (!state.auth.notifyExpired(baseUrl)) return;
|
|
1719
|
+
signOut(baseUrl);
|
|
1720
|
+
await store.persistStack(baseUrl, state.store.get());
|
|
1721
|
+
onExpired?.(baseUrl);
|
|
1722
|
+
};
|
|
1723
|
+
const renewIfStale = async (baseUrl) => {
|
|
1724
|
+
if (isStale(baseUrl)) await rotate(baseUrl);
|
|
1725
|
+
};
|
|
1726
|
+
const middleware = (baseUrl) => require_middleware.createBearerAuthMiddleware({ getAccessToken: async ({ forceRefresh = false } = {}) => {
|
|
1727
|
+
if (forceRefresh) {
|
|
1728
|
+
if (!state.auth.requireCredential(baseUrl).success) return null;
|
|
1729
|
+
return require_transientRetries.Result.unwrap(await rotate(baseUrl));
|
|
1730
|
+
}
|
|
1731
|
+
await renewIfStale(baseUrl);
|
|
1732
|
+
return state.auth.getAccessToken(baseUrl);
|
|
1733
|
+
} });
|
|
1734
|
+
return {
|
|
1735
|
+
middleware,
|
|
1736
|
+
rotate,
|
|
1737
|
+
renewIfStale,
|
|
1738
|
+
restore,
|
|
1739
|
+
restoreRetained,
|
|
1740
|
+
signOut,
|
|
1741
|
+
forget
|
|
1742
|
+
};
|
|
1743
|
+
};
|
|
1744
|
+
//#endregion
|
|
1636
1745
|
//#region src/keboola/bearer/context/resource.ts
|
|
1637
1746
|
/**
|
|
1638
1747
|
* Owns fetching one async value per key — a caller names what it needs and never orchestrates the
|
|
@@ -1761,6 +1870,7 @@ const createProjectContext = ({ state, credentials, stackContext }) => {
|
|
|
1761
1870
|
};
|
|
1762
1871
|
//#endregion
|
|
1763
1872
|
//#region src/keboola/bearer/context/stack.ts
|
|
1873
|
+
const STACK_INDEX_TIMEOUT_MS = 3e4;
|
|
1764
1874
|
const createStackContext = (state) => {
|
|
1765
1875
|
const resource = createResource({
|
|
1766
1876
|
key: (baseUrl) => baseUrl,
|
|
@@ -1770,7 +1880,7 @@ const createStackContext = (state) => {
|
|
|
1770
1880
|
type: "sapi-token",
|
|
1771
1881
|
token: ""
|
|
1772
1882
|
}
|
|
1773
|
-
}).getStackInfo({ exclude: "componentDetails" })
|
|
1883
|
+
}).getStackInfo({ exclude: "componentDetails" }, AbortSignal.timeout(STACK_INDEX_TIMEOUT_MS))
|
|
1774
1884
|
});
|
|
1775
1885
|
resource.subscribe(({ key, status }) => {
|
|
1776
1886
|
state.stacks.updateContext(key, status);
|
|
@@ -1949,14 +2059,16 @@ const createPerProject = ({ state, credentials, middlewareFor, stack, clientServ
|
|
|
1949
2059
|
*/
|
|
1950
2060
|
const SESSION_STORAGE_KEY = "keboola:session";
|
|
1951
2061
|
/**
|
|
1952
|
-
* What survives a reload, per
|
|
2062
|
+
* What survives a reload, per grant type.
|
|
2063
|
+
*
|
|
2064
|
+
* - Written under `credential`: the key every blob already stored carries.
|
|
1953
2065
|
*
|
|
1954
2066
|
* - `token`: the refresh token. It rotates, is single-use and is server-revocable, so a leaked
|
|
1955
2067
|
* snapshot has limited and revocable value. The access token is never written.
|
|
1956
2068
|
* - `cookie`: the session id. The session cookie is the durable half and the browser keeps it;
|
|
1957
2069
|
* the id alone renews nothing.
|
|
1958
2070
|
*/
|
|
1959
|
-
const
|
|
2071
|
+
const persistedGrantSchema = zod.discriminatedUnion("type", [zod.object({
|
|
1960
2072
|
type: zod.literal("token"),
|
|
1961
2073
|
refreshToken: zod.string()
|
|
1962
2074
|
}), zod.object({
|
|
@@ -1965,32 +2077,68 @@ const persistedCredentialSchema = zod.discriminatedUnion("type", [zod.object({
|
|
|
1965
2077
|
})]);
|
|
1966
2078
|
/** A record per project rather than a bare id, so a project can grow a field without a migration. */
|
|
1967
2079
|
const persistedProjectSchema = zod.object({ projectId: zod.number() });
|
|
2080
|
+
const persistedStackSchema = zod.object({
|
|
2081
|
+
baseUrl: zod.string(),
|
|
2082
|
+
credential: persistedGrantSchema.nullable().catch(null),
|
|
2083
|
+
retained: zod.object({ grant: persistedGrantSchema }).nullable().default(null).catch(null),
|
|
2084
|
+
projects: zod.array(persistedProjectSchema)
|
|
2085
|
+
});
|
|
1968
2086
|
const persistedSessionSchema = zod.object({
|
|
1969
2087
|
current: zod.object({
|
|
1970
2088
|
baseUrl: zod.string(),
|
|
1971
2089
|
projectId: zod.number().nullable()
|
|
1972
2090
|
}).nullable(),
|
|
1973
|
-
stacks: zod.array(
|
|
1974
|
-
baseUrl: zod.string(),
|
|
1975
|
-
credential: persistedCredentialSchema.nullable().catch(null),
|
|
1976
|
-
projects: zod.array(persistedProjectSchema)
|
|
1977
|
-
}))
|
|
2091
|
+
stacks: zod.array(persistedStackSchema)
|
|
1978
2092
|
});
|
|
1979
2093
|
const EMPTY_PERSISTED_SESSION = {
|
|
1980
2094
|
current: null,
|
|
1981
2095
|
stacks: []
|
|
1982
2096
|
};
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2097
|
+
const projectsOf = (projects, baseUrl) => Object.values(projects).filter((project) => project.baseUrl === baseUrl).map(({ projectId }) => ({ projectId }));
|
|
2098
|
+
const grantsOf = (stack) => ({
|
|
2099
|
+
credential: stack.auth.status === "authenticated" ? Entry.grant(stack.auth.credential) : null,
|
|
2100
|
+
retained: stack.retained
|
|
2101
|
+
});
|
|
2102
|
+
/**
|
|
2103
|
+
* The stored session, rewritten from the table except for the grants.
|
|
2104
|
+
*
|
|
2105
|
+
* - Scope, stack list and open projects come from memory.
|
|
2106
|
+
* - `credential` and `retained` stay as stored: a grant another document rotated must not be put
|
|
2107
|
+
* back by a snapshot of this one's older table.
|
|
2108
|
+
*/
|
|
2109
|
+
const mergeSnapshot = (stored, { active, stacks, projects }) => ({
|
|
2110
|
+
current: {
|
|
2111
|
+
baseUrl: active.baseUrl,
|
|
2112
|
+
projectId: active.projectId
|
|
2113
|
+
},
|
|
2114
|
+
stacks: Object.values(stacks).map(({ baseUrl }) => {
|
|
2115
|
+
const kept = stored.stacks.find((stack) => stack.baseUrl === baseUrl);
|
|
2116
|
+
return {
|
|
2117
|
+
baseUrl,
|
|
2118
|
+
credential: kept?.credential ?? null,
|
|
2119
|
+
retained: kept?.retained ?? null,
|
|
2120
|
+
projects: projectsOf(projects, baseUrl)
|
|
2121
|
+
};
|
|
2122
|
+
})
|
|
2123
|
+
});
|
|
2124
|
+
const upsertStack = (stored, baseUrl, update) => {
|
|
2125
|
+
const index = stored.stacks.findIndex((stack) => stack.baseUrl === baseUrl);
|
|
2126
|
+
const stacks = [...stored.stacks];
|
|
2127
|
+
if (index < 0) stacks.push(update(void 0));
|
|
2128
|
+
else stacks[index] = update(stacks[index]);
|
|
2129
|
+
return {
|
|
2130
|
+
...stored,
|
|
2131
|
+
stacks
|
|
1992
2132
|
};
|
|
1993
2133
|
};
|
|
2134
|
+
/**
|
|
2135
|
+
* The stored session, reached in two ways.
|
|
2136
|
+
*
|
|
2137
|
+
* - `locked`: the only way to read, and the only way to a grant write. Rotation and restore hold
|
|
2138
|
+
* it across the refresh; sign-in, sign-out and the boot restore open it for one step.
|
|
2139
|
+
* - `snapshot`: the table minus its grants, under the lock, coalesced; what the store subscription
|
|
2140
|
+
* feeds, and what a scope change awaits before the document leaves.
|
|
2141
|
+
*/
|
|
1994
2142
|
const createSessionPersistor = (storage) => {
|
|
1995
2143
|
const persistor = createPersistor({
|
|
1996
2144
|
storage,
|
|
@@ -1998,20 +2146,35 @@ const createSessionPersistor = (storage) => {
|
|
|
1998
2146
|
schema: persistedSessionSchema,
|
|
1999
2147
|
defaultValue: EMPTY_PERSISTED_SESSION
|
|
2000
2148
|
});
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2149
|
+
const persistStack = (cell, baseUrl, { stacks, projects }) => {
|
|
2150
|
+
const stack = stacks[baseUrl];
|
|
2151
|
+
if (stack === void 0) return Promise.resolve();
|
|
2152
|
+
return cell.modify((stored) => upsertStack(stored, baseUrl, (existing) => ({
|
|
2153
|
+
baseUrl,
|
|
2154
|
+
...grantsOf(stack),
|
|
2155
|
+
projects: existing?.projects ?? projectsOf(projects, baseUrl)
|
|
2156
|
+
})));
|
|
2157
|
+
};
|
|
2158
|
+
const locked = (task) => persistor.locked((cell) => task({
|
|
2159
|
+
read: cell.read,
|
|
2160
|
+
persistStack: (baseUrl, state) => persistStack(cell, baseUrl, state)
|
|
2161
|
+
}));
|
|
2162
|
+
let latest = null;
|
|
2163
|
+
let pending = null;
|
|
2164
|
+
const snapshot = (state) => {
|
|
2165
|
+
latest = state;
|
|
2166
|
+
if (pending) return pending;
|
|
2167
|
+
const write = persistor.locked((cell) => {
|
|
2168
|
+
pending = null;
|
|
2169
|
+
const table = latest ?? state;
|
|
2170
|
+
return cell.modify((stored) => mergeSnapshot(stored, table));
|
|
2171
|
+
});
|
|
2172
|
+
pending = write;
|
|
2173
|
+
return write;
|
|
2174
|
+
};
|
|
2012
2175
|
return {
|
|
2013
|
-
|
|
2014
|
-
|
|
2176
|
+
locked,
|
|
2177
|
+
snapshot
|
|
2015
2178
|
};
|
|
2016
2179
|
};
|
|
2017
2180
|
//#endregion
|
|
@@ -2129,15 +2292,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2129
2292
|
await credentials.renewIfStale(project.baseUrl);
|
|
2130
2293
|
return headersFor(require_transientRetries.Result.unwrap(state.projects.get(project.id)));
|
|
2131
2294
|
};
|
|
2132
|
-
const
|
|
2133
|
-
|
|
2134
|
-
if (input.type !== "token") return require_transientRetries.Result.unwrap(state.auth.authenticate(stack.baseUrl, input));
|
|
2295
|
+
const toCredential = (input) => {
|
|
2296
|
+
if (input.type !== "token") return input;
|
|
2135
2297
|
const { refreshToken } = input;
|
|
2136
2298
|
if (!refreshToken) throw new KeboolaError(KeboolaErrorType.NotAuthenticated);
|
|
2137
|
-
return
|
|
2299
|
+
return {
|
|
2138
2300
|
...input,
|
|
2139
2301
|
refreshToken
|
|
2140
|
-
}
|
|
2302
|
+
};
|
|
2303
|
+
};
|
|
2304
|
+
const authenticate = (input) => {
|
|
2305
|
+
const { baseUrl } = state.scope.getActiveStack();
|
|
2306
|
+
const signedIn = require_transientRetries.Result.unwrap(state.auth.authenticate(baseUrl, toCredential(input)));
|
|
2307
|
+
persistor.locked((store) => store.persistStack(baseUrl, state.store.get())).catch((error) => {
|
|
2308
|
+
console.warn("createKeboola: the sign-in could not be stored", error);
|
|
2309
|
+
});
|
|
2310
|
+
return signedIn;
|
|
2141
2311
|
};
|
|
2142
2312
|
/**
|
|
2143
2313
|
* The flat product surface: `auth` and `management` per stack, the rest per project.
|
|
@@ -2177,11 +2347,21 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2177
2347
|
require_transientRetries.Result.unwrapOr(state.projects.open(baseUrl, projectId), null);
|
|
2178
2348
|
return perProject.get(project).api;
|
|
2179
2349
|
};
|
|
2180
|
-
/**
|
|
2181
|
-
|
|
2350
|
+
/**
|
|
2351
|
+
* The scope's sign-in, or a named stack's — and everything that sign-in derived.
|
|
2352
|
+
*
|
|
2353
|
+
* - `retain` keeps the grant on the stack, persisted beside the sign-in it ended, for
|
|
2354
|
+
* `restoreRetained`; the next sign-in on the stack replaces it.
|
|
2355
|
+
* - The table is signed out on return; the promise resolves once that is stored, so a caller
|
|
2356
|
+
* leaving the document waits for it.
|
|
2357
|
+
*/
|
|
2358
|
+
const signOut = ({ baseUrl, ...options } = {}) => {
|
|
2182
2359
|
const target = requireStackUrl(baseUrl);
|
|
2183
|
-
|
|
2360
|
+
const signedOut = require_transientRetries.Result.unwrap(credentials.signOut(target, options));
|
|
2361
|
+
return persistor.locked((store) => store.persistStack(target, state.store.get())).then(() => signedOut);
|
|
2184
2362
|
};
|
|
2363
|
+
/** Signs a stack back in from what a retained sign-out kept; `unreachable` leaves it to retry. */
|
|
2364
|
+
const restoreRetained = (baseUrl) => credentials.restoreRetained(require_createFetchClient.normalizeBaseUrl(baseUrl));
|
|
2185
2365
|
/**
|
|
2186
2366
|
* `input` replaces the active stack's sign-in, whatever it holds.
|
|
2187
2367
|
*
|
|
@@ -2218,16 +2398,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2218
2398
|
/**
|
|
2219
2399
|
* Persistence starts only once the restore has settled.
|
|
2220
2400
|
*
|
|
2221
|
-
* - Mid-hydration an unexchanged stack is `anonymous`;
|
|
2401
|
+
* - Mid-hydration an unexchanged stack is `anonymous`; the persistor would erase the
|
|
2222
2402
|
* refresh token the exchange is about to spend.
|
|
2223
2403
|
* - Writes the settled table once: the subscription fires only on the next change.
|
|
2224
2404
|
*/
|
|
2225
2405
|
const enablePersistence = () => {
|
|
2226
2406
|
if (persisting) return;
|
|
2227
2407
|
persisting = true;
|
|
2228
|
-
|
|
2229
|
-
state.store.subscribe(
|
|
2408
|
+
snapshot(state.store.get());
|
|
2409
|
+
state.store.subscribe(snapshot);
|
|
2410
|
+
};
|
|
2411
|
+
const snapshot = (table) => {
|
|
2412
|
+
persistor.snapshot(table).catch((error) => {
|
|
2413
|
+
console.warn("createKeboola: the session could not be stored", error);
|
|
2414
|
+
});
|
|
2230
2415
|
};
|
|
2416
|
+
const persistScope = () => persisting ? persistor.snapshot(state.store.get()) : Promise.resolve();
|
|
2231
2417
|
/**
|
|
2232
2418
|
* The same, deferred until a sign-in.
|
|
2233
2419
|
*
|
|
@@ -2281,14 +2467,22 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2281
2467
|
resume,
|
|
2282
2468
|
stack: {
|
|
2283
2469
|
getActive: getActiveStack,
|
|
2284
|
-
|
|
2470
|
+
/** Scoped on return; resolves once that is stored, for a caller leaving the document. */
|
|
2471
|
+
select: byCaller((baseUrl) => {
|
|
2472
|
+
const stack = selectStack(baseUrl);
|
|
2473
|
+
return persistScope().then(() => stack);
|
|
2474
|
+
}),
|
|
2285
2475
|
close: closeStack,
|
|
2286
2476
|
retryContext: perStack.context.retry,
|
|
2287
2477
|
getContext: (baseUrl) => perStack.context.get(requireStackUrl(baseUrl)),
|
|
2288
2478
|
getContextAsync: (baseUrl) => perStack.context.getAsync(requireStackUrl(baseUrl))
|
|
2289
2479
|
},
|
|
2290
2480
|
project: {
|
|
2291
|
-
|
|
2481
|
+
/** Scoped on return; resolves once that is stored, for a caller leaving the document. */
|
|
2482
|
+
select: byCaller((projectId) => {
|
|
2483
|
+
const project = selectProject(projectId);
|
|
2484
|
+
return persistScope().then(() => project);
|
|
2485
|
+
}),
|
|
2292
2486
|
close: closeProject,
|
|
2293
2487
|
deactivate: state.scope.deactivate,
|
|
2294
2488
|
retryContext: perProject.context.retry,
|
|
@@ -2299,6 +2493,7 @@ const createKeboola = ({ defaultBaseUrl, storage, middlewares, clientServiceUrls
|
|
|
2299
2493
|
authenticate: byCaller(authenticate),
|
|
2300
2494
|
replace: byCaller(replace),
|
|
2301
2495
|
signOut: byCaller(signOut),
|
|
2496
|
+
restoreRetained: byCaller(restoreRetained),
|
|
2302
2497
|
/** Whether the active stack holds a credential — `restoring` is not one yet. */
|
|
2303
2498
|
isAuthenticated,
|
|
2304
2499
|
isAuthenticatedAsync: () => resume().then(isAuthenticated),
|
|
@@ -2548,6 +2743,7 @@ exports.isEmptyDeep = require_configurations.isEmptyDeep;
|
|
|
2548
2743
|
exports.isFetchClientError = require_createFetchClient.isFetchClientError;
|
|
2549
2744
|
exports.isHtmlResponseError = require_validateConnectionStatus.isHtmlResponseError;
|
|
2550
2745
|
exports.isKeboolaError = isKeboolaError;
|
|
2746
|
+
exports.isManageError = require_storage.isManageError;
|
|
2551
2747
|
exports.isManagementClientAuthError = require_management.isManagementClientAuthError;
|
|
2552
2748
|
exports.isManagementSessionMintError = require_management.isManagementSessionMintError;
|
|
2553
2749
|
exports.isPlainObject = require_isPlainObject.isPlainObject;
|
|
@@ -2561,11 +2757,14 @@ exports.isValidationError = require_ValidationError.isValidationError;
|
|
|
2561
2757
|
exports.jobStatus = require_transientRetries.jobStatus;
|
|
2562
2758
|
exports.keboolaUID = require_tag.keboolaUID;
|
|
2563
2759
|
exports.lazy = require_transientRetries.lazy;
|
|
2760
|
+
exports.manageErrorCode = require_storage.manageErrorCode;
|
|
2564
2761
|
exports.nextCursorOf = require_authClient.nextCursorOf;
|
|
2565
2762
|
exports.parseLogLines = require_appLogs.parseLogLines;
|
|
2566
2763
|
exports.parseOrThrow = require_ValidationError.parseOrThrow;
|
|
2567
2764
|
exports.poller = require_transientRetries.poller;
|
|
2765
|
+
exports.queueSeries = queueSeries;
|
|
2568
2766
|
exports.readableReason = require_storage.readableReason;
|
|
2767
|
+
exports.retryAfterSeconds = require_storage.retryAfterSeconds;
|
|
2569
2768
|
exports.schemaGuidedMerge = require_configurations.schemaGuidedMerge;
|
|
2570
2769
|
exports.series = require_storage.series;
|
|
2571
2770
|
exports.shallowEqual = shallowEqual;
|