bc-api-client 0.1.0-beta.1 → 0.1.0-beta.10

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/dist/index.js CHANGED
@@ -1,597 +1,15 @@
1
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/errors/HTTPError.js
2
- var HTTPError = class extends Error {
3
- response;
4
- request;
5
- options;
6
- constructor(response, request2, options) {
7
- const code = response.status || response.status === 0 ? response.status : "";
8
- const title = response.statusText || "";
9
- const status = `${code} ${title}`.trim();
10
- const reason = status ? `status code ${status}` : "an unknown error";
11
- super(`Request failed with ${reason}: ${request2.method} ${request2.url}`);
12
- this.name = "HTTPError";
13
- this.response = response;
14
- this.request = request2;
15
- this.options = options;
16
- }
17
- };
18
-
19
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/errors/TimeoutError.js
20
- var TimeoutError = class extends Error {
21
- request;
22
- constructor(request2) {
23
- super(`Request timed out: ${request2.method} ${request2.url}`);
24
- this.name = "TimeoutError";
25
- this.request = request2;
26
- }
27
- };
28
-
29
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/core/constants.js
30
- var supportsRequestStreams = (() => {
31
- let duplexAccessed = false;
32
- let hasContentType = false;
33
- const supportsReadableStream = typeof globalThis.ReadableStream === "function";
34
- const supportsRequest = typeof globalThis.Request === "function";
35
- if (supportsReadableStream && supportsRequest) {
36
- try {
37
- hasContentType = new globalThis.Request("https://empty.invalid", {
38
- body: new globalThis.ReadableStream(),
39
- method: "POST",
40
- // @ts-expect-error - Types are outdated.
41
- get duplex() {
42
- duplexAccessed = true;
43
- return "half";
44
- }
45
- }).headers.has("Content-Type");
46
- } catch (error) {
47
- if (error instanceof Error && error.message === "unsupported BodyInit type") {
48
- return false;
49
- }
50
- throw error;
51
- }
52
- }
53
- return duplexAccessed && !hasContentType;
54
- })();
55
- var supportsAbortController = typeof globalThis.AbortController === "function";
56
- var supportsResponseStreams = typeof globalThis.ReadableStream === "function";
57
- var supportsFormData = typeof globalThis.FormData === "function";
58
- var requestMethods = ["get", "post", "put", "patch", "head", "delete"];
59
- var validate = () => void 0;
60
- validate();
61
- var responseTypes = {
62
- json: "application/json",
63
- text: "text/*",
64
- formData: "multipart/form-data",
65
- arrayBuffer: "*/*",
66
- blob: "*/*"
67
- };
68
- var maxSafeTimeout = 2147483647;
69
- var usualFormBoundarySize = new TextEncoder().encode("------WebKitFormBoundaryaxpyiPgbbPti10Rw").length;
70
- var stop = Symbol("stop");
71
- var kyOptionKeys = {
72
- json: true,
73
- parseJson: true,
74
- stringifyJson: true,
75
- searchParams: true,
76
- prefixUrl: true,
77
- retry: true,
78
- timeout: true,
79
- hooks: true,
80
- throwHttpErrors: true,
81
- onDownloadProgress: true,
82
- onUploadProgress: true,
83
- fetch: true
84
- };
85
- var requestOptionsRegistry = {
86
- method: true,
87
- headers: true,
88
- body: true,
89
- mode: true,
90
- credentials: true,
91
- cache: true,
92
- redirect: true,
93
- referrer: true,
94
- referrerPolicy: true,
95
- integrity: true,
96
- keepalive: true,
97
- signal: true,
98
- window: true,
99
- dispatcher: true,
100
- duplex: true,
101
- priority: true
102
- };
103
-
104
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/body.js
105
- var getBodySize = (body) => {
106
- if (!body) {
107
- return 0;
108
- }
109
- if (body instanceof FormData) {
110
- let size = 0;
111
- for (const [key, value] of body) {
112
- size += usualFormBoundarySize;
113
- size += new TextEncoder().encode(`Content-Disposition: form-data; name="${key}"`).length;
114
- size += typeof value === "string" ? new TextEncoder().encode(value).length : value.size;
115
- }
116
- return size;
117
- }
118
- if (body instanceof Blob) {
119
- return body.size;
120
- }
121
- if (body instanceof ArrayBuffer) {
122
- return body.byteLength;
123
- }
124
- if (typeof body === "string") {
125
- return new TextEncoder().encode(body).length;
126
- }
127
- if (body instanceof URLSearchParams) {
128
- return new TextEncoder().encode(body.toString()).length;
129
- }
130
- if ("byteLength" in body) {
131
- return body.byteLength;
132
- }
133
- if (typeof body === "object" && body !== null) {
134
- try {
135
- const jsonString = JSON.stringify(body);
136
- return new TextEncoder().encode(jsonString).length;
137
- } catch {
138
- return 0;
139
- }
140
- }
141
- return 0;
142
- };
143
- var streamResponse = (response, onDownloadProgress) => {
144
- const totalBytes = Number(response.headers.get("content-length")) || 0;
145
- let transferredBytes = 0;
146
- if (response.status === 204) {
147
- if (onDownloadProgress) {
148
- onDownloadProgress({ percent: 1, totalBytes, transferredBytes }, new Uint8Array());
149
- }
150
- return new Response(null, {
151
- status: response.status,
152
- statusText: response.statusText,
153
- headers: response.headers
154
- });
155
- }
156
- return new Response(new ReadableStream({
157
- async start(controller) {
158
- const reader = response.body.getReader();
159
- if (onDownloadProgress) {
160
- onDownloadProgress({ percent: 0, transferredBytes: 0, totalBytes }, new Uint8Array());
161
- }
162
- async function read() {
163
- const { done, value } = await reader.read();
164
- if (done) {
165
- controller.close();
166
- return;
167
- }
168
- if (onDownloadProgress) {
169
- transferredBytes += value.byteLength;
170
- const percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
171
- onDownloadProgress({ percent, transferredBytes, totalBytes }, value);
172
- }
173
- controller.enqueue(value);
174
- await read();
175
- }
176
- await read();
177
- }
178
- }), {
179
- status: response.status,
180
- statusText: response.statusText,
181
- headers: response.headers
182
- });
183
- };
184
- var streamRequest = (request2, onUploadProgress) => {
185
- const totalBytes = getBodySize(request2.body);
186
- let transferredBytes = 0;
187
- return new Request(request2, {
188
- // @ts-expect-error - Types are outdated.
189
- duplex: "half",
190
- body: new ReadableStream({
191
- async start(controller) {
192
- const reader = request2.body instanceof ReadableStream ? request2.body.getReader() : new Response("").body.getReader();
193
- async function read() {
194
- const { done, value } = await reader.read();
195
- if (done) {
196
- if (onUploadProgress) {
197
- onUploadProgress({ percent: 1, transferredBytes, totalBytes: Math.max(totalBytes, transferredBytes) }, new Uint8Array());
198
- }
199
- controller.close();
200
- return;
201
- }
202
- transferredBytes += value.byteLength;
203
- let percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
204
- if (totalBytes < transferredBytes || percent === 1) {
205
- percent = 0.99;
206
- }
207
- if (onUploadProgress) {
208
- onUploadProgress({ percent: Number(percent.toFixed(2)), transferredBytes, totalBytes }, value);
209
- }
210
- controller.enqueue(value);
211
- await read();
212
- }
213
- await read();
214
- }
215
- })
216
- });
217
- };
218
-
219
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/is.js
220
- var isObject = (value) => value !== null && typeof value === "object";
221
-
222
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/merge.js
223
- var validateAndMerge = (...sources) => {
224
- for (const source of sources) {
225
- if ((!isObject(source) || Array.isArray(source)) && source !== void 0) {
226
- throw new TypeError("The `options` argument must be an object");
227
- }
228
- }
229
- return deepMerge({}, ...sources);
230
- };
231
- var mergeHeaders = (source1 = {}, source2 = {}) => {
232
- const result = new globalThis.Headers(source1);
233
- const isHeadersInstance = source2 instanceof globalThis.Headers;
234
- const source = new globalThis.Headers(source2);
235
- for (const [key, value] of source.entries()) {
236
- if (isHeadersInstance && value === "undefined" || value === void 0) {
237
- result.delete(key);
238
- } else {
239
- result.set(key, value);
240
- }
241
- }
242
- return result;
243
- };
244
- function newHookValue(original, incoming, property) {
245
- return Object.hasOwn(incoming, property) && incoming[property] === void 0 ? [] : deepMerge(original[property] ?? [], incoming[property] ?? []);
246
- }
247
- var mergeHooks = (original = {}, incoming = {}) => ({
248
- beforeRequest: newHookValue(original, incoming, "beforeRequest"),
249
- beforeRetry: newHookValue(original, incoming, "beforeRetry"),
250
- afterResponse: newHookValue(original, incoming, "afterResponse"),
251
- beforeError: newHookValue(original, incoming, "beforeError")
252
- });
253
- var deepMerge = (...sources) => {
254
- let returnValue = {};
255
- let headers = {};
256
- let hooks = {};
257
- for (const source of sources) {
258
- if (Array.isArray(source)) {
259
- if (!Array.isArray(returnValue)) {
260
- returnValue = [];
261
- }
262
- returnValue = [...returnValue, ...source];
263
- } else if (isObject(source)) {
264
- for (let [key, value] of Object.entries(source)) {
265
- if (isObject(value) && key in returnValue) {
266
- value = deepMerge(returnValue[key], value);
267
- }
268
- returnValue = { ...returnValue, [key]: value };
269
- }
270
- if (isObject(source.hooks)) {
271
- hooks = mergeHooks(hooks, source.hooks);
272
- returnValue.hooks = hooks;
273
- }
274
- if (isObject(source.headers)) {
275
- headers = mergeHeaders(headers, source.headers);
276
- returnValue.headers = headers;
277
- }
278
- }
279
- }
280
- return returnValue;
281
- };
282
-
283
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/normalize.js
284
- var normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
285
- var retryMethods = ["get", "put", "head", "delete", "options", "trace"];
286
- var retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
287
- var retryAfterStatusCodes = [413, 429, 503];
288
- var defaultRetryOptions = {
289
- limit: 2,
290
- methods: retryMethods,
291
- statusCodes: retryStatusCodes,
292
- afterStatusCodes: retryAfterStatusCodes,
293
- maxRetryAfter: Number.POSITIVE_INFINITY,
294
- backoffLimit: Number.POSITIVE_INFINITY,
295
- delay: (attemptCount) => 0.3 * 2 ** (attemptCount - 1) * 1e3
296
- };
297
- var normalizeRetryOptions = (retry = {}) => {
298
- if (typeof retry === "number") {
299
- return {
300
- ...defaultRetryOptions,
301
- limit: retry
302
- };
303
- }
304
- if (retry.methods && !Array.isArray(retry.methods)) {
305
- throw new Error("retry.methods must be an array");
306
- }
307
- if (retry.statusCodes && !Array.isArray(retry.statusCodes)) {
308
- throw new Error("retry.statusCodes must be an array");
309
- }
310
- return {
311
- ...defaultRetryOptions,
312
- ...retry
313
- };
314
- };
315
-
316
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/timeout.js
317
- async function timeout(request2, init, abortController, options) {
318
- return new Promise((resolve, reject) => {
319
- const timeoutId = setTimeout(() => {
320
- if (abortController) {
321
- abortController.abort();
322
- }
323
- reject(new TimeoutError(request2));
324
- }, options.timeout);
325
- void options.fetch(request2, init).then(resolve).catch(reject).then(() => {
326
- clearTimeout(timeoutId);
327
- });
328
- });
329
- }
330
-
331
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/delay.js
332
- async function delay(ms, { signal }) {
333
- return new Promise((resolve, reject) => {
334
- if (signal) {
335
- signal.throwIfAborted();
336
- signal.addEventListener("abort", abortHandler, { once: true });
337
- }
338
- function abortHandler() {
339
- clearTimeout(timeoutId);
340
- reject(signal.reason);
341
- }
342
- const timeoutId = setTimeout(() => {
343
- signal?.removeEventListener("abort", abortHandler);
344
- resolve();
345
- }, ms);
346
- });
347
- }
348
-
349
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/utils/options.js
350
- var findUnknownOptions = (request2, options) => {
351
- const unknownOptions = {};
352
- for (const key in options) {
353
- if (!(key in requestOptionsRegistry) && !(key in kyOptionKeys) && !(key in request2)) {
354
- unknownOptions[key] = options[key];
355
- }
356
- }
357
- return unknownOptions;
358
- };
359
-
360
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/core/Ky.js
361
- var Ky = class _Ky {
362
- static create(input, options) {
363
- const ky2 = new _Ky(input, options);
364
- const function_ = async () => {
365
- if (typeof ky2._options.timeout === "number" && ky2._options.timeout > maxSafeTimeout) {
366
- throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
367
- }
368
- await Promise.resolve();
369
- let response = await ky2._fetch();
370
- for (const hook of ky2._options.hooks.afterResponse) {
371
- const modifiedResponse = await hook(ky2.request, ky2._options, ky2._decorateResponse(response.clone()));
372
- if (modifiedResponse instanceof globalThis.Response) {
373
- response = modifiedResponse;
374
- }
375
- }
376
- ky2._decorateResponse(response);
377
- if (!response.ok && ky2._options.throwHttpErrors) {
378
- let error = new HTTPError(response, ky2.request, ky2._options);
379
- for (const hook of ky2._options.hooks.beforeError) {
380
- error = await hook(error);
381
- }
382
- throw error;
383
- }
384
- if (ky2._options.onDownloadProgress) {
385
- if (typeof ky2._options.onDownloadProgress !== "function") {
386
- throw new TypeError("The `onDownloadProgress` option must be a function");
387
- }
388
- if (!supportsResponseStreams) {
389
- throw new Error("Streams are not supported in your environment. `ReadableStream` is missing.");
390
- }
391
- return streamResponse(response.clone(), ky2._options.onDownloadProgress);
392
- }
393
- return response;
394
- };
395
- const isRetriableMethod = ky2._options.retry.methods.includes(ky2.request.method.toLowerCase());
396
- const result = (isRetriableMethod ? ky2._retry(function_) : function_()).finally(async () => {
397
- if (!ky2.request.bodyUsed) {
398
- await ky2.request.body?.cancel();
399
- }
400
- });
401
- for (const [type, mimeType] of Object.entries(responseTypes)) {
402
- result[type] = async () => {
403
- ky2.request.headers.set("accept", ky2.request.headers.get("accept") || mimeType);
404
- const response = await result;
405
- if (type === "json") {
406
- if (response.status === 204) {
407
- return "";
408
- }
409
- const arrayBuffer = await response.clone().arrayBuffer();
410
- const responseSize = arrayBuffer.byteLength;
411
- if (responseSize === 0) {
412
- return "";
413
- }
414
- if (options.parseJson) {
415
- return options.parseJson(await response.text());
416
- }
417
- }
418
- return response[type]();
419
- };
420
- }
421
- return result;
422
- }
423
- request;
424
- abortController;
425
- _retryCount = 0;
426
- _input;
427
- _options;
428
- // eslint-disable-next-line complexity
429
- constructor(input, options = {}) {
430
- this._input = input;
431
- this._options = {
432
- ...options,
433
- headers: mergeHeaders(this._input.headers, options.headers),
434
- hooks: mergeHooks({
435
- beforeRequest: [],
436
- beforeRetry: [],
437
- beforeError: [],
438
- afterResponse: []
439
- }, options.hooks),
440
- method: normalizeRequestMethod(options.method ?? this._input.method ?? "GET"),
441
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
442
- prefixUrl: String(options.prefixUrl || ""),
443
- retry: normalizeRetryOptions(options.retry),
444
- throwHttpErrors: options.throwHttpErrors !== false,
445
- timeout: options.timeout ?? 1e4,
446
- fetch: options.fetch ?? globalThis.fetch.bind(globalThis)
447
- };
448
- if (typeof this._input !== "string" && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
449
- throw new TypeError("`input` must be a string, URL, or Request");
450
- }
451
- if (this._options.prefixUrl && typeof this._input === "string") {
452
- if (this._input.startsWith("/")) {
453
- throw new Error("`input` must not begin with a slash when using `prefixUrl`");
454
- }
455
- if (!this._options.prefixUrl.endsWith("/")) {
456
- this._options.prefixUrl += "/";
457
- }
458
- this._input = this._options.prefixUrl + this._input;
459
- }
460
- if (supportsAbortController) {
461
- const originalSignal = this._options.signal ?? this._input.signal;
462
- this.abortController = new globalThis.AbortController();
463
- this._options.signal = originalSignal ? AbortSignal.any([originalSignal, this.abortController.signal]) : this.abortController.signal;
464
- }
465
- if (supportsRequestStreams) {
466
- this._options.duplex = "half";
467
- }
468
- if (this._options.json !== void 0) {
469
- this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json);
470
- this._options.headers.set("content-type", this._options.headers.get("content-type") ?? "application/json");
471
- }
472
- this.request = new globalThis.Request(this._input, this._options);
473
- if (this._options.searchParams) {
474
- const textSearchParams = typeof this._options.searchParams === "string" ? this._options.searchParams.replace(/^\?/, "") : new URLSearchParams(this._options.searchParams).toString();
475
- const searchParams = "?" + textSearchParams;
476
- const url = this.request.url.replace(/(?:\?.*?)?(?=#|$)/, searchParams);
477
- if ((supportsFormData && this._options.body instanceof globalThis.FormData || this._options.body instanceof URLSearchParams) && !(this._options.headers && this._options.headers["content-type"])) {
478
- this.request.headers.delete("content-type");
479
- }
480
- this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
481
- }
482
- if (this._options.onUploadProgress) {
483
- if (typeof this._options.onUploadProgress !== "function") {
484
- throw new TypeError("The `onUploadProgress` option must be a function");
485
- }
486
- if (!supportsRequestStreams) {
487
- throw new Error("Request streams are not supported in your environment. The `duplex` option for `Request` is not available.");
488
- }
489
- const originalBody = this.request.body;
490
- if (originalBody) {
491
- this.request = streamRequest(this.request, this._options.onUploadProgress);
492
- }
493
- }
494
- }
495
- _calculateRetryDelay(error) {
496
- this._retryCount++;
497
- if (this._retryCount > this._options.retry.limit || error instanceof TimeoutError) {
498
- throw error;
499
- }
500
- if (error instanceof HTTPError) {
501
- if (!this._options.retry.statusCodes.includes(error.response.status)) {
502
- throw error;
503
- }
504
- const retryAfter = error.response.headers.get("Retry-After") ?? error.response.headers.get("RateLimit-Reset") ?? error.response.headers.get("X-RateLimit-Reset") ?? error.response.headers.get("X-Rate-Limit-Reset");
505
- if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
506
- let after = Number(retryAfter) * 1e3;
507
- if (Number.isNaN(after)) {
508
- after = Date.parse(retryAfter) - Date.now();
509
- } else if (after >= Date.parse("2024-01-01")) {
510
- after -= Date.now();
511
- }
512
- const max = this._options.retry.maxRetryAfter ?? after;
513
- return after < max ? after : max;
514
- }
515
- if (error.response.status === 413) {
516
- throw error;
517
- }
518
- }
519
- const retryDelay = this._options.retry.delay(this._retryCount);
520
- return Math.min(this._options.retry.backoffLimit, retryDelay);
521
- }
522
- _decorateResponse(response) {
523
- if (this._options.parseJson) {
524
- response.json = async () => this._options.parseJson(await response.text());
525
- }
526
- return response;
527
- }
528
- async _retry(function_) {
529
- try {
530
- return await function_();
531
- } catch (error) {
532
- const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
533
- if (this._retryCount < 1) {
534
- throw error;
535
- }
536
- await delay(ms, { signal: this._options.signal });
537
- for (const hook of this._options.hooks.beforeRetry) {
538
- const hookResult = await hook({
539
- request: this.request,
540
- options: this._options,
541
- error,
542
- retryCount: this._retryCount
543
- });
544
- if (hookResult === stop) {
545
- return;
546
- }
547
- }
548
- return this._retry(function_);
549
- }
550
- }
551
- async _fetch() {
552
- for (const hook of this._options.hooks.beforeRequest) {
553
- const result = await hook(this.request, this._options);
554
- if (result instanceof Request) {
555
- this.request = result;
556
- break;
557
- }
558
- if (result instanceof Response) {
559
- return result;
560
- }
561
- }
562
- const nonRequestOptions = findUnknownOptions(this.request, this._options);
563
- const mainRequest = this.request;
564
- this.request = mainRequest.clone();
565
- if (this._options.timeout === false) {
566
- return this._options.fetch(mainRequest, nonRequestOptions);
567
- }
568
- return timeout(mainRequest, nonRequestOptions, this.abortController, this._options);
569
- }
570
- };
571
-
572
- // node_modules/.pnpm/ky@1.8.1/node_modules/ky/distribution/index.js
573
- var createInstance = (defaults) => {
574
- const ky2 = (input, options) => Ky.create(input, validateAndMerge(defaults, options));
575
- for (const method of requestMethods) {
576
- ky2[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
577
- }
578
- ky2.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
579
- ky2.extend = (newDefaults) => {
580
- if (typeof newDefaults === "function") {
581
- newDefaults = newDefaults(defaults ?? {});
582
- }
583
- return createInstance(validateAndMerge(defaults, newDefaults));
584
- };
585
- ky2.stop = stop;
586
- return ky2;
587
- };
588
- var ky = createInstance();
589
- var distribution_default = ky;
590
-
591
1
  // src/net.ts
2
+ import ky, { HTTPError } from "ky";
3
+ var Methods = {
4
+ GET: "GET",
5
+ POST: "POST",
6
+ PUT: "PUT",
7
+ DELETE: "DELETE"
8
+ };
9
+ var BASE_URL = "https://api.bigcommerce.com/stores/";
592
10
  var CONFIG = {
593
11
  /** Base URL for BigCommerce API */
594
- BASE_URL: "https://api.bigcommerce.com/stores/",
12
+ BASE_URL,
595
13
  /** Default API version to use */
596
14
  DEFAULT_VERSION: "v3",
597
15
  /** Maximum delay in milliseconds for rate limit retries */
@@ -603,26 +21,26 @@ var CONFIG = {
603
21
  /** Rate limit header names */
604
22
  HEADERS: {
605
23
  /** Time window for rate limiting in milliseconds */
606
- WINDOW: "X-Rate-Limit-Time-Window-Ms",
24
+ WINDOW: "x-rate-limit-time-window-ms",
607
25
  /** Time to wait before retrying after rate limit in milliseconds */
608
- RETRY_AFTER: "X-Rate-Limit-Time-Reset-Ms",
26
+ RETRY_AFTER: "x-rate-limit-time-reset-ms",
609
27
  /** Total request quota for the time window */
610
- REQUEST_QUOTA: "X-Rate-Limit-Requests-Quota",
28
+ REQUEST_QUOTA: "x-rate-limit-requests-quota",
611
29
  /** Number of requests remaining in the current window */
612
- REQUESTS_LEFT: "X-Rate-Limit-Requests-Left"
30
+ REQUESTS_LEFT: "x-rate-limit-requests-left"
613
31
  }
614
32
  };
615
33
  var RequestError = class extends Error {
616
- constructor(status, message2, data, cause) {
617
- super(message2, { cause });
34
+ constructor(status, message, data, cause) {
35
+ super(message, { cause });
618
36
  this.status = status;
619
- this.message = message2;
37
+ this.message = message;
620
38
  this.data = data;
621
39
  this.cause = cause;
622
40
  }
623
41
  };
624
42
  var request = async (options) => {
625
- const { maxDelay = CONFIG.DEFAULT_MAX_DELAY, maxRetries = CONFIG.DEFAULT_MAX_RETRIES } = options;
43
+ const { maxDelay = CONFIG.DEFAULT_MAX_DELAY, maxRetries = CONFIG.DEFAULT_MAX_RETRIES, logger } = options;
626
44
  let retries = 0;
627
45
  let lastError = null;
628
46
  while (retries < maxRetries) {
@@ -634,6 +52,11 @@ var request = async (options) => {
634
52
  if (err.status === 429 && typeof err.data === "object" && err.data !== null && "headers" in err.data) {
635
53
  const headers = err.data.headers;
636
54
  const retryAfter = Number.parseInt(headers[CONFIG.HEADERS.RETRY_AFTER]);
55
+ logger?.debug({
56
+ retryAfter,
57
+ retries,
58
+ remaining: headers[CONFIG.HEADERS.REQUESTS_LEFT]
59
+ }, "Rate limit hit, retrying");
637
60
  if (Number.isNaN(retryAfter)) {
638
61
  throw new RequestError(
639
62
  err.status,
@@ -643,6 +66,10 @@ var request = async (options) => {
643
66
  );
644
67
  }
645
68
  if (retryAfter > maxDelay) {
69
+ logger?.warn({
70
+ retryAfter,
71
+ maxDelay
72
+ }, "Rate limit delay exceeds maximum allowed delay");
646
73
  throw new RequestError(
647
74
  err.status,
648
75
  `Rate limit exceeded: ${retryAfter}ms, ${err.message}`,
@@ -657,17 +84,30 @@ var request = async (options) => {
657
84
  throw err;
658
85
  }
659
86
  }
87
+ logger?.error({
88
+ retries,
89
+ error: lastError
90
+ }, "Request failed after maximum retries");
660
91
  throw lastError ?? new RequestError(500, "Failed to make request", "Too many retries after rate limit");
661
92
  };
662
93
  var safeRequest = async (options) => {
94
+ const { logger } = options;
663
95
  let res;
664
96
  try {
665
97
  res = await call(options);
666
- } catch (_error) {
667
- if (_error instanceof RequestError) {
668
- throw _error;
98
+ } catch (error) {
99
+ if (error instanceof RequestError) {
100
+ throw error;
101
+ }
102
+ if (!(error instanceof HTTPError)) {
103
+ logger?.error({
104
+ error: error instanceof Error ? {
105
+ name: error.name,
106
+ message: error.message
107
+ } : error
108
+ }, "Unexpected error during request");
109
+ throw error;
669
110
  }
670
- const error = _error;
671
111
  let data;
672
112
  let errorMessage = error.message;
673
113
  try {
@@ -682,12 +122,16 @@ var safeRequest = async (options) => {
682
122
  } catch {
683
123
  data = "Failed to read error response";
684
124
  }
125
+ logger?.error({
126
+ status: error?.response?.status,
127
+ errorMessage
128
+ }, "HTTP error during request");
685
129
  throw new RequestError(
686
- error.response.status,
130
+ error?.response?.status ?? 500,
687
131
  errorMessage,
688
132
  {
689
133
  data,
690
- headers: Object.fromEntries(error.response.headers.entries())
134
+ headers: Object.fromEntries(error?.response?.headers?.entries() ?? [])
691
135
  },
692
136
  error
693
137
  );
@@ -699,6 +143,13 @@ var safeRequest = async (options) => {
699
143
  try {
700
144
  return JSON.parse(text);
701
145
  } catch (error) {
146
+ logger?.error({
147
+ status: res.status,
148
+ error: error instanceof Error ? {
149
+ name: error.name,
150
+ message: error.message
151
+ } : error
152
+ }, "Failed to parse response");
702
153
  throw new RequestError(
703
154
  res.status,
704
155
  `Failed to parse response: ${text}`,
@@ -707,12 +158,16 @@ var safeRequest = async (options) => {
707
158
  );
708
159
  }
709
160
  };
710
- var call = (options) => {
711
- const { storeHash, accessToken, endpoint, method = "GET", body, version = CONFIG.DEFAULT_VERSION, query } = options;
161
+ var call = async (options) => {
162
+ const { storeHash, accessToken, endpoint, method = "GET", body, version = CONFIG.DEFAULT_VERSION, query, logger } = options;
712
163
  const url = `${CONFIG.BASE_URL}${storeHash}/${version}/${endpoint.replace(/^\//, "")}`;
713
164
  const searchParams = query ? new URLSearchParams(query).toString() : "";
714
165
  const fullUrl = searchParams ? `${url}?${searchParams}` : url;
715
166
  if (fullUrl.length > CONFIG.MAX_URL_LENGTH) {
167
+ logger?.error({
168
+ urlLength: fullUrl.length,
169
+ maxLength: CONFIG.MAX_URL_LENGTH
170
+ }, "URL length exceeds maximum allowed length");
716
171
  throw new RequestError(
717
172
  400,
718
173
  "URL too long",
@@ -728,129 +183,10 @@ var call = (options) => {
728
183
  },
729
184
  json: body
730
185
  };
731
- return distribution_default(fullUrl, request2);
186
+ const response = await ky(fullUrl, request2);
187
+ return response;
732
188
  };
733
189
 
734
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-ANXBDSUI.js
735
- var e = { done: true, hasNext: false };
736
- var s = { done: false, hasNext: false };
737
- var a = () => e;
738
-
739
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-3GOCSNFN.js
740
- function C(t, ...o2) {
741
- let n = t, u3 = o2.map((e2) => "lazy" in e2 ? y(e2) : void 0), p = 0;
742
- for (; p < o2.length; ) {
743
- if (u3[p] === void 0 || !B(n)) {
744
- let i2 = o2[p];
745
- n = i2(n), p += 1;
746
- continue;
747
- }
748
- let r = [];
749
- for (let i2 = p; i2 < o2.length; i2++) {
750
- let l = u3[i2];
751
- if (l === void 0 || (r.push(l), l.isSingle)) break;
752
- }
753
- let a3 = [];
754
- for (let i2 of n) if (f(i2, a3, r)) break;
755
- let { isSingle: s4 } = r.at(-1);
756
- n = s4 ? a3[0] : a3, p += r.length;
757
- }
758
- return n;
759
- }
760
- function f(t, o2, n) {
761
- if (n.length === 0) return o2.push(t), false;
762
- let u3 = t, p = s, e2 = false;
763
- for (let [r, a3] of n.entries()) {
764
- let { index: s4, items: i2 } = a3;
765
- if (i2.push(u3), p = a3(u3, s4, i2), a3.index += 1, p.hasNext) {
766
- if (p.hasMany ?? false) {
767
- for (let l of p.next) if (f(l, o2, n.slice(r + 1))) return true;
768
- return e2;
769
- }
770
- u3 = p.next;
771
- }
772
- if (!p.hasNext) break;
773
- p.done && (e2 = true);
774
- }
775
- return p.hasNext && o2.push(u3), e2;
776
- }
777
- function y(t) {
778
- let { lazy: o2, lazyArgs: n } = t, u3 = o2(...n);
779
- return Object.assign(u3, { isSingle: o2.single ?? false, index: 0, items: [] });
780
- }
781
- function B(t) {
782
- return typeof t == "string" || typeof t == "object" && t !== null && Symbol.iterator in t;
783
- }
784
-
785
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-LFJW7BOT.js
786
- function y2(t, i2) {
787
- let a3 = i2.length - t.length;
788
- if (a3 === 1) {
789
- let [n, ...r] = i2;
790
- return C(n, { lazy: t, lazyArgs: r });
791
- }
792
- if (a3 === 0) {
793
- let n = { lazy: t, lazyArgs: i2 };
794
- return Object.assign((e2) => C(e2, n), n);
795
- }
796
- throw new Error("Wrong number of arguments");
797
- }
798
-
799
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-D6FCK2GA.js
800
- function u(o2, n, a3) {
801
- let t = (r) => o2(r, ...n);
802
- return a3 === void 0 ? t : Object.assign(t, { lazy: a3, lazyArgs: n });
803
- }
804
-
805
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-WIMGWYZL.js
806
- function u2(r, n, o2) {
807
- let a3 = r.length - n.length;
808
- if (a3 === 0) return r(...n);
809
- if (a3 === 1) return u(r, n, o2);
810
- throw new Error("Wrong number of arguments");
811
- }
812
-
813
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-ENS7GPLZ.js
814
- function a2(...r) {
815
- return u2(o, r);
816
- }
817
- function o(r, t) {
818
- let e2 = [];
819
- for (let n = r; n < t; n++) e2.push(n);
820
- return e2;
821
- }
822
-
823
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-ICBBHOCR.js
824
- function s2(...t) {
825
- return y2(i, t);
826
- }
827
- function i(t) {
828
- if (t.length === 0) return a;
829
- let n = /* @__PURE__ */ new Map();
830
- for (let r of t) n.set(r, (n.get(r) ?? 0) + 1);
831
- return (r) => {
832
- let e2 = n.get(r);
833
- return e2 === void 0 || e2 === 0 ? s : (e2 === 1 ? n.delete(r) : n.set(r, e2 - 1), { hasNext: true, next: r, done: n.size === 0 });
834
- };
835
- }
836
-
837
- // node_modules/.pnpm/remeda@2.21.3/node_modules/remeda/dist/chunk-WFMWIRTS.js
838
- function f2(...e2) {
839
- return u2(s3, e2);
840
- }
841
- function s3(e2, n) {
842
- if (n < 1) throw new RangeError(`chunk: A chunk size of '${n.toString()}' would result in an infinite array`);
843
- if (e2.length === 0) return [];
844
- if (n >= e2.length) return [[...e2]];
845
- let i2 = Math.ceil(e2.length / n), u3 = new Array(i2);
846
- if (n === 1) for (let [r, t] of e2.entries()) u3[r] = [t];
847
- else for (let r = 0; r < i2; r += 1) {
848
- let t = r * n;
849
- u3[r] = e2.slice(t, t + n);
850
- }
851
- return u3;
852
- }
853
-
854
190
  // src/util.ts
855
191
  var chunkStrLength = (items, options = {}) => {
856
192
  const { maxLength = 2048, chunkLength = 250, offset = 0, separatorSize = 1 } = options;
@@ -883,42 +219,109 @@ var chunkStrLength = (items, options = {}) => {
883
219
 
884
220
  // src/client.ts
885
221
  var MAX_PAGE_SIZE = 250;
222
+ var DEFAULT_CONCURRENCY = 10;
223
+ function chunkArray(array, size) {
224
+ return Array.from(
225
+ { length: Math.ceil(array.length / size) },
226
+ (_, i) => array.slice(i * size, i * size + size)
227
+ );
228
+ }
229
+ function rangeArray(start, end) {
230
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
231
+ }
886
232
  var BigCommerceClient = class {
233
+ /**
234
+ * Creates a new BigCommerce client instance
235
+ * @param config - Configuration options for the client
236
+ * @param config.storeHash - The store hash to use for the client
237
+ * @param config.accessToken - The API access token to use for the client
238
+ * @param config.maxRetries - The maximum number of retries for rate limit errors (default: 5)
239
+ * @param config.maxDelay - Maximum time to wait to retry in case of rate limit errors in milliseconds (default: 60000 - 1 minute). If `X-Rate-Limit-Time-Reset-Ms` header is higher than `maxDelay`, the request will fail immediately.
240
+ * @param config.concurrency - The default concurrency for concurrent methods (default: 10)
241
+ * @param config.skipErrors - Whether to skip errors during concurrent requests (default: false)
242
+ * @param config.logger - Optional logger instance for debugging and error tracking
243
+ */
887
244
  constructor(config) {
888
245
  this.config = config;
889
246
  }
890
- async get(options) {
247
+ /**
248
+ * Makes a GET request to the BigCommerce API
249
+ * @param endpoint - The API endpoint to request
250
+ * @param options.query - Query parameters to include in the request
251
+ * @param options.version - API version to use (v2 or v3) (default: v3)
252
+ * @returns Promise resolving to the response data of type `R`
253
+ */
254
+ async get(endpoint, options) {
891
255
  return request({
892
- ...options,
256
+ endpoint,
893
257
  method: "GET",
258
+ ...options,
894
259
  ...this.config
895
260
  });
896
261
  }
897
- async post(options) {
262
+ /**
263
+ * Makes a POST request to the BigCommerce API
264
+ * @param endpoint - The API endpoint to request
265
+ * @param options.query - Query parameters to include in the request
266
+ * @param options.version - API version to use (v2 or v3) (default: v3)
267
+ * @param options.body - Request body data of type `T`
268
+ * @returns Promise resolving to the response data of type `R`
269
+ */
270
+ async post(endpoint, options) {
898
271
  return request({
899
- ...options,
272
+ endpoint,
900
273
  method: "POST",
274
+ ...options,
901
275
  ...this.config
902
276
  });
903
277
  }
904
- async put(options) {
278
+ /**
279
+ * Makes a PUT request to the BigCommerce API
280
+ * @param endpoint - The API endpoint to request
281
+ * @param options.query - Query parameters to include in the request
282
+ * @param options.version - API version to use (v2 or v3) (default: v3)
283
+ * @param options.body - Request body data of type `T`
284
+ * @returns Promise resolving to the response data of type `R`
285
+ */
286
+ async put(endpoint, options) {
905
287
  return request({
906
- ...options,
288
+ endpoint,
907
289
  method: "PUT",
290
+ ...options,
908
291
  ...this.config
909
292
  });
910
293
  }
911
- async delete(endpoint) {
294
+ /**
295
+ * Makes a DELETE request to the BigCommerce API
296
+ * @param endpoint - The API endpoint to delete
297
+ * @param options.version - API version to use (v2 or v3) (default: v3)
298
+ * @returns Promise resolving to void
299
+ */
300
+ async delete(endpoint, options) {
912
301
  await request({
913
302
  endpoint,
914
303
  method: "DELETE",
304
+ ...options,
915
305
  ...this.config
916
306
  });
917
307
  }
308
+ /**
309
+ * Executes multiple requests concurrently with controlled concurrency
310
+ * @param requests - Array of request options to execute
311
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
312
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
313
+ * @returns Promise resolving to array of response data
314
+ */
918
315
  async concurrent(requests, options) {
919
- const chunks = f2(requests, options.concurrency ?? 10);
920
- const skipErrors = options.skipErrors ?? false;
316
+ const chunkSize = options?.concurrency ?? this.config.concurrency ?? DEFAULT_CONCURRENCY;
317
+ const chunks = chunkArray(requests, chunkSize);
318
+ const skipErrors = options?.skipErrors ?? this.config.skipErrors ?? false;
921
319
  const results = [];
320
+ this.config.logger?.debug({
321
+ totalRequests: requests.length,
322
+ chunkSize,
323
+ chunks: chunks.length
324
+ }, "Starting concurrent requests");
922
325
  for (const chunk of chunks) {
923
326
  const responses = await Promise.allSettled(
924
327
  chunk.map(
@@ -935,14 +338,28 @@ var BigCommerceClient = class {
935
338
  if (!skipErrors) {
936
339
  throw response.reason;
937
340
  } else {
938
- console.warn(`Error in concurrent request: ${response.reason}`);
341
+ this.config.logger?.warn({
342
+ error: response.reason instanceof Error ? {
343
+ name: response.reason.name,
344
+ message: response.reason.message
345
+ } : response.reason
346
+ }, "Error in concurrent request");
939
347
  }
940
348
  }
941
349
  });
942
350
  }
943
351
  return results;
944
352
  }
945
- async collect(options) {
353
+ /**
354
+ * Collects all pages of data from a paginated v3 API endpoint.
355
+ * This method pulls the first page and uses pagination meta to collect the remaining pages concurrently.
356
+ * @param endpoint - The API endpoint to request
357
+ * @param options.query - Query parameters to include in the request
358
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
359
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
360
+ * @returns Promise resolving to array of all items across all pages
361
+ */
362
+ async collect(endpoint, options) {
946
363
  if (options.query) {
947
364
  if (!options.query.limit) {
948
365
  options.query.limit = MAX_PAGE_SIZE.toString();
@@ -950,24 +367,44 @@ var BigCommerceClient = class {
950
367
  } else {
951
368
  options.query = { limit: MAX_PAGE_SIZE.toString() };
952
369
  }
953
- const first = await this.get(options);
370
+ const first = await this.get(endpoint, options);
954
371
  if (!Array.isArray(first.data) || !first?.meta?.pagination?.total_pages) {
955
372
  return first.data;
956
373
  }
957
374
  const results = [...first.data];
958
375
  const pages = first.meta.pagination.total_pages;
959
- const remainingPages = a2(2, pages + 1);
960
- const requests = remainingPages.map((page) => ({
961
- ...options,
962
- query: { ...options.query, page: page.toString() }
963
- }));
964
- const responses = await this.concurrent(requests, options);
965
- responses.forEach((response) => {
966
- results.push(...response.data);
967
- });
376
+ if (pages > 1) {
377
+ this.config.logger?.debug({
378
+ totalPages: pages,
379
+ itemsPerPage: first.data.length
380
+ }, "Collecting remaining pages");
381
+ const pageRequests = rangeArray(2, pages).map((page) => ({
382
+ endpoint,
383
+ method: "GET",
384
+ query: {
385
+ ...options.query,
386
+ page: page.toString()
387
+ }
388
+ }));
389
+ const remainingPages = await this.concurrent(pageRequests, options);
390
+ remainingPages.forEach((page) => {
391
+ if (Array.isArray(page.data)) {
392
+ results.push(...page.data);
393
+ }
394
+ });
395
+ }
968
396
  return results;
969
397
  }
970
- async collectV2(options) {
398
+ /**
399
+ * Collects all pages of data from a paginated v2 API endpoint.
400
+ * This method simply pulls all pages concurrently until a 204 is returned in a batch.
401
+ * @param endpoint - The API endpoint to request
402
+ * @param options.query - Query parameters to include in the request
403
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
404
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
405
+ * @returns Promise resolving to array of all items across all pages
406
+ */
407
+ async collectV2(endpoint, options) {
971
408
  if (options.query) {
972
409
  if (!options.query.limit) {
973
410
  options.query.limit = MAX_PAGE_SIZE.toString();
@@ -978,16 +415,17 @@ var BigCommerceClient = class {
978
415
  let done = false;
979
416
  const results = [];
980
417
  let page = 1;
981
- const concurrency = options.concurrency ?? 10;
418
+ const concurrency = options.concurrency ?? this.config.concurrency ?? DEFAULT_CONCURRENCY;
982
419
  while (!done) {
983
- const pages = a2(page, page + concurrency);
420
+ const pages = rangeArray(page, page + concurrency);
984
421
  page += concurrency;
985
422
  const requests = pages.map((page2) => ({
986
423
  ...options,
424
+ endpoint,
987
425
  version: "v2",
988
426
  query: { ...options.query, page: page2.toString() }
989
427
  }));
990
- const responses = await Promise.allSettled(requests.map((request2) => this.get(request2)));
428
+ const responses = await Promise.allSettled(requests.map((request2) => this.get(endpoint, request2)));
991
429
  responses.forEach((response) => {
992
430
  if (response.status === "fulfilled") {
993
431
  if (response.value) {
@@ -999,10 +437,15 @@ var BigCommerceClient = class {
999
437
  if (response.reason instanceof RequestError && response.reason.status === 404) {
1000
438
  done = true;
1001
439
  } else {
1002
- if (!options.skipErrors) {
440
+ if (!(options.skipErrors ?? this.config.skipErrors ?? false)) {
1003
441
  throw response.reason;
1004
442
  } else {
1005
- console.warn(`Error in collectV2: ${response.reason}`);
443
+ this.config.logger?.warn({
444
+ error: response.reason instanceof Error ? {
445
+ name: response.reason.name,
446
+ message: response.reason.message
447
+ } : response.reason
448
+ }, "Error in collectV2");
1006
449
  }
1007
450
  }
1008
451
  }
@@ -1010,7 +453,20 @@ var BigCommerceClient = class {
1010
453
  }
1011
454
  return results;
1012
455
  }
1013
- async query(options) {
456
+ /**
457
+ * Queries multiple values against a single field using the v3 API.
458
+ * If the url + query params are too long, the query will be chunked. Otherwise, this method acts like `collect`.
459
+ * This method does not check for uniqueness of the `values` array.
460
+ *
461
+ * @param endpoint - The API endpoint to request
462
+ * @param options.key - The field name to query against e.g. `sku:in`
463
+ * @param options.values - Array of values to query for e.g. `['123', '456', ...]`
464
+ * @param options.query - Additional query parameters
465
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
466
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
467
+ * @returns Promise resolving to array of matching items
468
+ */
469
+ async query(endpoint, options) {
1014
470
  if (options.query) {
1015
471
  if (!options.query.limit) {
1016
472
  options.query.limit = MAX_PAGE_SIZE.toString();
@@ -1018,12 +474,21 @@ var BigCommerceClient = class {
1018
474
  } else {
1019
475
  options.query = { limit: MAX_PAGE_SIZE.toString() };
1020
476
  }
477
+ const { limit: _, ...restQuery } = options.query;
478
+ const fullUrl = `${BASE_URL}${this.config.storeHash}/v3/${endpoint}?${new URLSearchParams(restQuery).toString()}`;
1021
479
  const queryStr = options.values.map((value) => `${value}`);
1022
480
  const chunks = chunkStrLength(queryStr, {
1023
- chunkLength: MAX_PAGE_SIZE
481
+ offset: fullUrl.length,
482
+ chunkLength: Number.parseInt(options.query?.limit) || MAX_PAGE_SIZE
1024
483
  });
484
+ this.config.logger?.debug({
485
+ totalValues: options.values.length,
486
+ chunks: chunks.length,
487
+ valuesPerChunk: chunks[0]?.length
488
+ }, "Querying with chunked values");
1025
489
  const requests = chunks.map((chunk) => ({
1026
490
  ...options,
491
+ endpoint,
1027
492
  query: { ...options.query, [options.key]: chunk.join(",") }
1028
493
  }));
1029
494
  const responses = await this.concurrent(requests, options);
@@ -1031,1092 +496,38 @@ var BigCommerceClient = class {
1031
496
  }
1032
497
  };
1033
498
 
1034
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/buffer_utils.js
1035
- var encoder = new TextEncoder();
1036
- var decoder = new TextDecoder();
1037
- var MAX_INT32 = 2 ** 32;
1038
- function concat(...buffers) {
1039
- const size = buffers.reduce((acc, { length }) => acc + length, 0);
1040
- const buf = new Uint8Array(size);
1041
- let i2 = 0;
1042
- for (const buffer of buffers) {
1043
- buf.set(buffer, i2);
1044
- i2 += buffer.length;
1045
- }
1046
- return buf;
1047
- }
1048
-
1049
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/base64.js
1050
- function decodeBase64(encoded) {
1051
- if (Uint8Array.fromBase64) {
1052
- return Uint8Array.fromBase64(encoded);
1053
- }
1054
- const binary = atob(encoded);
1055
- const bytes = new Uint8Array(binary.length);
1056
- for (let i2 = 0; i2 < binary.length; i2++) {
1057
- bytes[i2] = binary.charCodeAt(i2);
1058
- }
1059
- return bytes;
1060
- }
1061
-
1062
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/util/base64url.js
1063
- function decode(input) {
1064
- if (Uint8Array.fromBase64) {
1065
- return Uint8Array.fromBase64(typeof input === "string" ? input : decoder.decode(input), {
1066
- alphabet: "base64url"
1067
- });
1068
- }
1069
- let encoded = input;
1070
- if (encoded instanceof Uint8Array) {
1071
- encoded = decoder.decode(encoded);
1072
- }
1073
- encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "");
1074
- try {
1075
- return decodeBase64(encoded);
1076
- } catch {
1077
- throw new TypeError("The input to be decoded is not correctly encoded.");
1078
- }
1079
- }
1080
-
1081
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/util/errors.js
1082
- var JOSEError = class extends Error {
1083
- static code = "ERR_JOSE_GENERIC";
1084
- code = "ERR_JOSE_GENERIC";
1085
- constructor(message2, options) {
1086
- super(message2, options);
1087
- this.name = this.constructor.name;
1088
- Error.captureStackTrace?.(this, this.constructor);
1089
- }
1090
- };
1091
- var JWTClaimValidationFailed = class extends JOSEError {
1092
- static code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
1093
- code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
1094
- claim;
1095
- reason;
1096
- payload;
1097
- constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
1098
- super(message2, { cause: { claim, reason, payload } });
1099
- this.claim = claim;
1100
- this.reason = reason;
1101
- this.payload = payload;
1102
- }
1103
- };
1104
- var JWTExpired = class extends JOSEError {
1105
- static code = "ERR_JWT_EXPIRED";
1106
- code = "ERR_JWT_EXPIRED";
1107
- claim;
1108
- reason;
1109
- payload;
1110
- constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
1111
- super(message2, { cause: { claim, reason, payload } });
1112
- this.claim = claim;
1113
- this.reason = reason;
1114
- this.payload = payload;
1115
- }
1116
- };
1117
- var JOSEAlgNotAllowed = class extends JOSEError {
1118
- static code = "ERR_JOSE_ALG_NOT_ALLOWED";
1119
- code = "ERR_JOSE_ALG_NOT_ALLOWED";
1120
- };
1121
- var JOSENotSupported = class extends JOSEError {
1122
- static code = "ERR_JOSE_NOT_SUPPORTED";
1123
- code = "ERR_JOSE_NOT_SUPPORTED";
1124
- };
1125
- var JWSInvalid = class extends JOSEError {
1126
- static code = "ERR_JWS_INVALID";
1127
- code = "ERR_JWS_INVALID";
1128
- };
1129
- var JWTInvalid = class extends JOSEError {
1130
- static code = "ERR_JWT_INVALID";
1131
- code = "ERR_JWT_INVALID";
1132
- };
1133
- var JWSSignatureVerificationFailed = class extends JOSEError {
1134
- static code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
1135
- code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
1136
- constructor(message2 = "signature verification failed", options) {
1137
- super(message2, options);
1138
- }
1139
- };
1140
-
1141
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/crypto_key.js
1142
- function unusable(name, prop = "algorithm.name") {
1143
- return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
1144
- }
1145
- function isAlgorithm(algorithm, name) {
1146
- return algorithm.name === name;
1147
- }
1148
- function getHashLength(hash) {
1149
- return parseInt(hash.name.slice(4), 10);
1150
- }
1151
- function getNamedCurve(alg) {
1152
- switch (alg) {
1153
- case "ES256":
1154
- return "P-256";
1155
- case "ES384":
1156
- return "P-384";
1157
- case "ES512":
1158
- return "P-521";
1159
- default:
1160
- throw new Error("unreachable");
1161
- }
1162
- }
1163
- function checkUsage(key, usage) {
1164
- if (usage && !key.usages.includes(usage)) {
1165
- throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
1166
- }
1167
- }
1168
- function checkSigCryptoKey(key, alg, usage) {
1169
- switch (alg) {
1170
- case "HS256":
1171
- case "HS384":
1172
- case "HS512": {
1173
- if (!isAlgorithm(key.algorithm, "HMAC"))
1174
- throw unusable("HMAC");
1175
- const expected = parseInt(alg.slice(2), 10);
1176
- const actual = getHashLength(key.algorithm.hash);
1177
- if (actual !== expected)
1178
- throw unusable(`SHA-${expected}`, "algorithm.hash");
1179
- break;
1180
- }
1181
- case "RS256":
1182
- case "RS384":
1183
- case "RS512": {
1184
- if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5"))
1185
- throw unusable("RSASSA-PKCS1-v1_5");
1186
- const expected = parseInt(alg.slice(2), 10);
1187
- const actual = getHashLength(key.algorithm.hash);
1188
- if (actual !== expected)
1189
- throw unusable(`SHA-${expected}`, "algorithm.hash");
1190
- break;
1191
- }
1192
- case "PS256":
1193
- case "PS384":
1194
- case "PS512": {
1195
- if (!isAlgorithm(key.algorithm, "RSA-PSS"))
1196
- throw unusable("RSA-PSS");
1197
- const expected = parseInt(alg.slice(2), 10);
1198
- const actual = getHashLength(key.algorithm.hash);
1199
- if (actual !== expected)
1200
- throw unusable(`SHA-${expected}`, "algorithm.hash");
1201
- break;
1202
- }
1203
- case "Ed25519":
1204
- case "EdDSA": {
1205
- if (!isAlgorithm(key.algorithm, "Ed25519"))
1206
- throw unusable("Ed25519");
1207
- break;
1208
- }
1209
- case "ES256":
1210
- case "ES384":
1211
- case "ES512": {
1212
- if (!isAlgorithm(key.algorithm, "ECDSA"))
1213
- throw unusable("ECDSA");
1214
- const expected = getNamedCurve(alg);
1215
- const actual = key.algorithm.namedCurve;
1216
- if (actual !== expected)
1217
- throw unusable(expected, "algorithm.namedCurve");
1218
- break;
1219
- }
1220
- default:
1221
- throw new TypeError("CryptoKey does not support this operation");
1222
- }
1223
- checkUsage(key, usage);
1224
- }
1225
-
1226
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/invalid_key_input.js
1227
- function message(msg, actual, ...types) {
1228
- types = types.filter(Boolean);
1229
- if (types.length > 2) {
1230
- const last = types.pop();
1231
- msg += `one of type ${types.join(", ")}, or ${last}.`;
1232
- } else if (types.length === 2) {
1233
- msg += `one of type ${types[0]} or ${types[1]}.`;
1234
- } else {
1235
- msg += `of type ${types[0]}.`;
1236
- }
1237
- if (actual == null) {
1238
- msg += ` Received ${actual}`;
1239
- } else if (typeof actual === "function" && actual.name) {
1240
- msg += ` Received function ${actual.name}`;
1241
- } else if (typeof actual === "object" && actual != null) {
1242
- if (actual.constructor?.name) {
1243
- msg += ` Received an instance of ${actual.constructor.name}`;
1244
- }
1245
- }
1246
- return msg;
1247
- }
1248
- var invalid_key_input_default = (actual, ...types) => {
1249
- return message("Key must be ", actual, ...types);
1250
- };
1251
- function withAlg(alg, actual, ...types) {
1252
- return message(`Key for the ${alg} algorithm must be `, actual, ...types);
1253
- }
1254
-
1255
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/is_key_like.js
1256
- function isCryptoKey(key) {
1257
- return key?.[Symbol.toStringTag] === "CryptoKey";
1258
- }
1259
- function isKeyObject(key) {
1260
- return key?.[Symbol.toStringTag] === "KeyObject";
1261
- }
1262
- var is_key_like_default = (key) => {
1263
- return isCryptoKey(key) || isKeyObject(key);
1264
- };
1265
-
1266
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/is_disjoint.js
1267
- var is_disjoint_default = (...headers) => {
1268
- const sources = headers.filter(Boolean);
1269
- if (sources.length === 0 || sources.length === 1) {
1270
- return true;
1271
- }
1272
- let acc;
1273
- for (const header of sources) {
1274
- const parameters = Object.keys(header);
1275
- if (!acc || acc.size === 0) {
1276
- acc = new Set(parameters);
1277
- continue;
1278
- }
1279
- for (const parameter of parameters) {
1280
- if (acc.has(parameter)) {
1281
- return false;
1282
- }
1283
- acc.add(parameter);
1284
- }
1285
- }
1286
- return true;
1287
- };
1288
-
1289
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/is_object.js
1290
- function isObjectLike(value) {
1291
- return typeof value === "object" && value !== null;
1292
- }
1293
- var is_object_default = (input) => {
1294
- if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") {
1295
- return false;
1296
- }
1297
- if (Object.getPrototypeOf(input) === null) {
1298
- return true;
1299
- }
1300
- let proto = input;
1301
- while (Object.getPrototypeOf(proto) !== null) {
1302
- proto = Object.getPrototypeOf(proto);
1303
- }
1304
- return Object.getPrototypeOf(input) === proto;
1305
- };
1306
-
1307
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/check_key_length.js
1308
- var check_key_length_default = (alg, key) => {
1309
- if (alg.startsWith("RS") || alg.startsWith("PS")) {
1310
- const { modulusLength } = key.algorithm;
1311
- if (typeof modulusLength !== "number" || modulusLength < 2048) {
1312
- throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
1313
- }
1314
- }
1315
- };
1316
-
1317
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/jwk_to_key.js
1318
- function subtleMapping(jwk) {
1319
- let algorithm;
1320
- let keyUsages;
1321
- switch (jwk.kty) {
1322
- case "RSA": {
1323
- switch (jwk.alg) {
1324
- case "PS256":
1325
- case "PS384":
1326
- case "PS512":
1327
- algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` };
1328
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1329
- break;
1330
- case "RS256":
1331
- case "RS384":
1332
- case "RS512":
1333
- algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` };
1334
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1335
- break;
1336
- case "RSA-OAEP":
1337
- case "RSA-OAEP-256":
1338
- case "RSA-OAEP-384":
1339
- case "RSA-OAEP-512":
1340
- algorithm = {
1341
- name: "RSA-OAEP",
1342
- hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`
1343
- };
1344
- keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
1345
- break;
1346
- default:
1347
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
1348
- }
1349
- break;
1350
- }
1351
- case "EC": {
1352
- switch (jwk.alg) {
1353
- case "ES256":
1354
- algorithm = { name: "ECDSA", namedCurve: "P-256" };
1355
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1356
- break;
1357
- case "ES384":
1358
- algorithm = { name: "ECDSA", namedCurve: "P-384" };
1359
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1360
- break;
1361
- case "ES512":
1362
- algorithm = { name: "ECDSA", namedCurve: "P-521" };
1363
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1364
- break;
1365
- case "ECDH-ES":
1366
- case "ECDH-ES+A128KW":
1367
- case "ECDH-ES+A192KW":
1368
- case "ECDH-ES+A256KW":
1369
- algorithm = { name: "ECDH", namedCurve: jwk.crv };
1370
- keyUsages = jwk.d ? ["deriveBits"] : [];
1371
- break;
1372
- default:
1373
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
1374
- }
1375
- break;
1376
- }
1377
- case "OKP": {
1378
- switch (jwk.alg) {
1379
- case "Ed25519":
1380
- case "EdDSA":
1381
- algorithm = { name: "Ed25519" };
1382
- keyUsages = jwk.d ? ["sign"] : ["verify"];
1383
- break;
1384
- case "ECDH-ES":
1385
- case "ECDH-ES+A128KW":
1386
- case "ECDH-ES+A192KW":
1387
- case "ECDH-ES+A256KW":
1388
- algorithm = { name: jwk.crv };
1389
- keyUsages = jwk.d ? ["deriveBits"] : [];
1390
- break;
1391
- default:
1392
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
1393
- }
1394
- break;
1395
- }
1396
- default:
1397
- throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
1398
- }
1399
- return { algorithm, keyUsages };
1400
- }
1401
- var jwk_to_key_default = async (jwk) => {
1402
- if (!jwk.alg) {
1403
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
1404
- }
1405
- const { algorithm, keyUsages } = subtleMapping(jwk);
1406
- const keyData = { ...jwk };
1407
- delete keyData.alg;
1408
- delete keyData.use;
1409
- return crypto.subtle.importKey("jwk", keyData, algorithm, jwk.ext ?? (jwk.d ? false : true), jwk.key_ops ?? keyUsages);
1410
- };
1411
-
1412
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/validate_crit.js
1413
- var validate_crit_default = (Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) => {
1414
- if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) {
1415
- throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
1416
- }
1417
- if (!protectedHeader || protectedHeader.crit === void 0) {
1418
- return /* @__PURE__ */ new Set();
1419
- }
1420
- if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) {
1421
- throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
1422
- }
1423
- let recognized;
1424
- if (recognizedOption !== void 0) {
1425
- recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
1426
- } else {
1427
- recognized = recognizedDefault;
1428
- }
1429
- for (const parameter of protectedHeader.crit) {
1430
- if (!recognized.has(parameter)) {
1431
- throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
1432
- }
1433
- if (joseHeader[parameter] === void 0) {
1434
- throw new Err(`Extension Header Parameter "${parameter}" is missing`);
1435
- }
1436
- if (recognized.get(parameter) && protectedHeader[parameter] === void 0) {
1437
- throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
1438
- }
1439
- }
1440
- return new Set(protectedHeader.crit);
1441
- };
1442
-
1443
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/validate_algorithms.js
1444
- var validate_algorithms_default = (option, algorithms) => {
1445
- if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s4) => typeof s4 !== "string"))) {
1446
- throw new TypeError(`"${option}" option must be an array of strings`);
1447
- }
1448
- if (!algorithms) {
1449
- return void 0;
1450
- }
1451
- return new Set(algorithms);
1452
- };
1453
-
1454
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/is_jwk.js
1455
- function isJWK(key) {
1456
- return is_object_default(key) && typeof key.kty === "string";
1457
- }
1458
- function isPrivateJWK(key) {
1459
- return key.kty !== "oct" && typeof key.d === "string";
1460
- }
1461
- function isPublicJWK(key) {
1462
- return key.kty !== "oct" && typeof key.d === "undefined";
1463
- }
1464
- function isSecretJWK(key) {
1465
- return key.kty === "oct" && typeof key.k === "string";
1466
- }
1467
-
1468
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/normalize_key.js
1469
- var cache;
1470
- var handleJWK = async (key, jwk, alg, freeze = false) => {
1471
- cache ||= /* @__PURE__ */ new WeakMap();
1472
- let cached = cache.get(key);
1473
- if (cached?.[alg]) {
1474
- return cached[alg];
1475
- }
1476
- const cryptoKey = await jwk_to_key_default({ ...jwk, alg });
1477
- if (freeze)
1478
- Object.freeze(key);
1479
- if (!cached) {
1480
- cache.set(key, { [alg]: cryptoKey });
1481
- } else {
1482
- cached[alg] = cryptoKey;
1483
- }
1484
- return cryptoKey;
1485
- };
1486
- var handleKeyObject = (keyObject, alg) => {
1487
- cache ||= /* @__PURE__ */ new WeakMap();
1488
- let cached = cache.get(keyObject);
1489
- if (cached?.[alg]) {
1490
- return cached[alg];
1491
- }
1492
- const isPublic = keyObject.type === "public";
1493
- const extractable = isPublic ? true : false;
1494
- let cryptoKey;
1495
- if (keyObject.asymmetricKeyType === "x25519") {
1496
- switch (alg) {
1497
- case "ECDH-ES":
1498
- case "ECDH-ES+A128KW":
1499
- case "ECDH-ES+A192KW":
1500
- case "ECDH-ES+A256KW":
1501
- break;
1502
- default:
1503
- throw new TypeError("given KeyObject instance cannot be used for this algorithm");
1504
- }
1505
- cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ["deriveBits"]);
1506
- }
1507
- if (keyObject.asymmetricKeyType === "ed25519") {
1508
- if (alg !== "EdDSA" && alg !== "Ed25519") {
1509
- throw new TypeError("given KeyObject instance cannot be used for this algorithm");
1510
- }
1511
- cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
1512
- isPublic ? "verify" : "sign"
1513
- ]);
1514
- }
1515
- if (keyObject.asymmetricKeyType === "rsa") {
1516
- let hash;
1517
- switch (alg) {
1518
- case "RSA-OAEP":
1519
- hash = "SHA-1";
1520
- break;
1521
- case "RS256":
1522
- case "PS256":
1523
- case "RSA-OAEP-256":
1524
- hash = "SHA-256";
1525
- break;
1526
- case "RS384":
1527
- case "PS384":
1528
- case "RSA-OAEP-384":
1529
- hash = "SHA-384";
1530
- break;
1531
- case "RS512":
1532
- case "PS512":
1533
- case "RSA-OAEP-512":
1534
- hash = "SHA-512";
1535
- break;
1536
- default:
1537
- throw new TypeError("given KeyObject instance cannot be used for this algorithm");
1538
- }
1539
- if (alg.startsWith("RSA-OAEP")) {
1540
- return keyObject.toCryptoKey({
1541
- name: "RSA-OAEP",
1542
- hash
1543
- }, extractable, isPublic ? ["encrypt"] : ["decrypt"]);
1544
- }
1545
- cryptoKey = keyObject.toCryptoKey({
1546
- name: alg.startsWith("PS") ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
1547
- hash
1548
- }, extractable, [isPublic ? "verify" : "sign"]);
1549
- }
1550
- if (keyObject.asymmetricKeyType === "ec") {
1551
- const nist = /* @__PURE__ */ new Map([
1552
- ["prime256v1", "P-256"],
1553
- ["secp384r1", "P-384"],
1554
- ["secp521r1", "P-521"]
1555
- ]);
1556
- const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);
1557
- if (!namedCurve) {
1558
- throw new TypeError("given KeyObject instance cannot be used for this algorithm");
1559
- }
1560
- if (alg === "ES256" && namedCurve === "P-256") {
1561
- cryptoKey = keyObject.toCryptoKey({
1562
- name: "ECDSA",
1563
- namedCurve
1564
- }, extractable, [isPublic ? "verify" : "sign"]);
1565
- }
1566
- if (alg === "ES384" && namedCurve === "P-384") {
1567
- cryptoKey = keyObject.toCryptoKey({
1568
- name: "ECDSA",
1569
- namedCurve
1570
- }, extractable, [isPublic ? "verify" : "sign"]);
1571
- }
1572
- if (alg === "ES512" && namedCurve === "P-521") {
1573
- cryptoKey = keyObject.toCryptoKey({
1574
- name: "ECDSA",
1575
- namedCurve
1576
- }, extractable, [isPublic ? "verify" : "sign"]);
1577
- }
1578
- if (alg.startsWith("ECDH-ES")) {
1579
- cryptoKey = keyObject.toCryptoKey({
1580
- name: "ECDH",
1581
- namedCurve
1582
- }, extractable, isPublic ? [] : ["deriveBits"]);
1583
- }
1584
- }
1585
- if (!cryptoKey) {
1586
- throw new TypeError("given KeyObject instance cannot be used for this algorithm");
1587
- }
1588
- if (!cached) {
1589
- cache.set(keyObject, { [alg]: cryptoKey });
1590
- } else {
1591
- cached[alg] = cryptoKey;
1592
- }
1593
- return cryptoKey;
1594
- };
1595
- var normalize_key_default = async (key, alg) => {
1596
- if (key instanceof Uint8Array) {
1597
- return key;
1598
- }
1599
- if (isCryptoKey(key)) {
1600
- return key;
1601
- }
1602
- if (isKeyObject(key)) {
1603
- if (key.type === "secret") {
1604
- return key.export();
1605
- }
1606
- if ("toCryptoKey" in key && typeof key.toCryptoKey === "function") {
1607
- try {
1608
- return handleKeyObject(key, alg);
1609
- } catch (err) {
1610
- if (err instanceof TypeError) {
1611
- throw err;
1612
- }
1613
- }
1614
- }
1615
- let jwk = key.export({ format: "jwk" });
1616
- return handleJWK(key, jwk, alg);
1617
- }
1618
- if (isJWK(key)) {
1619
- if (key.k) {
1620
- return decode(key.k);
1621
- }
1622
- return handleJWK(key, key, alg, true);
1623
- }
1624
- throw new Error("unreachable");
1625
- };
1626
-
1627
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/check_key_type.js
1628
- var tag = (key) => key?.[Symbol.toStringTag];
1629
- var jwkMatchesOp = (alg, key, usage) => {
1630
- if (key.use !== void 0) {
1631
- let expected;
1632
- switch (usage) {
1633
- case "sign":
1634
- case "verify":
1635
- expected = "sig";
1636
- break;
1637
- case "encrypt":
1638
- case "decrypt":
1639
- expected = "enc";
1640
- break;
1641
- }
1642
- if (key.use !== expected) {
1643
- throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
1644
- }
1645
- }
1646
- if (key.alg !== void 0 && key.alg !== alg) {
1647
- throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
1648
- }
1649
- if (Array.isArray(key.key_ops)) {
1650
- let expectedKeyOp;
1651
- switch (true) {
1652
- case (usage === "sign" || usage === "verify"):
1653
- case alg === "dir":
1654
- case alg.includes("CBC-HS"):
1655
- expectedKeyOp = usage;
1656
- break;
1657
- case alg.startsWith("PBES2"):
1658
- expectedKeyOp = "deriveBits";
1659
- break;
1660
- case /^A\d{3}(?:GCM)?(?:KW)?$/.test(alg):
1661
- if (!alg.includes("GCM") && alg.endsWith("KW")) {
1662
- expectedKeyOp = usage === "encrypt" ? "wrapKey" : "unwrapKey";
1663
- } else {
1664
- expectedKeyOp = usage;
1665
- }
1666
- break;
1667
- case (usage === "encrypt" && alg.startsWith("RSA")):
1668
- expectedKeyOp = "wrapKey";
1669
- break;
1670
- case usage === "decrypt":
1671
- expectedKeyOp = alg.startsWith("RSA") ? "unwrapKey" : "deriveBits";
1672
- break;
1673
- }
1674
- if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
1675
- throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
1676
- }
1677
- }
1678
- return true;
1679
- };
1680
- var symmetricTypeCheck = (alg, key, usage) => {
1681
- if (key instanceof Uint8Array)
1682
- return;
1683
- if (isJWK(key)) {
1684
- if (isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
1685
- return;
1686
- throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
1687
- }
1688
- if (!is_key_like_default(key)) {
1689
- throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key", "Uint8Array"));
1690
- }
1691
- if (key.type !== "secret") {
1692
- throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
1693
- }
1694
- };
1695
- var asymmetricTypeCheck = (alg, key, usage) => {
1696
- if (isJWK(key)) {
1697
- switch (usage) {
1698
- case "decrypt":
1699
- case "sign":
1700
- if (isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
1701
- return;
1702
- throw new TypeError(`JSON Web Key for this operation be a private JWK`);
1703
- case "encrypt":
1704
- case "verify":
1705
- if (isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
1706
- return;
1707
- throw new TypeError(`JSON Web Key for this operation be a public JWK`);
1708
- }
1709
- }
1710
- if (!is_key_like_default(key)) {
1711
- throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key"));
1712
- }
1713
- if (key.type === "secret") {
1714
- throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
1715
- }
1716
- if (key.type === "public") {
1717
- switch (usage) {
1718
- case "sign":
1719
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
1720
- case "decrypt":
1721
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
1722
- default:
1723
- break;
1724
- }
1725
- }
1726
- if (key.type === "private") {
1727
- switch (usage) {
1728
- case "verify":
1729
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
1730
- case "encrypt":
1731
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
1732
- default:
1733
- break;
1734
- }
1735
- }
1736
- };
1737
- var check_key_type_default = (alg, key, usage) => {
1738
- const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A(?:128|192|256)(?:GCM)?(?:KW)?$/.test(alg) || /^A(?:128|192|256)CBC-HS(?:256|384|512)$/.test(alg);
1739
- if (symmetric) {
1740
- symmetricTypeCheck(alg, key, usage);
1741
- } else {
1742
- asymmetricTypeCheck(alg, key, usage);
1743
- }
1744
- };
1745
-
1746
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/subtle_dsa.js
1747
- var subtle_dsa_default = (alg, algorithm) => {
1748
- const hash = `SHA-${alg.slice(-3)}`;
1749
- switch (alg) {
1750
- case "HS256":
1751
- case "HS384":
1752
- case "HS512":
1753
- return { hash, name: "HMAC" };
1754
- case "PS256":
1755
- case "PS384":
1756
- case "PS512":
1757
- return { hash, name: "RSA-PSS", saltLength: parseInt(alg.slice(-3), 10) >> 3 };
1758
- case "RS256":
1759
- case "RS384":
1760
- case "RS512":
1761
- return { hash, name: "RSASSA-PKCS1-v1_5" };
1762
- case "ES256":
1763
- case "ES384":
1764
- case "ES512":
1765
- return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve };
1766
- case "Ed25519":
1767
- case "EdDSA":
1768
- return { name: "Ed25519" };
1769
- default:
1770
- throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
1771
- }
1772
- };
1773
-
1774
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/get_sign_verify_key.js
1775
- var get_sign_verify_key_default = async (alg, key, usage) => {
1776
- if (key instanceof Uint8Array) {
1777
- if (!alg.startsWith("HS")) {
1778
- throw new TypeError(invalid_key_input_default(key, "CryptoKey", "KeyObject", "JSON Web Key"));
1779
- }
1780
- return crypto.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]);
1781
- }
1782
- checkSigCryptoKey(key, alg, usage);
1783
- return key;
1784
- };
1785
-
1786
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/verify.js
1787
- var verify_default = async (alg, key, signature, data) => {
1788
- const cryptoKey = await get_sign_verify_key_default(alg, key, "verify");
1789
- check_key_length_default(alg, cryptoKey);
1790
- const algorithm = subtle_dsa_default(alg, cryptoKey.algorithm);
1791
- try {
1792
- return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
1793
- } catch {
1794
- return false;
1795
- }
1796
- };
1797
-
1798
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/jws/flattened/verify.js
1799
- async function flattenedVerify(jws, key, options) {
1800
- if (!is_object_default(jws)) {
1801
- throw new JWSInvalid("Flattened JWS must be an object");
1802
- }
1803
- if (jws.protected === void 0 && jws.header === void 0) {
1804
- throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
1805
- }
1806
- if (jws.protected !== void 0 && typeof jws.protected !== "string") {
1807
- throw new JWSInvalid("JWS Protected Header incorrect type");
1808
- }
1809
- if (jws.payload === void 0) {
1810
- throw new JWSInvalid("JWS Payload missing");
1811
- }
1812
- if (typeof jws.signature !== "string") {
1813
- throw new JWSInvalid("JWS Signature missing or incorrect type");
1814
- }
1815
- if (jws.header !== void 0 && !is_object_default(jws.header)) {
1816
- throw new JWSInvalid("JWS Unprotected Header incorrect type");
1817
- }
1818
- let parsedProt = {};
1819
- if (jws.protected) {
1820
- try {
1821
- const protectedHeader = decode(jws.protected);
1822
- parsedProt = JSON.parse(decoder.decode(protectedHeader));
1823
- } catch {
1824
- throw new JWSInvalid("JWS Protected Header is invalid");
1825
- }
1826
- }
1827
- if (!is_disjoint_default(parsedProt, jws.header)) {
1828
- throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
1829
- }
1830
- const joseHeader = {
1831
- ...parsedProt,
1832
- ...jws.header
1833
- };
1834
- const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options?.crit, parsedProt, joseHeader);
1835
- let b64 = true;
1836
- if (extensions.has("b64")) {
1837
- b64 = parsedProt.b64;
1838
- if (typeof b64 !== "boolean") {
1839
- throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
1840
- }
1841
- }
1842
- const { alg } = joseHeader;
1843
- if (typeof alg !== "string" || !alg) {
1844
- throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
1845
- }
1846
- const algorithms = options && validate_algorithms_default("algorithms", options.algorithms);
1847
- if (algorithms && !algorithms.has(alg)) {
1848
- throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
1849
- }
1850
- if (b64) {
1851
- if (typeof jws.payload !== "string") {
1852
- throw new JWSInvalid("JWS Payload must be a string");
1853
- }
1854
- } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) {
1855
- throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
1856
- }
1857
- let resolvedKey = false;
1858
- if (typeof key === "function") {
1859
- key = await key(parsedProt, jws);
1860
- resolvedKey = true;
1861
- }
1862
- check_key_type_default(alg, key, "verify");
1863
- const data = concat(encoder.encode(jws.protected ?? ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload);
1864
- let signature;
1865
- try {
1866
- signature = decode(jws.signature);
1867
- } catch {
1868
- throw new JWSInvalid("Failed to base64url decode the signature");
1869
- }
1870
- const k = await normalize_key_default(key, alg);
1871
- const verified = await verify_default(alg, k, signature, data);
1872
- if (!verified) {
1873
- throw new JWSSignatureVerificationFailed();
1874
- }
1875
- let payload;
1876
- if (b64) {
1877
- try {
1878
- payload = decode(jws.payload);
1879
- } catch {
1880
- throw new JWSInvalid("Failed to base64url decode the payload");
1881
- }
1882
- } else if (typeof jws.payload === "string") {
1883
- payload = encoder.encode(jws.payload);
1884
- } else {
1885
- payload = jws.payload;
1886
- }
1887
- const result = { payload };
1888
- if (jws.protected !== void 0) {
1889
- result.protectedHeader = parsedProt;
1890
- }
1891
- if (jws.header !== void 0) {
1892
- result.unprotectedHeader = jws.header;
1893
- }
1894
- if (resolvedKey) {
1895
- return { ...result, key: k };
1896
- }
1897
- return result;
1898
- }
1899
-
1900
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/jws/compact/verify.js
1901
- async function compactVerify(jws, key, options) {
1902
- if (jws instanceof Uint8Array) {
1903
- jws = decoder.decode(jws);
1904
- }
1905
- if (typeof jws !== "string") {
1906
- throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
1907
- }
1908
- const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
1909
- if (length !== 3) {
1910
- throw new JWSInvalid("Invalid Compact JWS");
1911
- }
1912
- const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);
1913
- const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
1914
- if (typeof key === "function") {
1915
- return { ...result, key: verified.key };
1916
- }
1917
- return result;
1918
- }
1919
-
1920
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/epoch.js
1921
- var epoch_default = (date) => Math.floor(date.getTime() / 1e3);
1922
-
1923
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/secs.js
1924
- var minute = 60;
1925
- var hour = minute * 60;
1926
- var day = hour * 24;
1927
- var week = day * 7;
1928
- var year = day * 365.25;
1929
- var REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
1930
- var secs_default = (str) => {
1931
- const matched = REGEX.exec(str);
1932
- if (!matched || matched[4] && matched[1]) {
1933
- throw new TypeError("Invalid time period format");
1934
- }
1935
- const value = parseFloat(matched[2]);
1936
- const unit = matched[3].toLowerCase();
1937
- let numericDate;
1938
- switch (unit) {
1939
- case "sec":
1940
- case "secs":
1941
- case "second":
1942
- case "seconds":
1943
- case "s":
1944
- numericDate = Math.round(value);
1945
- break;
1946
- case "minute":
1947
- case "minutes":
1948
- case "min":
1949
- case "mins":
1950
- case "m":
1951
- numericDate = Math.round(value * minute);
1952
- break;
1953
- case "hour":
1954
- case "hours":
1955
- case "hr":
1956
- case "hrs":
1957
- case "h":
1958
- numericDate = Math.round(value * hour);
1959
- break;
1960
- case "day":
1961
- case "days":
1962
- case "d":
1963
- numericDate = Math.round(value * day);
1964
- break;
1965
- case "week":
1966
- case "weeks":
1967
- case "w":
1968
- numericDate = Math.round(value * week);
1969
- break;
1970
- default:
1971
- numericDate = Math.round(value * year);
1972
- break;
1973
- }
1974
- if (matched[1] === "-" || matched[4] === "ago") {
1975
- return -numericDate;
1976
- }
1977
- return numericDate;
1978
- };
1979
-
1980
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/lib/jwt_claims_set.js
1981
- var normalizeTyp = (value) => {
1982
- if (value.includes("/")) {
1983
- return value.toLowerCase();
1984
- }
1985
- return `application/${value.toLowerCase()}`;
1986
- };
1987
- var checkAudiencePresence = (audPayload, audOption) => {
1988
- if (typeof audPayload === "string") {
1989
- return audOption.includes(audPayload);
1990
- }
1991
- if (Array.isArray(audPayload)) {
1992
- return audOption.some(Set.prototype.has.bind(new Set(audPayload)));
1993
- }
1994
- return false;
1995
- };
1996
- function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
1997
- let payload;
1998
- try {
1999
- payload = JSON.parse(decoder.decode(encodedPayload));
2000
- } catch {
2001
- }
2002
- if (!is_object_default(payload)) {
2003
- throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
2004
- }
2005
- const { typ } = options;
2006
- if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {
2007
- throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', payload, "typ", "check_failed");
2008
- }
2009
- const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;
2010
- const presenceCheck = [...requiredClaims];
2011
- if (maxTokenAge !== void 0)
2012
- presenceCheck.push("iat");
2013
- if (audience !== void 0)
2014
- presenceCheck.push("aud");
2015
- if (subject !== void 0)
2016
- presenceCheck.push("sub");
2017
- if (issuer !== void 0)
2018
- presenceCheck.push("iss");
2019
- for (const claim of new Set(presenceCheck.reverse())) {
2020
- if (!(claim in payload)) {
2021
- throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
2022
- }
2023
- }
2024
- if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {
2025
- throw new JWTClaimValidationFailed('unexpected "iss" claim value', payload, "iss", "check_failed");
2026
- }
2027
- if (subject && payload.sub !== subject) {
2028
- throw new JWTClaimValidationFailed('unexpected "sub" claim value', payload, "sub", "check_failed");
2029
- }
2030
- if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) {
2031
- throw new JWTClaimValidationFailed('unexpected "aud" claim value', payload, "aud", "check_failed");
2032
- }
2033
- let tolerance;
2034
- switch (typeof options.clockTolerance) {
2035
- case "string":
2036
- tolerance = secs_default(options.clockTolerance);
2037
- break;
2038
- case "number":
2039
- tolerance = options.clockTolerance;
2040
- break;
2041
- case "undefined":
2042
- tolerance = 0;
2043
- break;
2044
- default:
2045
- throw new TypeError("Invalid clockTolerance option type");
2046
- }
2047
- const { currentDate } = options;
2048
- const now = epoch_default(currentDate || /* @__PURE__ */ new Date());
2049
- if ((payload.iat !== void 0 || maxTokenAge) && typeof payload.iat !== "number") {
2050
- throw new JWTClaimValidationFailed('"iat" claim must be a number', payload, "iat", "invalid");
2051
- }
2052
- if (payload.nbf !== void 0) {
2053
- if (typeof payload.nbf !== "number") {
2054
- throw new JWTClaimValidationFailed('"nbf" claim must be a number', payload, "nbf", "invalid");
2055
- }
2056
- if (payload.nbf > now + tolerance) {
2057
- throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', payload, "nbf", "check_failed");
2058
- }
2059
- }
2060
- if (payload.exp !== void 0) {
2061
- if (typeof payload.exp !== "number") {
2062
- throw new JWTClaimValidationFailed('"exp" claim must be a number', payload, "exp", "invalid");
2063
- }
2064
- if (payload.exp <= now - tolerance) {
2065
- throw new JWTExpired('"exp" claim timestamp check failed', payload, "exp", "check_failed");
2066
- }
2067
- }
2068
- if (maxTokenAge) {
2069
- const age = now - payload.iat;
2070
- const max = typeof maxTokenAge === "number" ? maxTokenAge : secs_default(maxTokenAge);
2071
- if (age - tolerance > max) {
2072
- throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', payload, "iat", "check_failed");
2073
- }
2074
- if (age < 0 - tolerance) {
2075
- throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', payload, "iat", "check_failed");
2076
- }
2077
- }
2078
- return payload;
2079
- }
2080
-
2081
- // node_modules/.pnpm/jose@6.0.11/node_modules/jose/dist/webapi/jwt/verify.js
2082
- async function jwtVerify(jwt, key, options) {
2083
- const verified = await compactVerify(jwt, key, options);
2084
- if (verified.protectedHeader.crit?.includes("b64") && verified.protectedHeader.b64 === false) {
2085
- throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
2086
- }
2087
- const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
2088
- const result = { payload, protectedHeader: verified.protectedHeader };
2089
- if (typeof key === "function") {
2090
- return { ...result, key: verified.key };
2091
- }
2092
- return result;
2093
- }
2094
-
2095
499
  // src/auth.ts
500
+ import ky2 from "ky";
501
+ import * as jose from "jose";
2096
502
  var GRANT_TYPE = "authorization_code";
2097
503
  var TOKEN_ENDPOINT = "https://login.bigcommerce.com/oauth2/token";
2098
504
  var ISSUER = "bc";
2099
505
  var BigCommerceAuth = class {
2100
506
  /**
2101
- * Creates a new BigCommerceAuth instance
507
+ * Creates a new BigCommerceAuth instance for handling OAuth authentication
2102
508
  * @param config - Configuration options for BigCommerce authentication
509
+ * @param config.clientId - The OAuth client ID from BigCommerce
510
+ * @param config.secret - The OAuth client secret from BigCommerce
511
+ * @param config.redirectUri - The redirect URI registered with BigCommerce
512
+ * @param config.scopes - Optional array of scopes to validate during auth callback
513
+ * @param config.logger - Optional logger instance for debugging and error tracking
2103
514
  * @throws {Error} If the redirect URI is invalid
2104
515
  */
2105
516
  constructor(config) {
2106
517
  this.config = config;
2107
518
  try {
2108
- URL.parse(this.config.redirectUri);
519
+ new URL(this.config.redirectUri);
2109
520
  } catch (error) {
2110
521
  throw new Error("Invalid redirect URI", { cause: error });
2111
522
  }
2112
523
  }
2113
524
  /**
2114
525
  * Requests an access token from BigCommerce
2115
- * @param data - Either a query string or AuthQuery object containing auth callback data
526
+ * @param data - Either a query string, URLSearchParams, or AuthQuery object containing auth callback data
2116
527
  * @returns Promise resolving to the token response
2117
528
  */
2118
529
  async requestToken(data) {
2119
- const query = typeof data === "string" ? this.parseQueryString(data) : data;
530
+ const query = typeof data === "string" || data instanceof URLSearchParams ? this.parseQueryString(data) : data;
2120
531
  const tokenRequest = {
2121
532
  client_id: this.config.clientId,
2122
533
  client_secret: this.config.secret,
@@ -2124,27 +535,44 @@ var BigCommerceAuth = class {
2124
535
  grant_type: GRANT_TYPE,
2125
536
  redirect_uri: this.config.redirectUri
2126
537
  };
2127
- return await distribution_default(TOKEN_ENDPOINT, {
538
+ this.config.logger?.debug({
539
+ clientId: this.config.clientId,
540
+ context: query.context,
541
+ scopes: query.scope
542
+ }, "Requesting OAuth token");
543
+ const res = await ky2(TOKEN_ENDPOINT, {
2128
544
  method: "POST",
2129
545
  json: tokenRequest
2130
- }).json();
546
+ });
547
+ return res.json();
2131
548
  }
2132
549
  /**
2133
550
  * Verifies a JWT payload from BigCommerce
2134
551
  * @param jwtPayload - The JWT string to verify
552
+ * @param storeHash - The store hash for the BigCommerce store
2135
553
  * @returns Promise resolving to the verified JWT claims
2136
554
  * @throws {Error} If the JWT is invalid
2137
555
  */
2138
- async verify(jwtPayload) {
556
+ async verify(jwtPayload, storeHash) {
2139
557
  try {
2140
558
  const secret = new TextEncoder().encode(this.config.secret);
2141
- const { payload } = await jwtVerify(jwtPayload, secret, {
559
+ const { payload } = await jose.jwtVerify(jwtPayload, secret, {
2142
560
  audience: this.config.clientId,
2143
561
  issuer: ISSUER,
2144
- subject: `stores/${this.config.storeHash}`
562
+ subject: `stores/${storeHash}`
2145
563
  });
564
+ this.config.logger?.debug({
565
+ userId: payload.user?.id,
566
+ storeHash: payload.sub.split("/")[1]
567
+ }, "JWT verified successfully");
2146
568
  return payload;
2147
569
  } catch (error) {
570
+ this.config.logger?.error({
571
+ error: error instanceof Error ? {
572
+ name: error.name,
573
+ message: error.message
574
+ } : error
575
+ });
2148
576
  throw new Error("Invalid JWT payload", { cause: error });
2149
577
  }
2150
578
  }
@@ -2155,7 +583,7 @@ var BigCommerceAuth = class {
2155
583
  * @throws {Error} If required parameters are missing or scopes are invalid
2156
584
  */
2157
585
  parseQueryString(queryString) {
2158
- const params = new URLSearchParams(queryString);
586
+ const params = typeof queryString === "string" ? new URLSearchParams(queryString) : queryString;
2159
587
  const code = params.get("code");
2160
588
  const scope = params.get("scope");
2161
589
  const context = params.get("context");
@@ -2187,22 +615,20 @@ var BigCommerceAuth = class {
2187
615
  * @throws {Error} If the scopes don't match the expected scopes
2188
616
  */
2189
617
  validateScopes(scopes) {
2190
- const scopesArray = scopes.split(" ");
2191
- if (this.config.scopes?.length) {
2192
- const int = s2(scopesArray, this.config.scopes);
2193
- if (int.length !== scopesArray.length) {
2194
- throw new Error(`Scope mismatch: ${scopes}; expected: ${this.config.scopes.join(" ")}`);
2195
- }
618
+ if (!this.config.scopes) {
619
+ return;
620
+ }
621
+ const grantedScopes = scopes.split(" ");
622
+ const requiredScopes = this.config.scopes;
623
+ const missingScopes = requiredScopes.filter((scope) => !grantedScopes.includes(scope));
624
+ if (missingScopes.length) {
625
+ throw new Error(`Scope mismatch: ${scopes}; expected: ${this.config.scopes.join(" ")}`);
2196
626
  }
2197
627
  }
2198
628
  };
2199
629
  export {
2200
630
  BigCommerceAuth,
2201
- BigCommerceClient
631
+ BigCommerceClient,
632
+ Methods
2202
633
  };
2203
- /*! Bundled license information:
2204
-
2205
- ky/distribution/index.js:
2206
- (*! MIT License © Sindre Sorhus *)
2207
- */
2208
634
  //# sourceMappingURL=index.js.map