@stackframe/stack-shared 2.8.8 → 2.8.11
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/CHANGELOG.md +14 -0
- package/dist/config/format.d.cts +39 -0
- package/dist/config/format.d.ts +14 -13
- package/dist/config/format.js +147 -206
- package/dist/config/format.js.map +1 -0
- package/dist/config/schema.d.cts +729 -0
- package/dist/config/schema.d.ts +59 -51
- package/dist/config/schema.js +232 -172
- package/dist/config/schema.js.map +1 -0
- package/dist/crud.d.cts +102 -0
- package/dist/crud.d.ts +15 -13
- package/dist/crud.js +83 -128
- package/dist/crud.js.map +1 -0
- package/dist/esm/config/format.js +135 -0
- package/dist/esm/config/format.js.map +1 -0
- package/dist/esm/config/schema.js +201 -0
- package/dist/esm/config/schema.js.map +1 -0
- package/dist/esm/crud.js +60 -0
- package/dist/esm/crud.js.map +1 -0
- package/dist/esm/global.d.js +1 -0
- package/dist/esm/global.d.js.map +1 -0
- package/dist/esm/helpers/password.js +17 -0
- package/dist/esm/helpers/password.js.map +1 -0
- package/dist/esm/helpers/production-mode.js +50 -0
- package/dist/esm/helpers/production-mode.js.map +1 -0
- package/dist/esm/hooks/use-async-callback.js +38 -0
- package/dist/esm/hooks/use-async-callback.js.map +1 -0
- package/dist/esm/hooks/use-async-external-store.js +23 -0
- package/dist/esm/hooks/use-async-external-store.js.map +1 -0
- package/dist/esm/hooks/use-hash.js +17 -0
- package/dist/esm/hooks/use-hash.js.map +1 -0
- package/dist/esm/hooks/use-strict-memo.js +61 -0
- package/dist/esm/hooks/use-strict-memo.js.map +1 -0
- package/dist/esm/index.js +22 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interface/adminInterface.js +244 -0
- package/dist/esm/interface/adminInterface.js.map +1 -0
- package/dist/esm/interface/clientInterface.js +2041 -0
- package/dist/esm/interface/clientInterface.js.map +1 -0
- package/dist/esm/interface/crud/contact-channels.js +77 -0
- package/dist/esm/interface/crud/contact-channels.js.map +1 -0
- package/dist/esm/interface/crud/current-user.js +65 -0
- package/dist/esm/interface/crud/current-user.js.map +1 -0
- package/dist/esm/interface/crud/email-templates.js +52 -0
- package/dist/esm/interface/crud/email-templates.js.map +1 -0
- package/dist/esm/interface/crud/emails.js +20 -0
- package/dist/esm/interface/crud/emails.js.map +1 -0
- package/dist/esm/interface/crud/internal-api-keys.js +69 -0
- package/dist/esm/interface/crud/internal-api-keys.js.map +1 -0
- package/dist/esm/interface/crud/oauth.js +24 -0
- package/dist/esm/interface/crud/oauth.js.map +1 -0
- package/dist/esm/interface/crud/project-api-keys.js +93 -0
- package/dist/esm/interface/crud/project-api-keys.js.map +1 -0
- package/dist/esm/interface/crud/project-permissions.js +113 -0
- package/dist/esm/interface/crud/project-permissions.js.map +1 -0
- package/dist/esm/interface/crud/projects.js +180 -0
- package/dist/esm/interface/crud/projects.js.map +1 -0
- package/dist/esm/interface/crud/sessions.js +62 -0
- package/dist/esm/interface/crud/sessions.js.map +1 -0
- package/dist/esm/interface/crud/svix-token.js +22 -0
- package/dist/esm/interface/crud/svix-token.js.map +1 -0
- package/dist/esm/interface/crud/team-invitation-details.js +23 -0
- package/dist/esm/interface/crud/team-invitation-details.js.map +1 -0
- package/dist/esm/interface/crud/team-invitation.js +36 -0
- package/dist/esm/interface/crud/team-invitation.js.map +1 -0
- package/dist/esm/interface/crud/team-member-profiles.js +62 -0
- package/dist/esm/interface/crud/team-member-profiles.js.map +1 -0
- package/dist/esm/interface/crud/team-memberships.js +60 -0
- package/dist/esm/interface/crud/team-memberships.js.map +1 -0
- package/dist/esm/interface/crud/team-permissions.js +114 -0
- package/dist/esm/interface/crud/team-permissions.js.map +1 -0
- package/dist/esm/interface/crud/teams.js +143 -0
- package/dist/esm/interface/crud/teams.js.map +1 -0
- package/dist/esm/interface/crud/users.js +139 -0
- package/dist/esm/interface/crud/users.js.map +1 -0
- package/dist/esm/interface/serverInterface.js +485 -0
- package/dist/esm/interface/serverInterface.js.map +1 -0
- package/dist/esm/interface/webhooks.js +21 -0
- package/dist/esm/interface/webhooks.js.map +1 -0
- package/dist/esm/known-errors.js +1238 -0
- package/dist/esm/known-errors.js.map +1 -0
- package/dist/esm/schema-fields.js +484 -0
- package/dist/esm/schema-fields.js.map +1 -0
- package/dist/esm/sessions.js +168 -0
- package/dist/esm/sessions.js.map +1 -0
- package/dist/esm/utils/api-keys.js +79 -0
- package/dist/esm/utils/api-keys.js.map +1 -0
- package/dist/esm/utils/arrays.js +78 -0
- package/dist/esm/utils/arrays.js.map +1 -0
- package/dist/esm/utils/base64.js +18 -0
- package/dist/esm/utils/base64.js.map +1 -0
- package/dist/esm/utils/booleans.js +12 -0
- package/dist/esm/utils/booleans.js.map +1 -0
- package/dist/esm/utils/browser-compat.js +21 -0
- package/dist/esm/utils/browser-compat.js.map +1 -0
- package/dist/esm/utils/bytes.js +160 -0
- package/dist/esm/utils/bytes.js.map +1 -0
- package/dist/esm/utils/caches.js +167 -0
- package/dist/esm/utils/caches.js.map +1 -0
- package/dist/esm/utils/compile-time.js +11 -0
- package/dist/esm/utils/compile-time.js.map +1 -0
- package/dist/esm/utils/crypto.js +25 -0
- package/dist/esm/utils/crypto.js.map +1 -0
- package/dist/esm/utils/dates.js +64 -0
- package/dist/esm/utils/dates.js.map +1 -0
- package/dist/esm/utils/dom.js +11 -0
- package/dist/esm/utils/dom.js.map +1 -0
- package/dist/esm/utils/env.js +58 -0
- package/dist/esm/utils/env.js.map +1 -0
- package/dist/esm/utils/errors.js +174 -0
- package/dist/esm/utils/errors.js.map +1 -0
- package/dist/esm/utils/fs.js +37 -0
- package/dist/esm/utils/fs.js.map +1 -0
- package/dist/esm/utils/functions.js +12 -0
- package/dist/esm/utils/functions.js.map +1 -0
- package/dist/esm/utils/geo.js +15 -0
- package/dist/esm/utils/geo.js.map +1 -0
- package/dist/esm/utils/globals.js +18 -0
- package/dist/esm/utils/globals.js.map +1 -0
- package/dist/esm/utils/hashes.js +55 -0
- package/dist/esm/utils/hashes.js.map +1 -0
- package/dist/esm/utils/html.js +13 -0
- package/dist/esm/utils/html.js.map +1 -0
- package/dist/esm/utils/http.js +60 -0
- package/dist/esm/utils/http.js.map +1 -0
- package/dist/esm/utils/ips.js +15 -0
- package/dist/esm/utils/ips.js.map +1 -0
- package/dist/esm/utils/json.js +31 -0
- package/dist/esm/utils/json.js.map +1 -0
- package/dist/esm/utils/jwt.js +87 -0
- package/dist/esm/utils/jwt.js.map +1 -0
- package/dist/esm/utils/locks.js +57 -0
- package/dist/esm/utils/locks.js.map +1 -0
- package/dist/esm/utils/maps.js +181 -0
- package/dist/esm/utils/maps.js.map +1 -0
- package/dist/esm/utils/math.js +8 -0
- package/dist/esm/utils/math.js.map +1 -0
- package/dist/esm/utils/node-http.js +42 -0
- package/dist/esm/utils/node-http.js.map +1 -0
- package/dist/esm/utils/numbers.js +32 -0
- package/dist/esm/utils/numbers.js.map +1 -0
- package/dist/esm/utils/oauth.js +10 -0
- package/dist/esm/utils/oauth.js.map +1 -0
- package/dist/esm/utils/objects.js +177 -0
- package/dist/esm/utils/objects.js.map +1 -0
- package/dist/esm/utils/passkey.js +1 -0
- package/dist/esm/utils/passkey.js.map +1 -0
- package/dist/esm/utils/promises.js +233 -0
- package/dist/esm/utils/promises.js.map +1 -0
- package/dist/esm/utils/proxies.js +128 -0
- package/dist/esm/utils/proxies.js.map +1 -0
- package/dist/esm/utils/react.js +78 -0
- package/dist/esm/utils/react.js.map +1 -0
- package/dist/esm/utils/results.js +141 -0
- package/dist/esm/utils/results.js.map +1 -0
- package/dist/esm/utils/sentry.js +20 -0
- package/dist/esm/utils/sentry.js.map +1 -0
- package/dist/esm/utils/stores.js +195 -0
- package/dist/esm/utils/stores.js.map +1 -0
- package/dist/esm/utils/strings.js +295 -0
- package/dist/esm/utils/strings.js.map +1 -0
- package/dist/esm/utils/strings.nicify.test.js +222 -0
- package/dist/esm/utils/strings.nicify.test.js.map +1 -0
- package/dist/esm/utils/types.js +1 -0
- package/dist/esm/utils/types.js.map +1 -0
- package/dist/esm/utils/unicode.js +11 -0
- package/dist/esm/utils/unicode.js.map +1 -0
- package/dist/esm/utils/urls.js +53 -0
- package/dist/esm/utils/urls.js.map +1 -0
- package/dist/esm/utils/uuids.js +16 -0
- package/dist/esm/utils/uuids.js.map +1 -0
- package/dist/global.d.d.cts +1 -0
- package/dist/global.d.d.ts +1 -0
- package/dist/global.d.js +2 -0
- package/dist/global.d.js.map +1 -0
- package/dist/helpers/password.d.cts +11 -0
- package/dist/helpers/password.d.ts +11 -2
- package/dist/helpers/password.js +41 -11
- package/dist/helpers/password.js.map +1 -0
- package/dist/helpers/production-mode.d.cts +12 -0
- package/dist/helpers/production-mode.d.ts +9 -3
- package/dist/helpers/production-mode.js +72 -45
- package/dist/helpers/production-mode.js.map +1 -0
- package/dist/hooks/use-async-callback.d.cts +6 -0
- package/dist/hooks/use-async-callback.d.ts +6 -3
- package/dist/hooks/use-async-callback.js +72 -30
- package/dist/hooks/use-async-callback.js.map +1 -0
- package/dist/hooks/use-async-external-store.d.cts +7 -0
- package/dist/hooks/use-async-external-store.d.ts +5 -2
- package/dist/hooks/use-async-external-store.js +47 -19
- package/dist/hooks/use-async-external-store.js.map +1 -0
- package/dist/hooks/use-hash.d.cts +3 -0
- package/dist/hooks/use-hash.d.ts +3 -1
- package/dist/hooks/use-hash.js +41 -8
- package/dist/hooks/use-hash.js.map +1 -0
- package/dist/hooks/use-strict-memo.d.cts +8 -0
- package/dist/hooks/use-strict-memo.d.ts +3 -1
- package/dist/hooks/use-strict-memo.js +78 -131
- package/dist/hooks/use-strict-memo.js.map +1 -0
- package/dist/index.d.cts +30 -0
- package/dist/index.d.ts +30 -4
- package/dist/index.js +42 -4
- package/dist/index.js.map +1 -0
- package/dist/interface/adminInterface.d.cts +94 -0
- package/dist/interface/adminInterface.d.ts +38 -15
- package/dist/interface/adminInterface.js +269 -174
- package/dist/interface/adminInterface.js.map +1 -0
- package/dist/interface/clientInterface.d.cts +260 -0
- package/dist/interface/clientInterface.d.ts +25 -18
- package/dist/interface/clientInterface.js +2054 -995
- package/dist/interface/clientInterface.js.map +1 -0
- package/dist/interface/crud/contact-channels.d.cts +180 -0
- package/dist/interface/crud/contact-channels.d.ts +30 -25
- package/dist/interface/crud/contact-channels.js +101 -59
- package/dist/interface/crud/contact-channels.js.map +1 -0
- package/dist/interface/crud/current-user.d.cts +205 -0
- package/dist/interface/crud/current-user.d.ts +17 -12
- package/dist/interface/crud/current-user.js +86 -56
- package/dist/interface/crud/current-user.js.map +1 -0
- package/dist/interface/crud/email-templates.d.cts +84 -0
- package/dist/interface/crud/email-templates.d.ts +24 -19
- package/dist/interface/crud/email-templates.js +77 -37
- package/dist/interface/crud/email-templates.js.map +1 -0
- package/dist/interface/crud/emails.d.cts +69 -0
- package/dist/interface/crud/emails.d.ts +12 -7
- package/dist/interface/crud/emails.js +54 -12
- package/dist/interface/crud/emails.js.map +1 -0
- package/dist/interface/crud/internal-api-keys.d.cts +139 -0
- package/dist/interface/crud/internal-api-keys.d.ts +22 -17
- package/dist/interface/crud/internal-api-keys.js +92 -54
- package/dist/interface/crud/internal-api-keys.js.map +1 -0
- package/dist/interface/crud/oauth.d.cts +34 -0
- package/dist/interface/crud/oauth.d.ts +16 -11
- package/dist/interface/crud/oauth.js +48 -14
- package/dist/interface/crud/oauth.js.map +1 -0
- package/dist/interface/crud/project-api-keys.d.cts +196 -0
- package/dist/interface/crud/project-api-keys.d.ts +20 -12
- package/dist/interface/crud/project-api-keys.js +121 -74
- package/dist/interface/crud/project-api-keys.js.map +1 -0
- package/dist/interface/crud/project-permissions.d.cts +160 -0
- package/dist/interface/crud/project-permissions.d.ts +38 -33
- package/dist/interface/crud/project-permissions.js +148 -90
- package/dist/interface/crud/project-permissions.js.map +1 -0
- package/dist/interface/crud/projects.d.cts +627 -0
- package/dist/interface/crud/projects.d.ts +43 -51
- package/dist/interface/crud/projects.js +210 -156
- package/dist/interface/crud/projects.js.map +1 -0
- package/dist/interface/crud/sessions.d.cts +149 -0
- package/dist/interface/crud/sessions.d.ts +21 -16
- package/dist/interface/crud/sessions.js +86 -50
- package/dist/interface/crud/sessions.js.map +1 -0
- package/dist/interface/crud/svix-token.d.cts +26 -0
- package/dist/interface/crud/svix-token.d.ts +14 -9
- package/dist/interface/crud/svix-token.js +46 -12
- package/dist/interface/crud/svix-token.js.map +1 -0
- package/dist/interface/crud/team-invitation-details.d.cts +30 -0
- package/dist/interface/crud/team-invitation-details.d.ts +12 -7
- package/dist/interface/crud/team-invitation-details.js +57 -15
- package/dist/interface/crud/team-invitation-details.js.map +1 -0
- package/dist/interface/crud/team-invitation.d.cts +49 -0
- package/dist/interface/crud/team-invitation.d.ts +13 -8
- package/dist/interface/crud/team-invitation.js +69 -27
- package/dist/interface/crud/team-invitation.js.map +1 -0
- package/dist/interface/crud/team-member-profiles.d.cts +229 -0
- package/dist/interface/crud/team-member-profiles.d.ts +20 -15
- package/dist/interface/crud/team-member-profiles.js +95 -49
- package/dist/interface/crud/team-member-profiles.js.map +1 -0
- package/dist/interface/crud/team-memberships.d.cts +74 -0
- package/dist/interface/crud/team-memberships.d.ts +22 -17
- package/dist/interface/crud/team-memberships.js +85 -45
- package/dist/interface/crud/team-memberships.js.map +1 -0
- package/dist/interface/crud/team-permissions.d.cts +168 -0
- package/dist/interface/crud/team-permissions.d.ts +38 -33
- package/dist/interface/crud/team-permissions.js +149 -91
- package/dist/interface/crud/team-permissions.js.map +1 -0
- package/dist/interface/crud/teams.d.cts +298 -0
- package/dist/interface/crud/teams.d.ts +45 -40
- package/dist/interface/crud/teams.js +177 -119
- package/dist/interface/crud/teams.js.map +1 -0
- package/dist/interface/crud/users.d.cts +469 -0
- package/dist/interface/crud/users.d.ts +31 -26
- package/dist/interface/crud/users.js +172 -118
- package/dist/interface/crud/users.js.map +1 -0
- package/dist/interface/serverInterface.d.cts +128 -0
- package/dist/interface/serverInterface.d.ts +29 -17
- package/dist/interface/serverInterface.js +506 -339
- package/dist/interface/serverInterface.js.map +1 -0
- package/dist/interface/webhooks.d.cts +292 -0
- package/dist/interface/webhooks.d.ts +6 -3
- package/dist/interface/webhooks.js +45 -15
- package/dist/interface/webhooks.js.map +1 -0
- package/dist/known-errors.d.cts +447 -0
- package/dist/known-errors.d.ts +15 -9
- package/dist/known-errors.js +1104 -562
- package/dist/known-errors.js.map +1 -0
- package/dist/schema-fields.d.cts +163 -0
- package/dist/schema-fields.d.ts +116 -114
- package/dist/schema-fields.js +593 -427
- package/dist/schema-fields.js.map +1 -0
- package/dist/sessions.d.cts +109 -0
- package/dist/sessions.d.ts +6 -3
- package/dist/sessions.js +201 -172
- package/dist/sessions.js.map +1 -0
- package/dist/utils/api-keys.d.cts +24 -0
- package/dist/utils/api-keys.d.ts +5 -4
- package/dist/utils/api-keys.js +106 -66
- package/dist/utils/api-keys.js.map +1 -0
- package/dist/utils/arrays.d.cts +18 -0
- package/dist/utils/arrays.d.ts +15 -13
- package/dist/utils/arrays.js +101 -168
- package/dist/utils/arrays.js.map +1 -0
- package/dist/utils/base64.d.cts +4 -0
- package/dist/utils/base64.d.ts +4 -2
- package/dist/utils/base64.js +41 -20
- package/dist/utils/base64.js.map +1 -0
- package/dist/utils/booleans.d.cts +6 -0
- package/dist/utils/booleans.d.ts +6 -4
- package/dist/utils/booleans.js +35 -27
- package/dist/utils/booleans.js.map +1 -0
- package/dist/utils/browser-compat.d.cts +8 -0
- package/dist/utils/browser-compat.d.ts +3 -1
- package/dist/utils/browser-compat.js +45 -16
- package/dist/utils/browser-compat.js.map +1 -0
- package/dist/utils/bytes.d.cts +15 -0
- package/dist/utils/bytes.d.ts +15 -13
- package/dist/utils/bytes.js +182 -270
- package/dist/utils/bytes.js.map +1 -0
- package/dist/utils/caches.d.cts +98 -0
- package/dist/utils/caches.d.ts +17 -14
- package/dist/utils/caches.js +188 -193
- package/dist/utils/caches.js.map +1 -0
- package/dist/utils/compile-time.d.cts +8 -0
- package/dist/utils/compile-time.d.ts +3 -1
- package/dist/utils/compile-time.js +35 -10
- package/dist/utils/compile-time.js.map +1 -0
- package/dist/utils/crypto.d.cts +8 -0
- package/dist/utils/crypto.d.ts +4 -2
- package/dist/utils/crypto.js +49 -21
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/dates.d.cts +15 -0
- package/dist/utils/dates.d.ts +6 -4
- package/dist/utils/dates.js +83 -105
- package/dist/utils/dates.js.map +1 -0
- package/dist/utils/dom.d.cts +3 -0
- package/dist/utils/dom.d.ts +3 -1
- package/dist/utils/dom.js +35 -7
- package/dist/utils/dom.js.map +1 -0
- package/dist/utils/env.d.cts +9 -0
- package/dist/utils/env.d.ts +6 -4
- package/dist/utils/env.js +70 -43
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/errors.d.cts +223 -0
- package/dist/utils/errors.d.ts +14 -11
- package/dist/utils/errors.js +148 -126
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/fs.d.cts +7 -0
- package/dist/utils/fs.d.ts +5 -3
- package/dist/utils/fs.js +70 -27
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/functions.d.cts +4 -0
- package/dist/utils/functions.d.ts +4 -2
- package/dist/utils/functions.js +35 -18
- package/dist/utils/functions.js.map +1 -0
- package/dist/utils/geo.d.cts +22 -0
- package/dist/utils/geo.d.ts +6 -3
- package/dist/utils/geo.js +39 -9
- package/dist/utils/geo.js.map +1 -0
- package/dist/utils/globals.d.cts +5 -0
- package/dist/utils/globals.d.ts +4 -2
- package/dist/utils/globals.js +41 -14
- package/dist/utils/globals.js.map +1 -0
- package/dist/utils/hashes.d.cts +7 -0
- package/dist/utils/hashes.d.ts +7 -5
- package/dist/utils/hashes.js +87 -41
- package/dist/utils/hashes.js.map +1 -0
- package/dist/utils/html.d.cts +4 -0
- package/dist/utils/html.d.ts +4 -2
- package/dist/utils/html.js +36 -37
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/http.d.cts +43 -0
- package/dist/utils/http.d.ts +6 -4
- package/dist/utils/http.js +83 -83
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/ips.d.cts +6 -0
- package/dist/utils/ips.d.ts +6 -4
- package/dist/utils/ips.js +48 -35
- package/dist/utils/ips.js.map +1 -0
- package/dist/utils/json.d.cts +13 -0
- package/dist/utils/json.d.ts +9 -6
- package/dist/utils/json.js +54 -157
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/jwt.d.cts +44 -0
- package/dist/utils/jwt.d.ts +14 -11
- package/dist/utils/jwt.js +119 -84
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/locks.d.cts +15 -0
- package/dist/utils/locks.d.ts +3 -2
- package/dist/utils/locks.js +76 -56
- package/dist/utils/locks.js.map +1 -0
- package/dist/utils/maps.d.cts +59 -0
- package/dist/utils/maps.d.ts +6 -4
- package/dist/utils/maps.js +207 -343
- package/dist/utils/maps.js.map +1 -0
- package/dist/utils/math.d.cts +6 -0
- package/dist/utils/math.d.ts +3 -1
- package/dist/utils/math.js +31 -16
- package/dist/utils/math.js.map +1 -0
- package/dist/utils/node-http.d.cts +15 -0
- package/dist/utils/node-http.d.ts +5 -5
- package/dist/utils/node-http.js +65 -36
- package/dist/utils/node-http.js.map +1 -0
- package/dist/utils/numbers.d.cts +5 -0
- package/dist/utils/numbers.d.ts +5 -3
- package/dist/utils/numbers.js +53 -66
- package/dist/utils/numbers.js.map +1 -0
- package/dist/utils/oauth.d.cts +8 -0
- package/dist/utils/oauth.d.ts +8 -6
- package/dist/utils/oauth.js +37 -4
- package/dist/utils/oauth.js.map +1 -0
- package/dist/utils/objects.d.cts +69 -0
- package/dist/utils/objects.d.ts +37 -32
- package/dist/utils/objects.js +224 -374
- package/dist/utils/objects.js.map +1 -0
- package/dist/utils/passkey.d.cts +1 -0
- package/dist/utils/passkey.d.ts +1 -1
- package/dist/utils/passkey.js +19 -1
- package/dist/utils/passkey.js.map +1 -0
- package/dist/utils/promises.d.cts +74 -0
- package/dist/utils/promises.d.ts +20 -18
- package/dist/utils/promises.js +252 -393
- package/dist/utils/promises.js.map +1 -0
- package/dist/utils/proxies.d.cts +4 -0
- package/dist/utils/proxies.d.ts +4 -2
- package/dist/utils/proxies.js +150 -161
- package/dist/utils/proxies.js.map +1 -0
- package/dist/utils/react.d.cts +25 -0
- package/dist/utils/react.d.ts +9 -6
- package/dist/utils/react.js +88 -134
- package/dist/utils/react.js.map +1 -0
- package/dist/utils/results.d.cts +78 -0
- package/dist/utils/results.d.ts +10 -9
- package/dist/utils/results.js +143 -324
- package/dist/utils/results.js.map +1 -0
- package/dist/utils/sentry.d.cts +5 -0
- package/dist/utils/sentry.d.ts +5 -2
- package/dist/utils/sentry.js +44 -14
- package/dist/utils/sentry.js.map +1 -0
- package/dist/utils/stores.d.cts +102 -0
- package/dist/utils/stores.d.ts +12 -9
- package/dist/utils/stores.js +219 -189
- package/dist/utils/stores.js.map +1 -0
- package/dist/utils/strings.d.cts +72 -0
- package/dist/utils/strings.d.ts +22 -20
- package/dist/utils/strings.js +300 -580
- package/dist/utils/strings.js.map +1 -0
- package/dist/utils/strings.nicify.test.d.cts +2 -0
- package/dist/utils/strings.nicify.test.d.ts +2 -1
- package/dist/utils/strings.nicify.test.js +168 -158
- package/dist/utils/strings.nicify.test.js.map +1 -0
- package/dist/utils/types.d.cts +23 -0
- package/dist/utils/types.d.ts +8 -6
- package/dist/utils/types.js +19 -1
- package/dist/utils/types.js.map +1 -0
- package/dist/utils/unicode.d.cts +3 -0
- package/dist/utils/unicode.d.ts +3 -1
- package/dist/utils/unicode.js +34 -21
- package/dist/utils/unicode.js.map +1 -0
- package/dist/utils/urls.d.cts +20 -0
- package/dist/utils/urls.d.ts +10 -8
- package/dist/utils/urls.js +76 -165
- package/dist/utils/urls.js.map +1 -0
- package/dist/utils/uuids.d.cts +4 -0
- package/dist/utils/uuids.d.ts +4 -2
- package/dist/utils/uuids.js +39 -35
- package/dist/utils/uuids.js.map +1 -0
- package/package.json +5 -5
|
@@ -1,76 +1,934 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/interface/clientInterface.ts
|
|
21
|
+
var clientInterface_exports = {};
|
|
22
|
+
__export(clientInterface_exports, {
|
|
23
|
+
StackClientInterface: () => StackClientInterface
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(clientInterface_exports);
|
|
26
|
+
|
|
27
|
+
// ../../node_modules/.pnpm/oauth4webapi@2.10.4/node_modules/oauth4webapi/build/index.js
|
|
28
|
+
var USER_AGENT;
|
|
29
|
+
if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) {
|
|
30
|
+
const NAME = "oauth4webapi";
|
|
31
|
+
const VERSION = "v2.10.4";
|
|
32
|
+
USER_AGENT = `${NAME}/${VERSION}`;
|
|
33
|
+
}
|
|
34
|
+
function looseInstanceOf(input, expected) {
|
|
35
|
+
if (input == null) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return input instanceof expected || Object.getPrototypeOf(input)[Symbol.toStringTag] === expected.prototype[Symbol.toStringTag];
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
var clockSkew = Symbol();
|
|
45
|
+
var clockTolerance = Symbol();
|
|
46
|
+
var customFetch = Symbol();
|
|
47
|
+
var useMtlsAlias = Symbol();
|
|
48
|
+
var encoder = new TextEncoder();
|
|
49
|
+
var decoder = new TextDecoder();
|
|
50
|
+
function buf(input) {
|
|
51
|
+
if (typeof input === "string") {
|
|
52
|
+
return encoder.encode(input);
|
|
53
|
+
}
|
|
54
|
+
return decoder.decode(input);
|
|
55
|
+
}
|
|
56
|
+
var CHUNK_SIZE = 32768;
|
|
57
|
+
function encodeBase64Url(input) {
|
|
58
|
+
if (input instanceof ArrayBuffer) {
|
|
59
|
+
input = new Uint8Array(input);
|
|
60
|
+
}
|
|
61
|
+
const arr = [];
|
|
62
|
+
for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {
|
|
63
|
+
arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
64
|
+
}
|
|
65
|
+
return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
66
|
+
}
|
|
67
|
+
function decodeBase64Url(input) {
|
|
68
|
+
try {
|
|
69
|
+
const binary = atob(input.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""));
|
|
70
|
+
const bytes = new Uint8Array(binary.length);
|
|
71
|
+
for (let i = 0; i < binary.length; i++) {
|
|
72
|
+
bytes[i] = binary.charCodeAt(i);
|
|
73
|
+
}
|
|
74
|
+
return bytes;
|
|
75
|
+
} catch (cause) {
|
|
76
|
+
throw new OPE("The input to be decoded is not correctly encoded.", { cause });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function b64u(input) {
|
|
80
|
+
if (typeof input === "string") {
|
|
81
|
+
return decodeBase64Url(input);
|
|
82
|
+
}
|
|
83
|
+
return encodeBase64Url(input);
|
|
84
|
+
}
|
|
85
|
+
var LRU = class {
|
|
86
|
+
constructor(maxSize) {
|
|
87
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
88
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
89
|
+
this.maxSize = maxSize;
|
|
90
|
+
}
|
|
91
|
+
get(key) {
|
|
92
|
+
let v = this.cache.get(key);
|
|
93
|
+
if (v) {
|
|
94
|
+
return v;
|
|
95
|
+
}
|
|
96
|
+
if (v = this._cache.get(key)) {
|
|
97
|
+
this.update(key, v);
|
|
98
|
+
return v;
|
|
99
|
+
}
|
|
100
|
+
return void 0;
|
|
101
|
+
}
|
|
102
|
+
has(key) {
|
|
103
|
+
return this.cache.has(key) || this._cache.has(key);
|
|
104
|
+
}
|
|
105
|
+
set(key, value) {
|
|
106
|
+
if (this.cache.has(key)) {
|
|
107
|
+
this.cache.set(key, value);
|
|
108
|
+
} else {
|
|
109
|
+
this.update(key, value);
|
|
110
|
+
}
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
delete(key) {
|
|
114
|
+
if (this.cache.has(key)) {
|
|
115
|
+
return this.cache.delete(key);
|
|
116
|
+
}
|
|
117
|
+
if (this._cache.has(key)) {
|
|
118
|
+
return this._cache.delete(key);
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
update(key, value) {
|
|
123
|
+
this.cache.set(key, value);
|
|
124
|
+
if (this.cache.size >= this.maxSize) {
|
|
125
|
+
this._cache = this.cache;
|
|
126
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var UnsupportedOperationError = class extends Error {
|
|
131
|
+
constructor(message) {
|
|
132
|
+
super(message ?? "operation not supported");
|
|
133
|
+
this.name = this.constructor.name;
|
|
134
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var OperationProcessingError = class extends Error {
|
|
138
|
+
constructor(message, options) {
|
|
139
|
+
super(message, options);
|
|
140
|
+
this.name = this.constructor.name;
|
|
141
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var OPE = OperationProcessingError;
|
|
145
|
+
var dpopNonces = new LRU(100);
|
|
146
|
+
function isCryptoKey(key) {
|
|
147
|
+
return key instanceof CryptoKey;
|
|
148
|
+
}
|
|
149
|
+
function isPrivateKey(key) {
|
|
150
|
+
return isCryptoKey(key) && key.type === "private";
|
|
151
|
+
}
|
|
152
|
+
function isPublicKey(key) {
|
|
153
|
+
return isCryptoKey(key) && key.type === "public";
|
|
154
|
+
}
|
|
155
|
+
function processDpopNonce(response) {
|
|
156
|
+
try {
|
|
157
|
+
const nonce = response.headers.get("dpop-nonce");
|
|
158
|
+
if (nonce) {
|
|
159
|
+
dpopNonces.set(new URL(response.url).origin, nonce);
|
|
160
|
+
}
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
return response;
|
|
164
|
+
}
|
|
165
|
+
function isJsonObject(input) {
|
|
166
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
function prepareHeaders(input) {
|
|
172
|
+
if (looseInstanceOf(input, Headers)) {
|
|
173
|
+
input = Object.fromEntries(input.entries());
|
|
174
|
+
}
|
|
175
|
+
const headers = new Headers(input);
|
|
176
|
+
if (USER_AGENT && !headers.has("user-agent")) {
|
|
177
|
+
headers.set("user-agent", USER_AGENT);
|
|
178
|
+
}
|
|
179
|
+
if (headers.has("authorization")) {
|
|
180
|
+
throw new TypeError('"options.headers" must not include the "authorization" header name');
|
|
181
|
+
}
|
|
182
|
+
if (headers.has("dpop")) {
|
|
183
|
+
throw new TypeError('"options.headers" must not include the "dpop" header name');
|
|
184
|
+
}
|
|
185
|
+
return headers;
|
|
186
|
+
}
|
|
187
|
+
function signal(value) {
|
|
188
|
+
if (typeof value === "function") {
|
|
189
|
+
value = value();
|
|
190
|
+
}
|
|
191
|
+
if (!(value instanceof AbortSignal)) {
|
|
192
|
+
throw new TypeError('"options.signal" must return or be an instance of AbortSignal');
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
function validateString(input) {
|
|
197
|
+
return typeof input === "string" && input.length !== 0;
|
|
198
|
+
}
|
|
199
|
+
function randomBytes() {
|
|
200
|
+
return b64u(crypto.getRandomValues(new Uint8Array(32)));
|
|
201
|
+
}
|
|
202
|
+
function getKeyAndKid(input) {
|
|
203
|
+
if (input instanceof CryptoKey) {
|
|
204
|
+
return { key: input };
|
|
205
|
+
}
|
|
206
|
+
if (!(input?.key instanceof CryptoKey)) {
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
if (input.kid !== void 0 && !validateString(input.kid)) {
|
|
210
|
+
throw new TypeError('"kid" must be a non-empty string');
|
|
211
|
+
}
|
|
212
|
+
return { key: input.key, kid: input.kid };
|
|
213
|
+
}
|
|
214
|
+
function formUrlEncode(token) {
|
|
215
|
+
return encodeURIComponent(token).replace(/%20/g, "+");
|
|
216
|
+
}
|
|
217
|
+
function clientSecretBasic(clientId, clientSecret) {
|
|
218
|
+
const username = formUrlEncode(clientId);
|
|
219
|
+
const password = formUrlEncode(clientSecret);
|
|
220
|
+
const credentials = btoa(`${username}:${password}`);
|
|
221
|
+
return `Basic ${credentials}`;
|
|
222
|
+
}
|
|
223
|
+
function psAlg(key) {
|
|
224
|
+
switch (key.algorithm.hash.name) {
|
|
225
|
+
case "SHA-256":
|
|
226
|
+
return "PS256";
|
|
227
|
+
case "SHA-384":
|
|
228
|
+
return "PS384";
|
|
229
|
+
case "SHA-512":
|
|
230
|
+
return "PS512";
|
|
231
|
+
default:
|
|
232
|
+
throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function rsAlg(key) {
|
|
236
|
+
switch (key.algorithm.hash.name) {
|
|
237
|
+
case "SHA-256":
|
|
238
|
+
return "RS256";
|
|
239
|
+
case "SHA-384":
|
|
240
|
+
return "RS384";
|
|
241
|
+
case "SHA-512":
|
|
242
|
+
return "RS512";
|
|
243
|
+
default:
|
|
244
|
+
throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function esAlg(key) {
|
|
248
|
+
switch (key.algorithm.namedCurve) {
|
|
249
|
+
case "P-256":
|
|
250
|
+
return "ES256";
|
|
251
|
+
case "P-384":
|
|
252
|
+
return "ES384";
|
|
253
|
+
case "P-521":
|
|
254
|
+
return "ES512";
|
|
255
|
+
default:
|
|
256
|
+
throw new UnsupportedOperationError("unsupported EcKeyAlgorithm namedCurve");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function keyToJws(key) {
|
|
260
|
+
switch (key.algorithm.name) {
|
|
261
|
+
case "RSA-PSS":
|
|
262
|
+
return psAlg(key);
|
|
263
|
+
case "RSASSA-PKCS1-v1_5":
|
|
264
|
+
return rsAlg(key);
|
|
265
|
+
case "ECDSA":
|
|
266
|
+
return esAlg(key);
|
|
267
|
+
case "Ed25519":
|
|
268
|
+
case "Ed448":
|
|
269
|
+
return "EdDSA";
|
|
270
|
+
default:
|
|
271
|
+
throw new UnsupportedOperationError("unsupported CryptoKey algorithm name");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function getClockSkew(client) {
|
|
275
|
+
const skew = client?.[clockSkew];
|
|
276
|
+
return typeof skew === "number" && Number.isFinite(skew) ? skew : 0;
|
|
277
|
+
}
|
|
278
|
+
function getClockTolerance(client) {
|
|
279
|
+
const tolerance = client?.[clockTolerance];
|
|
280
|
+
return typeof tolerance === "number" && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1 ? tolerance : 30;
|
|
281
|
+
}
|
|
282
|
+
function epochTime() {
|
|
283
|
+
return Math.floor(Date.now() / 1e3);
|
|
284
|
+
}
|
|
285
|
+
function clientAssertion(as, client) {
|
|
286
|
+
const now = epochTime() + getClockSkew(client);
|
|
287
|
+
return {
|
|
288
|
+
jti: randomBytes(),
|
|
289
|
+
aud: [as.issuer, as.token_endpoint],
|
|
290
|
+
exp: now + 60,
|
|
291
|
+
iat: now,
|
|
292
|
+
nbf: now,
|
|
293
|
+
iss: client.client_id,
|
|
294
|
+
sub: client.client_id
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
async function privateKeyJwt(as, client, key, kid) {
|
|
298
|
+
return jwt({
|
|
299
|
+
alg: keyToJws(key),
|
|
300
|
+
kid
|
|
301
|
+
}, clientAssertion(as, client), key);
|
|
302
|
+
}
|
|
303
|
+
function assertAs(as) {
|
|
304
|
+
if (typeof as !== "object" || as === null) {
|
|
305
|
+
throw new TypeError('"as" must be an object');
|
|
306
|
+
}
|
|
307
|
+
if (!validateString(as.issuer)) {
|
|
308
|
+
throw new TypeError('"as.issuer" property must be a non-empty string');
|
|
309
|
+
}
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
function assertClient(client) {
|
|
313
|
+
if (typeof client !== "object" || client === null) {
|
|
314
|
+
throw new TypeError('"client" must be an object');
|
|
315
|
+
}
|
|
316
|
+
if (!validateString(client.client_id)) {
|
|
317
|
+
throw new TypeError('"client.client_id" property must be a non-empty string');
|
|
318
|
+
}
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
function assertClientSecret(clientSecret) {
|
|
322
|
+
if (!validateString(clientSecret)) {
|
|
323
|
+
throw new TypeError('"client.client_secret" property must be a non-empty string');
|
|
324
|
+
}
|
|
325
|
+
return clientSecret;
|
|
326
|
+
}
|
|
327
|
+
function assertNoClientPrivateKey(clientAuthMethod, clientPrivateKey) {
|
|
328
|
+
if (clientPrivateKey !== void 0) {
|
|
329
|
+
throw new TypeError(`"options.clientPrivateKey" property must not be provided when ${clientAuthMethod} client authentication method is used.`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function assertNoClientSecret(clientAuthMethod, clientSecret) {
|
|
333
|
+
if (clientSecret !== void 0) {
|
|
334
|
+
throw new TypeError(`"client.client_secret" property must not be provided when ${clientAuthMethod} client authentication method is used.`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async function clientAuthentication(as, client, body, headers, clientPrivateKey) {
|
|
338
|
+
body.delete("client_secret");
|
|
339
|
+
body.delete("client_assertion_type");
|
|
340
|
+
body.delete("client_assertion");
|
|
341
|
+
switch (client.token_endpoint_auth_method) {
|
|
342
|
+
case void 0:
|
|
343
|
+
case "client_secret_basic": {
|
|
344
|
+
assertNoClientPrivateKey("client_secret_basic", clientPrivateKey);
|
|
345
|
+
headers.set("authorization", clientSecretBasic(client.client_id, assertClientSecret(client.client_secret)));
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
case "client_secret_post": {
|
|
349
|
+
assertNoClientPrivateKey("client_secret_post", clientPrivateKey);
|
|
350
|
+
body.set("client_id", client.client_id);
|
|
351
|
+
body.set("client_secret", assertClientSecret(client.client_secret));
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
case "private_key_jwt": {
|
|
355
|
+
assertNoClientSecret("private_key_jwt", client.client_secret);
|
|
356
|
+
if (clientPrivateKey === void 0) {
|
|
357
|
+
throw new TypeError('"options.clientPrivateKey" must be provided when "client.token_endpoint_auth_method" is "private_key_jwt"');
|
|
358
|
+
}
|
|
359
|
+
const { key, kid } = getKeyAndKid(clientPrivateKey);
|
|
360
|
+
if (!isPrivateKey(key)) {
|
|
361
|
+
throw new TypeError('"options.clientPrivateKey.key" must be a private CryptoKey');
|
|
362
|
+
}
|
|
363
|
+
body.set("client_id", client.client_id);
|
|
364
|
+
body.set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
|
|
365
|
+
body.set("client_assertion", await privateKeyJwt(as, client, key, kid));
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
case "tls_client_auth":
|
|
369
|
+
case "self_signed_tls_client_auth":
|
|
370
|
+
case "none": {
|
|
371
|
+
assertNoClientSecret(client.token_endpoint_auth_method, client.client_secret);
|
|
372
|
+
assertNoClientPrivateKey(client.token_endpoint_auth_method, clientPrivateKey);
|
|
373
|
+
body.set("client_id", client.client_id);
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
default:
|
|
377
|
+
throw new UnsupportedOperationError("unsupported client token_endpoint_auth_method");
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
async function jwt(header, claimsSet, key) {
|
|
381
|
+
if (!key.usages.includes("sign")) {
|
|
382
|
+
throw new TypeError('CryptoKey instances used for signing assertions must include "sign" in their "usages"');
|
|
383
|
+
}
|
|
384
|
+
const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(claimsSet)))}`;
|
|
385
|
+
const signature = b64u(await crypto.subtle.sign(keyToSubtle(key), key, buf(input)));
|
|
386
|
+
return `${input}.${signature}`;
|
|
387
|
+
}
|
|
388
|
+
async function dpopProofJwt(headers, options, url, htm, clockSkew2, accessToken) {
|
|
389
|
+
const { privateKey, publicKey, nonce = dpopNonces.get(url.origin) } = options;
|
|
390
|
+
if (!isPrivateKey(privateKey)) {
|
|
391
|
+
throw new TypeError('"DPoP.privateKey" must be a private CryptoKey');
|
|
392
|
+
}
|
|
393
|
+
if (!isPublicKey(publicKey)) {
|
|
394
|
+
throw new TypeError('"DPoP.publicKey" must be a public CryptoKey');
|
|
395
|
+
}
|
|
396
|
+
if (nonce !== void 0 && !validateString(nonce)) {
|
|
397
|
+
throw new TypeError('"DPoP.nonce" must be a non-empty string or undefined');
|
|
398
|
+
}
|
|
399
|
+
if (!publicKey.extractable) {
|
|
400
|
+
throw new TypeError('"DPoP.publicKey.extractable" must be true');
|
|
401
|
+
}
|
|
402
|
+
const now = epochTime() + clockSkew2;
|
|
403
|
+
const proof = await jwt({
|
|
404
|
+
alg: keyToJws(privateKey),
|
|
405
|
+
typ: "dpop+jwt",
|
|
406
|
+
jwk: await publicJwk(publicKey)
|
|
407
|
+
}, {
|
|
408
|
+
iat: now,
|
|
409
|
+
jti: randomBytes(),
|
|
410
|
+
htm,
|
|
411
|
+
nonce,
|
|
412
|
+
htu: `${url.origin}${url.pathname}`,
|
|
413
|
+
ath: accessToken ? b64u(await crypto.subtle.digest("SHA-256", buf(accessToken))) : void 0
|
|
414
|
+
}, privateKey);
|
|
415
|
+
headers.set("dpop", proof);
|
|
416
|
+
}
|
|
417
|
+
var jwkCache;
|
|
418
|
+
async function getSetPublicJwkCache(key) {
|
|
419
|
+
const { kty, e, n, x, y, crv } = await crypto.subtle.exportKey("jwk", key);
|
|
420
|
+
const jwk = { kty, e, n, x, y, crv };
|
|
421
|
+
jwkCache.set(key, jwk);
|
|
422
|
+
return jwk;
|
|
423
|
+
}
|
|
424
|
+
async function publicJwk(key) {
|
|
425
|
+
jwkCache || (jwkCache = /* @__PURE__ */ new WeakMap());
|
|
426
|
+
return jwkCache.get(key) || getSetPublicJwkCache(key);
|
|
427
|
+
}
|
|
428
|
+
function validateEndpoint(value, endpoint, options) {
|
|
429
|
+
if (typeof value !== "string") {
|
|
430
|
+
if (options?.[useMtlsAlias]) {
|
|
431
|
+
throw new TypeError(`"as.mtls_endpoint_aliases.${endpoint}" must be a string`);
|
|
432
|
+
}
|
|
433
|
+
throw new TypeError(`"as.${endpoint}" must be a string`);
|
|
434
|
+
}
|
|
435
|
+
return new URL(value);
|
|
436
|
+
}
|
|
437
|
+
function resolveEndpoint(as, endpoint, options) {
|
|
438
|
+
if (options?.[useMtlsAlias] && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) {
|
|
439
|
+
return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, options);
|
|
440
|
+
}
|
|
441
|
+
return validateEndpoint(as[endpoint], endpoint);
|
|
442
|
+
}
|
|
443
|
+
function isOAuth2Error(input) {
|
|
444
|
+
const value = input;
|
|
445
|
+
if (typeof value !== "object" || Array.isArray(value) || value === null) {
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
return value.error !== void 0;
|
|
449
|
+
}
|
|
450
|
+
var skipSubjectCheck = Symbol();
|
|
451
|
+
async function authenticatedRequest(as, client, method, url, body, headers, options) {
|
|
452
|
+
await clientAuthentication(as, client, body, headers, options?.clientPrivateKey);
|
|
453
|
+
headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8");
|
|
454
|
+
return (options?.[customFetch] || fetch)(url.href, {
|
|
455
|
+
body,
|
|
456
|
+
headers: Object.fromEntries(headers.entries()),
|
|
457
|
+
method,
|
|
458
|
+
redirect: "manual",
|
|
459
|
+
signal: options?.signal ? signal(options.signal) : null
|
|
460
|
+
}).then(processDpopNonce);
|
|
461
|
+
}
|
|
462
|
+
async function tokenEndpointRequest(as, client, grantType, parameters, options) {
|
|
463
|
+
const url = resolveEndpoint(as, "token_endpoint", options);
|
|
464
|
+
parameters.set("grant_type", grantType);
|
|
465
|
+
const headers = prepareHeaders(options?.headers);
|
|
466
|
+
headers.set("accept", "application/json");
|
|
467
|
+
if (options?.DPoP !== void 0) {
|
|
468
|
+
await dpopProofJwt(headers, options.DPoP, url, "POST", getClockSkew(client));
|
|
469
|
+
}
|
|
470
|
+
return authenticatedRequest(as, client, "POST", url, parameters, headers, options);
|
|
471
|
+
}
|
|
472
|
+
async function refreshTokenGrantRequest(as, client, refreshToken, options) {
|
|
473
|
+
assertAs(as);
|
|
474
|
+
assertClient(client);
|
|
475
|
+
if (!validateString(refreshToken)) {
|
|
476
|
+
throw new TypeError('"refreshToken" must be a non-empty string');
|
|
477
|
+
}
|
|
478
|
+
const parameters = new URLSearchParams(options?.additionalParameters);
|
|
479
|
+
parameters.set("refresh_token", refreshToken);
|
|
480
|
+
return tokenEndpointRequest(as, client, "refresh_token", parameters, options);
|
|
481
|
+
}
|
|
482
|
+
var idTokenClaims = /* @__PURE__ */ new WeakMap();
|
|
483
|
+
async function processGenericAccessTokenResponse(as, client, response, ignoreIdToken = false, ignoreRefreshToken = false) {
|
|
484
|
+
assertAs(as);
|
|
485
|
+
assertClient(client);
|
|
486
|
+
if (!looseInstanceOf(response, Response)) {
|
|
487
|
+
throw new TypeError('"response" must be an instance of Response');
|
|
488
|
+
}
|
|
489
|
+
if (response.status !== 200) {
|
|
490
|
+
let err;
|
|
491
|
+
if (err = await handleOAuthBodyError(response)) {
|
|
492
|
+
return err;
|
|
493
|
+
}
|
|
494
|
+
throw new OPE('"response" is not a conform Token Endpoint response');
|
|
495
|
+
}
|
|
496
|
+
assertReadableResponse(response);
|
|
497
|
+
let json;
|
|
498
|
+
try {
|
|
499
|
+
json = await response.json();
|
|
500
|
+
} catch (cause) {
|
|
501
|
+
throw new OPE('failed to parse "response" body as JSON', { cause });
|
|
502
|
+
}
|
|
503
|
+
if (!isJsonObject(json)) {
|
|
504
|
+
throw new OPE('"response" body must be a top level object');
|
|
505
|
+
}
|
|
506
|
+
if (!validateString(json.access_token)) {
|
|
507
|
+
throw new OPE('"response" body "access_token" property must be a non-empty string');
|
|
508
|
+
}
|
|
509
|
+
if (!validateString(json.token_type)) {
|
|
510
|
+
throw new OPE('"response" body "token_type" property must be a non-empty string');
|
|
511
|
+
}
|
|
512
|
+
json.token_type = json.token_type.toLowerCase();
|
|
513
|
+
if (json.token_type !== "dpop" && json.token_type !== "bearer") {
|
|
514
|
+
throw new UnsupportedOperationError("unsupported `token_type` value");
|
|
515
|
+
}
|
|
516
|
+
if (json.expires_in !== void 0 && (typeof json.expires_in !== "number" || json.expires_in <= 0)) {
|
|
517
|
+
throw new OPE('"response" body "expires_in" property must be a positive number');
|
|
518
|
+
}
|
|
519
|
+
if (!ignoreRefreshToken && json.refresh_token !== void 0 && !validateString(json.refresh_token)) {
|
|
520
|
+
throw new OPE('"response" body "refresh_token" property must be a non-empty string');
|
|
521
|
+
}
|
|
522
|
+
if (json.scope !== void 0 && typeof json.scope !== "string") {
|
|
523
|
+
throw new OPE('"response" body "scope" property must be a string');
|
|
524
|
+
}
|
|
525
|
+
if (!ignoreIdToken) {
|
|
526
|
+
if (json.id_token !== void 0 && !validateString(json.id_token)) {
|
|
527
|
+
throw new OPE('"response" body "id_token" property must be a non-empty string');
|
|
528
|
+
}
|
|
529
|
+
if (json.id_token) {
|
|
530
|
+
const { claims } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(void 0, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported), noSignatureCheck, getClockSkew(client), getClockTolerance(client)).then(validatePresence.bind(void 0, ["aud", "exp", "iat", "iss", "sub"])).then(validateIssuer.bind(void 0, as.issuer)).then(validateAudience.bind(void 0, client.client_id));
|
|
531
|
+
if (Array.isArray(claims.aud) && claims.aud.length !== 1 && claims.azp !== client.client_id) {
|
|
532
|
+
throw new OPE('unexpected ID Token "azp" (authorized party) claim value');
|
|
533
|
+
}
|
|
534
|
+
if (client.require_auth_time && typeof claims.auth_time !== "number") {
|
|
535
|
+
throw new OPE('unexpected ID Token "auth_time" (authentication time) claim value');
|
|
536
|
+
}
|
|
537
|
+
idTokenClaims.set(json, claims);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return json;
|
|
541
|
+
}
|
|
542
|
+
async function processRefreshTokenResponse(as, client, response) {
|
|
543
|
+
return processGenericAccessTokenResponse(as, client, response);
|
|
544
|
+
}
|
|
545
|
+
function validateAudience(expected, result) {
|
|
546
|
+
if (Array.isArray(result.claims.aud)) {
|
|
547
|
+
if (!result.claims.aud.includes(expected)) {
|
|
548
|
+
throw new OPE('unexpected JWT "aud" (audience) claim value');
|
|
549
|
+
}
|
|
550
|
+
} else if (result.claims.aud !== expected) {
|
|
551
|
+
throw new OPE('unexpected JWT "aud" (audience) claim value');
|
|
552
|
+
}
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
555
|
+
function validateIssuer(expected, result) {
|
|
556
|
+
if (result.claims.iss !== expected) {
|
|
557
|
+
throw new OPE('unexpected JWT "iss" (issuer) claim value');
|
|
558
|
+
}
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
var branded = /* @__PURE__ */ new WeakSet();
|
|
562
|
+
function brand(searchParams) {
|
|
563
|
+
branded.add(searchParams);
|
|
564
|
+
return searchParams;
|
|
565
|
+
}
|
|
566
|
+
async function authorizationCodeGrantRequest(as, client, callbackParameters, redirectUri, codeVerifier, options) {
|
|
567
|
+
assertAs(as);
|
|
568
|
+
assertClient(client);
|
|
569
|
+
if (!branded.has(callbackParameters)) {
|
|
570
|
+
throw new TypeError('"callbackParameters" must be an instance of URLSearchParams obtained from "validateAuthResponse()", or "validateJwtAuthResponse()');
|
|
571
|
+
}
|
|
572
|
+
if (!validateString(redirectUri)) {
|
|
573
|
+
throw new TypeError('"redirectUri" must be a non-empty string');
|
|
574
|
+
}
|
|
575
|
+
if (!validateString(codeVerifier)) {
|
|
576
|
+
throw new TypeError('"codeVerifier" must be a non-empty string');
|
|
577
|
+
}
|
|
578
|
+
const code = getURLSearchParameter(callbackParameters, "code");
|
|
579
|
+
if (!code) {
|
|
580
|
+
throw new OPE('no authorization code in "callbackParameters"');
|
|
581
|
+
}
|
|
582
|
+
const parameters = new URLSearchParams(options?.additionalParameters);
|
|
583
|
+
parameters.set("redirect_uri", redirectUri);
|
|
584
|
+
parameters.set("code_verifier", codeVerifier);
|
|
585
|
+
parameters.set("code", code);
|
|
586
|
+
return tokenEndpointRequest(as, client, "authorization_code", parameters, options);
|
|
587
|
+
}
|
|
588
|
+
var jwtClaimNames = {
|
|
589
|
+
aud: "audience",
|
|
590
|
+
c_hash: "code hash",
|
|
591
|
+
client_id: "client id",
|
|
592
|
+
exp: "expiration time",
|
|
593
|
+
iat: "issued at",
|
|
594
|
+
iss: "issuer",
|
|
595
|
+
jti: "jwt id",
|
|
596
|
+
nonce: "nonce",
|
|
597
|
+
s_hash: "state hash",
|
|
598
|
+
sub: "subject",
|
|
599
|
+
ath: "access token hash",
|
|
600
|
+
htm: "http method",
|
|
601
|
+
htu: "http uri",
|
|
602
|
+
cnf: "confirmation"
|
|
603
|
+
};
|
|
604
|
+
function validatePresence(required, result) {
|
|
605
|
+
for (const claim of required) {
|
|
606
|
+
if (result.claims[claim] === void 0) {
|
|
607
|
+
throw new OPE(`JWT "${claim}" (${jwtClaimNames[claim]}) claim missing`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return result;
|
|
611
|
+
}
|
|
612
|
+
var expectNoNonce = Symbol();
|
|
613
|
+
var skipAuthTimeCheck = Symbol();
|
|
614
|
+
async function processAuthorizationCodeOAuth2Response(as, client, response) {
|
|
615
|
+
const result = await processGenericAccessTokenResponse(as, client, response, true);
|
|
616
|
+
if (isOAuth2Error(result)) {
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
if (result.id_token !== void 0) {
|
|
620
|
+
if (typeof result.id_token === "string" && result.id_token.length) {
|
|
621
|
+
throw new OPE("Unexpected ID Token returned, use processAuthorizationCodeOpenIDResponse() for OpenID Connect callback processing");
|
|
622
|
+
}
|
|
623
|
+
delete result.id_token;
|
|
624
|
+
}
|
|
625
|
+
return result;
|
|
626
|
+
}
|
|
627
|
+
function assertReadableResponse(response) {
|
|
628
|
+
if (response.bodyUsed) {
|
|
629
|
+
throw new TypeError('"response" body has been used already');
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
async function handleOAuthBodyError(response) {
|
|
633
|
+
if (response.status > 399 && response.status < 500) {
|
|
634
|
+
assertReadableResponse(response);
|
|
635
|
+
try {
|
|
636
|
+
const json = await response.json();
|
|
637
|
+
if (isJsonObject(json) && typeof json.error === "string" && json.error.length) {
|
|
638
|
+
if (json.error_description !== void 0 && typeof json.error_description !== "string") {
|
|
639
|
+
delete json.error_description;
|
|
640
|
+
}
|
|
641
|
+
if (json.error_uri !== void 0 && typeof json.error_uri !== "string") {
|
|
642
|
+
delete json.error_uri;
|
|
643
|
+
}
|
|
644
|
+
if (json.algs !== void 0 && typeof json.algs !== "string") {
|
|
645
|
+
delete json.algs;
|
|
646
|
+
}
|
|
647
|
+
if (json.scope !== void 0 && typeof json.scope !== "string") {
|
|
648
|
+
delete json.scope;
|
|
649
|
+
}
|
|
650
|
+
return json;
|
|
651
|
+
}
|
|
652
|
+
} catch {
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return void 0;
|
|
656
|
+
}
|
|
657
|
+
function checkRsaKeyAlgorithm(algorithm) {
|
|
658
|
+
if (typeof algorithm.modulusLength !== "number" || algorithm.modulusLength < 2048) {
|
|
659
|
+
throw new OPE(`${algorithm.name} modulusLength must be at least 2048 bits`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function ecdsaHashName(namedCurve) {
|
|
663
|
+
switch (namedCurve) {
|
|
664
|
+
case "P-256":
|
|
665
|
+
return "SHA-256";
|
|
666
|
+
case "P-384":
|
|
667
|
+
return "SHA-384";
|
|
668
|
+
case "P-521":
|
|
669
|
+
return "SHA-512";
|
|
670
|
+
default:
|
|
671
|
+
throw new UnsupportedOperationError();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
function keyToSubtle(key) {
|
|
675
|
+
switch (key.algorithm.name) {
|
|
676
|
+
case "ECDSA":
|
|
677
|
+
return {
|
|
678
|
+
name: key.algorithm.name,
|
|
679
|
+
hash: ecdsaHashName(key.algorithm.namedCurve)
|
|
680
|
+
};
|
|
681
|
+
case "RSA-PSS": {
|
|
682
|
+
checkRsaKeyAlgorithm(key.algorithm);
|
|
683
|
+
switch (key.algorithm.hash.name) {
|
|
684
|
+
case "SHA-256":
|
|
685
|
+
case "SHA-384":
|
|
686
|
+
case "SHA-512":
|
|
687
|
+
return {
|
|
688
|
+
name: key.algorithm.name,
|
|
689
|
+
saltLength: parseInt(key.algorithm.hash.name.slice(-3), 10) >> 3
|
|
690
|
+
};
|
|
691
|
+
default:
|
|
692
|
+
throw new UnsupportedOperationError();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
case "RSASSA-PKCS1-v1_5":
|
|
696
|
+
checkRsaKeyAlgorithm(key.algorithm);
|
|
697
|
+
return key.algorithm.name;
|
|
698
|
+
case "Ed448":
|
|
699
|
+
case "Ed25519":
|
|
700
|
+
return key.algorithm.name;
|
|
701
|
+
}
|
|
702
|
+
throw new UnsupportedOperationError();
|
|
703
|
+
}
|
|
704
|
+
var noSignatureCheck = Symbol();
|
|
705
|
+
async function validateJwt(jws, checkAlg, getKey, clockSkew2, clockTolerance2) {
|
|
706
|
+
const { 0: protectedHeader, 1: payload, 2: encodedSignature, length } = jws.split(".");
|
|
707
|
+
if (length === 5) {
|
|
708
|
+
throw new UnsupportedOperationError("JWE structure JWTs are not supported");
|
|
709
|
+
}
|
|
710
|
+
if (length !== 3) {
|
|
711
|
+
throw new OPE("Invalid JWT");
|
|
712
|
+
}
|
|
713
|
+
let header;
|
|
714
|
+
try {
|
|
715
|
+
header = JSON.parse(buf(b64u(protectedHeader)));
|
|
716
|
+
} catch (cause) {
|
|
717
|
+
throw new OPE("failed to parse JWT Header body as base64url encoded JSON", { cause });
|
|
718
|
+
}
|
|
719
|
+
if (!isJsonObject(header)) {
|
|
720
|
+
throw new OPE("JWT Header must be a top level object");
|
|
721
|
+
}
|
|
722
|
+
checkAlg(header);
|
|
723
|
+
if (header.crit !== void 0) {
|
|
724
|
+
throw new OPE('unexpected JWT "crit" header parameter');
|
|
725
|
+
}
|
|
726
|
+
const signature = b64u(encodedSignature);
|
|
727
|
+
let key;
|
|
728
|
+
if (getKey !== noSignatureCheck) {
|
|
729
|
+
key = await getKey(header);
|
|
730
|
+
const input = `${protectedHeader}.${payload}`;
|
|
731
|
+
const verified = await crypto.subtle.verify(keyToSubtle(key), key, signature, buf(input));
|
|
732
|
+
if (!verified) {
|
|
733
|
+
throw new OPE("JWT signature verification failed");
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
let claims;
|
|
737
|
+
try {
|
|
738
|
+
claims = JSON.parse(buf(b64u(payload)));
|
|
739
|
+
} catch (cause) {
|
|
740
|
+
throw new OPE("failed to parse JWT Payload body as base64url encoded JSON", { cause });
|
|
741
|
+
}
|
|
742
|
+
if (!isJsonObject(claims)) {
|
|
743
|
+
throw new OPE("JWT Payload must be a top level object");
|
|
744
|
+
}
|
|
745
|
+
const now = epochTime() + clockSkew2;
|
|
746
|
+
if (claims.exp !== void 0) {
|
|
747
|
+
if (typeof claims.exp !== "number") {
|
|
748
|
+
throw new OPE('unexpected JWT "exp" (expiration time) claim type');
|
|
749
|
+
}
|
|
750
|
+
if (claims.exp <= now - clockTolerance2) {
|
|
751
|
+
throw new OPE('unexpected JWT "exp" (expiration time) claim value, timestamp is <= now()');
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
if (claims.iat !== void 0) {
|
|
755
|
+
if (typeof claims.iat !== "number") {
|
|
756
|
+
throw new OPE('unexpected JWT "iat" (issued at) claim type');
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (claims.iss !== void 0) {
|
|
760
|
+
if (typeof claims.iss !== "string") {
|
|
761
|
+
throw new OPE('unexpected JWT "iss" (issuer) claim type');
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (claims.nbf !== void 0) {
|
|
765
|
+
if (typeof claims.nbf !== "number") {
|
|
766
|
+
throw new OPE('unexpected JWT "nbf" (not before) claim type');
|
|
767
|
+
}
|
|
768
|
+
if (claims.nbf > now + clockTolerance2) {
|
|
769
|
+
throw new OPE('unexpected JWT "nbf" (not before) claim value, timestamp is > now()');
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (claims.aud !== void 0) {
|
|
773
|
+
if (typeof claims.aud !== "string" && !Array.isArray(claims.aud)) {
|
|
774
|
+
throw new OPE('unexpected JWT "aud" (audience) claim type');
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return { header, claims, signature, key };
|
|
778
|
+
}
|
|
779
|
+
function checkSigningAlgorithm(client, issuer, header) {
|
|
780
|
+
if (client !== void 0) {
|
|
781
|
+
if (header.alg !== client) {
|
|
782
|
+
throw new OPE('unexpected JWT "alg" header parameter');
|
|
783
|
+
}
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (Array.isArray(issuer)) {
|
|
787
|
+
if (!issuer.includes(header.alg)) {
|
|
788
|
+
throw new OPE('unexpected JWT "alg" header parameter');
|
|
789
|
+
}
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (header.alg !== "RS256") {
|
|
793
|
+
throw new OPE('unexpected JWT "alg" header parameter');
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function getURLSearchParameter(parameters, name) {
|
|
797
|
+
const { 0: value, length } = parameters.getAll(name);
|
|
798
|
+
if (length > 1) {
|
|
799
|
+
throw new OPE(`"${name}" parameter must be provided only once`);
|
|
800
|
+
}
|
|
801
|
+
return value;
|
|
802
|
+
}
|
|
803
|
+
var skipStateCheck = Symbol();
|
|
804
|
+
var expectNoState = Symbol();
|
|
805
|
+
function validateAuthResponse(as, client, parameters, expectedState) {
|
|
806
|
+
assertAs(as);
|
|
807
|
+
assertClient(client);
|
|
808
|
+
if (parameters instanceof URL) {
|
|
809
|
+
parameters = parameters.searchParams;
|
|
810
|
+
}
|
|
811
|
+
if (!(parameters instanceof URLSearchParams)) {
|
|
812
|
+
throw new TypeError('"parameters" must be an instance of URLSearchParams, or URL');
|
|
813
|
+
}
|
|
814
|
+
if (getURLSearchParameter(parameters, "response")) {
|
|
815
|
+
throw new OPE('"parameters" contains a JARM response, use validateJwtAuthResponse() instead of validateAuthResponse()');
|
|
816
|
+
}
|
|
817
|
+
const iss = getURLSearchParameter(parameters, "iss");
|
|
818
|
+
const state = getURLSearchParameter(parameters, "state");
|
|
819
|
+
if (!iss && as.authorization_response_iss_parameter_supported) {
|
|
820
|
+
throw new OPE('response parameter "iss" (issuer) missing');
|
|
821
|
+
}
|
|
822
|
+
if (iss && iss !== as.issuer) {
|
|
823
|
+
throw new OPE('unexpected "iss" (issuer) response parameter value');
|
|
824
|
+
}
|
|
825
|
+
switch (expectedState) {
|
|
826
|
+
case void 0:
|
|
827
|
+
case expectNoState:
|
|
828
|
+
if (state !== void 0) {
|
|
829
|
+
throw new OPE('unexpected "state" response parameter encountered');
|
|
830
|
+
}
|
|
831
|
+
break;
|
|
832
|
+
case skipStateCheck:
|
|
833
|
+
break;
|
|
834
|
+
default:
|
|
835
|
+
if (!validateString(expectedState)) {
|
|
836
|
+
throw new OPE('"expectedState" must be a non-empty string');
|
|
837
|
+
}
|
|
838
|
+
if (state === void 0) {
|
|
839
|
+
throw new OPE('response parameter "state" missing');
|
|
840
|
+
}
|
|
841
|
+
if (state !== expectedState) {
|
|
842
|
+
throw new OPE('unexpected "state" response parameter value');
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
const error = getURLSearchParameter(parameters, "error");
|
|
846
|
+
if (error) {
|
|
847
|
+
return {
|
|
848
|
+
error,
|
|
849
|
+
error_description: getURLSearchParameter(parameters, "error_description"),
|
|
850
|
+
error_uri: getURLSearchParameter(parameters, "error_uri")
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
const id_token = getURLSearchParameter(parameters, "id_token");
|
|
854
|
+
const token = getURLSearchParameter(parameters, "token");
|
|
855
|
+
if (id_token !== void 0 || token !== void 0) {
|
|
856
|
+
throw new UnsupportedOperationError("implicit and hybrid flows are not supported");
|
|
857
|
+
}
|
|
858
|
+
return brand(new URLSearchParams(parameters));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// src/interface/clientInterface.ts
|
|
862
|
+
var import_known_errors = require("../known-errors");
|
|
863
|
+
var import_sessions = require("../sessions");
|
|
864
|
+
var import_crypto = require("../utils/crypto");
|
|
865
|
+
var import_errors = require("../utils/errors");
|
|
866
|
+
var import_globals = require("../utils/globals");
|
|
867
|
+
var import_http = require("../utils/http");
|
|
868
|
+
var import_objects = require("../utils/objects");
|
|
869
|
+
var import_promises = require("../utils/promises");
|
|
870
|
+
var import_results = require("../utils/results");
|
|
871
|
+
var import_strings = require("../utils/strings");
|
|
872
|
+
var StackClientInterface = class {
|
|
873
|
+
constructor(options) {
|
|
874
|
+
this.options = options;
|
|
875
|
+
}
|
|
876
|
+
get projectId() {
|
|
877
|
+
return this.options.projectId;
|
|
878
|
+
}
|
|
879
|
+
getApiUrl() {
|
|
880
|
+
return this.options.getBaseUrl() + "/api/v1";
|
|
881
|
+
}
|
|
882
|
+
async runNetworkDiagnostics(session, requestType) {
|
|
883
|
+
const tryRequest = async (cb) => {
|
|
884
|
+
try {
|
|
885
|
+
await cb();
|
|
886
|
+
return "OK";
|
|
887
|
+
} catch (e) {
|
|
888
|
+
return `${e}`;
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
const cfTrace = await tryRequest(async () => {
|
|
892
|
+
const res = await fetch("https://1.1.1.1/cdn-cgi/trace");
|
|
893
|
+
if (!res.ok) {
|
|
894
|
+
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
const apiRoot = session !== void 0 && requestType !== void 0 ? await tryRequest(async () => {
|
|
898
|
+
const res = await this.sendClientRequestInner("/", {}, session, requestType);
|
|
899
|
+
if (res.status === "error") {
|
|
900
|
+
throw res.error;
|
|
901
|
+
}
|
|
902
|
+
}) : "Not tested";
|
|
903
|
+
const baseUrlBackend = await tryRequest(async () => {
|
|
904
|
+
const res = await fetch(new URL("/health", this.getApiUrl()));
|
|
905
|
+
if (!res.ok) {
|
|
906
|
+
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
const prodDashboard = await tryRequest(async () => {
|
|
910
|
+
const res = await fetch("https://app.stack-auth.com/health");
|
|
911
|
+
if (!res.ok) {
|
|
912
|
+
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
const prodBackend = await tryRequest(async () => {
|
|
916
|
+
const res = await fetch("https://api.stack-auth.com/health");
|
|
917
|
+
if (!res.ok) {
|
|
918
|
+
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
return {
|
|
922
|
+
"navigator?.onLine": import_globals.globalVar.navigator?.onLine,
|
|
923
|
+
cfTrace,
|
|
924
|
+
apiRoot,
|
|
925
|
+
baseUrlBackend,
|
|
926
|
+
prodDashboard,
|
|
927
|
+
prodBackend
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
async _createNetworkError(cause, session, requestType) {
|
|
931
|
+
return new Error(import_strings.deindent`
|
|
74
932
|
Stack Auth is unable to connect to the server. Please check your internet connection and try again.
|
|
75
933
|
|
|
76
934
|
If the problem persists, please contact support and provide a screenshot of your entire browser console.
|
|
@@ -78,932 +936,1133 @@ export class StackClientInterface {
|
|
|
78
936
|
${cause}
|
|
79
937
|
|
|
80
938
|
${JSON.stringify(await this.runNetworkDiagnostics(session, requestType), null, 2)}
|
|
81
|
-
`, { cause
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
939
|
+
`, { cause });
|
|
940
|
+
}
|
|
941
|
+
async _networkRetry(cb, session, requestType) {
|
|
942
|
+
const retriedResult = await import_results.Result.retry(
|
|
943
|
+
cb,
|
|
944
|
+
5,
|
|
945
|
+
{ exponentialDelayBase: 1e3 }
|
|
946
|
+
);
|
|
947
|
+
if (retriedResult.status === "error") {
|
|
948
|
+
if (import_globals.globalVar.navigator && !import_globals.globalVar.navigator.onLine) {
|
|
949
|
+
throw new Error("Failed to send Stack network request. It seems like you are offline, please check your internet connection and try again. This is not an error with Stack Auth. (window.navigator.onLine is falsy)", { cause: retriedResult.error });
|
|
950
|
+
}
|
|
951
|
+
throw await this._createNetworkError(retriedResult.error, session, requestType);
|
|
952
|
+
}
|
|
953
|
+
return retriedResult.data;
|
|
954
|
+
}
|
|
955
|
+
async _networkRetryException(cb, session, requestType) {
|
|
956
|
+
return await this._networkRetry(async () => await import_results.Result.fromThrowingAsync(cb), session, requestType);
|
|
957
|
+
}
|
|
958
|
+
async fetchNewAccessToken(refreshToken) {
|
|
959
|
+
if (!("publishableClientKey" in this.options)) {
|
|
960
|
+
throw new Error("Admin session token is currently not supported for fetching new access token. Did you try to log in on a StackApp initiated with the admin session?");
|
|
961
|
+
}
|
|
962
|
+
const as = {
|
|
963
|
+
issuer: this.options.getBaseUrl(),
|
|
964
|
+
algorithm: "oauth2",
|
|
965
|
+
token_endpoint: this.getApiUrl() + "/auth/oauth/token"
|
|
966
|
+
};
|
|
967
|
+
const client = {
|
|
968
|
+
client_id: this.projectId,
|
|
969
|
+
client_secret: this.options.publishableClientKey,
|
|
970
|
+
token_endpoint_auth_method: "client_secret_post"
|
|
971
|
+
};
|
|
972
|
+
const rawResponse = await this._networkRetryException(
|
|
973
|
+
async () => await refreshTokenGrantRequest(
|
|
974
|
+
as,
|
|
975
|
+
client,
|
|
976
|
+
refreshToken.token
|
|
977
|
+
)
|
|
978
|
+
);
|
|
979
|
+
const response = await this._processResponse(rawResponse);
|
|
980
|
+
if (response.status === "error") {
|
|
981
|
+
const error = response.error;
|
|
982
|
+
if (error instanceof import_known_errors.KnownErrors.RefreshTokenError) {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
throw error;
|
|
986
|
+
}
|
|
987
|
+
if (!response.data.ok) {
|
|
988
|
+
const body = await response.data.text();
|
|
989
|
+
throw new Error(`Failed to send refresh token request: ${response.status} ${body}`);
|
|
990
|
+
}
|
|
991
|
+
const result = await processRefreshTokenResponse(as, client, response.data);
|
|
992
|
+
if (isOAuth2Error(result)) {
|
|
993
|
+
throw new import_errors.StackAssertionError("OAuth error", { result });
|
|
994
|
+
}
|
|
995
|
+
if (!result.access_token) {
|
|
996
|
+
throw new import_errors.StackAssertionError("Access token not found in token endpoint response, this is weird!");
|
|
997
|
+
}
|
|
998
|
+
return new import_sessions.AccessToken(result.access_token);
|
|
999
|
+
}
|
|
1000
|
+
async sendClientRequest(path, requestOptions, session, requestType = "client") {
|
|
1001
|
+
session ??= this.createSession({
|
|
1002
|
+
refreshToken: null
|
|
1003
|
+
});
|
|
1004
|
+
return await this._networkRetry(
|
|
1005
|
+
() => this.sendClientRequestInner(path, requestOptions, session, requestType),
|
|
1006
|
+
session,
|
|
1007
|
+
requestType
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
createSession(options) {
|
|
1011
|
+
const session = new import_sessions.InternalSession({
|
|
1012
|
+
refreshAccessTokenCallback: async (refreshToken) => await this.fetchNewAccessToken(refreshToken),
|
|
1013
|
+
...options
|
|
1014
|
+
});
|
|
1015
|
+
return session;
|
|
1016
|
+
}
|
|
1017
|
+
async sendClientRequestAndCatchKnownError(path, requestOptions, tokenStoreOrNull, errorsToCatch) {
|
|
1018
|
+
try {
|
|
1019
|
+
return import_results.Result.ok(await this.sendClientRequest(path, requestOptions, tokenStoreOrNull));
|
|
1020
|
+
} catch (e) {
|
|
1021
|
+
for (const errorType of errorsToCatch) {
|
|
1022
|
+
if (e instanceof errorType) {
|
|
1023
|
+
return import_results.Result.error(e);
|
|
91
1024
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
refreshToken: null,
|
|
138
|
-
});
|
|
139
|
-
return await this._networkRetry(() => this.sendClientRequestInner(path, requestOptions, session, requestType), session, requestType);
|
|
140
|
-
}
|
|
141
|
-
createSession(options) {
|
|
142
|
-
const session = new InternalSession({
|
|
143
|
-
refreshAccessTokenCallback: async (refreshToken) => await this.fetchNewAccessToken(refreshToken),
|
|
144
|
-
...options,
|
|
145
|
-
});
|
|
146
|
-
return session;
|
|
147
|
-
}
|
|
148
|
-
async sendClientRequestAndCatchKnownError(path, requestOptions, tokenStoreOrNull, errorsToCatch) {
|
|
149
|
-
try {
|
|
150
|
-
return Result.ok(await this.sendClientRequest(path, requestOptions, tokenStoreOrNull));
|
|
151
|
-
}
|
|
152
|
-
catch (e) {
|
|
153
|
-
for (const errorType of errorsToCatch) {
|
|
154
|
-
if (e instanceof errorType) {
|
|
155
|
-
return Result.error(e);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
throw e;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
async sendClientRequestInner(path, options, session, requestType) {
|
|
1025
|
+
}
|
|
1026
|
+
throw e;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
async sendClientRequestInner(path, options, session, requestType) {
|
|
1030
|
+
let tokenObj = await session.getOrFetchLikelyValidTokens(2e4);
|
|
1031
|
+
let adminSession = "projectOwnerSession" in this.options ? this.options.projectOwnerSession : null;
|
|
1032
|
+
let adminTokenObj = adminSession ? await adminSession.getOrFetchLikelyValidTokens(2e4) : null;
|
|
1033
|
+
await this.options.prepareRequest?.();
|
|
1034
|
+
let url = this.getApiUrl() + path;
|
|
1035
|
+
if (url.endsWith("/")) {
|
|
1036
|
+
url = url.slice(0, -1);
|
|
1037
|
+
}
|
|
1038
|
+
const params = {
|
|
1039
|
+
/**
|
|
1040
|
+
* This fetch may be cross-origin, in which case we don't want to send cookies of the
|
|
1041
|
+
* original origin (this is the default behavior of `credentials`).
|
|
1042
|
+
*
|
|
1043
|
+
* To help debugging, also omit cookies on same-origin, so we don't accidentally
|
|
1044
|
+
* implement reliance on cookies anywhere.
|
|
1045
|
+
*
|
|
1046
|
+
* However, Cloudflare Workers don't actually support `credentials`, so we only set it
|
|
1047
|
+
* if Cloudflare-exclusive globals are not detected. https://github.com/cloudflare/workers-sdk/issues/2514
|
|
1048
|
+
*/
|
|
1049
|
+
..."WebSocketPair" in import_globals.globalVar ? {} : {
|
|
1050
|
+
credentials: "omit"
|
|
1051
|
+
},
|
|
1052
|
+
...options,
|
|
1053
|
+
headers: {
|
|
1054
|
+
"X-Stack-Override-Error-Status": "true",
|
|
1055
|
+
"X-Stack-Project-Id": this.projectId,
|
|
1056
|
+
"X-Stack-Access-Type": requestType,
|
|
1057
|
+
"X-Stack-Client-Version": this.options.clientVersion,
|
|
1058
|
+
...tokenObj ? {
|
|
1059
|
+
"X-Stack-Access-Token": tokenObj.accessToken.token
|
|
1060
|
+
} : {},
|
|
1061
|
+
...tokenObj?.refreshToken ? {
|
|
1062
|
+
"X-Stack-Refresh-Token": tokenObj.refreshToken.token
|
|
1063
|
+
} : {},
|
|
1064
|
+
..."publishableClientKey" in this.options ? {
|
|
1065
|
+
"X-Stack-Publishable-Client-Key": this.options.publishableClientKey
|
|
1066
|
+
} : {},
|
|
1067
|
+
...adminTokenObj ? {
|
|
1068
|
+
"X-Stack-Admin-Access-Token": adminTokenObj.accessToken.token
|
|
1069
|
+
} : {},
|
|
162
1070
|
/**
|
|
163
|
-
*
|
|
1071
|
+
* Next.js until v15 would cache fetch requests by default, and forcefully disabling it was nearly impossible.
|
|
1072
|
+
*
|
|
1073
|
+
* This header is used to change the cache key and hence always disable it, because we do our own caching.
|
|
1074
|
+
*
|
|
1075
|
+
* When we drop support for Next.js <15, we may be able to remove this header, but please make sure that this is
|
|
1076
|
+
* the case (I haven't actually tested.)
|
|
164
1077
|
*/
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
...("WebSocketPair" in globalVar ? {} : {
|
|
186
|
-
credentials: "omit",
|
|
187
|
-
}),
|
|
188
|
-
...options,
|
|
189
|
-
headers: {
|
|
190
|
-
"X-Stack-Override-Error-Status": "true",
|
|
191
|
-
"X-Stack-Project-Id": this.projectId,
|
|
192
|
-
"X-Stack-Access-Type": requestType,
|
|
193
|
-
"X-Stack-Client-Version": this.options.clientVersion,
|
|
194
|
-
...(tokenObj ? {
|
|
195
|
-
"X-Stack-Access-Token": tokenObj.accessToken.token,
|
|
196
|
-
} : {}),
|
|
197
|
-
...(tokenObj?.refreshToken ? {
|
|
198
|
-
"X-Stack-Refresh-Token": tokenObj.refreshToken.token,
|
|
199
|
-
} : {}),
|
|
200
|
-
...('publishableClientKey' in this.options ? {
|
|
201
|
-
"X-Stack-Publishable-Client-Key": this.options.publishableClientKey,
|
|
202
|
-
} : {}),
|
|
203
|
-
...(adminTokenObj ? {
|
|
204
|
-
"X-Stack-Admin-Access-Token": adminTokenObj.accessToken.token,
|
|
205
|
-
} : {}),
|
|
206
|
-
/**
|
|
207
|
-
* Next.js until v15 would cache fetch requests by default, and forcefully disabling it was nearly impossible.
|
|
208
|
-
*
|
|
209
|
-
* This header is used to change the cache key and hence always disable it, because we do our own caching.
|
|
210
|
-
*
|
|
211
|
-
* When we drop support for Next.js <15, we may be able to remove this header, but please make sure that this is
|
|
212
|
-
* the case (I haven't actually tested.)
|
|
213
|
-
*/
|
|
214
|
-
"X-Stack-Random-Nonce": generateSecureRandomString(),
|
|
215
|
-
...this.options.extraRequestHeaders,
|
|
216
|
-
...options.headers,
|
|
217
|
-
},
|
|
218
|
-
/**
|
|
219
|
-
* Cloudflare Workers does not support cache, so don't pass it there
|
|
220
|
-
*/
|
|
221
|
-
...("WebSocketPair" in globalVar ? {} : {
|
|
222
|
-
cache: "no-store",
|
|
223
|
-
}),
|
|
224
|
-
};
|
|
225
|
-
let rawRes;
|
|
226
|
-
try {
|
|
227
|
-
rawRes = await fetch(url, params);
|
|
228
|
-
}
|
|
229
|
-
catch (e) {
|
|
230
|
-
if (e instanceof TypeError) {
|
|
231
|
-
// Likely to be a network error. Retry if the request is idempotent, throw network error otherwise.
|
|
232
|
-
if (HTTP_METHODS[(params.method ?? "GET")].idempotent) {
|
|
233
|
-
return Result.error(e);
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
throw await this._createNetworkError(e, session, requestType);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
throw e;
|
|
240
|
-
}
|
|
241
|
-
const processedRes = await this._processResponse(rawRes);
|
|
242
|
-
if (processedRes.status === "error") {
|
|
243
|
-
// If the access token is invalid, reset it and retry
|
|
244
|
-
if (processedRes.error instanceof KnownErrors.InvalidAccessToken) {
|
|
245
|
-
if (!tokenObj) {
|
|
246
|
-
throw new StackAssertionError("Received invalid access token, but session is not logged in", { tokenObj, processedRes });
|
|
247
|
-
}
|
|
248
|
-
session.markAccessTokenExpired(tokenObj.accessToken);
|
|
249
|
-
return Result.error(processedRes.error);
|
|
250
|
-
}
|
|
251
|
-
// Same for the admin access token
|
|
252
|
-
// TODO HACK: Some of the backend hasn't been ported to use the new error codes, so if we have project owner tokens we need to check for ApiKeyNotFound too. Once the migration to smartRouteHandlers is complete, we can check for InvalidAdminAccessToken only.
|
|
253
|
-
if (adminSession && (processedRes.error instanceof KnownErrors.InvalidAdminAccessToken || processedRes.error instanceof KnownErrors.ApiKeyNotFound)) {
|
|
254
|
-
if (!adminTokenObj) {
|
|
255
|
-
throw new StackAssertionError("Received invalid admin access token, but admin session is not logged in", { adminTokenObj, processedRes });
|
|
256
|
-
}
|
|
257
|
-
adminSession.markAccessTokenExpired(adminTokenObj.accessToken);
|
|
258
|
-
return Result.error(processedRes.error);
|
|
259
|
-
}
|
|
260
|
-
// Known errors are client side errors, so except for the ones above they should not be retried
|
|
261
|
-
// Hence, throw instead of returning an error
|
|
262
|
-
throw processedRes.error;
|
|
263
|
-
}
|
|
264
|
-
const res = Object.assign(processedRes.data, {
|
|
265
|
-
usedTokens: tokenObj,
|
|
266
|
-
});
|
|
267
|
-
if (res.ok) {
|
|
268
|
-
return Result.ok(res);
|
|
269
|
-
}
|
|
270
|
-
else if (res.status === 429) {
|
|
271
|
-
// Rate limited, so retry if we can
|
|
272
|
-
const retryAfter = res.headers.get("Retry-After");
|
|
273
|
-
if (retryAfter !== null) {
|
|
274
|
-
console.log(`Rate limited while sending request to ${url}. Will retry after ${retryAfter} seconds...`);
|
|
275
|
-
await wait(Number(retryAfter) * 1000);
|
|
276
|
-
return Result.error(new Error(`Rate limited, retrying after ${retryAfter} seconds`));
|
|
277
|
-
}
|
|
278
|
-
console.log(`Rate limited while sending request to ${url}, no retry-after header received. Retrying...`);
|
|
279
|
-
return Result.error(new Error("Rate limited, no retry-after header received"));
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
const error = await res.text();
|
|
283
|
-
const errorObj = new StackAssertionError(`Failed to send request to ${url}: ${res.status} ${error}`, { request: params, res, path });
|
|
284
|
-
if (res.status === 508 && error.includes("INFINITE_LOOP_DETECTED")) {
|
|
285
|
-
// Some Vercel deployments seem to have an odd infinite loop bug. In that case, retry.
|
|
286
|
-
// See: https://github.com/stack-auth/stack-auth/issues/319
|
|
287
|
-
return Result.error(errorObj);
|
|
288
|
-
}
|
|
289
|
-
// Do not retry, throw error instead of returning one
|
|
290
|
-
throw errorObj;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async _processResponse(rawRes) {
|
|
294
|
-
let res = rawRes;
|
|
295
|
-
if (rawRes.headers.has("x-stack-actual-status")) {
|
|
296
|
-
const actualStatus = Number(rawRes.headers.get("x-stack-actual-status"));
|
|
297
|
-
res = new Response(rawRes.body, {
|
|
298
|
-
status: actualStatus,
|
|
299
|
-
statusText: rawRes.statusText,
|
|
300
|
-
headers: rawRes.headers,
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
// Handle known errors
|
|
304
|
-
if (res.headers.has("x-stack-known-error")) {
|
|
305
|
-
const errorJson = await res.json();
|
|
306
|
-
if (res.headers.get("x-stack-known-error") !== errorJson.code) {
|
|
307
|
-
throw new StackAssertionError("Mismatch between x-stack-known-error header and error code in body; the server's response is invalid");
|
|
308
|
-
}
|
|
309
|
-
const error = KnownError.fromJson(errorJson);
|
|
310
|
-
return Result.error(error);
|
|
1078
|
+
"X-Stack-Random-Nonce": (0, import_crypto.generateSecureRandomString)(),
|
|
1079
|
+
...this.options.extraRequestHeaders,
|
|
1080
|
+
...options.headers
|
|
1081
|
+
},
|
|
1082
|
+
/**
|
|
1083
|
+
* Cloudflare Workers does not support cache, so don't pass it there
|
|
1084
|
+
*/
|
|
1085
|
+
..."WebSocketPair" in import_globals.globalVar ? {} : {
|
|
1086
|
+
cache: "no-store"
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
let rawRes;
|
|
1090
|
+
try {
|
|
1091
|
+
rawRes = await fetch(url, params);
|
|
1092
|
+
} catch (e) {
|
|
1093
|
+
if (e instanceof TypeError) {
|
|
1094
|
+
if (import_http.HTTP_METHODS[params.method ?? "GET"].idempotent) {
|
|
1095
|
+
return import_results.Result.error(e);
|
|
1096
|
+
} else {
|
|
1097
|
+
throw await this._createNetworkError(e, session, requestType);
|
|
311
1098
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
body: JSON.stringify(options),
|
|
321
|
-
}, null);
|
|
322
|
-
throw new StackAssertionError(await res.text());
|
|
323
|
-
}
|
|
324
|
-
async sendForgotPasswordEmail(email, callbackUrl) {
|
|
325
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/send-reset-code", {
|
|
326
|
-
method: "POST",
|
|
327
|
-
headers: {
|
|
328
|
-
"Content-Type": "application/json"
|
|
329
|
-
},
|
|
330
|
-
body: JSON.stringify({
|
|
331
|
-
email,
|
|
332
|
-
callback_url: callbackUrl,
|
|
333
|
-
}),
|
|
334
|
-
}, null, [KnownErrors.UserNotFound]);
|
|
335
|
-
if (res.status === "error") {
|
|
336
|
-
return Result.error(res.error);
|
|
1099
|
+
}
|
|
1100
|
+
throw e;
|
|
1101
|
+
}
|
|
1102
|
+
const processedRes = await this._processResponse(rawRes);
|
|
1103
|
+
if (processedRes.status === "error") {
|
|
1104
|
+
if (processedRes.error instanceof import_known_errors.KnownErrors.InvalidAccessToken) {
|
|
1105
|
+
if (!tokenObj) {
|
|
1106
|
+
throw new import_errors.StackAssertionError("Received invalid access token, but session is not logged in", { tokenObj, processedRes });
|
|
337
1107
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
method: "POST",
|
|
345
|
-
headers: {
|
|
346
|
-
"Content-Type": "application/json"
|
|
347
|
-
},
|
|
348
|
-
body: JSON.stringify({
|
|
349
|
-
email,
|
|
350
|
-
callback_url: callbackUrl,
|
|
351
|
-
}),
|
|
352
|
-
}, session, [KnownErrors.EmailAlreadyVerified]);
|
|
353
|
-
if (res.status === "error") {
|
|
354
|
-
return res.error;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
async sendMagicLinkEmail(email, callbackUrl) {
|
|
358
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/otp/send-sign-in-code", {
|
|
359
|
-
method: "POST",
|
|
360
|
-
headers: {
|
|
361
|
-
"Content-Type": "application/json"
|
|
362
|
-
},
|
|
363
|
-
body: JSON.stringify({
|
|
364
|
-
email,
|
|
365
|
-
callback_url: callbackUrl,
|
|
366
|
-
}),
|
|
367
|
-
}, null, [KnownErrors.RedirectUrlNotWhitelisted]);
|
|
368
|
-
if (res.status === "error") {
|
|
369
|
-
return Result.error(res.error);
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
return Result.ok(await res.data.json());
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
async resetPassword(options) {
|
|
376
|
-
const res = await this.sendClientRequestAndCatchKnownError("onlyVerifyCode" in options ? "/auth/password/reset/check-code" : "/auth/password/reset", {
|
|
377
|
-
method: "POST",
|
|
378
|
-
headers: {
|
|
379
|
-
"Content-Type": "application/json"
|
|
380
|
-
},
|
|
381
|
-
body: JSON.stringify({
|
|
382
|
-
code: options.code,
|
|
383
|
-
...("password" in options ? { password: options.password } : {}),
|
|
384
|
-
}),
|
|
385
|
-
}, null, [KnownErrors.VerificationCodeError]);
|
|
386
|
-
if (res.status === "error") {
|
|
387
|
-
return Result.error(res.error);
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
return Result.ok(undefined);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
async updatePassword(options, session) {
|
|
394
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/update", {
|
|
395
|
-
method: "POST",
|
|
396
|
-
headers: {
|
|
397
|
-
"Content-Type": "application/json"
|
|
398
|
-
},
|
|
399
|
-
body: JSON.stringify({
|
|
400
|
-
old_password: options.oldPassword,
|
|
401
|
-
new_password: options.newPassword,
|
|
402
|
-
}),
|
|
403
|
-
}, session, [KnownErrors.PasswordConfirmationMismatch, KnownErrors.PasswordRequirementsNotMet]);
|
|
404
|
-
if (res.status === "error") {
|
|
405
|
-
return res.error;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
async setPassword(options, session) {
|
|
409
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/set", {
|
|
410
|
-
method: "POST",
|
|
411
|
-
headers: {
|
|
412
|
-
"Content-Type": "application/json"
|
|
413
|
-
},
|
|
414
|
-
body: JSON.stringify(options),
|
|
415
|
-
}, session, [KnownErrors.PasswordRequirementsNotMet]);
|
|
416
|
-
if (res.status === "error") {
|
|
417
|
-
return res.error;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
async verifyPasswordResetCode(code) {
|
|
421
|
-
const res = await this.resetPassword({ code, onlyVerifyCode: true });
|
|
422
|
-
if (res.status === "error") {
|
|
423
|
-
return Result.error(res.error);
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
return Result.ok(undefined);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
async verifyEmail(code) {
|
|
430
|
-
const res = await this.sendClientRequestAndCatchKnownError("/contact-channels/verify", {
|
|
431
|
-
method: "POST",
|
|
432
|
-
headers: {
|
|
433
|
-
"Content-Type": "application/json"
|
|
434
|
-
},
|
|
435
|
-
body: JSON.stringify({
|
|
436
|
-
code,
|
|
437
|
-
}),
|
|
438
|
-
}, null, [KnownErrors.VerificationCodeError]);
|
|
439
|
-
if (res.status === "error") {
|
|
440
|
-
return Result.error(res.error);
|
|
1108
|
+
session.markAccessTokenExpired(tokenObj.accessToken);
|
|
1109
|
+
return import_results.Result.error(processedRes.error);
|
|
1110
|
+
}
|
|
1111
|
+
if (adminSession && (processedRes.error instanceof import_known_errors.KnownErrors.InvalidAdminAccessToken || processedRes.error instanceof import_known_errors.KnownErrors.ApiKeyNotFound)) {
|
|
1112
|
+
if (!adminTokenObj) {
|
|
1113
|
+
throw new import_errors.StackAssertionError("Received invalid admin access token, but admin session is not logged in", { adminTokenObj, processedRes });
|
|
441
1114
|
}
|
|
442
|
-
|
|
443
|
-
|
|
1115
|
+
adminSession.markAccessTokenExpired(adminTokenObj.accessToken);
|
|
1116
|
+
return import_results.Result.error(processedRes.error);
|
|
1117
|
+
}
|
|
1118
|
+
throw processedRes.error;
|
|
1119
|
+
}
|
|
1120
|
+
const res = Object.assign(processedRes.data, {
|
|
1121
|
+
usedTokens: tokenObj
|
|
1122
|
+
});
|
|
1123
|
+
if (res.ok) {
|
|
1124
|
+
return import_results.Result.ok(res);
|
|
1125
|
+
} else if (res.status === 429) {
|
|
1126
|
+
const retryAfter = res.headers.get("Retry-After");
|
|
1127
|
+
if (retryAfter !== null) {
|
|
1128
|
+
console.log(`Rate limited while sending request to ${url}. Will retry after ${retryAfter} seconds...`);
|
|
1129
|
+
await (0, import_promises.wait)(Number(retryAfter) * 1e3);
|
|
1130
|
+
return import_results.Result.error(new Error(`Rate limited, retrying after ${retryAfter} seconds`));
|
|
1131
|
+
}
|
|
1132
|
+
console.log(`Rate limited while sending request to ${url}, no retry-after header received. Retrying...`);
|
|
1133
|
+
return import_results.Result.error(new Error("Rate limited, no retry-after header received"));
|
|
1134
|
+
} else {
|
|
1135
|
+
const error = await res.text();
|
|
1136
|
+
const errorObj = new import_errors.StackAssertionError(`Failed to send request to ${url}: ${res.status} ${error}`, { request: params, res, path });
|
|
1137
|
+
if (res.status === 508 && error.includes("INFINITE_LOOP_DETECTED")) {
|
|
1138
|
+
return import_results.Result.error(errorObj);
|
|
1139
|
+
}
|
|
1140
|
+
throw errorObj;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
async _processResponse(rawRes) {
|
|
1144
|
+
let res = rawRes;
|
|
1145
|
+
if (rawRes.headers.has("x-stack-actual-status")) {
|
|
1146
|
+
const actualStatus = Number(rawRes.headers.get("x-stack-actual-status"));
|
|
1147
|
+
res = new Response(rawRes.body, {
|
|
1148
|
+
status: actualStatus,
|
|
1149
|
+
statusText: rawRes.statusText,
|
|
1150
|
+
headers: rawRes.headers
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
if (res.headers.has("x-stack-known-error")) {
|
|
1154
|
+
const errorJson = await res.json();
|
|
1155
|
+
if (res.headers.get("x-stack-known-error") !== errorJson.code) {
|
|
1156
|
+
throw new import_errors.StackAssertionError("Mismatch between x-stack-known-error header and error code in body; the server's response is invalid");
|
|
1157
|
+
}
|
|
1158
|
+
const error = import_known_errors.KnownError.fromJson(errorJson);
|
|
1159
|
+
return import_results.Result.error(error);
|
|
1160
|
+
}
|
|
1161
|
+
return import_results.Result.ok(res);
|
|
1162
|
+
}
|
|
1163
|
+
async checkFeatureSupport(options) {
|
|
1164
|
+
const res = await this.sendClientRequest("/check-feature-support", {
|
|
1165
|
+
method: "POST",
|
|
1166
|
+
headers: {
|
|
1167
|
+
"Content-Type": "application/json"
|
|
1168
|
+
},
|
|
1169
|
+
body: JSON.stringify(options)
|
|
1170
|
+
}, null);
|
|
1171
|
+
throw new import_errors.StackAssertionError(await res.text());
|
|
1172
|
+
}
|
|
1173
|
+
async sendForgotPasswordEmail(email, callbackUrl) {
|
|
1174
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1175
|
+
"/auth/password/send-reset-code",
|
|
1176
|
+
{
|
|
1177
|
+
method: "POST",
|
|
1178
|
+
headers: {
|
|
1179
|
+
"Content-Type": "application/json"
|
|
1180
|
+
},
|
|
1181
|
+
body: JSON.stringify({
|
|
1182
|
+
email,
|
|
1183
|
+
callback_url: callbackUrl
|
|
1184
|
+
})
|
|
1185
|
+
},
|
|
1186
|
+
null,
|
|
1187
|
+
[import_known_errors.KnownErrors.UserNotFound]
|
|
1188
|
+
);
|
|
1189
|
+
if (res.status === "error") {
|
|
1190
|
+
return import_results.Result.error(res.error);
|
|
1191
|
+
} else {
|
|
1192
|
+
return import_results.Result.ok(void 0);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
async sendVerificationEmail(email, callbackUrl, session) {
|
|
1196
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1197
|
+
"/contact-channels/send-verification-code",
|
|
1198
|
+
{
|
|
1199
|
+
method: "POST",
|
|
1200
|
+
headers: {
|
|
1201
|
+
"Content-Type": "application/json"
|
|
1202
|
+
},
|
|
1203
|
+
body: JSON.stringify({
|
|
1204
|
+
email,
|
|
1205
|
+
callback_url: callbackUrl
|
|
1206
|
+
})
|
|
1207
|
+
},
|
|
1208
|
+
session,
|
|
1209
|
+
[import_known_errors.KnownErrors.EmailAlreadyVerified]
|
|
1210
|
+
);
|
|
1211
|
+
if (res.status === "error") {
|
|
1212
|
+
return res.error;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
async sendMagicLinkEmail(email, callbackUrl) {
|
|
1216
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1217
|
+
"/auth/otp/send-sign-in-code",
|
|
1218
|
+
{
|
|
1219
|
+
method: "POST",
|
|
1220
|
+
headers: {
|
|
1221
|
+
"Content-Type": "application/json"
|
|
1222
|
+
},
|
|
1223
|
+
body: JSON.stringify({
|
|
1224
|
+
email,
|
|
1225
|
+
callback_url: callbackUrl
|
|
1226
|
+
})
|
|
1227
|
+
},
|
|
1228
|
+
null,
|
|
1229
|
+
[import_known_errors.KnownErrors.RedirectUrlNotWhitelisted]
|
|
1230
|
+
);
|
|
1231
|
+
if (res.status === "error") {
|
|
1232
|
+
return import_results.Result.error(res.error);
|
|
1233
|
+
} else {
|
|
1234
|
+
return import_results.Result.ok(await res.data.json());
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
async resetPassword(options) {
|
|
1238
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1239
|
+
"onlyVerifyCode" in options ? "/auth/password/reset/check-code" : "/auth/password/reset",
|
|
1240
|
+
{
|
|
1241
|
+
method: "POST",
|
|
1242
|
+
headers: {
|
|
1243
|
+
"Content-Type": "application/json"
|
|
1244
|
+
},
|
|
1245
|
+
body: JSON.stringify({
|
|
1246
|
+
code: options.code,
|
|
1247
|
+
..."password" in options ? { password: options.password } : {}
|
|
1248
|
+
})
|
|
1249
|
+
},
|
|
1250
|
+
null,
|
|
1251
|
+
[import_known_errors.KnownErrors.VerificationCodeError]
|
|
1252
|
+
);
|
|
1253
|
+
if (res.status === "error") {
|
|
1254
|
+
return import_results.Result.error(res.error);
|
|
1255
|
+
} else {
|
|
1256
|
+
return import_results.Result.ok(void 0);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
async updatePassword(options, session) {
|
|
1260
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1261
|
+
"/auth/password/update",
|
|
1262
|
+
{
|
|
1263
|
+
method: "POST",
|
|
1264
|
+
headers: {
|
|
1265
|
+
"Content-Type": "application/json"
|
|
1266
|
+
},
|
|
1267
|
+
body: JSON.stringify({
|
|
1268
|
+
old_password: options.oldPassword,
|
|
1269
|
+
new_password: options.newPassword
|
|
1270
|
+
})
|
|
1271
|
+
},
|
|
1272
|
+
session,
|
|
1273
|
+
[import_known_errors.KnownErrors.PasswordConfirmationMismatch, import_known_errors.KnownErrors.PasswordRequirementsNotMet]
|
|
1274
|
+
);
|
|
1275
|
+
if (res.status === "error") {
|
|
1276
|
+
return res.error;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
async setPassword(options, session) {
|
|
1280
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1281
|
+
"/auth/password/set",
|
|
1282
|
+
{
|
|
1283
|
+
method: "POST",
|
|
1284
|
+
headers: {
|
|
1285
|
+
"Content-Type": "application/json"
|
|
1286
|
+
},
|
|
1287
|
+
body: JSON.stringify(options)
|
|
1288
|
+
},
|
|
1289
|
+
session,
|
|
1290
|
+
[import_known_errors.KnownErrors.PasswordRequirementsNotMet]
|
|
1291
|
+
);
|
|
1292
|
+
if (res.status === "error") {
|
|
1293
|
+
return res.error;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
async verifyPasswordResetCode(code) {
|
|
1297
|
+
const res = await this.resetPassword({ code, onlyVerifyCode: true });
|
|
1298
|
+
if (res.status === "error") {
|
|
1299
|
+
return import_results.Result.error(res.error);
|
|
1300
|
+
} else {
|
|
1301
|
+
return import_results.Result.ok(void 0);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
async verifyEmail(code) {
|
|
1305
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1306
|
+
"/contact-channels/verify",
|
|
1307
|
+
{
|
|
1308
|
+
method: "POST",
|
|
1309
|
+
headers: {
|
|
1310
|
+
"Content-Type": "application/json"
|
|
1311
|
+
},
|
|
1312
|
+
body: JSON.stringify({
|
|
1313
|
+
code
|
|
1314
|
+
})
|
|
1315
|
+
},
|
|
1316
|
+
null,
|
|
1317
|
+
[import_known_errors.KnownErrors.VerificationCodeError]
|
|
1318
|
+
);
|
|
1319
|
+
if (res.status === "error") {
|
|
1320
|
+
return import_results.Result.error(res.error);
|
|
1321
|
+
} else {
|
|
1322
|
+
return import_results.Result.ok(void 0);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
async initiatePasskeyRegistration(options, session) {
|
|
1326
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1327
|
+
"/auth/passkey/initiate-passkey-registration",
|
|
1328
|
+
{
|
|
1329
|
+
method: "POST",
|
|
1330
|
+
headers: {
|
|
1331
|
+
"Content-Type": "application/json"
|
|
1332
|
+
},
|
|
1333
|
+
body: JSON.stringify(options)
|
|
1334
|
+
},
|
|
1335
|
+
session,
|
|
1336
|
+
[]
|
|
1337
|
+
);
|
|
1338
|
+
if (res.status === "error") {
|
|
1339
|
+
return import_results.Result.error(res.error);
|
|
1340
|
+
}
|
|
1341
|
+
return import_results.Result.ok(await res.data.json());
|
|
1342
|
+
}
|
|
1343
|
+
async registerPasskey(options, session) {
|
|
1344
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1345
|
+
"/auth/passkey/register",
|
|
1346
|
+
{
|
|
1347
|
+
method: "POST",
|
|
1348
|
+
headers: {
|
|
1349
|
+
"Content-Type": "application/json"
|
|
1350
|
+
},
|
|
1351
|
+
body: JSON.stringify(options)
|
|
1352
|
+
},
|
|
1353
|
+
session,
|
|
1354
|
+
[import_known_errors.KnownErrors.PasskeyRegistrationFailed]
|
|
1355
|
+
);
|
|
1356
|
+
if (res.status === "error") {
|
|
1357
|
+
return import_results.Result.error(res.error);
|
|
1358
|
+
}
|
|
1359
|
+
return import_results.Result.ok(void 0);
|
|
1360
|
+
}
|
|
1361
|
+
async initiatePasskeyAuthentication(options, session) {
|
|
1362
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1363
|
+
"/auth/passkey/initiate-passkey-authentication",
|
|
1364
|
+
{
|
|
1365
|
+
method: "POST",
|
|
1366
|
+
headers: {
|
|
1367
|
+
"Content-Type": "application/json"
|
|
1368
|
+
},
|
|
1369
|
+
body: JSON.stringify(options)
|
|
1370
|
+
},
|
|
1371
|
+
session,
|
|
1372
|
+
[]
|
|
1373
|
+
);
|
|
1374
|
+
if (res.status === "error") {
|
|
1375
|
+
return import_results.Result.error(res.error);
|
|
1376
|
+
}
|
|
1377
|
+
return import_results.Result.ok(await res.data.json());
|
|
1378
|
+
}
|
|
1379
|
+
async sendTeamInvitation(options) {
|
|
1380
|
+
await this.sendClientRequest(
|
|
1381
|
+
"/team-invitations/send-code",
|
|
1382
|
+
{
|
|
1383
|
+
method: "POST",
|
|
1384
|
+
headers: {
|
|
1385
|
+
"Content-Type": "application/json"
|
|
1386
|
+
},
|
|
1387
|
+
body: JSON.stringify({
|
|
1388
|
+
email: options.email,
|
|
1389
|
+
team_id: options.teamId,
|
|
1390
|
+
callback_url: options.callbackUrl
|
|
1391
|
+
})
|
|
1392
|
+
},
|
|
1393
|
+
options.session
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
async acceptTeamInvitation(options) {
|
|
1397
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1398
|
+
options.type === "check" ? "/team-invitations/accept/check-code" : options.type === "details" ? "/team-invitations/accept/details" : "/team-invitations/accept",
|
|
1399
|
+
{
|
|
1400
|
+
method: "POST",
|
|
1401
|
+
headers: {
|
|
1402
|
+
"Content-Type": "application/json"
|
|
1403
|
+
},
|
|
1404
|
+
body: JSON.stringify({
|
|
1405
|
+
code: options.code
|
|
1406
|
+
})
|
|
1407
|
+
},
|
|
1408
|
+
options.session,
|
|
1409
|
+
[import_known_errors.KnownErrors.VerificationCodeError]
|
|
1410
|
+
);
|
|
1411
|
+
if (res.status === "error") {
|
|
1412
|
+
return import_results.Result.error(res.error);
|
|
1413
|
+
} else {
|
|
1414
|
+
return import_results.Result.ok(await res.data.json());
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
async totpMfa(attemptCode, totp, session) {
|
|
1418
|
+
const res = await this.sendClientRequest("/auth/mfa/sign-in", {
|
|
1419
|
+
method: "POST",
|
|
1420
|
+
headers: {
|
|
1421
|
+
"Content-Type": "application/json"
|
|
1422
|
+
},
|
|
1423
|
+
body: JSON.stringify({
|
|
1424
|
+
code: attemptCode,
|
|
1425
|
+
type: "totp",
|
|
1426
|
+
totp
|
|
1427
|
+
})
|
|
1428
|
+
}, session);
|
|
1429
|
+
const result = await res.json();
|
|
1430
|
+
return {
|
|
1431
|
+
accessToken: result.access_token,
|
|
1432
|
+
refreshToken: result.refresh_token,
|
|
1433
|
+
newUser: result.is_new_user
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
async signInWithCredential(email, password, session) {
|
|
1437
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1438
|
+
"/auth/password/sign-in",
|
|
1439
|
+
{
|
|
1440
|
+
method: "POST",
|
|
1441
|
+
headers: {
|
|
1442
|
+
"Content-Type": "application/json"
|
|
1443
|
+
},
|
|
1444
|
+
body: JSON.stringify({
|
|
1445
|
+
email,
|
|
1446
|
+
password
|
|
1447
|
+
})
|
|
1448
|
+
},
|
|
1449
|
+
session,
|
|
1450
|
+
[import_known_errors.KnownErrors.EmailPasswordMismatch]
|
|
1451
|
+
);
|
|
1452
|
+
if (res.status === "error") {
|
|
1453
|
+
return import_results.Result.error(res.error);
|
|
1454
|
+
}
|
|
1455
|
+
const result = await res.data.json();
|
|
1456
|
+
return import_results.Result.ok({
|
|
1457
|
+
accessToken: result.access_token,
|
|
1458
|
+
refreshToken: result.refresh_token
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
async signUpWithCredential(email, password, emailVerificationRedirectUrl, session) {
|
|
1462
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1463
|
+
"/auth/password/sign-up",
|
|
1464
|
+
{
|
|
1465
|
+
headers: {
|
|
1466
|
+
"Content-Type": "application/json"
|
|
1467
|
+
},
|
|
1468
|
+
method: "POST",
|
|
1469
|
+
body: JSON.stringify({
|
|
1470
|
+
email,
|
|
1471
|
+
password,
|
|
1472
|
+
verification_callback_url: emailVerificationRedirectUrl
|
|
1473
|
+
})
|
|
1474
|
+
},
|
|
1475
|
+
session,
|
|
1476
|
+
[import_known_errors.KnownErrors.UserWithEmailAlreadyExists, import_known_errors.KnownErrors.PasswordRequirementsNotMet]
|
|
1477
|
+
);
|
|
1478
|
+
if (res.status === "error") {
|
|
1479
|
+
return import_results.Result.error(res.error);
|
|
1480
|
+
}
|
|
1481
|
+
const result = await res.data.json();
|
|
1482
|
+
return import_results.Result.ok({
|
|
1483
|
+
accessToken: result.access_token,
|
|
1484
|
+
refreshToken: result.refresh_token
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
async signUpAnonymously(session) {
|
|
1488
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1489
|
+
"/auth/anonymous/sign-up",
|
|
1490
|
+
{
|
|
1491
|
+
method: "POST"
|
|
1492
|
+
},
|
|
1493
|
+
session,
|
|
1494
|
+
[]
|
|
1495
|
+
);
|
|
1496
|
+
if (res.status === "error") {
|
|
1497
|
+
return import_results.Result.error(res.error);
|
|
1498
|
+
}
|
|
1499
|
+
const result = await res.data.json();
|
|
1500
|
+
return import_results.Result.ok({
|
|
1501
|
+
accessToken: result.access_token,
|
|
1502
|
+
refreshToken: result.refresh_token
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
async signInWithMagicLink(code) {
|
|
1506
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1507
|
+
"/auth/otp/sign-in",
|
|
1508
|
+
{
|
|
1509
|
+
method: "POST",
|
|
1510
|
+
headers: {
|
|
1511
|
+
"Content-Type": "application/json"
|
|
1512
|
+
},
|
|
1513
|
+
body: JSON.stringify({
|
|
1514
|
+
code
|
|
1515
|
+
})
|
|
1516
|
+
},
|
|
1517
|
+
null,
|
|
1518
|
+
[import_known_errors.KnownErrors.VerificationCodeError]
|
|
1519
|
+
);
|
|
1520
|
+
if (res.status === "error") {
|
|
1521
|
+
return import_results.Result.error(res.error);
|
|
1522
|
+
}
|
|
1523
|
+
const result = await res.data.json();
|
|
1524
|
+
return import_results.Result.ok({
|
|
1525
|
+
accessToken: result.access_token,
|
|
1526
|
+
refreshToken: result.refresh_token,
|
|
1527
|
+
newUser: result.is_new_user
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
async signInWithPasskey(body) {
|
|
1531
|
+
const res = await this.sendClientRequestAndCatchKnownError(
|
|
1532
|
+
"/auth/passkey/sign-in",
|
|
1533
|
+
{
|
|
1534
|
+
method: "POST",
|
|
1535
|
+
headers: {
|
|
1536
|
+
"Content-Type": "application/json"
|
|
1537
|
+
},
|
|
1538
|
+
body: JSON.stringify(body)
|
|
1539
|
+
},
|
|
1540
|
+
null,
|
|
1541
|
+
[import_known_errors.KnownErrors.PasskeyAuthenticationFailed]
|
|
1542
|
+
);
|
|
1543
|
+
if (res.status === "error") {
|
|
1544
|
+
return import_results.Result.error(res.error);
|
|
1545
|
+
}
|
|
1546
|
+
const result = await res.data.json();
|
|
1547
|
+
return import_results.Result.ok({
|
|
1548
|
+
accessToken: result.access_token,
|
|
1549
|
+
refreshToken: result.refresh_token
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
async getOAuthUrl(options) {
|
|
1553
|
+
const updatedRedirectUrl = new URL(options.redirectUrl);
|
|
1554
|
+
for (const key of ["code", "state"]) {
|
|
1555
|
+
if (updatedRedirectUrl.searchParams.has(key)) {
|
|
1556
|
+
console.warn("Redirect URL already contains " + key + " parameter, removing it as it will be overwritten by the OAuth callback");
|
|
1557
|
+
}
|
|
1558
|
+
updatedRedirectUrl.searchParams.delete(key);
|
|
1559
|
+
}
|
|
1560
|
+
if (!("publishableClientKey" in this.options)) {
|
|
1561
|
+
throw new Error("Admin session token is currently not supported for OAuth");
|
|
1562
|
+
}
|
|
1563
|
+
const url = new URL(this.getApiUrl() + "/auth/oauth/authorize/" + options.provider.toLowerCase());
|
|
1564
|
+
url.searchParams.set("client_id", this.projectId);
|
|
1565
|
+
url.searchParams.set("client_secret", this.options.publishableClientKey);
|
|
1566
|
+
url.searchParams.set("redirect_uri", updatedRedirectUrl.toString());
|
|
1567
|
+
url.searchParams.set("scope", "legacy");
|
|
1568
|
+
url.searchParams.set("state", options.state);
|
|
1569
|
+
url.searchParams.set("grant_type", "authorization_code");
|
|
1570
|
+
url.searchParams.set("code_challenge", options.codeChallenge);
|
|
1571
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
1572
|
+
url.searchParams.set("response_type", "code");
|
|
1573
|
+
url.searchParams.set("type", options.type);
|
|
1574
|
+
url.searchParams.set("error_redirect_url", options.errorRedirectUrl);
|
|
1575
|
+
if (options.afterCallbackRedirectUrl) {
|
|
1576
|
+
url.searchParams.set("after_callback_redirect_url", options.afterCallbackRedirectUrl);
|
|
1577
|
+
}
|
|
1578
|
+
if (options.type === "link") {
|
|
1579
|
+
const tokens = await options.session.getOrFetchLikelyValidTokens(2e4);
|
|
1580
|
+
url.searchParams.set("token", tokens?.accessToken.token || "");
|
|
1581
|
+
if (options.providerScope) {
|
|
1582
|
+
url.searchParams.set("provider_scope", options.providerScope);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
return url.toString();
|
|
1586
|
+
}
|
|
1587
|
+
async callOAuthCallback(options) {
|
|
1588
|
+
if (!("publishableClientKey" in this.options)) {
|
|
1589
|
+
throw new Error("Admin session token is currently not supported for OAuth");
|
|
1590
|
+
}
|
|
1591
|
+
const as = {
|
|
1592
|
+
issuer: this.options.getBaseUrl(),
|
|
1593
|
+
algorithm: "oauth2",
|
|
1594
|
+
token_endpoint: this.getApiUrl() + "/auth/oauth/token"
|
|
1595
|
+
};
|
|
1596
|
+
const client = {
|
|
1597
|
+
client_id: this.projectId,
|
|
1598
|
+
client_secret: this.options.publishableClientKey,
|
|
1599
|
+
token_endpoint_auth_method: "client_secret_post"
|
|
1600
|
+
};
|
|
1601
|
+
const params = await this._networkRetryException(
|
|
1602
|
+
async () => validateAuthResponse(as, client, options.oauthParams, options.state)
|
|
1603
|
+
);
|
|
1604
|
+
if (isOAuth2Error(params)) {
|
|
1605
|
+
throw new import_errors.StackAssertionError("Error validating outer OAuth response", { params });
|
|
1606
|
+
}
|
|
1607
|
+
const response = await authorizationCodeGrantRequest(
|
|
1608
|
+
as,
|
|
1609
|
+
client,
|
|
1610
|
+
params,
|
|
1611
|
+
options.redirectUri,
|
|
1612
|
+
options.codeVerifier
|
|
1613
|
+
);
|
|
1614
|
+
const result = await processAuthorizationCodeOAuth2Response(as, client, response);
|
|
1615
|
+
if (isOAuth2Error(result)) {
|
|
1616
|
+
if ("code" in result && result.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
|
|
1617
|
+
throw new import_known_errors.KnownErrors.MultiFactorAuthenticationRequired(result.details.attempt_code);
|
|
1618
|
+
}
|
|
1619
|
+
throw new import_errors.StackAssertionError("Outer OAuth error during authorization code response", { result });
|
|
1620
|
+
}
|
|
1621
|
+
return {
|
|
1622
|
+
newUser: result.is_new_user,
|
|
1623
|
+
afterCallbackRedirectUrl: result.after_callback_redirect_url,
|
|
1624
|
+
accessToken: result.access_token,
|
|
1625
|
+
refreshToken: result.refresh_token ?? (0, import_errors.throwErr)("Refresh token not found in outer OAuth response")
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
async signOut(session) {
|
|
1629
|
+
const tokenObj = await session.getOrFetchLikelyValidTokens(2e4);
|
|
1630
|
+
if (tokenObj) {
|
|
1631
|
+
const resOrError = await this.sendClientRequestAndCatchKnownError(
|
|
1632
|
+
"/auth/sessions/current",
|
|
1633
|
+
{
|
|
1634
|
+
method: "DELETE",
|
|
1635
|
+
headers: {
|
|
1636
|
+
"Content-Type": "application/json"
|
|
1637
|
+
},
|
|
1638
|
+
body: JSON.stringify({})
|
|
1639
|
+
},
|
|
1640
|
+
session,
|
|
1641
|
+
[import_known_errors.KnownErrors.RefreshTokenError]
|
|
1642
|
+
);
|
|
1643
|
+
if (resOrError.status === "error") {
|
|
1644
|
+
if (resOrError.error instanceof import_known_errors.KnownErrors.RefreshTokenError) {
|
|
1645
|
+
} else {
|
|
1646
|
+
throw new import_errors.StackAssertionError("Unexpected error", { error: resOrError.error });
|
|
444
1647
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
})
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
}, session);
|
|
867
|
-
}
|
|
868
|
-
async deleteCurrentUser(session) {
|
|
869
|
-
await this.sendClientRequest("/users/me", {
|
|
870
|
-
method: "DELETE",
|
|
871
|
-
}, session);
|
|
872
|
-
}
|
|
873
|
-
async createClientContactChannel(data, session) {
|
|
874
|
-
const response = await this.sendClientRequest("/contact-channels", {
|
|
875
|
-
method: "POST",
|
|
876
|
-
headers: {
|
|
877
|
-
"content-type": "application/json",
|
|
878
|
-
},
|
|
879
|
-
body: JSON.stringify(data),
|
|
880
|
-
}, session);
|
|
881
|
-
return await response.json();
|
|
882
|
-
}
|
|
883
|
-
async updateClientContactChannel(id, data, session) {
|
|
884
|
-
const response = await this.sendClientRequest(`/contact-channels/me/${id}`, {
|
|
885
|
-
method: "PATCH",
|
|
886
|
-
headers: {
|
|
887
|
-
"content-type": "application/json",
|
|
888
|
-
},
|
|
889
|
-
body: JSON.stringify(data),
|
|
890
|
-
}, session);
|
|
891
|
-
return await response.json();
|
|
892
|
-
}
|
|
893
|
-
async deleteClientContactChannel(id, session) {
|
|
894
|
-
await this.sendClientRequest(`/contact-channels/me/${id}`, {
|
|
895
|
-
method: "DELETE",
|
|
896
|
-
}, session);
|
|
897
|
-
}
|
|
898
|
-
async deleteSession(sessionId, session) {
|
|
899
|
-
await this.sendClientRequest(`/auth/sessions/${sessionId}?user_id=me`, {
|
|
900
|
-
method: "DELETE",
|
|
901
|
-
}, session);
|
|
902
|
-
}
|
|
903
|
-
async listSessions(session) {
|
|
904
|
-
const response = await this.sendClientRequest("/auth/sessions?user_id=me", {
|
|
905
|
-
method: "GET",
|
|
906
|
-
}, session);
|
|
907
|
-
return await response.json();
|
|
908
|
-
}
|
|
909
|
-
async listClientContactChannels(session) {
|
|
910
|
-
const response = await this.sendClientRequest("/contact-channels?user_id=me", {
|
|
911
|
-
method: "GET",
|
|
912
|
-
}, session);
|
|
913
|
-
const json = await response.json();
|
|
914
|
-
return json.items;
|
|
915
|
-
}
|
|
916
|
-
async sendCurrentUserContactChannelVerificationEmail(contactChannelId, callbackUrl, session) {
|
|
917
|
-
const responseOrError = await this.sendClientRequestAndCatchKnownError(`/contact-channels/me/${contactChannelId}/send-verification-code`, {
|
|
918
|
-
method: "POST",
|
|
919
|
-
headers: {
|
|
920
|
-
"content-type": "application/json",
|
|
921
|
-
},
|
|
922
|
-
body: JSON.stringify({ callback_url: callbackUrl }),
|
|
923
|
-
}, session, [KnownErrors.EmailAlreadyVerified]);
|
|
924
|
-
if (responseOrError.status === "error") {
|
|
925
|
-
return Result.error(responseOrError.error);
|
|
926
|
-
}
|
|
927
|
-
return Result.ok(undefined);
|
|
928
|
-
}
|
|
929
|
-
async cliLogin(loginCode, refreshToken, session) {
|
|
930
|
-
const responseOrError = await this.sendClientRequestAndCatchKnownError("/auth/cli/complete", {
|
|
931
|
-
method: "POST",
|
|
932
|
-
headers: {
|
|
933
|
-
"Content-Type": "application/json"
|
|
934
|
-
},
|
|
935
|
-
body: JSON.stringify({
|
|
936
|
-
login_code: loginCode,
|
|
937
|
-
refresh_token: refreshToken,
|
|
938
|
-
}),
|
|
939
|
-
}, session, [KnownErrors.SchemaError]);
|
|
940
|
-
if (responseOrError.status === "error") {
|
|
941
|
-
return Result.error(responseOrError.error);
|
|
942
|
-
}
|
|
943
|
-
return Result.ok(undefined);
|
|
944
|
-
}
|
|
945
|
-
async _getApiKeyRequestInfo(options) {
|
|
946
|
-
if ("user_id" in options && "team_id" in options) {
|
|
947
|
-
throw new StackAssertionError("Cannot specify both user_id and team_id in _getApiKeyRequestInfo");
|
|
948
|
-
}
|
|
949
|
-
return {
|
|
950
|
-
endpoint: "team_id" in options ? "/team-api-keys" : "/user-api-keys",
|
|
951
|
-
queryParams: new URLSearchParams(filterUndefinedOrNull(options)),
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
async listProjectApiKeys(options, session, requestType) {
|
|
955
|
-
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
956
|
-
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
957
|
-
const response = await sendRequest(`${endpoint}?${queryParams.toString()}`, {
|
|
958
|
-
method: "GET",
|
|
959
|
-
}, session, requestType);
|
|
960
|
-
const json = await response.json();
|
|
961
|
-
return json.items;
|
|
962
|
-
}
|
|
963
|
-
async createProjectApiKey(data, session, requestType) {
|
|
964
|
-
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
965
|
-
const { endpoint } = await this._getApiKeyRequestInfo(data);
|
|
966
|
-
const response = await sendRequest(`${endpoint}`, {
|
|
967
|
-
method: "POST",
|
|
968
|
-
headers: {
|
|
969
|
-
"content-type": "application/json",
|
|
970
|
-
},
|
|
971
|
-
body: JSON.stringify(data),
|
|
972
|
-
}, session, requestType);
|
|
973
|
-
return await response.json();
|
|
974
|
-
}
|
|
975
|
-
async getProjectApiKey(options, keyId, session, requestType) {
|
|
976
|
-
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
977
|
-
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
978
|
-
const response = await sendRequest(`${endpoint}/${keyId}?${queryParams.toString()}`, {
|
|
979
|
-
method: "GET",
|
|
980
|
-
}, session, requestType);
|
|
981
|
-
return await response.json();
|
|
982
|
-
}
|
|
983
|
-
async updateProjectApiKey(options, keyId, data, session, requestType) {
|
|
984
|
-
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
985
|
-
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
986
|
-
const response = await sendRequest(`${endpoint}/${keyId}?${queryParams.toString()}`, {
|
|
987
|
-
method: "PATCH",
|
|
988
|
-
headers: {
|
|
989
|
-
"content-type": "application/json",
|
|
990
|
-
},
|
|
991
|
-
body: JSON.stringify(data),
|
|
992
|
-
}, session, requestType);
|
|
993
|
-
return await response.json();
|
|
994
|
-
}
|
|
995
|
-
async checkProjectApiKey(type, apiKey, session, requestType) {
|
|
996
|
-
const sendRequest = (requestType === "client" ? this.sendClientRequestAndCatchKnownError : this.sendServerRequestAndCatchKnownError).bind(this);
|
|
997
|
-
const result = await sendRequest(`/${type}-api-keys/check`, {
|
|
998
|
-
method: "POST",
|
|
999
|
-
headers: {
|
|
1000
|
-
"content-type": "application/json",
|
|
1001
|
-
},
|
|
1002
|
-
body: JSON.stringify({ api_key: apiKey }),
|
|
1003
|
-
}, session, [KnownErrors.ApiKeyNotValid]);
|
|
1004
|
-
if (result.status === "error") {
|
|
1005
|
-
return null;
|
|
1006
|
-
}
|
|
1007
|
-
return await result.data.json();
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1648
|
+
} else {
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
session.markInvalid();
|
|
1652
|
+
}
|
|
1653
|
+
async getClientUserByToken(session) {
|
|
1654
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError(
|
|
1655
|
+
"/users/me",
|
|
1656
|
+
{},
|
|
1657
|
+
session,
|
|
1658
|
+
[import_known_errors.KnownErrors.CannotGetOwnUserWithoutUser]
|
|
1659
|
+
);
|
|
1660
|
+
if (responseOrError.status === "error") {
|
|
1661
|
+
if (responseOrError.error instanceof import_known_errors.KnownErrors.CannotGetOwnUserWithoutUser) {
|
|
1662
|
+
return null;
|
|
1663
|
+
} else {
|
|
1664
|
+
throw new import_errors.StackAssertionError("Unexpected uncaught error", { cause: responseOrError.error });
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
const response = responseOrError.data;
|
|
1668
|
+
const user = await response.json();
|
|
1669
|
+
if (!user) throw new import_errors.StackAssertionError("User endpoint returned null; this should never happen");
|
|
1670
|
+
return user;
|
|
1671
|
+
}
|
|
1672
|
+
async listTeamInvitations(options, session) {
|
|
1673
|
+
const response = await this.sendClientRequest(
|
|
1674
|
+
"/team-invitations?" + new URLSearchParams({ team_id: options.teamId }),
|
|
1675
|
+
{},
|
|
1676
|
+
session
|
|
1677
|
+
);
|
|
1678
|
+
const result = await response.json();
|
|
1679
|
+
return result.items;
|
|
1680
|
+
}
|
|
1681
|
+
async revokeTeamInvitation(invitationId, teamId, session) {
|
|
1682
|
+
await this.sendClientRequest(
|
|
1683
|
+
`/team-invitations/${invitationId}?team_id=${teamId}`,
|
|
1684
|
+
{ method: "DELETE" },
|
|
1685
|
+
session
|
|
1686
|
+
);
|
|
1687
|
+
}
|
|
1688
|
+
async listTeamMemberProfiles(options, session) {
|
|
1689
|
+
const response = await this.sendClientRequest(
|
|
1690
|
+
"/team-member-profiles?" + new URLSearchParams((0, import_objects.filterUndefined)({
|
|
1691
|
+
team_id: options.teamId,
|
|
1692
|
+
user_id: options.userId
|
|
1693
|
+
})),
|
|
1694
|
+
{},
|
|
1695
|
+
session
|
|
1696
|
+
);
|
|
1697
|
+
const result = await response.json();
|
|
1698
|
+
return result.items;
|
|
1699
|
+
}
|
|
1700
|
+
async getTeamMemberProfile(options, session) {
|
|
1701
|
+
const response = await this.sendClientRequest(
|
|
1702
|
+
`/team-member-profiles/${options.teamId}/${options.userId}`,
|
|
1703
|
+
{},
|
|
1704
|
+
session
|
|
1705
|
+
);
|
|
1706
|
+
return await response.json();
|
|
1707
|
+
}
|
|
1708
|
+
async leaveTeam(teamId, session) {
|
|
1709
|
+
await this.sendClientRequest(
|
|
1710
|
+
`/team-memberships/${teamId}/me`,
|
|
1711
|
+
{
|
|
1712
|
+
method: "DELETE",
|
|
1713
|
+
headers: {
|
|
1714
|
+
"content-type": "application/json"
|
|
1715
|
+
},
|
|
1716
|
+
body: JSON.stringify({})
|
|
1717
|
+
},
|
|
1718
|
+
session
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
async updateTeamMemberProfile(options, session) {
|
|
1722
|
+
await this.sendClientRequest(
|
|
1723
|
+
`/team-member-profiles/${options.teamId}/${options.userId}`,
|
|
1724
|
+
{
|
|
1725
|
+
method: "PATCH",
|
|
1726
|
+
headers: {
|
|
1727
|
+
"content-type": "application/json"
|
|
1728
|
+
},
|
|
1729
|
+
body: JSON.stringify(options.profile)
|
|
1730
|
+
},
|
|
1731
|
+
session
|
|
1732
|
+
);
|
|
1733
|
+
}
|
|
1734
|
+
async updateTeam(options, session) {
|
|
1735
|
+
await this.sendClientRequest(
|
|
1736
|
+
`/teams/${options.teamId}`,
|
|
1737
|
+
{
|
|
1738
|
+
method: "PATCH",
|
|
1739
|
+
headers: {
|
|
1740
|
+
"content-type": "application/json"
|
|
1741
|
+
},
|
|
1742
|
+
body: JSON.stringify(options.data)
|
|
1743
|
+
},
|
|
1744
|
+
session
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
async listCurrentUserTeamPermissions(options, session) {
|
|
1748
|
+
const response = await this.sendClientRequest(
|
|
1749
|
+
`/team-permissions?team_id=${options.teamId}&user_id=me&recursive=${options.recursive}`,
|
|
1750
|
+
{},
|
|
1751
|
+
session
|
|
1752
|
+
);
|
|
1753
|
+
const result = await response.json();
|
|
1754
|
+
return result.items;
|
|
1755
|
+
}
|
|
1756
|
+
async listCurrentUserProjectPermissions(options, session) {
|
|
1757
|
+
const response = await this.sendClientRequest(
|
|
1758
|
+
`/project-permissions?user_id=me&recursive=${options.recursive}`,
|
|
1759
|
+
{},
|
|
1760
|
+
session
|
|
1761
|
+
);
|
|
1762
|
+
const result = await response.json();
|
|
1763
|
+
return result.items;
|
|
1764
|
+
}
|
|
1765
|
+
async listCurrentUserTeams(session) {
|
|
1766
|
+
const response = await this.sendClientRequest(
|
|
1767
|
+
"/teams?user_id=me",
|
|
1768
|
+
{},
|
|
1769
|
+
session
|
|
1770
|
+
);
|
|
1771
|
+
const result = await response.json();
|
|
1772
|
+
return result.items;
|
|
1773
|
+
}
|
|
1774
|
+
async getClientProject() {
|
|
1775
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError("/projects/current", {}, null, [import_known_errors.KnownErrors.ProjectNotFound]);
|
|
1776
|
+
if (responseOrError.status === "error") {
|
|
1777
|
+
return import_results.Result.error(responseOrError.error);
|
|
1778
|
+
}
|
|
1779
|
+
const response = responseOrError.data;
|
|
1780
|
+
const project = await response.json();
|
|
1781
|
+
return import_results.Result.ok(project);
|
|
1782
|
+
}
|
|
1783
|
+
async updateClientUser(update, session) {
|
|
1784
|
+
await this.sendClientRequest(
|
|
1785
|
+
"/users/me",
|
|
1786
|
+
{
|
|
1787
|
+
method: "PATCH",
|
|
1788
|
+
headers: {
|
|
1789
|
+
"content-type": "application/json"
|
|
1790
|
+
},
|
|
1791
|
+
body: JSON.stringify(update)
|
|
1792
|
+
},
|
|
1793
|
+
session
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
async listProjects(session) {
|
|
1797
|
+
const response = await this.sendClientRequest("/internal/projects", {}, session);
|
|
1798
|
+
if (!response.ok) {
|
|
1799
|
+
throw new Error("Failed to list projects: " + response.status + " " + await response.text());
|
|
1800
|
+
}
|
|
1801
|
+
const json = await response.json();
|
|
1802
|
+
return json.items;
|
|
1803
|
+
}
|
|
1804
|
+
async createProject(project, session) {
|
|
1805
|
+
const fetchResponse = await this.sendClientRequest(
|
|
1806
|
+
"/internal/projects",
|
|
1807
|
+
{
|
|
1808
|
+
method: "POST",
|
|
1809
|
+
headers: {
|
|
1810
|
+
"content-type": "application/json"
|
|
1811
|
+
},
|
|
1812
|
+
body: JSON.stringify(project)
|
|
1813
|
+
},
|
|
1814
|
+
session
|
|
1815
|
+
);
|
|
1816
|
+
if (!fetchResponse.ok) {
|
|
1817
|
+
throw new Error("Failed to create project: " + fetchResponse.status + " " + await fetchResponse.text());
|
|
1818
|
+
}
|
|
1819
|
+
const json = await fetchResponse.json();
|
|
1820
|
+
return json;
|
|
1821
|
+
}
|
|
1822
|
+
async createProviderAccessToken(provider, scope, session) {
|
|
1823
|
+
const response = await this.sendClientRequest(
|
|
1824
|
+
`/connected-accounts/me/${provider}/access-token`,
|
|
1825
|
+
{
|
|
1826
|
+
method: "POST",
|
|
1827
|
+
headers: {
|
|
1828
|
+
"content-type": "application/json"
|
|
1829
|
+
},
|
|
1830
|
+
body: JSON.stringify({ scope })
|
|
1831
|
+
},
|
|
1832
|
+
session
|
|
1833
|
+
);
|
|
1834
|
+
return await response.json();
|
|
1835
|
+
}
|
|
1836
|
+
async createClientTeam(data, session) {
|
|
1837
|
+
const response = await this.sendClientRequest(
|
|
1838
|
+
"/teams",
|
|
1839
|
+
{
|
|
1840
|
+
method: "POST",
|
|
1841
|
+
headers: {
|
|
1842
|
+
"content-type": "application/json"
|
|
1843
|
+
},
|
|
1844
|
+
body: JSON.stringify(data)
|
|
1845
|
+
},
|
|
1846
|
+
session
|
|
1847
|
+
);
|
|
1848
|
+
return await response.json();
|
|
1849
|
+
}
|
|
1850
|
+
async deleteTeam(teamId, session) {
|
|
1851
|
+
await this.sendClientRequest(
|
|
1852
|
+
`/teams/${teamId}`,
|
|
1853
|
+
{
|
|
1854
|
+
method: "DELETE"
|
|
1855
|
+
},
|
|
1856
|
+
session
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
async deleteCurrentUser(session) {
|
|
1860
|
+
await this.sendClientRequest(
|
|
1861
|
+
"/users/me",
|
|
1862
|
+
{
|
|
1863
|
+
method: "DELETE"
|
|
1864
|
+
},
|
|
1865
|
+
session
|
|
1866
|
+
);
|
|
1867
|
+
}
|
|
1868
|
+
async createClientContactChannel(data, session) {
|
|
1869
|
+
const response = await this.sendClientRequest(
|
|
1870
|
+
"/contact-channels",
|
|
1871
|
+
{
|
|
1872
|
+
method: "POST",
|
|
1873
|
+
headers: {
|
|
1874
|
+
"content-type": "application/json"
|
|
1875
|
+
},
|
|
1876
|
+
body: JSON.stringify(data)
|
|
1877
|
+
},
|
|
1878
|
+
session
|
|
1879
|
+
);
|
|
1880
|
+
return await response.json();
|
|
1881
|
+
}
|
|
1882
|
+
async updateClientContactChannel(id, data, session) {
|
|
1883
|
+
const response = await this.sendClientRequest(
|
|
1884
|
+
`/contact-channels/me/${id}`,
|
|
1885
|
+
{
|
|
1886
|
+
method: "PATCH",
|
|
1887
|
+
headers: {
|
|
1888
|
+
"content-type": "application/json"
|
|
1889
|
+
},
|
|
1890
|
+
body: JSON.stringify(data)
|
|
1891
|
+
},
|
|
1892
|
+
session
|
|
1893
|
+
);
|
|
1894
|
+
return await response.json();
|
|
1895
|
+
}
|
|
1896
|
+
async deleteClientContactChannel(id, session) {
|
|
1897
|
+
await this.sendClientRequest(
|
|
1898
|
+
`/contact-channels/me/${id}`,
|
|
1899
|
+
{
|
|
1900
|
+
method: "DELETE"
|
|
1901
|
+
},
|
|
1902
|
+
session
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
async deleteSession(sessionId, session) {
|
|
1906
|
+
await this.sendClientRequest(
|
|
1907
|
+
`/auth/sessions/${sessionId}?user_id=me`,
|
|
1908
|
+
{
|
|
1909
|
+
method: "DELETE"
|
|
1910
|
+
},
|
|
1911
|
+
session
|
|
1912
|
+
);
|
|
1913
|
+
}
|
|
1914
|
+
async listSessions(session) {
|
|
1915
|
+
const response = await this.sendClientRequest(
|
|
1916
|
+
"/auth/sessions?user_id=me",
|
|
1917
|
+
{
|
|
1918
|
+
method: "GET"
|
|
1919
|
+
},
|
|
1920
|
+
session
|
|
1921
|
+
);
|
|
1922
|
+
return await response.json();
|
|
1923
|
+
}
|
|
1924
|
+
async listClientContactChannels(session) {
|
|
1925
|
+
const response = await this.sendClientRequest(
|
|
1926
|
+
"/contact-channels?user_id=me",
|
|
1927
|
+
{
|
|
1928
|
+
method: "GET"
|
|
1929
|
+
},
|
|
1930
|
+
session
|
|
1931
|
+
);
|
|
1932
|
+
const json = await response.json();
|
|
1933
|
+
return json.items;
|
|
1934
|
+
}
|
|
1935
|
+
async sendCurrentUserContactChannelVerificationEmail(contactChannelId, callbackUrl, session) {
|
|
1936
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError(
|
|
1937
|
+
`/contact-channels/me/${contactChannelId}/send-verification-code`,
|
|
1938
|
+
{
|
|
1939
|
+
method: "POST",
|
|
1940
|
+
headers: {
|
|
1941
|
+
"content-type": "application/json"
|
|
1942
|
+
},
|
|
1943
|
+
body: JSON.stringify({ callback_url: callbackUrl })
|
|
1944
|
+
},
|
|
1945
|
+
session,
|
|
1946
|
+
[import_known_errors.KnownErrors.EmailAlreadyVerified]
|
|
1947
|
+
);
|
|
1948
|
+
if (responseOrError.status === "error") {
|
|
1949
|
+
return import_results.Result.error(responseOrError.error);
|
|
1950
|
+
}
|
|
1951
|
+
return import_results.Result.ok(void 0);
|
|
1952
|
+
}
|
|
1953
|
+
async cliLogin(loginCode, refreshToken, session) {
|
|
1954
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError(
|
|
1955
|
+
"/auth/cli/complete",
|
|
1956
|
+
{
|
|
1957
|
+
method: "POST",
|
|
1958
|
+
headers: {
|
|
1959
|
+
"Content-Type": "application/json"
|
|
1960
|
+
},
|
|
1961
|
+
body: JSON.stringify({
|
|
1962
|
+
login_code: loginCode,
|
|
1963
|
+
refresh_token: refreshToken
|
|
1964
|
+
})
|
|
1965
|
+
},
|
|
1966
|
+
session,
|
|
1967
|
+
[import_known_errors.KnownErrors.SchemaError]
|
|
1968
|
+
);
|
|
1969
|
+
if (responseOrError.status === "error") {
|
|
1970
|
+
return import_results.Result.error(responseOrError.error);
|
|
1971
|
+
}
|
|
1972
|
+
return import_results.Result.ok(void 0);
|
|
1973
|
+
}
|
|
1974
|
+
async _getApiKeyRequestInfo(options) {
|
|
1975
|
+
if ("user_id" in options && "team_id" in options) {
|
|
1976
|
+
throw new import_errors.StackAssertionError("Cannot specify both user_id and team_id in _getApiKeyRequestInfo");
|
|
1977
|
+
}
|
|
1978
|
+
return {
|
|
1979
|
+
endpoint: "team_id" in options ? "/team-api-keys" : "/user-api-keys",
|
|
1980
|
+
queryParams: new URLSearchParams((0, import_objects.filterUndefinedOrNull)(options))
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
async listProjectApiKeys(options, session, requestType) {
|
|
1984
|
+
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
1985
|
+
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
1986
|
+
const response = await sendRequest(
|
|
1987
|
+
`${endpoint}?${queryParams.toString()}`,
|
|
1988
|
+
{
|
|
1989
|
+
method: "GET"
|
|
1990
|
+
},
|
|
1991
|
+
session,
|
|
1992
|
+
requestType
|
|
1993
|
+
);
|
|
1994
|
+
const json = await response.json();
|
|
1995
|
+
return json.items;
|
|
1996
|
+
}
|
|
1997
|
+
async createProjectApiKey(data, session, requestType) {
|
|
1998
|
+
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
1999
|
+
const { endpoint } = await this._getApiKeyRequestInfo(data);
|
|
2000
|
+
const response = await sendRequest(
|
|
2001
|
+
`${endpoint}`,
|
|
2002
|
+
{
|
|
2003
|
+
method: "POST",
|
|
2004
|
+
headers: {
|
|
2005
|
+
"content-type": "application/json"
|
|
2006
|
+
},
|
|
2007
|
+
body: JSON.stringify(data)
|
|
2008
|
+
},
|
|
2009
|
+
session,
|
|
2010
|
+
requestType
|
|
2011
|
+
);
|
|
2012
|
+
return await response.json();
|
|
2013
|
+
}
|
|
2014
|
+
async getProjectApiKey(options, keyId, session, requestType) {
|
|
2015
|
+
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
2016
|
+
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
2017
|
+
const response = await sendRequest(
|
|
2018
|
+
`${endpoint}/${keyId}?${queryParams.toString()}`,
|
|
2019
|
+
{
|
|
2020
|
+
method: "GET"
|
|
2021
|
+
},
|
|
2022
|
+
session,
|
|
2023
|
+
requestType
|
|
2024
|
+
);
|
|
2025
|
+
return await response.json();
|
|
2026
|
+
}
|
|
2027
|
+
async updateProjectApiKey(options, keyId, data, session, requestType) {
|
|
2028
|
+
const sendRequest = (requestType === "client" ? this.sendClientRequest : this.sendServerRequest).bind(this);
|
|
2029
|
+
const { endpoint, queryParams } = await this._getApiKeyRequestInfo(options);
|
|
2030
|
+
const response = await sendRequest(
|
|
2031
|
+
`${endpoint}/${keyId}?${queryParams.toString()}`,
|
|
2032
|
+
{
|
|
2033
|
+
method: "PATCH",
|
|
2034
|
+
headers: {
|
|
2035
|
+
"content-type": "application/json"
|
|
2036
|
+
},
|
|
2037
|
+
body: JSON.stringify(data)
|
|
2038
|
+
},
|
|
2039
|
+
session,
|
|
2040
|
+
requestType
|
|
2041
|
+
);
|
|
2042
|
+
return await response.json();
|
|
2043
|
+
}
|
|
2044
|
+
async checkProjectApiKey(type, apiKey, session, requestType) {
|
|
2045
|
+
const sendRequest = (requestType === "client" ? this.sendClientRequestAndCatchKnownError : this.sendServerRequestAndCatchKnownError).bind(this);
|
|
2046
|
+
const result = await sendRequest(
|
|
2047
|
+
`/${type}-api-keys/check`,
|
|
2048
|
+
{
|
|
2049
|
+
method: "POST",
|
|
2050
|
+
headers: {
|
|
2051
|
+
"content-type": "application/json"
|
|
2052
|
+
},
|
|
2053
|
+
body: JSON.stringify({ api_key: apiKey })
|
|
2054
|
+
},
|
|
2055
|
+
session,
|
|
2056
|
+
[import_known_errors.KnownErrors.ApiKeyNotValid]
|
|
2057
|
+
);
|
|
2058
|
+
if (result.status === "error") {
|
|
2059
|
+
return null;
|
|
2060
|
+
}
|
|
2061
|
+
return await result.data.json();
|
|
2062
|
+
}
|
|
2063
|
+
};
|
|
2064
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2065
|
+
0 && (module.exports = {
|
|
2066
|
+
StackClientInterface
|
|
2067
|
+
});
|
|
2068
|
+
//# sourceMappingURL=clientInterface.js.map
|