@idp.global/sdk 18.3.1 → 19.0.0

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/changelog.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-10-07 - 19.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - the relying-party socket binding takes the application's own TypedSocket, of any major (relyingparty)
8
+ - `RelyingPartySocketBinding` named TypedSocket 8 and SmartServe 6 types, so an application whose server runs TypedSocket 9 could not pass its transport. The binding reads only `setServerTag`, `findAllTargetConnectionsByTag` and a peer's upgrade headers; `TRelyingPartySocketConnection`, `TRelyingPartySocketPeer` and `TRelyingPartySocketTransport` are now exactly those structural shapes, and relyingparty imports no TypedSocket.
9
+ - Migration: an application that hands the connections of `connectionsOfSession` back to its TypedSocket (e.g. `removeServerTag`) names its connection type as the second type parameter: `RelyingPartySocketBinding<IUser, ISmartServeConnectionWrapper>`.
10
+
11
+ ### Maintenance
12
+
13
+ - release tooling: pnpm 12.8.2, @git.zone/tsbuild ^5.1.2, @git.zone/tsdoc ^3.0.2, @git.zone/tstest ^7.2.0, @types/node 26.6.3
14
+
3
15
  ## 2026-10-01 - 18.3.1
4
16
 
5
17
  ### Fixes
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@idp.global/sdk',
6
- version: '18.3.1',
6
+ version: '19.0.0',
7
7
  description: 'Reusable browser and server SDK for idp.global authentication.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxpQkFBaUI7SUFDdkIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLGdFQUFnRTtDQUM5RSxDQUFBIn0=
@@ -1,13 +1,32 @@
1
- import * as plugins from './plugins.js';
2
1
  import type { RelyingPartySessions } from './classes.relyingpartysessions.js';
3
2
  import type { IRelyingPartySession } from './interfaces.js';
4
- /** The part of a server `TypedSocket` the binding uses. */
5
- export type TRelyingPartySocketTransport = Pick<plugins.typedsocket.TypedSocket, 'setServerTag' | 'findAllTargetConnectionsByTag'>;
6
- export type TRelyingPartySocketConnection = plugins.typedsocket.ISmartServeConnectionWrapper;
7
- /** The SmartServe WebSocket peer underneath a connection, as a TypedSocket server hands it out. */
8
- export type TRelyingPartySocketPeer = TRelyingPartySocketConnection['peer'];
9
- /** A connection wrapper or its peer; `TypedSocket.setServerTag` takes either. */
10
- export type TRelyingPartySocketTarget = TRelyingPartySocketConnection | TRelyingPartySocketPeer;
3
+ /**
4
+ * The WebSocket peer underneath a connection, as far as the binding reads it:
5
+ * the headers its upgrade arrived with. A SmartServe peer of any major fits.
6
+ */
7
+ export type TRelyingPartySocketPeer = {
8
+ context: {
9
+ headers: {
10
+ get(nameArg: string): string | null;
11
+ };
12
+ };
13
+ };
14
+ /** A server connection as the binding reads it: its peer. A TypedSocket connection wrapper of any major fits. */
15
+ export type TRelyingPartySocketConnection = {
16
+ peer: TRelyingPartySocketPeer;
17
+ };
18
+ /** A connection or its peer; `TypedSocket.setServerTag` takes either. */
19
+ export type TRelyingPartySocketTarget<TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> = TConnection | TConnection['peer'];
20
+ /**
21
+ * The part of the application's server `TypedSocket` the binding uses. The
22
+ * binding names no TypedSocket or SmartServe version: the application's own
23
+ * transport fits whichever major it runs, and `connectionsOfSession` answers
24
+ * its own connection type.
25
+ */
26
+ export type TRelyingPartySocketTransport<TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> = {
27
+ setServerTag(targetArg: TRelyingPartySocketTarget<TConnection>, nameArg: string): void;
28
+ findAllTargetConnectionsByTag(nameArg: string): Promise<TConnection[]>;
29
+ };
11
30
  /** What a browser connection is pinned to for its whole life; no cookie and no CSRF token is kept. */
