@source-repo/rpc 3.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/LICENSE +21 -0
- package/README.md +1208 -0
- package/dist/Logging/ILogger.d.ts +7 -0
- package/dist/Logging/ILogger.d.ts.map +1 -0
- package/dist/Logging/ILogger.js +2 -0
- package/dist/Logging/ILogger.js.map +1 -0
- package/dist/NodeRpcServer.d.ts +55 -0
- package/dist/NodeRpcServer.d.ts.map +1 -0
- package/dist/NodeRpcServer.js +46 -0
- package/dist/NodeRpcServer.js.map +1 -0
- package/dist/RPC/Auth.d.ts +98 -0
- package/dist/RPC/Auth.d.ts.map +1 -0
- package/dist/RPC/Auth.js +14 -0
- package/dist/RPC/Auth.js.map +1 -0
- package/dist/RPC/Codec.d.ts +24 -0
- package/dist/RPC/Codec.d.ts.map +1 -0
- package/dist/RPC/Codec.js +21 -0
- package/dist/RPC/Codec.js.map +1 -0
- package/dist/RPC/Compatibility.d.ts +39 -0
- package/dist/RPC/Compatibility.d.ts.map +1 -0
- package/dist/RPC/Compatibility.js +195 -0
- package/dist/RPC/Compatibility.js.map +1 -0
- package/dist/RPC/Core.d.ts +188 -0
- package/dist/RPC/Core.d.ts.map +1 -0
- package/dist/RPC/Core.js +354 -0
- package/dist/RPC/Core.js.map +1 -0
- package/dist/RPC/Expose.d.ts +90 -0
- package/dist/RPC/Expose.d.ts.map +1 -0
- package/dist/RPC/Expose.js +110 -0
- package/dist/RPC/Expose.js.map +1 -0
- package/dist/RPC/Idempotency.d.ts +90 -0
- package/dist/RPC/Idempotency.d.ts.map +1 -0
- package/dist/RPC/Idempotency.js +46 -0
- package/dist/RPC/Idempotency.js.map +1 -0
- package/dist/RPC/Introspection.d.ts +92 -0
- package/dist/RPC/Introspection.d.ts.map +1 -0
- package/dist/RPC/Introspection.js +188 -0
- package/dist/RPC/Introspection.js.map +1 -0
- package/dist/RPC/Introspection.types.json +1093 -0
- package/dist/RPC/Messages.d.ts +108 -0
- package/dist/RPC/Messages.d.ts.map +1 -0
- package/dist/RPC/Messages.js +30 -0
- package/dist/RPC/Messages.js.map +1 -0
- package/dist/RPC/Rpc.d.ts +51 -0
- package/dist/RPC/Rpc.d.ts.map +1 -0
- package/dist/RPC/Rpc.js +54 -0
- package/dist/RPC/Rpc.js.map +1 -0
- package/dist/RPC/RpcClientHandler.d.ts +129 -0
- package/dist/RPC/RpcClientHandler.d.ts.map +1 -0
- package/dist/RPC/RpcClientHandler.js +267 -0
- package/dist/RPC/RpcClientHandler.js.map +1 -0
- package/dist/RPC/RpcServerHandler.d.ts +226 -0
- package/dist/RPC/RpcServerHandler.d.ts.map +1 -0
- package/dist/RPC/RpcServerHandler.js +676 -0
- package/dist/RPC/RpcServerHandler.js.map +1 -0
- package/dist/RPC/Schema.d.ts +150 -0
- package/dist/RPC/Schema.d.ts.map +1 -0
- package/dist/RPC/Schema.js +198 -0
- package/dist/RPC/Schema.js.map +1 -0
- package/dist/RPC/Signing.d.ts +118 -0
- package/dist/RPC/Signing.d.ts.map +1 -0
- package/dist/RPC/Signing.js +171 -0
- package/dist/RPC/Signing.js.map +1 -0
- package/dist/RPC/Tokens.d.ts +49 -0
- package/dist/RPC/Tokens.d.ts.map +1 -0
- package/dist/RPC/Tokens.js +45 -0
- package/dist/RPC/Tokens.js.map +1 -0
- package/dist/RpcClient.d.ts +91 -0
- package/dist/RpcClient.d.ts.map +1 -0
- package/dist/RpcClient.js +145 -0
- package/dist/RpcClient.js.map +1 -0
- package/dist/RpcServer.d.ts +191 -0
- package/dist/RpcServer.d.ts.map +1 -0
- package/dist/RpcServer.js +293 -0
- package/dist/RpcServer.js.map +1 -0
- package/dist/Transports/Mqtt5Frame.d.ts +107 -0
- package/dist/Transports/Mqtt5Frame.d.ts.map +1 -0
- package/dist/Transports/Mqtt5Frame.js +162 -0
- package/dist/Transports/Mqtt5Frame.js.map +1 -0
- package/dist/Transports/MqttTransport.d.ts +279 -0
- package/dist/Transports/MqttTransport.d.ts.map +1 -0
- package/dist/Transports/MqttTransport.js +843 -0
- package/dist/Transports/MqttTransport.js.map +1 -0
- package/dist/Transports/Presence.d.ts +68 -0
- package/dist/Transports/Presence.d.ts.map +1 -0
- package/dist/Transports/Presence.js +21 -0
- package/dist/Transports/Presence.js.map +1 -0
- package/dist/Transports/SocketIoClientTransport.d.ts +89 -0
- package/dist/Transports/SocketIoClientTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoClientTransport.js +280 -0
- package/dist/Transports/SocketIoClientTransport.js.map +1 -0
- package/dist/Transports/SocketIoServerTransport.d.ts +135 -0
- package/dist/Transports/SocketIoServerTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoServerTransport.js +505 -0
- package/dist/Transports/SocketIoServerTransport.js.map +1 -0
- package/dist/Utilities/Converters.d.ts +22 -0
- package/dist/Utilities/Converters.d.ts.map +1 -0
- package/dist/Utilities/Converters.js +58 -0
- package/dist/Utilities/Converters.js.map +1 -0
- package/dist/Utilities/Filter.d.ts +7 -0
- package/dist/Utilities/Filter.d.ts.map +1 -0
- package/dist/Utilities/Filter.js +14 -0
- package/dist/Utilities/Filter.js.map +1 -0
- package/dist/Utilities/ReadableName.d.ts +38 -0
- package/dist/Utilities/ReadableName.d.ts.map +1 -0
- package/dist/Utilities/ReadableName.js +58 -0
- package/dist/Utilities/ReadableName.js.map +1 -0
- package/dist/Utilities/Switch.d.ts +21 -0
- package/dist/Utilities/Switch.d.ts.map +1 -0
- package/dist/Utilities/Switch.js +70 -0
- package/dist/Utilities/Switch.js.map +1 -0
- package/dist/Utilities/TryCatch.d.ts +11 -0
- package/dist/Utilities/TryCatch.d.ts.map +1 -0
- package/dist/Utilities/TryCatch.js +13 -0
- package/dist/Utilities/TryCatch.js.map +1 -0
- package/dist/index-web.d.ts +25 -0
- package/dist/index-web.d.ts.map +1 -0
- package/dist/index-web.js +28 -0
- package/dist/index-web.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { MessageModule, MessageType } from './Core.js';
|
|
2
|
+
import { isEventFunction } from './Rpc.js';
|
|
3
|
+
import { RpcMessageType } from './RpcServerHandler.js';
|
|
4
|
+
import { EventEmitter } from 'events';
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
|
+
export const defaultCallTimeout = 10000;
|
|
7
|
+
/**
|
|
8
|
+
* Identifies one subscription: which peer, which exposed instance, which event.
|
|
9
|
+
*
|
|
10
|
+
* Handlers used to be registered under the bare event name, so a client watching `alarm` on two
|
|
11
|
+
* namespaces - or on two peers over one MQTT transport - delivered each event to all of them. An
|
|
12
|
+
* empty source matches any peer, for a proxy created without a target.
|
|
13
|
+
*/
|
|
14
|
+
export const subscriptionKey = (source, namespace, event) => `${source}\u0000${namespace}\u0000${event}`;
|
|
15
|
+
export class RpcError extends Error {
|
|
16
|
+
code;
|
|
17
|
+
remoteStack;
|
|
18
|
+
constructor(code, message,
|
|
19
|
+
/** Stack trace from the remote peer, when it sent one. */
|
|
20
|
+
remoteStack) {
|
|
21
|
+
super(message ? `${code}: ${message}` : code);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.remoteStack = remoteStack;
|
|
24
|
+
this.name = 'RpcError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function isSuccessResponse(payload) {
|
|
28
|
+
return payload.type === RpcMessageType.success;
|
|
29
|
+
}
|
|
30
|
+
function isEventMessage(payload) {
|
|
31
|
+
return payload.type === RpcMessageType.event;
|
|
32
|
+
}
|
|
33
|
+
function isErrorResponse(payload) {
|
|
34
|
+
return payload.type === RpcMessageType.error;
|
|
35
|
+
}
|
|
36
|
+
export class RpcClientHandler extends MessageModule {
|
|
37
|
+
callTimeout;
|
|
38
|
+
responsePromiseMap = new Map();
|
|
39
|
+
responseTimeoutMap = new Map();
|
|
40
|
+
/** Contract versions this client was built against, by namespace, declared on each call. */
|
|
41
|
+
schemaVersions;
|
|
42
|
+
/** Remote subscriptions held by this client, replayed by resubscribe() after a reconnect. */
|
|
43
|
+
subscriptions = new Map();
|
|
44
|
+
eventEmitter = new EventEmitter();
|
|
45
|
+
constructor(name, sources, callTimeout = defaultCallTimeout) {
|
|
46
|
+
super(name, sources);
|
|
47
|
+
this.callTimeout = callTimeout;
|
|
48
|
+
}
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
50
|
+
async receive(message, source, target) {
|
|
51
|
+
const payload = message.payload;
|
|
52
|
+
if (!payload)
|
|
53
|
+
return;
|
|
54
|
+
if (isEventMessage(payload)) {
|
|
55
|
+
this.deliverEvent(payload, source);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (isSuccessResponse(payload)) {
|
|
59
|
+
this.takePending(payload.id)?.resolve(payload.result);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (isErrorResponse(payload)) {
|
|
63
|
+
// Requires payload.id. A peer older than this fix sends errors without one, in which
|
|
64
|
+
// case the call can only be settled by its timeout.
|
|
65
|
+
this.takePending(payload.id)?.reject(new RpcError(payload.code, payload.error?.message, payload.error?.stack));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Routes an event to the handlers registered for that peer and that instance, rather than to
|
|
70
|
+
* everything listening for the name.
|
|
71
|
+
*/
|
|
72
|
+
deliverEvent(payload, source) {
|
|
73
|
+
// Held in a local so the narrowing survives into the delivery callbacks below.
|
|
74
|
+
const emitter = this.eventEmitter;
|
|
75
|
+
if (emitter instanceof EventEmitter) {
|
|
76
|
+
const from = source ?? '';
|
|
77
|
+
const keys = payload.path
|
|
78
|
+
? [subscriptionKey(from, payload.path, payload.event), subscriptionKey('', payload.path, payload.event)]
|
|
79
|
+
: // A peer that does not name the emitting instance: deliver to every subscription
|
|
80
|
+
// for this event whose peer matches, whatever namespace it was taken out on.
|
|
81
|
+
emitter
|
|
82
|
+
.eventNames()
|
|
83
|
+
.filter((name) => typeof name === 'string')
|
|
84
|
+
.filter((name) => {
|
|
85
|
+
const [keySource, , keyEvent] = name.split('\u0000');
|
|
86
|
+
return keyEvent === payload.event && (keySource === from || keySource === '');
|
|
87
|
+
});
|
|
88
|
+
for (const key of new Set(keys))
|
|
89
|
+
this.deliverSafely(() => emitter.emit(key, ...payload.params), payload);
|
|
90
|
+
}
|
|
91
|
+
// The handler's own emitter stays keyed by name: it is a firehose of everything this client
|
|
92
|
+
// receives, and its consumers read the path off the payload.
|
|
93
|
+
this.deliverSafely(() => this.emit(payload.event, payload.params), payload);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Run one subscriber without letting it unwind into the transport that delivered the event.
|
|
97
|
+
*
|
|
98
|
+
* These are application callbacks reached from a transport's inbound loop, so a handler that
|
|
99
|
+
* threw propagated all the way back out and became an unhandled rejection - one subscriber's
|
|
100
|
+
* bug ending the process for everything else the client was doing.
|
|
101
|
+
*/
|
|
102
|
+
deliverSafely(deliver, payload) {
|
|
103
|
+
try {
|
|
104
|
+
deliver();
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
this.emit('subscriberError', { event: payload.event, path: payload.path, error: e });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Re-issue every remote subscription this client holds. Called after the transport reconnects:
|
|
112
|
+
* if the server kept its state the calls are no-ops on its side, and if the server restarted
|
|
113
|
+
* they rebuild it. Either way the outgoing frames re-identify this client to the server, which
|
|
114
|
+
* is what makes server-pushed events addressable again.
|
|
115
|
+
*/
|
|
116
|
+
async resubscribe() {
|
|
117
|
+
const results = await Promise.allSettled([...this.subscriptions.values()].map((subscription) => this.call(subscription.remote, subscription.instanceName, 'on', subscription.event)));
|
|
118
|
+
const failed = results.filter((result) => result.status === 'rejected').length;
|
|
119
|
+
if (failed)
|
|
120
|
+
this.emit('resubscribeFailed', failed);
|
|
121
|
+
return results.length - failed;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Reject every in-flight call. A reply to a call that was in flight when the link dropped can
|
|
125
|
+
* no longer reach us, so failing now beats making every caller wait out the full timeout.
|
|
126
|
+
*
|
|
127
|
+
* How it failed depends on whether the request got out. One that never left cannot have run, and
|
|
128
|
+
* `TransportError` says so; one that was published and never answered may have run, and only
|
|
129
|
+
* `UnknownOutcome` is true of it. Reporting both the same way was the library telling callers
|
|
130
|
+
* that a command had failed when what it knew was that it had lost track of it.
|
|
131
|
+
*/
|
|
132
|
+
failPendingCalls(reason) {
|
|
133
|
+
for (const id of [...this.responsePromiseMap.keys()]) {
|
|
134
|
+
const sent = this.sentRequests.has(id);
|
|
135
|
+
this.sentRequests.delete(id);
|
|
136
|
+
this.takePending(id)?.reject(sent
|
|
137
|
+
? new RpcError('UnknownOutcome', `${reason}, after the request was sent - it may or may not have run`)
|
|
138
|
+
: new RpcError('TransportError', `${reason}, before the request was sent`));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Requests this client handed to a transport without it complaining.
|
|
143
|
+
*
|
|
144
|
+
* Not proof of delivery - nothing here can have that - but proof that the frame left, which is
|
|
145
|
+
* the line between a command that certainly did not run and one that might have.
|
|
146
|
+
*/
|
|
147
|
+
sentRequests = new Set();
|
|
148
|
+
/** Detach a pending call and cancel its timeout. Returns undefined if it already settled. */
|
|
149
|
+
takePending(id) {
|
|
150
|
+
if (id === undefined)
|
|
151
|
+
return undefined;
|
|
152
|
+
const promise = this.responsePromiseMap.get(id);
|
|
153
|
+
this.responsePromiseMap.delete(id);
|
|
154
|
+
this.sentRequests.delete(id);
|
|
155
|
+
const timeout = this.responseTimeoutMap.get(id);
|
|
156
|
+
if (timeout !== undefined) {
|
|
157
|
+
clearTimeout(timeout);
|
|
158
|
+
this.responseTimeoutMap.delete(id);
|
|
159
|
+
}
|
|
160
|
+
return promise;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Call a method on the RPC server.
|
|
164
|
+
* @param method The method to call.
|
|
165
|
+
* @param additionalParameter The (optional) additionalParameter to include. See the JsonRpc class for more details.
|
|
166
|
+
* @param params
|
|
167
|
+
*/
|
|
168
|
+
call(remote, instanceName, method, ...params) {
|
|
169
|
+
return this.callWith({}, remote, instanceName, method, ...params);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Call with per-call options. `call` is this with none.
|
|
173
|
+
*
|
|
174
|
+
* The only option so far is the idempotency key, which is the one thing a caller can say that
|
|
175
|
+
* the library cannot work out for itself: whether this is a new command or another go at one it
|
|
176
|
+
* has already sent.
|
|
177
|
+
*/
|
|
178
|
+
callWith(options, remote, instanceName, method, ...params) {
|
|
179
|
+
const payload = {
|
|
180
|
+
id: uuidv4(),
|
|
181
|
+
type: RpcMessageType.CallInstanceMethod,
|
|
182
|
+
path: instanceName,
|
|
183
|
+
method,
|
|
184
|
+
params,
|
|
185
|
+
version: this.schemaVersions?.[instanceName],
|
|
186
|
+
// The same number that arms the timer below, so what the far end is told is exactly
|
|
187
|
+
// what this caller is going to do. A request carrying no ttl is one with no deadline,
|
|
188
|
+
// which is what a caller that has disabled its own timeout is asking for.
|
|
189
|
+
ttl: this.callTimeout > 0 ? this.callTimeout : undefined,
|
|
190
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {})
|
|
191
|
+
};
|
|
192
|
+
return new Promise((resolve, reject) => {
|
|
193
|
+
// Registered before sending: a response can arrive before sendPayload's promise settles.
|
|
194
|
+
this.responsePromiseMap.set(payload.id, { resolve, reject });
|
|
195
|
+
this.responseTimeoutMap.set(payload.id, setTimeout(() => {
|
|
196
|
+
// A timeout is an unknown outcome by definition: the request went out, and
|
|
197
|
+
// nothing came back. Kept as Timeout because that names *why* nothing is known,
|
|
198
|
+
// which is more use than the general case - but a caller reading it should treat
|
|
199
|
+
// a command as possibly done. There is a note about this in the README.
|
|
200
|
+
this.takePending(payload.id)?.reject(new RpcError('Timeout', `no response to ${instanceName}.${method} within ${this.callTimeout} ms`));
|
|
201
|
+
}, this.callTimeout));
|
|
202
|
+
this.sendPayload(payload, MessageType.RequestMessage, this.name, remote).then(() => {
|
|
203
|
+
// Recorded only once the transport has accepted it, and only while the call is
|
|
204
|
+
// still pending - a reply may well have arrived and settled it already.
|
|
205
|
+
if (this.responsePromiseMap.has(payload.id))
|
|
206
|
+
this.sentRequests.add(payload.id);
|
|
207
|
+
}, (e) => {
|
|
208
|
+
// It never left, so whatever it would have done, it did not.
|
|
209
|
+
this.takePending(payload.id)?.reject(new RpcError('TransportError', e instanceof Error ? e.message : String(e)));
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Create a proxy object - a sort of wrapper for calling methods and listening for events.
|
|
215
|
+
* @param name Name of an existing instance on the server instance. If in the form "name: Class" an instance of type Class will be created
|
|
216
|
+
* on the server if it does not already exist.
|
|
217
|
+
*/
|
|
218
|
+
proxy(name, remote, options = {}) {
|
|
219
|
+
const proxyObj = {};
|
|
220
|
+
return new Proxy(proxyObj, {
|
|
221
|
+
get: (target, prop) => {
|
|
222
|
+
let result;
|
|
223
|
+
if (typeof prop === 'string') {
|
|
224
|
+
if (target[prop]) {
|
|
225
|
+
return target[prop];
|
|
226
|
+
}
|
|
227
|
+
else if (prop === '$with') {
|
|
228
|
+
// The one name on a proxy that is not a remote method: it returns another
|
|
229
|
+
// proxy for the same instance whose calls carry these options. Prefixed with
|
|
230
|
+
// `$` because everything else here is whatever the far end happens to expose,
|
|
231
|
+
// and a collision would silently shadow a real method.
|
|
232
|
+
target[prop] = (callOptions) => this.proxy(name, remote, { ...options, ...callOptions });
|
|
233
|
+
}
|
|
234
|
+
else if (isEventFunction(prop)) {
|
|
235
|
+
target[prop] = (...args) => {
|
|
236
|
+
const event = args[0];
|
|
237
|
+
if (typeof event === 'string') {
|
|
238
|
+
// Registered against this peer and this namespace, so a name shared
|
|
239
|
+
// with another instance does not deliver to both.
|
|
240
|
+
const key = subscriptionKey(remote ?? '', name, event);
|
|
241
|
+
this.eventEmitter[prop](key, ...args.slice(1));
|
|
242
|
+
// 'on' is the only form the server holds state for, so it is the
|
|
243
|
+
// only one worth replaying after a reconnect.
|
|
244
|
+
if (prop === 'on')
|
|
245
|
+
this.subscriptions.set(key, { remote, instanceName: name, event });
|
|
246
|
+
else if (prop === 'off' || prop === 'removeListener')
|
|
247
|
+
this.subscriptions.delete(key);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// removeAllListeners, setMaxListeners and friends take no event.
|
|
251
|
+
;
|
|
252
|
+
this.eventEmitter[prop](...args);
|
|
253
|
+
}
|
|
254
|
+
return this.call(remote, name, prop, args[0]);
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
target[prop] = (...args) => this.callWith(options, remote, name, prop, ...args);
|
|
259
|
+
}
|
|
260
|
+
result = target[prop];
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=RpcClientHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RpcClientHandler.js","sourceRoot":"","sources":["../../src/RPC/RpcClientHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { MessageModule, Message, GenericModule } from './Core.js';
|
|
2
|
+
import { RpcMessage, RpcMethodSemantics } from './Messages.js';
|
|
3
|
+
export * from './Messages.js';
|
|
4
|
+
import { IManageRpc } from './Rpc.js';
|
|
5
|
+
import { RpcAuthorizer, RpcIdentity } from './Auth.js';
|
|
6
|
+
import { type RpcIdempotencyStore } from './Idempotency.js';
|
|
7
|
+
import EventEmitter from 'events';
|
|
8
|
+
import { ILogger } from '../Logging/ILogger.js';
|
|
9
|
+
import { type RpcExecution } from './Expose.js';
|
|
10
|
+
import { RpcSchema } from './Schema.js';
|
|
11
|
+
export declare class EventProxy {
|
|
12
|
+
rpcServer: RpcServerHandler;
|
|
13
|
+
instance: EventEmitter;
|
|
14
|
+
event: string;
|
|
15
|
+
target: string;
|
|
16
|
+
instanceName: string;
|
|
17
|
+
/**
|
|
18
|
+
* Held so the listener can be removed again. Binding at registration time produced a fresh
|
|
19
|
+
* function that removeListener() could never match.
|
|
20
|
+
*/
|
|
21
|
+
private readonly listener;
|
|
22
|
+
constructor(rpcServer: RpcServerHandler, instance: EventEmitter, event: string, target: string, instanceName: string);
|
|
23
|
+
attach(): void;
|
|
24
|
+
detach(): void;
|
|
25
|
+
}
|
|
26
|
+
export type BindObject = {
|
|
27
|
+
[index: string]: (...args: unknown[]) => unknown;
|
|
28
|
+
};
|
|
29
|
+
export type ObjectByString = {
|
|
30
|
+
[index: string]: unknown;
|
|
31
|
+
};
|
|
32
|
+
/** How one instance is exposed, beyond the name it answers to. */
|
|
33
|
+
export interface ExposeOptions {
|
|
34
|
+
/**
|
|
35
|
+
* How far up the prototype chain to publish methods from. The old third argument, which was
|
|
36
|
+
* this number on its own; a number is still accepted so existing calls keep working.
|
|
37
|
+
*/
|
|
38
|
+
prototypeSteps?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Whether calls into this instance may overlap. Overrides what the class declares, since the
|
|
41
|
+
* call site knows how this particular instance is used.
|
|
42
|
+
*/
|
|
43
|
+
execution?: RpcExecution;
|
|
44
|
+
}
|
|
45
|
+
export declare class RpcServerHandler extends MessageModule<Message<RpcMessage>, RpcMessage, Message<RpcMessage>, RpcMessage> {
|
|
46
|
+
manageRpc: ManageRpc;
|
|
47
|
+
eventProxies: Map<string, EventProxy>;
|
|
48
|
+
/** Decides whether a call may proceed. When unset, every call that resolves is allowed. */
|
|
49
|
+
authorize?: RpcAuthorizer;
|
|
50
|
+
/** Supplied by RpcServer; asks the transports which identity a peer name is bound to. */
|
|
51
|
+
resolveIdentity?: (source: string) => RpcIdentity | undefined;
|
|
52
|
+
/** Reject calls from peers no transport can vouch for. */
|
|
53
|
+
requireIdentity: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Suppress duplicate requests. MQTT at QoS 1 is at-least-once, so the same request can be
|
|
56
|
+
* delivered twice; without this a retransmission would run the method a second time, which is
|
|
57
|
+
* not something a caller can undo. A duplicate is answered from the cache instead.
|
|
58
|
+
*/
|
|
59
|
+
deduplicateRequests: boolean;
|
|
60
|
+
/** How many recent request ids to remember. Oldest are evicted first. */
|
|
61
|
+
maxTrackedRequests: number;
|
|
62
|
+
/**
|
|
63
|
+
* Refuse a call whose caller has already stopped waiting for it, instead of running it late.
|
|
64
|
+
*
|
|
65
|
+
* A request carries the milliseconds its caller intended to wait, and that budget is counted
|
|
66
|
+
* from the moment this process received the frame. A read arriving late only wastes work; a
|
|
67
|
+
* command does not - the operator saw a timeout, did something else about it, and then the
|
|
68
|
+
* original 'start pump' runs anyway. On by default, because that outcome is worse than the
|
|
69
|
+
* failed call it replaces.
|
|
70
|
+
*/
|
|
71
|
+
refuseExpiredCalls: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Where to record what a non-repeatable command did, so a redelivery after a crash is answered
|
|
74
|
+
* rather than executed a second time. Unset means execution is at least once - see
|
|
75
|
+
* RPC/Idempotency.ts, which spells out exactly what that leaves open.
|
|
76
|
+
*/
|
|
77
|
+
idempotency?: RpcIdempotencyStore;
|
|
78
|
+
/** Describes what exposed methods accept. Absent means nothing is checked. */
|
|
79
|
+
schema?: RpcSchema;
|
|
80
|
+
/**
|
|
81
|
+
* 'described' checks calls into namespaces the schema covers and lets the rest through, so a
|
|
82
|
+
* partial schema is useful. 'required' refuses anything the schema does not describe.
|
|
83
|
+
*/
|
|
84
|
+
validation: 'off' | 'described' | 'required';
|
|
85
|
+
/** Check what handlers return as well as what callers send. Off by default: it is a self-check. */
|
|
86
|
+
validateResults: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* What to do with a caller declaring a contract version this schema has no history for.
|
|
89
|
+
* 'allow' by default, because truncating history is a legitimate operational choice and should
|
|
90
|
+
* not strand peers.
|
|
91
|
+
*/
|
|
92
|
+
unknownVersion: 'allow' | 'reject';
|
|
93
|
+
/** Verdicts by namespace and declared version, so the comparison runs once per peer, not per call. */
|
|
94
|
+
private compatibility;
|
|
95
|
+
private recentResponses;
|
|
96
|
+
private inFlightRequests;
|
|
97
|
+
constructor(name: string, sources?: GenericModule<unknown, unknown, Message, RpcMessage>[]);
|
|
98
|
+
/**
|
|
99
|
+
* Gate a call before it reaches an exposed method. Returns an error code to reject with, or
|
|
100
|
+
* undefined to allow. Subscriptions go through here too: without that, anyone could attach to
|
|
101
|
+
* an instance's events and receive everything it emits.
|
|
102
|
+
*/
|
|
103
|
+
private checkAccess;
|
|
104
|
+
/**
|
|
105
|
+
* Returns a reason to refuse the call, or undefined. The namespace's contract version rides
|
|
106
|
+
* along in the message, because a caller built against an older contract otherwise looks
|
|
107
|
+
* indistinguishable from one sending plain rubbish.
|
|
108
|
+
*/
|
|
109
|
+
private checkParams;
|
|
110
|
+
/**
|
|
111
|
+
* Compares the contract a caller declares with the one served here. Only a genuine structural
|
|
112
|
+
* incompatibility is refused: a caller whose contract still holds keeps working, which is why
|
|
113
|
+
* this compares schemas rather than gating on a version or a hash being equal.
|
|
114
|
+
*/
|
|
115
|
+
private checkVersion;
|
|
116
|
+
receive(message: Message<RpcMessage>, source: string, target: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Send a response and remember it against its request id, so a redelivered request can be
|
|
119
|
+
* answered without running the method again.
|
|
120
|
+
*/
|
|
121
|
+
private respond;
|
|
122
|
+
receivePayload(payload: RpcMessage, source: string, target: string): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Last resort when dispatch itself failed. Answers the caller if the request can still be
|
|
125
|
+
* identified, and never throws: the thing that failed may well be the transport this reply
|
|
126
|
+
* would go out on, and a failure to report a failure has nowhere left to go.
|
|
127
|
+
*/
|
|
128
|
+
private reportDispatchFailure;
|
|
129
|
+
private dispatch;
|
|
130
|
+
/**
|
|
131
|
+
* Run one call: check the budget, claim the command, invoke it, answer.
|
|
132
|
+
*
|
|
133
|
+
* Split out of dispatch because it is what a serial instance runs one at a time, and because
|
|
134
|
+
* the order of these four is the whole of the delivery semantics.
|
|
135
|
+
*/
|
|
136
|
+
private invoke;
|
|
137
|
+
/**
|
|
138
|
+
* Write down what the command did, before its answer is sent.
|
|
139
|
+
*
|
|
140
|
+
* This order is the one that matters. Recording after answering would leave a window in which
|
|
141
|
+
* the caller has the result and the store does not, so a redelivery arriving in that window
|
|
142
|
+
* runs the command again - which is the whole failure this is here to prevent. A store that
|
|
143
|
+
* cannot record it is reported and the answer still goes out: the command has already run, and
|
|
144
|
+
* withholding the result would not un-run it.
|
|
145
|
+
*/
|
|
146
|
+
private settle;
|
|
147
|
+
/** The command a call is an attempt at, or undefined when nothing here needs to know. */
|
|
148
|
+
private invocationFor;
|
|
149
|
+
/**
|
|
150
|
+
* What a method says it does to the world: the running class first, then the schema.
|
|
151
|
+
*
|
|
152
|
+
* The class wins because it is what will actually run. A schema is a description, and a server
|
|
153
|
+
* whose description has drifted from its code should act on the code.
|
|
154
|
+
*/
|
|
155
|
+
semanticsOf(payload: {
|
|
156
|
+
path: string;
|
|
157
|
+
method: string;
|
|
158
|
+
}): RpcMethodSemantics | undefined;
|
|
159
|
+
/** The queue a call belongs in, or undefined when this instance lets calls overlap. */
|
|
160
|
+
private executionKey;
|
|
161
|
+
/** One promise chain per key. Entries go away once nothing is waiting, so idle costs nothing. */
|
|
162
|
+
private executionQueues;
|
|
163
|
+
private serialise;
|
|
164
|
+
/**
|
|
165
|
+
* How long ago the caller's budget ran out, or undefined while it still has one.
|
|
166
|
+
*
|
|
167
|
+
* The budget starts when the frame arrived here, so it covers the wait in front of this method
|
|
168
|
+
* and nothing before it. What came before is the transport's to account for: MQTT 5 hands the
|
|
169
|
+
* broker the same budget as a message expiry, so a request that sat in a queue arrives already
|
|
170
|
+
* shortened, or does not arrive at all.
|
|
171
|
+
*/
|
|
172
|
+
private expiredBy;
|
|
173
|
+
/** Catches this server returning something its own contract does not allow. */
|
|
174
|
+
private checkResult;
|
|
175
|
+
private sendError;
|
|
176
|
+
/**
|
|
177
|
+
* Release every event subscription held for a peer that has gone away. Without this the
|
|
178
|
+
* exposed instance keeps the listener forever and each emit produces an undeliverable frame.
|
|
179
|
+
*/
|
|
180
|
+
removePeer(source: string): void;
|
|
181
|
+
sendEvent(target: string, event: string, params: unknown[], path?: string): Promise<void>;
|
|
182
|
+
}
|
|
183
|
+
export declare class ManageRpc implements IManageRpc {
|
|
184
|
+
logger?: ILogger | undefined;
|
|
185
|
+
exposedNameSpaceMethodMaps: {
|
|
186
|
+
[nameSpace: string]: Map<string, (...args: unknown[]) => void>;
|
|
187
|
+
};
|
|
188
|
+
exposedNameSpaceInstances: {
|
|
189
|
+
[nameSpace: string]: object;
|
|
190
|
+
};
|
|
191
|
+
exposedClasses: {
|
|
192
|
+
[className: string]: new (...args: unknown[]) => unknown;
|
|
193
|
+
};
|
|
194
|
+
createdInstances: Map<string, object>;
|
|
195
|
+
/** What each exposed namespace's methods declare about repeating them. */
|
|
196
|
+
exposedSemantics: {
|
|
197
|
+
[nameSpace: string]: Map<string, RpcMethodSemantics>;
|
|
198
|
+
};
|
|
199
|
+
/** How each exposed namespace lets its calls overlap. Absent is `parallel`. */
|
|
200
|
+
exposedExecution: {
|
|
201
|
+
[nameSpace: string]: RpcExecution;
|
|
202
|
+
};
|
|
203
|
+
constructor(logger?: ILogger | undefined);
|
|
204
|
+
/**
|
|
205
|
+
* Make the management surface callable remotely. Off unless RpcServer is constructed with
|
|
206
|
+
* exposeManagement, because it is the most dangerous thing this library can offer.
|
|
207
|
+
*
|
|
208
|
+
* Only createRpcInstance is published, and only for classes already passed to exposeClass().
|
|
209
|
+
* The previous behaviour was exposeClassInstance(this, 'manageRpc'), which published every
|
|
210
|
+
* method on this class - including exposeClassInstance and exposeObject themselves, letting
|
|
211
|
+
* any peer that could reach the transport publish arbitrary objects and instantiate arbitrary
|
|
212
|
+
* exposed classes. The logger was published the same way, so anyone could write log entries.
|
|
213
|
+
*/
|
|
214
|
+
exposeManagement(): void;
|
|
215
|
+
getNameSpaceMethodMap(name: string): Map<string, (...args: unknown[]) => void>;
|
|
216
|
+
/** Look up a namespace without creating one. Use this on paths that came off the wire. */
|
|
217
|
+
findNameSpaceMethodMap(name: string): Map<string, (...args: unknown[]) => void>;
|
|
218
|
+
/** Set by RpcServer: refuse to expose a class that marks nothing. */
|
|
219
|
+
requireExplicitExposure: boolean;
|
|
220
|
+
exposeClassInstance(instance: object, name?: string, options?: number | ExposeOptions): void;
|
|
221
|
+
exposeClass<T>(constructor: new () => T, aliasName?: string): void;
|
|
222
|
+
exposeObject(obj: object, name: string): void;
|
|
223
|
+
expose(methodName: string, method: () => void): void;
|
|
224
|
+
createRpcInstance(className: string, instanceName?: string, ...args: unknown[]): Promise<string>;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=RpcServerHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RpcServerHandler.d.ts","sourceRoot":"","sources":["../../src/RPC/RpcServerHandler.ts"],"names":[],"mappings":"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"}
|