@eudiplo/sdk-core 1.14.0-main.a39e98f → 1.14.0-main.a3bed4b
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 +189 -0
- package/dist/api/client/client.gen.d.mts +1 -1
- package/dist/api/client/client.gen.d.ts +1 -1
- package/dist/api/client/client.gen.js +102 -134
- package/dist/api/client/client.gen.mjs +102 -134
- package/dist/api/client/index.d.mts +4 -4
- package/dist/api/client/index.d.ts +4 -4
- package/dist/api/client/index.js +105 -141
- package/dist/api/client/index.mjs +105 -141
- package/dist/api/client/types.gen.d.mts +1 -1
- package/dist/api/client/types.gen.d.ts +1 -1
- package/dist/api/client.gen.d.mts +15 -2
- package/dist/api/client.gen.d.ts +15 -2
- package/dist/api/client.gen.js +103 -137
- package/dist/api/client.gen.mjs +103 -137
- package/dist/api/index.d.mts +245 -148
- package/dist/api/index.d.ts +245 -148
- package/dist/api/index.js +539 -315
- package/dist/api/index.mjs +482 -278
- package/dist/index.d.mts +368 -16
- package/dist/index.d.ts +368 -16
- package/dist/index.js +929 -325
- package/dist/index.mjs +866 -289
- package/dist/{types.gen-CIiveH8G.d.mts → types.gen-B0nhFpj5.d.mts} +39 -32
- package/dist/{types.gen-CIiveH8G.d.ts → types.gen-B0nhFpj5.d.ts} +39 -32
- package/dist/types.gen-iVMm3ieQ.d.mts +4508 -0
- package/dist/types.gen-iVMm3ieQ.d.ts +4508 -0
- package/package.json +8 -8
- package/dist/client.gen-CU56lLgT.d.mts +0 -2442
- package/dist/client.gen-CsfHl8pY.d.ts +0 -2442
package/README.md
CHANGED
|
@@ -82,6 +82,158 @@ await waitForCompletion();
|
|
|
82
82
|
| `verifyAndWait(options)` | One-liner: create request + wait for result |
|
|
83
83
|
| `issueAndWait(options)` | One-liner: create offer + wait for result |
|
|
84
84
|
|
|
85
|
+
### Digital Credentials API (Browser Native)
|
|
86
|
+
|
|
87
|
+
The SDK includes utilities for the [Digital Credentials API](https://wicg.github.io/digital-credentials/), enabling browser-native credential presentation without QR codes.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { isDcApiAvailable, verifyWithDcApi } from '@eudiplo/sdk-core';
|
|
91
|
+
|
|
92
|
+
// Check if browser supports DC API
|
|
93
|
+
if (isDcApiAvailable()) {
|
|
94
|
+
const result = await verifyWithDcApi({
|
|
95
|
+
baseUrl: 'https://eudiplo.example.com',
|
|
96
|
+
clientId: 'my-demo',
|
|
97
|
+
clientSecret: 'secret',
|
|
98
|
+
configId: 'age-over-18',
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
console.log('Verified!', result.session.credentials);
|
|
102
|
+
} else {
|
|
103
|
+
// Fall back to QR code flow
|
|
104
|
+
const session = await verifyAndWait({...});
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### DC API Functions
|
|
109
|
+
|
|
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 |
|
|
115
|
+
|
|
116
|
+
#### Lower-level DC API Usage
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { createDcApiRequest, EudiploClient } from '@eudiplo/sdk-core';
|
|
120
|
+
|
|
121
|
+
const client = new EudiploClient({...});
|
|
122
|
+
|
|
123
|
+
// Create presentation request
|
|
124
|
+
const { uri, sessionId } = await client.createPresentationRequest({
|
|
125
|
+
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
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Browser (React / vanilla JS):**
|
|
195
|
+
|
|
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
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**What stays where:**
|
|
228
|
+
|
|
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 |
|
|
236
|
+
|
|
85
237
|
### Class-based API (More Control)
|
|
86
238
|
|
|
87
239
|
```typescript
|
|
@@ -175,6 +327,43 @@ const session = await client.waitForSession(sessionId, {
|
|
|
175
327
|
});
|
|
176
328
|
```
|
|
177
329
|
|
|
330
|
+
### `subscribeToSession(sessionId, options)`
|
|
331
|
+
|
|
332
|
+
Subscribe to real-time session status updates via Server-Sent Events (SSE).
|
|
333
|
+
This is more efficient than polling and provides instant updates.
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
const subscription = await client.subscribeToSession(sessionId, {
|
|
337
|
+
onStatusChange: (event) => {
|
|
338
|
+
console.log(`Status: ${event.status}`);
|
|
339
|
+
if (['completed', 'expired', 'failed'].includes(event.status)) {
|
|
340
|
+
subscription.close();
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
onError: (error) => console.error('SSE error:', error),
|
|
344
|
+
onOpen: () => console.log('Connected'),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Later, to close the connection:
|
|
348
|
+
subscription.close();
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### `waitForSessionWithSse(sessionId, options)`
|
|
352
|
+
|
|
353
|
+
Wait for session completion using SSE instead of polling. Returns a Promise
|
|
354
|
+
that resolves when the session completes.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
try {
|
|
358
|
+
const finalStatus = await client.waitForSessionWithSse(sessionId, {
|
|
359
|
+
onStatusChange: (event) => console.log('Status:', event.status),
|
|
360
|
+
});
|
|
361
|
+
console.log('Session completed:', finalStatus);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error('Session failed:', error);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
178
367
|
## Examples
|
|
179
368
|
|
|
180
369
|
### Age Verification in a Web Shop
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/api/core/serverSentEvents.gen.ts
|
|
4
|
-
|
|
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
|
|
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/")) {
|
|
@@ -637,132 +616,121 @@ var createClient = (config = {}) => {
|
|
|
637
616
|
if (opts.body === void 0 || opts.serializedBody === "") {
|
|
638
617
|
opts.headers.delete("Content-Type");
|
|
639
618
|
}
|
|
640
|
-
const
|
|
641
|
-
|
|
619
|
+
const resolvedOpts = opts;
|
|
620
|
+
const url = buildUrl(resolvedOpts);
|
|
621
|
+
return { opts: resolvedOpts, url };
|
|
642
622
|
};
|
|
643
623
|
const request = async (options) => {
|
|
644
|
-
const
|
|
645
|
-
const
|
|
646
|
-
|
|
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;
|
|
624
|
+
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
|
625
|
+
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
|
626
|
+
let request2;
|
|
657
627
|
let response;
|
|
658
628
|
try {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
629
|
+
const { opts, url } = await beforeRequest(options);
|
|
630
|
+
const requestInit = {
|
|
631
|
+
redirect: "follow",
|
|
632
|
+
...opts,
|
|
633
|
+
body: getValidRequestBody(opts)
|
|
634
|
+
};
|
|
635
|
+
request2 = new Request(url, requestInit);
|
|
636
|
+
for (const fn of interceptors.request.fns) {
|
|
663
637
|
if (fn) {
|
|
664
|
-
|
|
665
|
-
error2,
|
|
666
|
-
void 0,
|
|
667
|
-
request2,
|
|
668
|
-
opts
|
|
669
|
-
);
|
|
638
|
+
request2 = await fn(request2, opts);
|
|
670
639
|
}
|
|
671
640
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
641
|
+
const _fetch = opts.fetch;
|
|
642
|
+
response = await _fetch(request2);
|
|
643
|
+
for (const fn of interceptors.response.fns) {
|
|
644
|
+
if (fn) {
|
|
645
|
+
response = await fn(response, request2, opts);
|
|
646
|
+
}
|
|
675
647
|
}
|
|
676
|
-
|
|
677
|
-
error: finalError2,
|
|
648
|
+
const result = {
|
|
678
649
|
request: request2,
|
|
679
|
-
response
|
|
650
|
+
response
|
|
680
651
|
};
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
652
|
+
if (response.ok) {
|
|
653
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
654
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
655
|
+
let emptyData;
|
|
656
|
+
switch (parseAs) {
|
|
657
|
+
case "arrayBuffer":
|
|
658
|
+
case "blob":
|
|
659
|
+
case "text":
|
|
660
|
+
emptyData = await response[parseAs]();
|
|
661
|
+
break;
|
|
662
|
+
case "formData":
|
|
663
|
+
emptyData = new FormData();
|
|
664
|
+
break;
|
|
665
|
+
case "stream":
|
|
666
|
+
emptyData = response.body;
|
|
667
|
+
break;
|
|
668
|
+
case "json":
|
|
669
|
+
default:
|
|
670
|
+
emptyData = {};
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
return opts.responseStyle === "data" ? emptyData : {
|
|
674
|
+
data: emptyData,
|
|
675
|
+
...result
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
let data;
|
|
695
679
|
switch (parseAs) {
|
|
696
680
|
case "arrayBuffer":
|
|
697
681
|
case "blob":
|
|
682
|
+
case "formData":
|
|
698
683
|
case "text":
|
|
699
|
-
|
|
684
|
+
data = await response[parseAs]();
|
|
700
685
|
break;
|
|
701
|
-
case "
|
|
702
|
-
|
|
686
|
+
case "json": {
|
|
687
|
+
const text = await response.text();
|
|
688
|
+
data = text ? JSON.parse(text) : {};
|
|
703
689
|
break;
|
|
690
|
+
}
|
|
704
691
|
case "stream":
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
emptyData = {};
|
|
710
|
-
break;
|
|
692
|
+
return opts.responseStyle === "data" ? response.body : {
|
|
693
|
+
data: response.body,
|
|
694
|
+
...result
|
|
695
|
+
};
|
|
711
696
|
}
|
|
712
|
-
|
|
713
|
-
|
|
697
|
+
if (parseAs === "json") {
|
|
698
|
+
if (opts.responseValidator) {
|
|
699
|
+
await opts.responseValidator(data);
|
|
700
|
+
}
|
|
701
|
+
if (opts.responseTransformer) {
|
|
702
|
+
data = await opts.responseTransformer(data);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return opts.responseStyle === "data" ? data : {
|
|
706
|
+
data,
|
|
714
707
|
...result
|
|
715
708
|
};
|
|
716
709
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
case "json":
|
|
723
|
-
case "text":
|
|
724
|
-
data = await response[parseAs]();
|
|
725
|
-
break;
|
|
726
|
-
case "stream":
|
|
727
|
-
return opts.responseStyle === "data" ? response.body : {
|
|
728
|
-
data: response.body,
|
|
729
|
-
...result
|
|
730
|
-
};
|
|
710
|
+
const textError = await response.text();
|
|
711
|
+
let jsonError;
|
|
712
|
+
try {
|
|
713
|
+
jsonError = JSON.parse(textError);
|
|
714
|
+
} catch {
|
|
731
715
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
if (
|
|
737
|
-
|
|
716
|
+
throw jsonError ?? textError;
|
|
717
|
+
} catch (error) {
|
|
718
|
+
let finalError = error;
|
|
719
|
+
for (const fn of interceptors.error.fns) {
|
|
720
|
+
if (fn) {
|
|
721
|
+
finalError = await fn(finalError, response, request2, options);
|
|
738
722
|
}
|
|
739
723
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
const textError = await response.text();
|
|
746
|
-
let jsonError;
|
|
747
|
-
try {
|
|
748
|
-
jsonError = JSON.parse(textError);
|
|
749
|
-
} catch {
|
|
750
|
-
}
|
|
751
|
-
const error = jsonError ?? textError;
|
|
752
|
-
let finalError = error;
|
|
753
|
-
for (const fn of interceptors.error.fns) {
|
|
754
|
-
if (fn) {
|
|
755
|
-
finalError = await fn(error, response, request2, opts);
|
|
724
|
+
finalError = finalError || {};
|
|
725
|
+
if (throwOnError) {
|
|
726
|
+
throw finalError;
|
|
756
727
|
}
|
|
728
|
+
return responseStyle === "data" ? void 0 : {
|
|
729
|
+
error: finalError,
|
|
730
|
+
request: request2,
|
|
731
|
+
response
|
|
732
|
+
};
|
|
757
733
|
}
|
|
758
|
-
finalError = finalError || {};
|
|
759
|
-
if (opts.throwOnError) {
|
|
760
|
-
throw finalError;
|
|
761
|
-
}
|
|
762
|
-
return opts.responseStyle === "data" ? void 0 : {
|
|
763
|
-
error: finalError,
|
|
764
|
-
...result
|
|
765
|
-
};
|
|
766
734
|
};
|
|
767
735
|
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
768
736
|
const makeSseFn = (method) => async (options) => {
|
|
@@ -770,7 +738,6 @@ var createClient = (config = {}) => {
|
|
|
770
738
|
return createSseClient({
|
|
771
739
|
...opts,
|
|
772
740
|
body: opts.body,
|
|
773
|
-
headers: opts.headers,
|
|
774
741
|
method,
|
|
775
742
|
onRequest: async (url2, init) => {
|
|
776
743
|
let request2 = new Request(url2, init);
|
|
@@ -785,8 +752,9 @@ var createClient = (config = {}) => {
|
|
|
785
752
|
url
|
|
786
753
|
});
|
|
787
754
|
};
|
|
755
|
+
const _buildUrl = (options) => buildUrl({ ..._config, ...options });
|
|
788
756
|
return {
|
|
789
|
-
buildUrl,
|
|
757
|
+
buildUrl: _buildUrl,
|
|
790
758
|
connect: makeMethodFn("CONNECT"),
|
|
791
759
|
delete: makeMethodFn("DELETE"),
|
|
792
760
|
get: makeMethodFn("GET"),
|