@eudiplo/sdk-core 1.14.0-main.cc24d2f → 1.14.0-main.cc2ac00

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/README.md CHANGED
@@ -12,227 +12,102 @@ pnpm add @eudiplo/sdk-core
12
12
  yarn add @eudiplo/sdk-core
13
13
  ```
14
14
 
15
- ## Quick Start - The Simplest Way
16
-
17
- ### One-liner for Age Verification
15
+ ## Quick Start
18
16
 
19
17
  ```typescript
20
- import { verifyAndWait } from '@eudiplo/sdk-core';
18
+ import { EudiploClient } from '@eudiplo/sdk-core';
21
19
 
22
- const session = await verifyAndWait({
20
+ const client = new EudiploClient({
23
21
  baseUrl: 'https://eudiplo.example.com',
24
22
  clientId: 'my-demo',
25
23
  clientSecret: 'secret',
26
- configId: 'age-over-18',
27
- onUri: (uri) => showQRCode(uri), // Your QR code display function
28
- onUpdate: (s) => console.log('Status:', s.status),
29
24
  });
30
25
 
31
- console.log('Verified!', session.credentials);
32
- ```
33
-
34
- ### Two-step Flow (More Control)
35
-
36
- ```typescript
37
- import { verify } from '@eudiplo/sdk-core';
38
-
39
- // Step 1: Create the request
40
- const { uri, sessionId, waitForCompletion } = await verify({
41
- baseUrl: 'https://eudiplo.example.com',
42
- clientId: 'my-demo',
43
- clientSecret: 'secret',
26
+ // Verification (QR flow)
27
+ const verifyOffer = await client.createPresentationRequest({
44
28
  configId: 'age-over-18',
45
29
  });
30
+ showQRCode(verifyOffer.uri);
31
+ const verifiedSession = await client.waitForSession(verifyOffer.sessionId);
46
32
 
47
- // Step 2: Show QR code
48
- showQRCode(uri);
49
-
50
- // Step 3: Wait for user to scan and respond
51
- const session = await waitForCompletion();
52
- console.log('Verified credentials:', session.credentials);
53
- ```
54
-
55
- ### Credential Issuance
56
-
57
- ```typescript
58
- import { issue } from '@eudiplo/sdk-core';
59
-
60
- const { uri, waitForCompletion } = await issue({
61
- baseUrl: 'https://eudiplo.example.com',
62
- clientId: 'my-demo',
63
- clientSecret: 'secret',
33
+ // Issuance (QR flow)
34
+ const issuanceOffer = await client.createIssuanceOffer({
64
35
  credentialConfigurationIds: ['PID'],
65
36
  claims: {
66
37
  PID: { given_name: 'John', family_name: 'Doe', birthdate: '1990-01-15' },
67
38
  },
68
39
  });
69
-
70
- showQRCode(uri);
71
- await waitForCompletion();
40
+ showQRCode(issuanceOffer.uri);
41
+ await client.waitForSession(issuanceOffer.sessionId);
72
42
  ```
73
43
 
74
44
  ## Full API
75
45
 
76
- ### Factory Functions (Easiest)
46
+ ### Class API
77
47
 
78
- | Function | Description |
79
- | ------------------------ | ----------------------------------------------------------------------------------------- |
80
- | `verify(options)` | Create a presentation request, returns `{ uri, sessionId, waitForCompletion, getStatus }` |
81
- | `issue(options)` | Create an issuance offer, returns `{ uri, sessionId, waitForCompletion, getStatus }` |
82
- | `verifyAndWait(options)` | One-liner: create request + wait for result |
83
- | `issueAndWait(options)` | One-liner: create offer + wait for result |
48
+ Use `EudiploClient` methods directly:
49
+
50
+ | Method | Description |
51
+ | ----------------------------- | ---------------------------------------------- |
52
+ | `createPresentationRequest()` | Create verification request URI and session ID |
53
+ | `createIssuanceOffer()` | Create issuance offer URI and session ID |
54
+ | `waitForSession()` | Poll session until terminal state |
55
+ | `subscribeToSession()` | Subscribe via SSE |
56
+ | `verifyWithDcApi()` | Browser-native DC API end-to-end flow |
84
57
 
85
58
  ### Digital Credentials API (Browser Native)
86
59
 
87
60
  The SDK includes utilities for the [Digital Credentials API](https://wicg.github.io/digital-credentials/), enabling browser-native credential presentation without QR codes.
88
61
 
89
62
  ```typescript
90
- import { isDcApiAvailable, verifyWithDcApi } from '@eudiplo/sdk-core';
63
+ import { isDcApiAvailable, EudiploClient } from '@eudiplo/sdk-core';
64
+
65
+ const client = new EudiploClient({
66
+ baseUrl: 'https://eudiplo.example.com',
67
+ clientId: 'my-demo',
68
+ clientSecret: 'secret',
69
+ });
91
70
 
92
71
  // Check if browser supports DC API
93
72
  if (isDcApiAvailable()) {
94
- const result = await verifyWithDcApi({
95
- baseUrl: 'https://eudiplo.example.com',
96
- clientId: 'my-demo',
97
- clientSecret: 'secret',
73
+ const result = await client.verifyWithDcApi({
98
74
  configId: 'age-over-18',
99
75
  });
100
76
 
101
- console.log('Verified!', result.session.credentials);
77
+ console.log('Verified!', result.credentials);
102
78
  } else {
103
- // Fall back to QR code flow
104
- const session = await verifyAndWait({...});
79
+ // Fall back to QR code flow using EudiploClient methods
105
80
  }
106
81
  ```
107
82
 
108
- #### DC API Functions
83
+ #### DC API Methods
109
84
 
110
- | Function | Description |
111
- | ---------------------- | --------------------------------------------------- |
112
- | `isDcApiAvailable()` | Check if browser supports Digital Credentials API |
113
- | `verifyWithDcApi()` | Complete verification flow using browser-native API |
114
- | `createDcApiRequest()` | Create a `DigitalCredentialRequestOptions` object |
85
+ | Method | Description |
86
+ | -------------------------------------------- | --------------------------------------------------- |
87
+ | `isDcApiAvailable()` | Check if browser supports Digital Credentials API |
88
+ | `client.verifyWithDcApi()` | Complete verification flow using browser-native API |
89
+ | `client.createDcApiPresentationRequest(...)` | Create DC API session with request object |
115
90
 
116
91
  #### Lower-level DC API Usage
117
92
 
118
93
  ```typescript
119
- import { createDcApiRequest, EudiploClient } from '@eudiplo/sdk-core';
94
+ import { EudiploClient } from '@eudiplo/sdk-core';
120
95
 
121
96
  const client = new EudiploClient({...});
122
97
 
123
- // Create presentation request
124
- const { uri, sessionId } = await client.createPresentationRequest({
98
+ // Create DC API session with request object
99
+ const session = await client.createDcApiPresentationRequest({
125
100
  configId: 'age-over-18',
126
- responseType: 'dc-api',
127
- });
128
-
129
- // Create the browser request object
130
- const request = createDcApiRequest(uri);
131
-
132
- // Call the browser API directly
133
- const credential = await navigator.credentials.get(request);
134
-
135
- // Submit the response and get verified session
136
- const session = await client.submitDcApiResponse(sessionId, credential);
137
- ```
138
-
139
- #### Secure Server/Client Deployment (Recommended for Production)
140
-
141
- When deploying to production, you should **never expose your client credentials to the browser**. The SDK provides helper functions to split the DC API flow between your server (where credentials are safe) and the browser (where the DC API runs).
142
-
143
- **Server-side Functions:**
144
-
145
- | Function | Description |
146
- | -------------------------------- | ------------------------------------------------------ |
147
- | `createDcApiRequestForBrowser()` | Create request on server, return safe data for browser |
148
- | `submitDcApiWalletResponse()` | Submit wallet response to EUDIPLO from server |
149
-
150
- **Browser-side Functions:**
151
-
152
- | Function | Description |
153
- | ------------- | ------------------------------------------------------ |
154
- | `callDcApi()` | Call the native DC API with a request from your server |
155
-
156
- ##### Example: Express.js Backend + Browser Frontend
157
-
158
- **Server (Express.js / Next.js API route):**
159
-
160
- ```typescript
161
- import {
162
- createDcApiRequestForBrowser,
163
- submitDcApiWalletResponse,
164
- } from '@eudiplo/sdk-core';
165
-
166
- // POST /api/start-verification
167
- app.post('/api/start-verification', async (req, res) => {
168
- const requestData = await createDcApiRequestForBrowser({
169
- baseUrl: process.env.EUDIPLO_URL,
170
- clientId: process.env.EUDIPLO_CLIENT_ID, // ✅ Safe on server
171
- clientSecret: process.env.EUDIPLO_SECRET, // ✅ Safe on server
172
- configId: 'age-over-18',
173
- });
174
-
175
- // Only safe data is sent to browser (no secrets)
176
- res.json(requestData);
177
- });
178
-
179
- // POST /api/complete-verification
180
- app.post('/api/complete-verification', async (req, res) => {
181
- const { responseUri, walletResponse } = req.body;
182
-
183
- const result = await submitDcApiWalletResponse({
184
- responseUri,
185
- walletResponse,
186
- sendResponse: true, // Get verified claims back
187
- });
188
-
189
- // result.credentials contains the verified data
190
- res.json(result);
191
101
  });
192
- ```
193
-
194
- **Browser (React / vanilla JS):**
195
102
 
196
- ```typescript
197
- import { callDcApi, isDcApiAvailable } from '@eudiplo/sdk-core';
198
-
199
- async function verifyAge() {
200
- // 1. Get the request from your server (credentials stay on server)
201
- const requestData = await fetch('/api/start-verification', {
202
- method: 'POST',
203
- }).then((r) => r.json());
204
-
205
- // 2. Check DC API support and call it locally
206
- if (!isDcApiAvailable()) {
207
- throw new Error('Digital Credentials API not supported');
208
- }
209
-
210
- const walletResponse = await callDcApi(requestData.requestObject);
211
-
212
- // 3. Send the wallet response back to your server for verification
213
- const result = await fetch('/api/complete-verification', {
214
- method: 'POST',
215
- headers: { 'Content-Type': 'application/json' },
216
- body: JSON.stringify({
217
- responseUri: requestData.responseUri,
218
- walletResponse,
219
- }),
220
- }).then((r) => r.json());
221
-
222
- console.log('Verified!', result.credentials);
223
- return result;
224
- }
103
+ // Submit using the browser-native DC API end-to-end
104
+ const result = await client.submitDcApiPresentation(session);
225
105
  ```
226
106
 
227
- **What stays where:**
107
+ #### Secure Deployment Note
228
108
 
229
- | Data | Location | Safe to expose? |
230
- | ------------------------------ | ---------------- | ------------------- |
231
- | `clientId` / `clientSecret` | Server only | ❌ Never expose |
232
- | `requestObject` (signed JWT) | Server → Browser | ✅ Yes |
233
- | `responseUri` | Server → Browser | ✅ Yes |
234
- | Wallet response (encrypted VP) | Browser → Server | ✅ Yes |
235
- | Verified credentials | Server only | Depends on use case |
109
+ For production deployments, keep `clientId` and `clientSecret` on the server.
110
+ Use `EudiploClient` methods to run the full flow (`createDcApiPresentationRequest` + `submitDcApiPresentation`) from trusted backend/application code.
236
111
 
237
112
  ### Class-based API (More Control)
238
113
 
@@ -1,4 +1,4 @@
1
- import { b as Config, C as Client } from '../../types.gen-D8LjzWc0.mjs';
1
+ import { b as Config, C as Client } from '../../types.gen-zNuA7BkO.mjs';
2
2
 
3
3
  declare const createClient: (config?: Config) => Client;
4
4
 
@@ -1,4 +1,4 @@
1
- import { b as Config, C as Client } from '../../types.gen-D8LjzWc0.js';
1
+ import { b as Config, C as Client } from '../../types.gen-zNuA7BkO.js';
2
2
 
3
3
  declare const createClient: (config?: Config) => Client;
4
4
 
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/api/core/serverSentEvents.gen.ts
4
- var createSseClient = ({
4
+ function createSseClient({
5
5
  onRequest,
6
6
  onSseError,
7
7
  onSseEvent,
@@ -13,7 +13,7 @@ var createSseClient = ({
13
13
  sseSleepFn,
14
14
  url,
15
15
  ...options
16
- }) => {
16
+ }) {
17
17
  let lastEventId;
18
18
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
19
19
  const createStream = async function* () {
@@ -41,10 +41,7 @@ var createSseClient = ({
41
41
  }
42
42
  const _fetch = options.fetch ?? globalThis.fetch;
43
43
  const response = await _fetch(request);
44
- if (!response.ok)
45
- throw new Error(
46
- `SSE failed: ${response.status} ${response.statusText}`
47
- );
44
+ if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
48
45
  if (!response.body) throw new Error("No body in SSE response");
49
46
  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
50
47
  let buffer = "";
@@ -60,7 +57,7 @@ var createSseClient = ({
60
57
  const { done, value } = await reader.read();
61
58
  if (done) break;
62
59
  buffer += value;
63
- buffer = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
60
+ buffer = buffer.replace(/\r\n?/g, "\n");
64
61
  const chunks = buffer.split("\n\n");
65
62
  buffer = chunks.pop() ?? "";
66
63
  for (const chunk of chunks) {
@@ -75,10 +72,7 @@ var createSseClient = ({
75
72
  } else if (line.startsWith("id:")) {
76
73
  lastEventId = line.replace(/^id:\s*/, "");
77
74
  } else if (line.startsWith("retry:")) {
78
- const parsed = Number.parseInt(
79
- line.replace(/^retry:\s*/, ""),
80
- 10
81
- );
75
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
82
76
  if (!Number.isNaN(parsed)) {
83
77
  retryDelay = parsed;
84
78
  }
@@ -124,17 +118,14 @@ var createSseClient = ({
124
118
  if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
125
119
  break;
126
120
  }
127
- const backoff = Math.min(
128
- retryDelay * 2 ** (attempt - 1),
129
- sseMaxRetryDelay ?? 3e4
130
- );
121
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
131
122
  await sleep(backoff);
132
123
  }
133
124
  }
134
125
  };
135
126
  const stream = createStream();
136
127
  return { stream };
137
- };
128
+ }
138
129
 
139
130
  // src/api/core/pathSerializer.gen.ts
140
131
  var separatorArrayExplode = (style) => {
@@ -235,11 +226,7 @@ var serializeObjectParam = ({
235
226
  if (style !== "deepObject" && !explode) {
236
227
  let values = [];
237
228
  Object.entries(value).forEach(([key, v]) => {
238
- values = [
239
- ...values,
240
- key,
241
- allowReserved ? v : encodeURIComponent(v)
242
- ];
229
+ values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
243
230
  });
244
231
  const joinedValues2 = values.join(",");
245
232
  switch (style) {
@@ -290,10 +277,7 @@ var defaultPathSerializer = ({ path, url: _url }) => {
290
277
  continue;
291
278
  }
292
279
  if (Array.isArray(value)) {
293
- url = url.replace(
294
- match,
295
- serializeArrayParam({ explode, name, style, value })
296
- );
280
+ url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
297
281
  continue;
298
282
  }
299
283
  if (typeof value === "object") {
@@ -381,10 +365,7 @@ var getAuthToken = async (auth, callback) => {
381
365
 
382
366
  // src/api/core/bodySerializer.gen.ts
383
367
  var jsonBodySerializer = {
384
- bodySerializer: (body) => JSON.stringify(
385
- body,
386
- (_key, value) => typeof value === "bigint" ? value.toString() : value
387
- )
368
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
388
369
  };
389
370
 
390
371
  // src/api/client/utils.gen.ts
@@ -449,9 +430,7 @@ var getParseAs = (contentType) => {
449
430
  if (cleanContent === "multipart/form-data") {
450
431
  return "formData";
451
432
  }
452
- if (["application/", "audio/", "image/", "video/"].some(
453
- (type) => cleanContent.startsWith(type)
454
- )) {
433
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
455
434
  return "blob";
456
435
  }
457
436
  if (cleanContent.startsWith("text/")) {
@@ -468,11 +447,8 @@ var checkForExistence = (options, name) => {
468
447
  }
469
448
  return false;
470
449
  };
471
- var setAuthParams = async ({
472
- security,
473
- ...options
474
- }) => {
475
- for (const auth of security) {
450
+ async function setAuthParams(options) {
451
+ for (const auth of options.security ?? []) {
476
452
  if (checkForExistence(options, auth.name)) {
477
453
  continue;
478
454
  }
@@ -497,7 +473,7 @@ var setAuthParams = async ({
497
473
  break;
498
474
  }
499
475
  }
500
- };
476
+ }
501
477
  var buildUrl = (options) => getUrl({
502
478
  baseUrl: options.baseUrl,
503
479
  path: options.path,
@@ -623,10 +599,7 @@ var createClient = (config = {}) => {
623
599
  serializedBody: void 0
624
600
  };
625
601
  if (opts.security) {
626
- await setAuthParams({
627
- ...opts,
628
- security: opts.security
629
- });
602
+ await setAuthParams(opts);
630
603
  }
631
604
  if (opts.requestValidator) {
632
605
  await opts.requestValidator(opts);
@@ -637,136 +610,121 @@ var createClient = (config = {}) => {
637
610
  if (opts.body === void 0 || opts.serializedBody === "") {
638
611
  opts.headers.delete("Content-Type");
639
612
  }
640
- const url = buildUrl(opts);
641
- return { opts, url };
613
+ const resolvedOpts = opts;
614
+ const url = buildUrl(resolvedOpts);
615
+ return { opts: resolvedOpts, url };
642
616
  };
643
617
  const request = async (options) => {
644
- const { opts, url } = await beforeRequest(options);
645
- const requestInit = {
646
- redirect: "follow",
647
- ...opts,
648
- body: getValidRequestBody(opts)
649
- };
650
- let request2 = new Request(url, requestInit);
651
- for (const fn of interceptors.request.fns) {
652
- if (fn) {
653
- request2 = await fn(request2, opts);
654
- }
655
- }
656
- const _fetch = opts.fetch;
618
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
619
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
620
+ let request2;
657
621
  let response;
658
622
  try {
659
- response = await _fetch(request2);
660
- } catch (error2) {
661
- let finalError2 = error2;
662
- for (const fn of interceptors.error.fns) {
623
+ const { opts, url } = await beforeRequest(options);
624
+ const requestInit = {
625
+ redirect: "follow",
626
+ ...opts,
627
+ body: getValidRequestBody(opts)
628
+ };
629
+ request2 = new Request(url, requestInit);
630
+ for (const fn of interceptors.request.fns) {
663
631
  if (fn) {
664
- finalError2 = await fn(
665
- error2,
666
- void 0,
667
- request2,
668
- opts
669
- );
632
+ request2 = await fn(request2, opts);
670
633
  }
671
634
  }
672
- finalError2 = finalError2 || {};
673
- if (opts.throwOnError) {
674
- throw finalError2;
635
+ const _fetch = opts.fetch;
636
+ response = await _fetch(request2);
637
+ for (const fn of interceptors.response.fns) {
638
+ if (fn) {
639
+ response = await fn(response, request2, opts);
640
+ }
675
641
  }
676
- return opts.responseStyle === "data" ? void 0 : {
677
- error: finalError2,
642
+ const result = {
678
643
  request: request2,
679
- response: void 0
644
+ response
680
645
  };
681
- }
682
- for (const fn of interceptors.response.fns) {
683
- if (fn) {
684
- response = await fn(response, request2, opts);
685
- }
686
- }
687
- const result = {
688
- request: request2,
689
- response
690
- };
691
- if (response.ok) {
692
- const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
693
- if (response.status === 204 || response.headers.get("Content-Length") === "0") {
694
- let emptyData;
646
+ if (response.ok) {
647
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
648
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
649
+ let emptyData;
650
+ switch (parseAs) {
651
+ case "arrayBuffer":
652
+ case "blob":
653
+ case "text":
654
+ emptyData = await response[parseAs]();
655
+ break;
656
+ case "formData":
657
+ emptyData = new FormData();
658
+ break;
659
+ case "stream":
660
+ emptyData = response.body;
661
+ break;
662
+ case "json":
663
+ default:
664
+ emptyData = {};
665
+ break;
666
+ }
667
+ return opts.responseStyle === "data" ? emptyData : {
668
+ data: emptyData,
669
+ ...result
670
+ };
671
+ }
672
+ let data;
695
673
  switch (parseAs) {
696
674
  case "arrayBuffer":
697
675
  case "blob":
676
+ case "formData":
698
677
  case "text":
699
- emptyData = await response[parseAs]();
678
+ data = await response[parseAs]();
700
679
  break;
701
- case "formData":
702
- emptyData = new FormData();
680
+ case "json": {
681
+ const text = await response.text();
682
+ data = text ? JSON.parse(text) : {};
703
683
  break;
684
+ }
704
685
  case "stream":
705
- emptyData = response.body;
706
- break;
707
- case "json":
708
- default:
709
- emptyData = {};
710
- break;
686
+ return opts.responseStyle === "data" ? response.body : {
687
+ data: response.body,
688
+ ...result
689
+ };
690
+ }
691
+ if (parseAs === "json") {
692
+ if (opts.responseValidator) {
693
+ await opts.responseValidator(data);
694
+ }
695
+ if (opts.responseTransformer) {
696
+ data = await opts.responseTransformer(data);
697
+ }
711
698
  }
712
- return opts.responseStyle === "data" ? emptyData : {
713
- data: emptyData,
699
+ return opts.responseStyle === "data" ? data : {
700
+ data,
714
701
  ...result
715
702
  };
716
703
  }
717
- let data;
718
- switch (parseAs) {
719
- case "arrayBuffer":
720
- case "blob":
721
- case "formData":
722
- case "text":
723
- data = await response[parseAs]();
724
- break;
725
- case "json": {
726
- const text = await response.text();
727
- data = text ? JSON.parse(text) : {};
728
- break;
729
- }
730
- case "stream":
731
- return opts.responseStyle === "data" ? response.body : {
732
- data: response.body,
733
- ...result
734
- };
704
+ const textError = await response.text();
705
+ let jsonError;
706
+ try {
707
+ jsonError = JSON.parse(textError);
708
+ } catch {
735
709
  }
736
- if (parseAs === "json") {
737
- if (opts.responseValidator) {
738
- await opts.responseValidator(data);
739
- }
740
- if (opts.responseTransformer) {
741
- data = await opts.responseTransformer(data);
710
+ throw jsonError ?? textError;
711
+ } catch (error) {
712
+ let finalError = error;
713
+ for (const fn of interceptors.error.fns) {
714
+ if (fn) {
715
+ finalError = await fn(finalError, response, request2, options);
742
716
  }
743
717
  }
744
- return opts.responseStyle === "data" ? data : {
745
- data,
746
- ...result
747
- };
748
- }
749
- const textError = await response.text();
750
- let jsonError;
751
- try {
752
- jsonError = JSON.parse(textError);
753
- } catch {
754
- }
755
- const error = jsonError ?? textError;
756
- let finalError = error;
757
- for (const fn of interceptors.error.fns) {
758
- if (fn) {
759
- finalError = await fn(error, response, request2, opts);
718
+ finalError = finalError || {};
719
+ if (throwOnError) {
720
+ throw finalError;
760
721
  }
722
+ return responseStyle === "data" ? void 0 : {
723
+ error: finalError,
724
+ request: request2,
725
+ response
726
+ };
761
727
  }
762
- finalError = finalError || {};
763
- if (opts.throwOnError) {
764
- throw finalError;
765
- }
766
- return opts.responseStyle === "data" ? void 0 : {
767
- error: finalError,
768
- ...result
769
- };
770
728
  };
771
729
  const makeMethodFn = (method) => (options) => request({ ...options, method });
772
730
  const makeSseFn = (method) => async (options) => {
@@ -774,7 +732,6 @@ var createClient = (config = {}) => {
774
732
  return createSseClient({
775
733
  ...opts,
776
734
  body: opts.body,
777
- headers: opts.headers,
778
735
  method,
779
736
  onRequest: async (url2, init) => {
780
737
  let request2 = new Request(url2, init);
@@ -789,8 +746,9 @@ var createClient = (config = {}) => {
789
746
  url
790
747
  });
791
748
  };
749
+ const _buildUrl = (options) => buildUrl({ ..._config, ...options });
792
750
  return {
793
- buildUrl,
751
+ buildUrl: _buildUrl,
794
752
  connect: makeMethodFn("CONNECT"),
795
753
  delete: makeMethodFn("DELETE"),
796
754
  get: makeMethodFn("GET"),