@stackframe/stack-shared 2.8.12 → 2.8.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/config/format.js +2 -2
  3. package/dist/config/schema.d.mts +32 -32
  4. package/dist/config/schema.d.ts +32 -32
  5. package/dist/config/schema.js +4 -4
  6. package/dist/config/schema.js.map +1 -1
  7. package/dist/crud.js +2 -2
  8. package/dist/esm/config/format.js +2 -2
  9. package/dist/esm/config/schema.js +4 -4
  10. package/dist/esm/config/schema.js.map +1 -1
  11. package/dist/esm/crud.js +2 -2
  12. package/dist/esm/helpers/password.js +1 -1
  13. package/dist/esm/helpers/production-mode.js +2 -2
  14. package/dist/esm/hooks/use-async-callback.js +1 -1
  15. package/dist/esm/hooks/use-async-external-store.js +1 -1
  16. package/dist/esm/hooks/use-hash.js +1 -1
  17. package/dist/esm/hooks/use-strict-memo.js +1 -1
  18. package/dist/esm/index.js +4 -4
  19. package/dist/esm/index.js.map +1 -1
  20. package/dist/esm/interface/{adminInterface.js → admin-interface.js} +19 -3
  21. package/dist/esm/interface/admin-interface.js.map +1 -0
  22. package/dist/esm/interface/{clientInterface.js → client-interface.js} +74 -856
  23. package/dist/esm/interface/client-interface.js.map +1 -0
  24. package/dist/esm/interface/crud/contact-channels.js +2 -2
  25. package/dist/esm/interface/crud/current-user.js +4 -4
  26. package/dist/esm/interface/crud/email-templates.js +3 -3
  27. package/dist/esm/interface/crud/email-templates.js.map +1 -1
  28. package/dist/esm/interface/crud/emails.js +3 -3
  29. package/dist/esm/interface/crud/internal-api-keys.js +2 -2
  30. package/dist/esm/interface/crud/notification-preferences.js +20 -0
  31. package/dist/esm/interface/crud/notification-preferences.js.map +1 -0
  32. package/dist/esm/interface/crud/oauth.js +2 -2
  33. package/dist/esm/interface/crud/project-api-keys.js +3 -3
  34. package/dist/esm/interface/crud/project-permissions.js +3 -3
  35. package/dist/esm/interface/crud/projects.js +3 -3
  36. package/dist/esm/interface/crud/sessions.js +3 -3
  37. package/dist/esm/interface/crud/svix-token.js +2 -2
  38. package/dist/esm/interface/crud/team-invitation-details.js +3 -3
  39. package/dist/esm/interface/crud/team-invitation.js +3 -3
  40. package/dist/esm/interface/crud/team-member-profiles.js +4 -4
  41. package/dist/esm/interface/crud/team-memberships.js +2 -2
  42. package/dist/esm/interface/crud/team-permissions.js +3 -3
  43. package/dist/esm/interface/crud/teams.js +3 -3
  44. package/dist/esm/interface/crud/users.js +3 -3
  45. package/dist/esm/interface/{serverInterface.js → server-interface.js} +34 -8
  46. package/dist/esm/interface/server-interface.js.map +1 -0
  47. package/dist/esm/interface/webhooks.js +4 -4
  48. package/dist/esm/known-errors.js +3 -3
  49. package/dist/esm/schema-fields.js +11 -11
  50. package/dist/esm/schema-fields.js.map +1 -1
  51. package/dist/esm/sessions.js +2 -2
  52. package/dist/esm/utils/api-keys.js +3 -3
  53. package/dist/esm/utils/arrays.js +1 -1
  54. package/dist/esm/utils/bytes.js +4 -27
  55. package/dist/esm/utils/bytes.js.map +1 -1
  56. package/dist/esm/utils/caches.js +4 -4
  57. package/dist/esm/utils/crypto.js +3 -3
  58. package/dist/esm/utils/dates.js +1 -1
  59. package/dist/esm/utils/env.js +2 -2
  60. package/dist/esm/utils/errors.js +3 -3
  61. package/dist/esm/utils/geo.js +1 -1
  62. package/dist/esm/utils/hashes.js +1 -1
  63. package/dist/esm/utils/html.js +1 -1
  64. package/dist/esm/utils/http.js +1 -1
  65. package/dist/esm/utils/json.js +1 -1
  66. package/dist/esm/utils/jwt.js +4 -4
  67. package/dist/esm/utils/maps.js +1 -1
  68. package/dist/esm/utils/node-http.js +1 -1
  69. package/dist/esm/utils/objects.js +3 -3
  70. package/dist/esm/utils/promises.js +5 -5
  71. package/dist/esm/utils/proxies.js +1 -1
  72. package/dist/esm/utils/react.js +3 -3
  73. package/dist/esm/utils/results.js +2 -2
  74. package/dist/esm/utils/stores.js +4 -4
  75. package/dist/esm/utils/strings.js +6 -3
  76. package/dist/esm/utils/strings.js.map +1 -1
  77. package/dist/esm/utils/strings.nicify.test.js +1 -1
  78. package/dist/esm/utils/unicode.js +1 -1
  79. package/dist/esm/utils/urls.js +2 -2
  80. package/dist/esm/utils/uuids.js +1 -1
  81. package/dist/helpers/password.js +1 -1
  82. package/dist/helpers/production-mode.js +2 -2
  83. package/dist/hooks/use-async-callback.js +1 -1
  84. package/dist/hooks/use-async-external-store.js +1 -1
  85. package/dist/hooks/use-hash.js +1 -1
  86. package/dist/hooks/use-strict-memo.js +1 -1
  87. package/dist/index.d.mts +4 -3
  88. package/dist/index.d.ts +4 -3
  89. package/dist/index.js +7 -7
  90. package/dist/index.js.map +1 -1
  91. package/dist/interface/{adminInterface.d.mts → admin-interface.d.mts} +4 -2
  92. package/dist/interface/{adminInterface.d.ts → admin-interface.d.ts} +4 -2
  93. package/dist/interface/{adminInterface.js → admin-interface.js} +23 -7
  94. package/dist/interface/admin-interface.js.map +1 -0
  95. package/dist/interface/{clientInterface.d.mts → client-interface.d.mts} +8 -0
  96. package/dist/interface/{clientInterface.d.ts → client-interface.d.ts} +8 -0
  97. package/dist/interface/{clientInterface.js → client-interface.js} +87 -861
  98. package/dist/interface/client-interface.js.map +1 -0
  99. package/dist/interface/crud/contact-channels.js +2 -2
  100. package/dist/interface/crud/current-user.js +4 -4
  101. package/dist/interface/crud/email-templates.d.mts +5 -5
  102. package/dist/interface/crud/email-templates.d.ts +5 -5
  103. package/dist/interface/crud/email-templates.js +3 -3
  104. package/dist/interface/crud/email-templates.js.map +1 -1
  105. package/dist/interface/crud/emails.js +3 -3
  106. package/dist/interface/crud/internal-api-keys.js +2 -2
  107. package/dist/interface/crud/notification-preferences.d.mts +25 -0
  108. package/dist/interface/crud/notification-preferences.d.ts +25 -0
  109. package/dist/interface/crud/notification-preferences.js +45 -0
  110. package/dist/interface/crud/notification-preferences.js.map +1 -0
  111. package/dist/interface/crud/oauth.js +2 -2
  112. package/dist/interface/crud/project-api-keys.js +3 -3
  113. package/dist/interface/crud/project-permissions.js +3 -3
  114. package/dist/interface/crud/projects.js +3 -3
  115. package/dist/interface/crud/sessions.js +3 -3
  116. package/dist/interface/crud/svix-token.js +2 -2
  117. package/dist/interface/crud/team-invitation-details.js +3 -3
  118. package/dist/interface/crud/team-invitation.js +3 -3
  119. package/dist/interface/crud/team-member-profiles.js +4 -4
  120. package/dist/interface/crud/team-memberships.js +2 -2
  121. package/dist/interface/crud/team-permissions.js +3 -3
  122. package/dist/interface/crud/teams.js +3 -3
  123. package/dist/interface/crud/users.js +3 -3
  124. package/dist/interface/{serverInterface.d.mts → server-interface.d.mts} +4 -1
  125. package/dist/interface/{serverInterface.d.ts → server-interface.d.ts} +4 -1
  126. package/dist/interface/{serverInterface.js → server-interface.js} +38 -12
  127. package/dist/interface/server-interface.js.map +1 -0
  128. package/dist/interface/webhooks.js +4 -4
  129. package/dist/known-errors.js +3 -3
  130. package/dist/schema-fields.js +11 -11
  131. package/dist/schema-fields.js.map +1 -1
  132. package/dist/sessions.js +2 -2
  133. package/dist/utils/api-keys.js +3 -3
  134. package/dist/utils/arrays.js +1 -1
  135. package/dist/utils/bytes.js +4 -27
  136. package/dist/utils/bytes.js.map +1 -1
  137. package/dist/utils/caches.js +4 -4
  138. package/dist/utils/crypto.js +3 -3
  139. package/dist/utils/dates.js +1 -1
  140. package/dist/utils/env.js +2 -2
  141. package/dist/utils/errors.js +3 -3
  142. package/dist/utils/geo.js +1 -1
  143. package/dist/utils/hashes.js +1 -1
  144. package/dist/utils/html.js +1 -1
  145. package/dist/utils/http.js +1 -1
  146. package/dist/utils/json.js +1 -1
  147. package/dist/utils/jwt.js +4 -4
  148. package/dist/utils/maps.js +1 -1
  149. package/dist/utils/node-http.js +1 -1
  150. package/dist/utils/objects.js +3 -3
  151. package/dist/utils/promises.js +5 -5
  152. package/dist/utils/proxies.js +1 -1
  153. package/dist/utils/react.js +3 -3
  154. package/dist/utils/results.js +2 -2
  155. package/dist/utils/stores.js +4 -4
  156. package/dist/utils/strings.js +6 -3
  157. package/dist/utils/strings.js.map +1 -1
  158. package/dist/utils/strings.nicify.test.js +1 -1
  159. package/dist/utils/unicode.js +1 -1
  160. package/dist/utils/urls.js +2 -2
  161. package/dist/utils/uuids.js +1 -1
  162. package/package.json +1 -1
  163. package/dist/esm/interface/adminInterface.js.map +0 -1
  164. package/dist/esm/interface/clientInterface.js.map +0 -1
  165. package/dist/esm/interface/serverInterface.js.map +0 -1
  166. package/dist/interface/adminInterface.js.map +0 -1
  167. package/dist/interface/clientInterface.js.map +0 -1
  168. package/dist/interface/serverInterface.js.map +0 -1
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,860 +17,33 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
- // src/interface/clientInterface.ts
21
- var clientInterface_exports = {};
22
- __export(clientInterface_exports, {
30
+ // src/interface/client-interface.ts
31
+ var client_interface_exports = {};
32
+ __export(client_interface_exports, {
23
33
  StackClientInterface: () => StackClientInterface
24
34
  });
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");
35
+ module.exports = __toCommonJS(client_interface_exports);
36
+ var oauth = __toESM(require("oauth4webapi"));
37
+ var import_known_errors = require("../known-errors.js");
38
+ var import_sessions = require("../sessions.js");
39
+ var import_crypto = require("../utils/crypto.js");
40
+ var import_errors = require("../utils/errors.js");
41
+ var import_globals = require("../utils/globals.js");
42
+ var import_http = require("../utils/http.js");
43
+ var import_objects = require("../utils/objects.js");
44
+ var import_promises = require("../utils/promises.js");
45
+ var import_results = require("../utils/results.js");
46
+ var import_strings = require("../utils/strings.js");
872
47
  var StackClientInterface = class {
873
48
  constructor(options) {
874
49
  this.options = options;
@@ -930,11 +105,11 @@ var StackClientInterface = class {
930
105
  async _createNetworkError(cause, session, requestType) {
931
106
  return new Error(import_strings.deindent`
932
107
  Stack Auth is unable to connect to the server. Please check your internet connection and try again.
933
-
108
+
934
109
  If the problem persists, please contact support and provide a screenshot of your entire browser console.
935
110
 
936
111
  ${cause}
937
-
112
+
938
113
  ${JSON.stringify(await this.runNetworkDiagnostics(session, requestType), null, 2)}
939
114
  `, { cause });
940
115
  }
@@ -970,7 +145,7 @@ var StackClientInterface = class {
970
145
  token_endpoint_auth_method: "client_secret_post"
971
146
  };
972
147
  const rawResponse = await this._networkRetryException(
973
- async () => await refreshTokenGrantRequest(
148
+ async () => await oauth.refreshTokenGrantRequest(
974
149
  as,
975
150
  client,
976
151
  refreshToken.token
@@ -988,8 +163,8 @@ var StackClientInterface = class {
988
163
  const body = await response.data.text();
989
164
  throw new Error(`Failed to send refresh token request: ${response.status} ${body}`);
990
165
  }
991
- const result = await processRefreshTokenResponse(as, client, response.data);
992
- if (isOAuth2Error(result)) {
166
+ const result = await oauth.processRefreshTokenResponse(as, client, response.data);
167
+ if (oauth.isOAuth2Error(result)) {
993
168
  throw new import_errors.StackAssertionError("OAuth error", { result });
994
169
  }
995
170
  if (!result.access_token) {
@@ -1529,6 +704,33 @@ var StackClientInterface = class {
1529
704
  newUser: result.is_new_user
1530
705
  });
1531
706
  }
707
+ async signInWithMfa(totp, code) {
708
+ const res = await this.sendClientRequestAndCatchKnownError(
709
+ "/auth/mfa/sign-in",
710
+ {
711
+ method: "POST",
712
+ headers: {
713
+ "Content-Type": "application/json"
714
+ },
715
+ body: JSON.stringify({
716
+ type: "totp",
717
+ totp,
718
+ code
719
+ })
720
+ },
721
+ null,
722
+ [import_known_errors.KnownErrors.VerificationCodeError]
723
+ );
724
+ if (res.status === "error") {
725
+ return import_results.Result.error(res.error);
726
+ }
727
+ const result = await res.data.json();
728
+ return import_results.Result.ok({
729
+ accessToken: result.access_token,
730
+ refreshToken: result.refresh_token,
731
+ newUser: result.is_new_user
732
+ });
733
+ }
1532
734
  async signInWithPasskey(body) {
1533
735
  const res = await this.sendClientRequestAndCatchKnownError(
1534
736
  "/auth/passkey/sign-in",
@@ -1601,20 +803,20 @@ var StackClientInterface = class {
1601
803
  token_endpoint_auth_method: "client_secret_post"
1602
804
  };
1603
805
  const params = await this._networkRetryException(
1604
- async () => validateAuthResponse(as, client, options.oauthParams, options.state)
806
+ async () => oauth.validateAuthResponse(as, client, options.oauthParams, options.state)
1605
807
  );
1606
- if (isOAuth2Error(params)) {
808
+ if (oauth.isOAuth2Error(params)) {
1607
809
  throw new import_errors.StackAssertionError("Error validating outer OAuth response", { params });
1608
810
  }
1609
- const response = await authorizationCodeGrantRequest(
811
+ const response = await oauth.authorizationCodeGrantRequest(
1610
812
  as,
1611
813
  client,
1612
814
  params,
1613
815
  options.redirectUri,
1614
816
  options.codeVerifier
1615
817
  );
1616
- const result = await processAuthorizationCodeOAuth2Response(as, client, response);
1617
- if (isOAuth2Error(result)) {
818
+ const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response);
819
+ if (oauth.isOAuth2Error(result)) {
1618
820
  if ("code" in result && result.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
1619
821
  throw new import_known_errors.KnownErrors.MultiFactorAuthenticationRequired(result.details.attempt_code);
1620
822
  }
@@ -2062,9 +1264,33 @@ var StackClientInterface = class {
2062
1264
  }
2063
1265
  return await result.data.json();
2064
1266
  }
1267
+ async listNotificationCategories(session) {
1268
+ const response = await this.sendClientRequest(
1269
+ `/emails/notification-preference/me`,
1270
+ {},
1271
+ session
1272
+ );
1273
+ const result = await response.json();
1274
+ return result.items;
1275
+ }
1276
+ async setNotificationsEnabled(notificationCategoryId, enabled, session) {
1277
+ await this.sendClientRequest(
1278
+ `/emails/notification-preference/me/${notificationCategoryId}`,
1279
+ {
1280
+ method: "PATCH",
1281
+ headers: {
1282
+ "content-type": "application/json"
1283
+ },
1284
+ body: JSON.stringify({
1285
+ enabled
1286
+ })
1287
+ },
1288
+ session
1289
+ );
1290
+ }
2065
1291
  };
2066
1292
  // Annotate the CommonJS export names for ESM import in node:
2067
1293
  0 && (module.exports = {
2068
1294
  StackClientInterface
2069
1295
  });
2070
- //# sourceMappingURL=clientInterface.js.map
1296
+ //# sourceMappingURL=client-interface.js.map