@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.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1208 -0
  3. package/dist/Logging/ILogger.d.ts +7 -0
  4. package/dist/Logging/ILogger.d.ts.map +1 -0
  5. package/dist/Logging/ILogger.js +2 -0
  6. package/dist/Logging/ILogger.js.map +1 -0
  7. package/dist/NodeRpcServer.d.ts +55 -0
  8. package/dist/NodeRpcServer.d.ts.map +1 -0
  9. package/dist/NodeRpcServer.js +46 -0
  10. package/dist/NodeRpcServer.js.map +1 -0
  11. package/dist/RPC/Auth.d.ts +98 -0
  12. package/dist/RPC/Auth.d.ts.map +1 -0
  13. package/dist/RPC/Auth.js +14 -0
  14. package/dist/RPC/Auth.js.map +1 -0
  15. package/dist/RPC/Codec.d.ts +24 -0
  16. package/dist/RPC/Codec.d.ts.map +1 -0
  17. package/dist/RPC/Codec.js +21 -0
  18. package/dist/RPC/Codec.js.map +1 -0
  19. package/dist/RPC/Compatibility.d.ts +39 -0
  20. package/dist/RPC/Compatibility.d.ts.map +1 -0
  21. package/dist/RPC/Compatibility.js +195 -0
  22. package/dist/RPC/Compatibility.js.map +1 -0
  23. package/dist/RPC/Core.d.ts +188 -0
  24. package/dist/RPC/Core.d.ts.map +1 -0
  25. package/dist/RPC/Core.js +354 -0
  26. package/dist/RPC/Core.js.map +1 -0
  27. package/dist/RPC/Expose.d.ts +90 -0
  28. package/dist/RPC/Expose.d.ts.map +1 -0
  29. package/dist/RPC/Expose.js +110 -0
  30. package/dist/RPC/Expose.js.map +1 -0
  31. package/dist/RPC/Idempotency.d.ts +90 -0
  32. package/dist/RPC/Idempotency.d.ts.map +1 -0
  33. package/dist/RPC/Idempotency.js +46 -0
  34. package/dist/RPC/Idempotency.js.map +1 -0
  35. package/dist/RPC/Introspection.d.ts +92 -0
  36. package/dist/RPC/Introspection.d.ts.map +1 -0
  37. package/dist/RPC/Introspection.js +188 -0
  38. package/dist/RPC/Introspection.js.map +1 -0
  39. package/dist/RPC/Introspection.types.json +1093 -0
  40. package/dist/RPC/Messages.d.ts +108 -0
  41. package/dist/RPC/Messages.d.ts.map +1 -0
  42. package/dist/RPC/Messages.js +30 -0
  43. package/dist/RPC/Messages.js.map +1 -0
  44. package/dist/RPC/Rpc.d.ts +51 -0
  45. package/dist/RPC/Rpc.d.ts.map +1 -0
  46. package/dist/RPC/Rpc.js +54 -0
  47. package/dist/RPC/Rpc.js.map +1 -0
  48. package/dist/RPC/RpcClientHandler.d.ts +129 -0
  49. package/dist/RPC/RpcClientHandler.d.ts.map +1 -0
  50. package/dist/RPC/RpcClientHandler.js +267 -0
  51. package/dist/RPC/RpcClientHandler.js.map +1 -0
  52. package/dist/RPC/RpcServerHandler.d.ts +226 -0
  53. package/dist/RPC/RpcServerHandler.d.ts.map +1 -0
  54. package/dist/RPC/RpcServerHandler.js +676 -0
  55. package/dist/RPC/RpcServerHandler.js.map +1 -0
  56. package/dist/RPC/Schema.d.ts +150 -0
  57. package/dist/RPC/Schema.d.ts.map +1 -0
  58. package/dist/RPC/Schema.js +198 -0
  59. package/dist/RPC/Schema.js.map +1 -0
  60. package/dist/RPC/Signing.d.ts +118 -0
  61. package/dist/RPC/Signing.d.ts.map +1 -0
  62. package/dist/RPC/Signing.js +171 -0
  63. package/dist/RPC/Signing.js.map +1 -0
  64. package/dist/RPC/Tokens.d.ts +49 -0
  65. package/dist/RPC/Tokens.d.ts.map +1 -0
  66. package/dist/RPC/Tokens.js +45 -0
  67. package/dist/RPC/Tokens.js.map +1 -0
  68. package/dist/RpcClient.d.ts +91 -0
  69. package/dist/RpcClient.d.ts.map +1 -0
  70. package/dist/RpcClient.js +145 -0
  71. package/dist/RpcClient.js.map +1 -0
  72. package/dist/RpcServer.d.ts +191 -0
  73. package/dist/RpcServer.d.ts.map +1 -0
  74. package/dist/RpcServer.js +293 -0
  75. package/dist/RpcServer.js.map +1 -0
  76. package/dist/Transports/Mqtt5Frame.d.ts +107 -0
  77. package/dist/Transports/Mqtt5Frame.d.ts.map +1 -0
  78. package/dist/Transports/Mqtt5Frame.js +162 -0
  79. package/dist/Transports/Mqtt5Frame.js.map +1 -0
  80. package/dist/Transports/MqttTransport.d.ts +279 -0
  81. package/dist/Transports/MqttTransport.d.ts.map +1 -0
  82. package/dist/Transports/MqttTransport.js +843 -0
  83. package/dist/Transports/MqttTransport.js.map +1 -0
  84. package/dist/Transports/Presence.d.ts +68 -0
  85. package/dist/Transports/Presence.d.ts.map +1 -0
  86. package/dist/Transports/Presence.js +21 -0
  87. package/dist/Transports/Presence.js.map +1 -0
  88. package/dist/Transports/SocketIoClientTransport.d.ts +89 -0
  89. package/dist/Transports/SocketIoClientTransport.d.ts.map +1 -0
  90. package/dist/Transports/SocketIoClientTransport.js +280 -0
  91. package/dist/Transports/SocketIoClientTransport.js.map +1 -0
  92. package/dist/Transports/SocketIoServerTransport.d.ts +135 -0
  93. package/dist/Transports/SocketIoServerTransport.d.ts.map +1 -0
  94. package/dist/Transports/SocketIoServerTransport.js +505 -0
  95. package/dist/Transports/SocketIoServerTransport.js.map +1 -0
  96. package/dist/Utilities/Converters.d.ts +22 -0
  97. package/dist/Utilities/Converters.d.ts.map +1 -0
  98. package/dist/Utilities/Converters.js +58 -0
  99. package/dist/Utilities/Converters.js.map +1 -0
  100. package/dist/Utilities/Filter.d.ts +7 -0
  101. package/dist/Utilities/Filter.d.ts.map +1 -0
  102. package/dist/Utilities/Filter.js +14 -0
  103. package/dist/Utilities/Filter.js.map +1 -0
  104. package/dist/Utilities/ReadableName.d.ts +38 -0
  105. package/dist/Utilities/ReadableName.d.ts.map +1 -0
  106. package/dist/Utilities/ReadableName.js +58 -0
  107. package/dist/Utilities/ReadableName.js.map +1 -0
  108. package/dist/Utilities/Switch.d.ts +21 -0
  109. package/dist/Utilities/Switch.d.ts.map +1 -0
  110. package/dist/Utilities/Switch.js +70 -0
  111. package/dist/Utilities/Switch.js.map +1 -0
  112. package/dist/Utilities/TryCatch.d.ts +11 -0
  113. package/dist/Utilities/TryCatch.d.ts.map +1 -0
  114. package/dist/Utilities/TryCatch.js +13 -0
  115. package/dist/Utilities/TryCatch.js.map +1 -0
  116. package/dist/index-web.d.ts +25 -0
  117. package/dist/index-web.d.ts.map +1 -0
  118. package/dist/index-web.js +28 -0
  119. package/dist/index-web.js.map +1 -0
  120. package/dist/index.d.ts +28 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +30 -0
  123. package/dist/index.js.map +1 -0
  124. package/package.json +77 -0
