@eudiplo/sdk-core 1.14.0-main.9f2d10d → 1.14.0-main.a02bfab

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
@@ -141,14 +141,16 @@ const session = await client.submitDcApiResponse(sessionId, credential);
141
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
142
 
143
143
  **Server-side Functions:**
144
- | Function | Description |
145
- | ---------------------- | --------------------------------------------------- |
144
+
145
+ | Function | Description |
146
+ | -------------------------------- | ------------------------------------------------------ |
146
147
  | `createDcApiRequestForBrowser()` | Create request on server, return safe data for browser |
147
- | `submitDcApiWalletResponse()` | Submit wallet response to EUDIPLO from server |
148
+ | `submitDcApiWalletResponse()` | Submit wallet response to EUDIPLO from server |
148
149
 
149
150
  **Browser-side Functions:**
150
- | Function | Description |
151
- | ---------------------- | --------------------------------------------------- |
151
+
152
+ | Function | Description |
153
+ | ------------- | ------------------------------------------------------ |
152
154
  | `callDcApi()` | Call the native DC API with a request from your server |
153
155
 
154
156
  ##### Example: Express.js Backend + Browser Frontend
@@ -165,8 +167,8 @@ import {
165
167
  app.post('/api/start-verification', async (req, res) => {
166
168
  const requestData = await createDcApiRequestForBrowser({
167
169
  baseUrl: process.env.EUDIPLO_URL,
168
- clientId: process.env.EUDIPLO_CLIENT_ID, // ✅ Safe on server
169
- clientSecret: process.env.EUDIPLO_SECRET, // ✅ Safe on server
170
+ clientId: process.env.EUDIPLO_CLIENT_ID, // ✅ Safe on server
171
+ clientSecret: process.env.EUDIPLO_SECRET, // ✅ Safe on server
170
172
  configId: 'age-over-18',
171
173
  });
172
174
 
@@ -181,7 +183,7 @@ app.post('/api/complete-verification', async (req, res) => {
181
183
  const result = await submitDcApiWalletResponse({
182
184
  responseUri,
183
185
  walletResponse,
184
- sendResponse: true, // Get verified claims back
186
+ sendResponse: true, // Get verified claims back
185
187
  });
186
188
 
187
189
  // result.credentials contains the verified data
@@ -224,13 +226,13 @@ async function verifyAge() {
224
226
 
225
227
  **What stays where:**
226
228
 
227
- | Data | Location | Safe to expose? |
228
- |------|----------|-----------------|
229
- | `clientId` / `clientSecret` | Server only | ❌ Never expose |
230
- | `requestObject` (signed JWT) | Server → Browser | ✅ Yes |
231
- | `responseUri` | Server → Browser | ✅ Yes |
232
- | Wallet response (encrypted VP) | Browser → Server | ✅ Yes |
233
- | Verified credentials | Server only | Depends on use case |
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 |
234
236
 
235
237
  ### Class-based API (More Control)
236
238
 
@@ -325,6 +327,43 @@ const session = await client.waitForSession(sessionId, {
325
327
  });
326
328
  ```
327
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
+
328
367
  ## Examples
329
368
 
330
369
  ### Age Verification in a Web Shop
@@ -1,4 +1,4 @@
1
- import { b as Config, C as Client } from '../../types.gen-DDunhhsd.mjs';
1
+ import { b as Config, C as Client } from '../../types.gen-DKrNRB-E.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-DDunhhsd.js';
1
+ import { b as Config, C as Client } from '../../types.gen-DKrNRB-E.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* () {
@@ -60,7 +60,7 @@ var createSseClient = ({
60
60
  const { done, value } = await reader.read();
61
61
  if (done) break;
62
62
  buffer += value;
63
- buffer = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
63
+ buffer = buffer.replace(/\r\n?/g, "\n");
64
64
  const chunks = buffer.split("\n\n");
65
65
  buffer = chunks.pop() ?? "";
66
66
  for (const chunk of chunks) {
@@ -134,7 +134,7 @@ var createSseClient = ({
134
134
  };
135
135
  const stream = createStream();
136
136
  return { stream };
137
- };
137
+ }
138
138
 
139
139
  // src/api/core/pathSerializer.gen.ts
140
140
  var separatorArrayExplode = (style) => {
@@ -637,136 +637,126 @@ var createClient = (config = {}) => {
637
637
  if (opts.body === void 0 || opts.serializedBody === "") {
638
638
  opts.headers.delete("Content-Type");
639
639
  }
640
- const url = buildUrl(opts);
641
- return { opts, url };
640
+ const resolvedOpts = opts;
641
+ const url = buildUrl(resolvedOpts);
642
+ return { opts: resolvedOpts, url };
642
643
  };
643
644
  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;
645
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
646
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
647
+ let request2;
657
648
  let response;
658
649
  try {
659
- response = await _fetch(request2);
660
- } catch (error2) {
661
- let finalError2 = error2;
662
- for (const fn of interceptors.error.fns) {
650
+ const { opts, url } = await beforeRequest(options);
651
+ const requestInit = {
652
+ redirect: "follow",
653
+ ...opts,
654
+ body: getValidRequestBody(opts)
655
+ };
656
+ request2 = new Request(url, requestInit);
657
+ for (const fn of interceptors.request.fns) {
663
658
  if (fn) {
664
- finalError2 = await fn(
665
- error2,
666
- void 0,
667
- request2,
668
- opts
669
- );
659
+ request2 = await fn(request2, opts);
670
660
  }
671
661
  }
672
- finalError2 = finalError2 || {};
673
- if (opts.throwOnError) {
674
- throw finalError2;
662
+ const _fetch = opts.fetch;
663
+ response = await _fetch(request2);
664
+ for (const fn of interceptors.response.fns) {
665
+ if (fn) {
666
+ response = await fn(response, request2, opts);
667
+ }
675
668
  }
676
- return opts.responseStyle === "data" ? void 0 : {
677
- error: finalError2,
669
+ const result = {
678
670
  request: request2,
679
- response: void 0
671
+ response
680
672
  };
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;
673
+ if (response.ok) {
674
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
675
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
676
+ let emptyData;
677
+ switch (parseAs) {
678
+ case "arrayBuffer":
679
+ case "blob":
680
+ case "text":
681
+ emptyData = await response[parseAs]();
682
+ break;
683
+ case "formData":
684
+ emptyData = new FormData();
685
+ break;
686
+ case "stream":
687
+ emptyData = response.body;
688
+ break;
689
+ case "json":
690
+ default:
691
+ emptyData = {};
692
+ break;
693
+ }
694
+ return opts.responseStyle === "data" ? emptyData : {
695
+ data: emptyData,
696
+ ...result
697
+ };
698
+ }
699
+ let data;
695
700
  switch (parseAs) {
696
701
  case "arrayBuffer":
697
702
  case "blob":
703
+ case "formData":
698
704
  case "text":
699
- emptyData = await response[parseAs]();
705
+ data = await response[parseAs]();
700
706
  break;
701
- case "formData":
702
- emptyData = new FormData();
707
+ case "json": {
708
+ const text = await response.text();
709
+ data = text ? JSON.parse(text) : {};
703
710
  break;
711
+ }
704
712
  case "stream":
705
- emptyData = response.body;
706
- break;
707
- case "json":
708
- default:
709
- emptyData = {};
710
- break;
713
+ return opts.responseStyle === "data" ? response.body : {
714
+ data: response.body,
715
+ ...result
716
+ };
717
+ }
718
+ if (parseAs === "json") {
719
+ if (opts.responseValidator) {
720
+ await opts.responseValidator(data);
721
+ }
722
+ if (opts.responseTransformer) {
723
+ data = await opts.responseTransformer(data);
724
+ }
711
725
  }
712
- return opts.responseStyle === "data" ? emptyData : {
713
- data: emptyData,
726
+ return opts.responseStyle === "data" ? data : {
727
+ data,
714
728
  ...result
715
729
  };
716
730
  }
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
- };
731
+ const textError = await response.text();
732
+ let jsonError;
733
+ try {
734
+ jsonError = JSON.parse(textError);
735
+ } catch {
735
736
  }
736
- if (parseAs === "json") {
737
- if (opts.responseValidator) {
738
- await opts.responseValidator(data);
739
- }
740
- if (opts.responseTransformer) {
741
- data = await opts.responseTransformer(data);
737
+ throw jsonError ?? textError;
738
+ } catch (error) {
739
+ let finalError = error;
740
+ for (const fn of interceptors.error.fns) {
741
+ if (fn) {
742
+ finalError = await fn(
743
+ finalError,
744
+ response,
745
+ request2,
746
+ options
747
+ );
742
748
  }
743
749
  }
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);
750
+ finalError = finalError || {};
751
+ if (throwOnError) {
752
+ throw finalError;
760
753
  }
754
+ return responseStyle === "data" ? void 0 : {
755
+ error: finalError,
756
+ request: request2,
757
+ response
758
+ };
761
759
  }
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
760
  };
771
761
  const makeMethodFn = (method) => (options) => request({ ...options, method });
772
762
  const makeSseFn = (method) => async (options) => {
@@ -774,7 +764,6 @@ var createClient = (config = {}) => {
774
764
  return createSseClient({
775
765
  ...opts,
776
766
  body: opts.body,
777
- headers: opts.headers,
778
767
  method,
779
768
  onRequest: async (url2, init) => {
780
769
  let request2 = new Request(url2, init);
@@ -789,8 +778,9 @@ var createClient = (config = {}) => {
789
778
  url
790
779
  });
791
780
  };
781
+ const _buildUrl = (options) => buildUrl({ ..._config, ...options });
792
782
  return {
793
- buildUrl,
783
+ buildUrl: _buildUrl,
794
784
  connect: makeMethodFn("CONNECT"),
795
785
  delete: makeMethodFn("DELETE"),
796
786
  get: makeMethodFn("GET"),