@serve.zone/platformclient 4.1.0 → 32.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/.smartconfig.json +1 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.platformclient.d.ts +25 -0
- package/dist_ts/classes.platformclient.js +55 -11
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/protocol.d.ts +29 -0
- package/dist_ts/protocol.js +67 -0
- package/package.json +8 -8
- package/readme.md +25 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.platformclient.ts +72 -11
- package/ts/index.ts +4 -0
- package/ts/protocol.ts +81 -0
package/.smartconfig.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/platformclient',
|
|
6
|
-
version: '
|
|
6
|
+
version: '32.0.0',
|
|
7
7
|
description: 'a module that makes it really easy to use the serve.zone platform inside your app'
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSw0QkFBNEI7SUFDbEMsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLG1GQUFtRjtDQUNqRyxDQUFBIn0=
|
|
@@ -4,7 +4,10 @@ import { SzPushNotificationConnector } from './email/classes.pushnotificationcon
|
|
|
4
4
|
import { SzLetterConnector } from './email/classes.letterconnector.js';
|
|
5
5
|
import { SzWebPushConnector } from './webpush/classes.webpushconnector.js';
|
|
6
6
|
import { SzCoreMailConnector, type ISzCoreMailConnectorOptions } from './coremail/classes.coremailconnector.js';
|
|
7
|
+
import { SzPlatformProtocolIncompatibleError } from './protocol.js';
|
|
7
8
|
import * as plugins from './plugins.js';
|
|
9
|
+
/** What a caller can act on: a usable session, none, or a peer of another contract. */
|
|
10
|
+
export type TSzPlatformSessionStatus = 'connected' | 'disconnected' | 'protocol-incompatible';
|
|
8
11
|
export interface ISzPlatformClientOptions {
|
|
9
12
|
authorizationString?: string;
|
|
10
13
|
authorization?: string;
|
|
@@ -24,6 +27,13 @@ export declare class SzPlatformClient {
|
|
|
24
27
|
platformBindings: plugins.servezoneInterfaces.platform.IPlatformBinding[];
|
|
25
28
|
typedrouter: plugins.typedrequest.TypedRouter;
|
|
26
29
|
typedsocket?: plugins.typedsocket.TypedSocket;
|
|
30
|
+
/**
|
|
31
|
+
* The refusal this client met, kept for the caller that never saw it.
|
|
32
|
+
*
|
|
33
|
+
* A refused offer stands until an operator upgrades one of the two sides, and a refusal met
|
|
34
|
+
* while a reconnect restores the session reaches no caller at all, so it is read from here.
|
|
35
|
+
*/
|
|
36
|
+
lastProtocolRefusal?: SzPlatformProtocolIncompatibleError;
|
|
27
37
|
private identity?;
|
|
28
38
|
private authenticationGeneration;
|
|
29
39
|
private authenticationAbort?;
|
|
@@ -50,6 +60,21 @@ export declare class SzPlatformClient {
|
|
|
50
60
|
private getConnectionAddress;
|
|
51
61
|
private getConfiguredAuthorizationString;
|
|
52
62
|
requireTypedSocket(): plugins.typedsocket.TypedSocket;
|
|
63
|
+
/**
|
|
64
|
+
* The platform session as a caller can act on it.
|
|
65
|
+
*
|
|
66
|
+
* `protocol-incompatible` outranks the transport state: it stands until an operator upgrades
|
|
67
|
+
* one of the two sides, and `lastProtocolRefusal` names both of them.
|
|
68
|
+
*/
|
|
69
|
+
getSessionStatus(): TSzPlatformSessionStatus;
|
|
70
|
+
/**
|
|
71
|
+
* Release the socket lifecycle a restoration was refused in; every other failure passes on.
|
|
72
|
+
*
|
|
73
|
+
* TypedSocket ends its own client on a denied restoration and never reconnects from one, so the
|
|
74
|
+
* reference held here is dead — keeping it would report an unavailable session instead of the
|
|
75
|
+
* incompatible peer.
|
|
76
|
+
*/
|
|
77
|
+
private releaseRefusedSocket;
|
|
53
78
|
private invalidateAuthentication;
|
|
54
79
|
private trackAuthentication;
|
|
55
80
|
private authenticate;
|
|
@@ -4,6 +4,7 @@ import { SzPushNotificationConnector } from './email/classes.pushnotificationcon
|
|
|
4
4
|
import { SzLetterConnector } from './email/classes.letterconnector.js';
|
|
5
5
|
import { SzWebPushConnector } from './webpush/classes.webpushconnector.js';
|
|
6
6
|
import { SzCoreMailConnector, } from './coremail/classes.coremailconnector.js';
|
|
7
|
+
import { platformSessionProtocolOffer, requireCompatibleProtocol, rethrowProtocolRefusal, SzPlatformProtocolIncompatibleError, } from './protocol.js';
|
|
7
8
|
import * as plugins from './plugins.js';
|
|
8
9
|
export class SzPlatformClient {
|
|
9
10
|
constructor(authorizationStringArg) {
|
|
@@ -60,7 +61,8 @@ export class SzPlatformClient {
|
|
|
60
61
|
restoreConnection: (context) => {
|
|
61
62
|
this.invalidateAuthentication();
|
|
62
63
|
const generation = this.authenticationGeneration;
|
|
63
|
-
return this.trackAuthentication(this.authenticate(context.createTypedRequest, context.abortSignal, generation)
|
|
64
|
+
return this.trackAuthentication(this.authenticate(context.createTypedRequest, context.abortSignal, generation)
|
|
65
|
+
.catch((error) => this.releaseRefusedSocket(error, generation)));
|
|
64
66
|
},
|
|
65
67
|
});
|
|
66
68
|
if (this.stopped) {
|
|
@@ -135,10 +137,43 @@ export class SzPlatformClient {
|
|
|
135
137
|
}
|
|
136
138
|
requireTypedSocket() {
|
|
137
139
|
this.assertRunning();
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
const socket = this.typedsocket;
|
|
141
|
+
const status = this.getSessionStatus();
|
|
142
|
+
// A refused protocol is the one unavailability a caller can act on, so it keeps its name.
|
|
143
|
+
if (status === 'protocol-incompatible' && this.lastProtocolRefusal)
|
|
144
|
+
throw this.lastProtocolRefusal;
|
|
145
|
+
if (!socket || status !== 'connected') {
|
|
140
146
|
throw new Error('Cloudly platform session is unavailable.');
|
|
141
|
-
|
|
147
|
+
}
|
|
148
|
+
return socket;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The platform session as a caller can act on it.
|
|
152
|
+
*
|
|
153
|
+
* `protocol-incompatible` outranks the transport state: it stands until an operator upgrades
|
|
154
|
+
* one of the two sides, and `lastProtocolRefusal` names both of them.
|
|
155
|
+
*/
|
|
156
|
+
getSessionStatus() {
|
|
157
|
+
if (this.lastProtocolRefusal)
|
|
158
|
+
return 'protocol-incompatible';
|
|
159
|
+
if (this.typedsocket?.getStatus() === 'connected' && this.identity
|
|
160
|
+
&& this.identity.expiresAt > Date.now())
|
|
161
|
+
return 'connected';
|
|
162
|
+
return 'disconnected';
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Release the socket lifecycle a restoration was refused in; every other failure passes on.
|
|
166
|
+
*
|
|
167
|
+
* TypedSocket ends its own client on a denied restoration and never reconnects from one, so the
|
|
168
|
+
* reference held here is dead — keeping it would report an unavailable session instead of the
|
|
169
|
+
* incompatible peer.
|
|
170
|
+
*/
|
|
171
|
+
releaseRefusedSocket(errorArg, generationArg) {
|
|
172
|
+
if (errorArg instanceof SzPlatformProtocolIncompatibleError
|
|
173
|
+
&& generationArg === this.authenticationGeneration) {
|
|
174
|
+
this.typedsocket = undefined;
|
|
175
|
+
}
|
|
176
|
+
throw errorArg;
|
|
142
177
|
}
|
|
143
178
|
invalidateAuthentication() {
|
|
144
179
|
this.authenticationGeneration++;
|
|
@@ -173,20 +208,29 @@ export class SzPlatformClient {
|
|
|
173
208
|
|| !Number.isSafeInteger(identity.expiresAt) || identity.expiresAt <= Date.now() + 1000) {
|
|
174
209
|
throw new Error('Invalid platform identity.');
|
|
175
210
|
}
|
|
176
|
-
const requestData = plugins.servezoneInterfaces.data.
|
|
177
|
-
|
|
211
|
+
const requestData = plugins.servezoneInterfaces.data.snapshotRegisterCloudlyClientSessionRequest({
|
|
212
|
+
identity: { jwt: identity.jwt }, protocol: platformSessionProtocolOffer,
|
|
178
213
|
});
|
|
179
|
-
const registration = createRequest('
|
|
214
|
+
const registration = createRequest('registerCloudlyClientSession');
|
|
180
215
|
registration.skipHooks = true;
|
|
181
|
-
const registered = await registration
|
|
182
|
-
|
|
216
|
+
const registered = await registration
|
|
217
|
+
.fire(requestData, { maxRetries: 0, abortSignal: signal })
|
|
218
|
+
.catch(rethrowProtocolRefusal);
|
|
219
|
+
requireCompatibleProtocol(plugins.servezoneInterfaces.data
|
|
220
|
+
.snapshotRegisterCloudlyClientSessionResponse(registered).protocol);
|
|
183
221
|
requireCurrent();
|
|
184
222
|
this.identity = { type: identity.type, role: identity.role, userId: identity.userId,
|
|
185
223
|
name: identity.userId, expiresAt: identity.expiresAt, jwt: requestData.identity.jwt };
|
|
186
224
|
}
|
|
187
|
-
catch {
|
|
225
|
+
catch (error) {
|
|
188
226
|
if (this.stopped || signal.aborted || generation !== this.authenticationGeneration)
|
|
189
227
|
throw this.createAbortError();
|
|
228
|
+
// A refused offer rejected no credential of this caller's, so it is named rather than
|
|
229
|
+
// collapsed, and kept where a restoration that has no caller can still be read.
|
|
230
|
+
if (error instanceof SzPlatformProtocolIncompatibleError) {
|
|
231
|
+
this.lastProtocolRefusal = error;
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
190
234
|
throw new Error('Cloudly platform authentication failed.');
|
|
191
235
|
}
|
|
192
236
|
}
|
|
@@ -333,4 +377,4 @@ export class SzPlatformClient {
|
|
|
333
377
|
return processEnv?.[envNameArg];
|
|
334
378
|
}
|
|
335
379
|
}
|
|
336
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wbGF0Zm9ybWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucGxhdGZvcm1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQzNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQzNFLE9BQU8sRUFDTCxtQkFBbUIsR0FFcEIsTUFBTSx5Q0FBeUMsQ0FBQztBQUNqRCxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQWV4QyxNQUFNLE9BQU8sZ0JBQWdCO0lBMEIzQixZQUFZLHNCQUEwRDtRQXpCL0QsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUdsQixxQkFBZ0IsR0FBNEQsRUFBRSxDQUFDO1FBQy9FLGdCQUFXLEdBQXFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUd0Riw2QkFBd0IsR0FBRyxDQUFDLENBQUM7UUFFN0IsNkJBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFHdkQsaUJBQVksR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkMsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUdQLGtDQUE2QixHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFFaEUsbUJBQWMsR0FBRyxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzVDLGlCQUFZLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEMsOEJBQXlCLEdBQUcsSUFBSSwy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
|
|
380
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wbGF0Zm9ybWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucGxhdGZvcm1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQzNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQzNFLE9BQU8sRUFDTCxtQkFBbUIsR0FFcEIsTUFBTSx5Q0FBeUMsQ0FBQztBQUNqRCxPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLHlCQUF5QixFQUN6QixzQkFBc0IsRUFDdEIsbUNBQW1DLEdBQ3BDLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBa0J4QyxNQUFNLE9BQU8sZ0JBQWdCO0lBaUMzQixZQUFZLHNCQUEwRDtRQWhDL0QsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUdsQixxQkFBZ0IsR0FBNEQsRUFBRSxDQUFDO1FBQy9FLGdCQUFXLEdBQXFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQVV0Riw2QkFBd0IsR0FBRyxDQUFDLENBQUM7UUFFN0IsNkJBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFHdkQsaUJBQVksR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkMsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUdQLGtDQUE2QixHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFFaEUsbUJBQWMsR0FBRyxJQUFJLGdCQUFnQixDQUFDLElB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
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './classes.platformclient.js';
|
|
2
|
+
export { platformSessionProtocolOffer, SzPlatformProtocolIncompatibleError, } from './protocol.js';
|
|
2
3
|
export * from './coremail/classes.coremailconnector.js';
|
|
3
4
|
export * from './email/classes.emailconnector.js';
|
|
4
5
|
export * from './webpush/classes.webpushconnector.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './classes.platformclient.js';
|
|
2
|
+
export { platformSessionProtocolOffer, SzPlatformProtocolIncompatibleError, } from './protocol.js';
|
|
2
3
|
export * from './coremail/classes.coremailconnector.js';
|
|
3
4
|
export * from './email/classes.emailconnector.js';
|
|
4
5
|
export * from './webpush/classes.webpushconnector.js';
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLE9BQU8sRUFDTCw0QkFBNEIsRUFDNUIsbUNBQW1DLEdBQ3BDLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLGNBQWMseUNBQXlDLENBQUM7QUFDeEQsY0FBYyxtQ0FBbUMsQ0FBQztBQUNsRCxjQUFjLHVDQUF1QyxDQUFDIn0=
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
/** This build's offer for the one session kind the platform client opens. */
|
|
3
|
+
export declare const platformSessionProtocolOffer: plugins.servezoneInterfaces.protocol.IProtocolOffer;
|
|
4
|
+
/**
|
|
5
|
+
* Two peers that cannot serve one session, named rather than collapsed into an authentication
|
|
6
|
+
* failure.
|
|
7
|
+
*
|
|
8
|
+
* A refusal stands until an operator upgrades one of the two sides, so it is never retried: the
|
|
9
|
+
* caller is rejected with it, and a refusal met while a reconnect restores the session — where no
|
|
10
|
+
* caller waits — ends that socket lifecycle and is retained on the client instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare class SzPlatformProtocolIncompatibleError extends Error {
|
|
13
|
+
readonly refusal: plugins.servezoneInterfaces.protocol.IProtocolRefusal;
|
|
14
|
+
constructor(refusalArg: plugins.servezoneInterfaces.protocol.IProtocolRefusal, optionsArg?: ErrorOptions);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rethrow a refused offer as this client's named error; every other failure passes untouched.
|
|
18
|
+
*
|
|
19
|
+
* The transport error stays attached as the cause, so the correlation a caller needs to find the
|
|
20
|
+
* hop in a log is not lost behind the refusal.
|
|
21
|
+
*/
|
|
22
|
+
export declare const rethrowProtocolRefusal: (errorArg: unknown) => never;
|
|
23
|
+
/**
|
|
24
|
+
* The controller's own offer, judged from this client's side.
|
|
25
|
+
*
|
|
26
|
+
* Acceptance is the controller's decision about this client; whether this client can serve the
|
|
27
|
+
* session it was just given is this check, and a client that cannot must not use it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const requireCompatibleProtocol: (peerOfferArg: plugins.servezoneInterfaces.protocol.IProtocolOffer) => void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
const protocol = plugins.servezoneInterfaces.protocol;
|
|
3
|
+
/**
|
|
4
|
+
* The oldest Cloudly release this client opens its platform session with.
|
|
5
|
+
*
|
|
6
|
+
* It is raised only by the commit that starts depending on a later `@serve.zone/interfaces`
|
|
7
|
+
* minor, and that raise is named in the changelog: a client that demands more than it needs
|
|
8
|
+
* refuses controllers it could have served. What this client speaks is never stated here — it is
|
|
9
|
+
* the installed release, which `createProtocolOffer` reads from the package itself.
|
|
10
|
+
*/
|
|
11
|
+
const platformSessionMinimumPeerVersion = '32.0.0';
|
|
12
|
+
/** This build's offer for the one session kind the platform client opens. */
|
|
13
|
+
export const platformSessionProtocolOffer = protocol.createProtocolOffer(platformSessionMinimumPeerVersion);
|
|
14
|
+
/**
|
|
15
|
+
* Two peers that cannot serve one session, named rather than collapsed into an authentication
|
|
16
|
+
* failure.
|
|
17
|
+
*
|
|
18
|
+
* A refusal stands until an operator upgrades one of the two sides, so it is never retried: the
|
|
19
|
+
* caller is rejected with it, and a refusal met while a reconnect restores the session — where no
|
|
20
|
+
* caller waits — ends that socket lifecycle and is retained on the client instead.
|
|
21
|
+
*/
|
|
22
|
+
export class SzPlatformProtocolIncompatibleError extends Error {
|
|
23
|
+
constructor(refusalArg, optionsArg) {
|
|
24
|
+
super(protocol.describeProtocolRefusal(refusalArg), optionsArg);
|
|
25
|
+
this.name = 'SzPlatformProtocolIncompatibleError';
|
|
26
|
+
this.refusal = refusalArg;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The payload a failed TypedRequest hop carried.
|
|
31
|
+
*
|
|
32
|
+
* Read structurally rather than through `instanceof TypedResponseError`: the request that fails is
|
|
33
|
+
* created by TypedSocket, which resolves its own `@api.global/typedrequest`, so a class identity
|
|
34
|
+
* check could miss a refusal in a consumer tree that holds a second copy.
|
|
35
|
+
*/
|
|
36
|
+
const readErrorData = (errorArg) => {
|
|
37
|
+
if (typeof errorArg !== 'object' || errorArg === null || !('errorData' in errorArg)) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return errorArg.errorData;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Rethrow a refused offer as this client's named error; every other failure passes untouched.
|
|
44
|
+
*
|
|
45
|
+
* The transport error stays attached as the cause, so the correlation a caller needs to find the
|
|
46
|
+
* hop in a log is not lost behind the refusal.
|
|
47
|
+
*/
|
|
48
|
+
export const rethrowProtocolRefusal = (errorArg) => {
|
|
49
|
+
const refusal = protocol.readProtocolRefusal(readErrorData(errorArg));
|
|
50
|
+
if (refusal === null) {
|
|
51
|
+
throw errorArg;
|
|
52
|
+
}
|
|
53
|
+
throw new SzPlatformProtocolIncompatibleError(refusal, { cause: errorArg });
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The controller's own offer, judged from this client's side.
|
|
57
|
+
*
|
|
58
|
+
* Acceptance is the controller's decision about this client; whether this client can serve the
|
|
59
|
+
* session it was just given is this check, and a client that cannot must not use it.
|
|
60
|
+
*/
|
|
61
|
+
export const requireCompatibleProtocol = (peerOfferArg) => {
|
|
62
|
+
const negotiation = protocol.negotiateProtocol(platformSessionProtocolOffer, peerOfferArg);
|
|
63
|
+
if (!negotiation.compatible) {
|
|
64
|
+
throw new SzPlatformProtocolIncompatibleError(negotiation.refusal);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9wcm90b2NvbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDO0FBRXREOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLGlDQUFpQyxHQUFHLFFBQVEsQ0FBQztBQUVuRCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQ3ZDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0FBRWxFOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sbUNBQW9DLFNBQVEsS0FBSztJQUc1RCxZQUNFLFVBQWlFLEVBQ2pFLFVBQXlCO1FBRXpCLEtBQUssQ0FBQyxRQUFRLENBQUMsdUJBQXVCLENBQUMsVUFBVSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLElBQUksR0FBRyxxQ0FBcUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztJQUM1QixDQUFDO0NBQ0Y7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxDQUFDLFFBQWlCLEVBQVcsRUFBRTtJQUNuRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxRQUFRLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxXQUFXLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUNwRixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUMsU0FBUyxDQUFDO0FBQzVCLENBQUMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxRQUFpQixFQUFTLEVBQUU7SUFDakUsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLElBQUksT0FBTyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3JCLE1BQU0sUUFBUSxDQUFDO0lBQ2pCLENBQUM7SUFDRCxNQUFNLElBQUksbUNBQW1DLENBQUMsT0FBTyxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7QUFDOUUsQ0FBQyxDQUFDO0FBRUY7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxZQUFpRSxFQUMzRCxFQUFFO0lBQ1IsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGlCQUFpQixDQUFDLDRCQUE0QixFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzNGLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLG1DQUFtQyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRSxDQUFDO0FBQ0gsQ0FBQyxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/platformclient",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "32.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "a module that makes it really easy to use the serve.zone platform inside your app",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -9,23 +9,23 @@
|
|
|
9
9
|
"author": "Task Venture Capital GmbH",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@git.zone/tsbuild": "^4.
|
|
12
|
+
"@git.zone/tsbuild": "^4.5.0",
|
|
13
13
|
"@git.zone/tsbundle": "^2.13.0",
|
|
14
14
|
"@git.zone/tsrun": "^2.0.6",
|
|
15
|
-
"@git.zone/tstest": "6.1.
|
|
15
|
+
"@git.zone/tstest": "6.1.1",
|
|
16
16
|
"@push.rocks/smartmongo": "9.0.0",
|
|
17
17
|
"@push.rocks/smartserve": "6.2.1",
|
|
18
|
-
"@serve.zone/coremail": "
|
|
19
|
-
"@types/node": "26.5.
|
|
18
|
+
"@serve.zone/coremail": "32.0.0",
|
|
19
|
+
"@types/node": "26.5.1"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@api.global/typedrequest": "^8.0.4",
|
|
23
23
|
"@api.global/typedrequest-interfaces": "^7.1.0",
|
|
24
|
-
"@api.global/typedsocket": "^8.
|
|
25
|
-
"@push.rocks/qenv": "^
|
|
24
|
+
"@api.global/typedsocket": "^8.4.0",
|
|
25
|
+
"@push.rocks/qenv": "^7.0.0",
|
|
26
26
|
"@push.rocks/smartlog": "^3.2.2",
|
|
27
27
|
"@push.rocks/smartntml": "^2.0.9",
|
|
28
|
-
"@serve.zone/interfaces": "^
|
|
28
|
+
"@serve.zone/interfaces": "^32.1.0"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
package/readme.md
CHANGED
|
@@ -45,11 +45,11 @@ await platformClient.emailConnector.sendEmail({
|
|
|
45
45
|
| `letterConnector` | `sendLetter()` | `letter` |
|
|
46
46
|
| `coreMailConnector` | `prepareOutboundSubmission()`, `uploadOutboundPart()`, `finalizeOutboundSubmission()`, `getOutboundSubmission()`, `listInboundDeliveries()`, `fetchInboundDelivery()`, `acknowledgeInboundDelivery()` | CoreMail workload binding |
|
|
47
47
|
|
|
48
|
-
The request and response payloads come from `@serve.zone/interfaces`, so TypeScript stays aligned with the serve.zone platform contracts.
|
|
48
|
+
The request and response payloads come from `@serve.zone/interfaces`, so TypeScript stays aligned with the serve.zone platform contracts. The installed `@serve.zone/interfaces` release *is* the contract version this client speaks; no payload states a schema version of its own.
|
|
49
49
|
|
|
50
50
|
## Configuration
|
|
51
51
|
|
|
52
|
-
The shared platform connection requires a Cloudly machine token and an explicit HTTPS Cloudly origin. On each connection it exchanges the token for an API machine identity and
|
|
52
|
+
The shared platform connection requires a Cloudly machine token and an explicit HTTPS Cloudly origin. On each connection it exchanges the token for an API machine identity and calls `registerCloudlyClientSession` with that JWT and its protocol offer before initialization succeeds. Reconnect repeats both steps, and a live connection renews its identity before expiry. Rejected credentials, invalid registration replies, or failed renewal close the connection. Value-free platform bindings describe capabilities; they never select the Cloudly authority or provide credentials.
|
|
53
53
|
|
|
54
54
|
| Value | Sources |
|
|
55
55
|
| --- | --- |
|
|
@@ -91,6 +91,28 @@ const client = new SzPlatformClient({
|
|
|
91
91
|
await client.init();
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## Protocol handshake
|
|
95
|
+
|
|
96
|
+
Every platform session states which contract it speaks. `registerCloudlyClientSession` carries `protocol.createProtocolOffer('32.0.0')` — the installed `@serve.zone/interfaces` version as `interfacesVersion`, and `32.0.0` as the oldest Cloudly release this client accepts — and Cloudly answers with its own offer, which this client negotiates against its own before it uses the session.
|
|
97
|
+
|
|
98
|
+
A peer that cannot serve the session is named, never collapsed into a credential failure: the caller is rejected with `SzPlatformProtocolIncompatibleError`, which carries the `IProtocolRefusal` (`code: 'protocol-incompatible'`, its reason, and both sides' offers). A refusal stands until an operator upgrades one of the two sides, so it is never retried: a refusal met while a reconnect restores the session — where no caller waits — ends that socket lifecycle and is kept on the client.
|
|
99
|
+
|
|
100
|
+
| Member | Meaning |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `getSessionStatus()` | `'connected'`, `'disconnected'`, or `'protocol-incompatible'` — the refusal outranks the transport state |
|
|
103
|
+
| `lastProtocolRefusal` | The retained `SzPlatformProtocolIncompatibleError`, with `refusal.refusing` and `refusal.refused` |
|
|
104
|
+
| `platformSessionProtocolOffer` | This build's offer, exported for callers that report platform compatibility |
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
await client.init().catch((error) => {
|
|
108
|
+
if (client.getSessionStatus() === 'protocol-incompatible') {
|
|
109
|
+
// Both offers are in client.lastProtocolRefusal.refusal; upgrade one side.
|
|
110
|
+
throw client.lastProtocolRefusal;
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
94
116
|
## Socket 8 migration
|
|
95
117
|
|
|
96
118
|
Version 4 requires Socket 8 peers: upgrade Cloudly and the dedicated dcrouter mail/Web Push endpoints together with their clients. Older Socket 4/5 servers are incompatible. Set `SERVEZONE_PLATFORM_URL` to Cloudly's HTTPS origin and retain `MAIL_TYPED_URL` for the dedicated mail endpoint. Replace legacy platform tokens with Cloudly service credentials; initialization no longer accepts a successful transport handshake as authentication. CoreMail, SMTP credential discovery, mail delivery status, attachments, Reply-To, and debug connector behavior remain available.
|
|
@@ -122,7 +144,7 @@ The current SMS verification method is spelled `sendSmsVerifcation()` in code. U
|
|
|
122
144
|
|
|
123
145
|
## Lifecycle
|
|
124
146
|
|
|
125
|
-
`SzPlatformClient` keeps separate TypedSocket connections for Cloudly, CoreMail, typed service mail, and managed Web Push. Call `stop()` to cancel initialization, renewal, and restoration and join their cleanup. `requireTypedSocket()` returns the authenticated Cloudly connection while
|
|
147
|
+
`SzPlatformClient` keeps separate TypedSocket connections for Cloudly, CoreMail, typed service mail, and managed Web Push. Call `stop()` to cancel initialization, renewal, and restoration and join their cleanup. `requireTypedSocket()` returns the authenticated Cloudly connection while `getSessionStatus()` is `connected`; `typedsocket` is optional. The mail router is private to its own connection, so Cloudly and Web Push peers cannot invoke inbound mail handlers.
|
|
126
148
|
|
|
127
149
|
```typescript
|
|
128
150
|
const client = new SzPlatformClient({
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -7,8 +7,17 @@ import {
|
|
|
7
7
|
SzCoreMailConnector,
|
|
8
8
|
type ISzCoreMailConnectorOptions,
|
|
9
9
|
} from './coremail/classes.coremailconnector.js';
|
|
10
|
+
import {
|
|
11
|
+
platformSessionProtocolOffer,
|
|
12
|
+
requireCompatibleProtocol,
|
|
13
|
+
rethrowProtocolRefusal,
|
|
14
|
+
SzPlatformProtocolIncompatibleError,
|
|
15
|
+
} from './protocol.js';
|
|
10
16
|
import * as plugins from './plugins.js';
|
|
11
17
|
|
|
18
|
+
/** What a caller can act on: a usable session, none, or a peer of another contract. */
|
|
19
|
+
export type TSzPlatformSessionStatus = 'connected' | 'disconnected' | 'protocol-incompatible';
|
|
20
|
+
|
|
12
21
|
export interface ISzPlatformClientOptions {
|
|
13
22
|
authorizationString?: string;
|
|
14
23
|
authorization?: string;
|
|
@@ -29,6 +38,13 @@ export class SzPlatformClient {
|
|
|
29
38
|
public platformBindings: plugins.servezoneInterfaces.platform.IPlatformBinding[] = [];
|
|
30
39
|
public typedrouter: plugins.typedrequest.TypedRouter = new plugins.typedrequest.TypedRouter();
|
|
31
40
|
public typedsocket?: plugins.typedsocket.TypedSocket;
|
|
41
|
+
/**
|
|
42
|
+
* The refusal this client met, kept for the caller that never saw it.
|
|
43
|
+
*
|
|
44
|
+
* A refused offer stands until an operator upgrades one of the two sides, and a refusal met
|
|
45
|
+
* while a reconnect restores the session reaches no caller at all, so it is read from here.
|
|
46
|
+
*/
|
|
47
|
+
public lastProtocolRefusal?: SzPlatformProtocolIncompatibleError;
|
|
32
48
|
private identity?: plugins.servezoneInterfaces.data.IIdentity;
|
|
33
49
|
private authenticationGeneration = 0;
|
|
34
50
|
private authenticationAbort?: AbortController;
|
|
@@ -98,7 +114,10 @@ export class SzPlatformClient {
|
|
|
98
114
|
restoreConnection: (context) => {
|
|
99
115
|
this.invalidateAuthentication();
|
|
100
116
|
const generation = this.authenticationGeneration;
|
|
101
|
-
return this.trackAuthentication(
|
|
117
|
+
return this.trackAuthentication(
|
|
118
|
+
this.authenticate(context.createTypedRequest, context.abortSignal, generation)
|
|
119
|
+
.catch((error) => this.releaseRefusedSocket(error, generation)),
|
|
120
|
+
);
|
|
102
121
|
},
|
|
103
122
|
},
|
|
104
123
|
);
|
|
@@ -188,9 +207,42 @@ export class SzPlatformClient {
|
|
|
188
207
|
|
|
189
208
|
public requireTypedSocket(): plugins.typedsocket.TypedSocket {
|
|
190
209
|
this.assertRunning();
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
210
|
+
const socket = this.typedsocket;
|
|
211
|
+
const status = this.getSessionStatus();
|
|
212
|
+
// A refused protocol is the one unavailability a caller can act on, so it keeps its name.
|
|
213
|
+
if (status === 'protocol-incompatible' && this.lastProtocolRefusal) throw this.lastProtocolRefusal;
|
|
214
|
+
if (!socket || status !== 'connected') {
|
|
215
|
+
throw new Error('Cloudly platform session is unavailable.');
|
|
216
|
+
}
|
|
217
|
+
return socket;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The platform session as a caller can act on it.
|
|
222
|
+
*
|
|
223
|
+
* `protocol-incompatible` outranks the transport state: it stands until an operator upgrades
|
|
224
|
+
* one of the two sides, and `lastProtocolRefusal` names both of them.
|
|
225
|
+
*/
|
|
226
|
+
public getSessionStatus(): TSzPlatformSessionStatus {
|
|
227
|
+
if (this.lastProtocolRefusal) return 'protocol-incompatible';
|
|
228
|
+
if (this.typedsocket?.getStatus() === 'connected' && this.identity
|
|
229
|
+
&& this.identity.expiresAt > Date.now()) return 'connected';
|
|
230
|
+
return 'disconnected';
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Release the socket lifecycle a restoration was refused in; every other failure passes on.
|
|
235
|
+
*
|
|
236
|
+
* TypedSocket ends its own client on a denied restoration and never reconnects from one, so the
|
|
237
|
+
* reference held here is dead — keeping it would report an unavailable session instead of the
|
|
238
|
+
* incompatible peer.
|
|
239
|
+
*/
|
|
240
|
+
private releaseRefusedSocket(errorArg: unknown, generationArg: number): never {
|
|
241
|
+
if (errorArg instanceof SzPlatformProtocolIncompatibleError
|
|
242
|
+
&& generationArg === this.authenticationGeneration) {
|
|
243
|
+
this.typedsocket = undefined;
|
|
244
|
+
}
|
|
245
|
+
throw errorArg;
|
|
194
246
|
}
|
|
195
247
|
|
|
196
248
|
private invalidateAuthentication(): void {
|
|
@@ -227,19 +279,28 @@ export class SzPlatformClient {
|
|
|
227
279
|
|| !Number.isSafeInteger(identity.expiresAt) || identity.expiresAt <= Date.now() + 1000) {
|
|
228
280
|
throw new Error('Invalid platform identity.');
|
|
229
281
|
}
|
|
230
|
-
const requestData = plugins.servezoneInterfaces.data.
|
|
231
|
-
|
|
282
|
+
const requestData = plugins.servezoneInterfaces.data.snapshotRegisterCloudlyClientSessionRequest({
|
|
283
|
+
identity: { jwt: identity.jwt }, protocol: platformSessionProtocolOffer,
|
|
232
284
|
});
|
|
233
|
-
const registration = createRequest<plugins.servezoneInterfaces.requests.runtimesession.
|
|
234
|
-
'
|
|
285
|
+
const registration = createRequest<plugins.servezoneInterfaces.requests.runtimesession.IReq_Any_Cloudly_RegisterCloudlyClientSession>(
|
|
286
|
+
'registerCloudlyClientSession');
|
|
235
287
|
registration.skipHooks = true;
|
|
236
|
-
const registered = await registration
|
|
237
|
-
|
|
288
|
+
const registered = await registration
|
|
289
|
+
.fire(requestData, { maxRetries: 0, abortSignal: signal })
|
|
290
|
+
.catch(rethrowProtocolRefusal);
|
|
291
|
+
requireCompatibleProtocol(plugins.servezoneInterfaces.data
|
|
292
|
+
.snapshotRegisterCloudlyClientSessionResponse(registered).protocol);
|
|
238
293
|
requireCurrent();
|
|
239
294
|
this.identity = { type: identity.type, role: identity.role, userId: identity.userId,
|
|
240
295
|
name: identity.userId, expiresAt: identity.expiresAt, jwt: requestData.identity.jwt };
|
|
241
|
-
} catch {
|
|
296
|
+
} catch (error) {
|
|
242
297
|
if (this.stopped || signal.aborted || generation !== this.authenticationGeneration) throw this.createAbortError();
|
|
298
|
+
// A refused offer rejected no credential of this caller's, so it is named rather than
|
|
299
|
+
// collapsed, and kept where a restoration that has no caller can still be read.
|
|
300
|
+
if (error instanceof SzPlatformProtocolIncompatibleError) {
|
|
301
|
+
this.lastProtocolRefusal = error;
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
243
304
|
throw new Error('Cloudly platform authentication failed.');
|
|
244
305
|
}
|
|
245
306
|
}
|
package/ts/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export * from './classes.platformclient.js';
|
|
2
|
+
export {
|
|
3
|
+
platformSessionProtocolOffer,
|
|
4
|
+
SzPlatformProtocolIncompatibleError,
|
|
5
|
+
} from './protocol.js';
|
|
2
6
|
export * from './coremail/classes.coremailconnector.js';
|
|
3
7
|
export * from './email/classes.emailconnector.js';
|
|
4
8
|
export * from './webpush/classes.webpushconnector.js';
|
package/ts/protocol.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
|
|
3
|
+
const protocol = plugins.servezoneInterfaces.protocol;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The oldest Cloudly release this client opens its platform session with.
|
|
7
|
+
*
|
|
8
|
+
* It is raised only by the commit that starts depending on a later `@serve.zone/interfaces`
|
|
9
|
+
* minor, and that raise is named in the changelog: a client that demands more than it needs
|
|
10
|
+
* refuses controllers it could have served. What this client speaks is never stated here — it is
|
|
11
|
+
* the installed release, which `createProtocolOffer` reads from the package itself.
|
|
12
|
+
*/
|
|
13
|
+
const platformSessionMinimumPeerVersion = '32.0.0';
|
|
14
|
+
|
|
15
|
+
/** This build's offer for the one session kind the platform client opens. */
|
|
16
|
+
export const platformSessionProtocolOffer: plugins.servezoneInterfaces.protocol.IProtocolOffer =
|
|
17
|
+
protocol.createProtocolOffer(platformSessionMinimumPeerVersion);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Two peers that cannot serve one session, named rather than collapsed into an authentication
|
|
21
|
+
* failure.
|
|
22
|
+
*
|
|
23
|
+
* A refusal stands until an operator upgrades one of the two sides, so it is never retried: the
|
|
24
|
+
* caller is rejected with it, and a refusal met while a reconnect restores the session — where no
|
|
25
|
+
* caller waits — ends that socket lifecycle and is retained on the client instead.
|
|
26
|
+
*/
|
|
27
|
+
export class SzPlatformProtocolIncompatibleError extends Error {
|
|
28
|
+
public readonly refusal: plugins.servezoneInterfaces.protocol.IProtocolRefusal;
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
refusalArg: plugins.servezoneInterfaces.protocol.IProtocolRefusal,
|
|
32
|
+
optionsArg?: ErrorOptions,
|
|
33
|
+
) {
|
|
34
|
+
super(protocol.describeProtocolRefusal(refusalArg), optionsArg);
|
|
35
|
+
this.name = 'SzPlatformProtocolIncompatibleError';
|
|
36
|
+
this.refusal = refusalArg;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The payload a failed TypedRequest hop carried.
|
|
42
|
+
*
|
|
43
|
+
* Read structurally rather than through `instanceof TypedResponseError`: the request that fails is
|
|
44
|
+
* created by TypedSocket, which resolves its own `@api.global/typedrequest`, so a class identity
|
|
45
|
+
* check could miss a refusal in a consumer tree that holds a second copy.
|
|
46
|
+
*/
|
|
47
|
+
const readErrorData = (errorArg: unknown): unknown => {
|
|
48
|
+
if (typeof errorArg !== 'object' || errorArg === null || !('errorData' in errorArg)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return errorArg.errorData;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Rethrow a refused offer as this client's named error; every other failure passes untouched.
|
|
56
|
+
*
|
|
57
|
+
* The transport error stays attached as the cause, so the correlation a caller needs to find the
|
|
58
|
+
* hop in a log is not lost behind the refusal.
|
|
59
|
+
*/
|
|
60
|
+
export const rethrowProtocolRefusal = (errorArg: unknown): never => {
|
|
61
|
+
const refusal = protocol.readProtocolRefusal(readErrorData(errorArg));
|
|
62
|
+
if (refusal === null) {
|
|
63
|
+
throw errorArg;
|
|
64
|
+
}
|
|
65
|
+
throw new SzPlatformProtocolIncompatibleError(refusal, { cause: errorArg });
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The controller's own offer, judged from this client's side.
|
|
70
|
+
*
|
|
71
|
+
* Acceptance is the controller's decision about this client; whether this client can serve the
|
|
72
|
+
* session it was just given is this check, and a client that cannot must not use it.
|
|
73
|
+
*/
|
|
74
|
+
export const requireCompatibleProtocol = (
|
|
75
|
+
peerOfferArg: plugins.servezoneInterfaces.protocol.IProtocolOffer,
|
|
76
|
+
): void => {
|
|
77
|
+
const negotiation = protocol.negotiateProtocol(platformSessionProtocolOffer, peerOfferArg);
|
|
78
|
+
if (!negotiation.compatible) {
|
|
79
|
+
throw new SzPlatformProtocolIncompatibleError(negotiation.refusal);
|
|
80
|
+
}
|
|
81
|
+
};
|