12
31
  export interface IRelyingPartyPinnedSession {
13
32
  sessionId: string;
@@ -27,10 +46,10 @@ export type TRelyingPartySocketRegistration = {
27
46
  registered: false;
28
47
  refusal: IRelyingPartySocketRefusal;
29
48
  };
30
- export interface IRelyingPartySocketBindingOptions<TPrincipal extends object | undefined = undefined> {
49
+ export interface IRelyingPartySocketBindingOptions<TPrincipal extends object | undefined = undefined, TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> {
31
50
  sessions: RelyingPartySessions<TPrincipal>;
32
51
  /** the transport typedserver created; `undefined` before the server runs */
33
- transport: () => TRelyingPartySocketTransport | undefined;
52
+ transport: () => TRelyingPartySocketTransport<TConnection> | undefined;
34
53
  /** the server-owned tag prefix that finds the connections of a session */
35
54
  tagPrefix?: string;
36
55
  }
@@ -43,10 +62,10 @@ export interface IRelyingPartySocketBindingOptions<TPrincipal extends object | u
43
62
  * request. Connection limits, rate limits and sweeps belong to the
44
63
  * application's socket gate.
45
64
  */
46
- export declare class RelyingPartySocketBinding<TPrincipal extends object | undefined = undefined> {
65
+ export declare class RelyingPartySocketBinding<TPrincipal extends object | undefined = undefined, TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> {
47
66
  #private;
48
67
  readonly tagPrefix: string;
49
- constructor(optionsArg: IRelyingPartySocketBindingOptions<TPrincipal>);
68
+ constructor(optionsArg: IRelyingPartySocketBindingOptions<TPrincipal, TConnection>);
50
69
  /** The upgrade headers a connection (or its peer) arrived with. */
51
70
  upgradeOf(targetArg: TRelyingPartySocketTarget): {
52
71
  origin: string | null;
@@ -66,7 +85,7 @@ export declare class RelyingPartySocketBinding<TPrincipal extends object | undef
66
85
  * Tags a connection — its wrapper or its peer — with its session; throws
67
86
  * when the transport is not running or the connection is gone.
68
87
  */
69
- tagConnection(targetArg: TRelyingPartySocketTarget, sessionIdArg: string): void;
88
+ tagConnection(targetArg: TRelyingPartySocketTarget<TConnection>, sessionIdArg: string): void;
70
89
  /**
71
90
  * The pinned session as it stands right now: re-read, live, its principal
72
91
  * active and unchanged (and resolved, with `principals.resolve`), touched
@@ -80,5 +99,5 @@ export declare class RelyingPartySocketBinding<TPrincipal extends object | undef
80
99
  verifyCsrf(candidateArg: unknown): boolean;
81
100
  } | null>;
82
101
  /** The live connections of one session, for closing them when it ends. */
83
- connectionsOfSession(sessionIdArg: string): Promise<readonly TRelyingPartySocketConnection[]>;
102
+ connectionsOfSession(sessionIdArg: string): Promise<readonly TConnection[]>;
84
103
  }
@@ -1,4 +1,3 @@
1
- import * as plugins from './plugins.js';
2
1
  import { sha256, timingSafeEqualString } from './helpers.crypto.js';
3
2
  const peerOf = (targetArg) => 'peer' in targetArg ? targetArg.peer : targetArg;
4
3
  /**
@@ -97,4 +96,4 @@ export class RelyingPartySocketBinding {
97
96
  return transport.findAllTargetConnectionsByTag(this.tagOf(sessionIdArg));
98
97
  }
99
98
  }
100
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zb2NrZXRiaW5kaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfcmVseWluZ3BhcnR5L2NsYXNzZXMuc29ja2V0YmluZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsTUFBTSxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFpQnBFLE1BQU0sTUFBTSxHQUFHLENBQUMsU0FBb0MsRUFBMkIsRUFBRSxDQUMvRSxNQUFNLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUEyQm5EOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLHlCQUF5QjtJQUMzQixTQUFTLENBQW1DO0lBQzVDLFVBQVUsQ0FBaUQ7SUFDcEQsU0FBUyxDQUFTO0lBRWxDLFlBQVksVUFBeUQ7UUFDbkUsSUFBSSxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQztRQUN2QyxJQUFJLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxTQUFTLElBQUksaUJBQWlCLENBQUM7SUFDN0QsQ0FBQztJQUVELG1FQUFtRTtJQUM1RCxTQUFTLENBQUMsU0FBb0M7UUFDbkQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7SUFDMUUsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsMEJBQTBCLENBQ3JDLFVBQW1CLEVBQ25C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
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zb2NrZXRiaW5kaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfcmVseWluZ3BhcnR5L2NsYXNzZXMuc29ja2V0YmluZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsTUFBTSxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFnQ3BFLE1BQU0sTUFBTSxHQUFHLENBQUMsU0FBb0MsRUFBMkIsRUFBRSxDQUMvRSxNQUFNLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUE4Qm5EOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLHlCQUF5QjtJQUkzQixTQUFTLENBQW1DO0lBQzVDLFVBQVUsQ0FBOEQ7SUFDakUsU0FBUyxDQUFTO0lBRWxDLFlBQVksVUFBc0U7UUFDaEYsSUFBSSxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQztRQUN2QyxJQUFJLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxTQUFTLElBQUksaUJBQWlCLENBQUM7SUFDN0QsQ0FBQztJQUVELG1FQUFtRTtJQUM1RCxTQUFTLENBQUMsU0FBb0M7UUFDbkQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7SUFDMUUsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsMEJBQTBCLENBQ3JDLFVBQW1CLEVBQ25CLFVBQTREO1FBRTVELElBQUksQ0FBQyxVQUFVLElBQUksT0FB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
@@ -2,8 +2,7 @@ import * as asyncHooks from 'node:async_hooks';
2
2
  import * as crypto from 'node:crypto';
3
3
  export { asyncHooks, crypto };
4
4
  import * as typedrequest from '@api.global/typedrequest';
5
- import * as typedsocket from '@api.global/typedsocket';
6
- export { typedrequest, typedsocket };
5
+ export { typedrequest };
7
6
  import * as nosqldb from '@lossless.org/client/nosqldb';
8
7
  export { nosqldb };
9
8
  import * as openidClient from 'openid-client';
@@ -2,10 +2,9 @@ import * as asyncHooks from 'node:async_hooks';
2
2
  import * as crypto from 'node:crypto';
3
3
  export { asyncHooks, crypto };
4
4
  import * as typedrequest from '@api.global/typedrequest';
5
- import * as typedsocket from '@api.global/typedsocket';
6
- export { typedrequest, typedsocket };
5
+ export { typedrequest };
7
6
  import * as nosqldb from '@lossless.org/client/nosqldb';
8
7
  export { nosqldb };
9
8
  import * as openidClient from 'openid-client';
10
9
  export { openidClient };
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3JlbHlpbmdwYXJ0eS9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUU5QixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUVyQyxPQUFPLEtBQUssT0FBTyxNQUFNLDhCQUE4QixDQUFDO0FBRXhELE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQixPQUFPLEtBQUssWUFBWSxNQUFNLGVBQWUsQ0FBQztBQUU5QyxPQUFPLEVBQUUsWUFBWSxFQUFFLENBQUMifQ==
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3JlbHlpbmdwYXJ0eS9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUU5QixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBRXpELE9BQU8sRUFBRSxZQUFZLEVBQUUsQ0FBQztBQUV4QixPQUFPLEtBQUssT0FBTyxNQUFNLDhCQUE4QixDQUFDO0FBRXhELE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQixPQUFPLEtBQUssWUFBWSxNQUFNLGVBQWUsQ0FBQztBQUU5QyxPQUFPLEVBQUUsWUFBWSxFQUFFLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idp.global/sdk",
3
- "version": "18.3.1",
3
+ "version": "19.0.0",
4
4
  "private": false,
5
5
  "description": "Reusable browser and server SDK for idp.global authentication.",
6
6
  "type": "module",
@@ -34,13 +34,13 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@api.global/typedserver": "^11.4.0",
37
- "@git.zone/tsbuild": "^5.0.0",
38
- "@git.zone/tsdoc": "^3.0.0",
37
+ "@git.zone/tsbuild": "^5.1.2",
38
+ "@git.zone/tsdoc": "^3.0.2",
39
39
  "@git.zone/tsrun": "^3.0.2",
40
- "@git.zone/tstest": "^6.3.2",
40
+ "@git.zone/tstest": "^7.2.0",
41
41
  "@lossless.org/client": "^1.0.0",
42
42
  "@lossless.org/nosqldb": "10.5.0",
43
- "@types/node": "26.6.2"
43
+ "@types/node": "26.6.3"
44
44
  },
45
45
  "files": [
46
46
  "ts/**/*",
package/readme.md CHANGED
@@ -660,7 +660,24 @@ then the application's. The two options are not combined.
660
660
 
661
661
  **Socket peers.** `RelyingPartySocketBinding.tagConnection` and `upgradeOf` take
662
662
  the connection wrapper or the bare SmartServe peer (`TRelyingPartySocketPeer`),
663
- the two forms `TypedSocket.setServerTag` accepts.
663
+ the two forms `TypedSocket.setServerTag` accepts. The binding names no
664
+ TypedSocket or SmartServe version: its transport, connection and peer types are
665
+ only what it reads (`setServerTag`, `findAllTargetConnectionsByTag`, a peer's
666
+ upgrade headers), so the application's own server `TypedSocket` fits whichever
667
+ major it runs. Name the application's connection type as the second type
668
+ parameter and `connectionsOfSession` answers it:
669
+
670
+ ```ts
671
+ import type { ISmartServeConnectionWrapper } from '@api.global/typedsocket';
672
+
673
+ const binding = new RelyingPartySocketBinding<IUser, ISmartServeConnectionWrapper>({
674
+ sessions,
675
+ transport: () => typedserver.typedsocket,
676
+ });
677
+ for (const connection of await binding.connectionsOfSession(sessionId)) {
678
+ typedserver.removeServerTag(connection, binding.tagOf(sessionId));
679
+ }
680
+ ```
664
681
 
665
682
  ### Relying-Party API Surface
666
683
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@idp.global/sdk',
6
- version: '18.3.1',
6
+ version: '19.0.0',
7
7
  description: 'Reusable browser and server SDK for idp.global authentication.'
8
8
  }
@@ -1,21 +1,35 @@
1
- import * as plugins from './plugins.js';
2
1
  import type { RelyingPartySessions } from './classes.relyingpartysessions.js';
3
2
  import { sha256, timingSafeEqualString } from './helpers.crypto.js';
4
3
  import type { IRelyingPartySession } from './interfaces.js';
5
4
 
6
- /** The part of a server `TypedSocket` the binding uses. */
7
- export type TRelyingPartySocketTransport = Pick<
8
- plugins.typedsocket.TypedSocket,
9
- 'setServerTag' | 'findAllTargetConnectionsByTag'
10
- >;
5
+ /**
6
+ * The WebSocket peer underneath a connection, as far as the binding reads it:
7
+ * the headers its upgrade arrived with. A SmartServe peer of any major fits.
8
+ */
9
+ export type TRelyingPartySocketPeer = {
10
+ context: { headers: { get(nameArg: string): string | null } };
11
+ };
11
12
 
12
- export type TRelyingPartySocketConnection = plugins.typedsocket.ISmartServeConnectionWrapper;
13
+ /** A server connection as the binding reads it: its peer. A TypedSocket connection wrapper of any major fits. */
14
+ export type TRelyingPartySocketConnection = {
15
+ peer: TRelyingPartySocketPeer;
16
+ };
13
17
 
14
- /** The SmartServe WebSocket peer underneath a connection, as a TypedSocket server hands it out. */
15
- export type TRelyingPartySocketPeer = TRelyingPartySocketConnection['peer'];
18
+ /** A connection or its peer; `TypedSocket.setServerTag` takes either. */
19
+ export type TRelyingPartySocketTarget<TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> =
20
+ | TConnection
21
+ | TConnection['peer'];
16
22
 
17
- /** A connection wrapper or its peer; `TypedSocket.setServerTag` takes either. */
18
- export type TRelyingPartySocketTarget = TRelyingPartySocketConnection | TRelyingPartySocketPeer;
23
+ /**
24
+ * The part of the application's server `TypedSocket` the binding uses. The
25
+ * binding names no TypedSocket or SmartServe version: the application's own
26
+ * transport fits whichever major it runs, and `connectionsOfSession` answers
27
+ * its own connection type.
28
+ */
29
+ export type TRelyingPartySocketTransport<TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection> = {
30
+ setServerTag(targetArg: TRelyingPartySocketTarget<TConnection>, nameArg: string): void;
31
+ findAllTargetConnectionsByTag(nameArg: string): Promise<TConnection[]>;
32
+ };
19
33
 
20
34
  const peerOf = (targetArg: TRelyingPartySocketTarget): TRelyingPartySocketPeer =>
21
35
  'peer' in targetArg ? targetArg.peer : targetArg;
@@ -37,10 +51,13 @@ export type TRelyingPartySocketRegistration =
37
51
  | { registered: true; pinned: IRelyingPartyPinnedSession; expiresAt: number }
38
52
  | { registered: false; refusal: IRelyingPartySocketRefusal };
39
53
 
40
- export interface IRelyingPartySocketBindingOptions<TPrincipal extends object | undefined = undefined> {
54
+ export interface IRelyingPartySocketBindingOptions<
55
+ TPrincipal extends object | undefined = undefined,
56
+ TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection,
57
+ > {
41
58
  sessions: RelyingPartySessions<TPrincipal>;
42
59
  /** the transport typedserver created; `undefined` before the server runs */
43
- transport: () => TRelyingPartySocketTransport | undefined;
60
+ transport: () => TRelyingPartySocketTransport<TConnection> | undefined;
44
61
  /** the server-owned tag prefix that finds the connections of a session */
45
62
  tagPrefix?: string;
46
63
  }
@@ -54,12 +71,15 @@ export interface IRelyingPartySocketBindingOptions<TPrincipal extends object | u
54
71
  * request. Connection limits, rate limits and sweeps belong to the
55
72
  * application's socket gate.
56
73
  */
57
- export class RelyingPartySocketBinding<TPrincipal extends object | undefined = undefined> {
74
+ export class RelyingPartySocketBinding<
75
+ TPrincipal extends object | undefined = undefined,
76
+ TConnection extends TRelyingPartySocketConnection = TRelyingPartySocketConnection,
77
+ > {
58
78
  readonly #sessions: RelyingPartySessions<TPrincipal>;
59
- readonly #transport: () => TRelyingPartySocketTransport | undefined;
79
+ readonly #transport: () => TRelyingPartySocketTransport<TConnection> | undefined;
60
80
  public readonly tagPrefix: string;
61
81
 
62
- constructor(optionsArg: IRelyingPartySocketBindingOptions<TPrincipal>) {
82
+ constructor(optionsArg: IRelyingPartySocketBindingOptions<TPrincipal, TConnection>) {
63
83
  this.#sessions = optionsArg.sessions;
64
84
  this.#transport = optionsArg.transport;
65
85
  this.tagPrefix = optionsArg.tagPrefix ?? 'idp_rp_session:';
@@ -112,7 +132,7 @@ export class RelyingPartySocketBinding<TPrincipal extends object | undefined = u
112
132
  * Tags a connection — its wrapper or its peer — with its session; throws
113
133
  * when the transport is not running or the connection is gone.
114
134
  */
115
- public tagConnection(targetArg: TRelyingPartySocketTarget, sessionIdArg: string): void {
135
+ public tagConnection(targetArg: TRelyingPartySocketTarget<TConnection>, sessionIdArg: string): void {
116
136
  const transport = this.#transport();
117
137
  if (!transport) {
118
138
  throw new Error('The socket transport is not running');
@@ -146,7 +166,7 @@ export class RelyingPartySocketBinding<TPrincipal extends object | undefined = u
146
166
  }
147
167
 
148
168
  /** The live connections of one session, for closing them when it ends. */
149
- public async connectionsOfSession(sessionIdArg: string): Promise<readonly TRelyingPartySocketConnection[]> {
169
+ public async connectionsOfSession(sessionIdArg: string): Promise<readonly TConnection[]> {
150
170
  const transport = this.#transport();
151
171
  if (!transport) {
152
172
  return [];
@@ -4,9 +4,8 @@ import * as crypto from 'node:crypto';
4
4
  export { asyncHooks, crypto };
5
5
 
6
6
  import * as typedrequest from '@api.global/typedrequest';
7
- import * as typedsocket from '@api.global/typedsocket';
8
7
 
9
- export { typedrequest, typedsocket };
8
+ export { typedrequest };
10
9
 
11
10
  import * as nosqldb from '@lossless.org/client/nosqldb';
12
11