@blimu/client 0.7.0 → 1.1.1

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 (54) hide show
  1. package/README.md +26 -79
  2. package/dist/client.d.mts +15 -59
  3. package/dist/client.d.ts +15 -59
  4. package/dist/client.js +1085 -109
  5. package/dist/client.js.map +1 -0
  6. package/dist/client.mjs +1112 -4
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/index.d.mts +10 -3
  9. package/dist/index.d.ts +10 -3
  10. package/dist/index.js +1227 -130
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +1317 -18
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/{schema-jwKwV_Bm.d.mts → schema-B4iFbKly.d.mts} +4 -15
  15. package/dist/{schema-jwKwV_Bm.d.ts → schema-B4iFbKly.d.ts} +4 -15
  16. package/dist/schema.d.mts +2 -1
  17. package/dist/schema.d.ts +2 -1
  18. package/dist/schema.js +1 -0
  19. package/dist/schema.js.map +1 -0
  20. package/dist/schema.mjs +1 -1
  21. package/dist/schema.mjs.map +1 -0
  22. package/dist/schema.zod-CyY7RTSY.d.mts +48 -0
  23. package/dist/schema.zod-CyY7RTSY.d.ts +48 -0
  24. package/dist/schema.zod.d.mts +2 -0
  25. package/dist/schema.zod.d.ts +2 -0
  26. package/dist/schema.zod.js +77 -0
  27. package/dist/schema.zod.js.map +1 -0
  28. package/dist/schema.zod.mjs +47 -0
  29. package/dist/schema.zod.mjs.map +1 -0
  30. package/dist/services/auth.d.mts +3 -25
  31. package/dist/services/auth.d.ts +3 -25
  32. package/dist/services/auth.js +7 -9
  33. package/dist/services/auth.js.map +1 -0
  34. package/dist/services/auth.mjs +59 -5
  35. package/dist/services/auth.mjs.map +1 -0
  36. package/dist/services/entitlements.d.mts +3 -11
  37. package/dist/services/entitlements.d.ts +3 -11
  38. package/dist/services/entitlements.js +8 -6
  39. package/dist/services/entitlements.js.map +1 -0
  40. package/dist/services/entitlements.mjs +28 -5
  41. package/dist/services/entitlements.mjs.map +1 -0
  42. package/dist/tsconfig.tsbuildinfo +1 -0
  43. package/dist/utils.d.mts +2 -0
  44. package/dist/utils.d.ts +2 -0
  45. package/dist/utils.js +1078 -3
  46. package/dist/utils.js.map +1 -0
  47. package/dist/utils.mjs +1092 -5
  48. package/dist/utils.mjs.map +1 -0
  49. package/package.json +18 -40
  50. package/dist/chunk-7SBLH5KM.mjs +0 -6
  51. package/dist/chunk-ATZGLDGF.mjs +0 -143
  52. package/dist/chunk-ENXZU3RF.mjs +0 -30
  53. package/dist/chunk-LZ27JJ4R.mjs +0 -25
  54. package/dist/chunk-YGEJFE6U.mjs +0 -65
package/dist/utils.js CHANGED
@@ -21,9 +21,1080 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var utils_exports = {};
22
22
  __export(utils_exports, {
23
23
  listAll: () => listAll,
24
- paginate: () => paginate
24
+ paginate: () => paginate,
25
+ parseNDJSONStream: () => parseNDJSONStream,
26
+ parseSSEStream: () => parseSSEStream
25
27
  });
26
28
  module.exports = __toCommonJS(utils_exports);