@@ -0,0 +1,7 @@
1
+ export type LogLevel = 'Verbose' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Fatal';
2
+ export interface ILogger {
3
+ log: (level: LogLevel, messageTemplate: string, properties?: {
4
+ [key: string]: unknown;
5
+ }) => void;
6
+ }
7
+ //# sourceMappingURL=ILogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ILogger.d.ts","sourceRoot":"","sources":["../../src/Logging/ILogger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAE1F,MAAM,WAAW,OAAO;IACpB,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;CACnG"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ILogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ILogger.js","sourceRoot":"","sources":["../../src/Logging/ILogger.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import type { Server } from 'http';
2
+ import type { ServerOptions as TlsServerOptions } from 'https';
3
+ import { Transport } from './RPC/Core.js';
4
+ import { MqttTransportOptions } from './Transports/MqttTransport.js';
5
+ import { ConnectServerOptions, RpcServerBase, RpcServerOptions, ServerOptions } from './RpcServer.js';
6
+ /**
7
+ * The server for a process that can listen.
8
+ *
9
+ * This is what `RpcServer` means everywhere except a browser, where the package's `browser` export
10
+ * condition resolves to RpcServerBase instead. The split is not cosmetic: a page cannot open a
11
+ * listening socket or speak MQTT, and putting those shapes here means `{ port: 8080 }` in browser
12
+ * code is a compile error rather than a class that throws when constructed. It also keeps
13
+ * socket.io's server and the MQTT client out of a browser bundle, because nothing a browser
14
+ * resolves imports this file at all.
15
+ */
16
+ /** A socket.io server this class opens and owns. */
17
+ export interface HttpServerOptions extends ServerOptions {
18
+ port: number;
19
+ /**
20
+ * TLS material for this server. Present means HTTPS; absent means plain HTTP.
21
+ *
22
+ * ```ts
23
+ * { port: 8443, tls: { cert: readFileSync('plant.crt'), key: readFileSync('plant.key') } }
24
+ * ```
25
+ */
26
+ tls?: TlsServerOptions;
27
+ path?: string;
28
+ /**
29
+ * @deprecated Refused. `https: true` opened an HTTPS server with no certificate and no key, so
30
+ * it listened and then failed every handshake. Pass `tls` with the certificate instead, or hand
31
+ * over a `server` you have configured yourself.
32
+ */
33
+ https?: never;
34
+ }
35
+ /** Attach to an http.Server you already have, so a page and its RPC arrive on one port. */
36
+ export interface ExternalServerOptions extends ServerOptions {
37
+ server: Server;
38
+ path?: string;
39
+ }
40
+ /** Serve over a broker. */
41
+ export interface MqttServerOptions extends ServerOptions, MqttTransportOptions {
42
+ brokerurl: string;
43
+ }
44
+ export interface NodeRpcServerOptions extends Omit<RpcServerOptions, 'transports'> {
45
+ transports: (HttpServerOptions | ExternalServerOptions | ConnectServerOptions | MqttServerOptions | Transport)[];
46
+ }
47
+ export declare class NodeRpcServer extends RpcServerBase {
48
+ constructor(options?: Partial<NodeRpcServerOptions>);
49
+ /** A socket.io server on the default port, which is what an unconfigured server has always been. */
50
+ protected configuredTransports(): {
51
+ port: number;
52
+ }[] | (ConnectServerOptions | Transport)[];
53
+ protected buildTransport(serveroption: unknown): Promise<Transport | undefined>;
54
+ }
55
+ //# sourceMappingURL=NodeRpcServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeRpcServer.d.ts","sourceRoot":"","sources":["../src/NodeRpcServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,OAAO,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAiB,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAEnF,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAGrG;;;;;;;;;GASG;AAEH,oDAAoD;AACpD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,gBAAgB,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAA;CAChB;AAED,2FAA2F;AAC3F,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,2BAA2B;AAC3B,MAAM,WAAW,iBAAkB,SAAQ,aAAa,EAAE,oBAAoB;IAC1E,SAAS,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC;IAC9E,UAAU,EAAE,CAAC,iBAAiB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,iBAAiB,GAAG,SAAS,CAAC,EAAE,CAAA;CACnH;AAED,qBAAa,aAAc,SAAQ,aAAa;IAC5C,YAAY,OAAO,GAAE,OAAO,CAAC,oBAAoB,CAAM,EAItD;IAED,oGAAoG;IACpG,UAAmB,oBAAoB;;+CAEtC;IAED,UAAyB,cAAc,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CA+B7F;CACJ"}
@@ -0,0 +1,46 @@
1
+ import { MqttTransport } from './Transports/MqttTransport.js';
2
+ import { SocketIoServerTransport } from './Transports/SocketIoServerTransport.js';
3
+ import { RpcServerBase } from './RpcServer.js';
4
+ import { defaultWebSocketPort } from './RPC/Rpc.js';
5
+ export class NodeRpcServer extends RpcServerBase {
6
+ constructor(options = {}) {
7
+ // The base stores the narrower union; this class only ever adds shapes to it, and
8
+ // buildTransport below is what actually reads them.
9
+ super(options);
10
+ }
11
+ /** A socket.io server on the default port, which is what an unconfigured server has always been. */
12
+ configuredTransports() {
13
+ return this.options.transports.length ? this.options.transports : [{ port: defaultWebSocketPort }];
14
+ }
15
+ async buildTransport(serveroption) {
16
+ const portable = await super.buildTransport(serveroption);
17
+ if (portable)
18
+ return portable;
19
+ if (serveroption.port) {
20
+ const httpOptions = serveroption;
21
+ // The type says `never`, which stops it at compile time; this stops it for a caller
22
+ // configuring the server from JSON, who would otherwise get a listening socket that
23
+ // fails every handshake.
24
+ if (serveroption.https)
25
+ throw new Error(`RpcServer '${this.options.name}': { https: true } is refused because it opened a server with no certificate. Pass tls: { cert, key } instead.`);
26
+ return new SocketIoServerTransport(this.options.name, undefined, httpOptions.port, httpOptions.tls, [], { path: httpOptions.path }, this.options.authenticate);
27
+ }
28
+ if (serveroption.server) {
29
+ const externalOptions = serveroption;
30
+ return new SocketIoServerTransport(this.options.name, externalOptions.server, 0, undefined, [], { path: externalOptions.path }, this.options.authenticate);
31
+ }
32
+ if (serveroption.brokerurl) {
33
+ const mqttServerOptions = serveroption;
34
+ return new MqttTransport(this.options.name, mqttServerOptions.brokerurl, {
35
+ // A server should not lose requests published while it was restarting, so it keeps
36
+ // its broker session by default. Clients do not: a late reply is useless to a call
37
+ // that has already timed out, and every short-lived peer would leave session state
38
+ // behind on the broker.
39
+ persistentSession: true,
40
+ ...mqttServerOptions
41
+ });
42
+ }
43
+ return undefined;
44
+ }
45
+ }
46
+ //# sourceMappingURL=NodeRpcServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeRpcServer.js","sourceRoot":"","sources":["../src/NodeRpcServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAwB,MAAM,+BAA+B,CAAA;AACnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAA;AACjF,OAAO,EAAwB,aAAa,EAAmC,MAAM,gBAAgB,CAAA;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAgDnD,MAAM,OAAO,aAAc,SAAQ,aAAa;IAC5C,YAAY,OAAO,GAAkC,EAAE;QACnD,kFAAkF;QAClF,oDAAoD;QACpD,KAAK,CAAC,OAAoC,CAAC,CAAA;IAC/C,CAAC;IAED,oGAAoG;IACjF,oBAAoB;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAA;IACtG,CAAC;IAEkB,KAAK,CAAC,cAAc,CAAC,YAAqB;QACzD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAA;QACzD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAE7B,IAAK,YAAkC,CAAC,IAAI,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,YAAiC,CAAA;YACrD,oFAAoF;YACpF,oFAAoF;YACpF,yBAAyB;YACzB,IAAK,YAAoC,CAAC,KAAK;gBAC3C,MAAM,IAAI,KAAK,CACX,cAAc,IAAI,CAAC,OAAO,CAAC,IAAI,gHAAgH,CAClJ,CAAA;YACL,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAClK,CAAC;QACD,IAAK,YAAsC,CAAC,MAAM,EAAE,CAAC;YACjD,MAAM,eAAe,GAAG,YAAqC,CAAA;YAC7D,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC9J,CAAC;QACD,IAAK,YAAkC,CAAC,SAAS,EAAE,CAAC;YAChD,MAAM,iBAAiB,GAAG,YAAiC,CAAA;YAC3D,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,SAAS,EAAE;gBACrE,mFAAmF;gBACnF,mFAAmF;gBACnF,mFAAmF;gBACnF,wBAAwB;gBACxB,iBAAiB,EAAE,IAAI;gBACvB,GAAG,iBAAiB;aACvB,CAAC,CAAA;QACN,CAAC;QACD,OAAO,SAAS,CAAA;IACpB,CAAC;CACJ"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Authentication and authorization types.
3
+ *
4
+ * Authentication happens at the transport, because that is the only layer that can tie a claim to
5
+ * a connection. The source field of a message header is supplied by the sender and is not evidence
6
+ * of anything on its own - a transport that authenticates must therefore pin each connection to
7
+ * one peer name and reject frames that claim a different one. Otherwise any authenticated peer
8
+ * could address messages as any other peer and inherit its rights.
9
+ *
10
+ * Authorization happens at the RPC layer, which is where a call is resolved to an instance and a
11
+ * method.
12
+ */
13
+ /**
14
+ * A certificate authority to trust when dialling a TLS peer, as PEM text or the bytes of one.
15
+ *
16
+ * The counterpart to `allowInsecureTls`, and the one to reach for first: a plant with its own
17
+ * authority wants *its* certificates trusted, not every certificate accepted. Verification stays
18
+ * on, so a server presenting anything this does not vouch for is still refused - which is the whole
19
+ * difference between a private trust root and no trust at all.
20
+ */
21
+ export type TrustedCertificateAuthority = string | Uint8Array | Array<string | Uint8Array>;
22
+ /** An authenticated peer. */
23
+ export interface RpcIdentity {
24
+ /**
25
+ * The peer name this identity may use as its message source. Frames claiming any other source
26
+ * are dropped, so an RpcClient's `name` option must match this when authentication is on.
27
+ */
28
+ name: string;
29
+ roles?: string[];
30
+ claims?: {
31
+ [key: string]: unknown;
32
+ };
33
+ }
34
+ /** What a transport knows about a peer trying to connect. */
35
+ export interface RpcConnectionInfo {
36
+ /** Remote address, when the transport can determine one. Useful for allow-lists and audit. */
37
+ address?: string;
38
+ }
39
+ /**
40
+ * Verify credentials presented at connection time. Return the identity to accept the peer, or
41
+ * undefined to reject it. Throwing also rejects.
42
+ */
43
+ export type RpcAuthenticator = (credentials: unknown, info: RpcConnectionInfo) => RpcIdentity | undefined | Promise<RpcIdentity | undefined>;
44
+ /** Everything known about a call at the point the decision is made. */
45
+ export interface RpcCallContext {
46
+ /**
47
+ * The authenticated caller, when the transport it arrived on authenticates. Undefined for
48
+ * transports that cannot authenticate, such as MQTT, where trust comes from the broker.
49
+ */
50
+ identity?: RpcIdentity;
51
+ /** Peer name the message claims as its source, and the address replies are sent to. */
52
+ source: string;
53
+ /** Name the target instance is exposed under. */
54
+ instanceName: string;
55
+ method: string;
56
+ params: unknown[];
57
+ /** True when the call is an event subscription rather than a method call. */
58
+ subscription: boolean;
59
+ }
60
+ /** Return false to reject a call with a Forbidden error. */
61
+ export type RpcAuthorizer = (context: RpcCallContext) => boolean | Promise<boolean>;
62
+ /**
63
+ * The parts of a frame a signature covers. Everything that decides where a message came from,
64
+ * where it is going and what it says, plus a nonce so a captured frame cannot be replayed.
65
+ *
66
+ * Both sides build these bytes the same way from the same fields, so there is no parsing
67
+ * ambiguity: see canonicalSignedBytes in Signing.ts for the exact encoding.
68
+ */
69
+ export interface SignedFrame {
70
+ source: string;
71
+ target: string;
72
+ time: number;
73
+ seq: number;
74
+ nonce: string;
75
+ payload: Uint8Array;
76
+ }
77
+ /** What a signer knows about the frame beyond the bytes it is signing. */
78
+ export interface SigningContext {
79
+ /** Peer that claims to have sent the frame. Selects which key to sign or verify with. */
80
+ source: string;
81
+ }
82
+ /**
83
+ * Produce a base64 signature over already-canonicalised bytes.
84
+ *
85
+ * Signers take bytes rather than a frame so one signer works across wire formats: the v1 header
86
+ * and the MQTT 5 property layout canonicalise different fields, and only the transport knows which
87
+ * it is speaking.
88
+ */
89
+ export type MessageSigner = (canonicalBytes: Uint8Array, context: SigningContext) => string | Promise<string>;
90
+ /**
91
+ * Check a signature over canonicalised bytes. Return the sender's identity to accept the frame,
92
+ * undefined to reject it.
93
+ *
94
+ * The returned identity's `name` must equal the frame's source; a transport rejects the frame
95
+ * otherwise, so a peer holding one key cannot sign messages claiming to come from another.
96
+ */
97
+ export type MessageVerifier = (canonicalBytes: Uint8Array, signature: string, context: SigningContext) => RpcIdentity | undefined | Promise<RpcIdentity | undefined>;
98
+ //# sourceMappingURL=Auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Auth.d.ts","sourceRoot":"","sources":["../../src/RPC/Auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAA;AAE1F,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IACxB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,MAAM,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACtC;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAC9B,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,KAAK,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;AAE5I,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,EAAE,CAAA;IACjB,6EAA6E;IAC7E,YAAY,EAAE,OAAO,CAAA;CACxB;AAED,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnF;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,UAAU,CAAA;CACtB;AAED,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC3B,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAE7G;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAC1B,cAAc,EAAE,UAAU,EAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,KACtB,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Authentication and authorization types.
3
+ *
4
+ * Authentication happens at the transport, because that is the only layer that can tie a claim to
5
+ * a connection. The source field of a message header is supplied by the sender and is not evidence
6
+ * of anything on its own - a transport that authenticates must therefore pin each connection to
7
+ * one peer name and reject frames that claim a different one. Otherwise any authenticated peer
8
+ * could address messages as any other peer and inherit its rights.
9
+ *
10
+ * Authorization happens at the RPC layer, which is where a call is resolved to an instance and a
11
+ * method.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=Auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Auth.js","sourceRoot":"","sources":["../../src/RPC/Auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Turns a message into the bytes a transport puts on the wire, and back again.
3
+ *
4
+ * Encoding belongs to the transport rather than to a module in the chain. A transport whose wire
5
+ * format is structured - MQTT 5 carries the method, the correlation and the reply address as
6
+ * packet properties - needs to see the message, and a converter sitting above it would already
7
+ * have flattened it to an opaque blob.
8
+ */
9
+ export interface FrameCodec {
10
+ /** MIME type for wire formats that can announce one, such as MQTT 5's contentType. */
11
+ readonly contentType: string;
12
+ encode(message: unknown): Uint8Array;
13
+ decode(bytes: Uint8Array): unknown;
14
+ }
15
+ /**
16
+ * The default. Sits between JSON and protobuf on size and parse cost without a schema toolchain,
17
+ * encodes Uint8Array natively, and has small allocation-light implementations for constrained
18
+ * targets.
19
+ */
20
+ export declare const msgPackCodec: FrameCodec;
21
+ /** Larger and lossy for binary, but readable in any tool and implementable anywhere. */
22
+ export declare const jsonCodec: FrameCodec;
23
+ export declare const codecFor: (useMsgPack: boolean) => FrameCodec;
24
+ //# sourceMappingURL=Codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Codec.d.ts","sourceRoot":"","sources":["../../src/RPC/Codec.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACvB,sFAAsF;IACtF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAA;IACpC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAA;CACrC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,UAK1B,CAAA;AAED,wFAAwF;AACxF,eAAO,MAAM,SAAS,EAAE,UAIvB,CAAA;AAED,eAAO,MAAM,QAAQ,eAAgB,OAAO,eAA4C,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { encode as msgPackEncode, decode as msgPackDecode } from '@msgpack/msgpack';
2
+ import { stringToUint8Array, uint8ArrayToString } from 'uint8array-extras';
3
+ /**
4
+ * The default. Sits between JSON and protobuf on size and parse cost without a schema toolchain,
5
+ * encodes Uint8Array natively, and has small allocation-light implementations for constrained
6
+ * targets.
7
+ */
8
+ export const msgPackCodec = {
9
+ contentType: 'application/msgpack',
10
+ // ignoreUndefined keeps JSON's behaviour of dropping undefined object properties.
11
+ encode: (message) => msgPackEncode(message, { ignoreUndefined: true }),
12
+ decode: (bytes) => msgPackDecode(bytes)
13
+ };
14
+ /** Larger and lossy for binary, but readable in any tool and implementable anywhere. */
15
+ export const jsonCodec = {
16
+ contentType: 'application/json',
17
+ encode: (message) => stringToUint8Array(JSON.stringify(message)),
18
+ decode: (bytes) => JSON.parse(uint8ArrayToString(bytes))
19
+ };
20
+ export const codecFor = (useMsgPack) => (useMsgPack ? msgPackCodec : jsonCodec);
21
+ //# sourceMappingURL=Codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Codec.js","sourceRoot":"","sources":["../../src/RPC/Codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAiB1E;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAe;IACpC,WAAW,EAAE,qBAAqB;IAClC,kFAAkF;IAClF,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IACtE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC;CAC1C,CAAA;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,SAAS,GAAe;IACjC,WAAW,EAAE,kBAAkB;IAC/B,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;CAC3D,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,UAAmB,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { NamespaceSchema, RpcSchema, TypeNode } from './Schema.js';
2
+ /**
3
+ * Deciding whether a caller built against an older contract can safely talk to the current one.
4
+ *
5
+ * Validating an old call against its own old schema would prove nothing: it still reaches the
6
+ * current implementation, so acceptance would only move the failure from the validator into the
7
+ * method body. What the stored history is actually good for is comparing the two contracts and
8
+ * asking whether every call the old one permitted is still one this one handles.
9
+ *
10
+ * That is ordinary function subtyping. Parameters are contravariant - the current contract has to
11
+ * accept everything the old one allowed, so widening a parameter is safe and narrowing it is not.
12
+ * Returns are covariant - everything the current contract can return has to fit what the old
13
+ * caller expects, so narrowing a return is safe and widening it is not.
14
+ *
15
+ * The check is conservative: where it cannot prove compatibility it reports incompatibility, since
16
+ * a false "safe" is the expensive direction.
17
+ */
18
+ export interface Incompatibility {
19
+ /** Where the problem is, e.g. "writeSetpoint argument 0". */
20
+ where: string;
21
+ reason: string;
22
+ }
23
+ /**
24
+ * True when every value valid under `from` is also valid under `to`.
25
+ *
26
+ * Recursive types are handled coinductively: a pair of named types already being compared is
27
+ * assumed to hold while the rest is proved. Without that, comparing a recursive type with itself
28
+ * descends forever and the depth guard reports it as incompatible - which would mark every
29
+ * recursive shape as a breaking change, including against an identical contract.
30
+ */
31
+ export declare const assignable: (from: TypeNode, to: TypeNode, types?: RpcSchema['types'], depth?: number, assumed?: Set<string>) => boolean;
32
+ /**
33
+ * Compares the contract a caller was built against with the one now being served. An empty result
34
+ * means every call the caller might make is still handled.
35
+ */
36
+ export declare const namespaceProblems: (caller: NamespaceSchema, current: NamespaceSchema, types?: RpcSchema['types']) => Incompatibility[];
37
+ /** One line naming why an older contract cannot be served, or undefined when it can. */
38
+ export declare const describeProblems: (namespace: string, version: string, current: string | undefined, problems: Incompatibility[]) => string | undefined;
39
+ //# sourceMappingURL=Compatibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Compatibility.d.ts","sourceRoot":"","sources":["../../src/RPC/Compatibility.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEhF;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,eAAe;IAC5B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACjB;AAWD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,SAAU,QAAQ,MAAM,QAAQ,UAAS,SAAS,CAAC,OAAO,CAAC,4BAA2B,GAAG,CAAC,MAAM,CAAC,KAAe,OAqFtI,CAAA;AAyCD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,WAAY,eAAe,WAAW,eAAe,UAAS,SAAS,CAAC,OAAO,CAAC,KAAQ,eAAe,EAgCpI,CAAA;AAED,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,cAAe,MAAM,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS,YAAY,eAAe,EAAE,uBAI1G,CAAA"}
@@ -0,0 +1,195 @@
1
+ import { SEMANTICS_RISK } from './Messages.js';
2
+ const resolve = (type, types) => (type.kind === 'ref' ? resolve(types?.[type.name] ?? { kind: 'any' }, types) : type);
3
+ const widerOrEqualNumber = (from, to) => {
4
+ if (to.integer && !from.integer)
5
+ return false;
6
+ if (to.min !== undefined && (from.min === undefined || from.min < to.min))
7
+ return false;
8
+ if (to.max !== undefined && (from.max === undefined || from.max > to.max))
9
+ return false;
10
+ return true;
11
+ };
12
+ /**
13
+ * True when every value valid under `from` is also valid under `to`.
14
+ *
15
+ * Recursive types are handled coinductively: a pair of named types already being compared is
16
+ * assumed to hold while the rest is proved. Without that, comparing a recursive type with itself
17
+ * descends forever and the depth guard reports it as incompatible - which would mark every
18
+ * recursive shape as a breaking change, including against an identical contract.
19
+ */
20
+ export const assignable = (from, to, types = {}, depth = 0, assumed = new Set()) => {
21
+ if (depth > 64)
22
+ return false;
23
+ if (from.kind === 'ref' && to.kind === 'ref') {
24
+ const pair = `${from.name} <: ${to.name}`;
25
+ if (assumed.has(pair))
26
+ return true;
27
+ assumed.add(pair);
28
+ }
29
+ const source = resolve(from, types);
30
+ const target = resolve(to, types);
31
+ if (target.kind === 'any')
32
+ return true;
33
+ // An 'any' source can hold anything, so only an 'any' target can accept it.
34
+ if (source.kind === 'any')
35
+ return false;
36
+ if (source.kind === 'union')
37
+ return source.options.every((option) => assignable(option, target, types, depth + 1, assumed));
38
+ if (target.kind === 'union')
39
+ return target.options.some((option) => assignable(source, option, types, depth + 1, assumed));
40
+ if (source.kind === 'literal') {
41
+ if (target.kind === 'literal')
42
+ return source.value === target.value;
43
+ const literalKind = source.value === null ? 'null' : typeof source.value;
44
+ if (literalKind !== target.kind)
45
+ return false;
46
+ if (target.kind === 'number' && typeof source.value === 'number')
47
+ return widerOrEqualNumber({ min: source.value, max: source.value, integer: Number.isInteger(source.value) }, target);
48
+ return true;
49
+ }
50
+ if (source.kind !== target.kind)
51
+ return false;
52
+ switch (source.kind) {
53
+ case 'null':
54
+ case 'boolean':
55
+ case 'date':
56
+ return true;
57
+ case 'number':
58
+ return widerOrEqualNumber(source, target);
59
+ case 'string': {
60
+ const stringTarget = target;
61
+ if (stringTarget.minLength !== undefined && (source.minLength === undefined || source.minLength < stringTarget.minLength))
62
+ return false;
63
+ if (stringTarget.maxLength !== undefined && (source.maxLength === undefined || source.maxLength > stringTarget.maxLength))
64
+ return false;
65
+ // Regex subsumption is undecidable in general, so only an identical pattern counts.
66
+ if (stringTarget.pattern !== undefined && stringTarget.pattern !== source.pattern)
67
+ return false;
68
+ return true;
69
+ }
70
+ case 'bytes': {
71
+ const bytesTarget = target;
72
+ return bytesTarget.maxBytes === undefined || (source.maxBytes !== undefined && source.maxBytes <= bytesTarget.maxBytes);
73
+ }
74
+ case 'array': {
75
+ const arrayTarget = target;
76
+ if (arrayTarget.maxItems !== undefined && (source.maxItems === undefined || source.maxItems > arrayTarget.maxItems))
77
+ return false;
78
+ return assignable(source.items, arrayTarget.items, types, depth + 1, assumed);
79
+ }
80
+ case 'tuple': {
81
+ const tupleTarget = target;
82
+ if (source.items.length !== tupleTarget.items.length)
83
+ return false;
84
+ return source.items.every((item, index) => assignable(item, tupleTarget.items[index], types, depth + 1, assumed));
85
+ }
86
+ case 'record': {
87
+ const recordTarget = target;
88
+ if (recordTarget.maxEntries !== undefined && (source.maxEntries === undefined || source.maxEntries > recordTarget.maxEntries))
89
+ return false;
90
+ // As with a string pattern: deciding whether one regex admits everything another does
91
+ // is undecidable in general, so only an identical constraint counts.
92
+ if (recordTarget.keyPattern !== undefined && recordTarget.keyPattern !== source.keyPattern)
93
+ return false;
94
+ return assignable(source.values, recordTarget.values, types, depth + 1, assumed);
95
+ }
96
+ case 'object': {
97
+ const objectTarget = target;
98
+ for (const [name, field] of Object.entries(objectTarget.fields)) {
99
+ const sourceField = source.fields[name];
100
+ if (!sourceField) {
101
+ // Gaining an optional field is the ordinary way a contract evolves; only a new
102
+ // required field breaks a source that never supplied it.
103
+ if (field.optional)
104
+ continue;
105
+ return false;
106
+ }
107
+ if (!field.optional && sourceField.optional)
108
+ return false;
109
+ if (!assignable(sourceField.type, field.type, types, depth + 1, assumed))
110
+ return false;
111
+ }
112
+ if (!objectTarget.additional) {
113
+ // The source could produce a property the target refuses.
114
+ for (const name of Object.keys(source.fields))
115
+ if (!(name in objectTarget.fields))
116
+ return false;
117
+ }
118
+ return true;
119
+ }
120
+ default:
121
+ return false;
122
+ }
123
+ };
124
+ /** Lowest number of arguments a caller of this method might send. */
125
+ const requiredArity = (method) => method.params.filter((type) => !(type.kind === 'any' || (type.kind === 'union' && type.options.some((o) => o.kind === 'literal' && o.value === null)))).length;
126
+ const methodProblems = (name, caller, current, types) => {
127
+ const problems = [];
128
+ // The current contract must accept every argument count the old caller might send.
129
+ if (!current.rest && current.params.length < caller.params.length)
130
+ problems.push({ where: name, reason: `takes at most ${current.params.length} arguments, but a caller may send ${caller.params.length}` });
131
+ if (requiredArity(current) > requiredArity(caller))
132
+ problems.push({ where: name, reason: `requires ${requiredArity(current)} arguments, but a caller may send as few as ${requiredArity(caller)}` });
133
+ // Parameters are contravariant: what the caller may send must still be accepted.
134
+ for (let i = 0; i < caller.params.length; i++) {
135
+ const currentParam = i < current.params.length ? current.params[i] : current.rest;
136
+ if (!currentParam)
137
+ continue;
138
+ if (!assignable(caller.params[i], currentParam, types))
139
+ problems.push({ where: `${name} argument ${i}`, reason: 'narrowed, so a value the caller may send is no longer accepted' });
140
+ }
141
+ // Returns are covariant: what this contract returns must still be understood.
142
+ if (caller.returns && current.returns && !assignable(current.returns, caller.returns, types))
143
+ problems.push({ where: `${name} return`, reason: 'widened, so a value this contract may return is not one the caller expects' });
144
+ // Semantics may become safer to repeat but not more dangerous. A caller told it was calling a
145
+ // query is entitled to have retried freely, and code written on that promise is still out there
146
+ // - so a method quietly becoming a command is a breaking change even though every type still
147
+ // lines up. This is the one incompatibility a type comparison cannot see.
148
+ const was = caller.semantics;
149
+ const now = current.semantics;
150
+ if (was && now && SEMANTICS_RISK[now] > SEMANTICS_RISK[was])
151
+ problems.push({ where: name, reason: `is now ${now} where the caller was told ${was}, so a retry the caller may already make is no longer safe` });
152
+ if (was && !now && SEMANTICS_RISK[was] < SEMANTICS_RISK['non-repeatable-command'])
153
+ problems.push({ where: name, reason: `no longer declares that it is ${was}, so a caller relying on that promise has nothing to rely on` });
154
+ return problems;
155
+ };
156
+ /**
157
+ * Compares the contract a caller was built against with the one now being served. An empty result
158
+ * means every call the caller might make is still handled.
159
+ */
160
+ export const namespaceProblems = (caller, current, types = {}) => {
161
+ const problems = [];
162
+ for (const [name, callerMethod] of Object.entries(caller.methods)) {
163
+ const currentMethod = current.methods[name];
164
+ if (!currentMethod) {
165
+ problems.push({ where: name, reason: 'no longer exists' });
166
+ continue;
167
+ }
168
+ problems.push(...methodProblems(name, callerMethod, currentMethod, types));
169
+ }
170
+ // Events travel the other way: emitted here, received there.
171
+ for (const [name, callerEvent] of Object.entries(caller.events ?? {})) {
172
+ const currentEvent = current.events?.[name];
173
+ if (!currentEvent) {
174
+ // Not unsafe, but a subscription that can never fire is a silent failure worth naming.
175
+ problems.push({ where: `event ${name}`, reason: 'is no longer emitted, so a subscription to it would never fire' });
176
+ continue;
177
+ }
178
+ for (let i = 0; i < currentEvent.params.length; i++) {
179
+ const callerParam = callerEvent.params[i];
180
+ if (!callerParam) {
181
+ problems.push({ where: `event ${name} argument ${i}`, reason: 'is emitted but the caller does not expect it' });
182
+ continue;
183
+ }
184
+ if (!assignable(currentEvent.params[i], callerParam, types))
185
+ problems.push({ where: `event ${name} argument ${i}`, reason: 'widened, so a value this contract may emit is not one the caller expects' });
186
+ }
187
+ }
188
+ return problems;
189
+ };
190
+ /** One line naming why an older contract cannot be served, or undefined when it can. */
191
+ export const describeProblems = (namespace, version, current, problems) => problems.length
192
+ ? `${namespace}@${version} is not compatible with ${namespace}@${current ?? 'current'}: ` +
193
+ problems.map((problem) => `${problem.where} ${problem.reason}`).join('; ')
194
+ : undefined;
195
+ //# sourceMappingURL=Compatibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Compatibility.js","sourceRoot":"","sources":["../../src/RPC/Compatibility.ts"],"names":[],"mappings":"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"}