@eudiplo/sdk-core 1.14.0-main.07a91c4 → 1.14.0-main.0934ac3
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 +5 -1
- package/dist/api/client/client.gen.mjs +5 -1
- package/dist/api/client/index.d.mts +1 -1
- package/dist/api/client/index.d.ts +1 -1
- package/dist/api/client/index.js +6 -2
- package/dist/api/client/index.mjs +6 -2
- 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 +5 -1
- package/dist/api/client.gen.mjs +5 -1
- package/dist/api/index.d.mts +136 -137
- package/dist/api/index.d.ts +136 -137
- package/dist/api/index.js +267 -190
- package/dist/api/index.mjs +234 -152
- package/dist/index.d.mts +368 -16
- package/dist/index.d.ts +368 -16
- package/dist/index.js +657 -200
- package/dist/index.mjs +618 -163
- package/dist/{types.gen-CIiveH8G.d.mts → types.gen-D8LjzWc0.d.mts} +3 -3
- package/dist/{types.gen-CIiveH8G.d.ts → types.gen-D8LjzWc0.d.ts} +3 -3
- package/dist/types.gen-sNmRQvUI.d.mts +3433 -0
- package/dist/types.gen-sNmRQvUI.d.ts +3433 -0
- package/package.json +4 -4
- 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
|
|
@@ -719,10 +719,14 @@ var createClient = (config = {}) => {
|
|
|
719
719
|
case "arrayBuffer":
|
|
720
720
|
case "blob":
|
|
721
721
|
case "formData":
|
|
722
|
-
case "json":
|
|
723
722
|
case "text":
|
|
724
723
|
data = await response[parseAs]();
|
|
725
724
|
break;
|
|
725
|
+
case "json": {
|
|
726
|
+
const text = await response.text();
|
|
727
|
+
data = text ? JSON.parse(text) : {};
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
726
730
|
case "stream":
|
|
727
731
|
return opts.responseStyle === "data" ? response.body : {
|
|
728
732
|
data: response.body,
|
|
@@ -717,10 +717,14 @@ var createClient = (config = {}) => {
|
|
|
717
717
|
case "arrayBuffer":
|
|
718
718
|
case "blob":
|
|
719
719
|
case "formData":
|
|
720
|
-
case "json":
|
|
721
720
|
case "text":
|
|
722
721
|
data = await response[parseAs]();
|
|
723
722
|
break;
|
|
723
|
+
case "json": {
|
|
724
|
+
const text = await response.text();
|
|
725
|
+
data = text ? JSON.parse(text) : {};
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
724
728
|
case "stream":
|
|
725
729
|
return opts.responseStyle === "data" ? response.body : {
|
|
726
730
|
data: response.body,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Auth,
|
|
1
|
+
export { A as Auth, C as Client, a as ClientOptions, b as Config, c as CreateClientConfig, O as Options, Q as QuerySerializerOptions, R as RequestOptions, d as RequestResult, e as ResolvedRequestOptions, f as ResponseStyle, T as TDataShape, g as createConfig, h as formDataBodySerializer, j as jsonBodySerializer, m as mergeHeaders, u as urlSearchParamsBodySerializer } from '../../types.gen-D8LjzWc0.mjs';
|
|
2
2
|
export { createClient } from './client.gen.mjs';
|
|
3
3
|
|
|
4
4
|
type Slot = "body" | "headers" | "path" | "query";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Auth,
|
|
1
|
+
export { A as Auth, C as Client, a as ClientOptions, b as Config, c as CreateClientConfig, O as Options, Q as QuerySerializerOptions, R as RequestOptions, d as RequestResult, e as ResolvedRequestOptions, f as ResponseStyle, T as TDataShape, g as createConfig, h as formDataBodySerializer, j as jsonBodySerializer, m as mergeHeaders, u as urlSearchParamsBodySerializer } from '../../types.gen-D8LjzWc0.js';
|
|
2
2
|
export { createClient } from './client.gen.js';
|
|
3
3
|
|
|
4
4
|
type Slot = "body" | "headers" | "path" | "query";
|
package/dist/api/client/index.js
CHANGED
|
@@ -88,7 +88,7 @@ var buildKeyMap = (fields, map) => {
|
|
|
88
88
|
};
|
|
89
89
|
var stripEmptySlots = (params) => {
|
|
90
90
|
for (const [slot, value] of Object.entries(params)) {
|
|
91
|
-
if (value && typeof value === "object" && !Object.keys(value).length) {
|
|
91
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !Object.keys(value).length) {
|
|
92
92
|
delete params[slot];
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -941,10 +941,14 @@ var createClient = (config = {}) => {
|
|
|
941
941
|
case "arrayBuffer":
|
|
942
942
|
case "blob":
|
|
943
943
|
case "formData":
|
|
944
|
-
case "json":
|
|
945
944
|
case "text":
|
|
946
945
|
data = await response[parseAs]();
|
|
947
946
|
break;
|
|
947
|
+
case "json": {
|
|
948
|
+
const text = await response.text();
|
|
949
|
+
data = text ? JSON.parse(text) : {};
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
948
952
|
case "stream":
|
|
949
953
|
return opts.responseStyle === "data" ? response.body : {
|
|
950
954
|
data: response.body,
|
|
@@ -86,7 +86,7 @@ var buildKeyMap = (fields, map) => {
|
|
|
86
86
|
};
|
|
87
87
|
var stripEmptySlots = (params) => {
|
|
88
88
|
for (const [slot, value] of Object.entries(params)) {
|
|
89
|
-
if (value && typeof value === "object" && !Object.keys(value).length) {
|
|
89
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !Object.keys(value).length) {
|
|
90
90
|
delete params[slot];
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -939,10 +939,14 @@ var createClient = (config = {}) => {
|
|
|
939
939
|
case "arrayBuffer":
|
|
940
940
|
case "blob":
|
|
941
941
|
case "formData":
|
|
942
|
-
case "json":
|
|
943
942
|
case "text":
|
|
944
943
|
data = await response[parseAs]();
|
|
945
944
|
break;
|
|
945
|
+
case "json": {
|
|
946
|
+
const text = await response.text();
|
|
947
|
+
data = text ? JSON.parse(text) : {};
|
|
948
|
+
break;
|
|
949
|
+
}
|
|
946
950
|
case "stream":
|
|
947
951
|
return opts.responseStyle === "data" ? response.body : {
|
|
948
952
|
data: response.body,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { C as Client, a as ClientOptions, b as Config, c as CreateClientConfig, O as Options, R as RequestOptions, d as RequestResult, e as ResolvedRequestOptions, f as ResponseStyle, T as TDataShape } from '../../types.gen-D8LjzWc0.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { C as Client, a as ClientOptions, b as Config, c as CreateClientConfig, O as Options, R as RequestOptions, d as RequestResult, e as ResolvedRequestOptions, f as ResponseStyle, T as TDataShape } from '../../types.gen-D8LjzWc0.js';
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
import '../types.gen-
|
|
2
|
-
|
|
1
|
+
import { C as Client, a as ClientOptions, b as Config } from '../types.gen-D8LjzWc0.mjs';
|
|
2
|
+
import { ae as ClientOptions$1 } from '../types.gen-sNmRQvUI.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `createClientConfig()` function will be called on client initialization
|
|
6
|
+
* and the returned object will become the client's initial configuration.
|
|
7
|
+
*
|
|
8
|
+
* You may want to initialize your client this way instead of calling
|
|
9
|
+
* `setConfig()`. This is useful for example if you're using Next.js
|
|
10
|
+
* to ensure your client always has the correct values.
|
|
11
|
+
*/
|
|
12
|
+
type CreateClientConfig<T extends ClientOptions = ClientOptions$1> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T> | Promise<Config<Required<ClientOptions> & T>>;
|
|
13
|
+
declare const client: Client;
|
|
14
|
+
|
|
15
|
+
export { type CreateClientConfig, client };
|
package/dist/api/client.gen.d.ts
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
import '../types.gen-
|
|
2
|
-
|
|
1
|
+
import { C as Client, a as ClientOptions, b as Config } from '../types.gen-D8LjzWc0.js';
|
|
2
|
+
import { ae as ClientOptions$1 } from '../types.gen-sNmRQvUI.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `createClientConfig()` function will be called on client initialization
|
|
6
|
+
* and the returned object will become the client's initial configuration.
|
|
7
|
+
*
|
|
8
|
+
* You may want to initialize your client this way instead of calling
|
|
9
|
+
* `setConfig()`. This is useful for example if you're using Next.js
|
|
10
|
+
* to ensure your client always has the correct values.
|
|
11
|
+
*/
|
|
12
|
+
type CreateClientConfig<T extends ClientOptions = ClientOptions$1> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T> | Promise<Config<Required<ClientOptions> & T>>;
|
|
13
|
+
declare const client: Client;
|
|
14
|
+
|
|
15
|
+
export { type CreateClientConfig, client };
|
package/dist/api/client.gen.js
CHANGED
|
@@ -719,10 +719,14 @@ var createClient = (config = {}) => {
|
|
|
719
719
|
case "arrayBuffer":
|
|
720
720
|
case "blob":
|
|
721
721
|
case "formData":
|
|
722
|
-
case "json":
|
|
723
722
|
case "text":
|
|
724
723
|
data = await response[parseAs]();
|
|
725
724
|
break;
|
|
725
|
+
case "json": {
|
|
726
|
+
const text = await response.text();
|
|
727
|
+
data = text ? JSON.parse(text) : {};
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
726
730
|
case "stream":
|
|
727
731
|
return opts.responseStyle === "data" ? response.body : {
|
|
728
732
|
data: response.body,
|
package/dist/api/client.gen.mjs
CHANGED
|
@@ -717,10 +717,14 @@ var createClient = (config = {}) => {
|
|
|
717
717
|
case "arrayBuffer":
|
|
718
718
|
case "blob":
|
|
719
719
|
case "formData":
|
|
720
|
-
case "json":
|
|
721
720
|
case "text":
|
|
722
721
|
data = await response[parseAs]();
|
|
723
722
|
break;
|
|
723
|
+
case "json": {
|
|
724
|
+
const text = await response.text();
|
|
725
|
+
data = text ? JSON.parse(text) : {};
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
724
728
|
case "stream":
|
|
725
729
|
return opts.responseStyle === "data" ? response.body : {
|
|
726
730
|
data: response.body,
|