docpouch-client 0.9.0 → 1.0.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.
- package/README.md +630 -449
- package/chat-09e440bd-c52c-44b9-bba4-01cebc84bd7b.txt +223 -0
- package/dist/index.d.ts +147 -6
- package/dist/index.js +308 -10
- package/{jest.config.js → jest.config.cjs} +1 -1
- package/package.json +41 -38
- package/src/index.ts +1003 -622
- package/tests/docPouchClient.test.ts +654 -0
- package/tests/mock-server.ts +613 -0
- package/tsconfig.build.json +7 -0
- package/tsconfig.json +9 -7
package/dist/index.js
CHANGED
|
@@ -25,6 +25,14 @@ export default class docPouchClient {
|
|
|
25
25
|
* @type {string | null}
|
|
26
26
|
*/
|
|
27
27
|
this.authToken = null;
|
|
28
|
+
this.oidcConfig = null;
|
|
29
|
+
this.oidcAccessToken = null;
|
|
30
|
+
this.oidcRefreshToken = null;
|
|
31
|
+
this.oidcIdToken = null;
|
|
32
|
+
this.oidcTokenExpiry = 0;
|
|
33
|
+
this.codeVerifier = null;
|
|
34
|
+
this.oidcState = null;
|
|
35
|
+
this.authMethod = 'none';
|
|
28
36
|
/**
|
|
29
37
|
* Flag indicating whether a connection attempt is in progress.
|
|
30
38
|
*
|
|
@@ -66,7 +74,7 @@ export default class docPouchClient {
|
|
|
66
74
|
return;
|
|
67
75
|
}
|
|
68
76
|
this.realTimeSync = newRealTimeSync;
|
|
69
|
-
if (newRealTimeSync && this.authToken) {
|
|
77
|
+
if (newRealTimeSync && (this.authToken || this.oidcAccessToken)) {
|
|
70
78
|
console.log("Activating realtime updates");
|
|
71
79
|
// Ensure we're not in the middle of another connection attempt
|
|
72
80
|
if (this.connectionInProgress) {
|
|
@@ -96,6 +104,7 @@ export default class docPouchClient {
|
|
|
96
104
|
const response = await this.request('/users/login', 'POST', credentials, false);
|
|
97
105
|
if (response.token) {
|
|
98
106
|
this.authToken = response.token;
|
|
107
|
+
this.authMethod = 'jwt';
|
|
99
108
|
// Reconnect websocket with new token if realtime sync is enabled
|
|
100
109
|
if (this.realTimeSync) {
|
|
101
110
|
this.initWebSocket();
|
|
@@ -236,8 +245,11 @@ export default class docPouchClient {
|
|
|
236
245
|
*/
|
|
237
246
|
setToken(token) {
|
|
238
247
|
console.log("Setting token to:", token ? "***token***" : "null");
|
|
248
|
+
this.authMethod = token ? 'jwt' : 'none';
|
|
239
249
|
const tokenChanged = this.authToken !== token;
|
|
240
250
|
this.authToken = token;
|
|
251
|
+
if (!token)
|
|
252
|
+
this.clearOidcTokens();
|
|
241
253
|
if (!tokenChanged) {
|
|
242
254
|
console.log("Token unchanged, no need to reconnect");
|
|
243
255
|
return;
|
|
@@ -279,17 +291,208 @@ export default class docPouchClient {
|
|
|
279
291
|
console.log("Socket connection debug info:");
|
|
280
292
|
console.log("- Connected:", this.socket.connected);
|
|
281
293
|
console.log("- Socket ID:", this.socket.id);
|
|
282
|
-
console.log("- Auth token present:", !!this.authToken);
|
|
294
|
+
console.log("- Auth token present:", !!this.authToken, "(method:", this.authMethod + ")");
|
|
295
|
+
console.log("- OIDC access token present:", !!this.oidcAccessToken);
|
|
283
296
|
console.log("- Connection in progress:", this.connectionInProgress);
|
|
284
297
|
console.log("- Realtime sync enabled:", this.realTimeSync);
|
|
285
298
|
console.log("- Socket options:", this.socket.io.opts);
|
|
299
|
+
const activeToken = this.authMethod === 'oidc' ? this.oidcAccessToken : this.authToken;
|
|
286
300
|
// Try to force reconnection
|
|
287
|
-
if (!this.socket.connected &&
|
|
301
|
+
if (!this.socket.connected && activeToken && this.realTimeSync) {
|
|
288
302
|
console.log("Attempting to force reconnection...");
|
|
289
|
-
this.socket.auth = { token:
|
|
303
|
+
this.socket.auth = { token: activeToken };
|
|
290
304
|
this.socket.connect();
|
|
291
305
|
}
|
|
292
306
|
}
|
|
307
|
+
// OIDC Authentication Methods
|
|
308
|
+
/**
|
|
309
|
+
* Initiates the OIDC authentication flow by redirecting to the authorization endpoint.
|
|
310
|
+
*
|
|
311
|
+
* @param {I_OidcConfig} config - OIDC provider configuration.
|
|
312
|
+
* @returns {Promise<void>}
|
|
313
|
+
*/
|
|
314
|
+
async loginWithOidc(config) {
|
|
315
|
+
this.oidcConfig = config;
|
|
316
|
+
const response = await fetch(`${config.issuer}/.well-known/openid-configuration`);
|
|
317
|
+
const discovery = await response.json();
|
|
318
|
+
this.codeVerifier = this.generateCodeVerifier();
|
|
319
|
+
this.oidcState = this.generateState();
|
|
320
|
+
const codeChallenge = await this.generateCodeChallenge(this.codeVerifier);
|
|
321
|
+
const params = new URLSearchParams({
|
|
322
|
+
response_type: 'code',
|
|
323
|
+
client_id: config.clientId,
|
|
324
|
+
redirect_uri: config.redirectUri,
|
|
325
|
+
scope: config.scopes?.join(' ') || 'openid profile',
|
|
326
|
+
state: this.oidcState,
|
|
327
|
+
code_challenge: codeChallenge,
|
|
328
|
+
code_challenge_method: 'S256'
|
|
329
|
+
});
|
|
330
|
+
window.location.href = `${discovery.authorization_endpoint}?${params.toString()}`;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Handles the OIDC callback by exchanging the authorization code for tokens.
|
|
334
|
+
*
|
|
335
|
+
* @returns {Promise<boolean>} True if the callback was handled successfully.
|
|
336
|
+
*/
|
|
337
|
+
async handleOidcCallback() {
|
|
338
|
+
const params = new URLSearchParams(window.location.search);
|
|
339
|
+
const code = params.get('code');
|
|
340
|
+
const state = params.get('state');
|
|
341
|
+
const error = params.get('error');
|
|
342
|
+
if (error)
|
|
343
|
+
throw new Error(`OAuth error: ${error}`);
|
|
344
|
+
if (!code || !state)
|
|
345
|
+
return false;
|
|
346
|
+
if (state !== this.oidcState)
|
|
347
|
+
throw new Error('State mismatch');
|
|
348
|
+
const discovery = await this.discoverOidc();
|
|
349
|
+
const body = new URLSearchParams({
|
|
350
|
+
grant_type: 'authorization_code',
|
|
351
|
+
code,
|
|
352
|
+
redirect_uri: this.oidcConfig.redirectUri,
|
|
353
|
+
client_id: this.oidcConfig.clientId,
|
|
354
|
+
code_verifier: this.codeVerifier || ''
|
|
355
|
+
});
|
|
356
|
+
const response = await fetch(discovery.token_endpoint, {
|
|
357
|
+
method: 'POST',
|
|
358
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
359
|
+
body: body.toString()
|
|
360
|
+
});
|
|
361
|
+
if (!response.ok)
|
|
362
|
+
throw new Error('Token exchange failed');
|
|
363
|
+
const raw = await response.json();
|
|
364
|
+
const tokens = {
|
|
365
|
+
accessToken: raw.access_token,
|
|
366
|
+
refreshToken: raw.refresh_token,
|
|
367
|
+
idToken: raw.id_token,
|
|
368
|
+
expiresIn: raw.expires_in,
|
|
369
|
+
tokenType: raw.token_type,
|
|
370
|
+
scope: raw.scope
|
|
371
|
+
};
|
|
372
|
+
this.setOidcTokens(tokens);
|
|
373
|
+
if (this.realTimeSync)
|
|
374
|
+
this.initWebSocket();
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
restoreOidcSession() {
|
|
378
|
+
if (typeof window === 'undefined' || !window.localStorage)
|
|
379
|
+
return false;
|
|
380
|
+
const stored = localStorage.getItem('docpouch_oidc_session');
|
|
381
|
+
if (!stored)
|
|
382
|
+
return false;
|
|
383
|
+
try {
|
|
384
|
+
const session = JSON.parse(stored);
|
|
385
|
+
if (!session.accessToken || Date.now() >= session.expiry) {
|
|
386
|
+
this.clearPersistedOidcSession();
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
this.authMethod = 'oidc';
|
|
390
|
+
this.oidcAccessToken = session.accessToken;
|
|
391
|
+
this.oidcRefreshToken = session.refreshToken || null;
|
|
392
|
+
this.oidcIdToken = session.idToken || null;
|
|
393
|
+
this.oidcTokenExpiry = session.expiry;
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
this.clearPersistedOidcSession();
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Ensures the OIDC access token is valid, refreshing it if necessary.
|
|
403
|
+
*/
|
|
404
|
+
async ensureValidOidcToken() {
|
|
405
|
+
if (this.authMethod !== 'oidc' || !this.oidcAccessToken)
|
|
406
|
+
throw new Error('Not authenticated via OIDC');
|
|
407
|
+
if (Date.now() >= this.oidcTokenExpiry - 60000) {
|
|
408
|
+
await this.refreshOidcToken();
|
|
409
|
+
}
|
|
410
|
+
return this.oidcAccessToken;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Returns the current authentication method.
|
|
414
|
+
*
|
|
415
|
+
* @returns {'jwt' | 'oidc' | 'none'} The active auth method.
|
|
416
|
+
*/
|
|
417
|
+
getAuthMethod() {
|
|
418
|
+
return this.authMethod;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Checks whether the client is currently authenticated.
|
|
422
|
+
*
|
|
423
|
+
* @returns {boolean} True if authenticated.
|
|
424
|
+
*/
|
|
425
|
+
isAuthenticated() {
|
|
426
|
+
return this.authMethod !== 'none' && (this.authMethod === 'jwt'
|
|
427
|
+
? !!this.authToken
|
|
428
|
+
: (this.oidcAccessToken !== null && Date.now() < this.oidcTokenExpiry));
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Returns the current active token, regardless of auth method.
|
|
432
|
+
*
|
|
433
|
+
* @returns {string | null} The active token or null.
|
|
434
|
+
*/
|
|
435
|
+
getToken() {
|
|
436
|
+
return this.authMethod === 'oidc' ? this.oidcAccessToken : this.authToken;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Logs out the client, clearing all tokens and disconnecting WebSocket.
|
|
440
|
+
*
|
|
441
|
+
* @returns {Promise<void>}
|
|
442
|
+
*/
|
|
443
|
+
async logout() {
|
|
444
|
+
this.authToken = null;
|
|
445
|
+
this.clearOidcTokens();
|
|
446
|
+
this.authMethod = 'none';
|
|
447
|
+
if (this.socket.connected)
|
|
448
|
+
this.socket.disconnect();
|
|
449
|
+
if (typeof window !== 'undefined' && window.location &&
|
|
450
|
+
(window.location.search.includes('code=') || window.location.search.includes('state='))) {
|
|
451
|
+
window.history.replaceState({}, '', window.location.pathname);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// OIDC Dynamic Client Registration Methods
|
|
455
|
+
/**
|
|
456
|
+
* Registers a new OIDC client with the server (dynamic client registration).
|
|
457
|
+
*
|
|
458
|
+
* @param {I_OidcClientRegistration} registration - Client metadata for registration.
|
|
459
|
+
* @param {string} [registrationToken] - Initial registration access token. If not provided, the current auth token is used.
|
|
460
|
+
* @returns {Promise<I_OidcClientResponse>} The registered client details.
|
|
461
|
+
*/
|
|
462
|
+
async registerOidcClient(registration, registrationToken) {
|
|
463
|
+
return await this.request('/oidc/reg', 'POST', registration, true, registrationToken);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Retrieves the registration state of an existing OIDC client.
|
|
467
|
+
*
|
|
468
|
+
* @param {string} clientId - The client identifier.
|
|
469
|
+
* @param {string} [registrationToken] - The registration access token. If not provided, the current auth token is used.
|
|
470
|
+
* @returns {Promise<I_OidcClientResponse>} The client details.
|
|
471
|
+
*/
|
|
472
|
+
async getOidcClient(clientId, registrationToken) {
|
|
473
|
+
return await this.request(`/oidc/reg/${clientId}`, 'GET', undefined, true, registrationToken);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Updates the registration of an existing OIDC client.
|
|
477
|
+
*
|
|
478
|
+
* @param {string} clientId - The client identifier.
|
|
479
|
+
* @param {I_OidcClientRegistration} registration - Updated client metadata.
|
|
480
|
+
* @param {string} [registrationToken] - The registration access token. If not provided, the current auth token is used.
|
|
481
|
+
* @returns {Promise<I_OidcClientResponse>} The updated client details.
|
|
482
|
+
*/
|
|
483
|
+
async updateOidcClient(clientId, registration, registrationToken) {
|
|
484
|
+
return await this.request(`/oidc/reg/${clientId}`, 'PUT', registration, true, registrationToken);
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Deletes an OIDC client registration.
|
|
488
|
+
*
|
|
489
|
+
* @param {string} clientId - The client identifier.
|
|
490
|
+
* @param {string} [registrationToken] - The registration access token. If not provided, the current auth token is used.
|
|
491
|
+
* @returns {Promise<void>}
|
|
492
|
+
*/
|
|
493
|
+
async deleteOidcClient(clientId, registrationToken) {
|
|
494
|
+
await this.request(`/oidc/reg/${clientId}`, 'DELETE', undefined, true, registrationToken);
|
|
495
|
+
}
|
|
293
496
|
/**
|
|
294
497
|
* Sets up permanent socket listeners for the client.
|
|
295
498
|
*
|
|
@@ -320,8 +523,9 @@ export default class docPouchClient {
|
|
|
320
523
|
* @private
|
|
321
524
|
*/
|
|
322
525
|
initWebSocket() {
|
|
323
|
-
|
|
324
|
-
|
|
526
|
+
const token = this.authMethod === 'oidc' ? this.oidcAccessToken : this.authToken;
|
|
527
|
+
console.log("initWebSocket called. Auth token present:", !!this.authToken, "Connection in progress:", this.connectionInProgress, "Socket connected:", this.socket.connected, "Auth method:", this.authMethod);
|
|
528
|
+
if (!token) {
|
|
325
529
|
console.log("Skipping WebSocket initialization: No auth token");
|
|
326
530
|
return;
|
|
327
531
|
}
|
|
@@ -337,7 +541,7 @@ export default class docPouchClient {
|
|
|
337
541
|
try {
|
|
338
542
|
console.log("Setting up WebSocket connection with token");
|
|
339
543
|
// Update the auth token
|
|
340
|
-
this.socket.auth = { token
|
|
544
|
+
this.socket.auth = { token };
|
|
341
545
|
// Remove any dynamic event listeners that might have been added
|
|
342
546
|
this.socket.offAny();
|
|
343
547
|
// Set up event handler for application events
|
|
@@ -383,12 +587,15 @@ export default class docPouchClient {
|
|
|
383
587
|
* @returns {Promise<T>} Parsed JSON response body.
|
|
384
588
|
* @private
|
|
385
589
|
*/
|
|
386
|
-
async request(endpoint, method, body, requiresAuth = true) {
|
|
590
|
+
async request(endpoint, method, body, requiresAuth = true, authTokenOverride) {
|
|
387
591
|
const headers = {
|
|
388
592
|
'Content-Type': 'application/json',
|
|
389
593
|
};
|
|
390
|
-
|
|
391
|
-
|
|
594
|
+
const authToken = authTokenOverride ?? (this.authMethod === 'oidc'
|
|
595
|
+
? await this.ensureValidOidcToken().catch(() => null)
|
|
596
|
+
: this.authToken);
|
|
597
|
+
if (requiresAuth && authToken)
|
|
598
|
+
headers['Authorization'] = `Bearer ${authToken}`;
|
|
392
599
|
if (this.socket.id)
|
|
393
600
|
headers['X-Socket-ID'] = this.socket.id;
|
|
394
601
|
const options = {
|
|
@@ -406,6 +613,97 @@ export default class docPouchClient {
|
|
|
406
613
|
}
|
|
407
614
|
throw new Error(`API error: ${response.status} ${response.statusText}`);
|
|
408
615
|
}
|
|
616
|
+
if (response.status === 204)
|
|
617
|
+
return undefined;
|
|
409
618
|
return await response.json();
|
|
410
619
|
}
|
|
620
|
+
// OIDC Private Helpers
|
|
621
|
+
async discoverOidc() {
|
|
622
|
+
const response = await fetch(`${this.oidcConfig.issuer}/.well-known/openid-configuration`);
|
|
623
|
+
return response.json();
|
|
624
|
+
}
|
|
625
|
+
setOidcTokens(tokens) {
|
|
626
|
+
this.authMethod = 'oidc';
|
|
627
|
+
this.oidcAccessToken = tokens.accessToken;
|
|
628
|
+
this.oidcRefreshToken = tokens.refreshToken || this.oidcRefreshToken;
|
|
629
|
+
this.oidcIdToken = tokens.idToken || null;
|
|
630
|
+
this.oidcTokenExpiry = Date.now() + (tokens.expiresIn * 1000);
|
|
631
|
+
this.persistOidcSession();
|
|
632
|
+
}
|
|
633
|
+
clearOidcTokens() {
|
|
634
|
+
this.oidcAccessToken = null;
|
|
635
|
+
this.oidcRefreshToken = null;
|
|
636
|
+
this.oidcIdToken = null;
|
|
637
|
+
this.oidcTokenExpiry = 0;
|
|
638
|
+
this.codeVerifier = null;
|
|
639
|
+
this.oidcState = null;
|
|
640
|
+
if (this.authMethod === 'oidc')
|
|
641
|
+
this.authMethod = 'none';
|
|
642
|
+
this.clearPersistedOidcSession();
|
|
643
|
+
}
|
|
644
|
+
persistOidcSession() {
|
|
645
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
646
|
+
const session = {
|
|
647
|
+
accessToken: this.oidcAccessToken,
|
|
648
|
+
refreshToken: this.oidcRefreshToken,
|
|
649
|
+
idToken: this.oidcIdToken,
|
|
650
|
+
expiry: this.oidcTokenExpiry
|
|
651
|
+
};
|
|
652
|
+
localStorage.setItem('docpouch_oidc_session', JSON.stringify(session));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
clearPersistedOidcSession() {
|
|
656
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
657
|
+
localStorage.removeItem('docpouch_oidc_session');
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
async refreshOidcToken() {
|
|
661
|
+
if (!this.oidcRefreshToken)
|
|
662
|
+
throw new Error('No refresh token available');
|
|
663
|
+
const discovery = await this.discoverOidc();
|
|
664
|
+
const body = new URLSearchParams({
|
|
665
|
+
grant_type: 'refresh_token',
|
|
666
|
+
refresh_token: this.oidcRefreshToken,
|
|
667
|
+
client_id: this.oidcConfig.clientId
|
|
668
|
+
});
|
|
669
|
+
const response = await fetch(discovery.token_endpoint, {
|
|
670
|
+
method: 'POST',
|
|
671
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
672
|
+
body: body.toString()
|
|
673
|
+
});
|
|
674
|
+
if (!response.ok) {
|
|
675
|
+
this.clearOidcTokens();
|
|
676
|
+
throw new Error('Token refresh failed');
|
|
677
|
+
}
|
|
678
|
+
const raw = await response.json();
|
|
679
|
+
const tokens = {
|
|
680
|
+
accessToken: raw.access_token,
|
|
681
|
+
refreshToken: raw.refresh_token,
|
|
682
|
+
idToken: raw.id_token,
|
|
683
|
+
expiresIn: raw.expires_in,
|
|
684
|
+
tokenType: raw.token_type,
|
|
685
|
+
scope: raw.scope
|
|
686
|
+
};
|
|
687
|
+
this.setOidcTokens(tokens);
|
|
688
|
+
}
|
|
689
|
+
generateCodeVerifier() {
|
|
690
|
+
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
|
|
691
|
+
const array = new Uint8Array(64);
|
|
692
|
+
crypto.getRandomValues(array);
|
|
693
|
+
return Array.from(array, byte => charset[byte % charset.length]).join('');
|
|
694
|
+
}
|
|
695
|
+
async generateCodeChallenge(verifier) {
|
|
696
|
+
const encoder = new TextEncoder();
|
|
697
|
+
const data = encoder.encode(verifier);
|
|
698
|
+
const digest = await crypto.subtle.digest('SHA-256', data);
|
|
699
|
+
return btoa(String.fromCharCode(...new Uint8Array(digest)))
|
|
700
|
+
.replace(/\+/g, '-')
|
|
701
|
+
.replace(/\//g, '_')
|
|
702
|
+
.replace(/=+$/, '');
|
|
703
|
+
}
|
|
704
|
+
generateState() {
|
|
705
|
+
const array = new Uint8Array(32);
|
|
706
|
+
crypto.getRandomValues(array);
|
|
707
|
+
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
708
|
+
}
|
|
411
709
|
}
|
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
},
|
|
12
12
|
extensionsToTreatAsEsm: ['.ts'],
|
|
13
13
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
14
|
-
testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
|
|
14
|
+
testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)', 'tests/**/*.test.ts'],
|
|
15
15
|
collectCoverage: true,
|
|
16
16
|
coverageDirectory: 'coverage',
|
|
17
17
|
coverageReporters: ['text', 'lcov'],
|
package/package.json
CHANGED
|
@@ -1,38 +1,41 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "docpouch-client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"main": "dist/index.js",
|
|
5
|
-
"types": "dist/index.d.ts",
|
|
6
|
-
"exports": {
|
|
7
|
-
".": {
|
|
8
|
-
"import": "./dist/index.js",
|
|
9
|
-
"require": "./dist/index.js"
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"type": "module",
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc",
|
|
15
|
-
"test": "jest"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"docPouch",
|
|
19
|
-
"API"
|
|
20
|
-
],
|
|
21
|
-
"author": "Jan Frecè",
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"description": "
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "https://github.com/BFH-JTF/docpouch-client"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@types/
|
|
30
|
-
"@types/
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
}
|
|
38
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "docpouch-client",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"require": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.build.json",
|
|
15
|
+
"test": "node --experimental-vm-modules --no-warnings ./node_modules/jest/bin/jest.js --forceExit --silent"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"docPouch",
|
|
19
|
+
"API"
|
|
20
|
+
],
|
|
21
|
+
"author": "Jan Frecè",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"description": "Client SDK for DocPouch API - supports JWT and OIDC authentication",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/BFH-JTF/docpouch-client"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/express": "^5.0.6",
|
|
30
|
+
"@types/jest": "^30.0.0",
|
|
31
|
+
"@types/node": "^25.7.0",
|
|
32
|
+
"express": "^5.2.1",
|
|
33
|
+
"jest": "^30.4.2",
|
|
34
|
+
"socket.io": "^4.8.3",
|
|
35
|
+
"ts-jest": "^29.4.9",
|
|
36
|
+
"typescript": "^6.0.3"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"socket.io-client": "^4.8.3"
|
|
40
|
+
}
|
|
41
|
+
}
|