29
+
30
+ // ../../node_modules/@blimu/fetch/dist/index.js
31
+ var __defProp2 = Object.defineProperty;
32
+ var __name = (target, value) => __defProp2(target, "name", { value, configurable: true });
33
+ var FetchError = class _FetchError extends Error {
34
+ static {
35
+ __name(this, "FetchError");
36
+ }
37
+ status;
38
+ data;
39
+ headers;
40
+ constructor(message, status, data, headers) {
41
+ super(message), this.status = status, this.data = data, this.headers = headers;
42
+ this.name = "FetchError";
43
+ if (Error.captureStackTrace) {
44
+ Error.captureStackTrace(this, _FetchError);
45
+ }
46
+ }
47
+ };
48
+ var ClientError = class extends FetchError {
49
+ static {
50
+ __name(this, "ClientError");
51
+ }
52
+ constructor(message, status, data, headers) {
53
+ super(message, status, data, headers);
54
+ this.name = "ClientError";
55
+ }
56
+ };
57
+ var ServerError = class extends FetchError {
58
+ static {
59
+ __name(this, "ServerError");
60
+ }
61
+ constructor(message, status, data, headers) {
62
+ super(message, status, data, headers);
63
+ this.name = "ServerError";
64
+ }
65
+ };
66
+ var BadRequestError = class extends ClientError {
67
+ static {
68
+ __name(this, "BadRequestError");
69
+ }
70
+ constructor(message = "Bad Request", data, headers) {
71
+ super(message, 400, data, headers);
72
+ this.name = "BadRequestError";
73
+ }
74
+ };
75
+ var UnauthorizedError = class extends ClientError {
76
+ static {
77
+ __name(this, "UnauthorizedError");
78
+ }
79
+ constructor(message = "Unauthorized", data, headers) {
80
+ super(message, 401, data, headers);
81
+ this.name = "UnauthorizedError";
82
+ }
83
+ };
84
+ var ForbiddenError = class extends ClientError {
85
+ static {
86
+ __name(this, "ForbiddenError");
87
+ }
88
+ constructor(message = "Forbidden", data, headers) {
89
+ super(message, 403, data, headers);
90
+ this.name = "ForbiddenError";
91
+ }
92
+ };
93
+ var NotFoundError = class extends ClientError {
94
+ static {
95
+ __name(this, "NotFoundError");
96
+ }
97
+ constructor(message = "Not Found", data, headers) {
98
+ super(message, 404, data, headers);
99
+ this.name = "NotFoundError";
100
+ }
101
+ };
102
+ var MethodNotAllowedError = class extends ClientError {
103
+ static {
104
+ __name(this, "MethodNotAllowedError");
105
+ }
106
+ constructor(message = "Method Not Allowed", data, headers) {
107
+ super(message, 405, data, headers);
108
+ this.name = "MethodNotAllowedError";
109
+ }
110
+ };
111
+ var ConflictError = class extends ClientError {
112
+ static {
113
+ __name(this, "ConflictError");
114
+ }
115
+ constructor(message = "Conflict", data, headers) {
116
+ super(message, 409, data, headers);
117
+ this.name = "ConflictError";
118
+ }
119
+ };
120
+ var UnprocessableEntityError = class extends ClientError {
121
+ static {
122
+ __name(this, "UnprocessableEntityError");
123
+ }
124
+ constructor(message = "Unprocessable Entity", data, headers) {
125
+ super(message, 422, data, headers);
126
+ this.name = "UnprocessableEntityError";
127
+ }
128
+ };
129
+ var TooManyRequestsError = class extends ClientError {
130
+ static {
131
+ __name(this, "TooManyRequestsError");
132
+ }
133
+ constructor(message = "Too Many Requests", data, headers) {
134
+ super(message, 429, data, headers);
135
+ this.name = "TooManyRequestsError";
136
+ }
137
+ };
138
+ var InternalServerError = class extends ServerError {
139
+ static {
140
+ __name(this, "InternalServerError");
141
+ }
142
+ constructor(message = "Internal Server Error", data, headers) {
143
+ super(message, 500, data, headers);
144
+ this.name = "InternalServerError";
145
+ }
146
+ };
147
+ var BadGatewayError = class extends ServerError {
148
+ static {
149
+ __name(this, "BadGatewayError");
150
+ }
151
+ constructor(message = "Bad Gateway", data, headers) {
152
+ super(message, 502, data, headers);
153
+ this.name = "BadGatewayError";
154
+ }
155
+ };
156
+ var ServiceUnavailableError = class extends ServerError {
157
+ static {
158
+ __name(this, "ServiceUnavailableError");
159
+ }
160
+ constructor(message = "Service Unavailable", data, headers) {
161
+ super(message, 503, data, headers);
162
+ this.name = "ServiceUnavailableError";
163
+ }
164
+ };
165
+ var GatewayTimeoutError = class extends ServerError {
166
+ static {
167
+ __name(this, "GatewayTimeoutError");
168
+ }
169
+ constructor(message = "Gateway Timeout", data, headers) {
170
+ super(message, 504, data, headers);
171
+ this.name = "GatewayTimeoutError";
172
+ }
173
+ };
174
+ function createFetchError(status, message, data, headers) {
175
+ const defaultMessage = message || `HTTP ${status}`;
176
+ switch (status) {
177
+ case 400:
178
+ return new BadRequestError(defaultMessage, data, headers);
179
+ case 401:
180
+ return new UnauthorizedError(defaultMessage, data, headers);
181
+ case 403:
182
+ return new ForbiddenError(defaultMessage, data, headers);
183
+ case 404:
184
+ return new NotFoundError(defaultMessage, data, headers);
185
+ case 405:
186
+ return new MethodNotAllowedError(defaultMessage, data, headers);
187
+ case 409:
188
+ return new ConflictError(defaultMessage, data, headers);
189
+ case 422:
190
+ return new UnprocessableEntityError(defaultMessage, data, headers);
191
+ case 429:
192
+ return new TooManyRequestsError(defaultMessage, data, headers);
193
+ // Generic 4xx
194
+ case 402:
195
+ case 406:
196
+ case 407:
197
+ case 408:
198
+ case 410:
199
+ case 411:
200
+ case 412:
201
+ case 413:
202
+ case 414:
203
+ case 415:
204
+ case 416:
205
+ case 417:
206
+ case 418:
207
+ case 421:
208
+ case 423:
209
+ case 424:
210
+ case 425:
211
+ case 426:
212
+ case 428:
213
+ case 431:
214
+ case 451:
215
+ return new ClientError(defaultMessage, status, data, headers);
216
+ // 5xx Server Errors
217
+ case 500:
218
+ return new InternalServerError(defaultMessage, data, headers);
219
+ case 502:
220
+ return new BadGatewayError(defaultMessage, data, headers);
221
+ case 503:
222
+ return new ServiceUnavailableError(defaultMessage, data, headers);
223
+ case 504:
224
+ return new GatewayTimeoutError(defaultMessage, data, headers);
225
+ // Generic 5xx
226
+ case 501:
227
+ case 505:
228
+ case 506:
229
+ case 507:
230
+ case 508:
231
+ case 510:
232
+ case 511:
233
+ return new ServerError(defaultMessage, status, data, headers);
234
+ default:
235
+ return new FetchError(defaultMessage, status, data, headers);
236
+ }
237
+ }
238
+ __name(createFetchError, "createFetchError");
239
+ var HookRegistry = class {
240
+ static {
241
+ __name(this, "HookRegistry");
242
+ }
243
+ hooks = /* @__PURE__ */ new Map();
244
+ constructor(config) {
245
+ if (config) {
246
+ this.registerFromConfig(config);
247
+ }
248
+ }
249
+ /**
250
+ * Register hooks from a configuration object
251
+ */
252
+ registerFromConfig(config) {
253
+ for (const [stage, hooks] of Object.entries(config)) {
254
+ if (hooks && Array.isArray(hooks)) {
255
+ for (const hook of hooks) {
256
+ this.register(stage, hook);
257
+ }
258
+ }
259
+ }
260
+ }
261
+ /**
262
+ * Register a hook for a specific stage
263
+ */
264
+ register(stage, hook) {
265
+ if (!this.hooks.has(stage)) {
266
+ this.hooks.set(stage, []);
267
+ }
268
+ this.hooks.get(stage).push(hook);
269
+ }
270
+ /**
271
+ * Remove a specific hook from a stage
272
+ */
273
+ remove(stage, hook) {
274
+ const hooks = this.hooks.get(stage);
275
+ if (!hooks) {
276
+ return false;
277
+ }
278
+ const index = hooks.indexOf(hook);
279
+ if (index === -1) {
280
+ return false;
281
+ }
282
+ hooks.splice(index, 1);
283
+ return true;
284
+ }
285
+ /**
286
+ * Clear all hooks for a specific stage, or all hooks if no stage is provided
287
+ */
288
+ clear(stage) {
289
+ if (stage) {
290
+ this.hooks.delete(stage);
291
+ } else {
292
+ this.hooks.clear();
293
+ }
294
+ }
295
+ /**
296
+ * Get all hooks for a specific stage
297
+ */
298
+ get(stage) {
299
+ return this.hooks.get(stage) || [];
300
+ }
301
+ /**
302
+ * Execute all hooks for a specific stage in registration order
303
+ */
304
+ async execute(stage, context) {
305
+ const hooks = this.get(stage);
306
+ for (const hook of hooks) {
307
+ await hook(context);
308
+ }
309
+ }
310
+ /**
311
+ * Check if any hooks are registered for a stage
312
+ */
313
+ has(stage) {
314
+ return this.hooks.has(stage) && this.hooks.get(stage).length > 0;
315
+ }
316
+ };
317
+ var exponentialStrategy = /* @__PURE__ */ __name((attempt, baseBackoffMs) => {
318
+ return baseBackoffMs * Math.pow(2, attempt);
319
+ }, "exponentialStrategy");
320
+ var linearStrategy = /* @__PURE__ */ __name((attempt, baseBackoffMs) => {
321
+ return baseBackoffMs * (attempt + 1);
322
+ }, "linearStrategy");
323
+ function getRetryStrategy(strategy) {
324
+ if (typeof strategy === "function") {
325
+ return strategy;
326
+ }
327
+ switch (strategy) {
328
+ case "exponential":
329
+ return exponentialStrategy;
330
+ case "linear":
331
+ return linearStrategy;
332
+ default:
333
+ return exponentialStrategy;
334
+ }
335
+ }
336
+ __name(getRetryStrategy, "getRetryStrategy");
337
+ function calculateRetryDelay(attempt, strategy, baseBackoffMs) {
338
+ const strategyFn = getRetryStrategy(strategy);
339
+ return strategyFn(attempt, baseBackoffMs);
340
+ }
341
+ __name(calculateRetryDelay, "calculateRetryDelay");
342
+ async function* parseSSEStream(response) {
343
+ if (!response.body) {
344
+ return;
345
+ }
346
+ const reader = response.body.getReader();
347
+ const decoder = new TextDecoder();
348
+ let buffer = "";
349
+ try {
350
+ while (true) {
351
+ const { done, value } = await reader.read();
352
+ if (done) break;
353
+ buffer += decoder.decode(value, {
354
+ stream: true
355
+ });
356
+ const lines = buffer.split("\n");
357
+ buffer = lines.pop() || "";
358
+ let currentEvent = {};
359
+ for (const line of lines) {
360
+ if (line.trim() === "") {
361
+ if (currentEvent.data !== void 0) {
362
+ yield currentEvent.data;
363
+ }
364
+ currentEvent = {};
365
+ continue;
366
+ }
367
+ const colonIndex = line.indexOf(":");
368
+ if (colonIndex === -1) continue;
369
+ const field = line.substring(0, colonIndex).trim();
370
+ const value2 = line.substring(colonIndex + 1).trim();
371
+ if (field === "data") {
372
+ currentEvent.data = currentEvent.data ? currentEvent.data + "\n" + value2 : value2;
373
+ } else if (field === "event") {
374
+ currentEvent.type = value2;
375
+ } else if (field === "id") {
376
+ currentEvent.id = value2;
377
+ }
378
+ }
379
+ }
380
+ if (buffer.trim()) {
381
+ const lines = buffer.split("\n");
382
+ let currentEvent = {};
383
+ for (const line of lines) {
384
+ if (line.trim() === "" && currentEvent.data !== void 0) {
385
+ yield currentEvent.data;
386
+ currentEvent = {};
387
+ continue;
388
+ }
389
+ const colonIndex = line.indexOf(":");
390
+ if (colonIndex !== -1) {
391
+ const field = line.substring(0, colonIndex).trim();
392
+ const value = line.substring(colonIndex + 1).trim();
393
+ if (field === "data") {
394
+ currentEvent.data = currentEvent.data ? currentEvent.data + "\n" + value : value;
395
+ }
396
+ }
397
+ }
398
+ if (currentEvent.data !== void 0) {
399
+ yield currentEvent.data;
400
+ }
401
+ }
402
+ } finally {
403
+ reader.releaseLock();
404
+ }
405
+ }
406
+ __name(parseSSEStream, "parseSSEStream");
407
+ async function* parseNDJSONStream(response) {
408
+ if (!response.body) {
409
+ return;
410
+ }
411
+ const reader = response.body.getReader();
412
+ const decoder = new TextDecoder();
413
+ let buffer = "";
414
+ try {
415
+ while (true) {
416
+ const { done, value } = await reader.read();
417
+ if (done) break;
418
+ buffer += decoder.decode(value, {
419
+ stream: true
420
+ });
421
+ const lines = buffer.split("\n");
422
+ buffer = lines.pop() || "";
423
+ for (const line of lines) {
424
+ const trimmed = line.trim();
425
+ if (trimmed === "") continue;
426
+ try {
427
+ const parsed = JSON.parse(trimmed);
428
+ yield parsed;
429
+ } catch (error) {
430
+ console.warn("Skipping invalid JSON line:", trimmed);
431
+ }
432
+ }
433
+ }
434
+ if (buffer.trim()) {
435
+ try {
436
+ const parsed = JSON.parse(buffer.trim());
437
+ yield parsed;
438
+ } catch (error) {
439
+ console.warn("Skipping invalid JSON in buffer:", buffer.trim());
440
+ }
441
+ }
442
+ } finally {
443
+ reader.releaseLock();
444
+ }
445
+ }
446
+ __name(parseNDJSONStream, "parseNDJSONStream");
447
+ async function* parseChunkedStream(response) {
448
+ if (!response.body) {
449
+ return;
450
+ }
451
+ const reader = response.body.getReader();
452
+ const decoder = new TextDecoder();
453
+ try {
454
+ while (true) {
455
+ const { done, value } = await reader.read();
456
+ if (done) break;
457
+ const chunk = decoder.decode(value, {
458
+ stream: true
459
+ });
460
+ yield chunk;
461
+ }
462
+ } finally {
463
+ reader.releaseLock();
464
+ }
465
+ }
466
+ __name(parseChunkedStream, "parseChunkedStream");
467
+ function isBrowser() {
468
+ return typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.window.document !== "undefined";
469
+ }
470
+ __name(isBrowser, "isBrowser");
471
+ function isNode() {
472
+ return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
473
+ }
474
+ __name(isNode, "isNode");
475
+ function encodeBase64(str) {
476
+ if (isBrowser()) {
477
+ if (typeof btoa !== "undefined") {
478
+ return btoa(str);
479
+ }
480
+ throw new Error("btoa is not available. This should not happen in a browser environment.");
481
+ } else {
482
+ if (typeof Buffer !== "undefined") {
483
+ return Buffer.from(str, "utf-8").toString("base64");
484
+ }
485
+ throw new Error("Buffer is not available. Please ensure you're running in Node.js or provide a polyfill.");
486
+ }
487
+ }
488
+ __name(encodeBase64, "encodeBase64");
489
+ function isFetchAvailable() {
490
+ return typeof fetch !== "undefined";
491
+ }
492
+ __name(isFetchAvailable, "isFetchAvailable");
493
+ function isAbortControllerAvailable() {
494
+ return typeof AbortController !== "undefined";
495
+ }
496
+ __name(isAbortControllerAvailable, "isAbortControllerAvailable");
497
+ function getFetchErrorMessage() {
498
+ if (isBrowser()) {
499
+ return "fetch is not available in this browser. Please use a modern browser or provide a polyfill.";
500
+ } else {
501
+ return "fetch is not available. Node.js 22+ includes native fetch. For older versions, please provide a custom fetch implementation (e.g., from 'undici' or 'node-fetch').";
502
+ }
503
+ }
504
+ __name(getFetchErrorMessage, "getFetchErrorMessage");
505
+ function serializeQueryParams(query) {
506
+ const params = new URLSearchParams();
507
+ for (const [key, value] of Object.entries(query)) {
508
+ if (value === void 0 || value === null) {
509
+ continue;
510
+ }
511
+ if (Array.isArray(value)) {
512
+ for (const item of value) {
513
+ if (item !== void 0 && item !== null) {
514
+ params.append(key, String(item));
515
+ }
516
+ }
517
+ } else {
518
+ params.set(key, String(value));
519
+ }
520
+ }
521
+ return params;
522
+ }
523
+ __name(serializeQueryParams, "serializeQueryParams");
524
+ function buildUrl(baseUrl, path, query) {
525
+ let normalizedPath = path || "";
526
+ if (normalizedPath.length > 1 && normalizedPath.endsWith("/")) {
527
+ normalizedPath = normalizedPath.slice(0, -1);
528
+ }
529
+ let normalizedBaseUrl = baseUrl || "";
530
+ if (normalizedBaseUrl) {
531
+ try {
532
+ const baseUrlObj = new URL(normalizedBaseUrl);
533
+ if (baseUrlObj.pathname && baseUrlObj.pathname !== "/" && !normalizedBaseUrl.endsWith("/")) {
534
+ normalizedBaseUrl = normalizedBaseUrl + "/";
535
+ }
536
+ } catch {
537
+ }
538
+ }
539
+ if (normalizedPath.startsWith("/")) {
540
+ normalizedPath = normalizedPath.slice(1);
541
+ }
542
+ const url = new URL(normalizedPath, normalizedBaseUrl);
543
+ if (query) {
544
+ const params = serializeQueryParams(query);
545
+ const keys = Array.from(new Set(params.keys()));
546
+ for (const key of keys) {
547
+ url.searchParams.delete(key);
548
+ for (const value of params.getAll(key)) {
549
+ url.searchParams.append(key, value);
550
+ }
551
+ }
552
+ }
553
+ return url;
554
+ }
555
+ __name(buildUrl, "buildUrl");
556
+ function getContentType(body) {
557
+ if (body === null || body === void 0) {
558
+ return void 0;
559
+ }
560
+ if (body instanceof FormData) {
561
+ return void 0;
562
+ }
563
+ if (body instanceof URLSearchParams) {
564
+ return "application/x-www-form-urlencoded";
565
+ }
566
+ if (typeof body === "string") {
567
+ try {
568
+ JSON.parse(body);
569
+ return "application/json";
570
+ } catch {
571
+ return "text/plain";
572
+ }
573
+ }
574
+ if (typeof body === "object") {
575
+ return "application/json";
576
+ }
577
+ return void 0;
578
+ }
579
+ __name(getContentType, "getContentType");
580
+ function serializeBody(body, contentType) {
581
+ if (body === null || body === void 0) {
582
+ return null;
583
+ }
584
+ if (typeof body === "string" || body instanceof FormData || body instanceof URLSearchParams || body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
585
+ return body;
586
+ }
587
+ if (contentType === "application/x-www-form-urlencoded" && typeof body === "object" && body !== null && !Array.isArray(body)) {
588
+ const params = new URLSearchParams();
589
+ for (const [key, value] of Object.entries(body)) {
590
+ if (value !== null && value !== void 0) {
591
+ if (Array.isArray(value)) {
592
+ for (const item of value) {
593
+ params.append(key, String(item));
594
+ }
595
+ } else {
596
+ params.append(key, String(value));
597
+ }
598
+ }
599
+ }
600
+ return params;
601
+ }
602
+ if (typeof body === "object") {
603
+ return JSON.stringify(body);
604
+ }
605
+ return String(body);
606
+ }
607
+ __name(serializeBody, "serializeBody");
608
+ async function parseResponse(response) {
609
+ const contentType = response.headers.get("content-type") || "";
610
+ if (contentType.includes("application/json")) {
611
+ return await response.json();
612
+ } else if (contentType.startsWith("text/")) {
613
+ return await response.text();
614
+ } else {
615
+ return await response.arrayBuffer();
616
+ }
617
+ }
618
+ __name(parseResponse, "parseResponse");
619
+ function isSuccessResponse(response) {
620
+ return response.ok;
621
+ }
622
+ __name(isSuccessResponse, "isSuccessResponse");
623
+ var FetchClient = class {
624
+ static {
625
+ __name(this, "FetchClient");
626
+ }
627
+ hookRegistry;
628
+ cfg;
629
+ constructor(config = {}) {
630
+ this.cfg = config;
631
+ if (!this.cfg.baseURL) {
632
+ this.cfg.baseURL = "";
633
+ }
634
+ this.hookRegistry = new HookRegistry(this.cfg.hooks);
635
+ if (!isFetchAvailable() && !this.cfg.fetch) {
636
+ throw new Error(getFetchErrorMessage());
637
+ }
638
+ }
639
+ /**
640
+ * Add an authentication strategy
641
+ */
642
+ addAuthStrategy(strategy) {
643
+ if (!this.cfg.auth) {
644
+ this.cfg.auth = {
645
+ strategies: []
646
+ };
647
+ }
648
+ this.cfg.auth.strategies.push(strategy);
649
+ }
650
+ /**
651
+ * Remove all authentication strategies
652
+ */
653
+ clearAuthStrategies() {
654
+ if (this.cfg.auth) {
655
+ this.cfg.auth.strategies = [];
656
+ }
657
+ }
658
+ /**
659
+ * Register a hook for a specific lifecycle stage
660
+ */
661
+ useHook(stage, hook) {
662
+ this.hookRegistry.register(stage, hook);
663
+ }
664
+ /**
665
+ * Remove a hook
666
+ */
667
+ removeHook(stage, hook) {
668
+ return this.hookRegistry.remove(stage, hook);
669
+ }
670
+ /**
671
+ * Clear hooks for a stage or all hooks
672
+ */
673
+ clearHooks(stage) {
674
+ this.hookRegistry.clear(stage);
675
+ }
676
+ /**
677
+ * Make an HTTP request
678
+ */
679
+ async request(init) {
680
+ let url = buildUrl(this.cfg.baseURL || "", init.path, init.query);
681
+ const headers = new Headers(this.cfg.headers || {});
682
+ if (init.headers) {
683
+ if (init.headers instanceof Headers) {
684
+ init.headers.forEach((value, key) => {
685
+ headers.set(key, value);
686
+ });
687
+ } else {
688
+ Object.entries(init.headers).forEach(([key, value]) => {
689
+ headers.set(key, String(value));
690
+ });
691
+ }
692
+ }
693
+ await this.applyAuthentication(headers, url);
694
+ let bodyContentType;
695
+ if (init.body !== void 0) {
696
+ bodyContentType = headers.get("Content-Type") || void 0;
697
+ if (!bodyContentType) {
698
+ bodyContentType = getContentType(init.body);
699
+ if (bodyContentType) {
700
+ headers.set("Content-Type", bodyContentType);
701
+ }
702
+ }
703
+ }
704
+ const retries = this.cfg.retry?.retries ?? 0;
705
+ const baseBackoff = this.cfg.retry?.backoffMs ?? 300;
706
+ const retryOn = this.cfg.retry?.retryOn ?? [
707
+ 429,
708
+ 500,
709
+ 502,
710
+ 503,
711
+ 504
712
+ ];
713
+ const retryStrategy = this.cfg.retry?.strategy ?? "exponential";
714
+ let lastError;
715
+ for (let attempt = 0; attempt <= retries + 1; attempt++) {
716
+ try {
717
+ let attemptUrl = buildUrl(this.cfg.baseURL || "", init.path, init.query);
718
+ const attemptHeaders = new Headers(headers);
719
+ await this.applyAuthentication(attemptHeaders, attemptUrl);
720
+ return await this.doRequest(attemptUrl, init, attemptHeaders, attempt, bodyContentType);
721
+ } catch (err) {
722
+ lastError = err;
723
+ const shouldRetry = this.shouldRetry(err, attempt, retries, retryOn);
724
+ if (shouldRetry) {
725
+ if (this.hookRegistry.has("beforeRetry")) {
726
+ await this.hookRegistry.execute("beforeRetry", {
727
+ url: url.toString(),
728
+ init: {
729
+ ...init,
730
+ headers
731
+ },
732
+ attempt,
733
+ error: err,
734
+ retryCount: attempt
735
+ });
736
+ }
737
+ const delay = calculateRetryDelay(attempt, retryStrategy, baseBackoff);
738
+ await new Promise((resolve) => setTimeout(resolve, delay));
739
+ if (this.hookRegistry.has("afterRetry")) {
740
+ await this.hookRegistry.execute("afterRetry", {
741
+ url: url.toString(),
742
+ init: {
743
+ ...init,
744
+ headers
745
+ },
746
+ attempt,
747
+ error: err,
748
+ retryCount: attempt,
749
+ success: false
750
+ });
751
+ }
752
+ continue;
753
+ }
754
+ throw err;
755
+ }
756
+ }
757
+ throw lastError;
758
+ }
759
+ /**
760
+ * Make a streaming HTTP request
761
+ */
762
+ async *requestStream(init) {
763
+ let url = buildUrl(this.cfg.baseURL || "", init.path, init.query);
764
+ const headers = new Headers(this.cfg.headers || {});
765
+ if (init.headers) {
766
+ if (init.headers instanceof Headers) {
767
+ init.headers.forEach((value, key) => {
768
+ headers.set(key, value);
769
+ });
770
+ } else {
771
+ Object.entries(init.headers).forEach(([key, value]) => {
772
+ headers.set(key, String(value));
773
+ });
774
+ }
775
+ }
776
+ await this.applyAuthentication(headers, url);
777
+ let bodyContentType = headers.get("Content-Type") || void 0;
778
+ if (init.contentType && !bodyContentType) {
779
+ bodyContentType = init.contentType;
780
+ headers.set("Content-Type", bodyContentType);
781
+ }
782
+ const fetchInit = {
783
+ ...init,
784
+ headers,
785
+ body: serializeBody(init.body, bodyContentType)
786
+ };
787
+ if (this.cfg.credentials !== void 0) {
788
+ fetchInit.credentials = this.cfg.credentials;
789
+ }
790
+ if (this.hookRegistry.has("beforeRequest")) {
791
+ await this.hookRegistry.execute("beforeRequest", {
792
+ url: url.toString(),
793
+ init: fetchInit,
794
+ attempt: 0
795
+ });
796
+ }
797
+ let controller;
798
+ let timeoutId;
799
+ const existingSignal = fetchInit.signal;
800
+ if (this.cfg.timeoutMs && typeof AbortController !== "undefined") {
801
+ controller = new AbortController();
802
+ if (existingSignal) {
803
+ if (existingSignal.aborted) {
804
+ controller.abort();
805
+ } else {
806
+ existingSignal.addEventListener("abort", () => {
807
+ controller?.abort();
808
+ });
809
+ }
810
+ }
811
+ fetchInit.signal = controller.signal;
812
+ timeoutId = setTimeout(() => {
813
+ controller?.abort();
814
+ if (this.hookRegistry.has("onTimeout")) {
815
+ this.hookRegistry.execute("onTimeout", {
816
+ url: url.toString(),
817
+ init: fetchInit,
818
+ attempt: 0,
819
+ timeoutMs: this.cfg.timeoutMs
820
+ });
821
+ }
822
+ }, this.cfg.timeoutMs);
823
+ }
824
+ try {
825
+ const fetchFn = this.cfg.fetch || fetch;
826
+ const res = await fetchFn(url.toString(), fetchInit);
827
+ if (this.hookRegistry.has("afterRequest")) {
828
+ await this.hookRegistry.execute("afterRequest", {
829
+ url: url.toString(),
830
+ init: fetchInit,
831
+ attempt: 0,
832
+ response: res
833
+ });
834
+ }
835
+ if (!res.ok) {
836
+ const parsed = await parseResponse(res);
837
+ const error = createFetchError(res.status, parsed?.message || `HTTP ${res.status}`, parsed, res.headers);
838
+ if (this.hookRegistry.has("onError")) {
839
+ await this.hookRegistry.execute("onError", {
840
+ url: url.toString(),
841
+ init: fetchInit,
842
+ attempt: 0,
843
+ error
844
+ });
845
+ }
846
+ throw error;
847
+ }
848
+ if (this.hookRegistry.has("onStreamStart")) {
849
+ await this.hookRegistry.execute("onStreamStart", {
850
+ url: url.toString(),
851
+ init: fetchInit,
852
+ attempt: 0,
853
+ response: res
854
+ });
855
+ }
856
+ const streamingFormat = init.streamingFormat || "chunked";
857
+ if (streamingFormat === "sse") {
858
+ for await (const chunk of parseSSEStream(res)) {
859
+ let transformedChunk = chunk;
860
+ if (this.hookRegistry.has("onStreamChunk")) {
861
+ await this.hookRegistry.execute("onStreamChunk", {
862
+ url: url.toString(),
863
+ init: fetchInit,
864
+ attempt: 0,
865
+ chunk
866
+ });
867
+ }
868
+ yield transformedChunk;
869
+ }
870
+ } else if (streamingFormat === "ndjson") {
871
+ for await (const chunk of parseNDJSONStream(res)) {
872
+ let transformedChunk = chunk;
873
+ if (this.hookRegistry.has("onStreamChunk")) {
874
+ await this.hookRegistry.execute("onStreamChunk", {
875
+ url: url.toString(),
876
+ init: fetchInit,
877
+ attempt: 0,
878
+ chunk
879
+ });
880
+ }
881
+ yield transformedChunk;
882
+ }
883
+ } else {
884
+ for await (const chunk of parseChunkedStream(res)) {
885
+ let transformedChunk = chunk;
886
+ if (this.hookRegistry.has("onStreamChunk")) {
887
+ await this.hookRegistry.execute("onStreamChunk", {
888
+ url: url.toString(),
889
+ init: fetchInit,
890
+ attempt: 0,
891
+ chunk
892
+ });
893
+ }
894
+ yield transformedChunk;
895
+ }
896
+ }
897
+ if (this.hookRegistry.has("onStreamEnd")) {
898
+ await this.hookRegistry.execute("onStreamEnd", {
899
+ url: url.toString(),
900
+ init: fetchInit,
901
+ attempt: 0,
902
+ response: res
903
+ });
904
+ }
905
+ } catch (err) {
906
+ if (this.hookRegistry.has("onError")) {
907
+ await this.hookRegistry.execute("onError", {
908
+ url: url.toString(),
909
+ init: fetchInit,
910
+ attempt: 0,
911
+ error: err
912
+ });
913
+ }
914
+ throw err;
915
+ } finally {
916
+ if (timeoutId) {
917
+ clearTimeout(timeoutId);
918
+ }
919
+ }
920
+ }
921
+ /**
922
+ * Internal method to execute a single request attempt
923
+ */
924
+ async doRequest(url, init, baseHeaders, attempt, contentType) {
925
+ const requestHeaders = baseHeaders;
926
+ const fetchInit = {
927
+ ...init,
928
+ headers: requestHeaders,
929
+ body: serializeBody(init.body, contentType)
930
+ };
931
+ if (this.cfg.credentials !== void 0) {
932
+ fetchInit.credentials = this.cfg.credentials;
933
+ }
934
+ if (this.hookRegistry.has("beforeRequest")) {
935
+ await this.hookRegistry.execute("beforeRequest", {
936
+ url: url.toString(),
937
+ init: fetchInit,
938
+ attempt
939
+ });
940
+ }
941
+ let controller;
942
+ let timeoutId;
943
+ const existingSignal = fetchInit.signal;
944
+ if (this.cfg.timeoutMs && typeof AbortController !== "undefined") {
945
+ controller = new AbortController();
946
+ if (existingSignal) {
947
+ if (existingSignal.aborted) {
948
+ controller.abort();
949
+ } else {
950
+ existingSignal.addEventListener("abort", () => {
951
+ controller?.abort();
952
+ });
953
+ }
954
+ }
955
+ fetchInit.signal = controller.signal;
956
+ timeoutId = setTimeout(() => {
957
+ controller?.abort();
958
+ if (this.hookRegistry.has("onTimeout")) {
959
+ this.hookRegistry.execute("onTimeout", {
960
+ url: url.toString(),
961
+ init: fetchInit,
962
+ attempt,
963
+ timeoutMs: this.cfg.timeoutMs
964
+ });
965
+ }
966
+ }, this.cfg.timeoutMs);
967
+ }
968
+ try {
969
+ const fetchFn = this.cfg.fetch || fetch;
970
+ const res = await fetchFn(url.toString(), fetchInit);
971
+ if (this.hookRegistry.has("afterRequest")) {
972
+ await this.hookRegistry.execute("afterRequest", {
973
+ url: url.toString(),
974
+ init: fetchInit,
975
+ attempt,
976
+ response: res
977
+ });
978
+ }
979
+ const parsed = await parseResponse(res);
980
+ if (this.hookRegistry.has("afterResponse")) {
981
+ await this.hookRegistry.execute("afterResponse", {
982
+ url: url.toString(),
983
+ init: fetchInit,
984
+ attempt,
985
+ response: res,
986
+ data: parsed
987
+ });
988
+ }
989
+ if (!isSuccessResponse(res)) {
990
+ const error = createFetchError(res.status, parsed?.message || `HTTP ${res.status}`, parsed, res.headers);
991
+ if (this.hookRegistry.has("onError")) {
992
+ await this.hookRegistry.execute("onError", {
993
+ url: url.toString(),
994
+ init: fetchInit,
995
+ attempt,
996
+ error
997
+ });
998
+ }
999
+ throw error;
1000
+ }
1001
+ return parsed;
1002
+ } catch (err) {
1003
+ if (this.hookRegistry.has("onError")) {
1004
+ await this.hookRegistry.execute("onError", {
1005
+ url: url.toString(),
1006
+ init: fetchInit,
1007
+ attempt,
1008
+ error: err
1009
+ });
1010
+ }
1011
+ if (err instanceof DOMException) {
1012
+ throw err;
1013
+ }
1014
+ if (err instanceof FetchError) {
1015
+ throw err;
1016
+ }
1017
+ const status = err?.status;
1018
+ const statusCode = typeof status === "number" ? status : 0;
1019
+ if (typeof err === "string") {
1020
+ throw createFetchError(statusCode, err);
1021
+ }
1022
+ throw createFetchError(statusCode, err?.message || "Network error");
1023
+ } finally {
1024
+ if (timeoutId) {
1025
+ clearTimeout(timeoutId);
1026
+ }
1027
+ }
1028
+ }
1029
+ /**
1030
+ * Apply authentication strategies
1031
+ */
1032
+ async applyAuthentication(headers, url) {
1033
+ if (!this.cfg.auth?.strategies) {
1034
+ return;
1035
+ }
1036
+ for (const strategy of this.cfg.auth.strategies) {
1037
+ await this.applyAuthStrategy(strategy, headers, url);
1038
+ }
1039
+ }
1040
+ /**
1041
+ * Apply a single authentication strategy
1042
+ */
1043
+ async applyAuthStrategy(strategy, headers, url) {
1044
+ switch (strategy.type) {
1045
+ case "bearer": {
1046
+ const token = typeof strategy.token === "function" ? await strategy.token() : strategy.token;
1047
+ if (token != null) {
1048
+ const headerName = strategy.headerName || "Authorization";
1049
+ headers.set(headerName, `Bearer ${String(token)}`);
1050
+ }
1051
+ break;
1052
+ }
1053
+ case "basic": {
1054
+ const encoded = encodeBase64(`${strategy.username}:${strategy.password}`);
1055
+ headers.set("Authorization", `Basic ${encoded}`);
1056
+ break;
1057
+ }
1058
+ case "apiKey": {
1059
+ const key = typeof strategy.key === "function" ? await strategy.key() : strategy.key;
1060
+ if (key != null) {
1061
+ switch (strategy.location) {
1062
+ case "header":
1063
+ headers.set(strategy.name, String(key));
1064
+ break;
1065
+ case "query":
1066
+ url.searchParams.set(strategy.name, String(key));
1067
+ break;
1068
+ case "cookie":
1069
+ headers.set("Cookie", `${strategy.name}=${String(key)}`);
1070
+ break;
1071
+ }
1072
+ }
1073
+ break;
1074
+ }
1075
+ case "custom":
1076
+ await strategy.apply(headers, url);
1077
+ break;
1078
+ }
1079
+ }
1080
+ /**
1081
+ * Determine if an error should be retried
1082
+ */
1083
+ shouldRetry(error, attempt, maxRetries, retryOn) {
1084
+ if (attempt >= maxRetries) {
1085
+ return false;
1086
+ }
1087
+ if (this.cfg.retry?.retryOnError) {
1088
+ return this.cfg.retry.retryOnError(error);
1089
+ }
1090
+ if (error instanceof FetchError) {
1091
+ return retryOn.includes(error.status);
1092
+ }
1093
+ return true;
1094
+ }
1095
+ };
1096
+
1097
+ // src/utils.ts
27
1098
  async function* paginate(fetchPage, initialQuery = {}, pageSize = 100) {
28
1099
  let offset = Number(initialQuery.offset ?? 0);
29
1100
  const limit = Number(initialQuery.limit ?? pageSize);
@@ -40,11 +1111,15 @@ async function* paginate(fetchPage, initialQuery = {}, pageSize = 100) {
40
1111
  }
41
1112
  async function listAll(fetchPage, query = {}, pageSize = 100) {
42
1113
  const out = [];
43
- for await (const item of paginate(fetchPage, query, pageSize)) out.push(item);
1114
+ for await (const item of paginate(fetchPage, query, pageSize))
1115
+ out.push(item);
44
1116
  return out;
45
1117
  }
46
1118
  // Annotate the CommonJS export names for ESM import in node:
47
1119
  0 && (module.exports = {
48
1120
  listAll,
49
- paginate
1121
+ paginate,
1122
+ parseNDJSONStream,
1123
+ parseSSEStream
50
1124
  });
1125
+ //# sourceMappingURL=utils.js.map