@push-rpc/next 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.prettierrc.json +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +26 -0
  4. package/dist/client/HttpClient.d.ts +10 -0
  5. package/dist/client/HttpClient.js +67 -0
  6. package/dist/client/HttpClient.js.map +1 -0
  7. package/dist/client/RemoteSubscriptions.d.ts +14 -0
  8. package/dist/client/RemoteSubscriptions.js +84 -0
  9. package/dist/client/RemoteSubscriptions.js.map +1 -0
  10. package/dist/client/RpcClientImpl.d.ts +22 -0
  11. package/dist/client/RpcClientImpl.js +96 -0
  12. package/dist/client/RpcClientImpl.js.map +1 -0
  13. package/dist/client/WebSocketConnection.d.ts +33 -0
  14. package/dist/client/WebSocketConnection.js +152 -0
  15. package/dist/client/WebSocketConnection.js.map +1 -0
  16. package/dist/client/index.d.ts +22 -0
  17. package/dist/client/index.js +28 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/client/remote.d.ts +14 -0
  20. package/dist/client/remote.js +66 -0
  21. package/dist/client/remote.js.map +1 -0
  22. package/dist/index.d.ts +12 -0
  23. package/dist/index.js +20 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/logger.d.ts +8 -0
  26. package/dist/logger.js +9 -0
  27. package/dist/logger.js.map +1 -0
  28. package/dist/rpc.d.ts +36 -0
  29. package/dist/rpc.js +32 -0
  30. package/dist/rpc.js.map +1 -0
  31. package/dist/server/ConnectionsServer.d.ts +13 -0
  32. package/dist/server/ConnectionsServer.js +60 -0
  33. package/dist/server/ConnectionsServer.js.map +1 -0
  34. package/dist/server/LocalSubscriptions.d.ts +12 -0
  35. package/dist/server/LocalSubscriptions.js +113 -0
  36. package/dist/server/LocalSubscriptions.js.map +1 -0
  37. package/dist/server/RpcServerImpl.d.ts +23 -0
  38. package/dist/server/RpcServerImpl.js +164 -0
  39. package/dist/server/RpcServerImpl.js.map +1 -0
  40. package/dist/server/http.d.ts +9 -0
  41. package/dist/server/http.js +83 -0
  42. package/dist/server/http.js.map +1 -0
  43. package/dist/server/index.d.ts +29 -0
  44. package/dist/server/index.js +31 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/dist/server/local.d.ts +15 -0
  47. package/dist/server/local.js +46 -0
  48. package/dist/server/local.js.map +1 -0
  49. package/dist/utils/json.d.ts +2 -0
  50. package/dist/utils/json.js +34 -0
  51. package/dist/utils/json.js.map +1 -0
  52. package/dist/utils/middleware.d.ts +2 -0
  53. package/dist/utils/middleware.js +31 -0
  54. package/dist/utils/middleware.js.map +1 -0
  55. package/dist/utils/promises.d.ts +5 -0
  56. package/dist/utils/promises.js +29 -0
  57. package/dist/utils/promises.js.map +1 -0
  58. package/dist/utils/throttle.d.ts +4 -0
  59. package/dist/utils/throttle.js +40 -0
  60. package/dist/utils/throttle.js.map +1 -0
  61. package/dist/utils/types.d.ts +1 -0
  62. package/dist/utils/types.js +3 -0
  63. package/dist/utils/types.js.map +1 -0
  64. package/example/api.ts +15 -0
  65. package/example/client.ts +16 -0
  66. package/example/server.ts +37 -0
  67. package/package.json +34 -0
  68. package/src/client/HttpClient.ts +80 -0
  69. package/src/client/RemoteSubscriptions.ts +121 -0
  70. package/src/client/RpcClientImpl.ts +177 -0
  71. package/src/client/WebSocketConnection.ts +183 -0
  72. package/src/client/index.ts +56 -0
  73. package/src/client/remote.ts +118 -0
  74. package/src/index.ts +18 -0
  75. package/src/logger.ts +12 -0
  76. package/src/rpc.ts +51 -0
  77. package/src/server/ConnectionsServer.ts +78 -0
  78. package/src/server/LocalSubscriptions.ts +155 -0
  79. package/src/server/RpcServerImpl.ts +252 -0
  80. package/src/server/http.ts +109 -0
  81. package/src/server/index.ts +65 -0
  82. package/src/server/local.ts +80 -0
  83. package/src/utils/json.ts +32 -0
  84. package/src/utils/middleware.ts +38 -0
  85. package/src/utils/promises.ts +25 -0
  86. package/src/utils/throttle.ts +48 -0
  87. package/src/utils/types.ts +1 -0
  88. package/tests/calls.ts +215 -0
  89. package/tests/connection.ts +107 -0
  90. package/tests/context.ts +176 -0
  91. package/tests/middleware.ts +112 -0
  92. package/tests/misc.ts +187 -0
  93. package/tests/subscriptions.ts +442 -0
  94. package/tests/testUtils.ts +52 -0
  95. package/tests/triggers.ts +138 -0
  96. package/tsconfig.cjs.json +20 -0
  97. package/tsconfig.json +26 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "printWidth": 100,
3
+ "semi": false,
4
+ "trailingComma": "es5",
5
+ "bracketSpacing": false,
6
+ "htmlWhitespaceSensitivity": "ignore"
7
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019-2024 Vasyl Stashuk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ ## Glossary
2
+
3
+ **Remote function**. A function that is implemented at the server side and can be called from the client side. Function
4
+ can either be called synchronously or subscribed to. Subscribed function needs to be "triggered" at the server side to
5
+ resend the data to the subscribed clients. Sometimes remote function is called "item".
6
+
7
+ Remote function must return Promise and can accept any number of arguments. Note! Variables number of arguments is not
8
+ supported (because optional argument is used for context and CallOptions). Remote function can throw an error, which
9
+ will be propagated to the client.
10
+
11
+ **Services**. Services are used to group remote functions. Services object can be instances of classes or plain objects.
12
+ Services can be nested.
13
+
14
+ **Context**. Only lives at the server side. Contains metadata about request and connection. It is passed to all the
15
+ middlewares and remote functions as the last parameter. For subscriptions, context is initially created during '
16
+ subscribe' invocation and copied to each 'trigger' invocation. Context, created by overriding `createContext`, should
17
+ contain only JSON data, to allow copying. Context can be modified in middlewares; these modification doesn't have to be
18
+ JSON-only.
19
+
20
+ **Middlewares**. Middlewares are used to intercept client and server requests. Both calls and subscriptions can be
21
+ intercepted?. Middlewares can be attached on both client and server side. Middlewares receive context as the last
22
+ arguments in the invocation. Middleware can modify context.
23
+
24
+ **Throttling**. Used to limit number of notifications from the remote functions. With throttling enabled, not all
25
+ triggers will result in new notifications. Throttling can be used with reducers to aggregate values supplied in
26
+ triggers.
@@ -0,0 +1,10 @@
1
+ export declare class HttpClient {
2
+ private url;
3
+ private clientId;
4
+ constructor(url: string, clientId: string);
5
+ call(itemName: string, params: unknown[], callTimeout: number): Promise<unknown>;
6
+ subscribe(itemName: string, params: unknown[], callTimeout: number): Promise<unknown>;
7
+ unsubscribe(itemName: string, params: unknown[], callTimeout: number): Promise<void>;
8
+ private getItemUrl;
9
+ private httpRequest;
10
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpClient = void 0;
4
+ const rpc_js_1 = require("../rpc.js");
5
+ const json_js_1 = require("../utils/json.js");
6
+ class HttpClient {
7
+ constructor(url, clientId) {
8
+ this.url = url;
9
+ this.clientId = clientId;
10
+ }
11
+ call(itemName, params, callTimeout) {
12
+ return this.httpRequest("POST", itemName, params, callTimeout);
13
+ }
14
+ async subscribe(itemName, params, callTimeout) {
15
+ return this.httpRequest("PUT", itemName, params, callTimeout);
16
+ }
17
+ async unsubscribe(itemName, params, callTimeout) {
18
+ await this.httpRequest("PATCH", itemName, params, callTimeout);
19
+ }
20
+ getItemUrl(itemName) {
21
+ return `${this.url}/${itemName}`;
22
+ }
23
+ async httpRequest(method, itemName, params, callTimeout) {
24
+ try {
25
+ const response = await fetch(this.getItemUrl(itemName), {
26
+ method,
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ [rpc_js_1.CLIENT_ID_HEADER]: this.clientId,
30
+ },
31
+ body: (0, json_js_1.safeStringify)(params),
32
+ signal: AbortSignal.timeout(callTimeout),
33
+ });
34
+ if (response.status == 204) {
35
+ return;
36
+ }
37
+ const contentType = response.headers.get("content-type");
38
+ const text = await response.text();
39
+ const res = contentType && contentType.includes("application/json") ? (0, json_js_1.safeParseJson)(text) : text;
40
+ if (response.status < 200 || response.status >= 300) {
41
+ const error = new Error(response.statusText);
42
+ Object.assign(error, { code: response.status });
43
+ if (typeof res == "object") {
44
+ Object.assign(error, res);
45
+ }
46
+ throw error;
47
+ }
48
+ else {
49
+ return res;
50
+ }
51
+ }
52
+ catch (e) {
53
+ if (e.message == "fetch failed" && e.cause) {
54
+ e = e.cause;
55
+ }
56
+ if (e.message?.toLowerCase()?.includes("timeout")) {
57
+ // NodeJS undici http client timeout
58
+ const error = new Error("Timeout");
59
+ Object.assign(error, { code: rpc_js_1.RpcErrors.Timeout });
60
+ throw error;
61
+ }
62
+ throw e;
63
+ }
64
+ }
65
+ }
66
+ exports.HttpClient = HttpClient;
67
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/client/HttpClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare class RemoteSubscriptions {
2
+ subscribe(initialData: unknown, itemName: string, parameters: unknown[], consumer: (d: unknown) => void): void;
3
+ unsubscribe(itemName: string, parameters: unknown[], consumer: (d: unknown) => void): boolean;
4
+ private addSubscription;
5
+ private removeSubscription;
6
+ getCached(itemName: string, parameters: unknown[]): unknown | undefined;
7
+ consume(itemName: string, parameters: unknown[], data: unknown): void;
8
+ getAllSubscriptions(): Array<[
9
+ itemName: string,
10
+ parameters: unknown[],
11
+ consumers: Array<(d: unknown) => void>
12
+ ]>;
13
+ private byItem;
14
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RemoteSubscriptions = void 0;
4
+ const json_js_1 = require("../utils/json.js");
5
+ class RemoteSubscriptions {
6
+ constructor() {
7
+ this.byItem = new Map();
8
+ }
9
+ subscribe(initialData, itemName, parameters, consumer) {
10
+ this.addSubscription(itemName, parameters, consumer);
11
+ this.consume(itemName, parameters, initialData);
12
+ }
13
+ unsubscribe(itemName, parameters, consumer) {
14
+ const parametersKey = getParametersKey(parameters);
15
+ return this.removeSubscription(itemName, parametersKey, consumer);
16
+ }
17
+ addSubscription(itemName, parameters, consumer) {
18
+ const itemSubscriptions = this.byItem.get(itemName) || { byParameters: new Map() };
19
+ this.byItem.set(itemName, itemSubscriptions);
20
+ const parametersKey = getParametersKey(parameters);
21
+ const parameterSubscriptions = itemSubscriptions.byParameters.get(parametersKey) || {
22
+ parameters,
23
+ cached: null,
24
+ consumers: [],
25
+ };
26
+ itemSubscriptions.byParameters.set(parametersKey, parameterSubscriptions);
27
+ parameterSubscriptions.consumers.push(consumer);
28
+ }
29
+ removeSubscription(itemName, parametersKey, consumer) {
30
+ const itemSubscriptions = this.byItem.get(itemName);
31
+ if (!itemSubscriptions)
32
+ return false;
33
+ const filterSubscriptions = itemSubscriptions.byParameters.get(parametersKey);
34
+ if (!filterSubscriptions)
35
+ return false;
36
+ const index = filterSubscriptions.consumers.indexOf(consumer);
37
+ if (index == -1)
38
+ return false;
39
+ filterSubscriptions.consumers.splice(index, 1);
40
+ if (!filterSubscriptions.consumers.length) {
41
+ itemSubscriptions.byParameters.delete(parametersKey);
42
+ if (itemSubscriptions.byParameters.size == 0) {
43
+ this.byItem.delete(itemName);
44
+ }
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+ getCached(itemName, parameters) {
50
+ const parametersKey = getParametersKey(parameters);
51
+ const itemSubscriptions = this.byItem.get(itemName);
52
+ if (!itemSubscriptions)
53
+ return;
54
+ const filterSubscriptions = itemSubscriptions.byParameters.get(parametersKey);
55
+ return filterSubscriptions?.cached;
56
+ }
57
+ consume(itemName, parameters, data) {
58
+ const parametersKey = getParametersKey(parameters);
59
+ const itemSubscriptions = this.byItem.get(itemName);
60
+ if (!itemSubscriptions)
61
+ return;
62
+ const filterSubscriptions = itemSubscriptions.byParameters.get(parametersKey);
63
+ if (!filterSubscriptions)
64
+ return;
65
+ filterSubscriptions.cached = data;
66
+ filterSubscriptions.consumers.forEach((consumer) => {
67
+ consumer(data);
68
+ });
69
+ }
70
+ getAllSubscriptions() {
71
+ const result = [];
72
+ for (const [itemName, itemSubscriptions] of this.byItem) {
73
+ for (const [, parameterSubscriptions] of itemSubscriptions.byParameters) {
74
+ result.push([itemName, parameterSubscriptions.parameters, parameterSubscriptions.consumers]);
75
+ }
76
+ }
77
+ return result;
78
+ }
79
+ }
80
+ exports.RemoteSubscriptions = RemoteSubscriptions;
81
+ function getParametersKey(parameters) {
82
+ return (0, json_js_1.safeStringify)(parameters);
83
+ }
84
+ //# sourceMappingURL=RemoteSubscriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoteSubscriptions.js","sourceRoot":"","sources":["../../src/client/RemoteSubscriptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /// <reference types="ws" />
2
+ import { Services } from "../rpc.js";
3
+ import { ServicesWithSubscriptions } from "./remote.js";
4
+ import { ConsumeServicesOptions, RpcClient } from "./index.js";
5
+ export declare class RpcClientImpl<S extends Services<S>> implements RpcClient {
6
+ private readonly options;
7
+ constructor(url: string, options: ConsumeServicesOptions);
8
+ private readonly clientId;
9
+ private readonly httpClient;
10
+ private readonly remoteSubscriptions;
11
+ private readonly connection;
12
+ isConnected(): boolean;
13
+ close(): Promise<void>;
14
+ _allSubscriptions(): [itemName: string, parameters: unknown[], consumers: (d: unknown) => void][];
15
+ _webSocket(): import("ws") | null;
16
+ createRemote(): ServicesWithSubscriptions<S>;
17
+ private call;
18
+ private subscribe;
19
+ private unsubscribe;
20
+ private resubscribe;
21
+ private invoke;
22
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RpcClientImpl = void 0;
4
+ const rpc_js_1 = require("../rpc.js");
5
+ const HttpClient_js_1 = require("./HttpClient.js");
6
+ const RemoteSubscriptions_js_1 = require("./RemoteSubscriptions.js");
7
+ const WebSocketConnection_js_1 = require("./WebSocketConnection.js");
8
+ const nanoid_1 = require("nanoid");
9
+ const remote_js_1 = require("./remote.js");
10
+ const middleware_js_1 = require("../utils/middleware.js");
11
+ class RpcClientImpl {
12
+ constructor(url, options) {
13
+ this.options = options;
14
+ this.clientId = (0, nanoid_1.nanoid)();
15
+ this.call = (itemName, parameters, callOptions) => {
16
+ return this.invoke(itemName, rpc_js_1.InvocationType.Call, (...parameters) => this.httpClient.call(itemName, parameters, callOptions?.timeout ?? this.options.callTimeout), parameters);
17
+ };
18
+ this.subscribe = async (itemName, parameters, consumer, callOptions) => {
19
+ const cached = this.remoteSubscriptions.getCached(itemName, parameters);
20
+ if (cached !== undefined) {
21
+ consumer(cached);
22
+ }
23
+ if (this.options.subscribe) {
24
+ this.connection.connect().catch((e) => {
25
+ // ignored
26
+ });
27
+ }
28
+ const data = await this.invoke(itemName, rpc_js_1.InvocationType.Subscribe, (...parameters) => this.httpClient.subscribe(itemName, parameters, callOptions?.timeout ?? this.options.callTimeout), parameters);
29
+ this.remoteSubscriptions.subscribe(data, itemName, parameters, consumer);
30
+ };
31
+ this.unsubscribe = async (itemName, parameters, consumer, callOptions) => {
32
+ const noSubscriptionsLeft = this.remoteSubscriptions.unsubscribe(itemName, parameters, consumer);
33
+ if (noSubscriptionsLeft) {
34
+ await this.invoke(itemName, rpc_js_1.InvocationType.Unsubscribe, (...parameters) => this.httpClient.unsubscribe(itemName, parameters, callOptions?.timeout ?? this.options.callTimeout), parameters);
35
+ }
36
+ };
37
+ this.resubscribe = () => {
38
+ for (const [itemName, params, consumers] of this.remoteSubscriptions.getAllSubscriptions()) {
39
+ this.httpClient
40
+ .subscribe(itemName, params, this.options.callTimeout)
41
+ .then((data) => {
42
+ this.remoteSubscriptions.consume(itemName, params, data);
43
+ })
44
+ .catch((e) => {
45
+ for (const consumer of consumers) {
46
+ this.remoteSubscriptions.unsubscribe(itemName, params, consumer);
47
+ }
48
+ });
49
+ }
50
+ };
51
+ this.httpClient = new HttpClient_js_1.HttpClient(url, this.clientId);
52
+ this.remoteSubscriptions = new RemoteSubscriptions_js_1.RemoteSubscriptions();
53
+ this.connection = new WebSocketConnection_js_1.WebSocketConnection(url, this.clientId, {
54
+ errorDelayMaxDuration: options.errorDelayMaxDuration,
55
+ reconnectDelay: options.reconnectDelay,
56
+ pingInterval: options.pingInterval,
57
+ }, (itemName, parameters, data) => {
58
+ this.remoteSubscriptions.consume(itemName, parameters, data);
59
+ }, this.resubscribe);
60
+ }
61
+ isConnected() {
62
+ return this.connection.isConnected();
63
+ }
64
+ close() {
65
+ return this.connection.close();
66
+ }
67
+ _allSubscriptions() {
68
+ const result = [];
69
+ for (const [itemName, parameters, consumers,] of this.remoteSubscriptions.getAllSubscriptions()) {
70
+ for (const consumer of consumers) {
71
+ result.push([itemName, parameters, consumer]);
72
+ }
73
+ }
74
+ return result;
75
+ }
76
+ _webSocket() {
77
+ return this.connection._webSocket();
78
+ }
79
+ createRemote() {
80
+ return (0, remote_js_1.createRemote)({
81
+ call: this.call,
82
+ subscribe: this.subscribe,
83
+ unsubscribe: this.unsubscribe,
84
+ });
85
+ }
86
+ invoke(itemName, invocationType, next, parameters) {
87
+ const ctx = {
88
+ clientId: this.clientId,
89
+ itemName,
90
+ invocationType: invocationType,
91
+ };
92
+ return (0, middleware_js_1.withMiddlewares)(ctx, this.options.middleware, next, ...parameters);
93
+ }
94
+ }
95
+ exports.RpcClientImpl = RpcClientImpl;
96
+ //# sourceMappingURL=RpcClientImpl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcClientImpl.js","sourceRoot":"","sources":["../../src/client/RpcClientImpl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import WebSocket from "ws";
2
+ export declare class WebSocketConnection {
3
+ private readonly url;
4
+ private readonly clientId;
5
+ private readonly options;
6
+ private readonly consume;
7
+ private readonly onConnected;
8
+ constructor(url: string, clientId: string, options: {
9
+ reconnectDelay: number;
10
+ errorDelayMaxDuration: number;
11
+ pingInterval: number;
12
+ }, consume: (itemName: string, parameters: unknown[], data: unknown) => void, onConnected: () => void);
13
+ close(): Promise<void>;
14
+ /**
15
+ * Connect to the server, on each disconnect try to disconnect.
16
+ * Resolves at first successful connect. Reconnection loop continues even after resolution
17
+ * Never rejects
18
+ */
19
+ connect(): Promise<void>;
20
+ isConnected(): boolean;
21
+ /**
22
+ * Connect this to server
23
+ *
24
+ * Resolves on successful connection, rejects on connection error or connection timeout
25
+ */
26
+ private establishConnection;
27
+ private socket;
28
+ private disconnectedMark;
29
+ private pingTimeout;
30
+ private heartbeat;
31
+ private receiveSocketMessage;
32
+ _webSocket(): WebSocket | null;
33
+ }
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebSocketConnection = void 0;
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const logger_js_1 = require("../logger.js");
9
+ const json_js_1 = require("../utils/json.js");
10
+ const promises_js_1 = require("../utils/promises.js");
11
+ class WebSocketConnection {
12
+ constructor(url, clientId, options, consume, onConnected) {
13
+ this.url = url;
14
+ this.clientId = clientId;
15
+ this.options = options;
16
+ this.consume = consume;
17
+ this.onConnected = onConnected;
18
+ this.socket = null;
19
+ this.disconnectedMark = true;
20
+ this.pingTimeout = null;
21
+ this.url = url;
22
+ this.clientId = clientId;
23
+ }
24
+ async close() {
25
+ this.disconnectedMark = true;
26
+ if (this.socket) {
27
+ this.socket.terminate();
28
+ this.socket = null;
29
+ }
30
+ if (this.pingTimeout) {
31
+ clearTimeout(this.pingTimeout);
32
+ }
33
+ }
34
+ /**
35
+ * Connect to the server, on each disconnect try to disconnect.
36
+ * Resolves at first successful connect. Reconnection loop continues even after resolution
37
+ * Never rejects
38
+ */
39
+ connect() {
40
+ if (this.socket || !this.disconnectedMark)
41
+ return Promise.resolve();
42
+ this.disconnectedMark = false;
43
+ return new Promise(async (resolve) => {
44
+ let onFirstConnection = resolve;
45
+ let errorDelay = 0;
46
+ while (true) {
47
+ // connect, and wait for ...
48
+ await new Promise((resolve) => {
49
+ // 1. ...disconnected
50
+ const connectionPromise = this.establishConnection(resolve);
51
+ connectionPromise.then(() => {
52
+ // first reconnect after successful connection is done without delay
53
+ errorDelay = 0;
54
+ // signal about first connection
55
+ onFirstConnection();
56
+ onFirstConnection = () => { };
57
+ }, () => {
58
+ // 2. ... unable to establish connection
59
+ resolve();
60
+ });
61
+ });
62
+ // disconnected while connecting?
63
+ if (this.disconnectedMark) {
64
+ return;
65
+ }
66
+ await (0, promises_js_1.adelay)(this.options.reconnectDelay + errorDelay);
67
+ // disconnected while waiting?
68
+ if (this.disconnectedMark) {
69
+ return;
70
+ }
71
+ errorDelay = Math.round(Math.random() * this.options.errorDelayMaxDuration);
72
+ }
73
+ });
74
+ }
75
+ isConnected() {
76
+ return this.socket !== null;
77
+ }
78
+ /**
79
+ * Connect this to server
80
+ *
81
+ * Resolves on successful connection, rejects on connection error or connection timeout
82
+ */
83
+ async establishConnection(onDisconnected) {
84
+ return new Promise(async (resolve, reject) => {
85
+ try {
86
+ const socket = new ws_1.default(this.url, this.clientId);
87
+ let connected = false;
88
+ socket.on("open", () => {
89
+ this.socket = socket;
90
+ connected = true;
91
+ resolve();
92
+ this.heartbeat();
93
+ this.onConnected();
94
+ });
95
+ socket.on("ping", () => {
96
+ this.heartbeat();
97
+ });
98
+ socket.on("close", () => {
99
+ this.socket = null;
100
+ if (connected) {
101
+ onDisconnected();
102
+ }
103
+ if (this.pingTimeout) {
104
+ clearTimeout(this.pingTimeout);
105
+ }
106
+ });
107
+ socket.on("error", (e) => {
108
+ if (!connected) {
109
+ reject(e);
110
+ }
111
+ logger_js_1.log.warn("WS connection error", e.message);
112
+ try {
113
+ socket.close();
114
+ }
115
+ catch (e) {
116
+ // ignore
117
+ }
118
+ });
119
+ socket.on("message", (message) => {
120
+ this.receiveSocketMessage(message);
121
+ });
122
+ }
123
+ catch (e) {
124
+ reject(e);
125
+ }
126
+ });
127
+ }
128
+ heartbeat() {
129
+ if (this.pingTimeout) {
130
+ clearTimeout(this.pingTimeout);
131
+ }
132
+ this.pingTimeout = setTimeout(() => {
133
+ this.socket?.terminate();
134
+ }, this.options.pingInterval * 1.5);
135
+ }
136
+ async receiveSocketMessage(rawMessage) {
137
+ try {
138
+ const msg = rawMessage.toString();
139
+ const [itemName, data, ...parameters] = (0, json_js_1.safeParseJson)(msg);
140
+ this.consume(itemName, parameters, data);
141
+ }
142
+ catch (e) {
143
+ logger_js_1.log.warn("Invalid message received", e);
144
+ }
145
+ }
146
+ // test-only
147
+ _webSocket() {
148
+ return this.socket;
149
+ }
150
+ }
151
+ exports.WebSocketConnection = WebSocketConnection;
152
+ //# sourceMappingURL=WebSocketConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketConnection.js","sourceRoot":"","sources":["../../src/client/WebSocketConnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { RpcContext, Services } from "../rpc.js";
2
+ import { ServicesWithSubscriptions } from "./remote.js";
3
+ import WebSocket from "ws";
4
+ import { Middleware } from "../utils/middleware.js";
5
+ export type RpcClient = {
6
+ isConnected(): boolean;
7
+ close(): Promise<void>;
8
+ _allSubscriptions(): Array<any[]>;
9
+ _webSocket(): WebSocket | null;
10
+ };
11
+ export type ConsumeServicesOptions = {
12
+ callTimeout: number;
13
+ subscribe: boolean;
14
+ reconnectDelay: number;
15
+ errorDelayMaxDuration: number;
16
+ pingInterval: number;
17
+ middleware: Middleware<RpcContext>[];
18
+ };
19
+ export declare function consumeServices<S extends Services<S>>(url: string, overrideOptions?: Partial<ConsumeServicesOptions>): Promise<{
20
+ client: RpcClient;
21
+ remote: ServicesWithSubscriptions<S>;
22
+ }>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.consumeServices = void 0;
4
+ const RpcClientImpl_js_1 = require("./RpcClientImpl.js");
5
+ async function consumeServices(url, overrideOptions = {}) {
6
+ if (url.endsWith("/")) {
7
+ throw new Error("URL must not end with /");
8
+ }
9
+ const options = {
10
+ ...defaultOptions,
11
+ ...overrideOptions,
12
+ };
13
+ const client = new RpcClientImpl_js_1.RpcClientImpl(url, options);
14
+ return {
15
+ client,
16
+ remote: client.createRemote(),
17
+ };
18
+ }
19
+ exports.consumeServices = consumeServices;
20
+ const defaultOptions = {
21
+ callTimeout: 5 * 1000,
22
+ subscribe: true,
23
+ reconnectDelay: 0,
24
+ errorDelayMaxDuration: 15 * 1000,
25
+ pingInterval: 30 * 1000, // should be in-sync with server
26
+ middleware: [],
27
+ };
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAGA,yDAAgD;AAqBzC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,kBAAmD,EAAE;IAKrD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,OAAO,GAAG;QACd,GAAG,cAAc;QACjB,GAAG,eAAe;KACnB,CAAA;IAED,MAAM,MAAM,GAAG,IAAI,gCAAa,CAAI,GAAG,EAAE,OAAO,CAAC,CAAA;IAEjD,OAAO;QACL,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE;KAC9B,CAAA;AACH,CAAC;AAtBD,0CAsBC;AAED,MAAM,cAAc,GAA2B;IAC7C,WAAW,EAAE,CAAC,GAAG,IAAI;IACrB,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,CAAC;IACjB,qBAAqB,EAAE,EAAE,GAAG,IAAI;IAChC,YAAY,EAAE,EAAE,GAAG,IAAI,EAAE,gCAAgC;IACzD,UAAU,EAAE,EAAE;CACf,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { CallOptions, Consumer, RemoteFunction, Services } from "../rpc.js";
2
+ export declare function createRemote<S extends Services<S>>(hooks: RemoteHooks, name?: string): ServicesWithSubscriptions<S>;
3
+ export type RemoteHooks = {
4
+ call(itemName: string, parameters: unknown[], callOptions?: CallOptions): Promise<unknown>;
5
+ subscribe(itemName: string, parameters: unknown[], consumer: (d: unknown) => void, callOptions?: CallOptions): Promise<void>;
6
+ unsubscribe(itemName: string, parameters: unknown[], consumer: (d: unknown) => void, callOptions?: CallOptions): Promise<void>;
7
+ };
8
+ export type AddParameters<TFunction extends (...args: any) => any, TParameters extends [...args: any]> = (...args: [...Parameters<TFunction>, ...TParameters]) => ReturnType<TFunction>;
9
+ export type ServicesWithSubscriptions<T extends Services<T>> = {
10
+ [K in keyof T]: T[K] extends RemoteFunction ? AddParameters<T[K], [CallOptions?]> & {
11
+ subscribe(consumer: Consumer<T[K]>, ...parameters: [...Parameters<T[K]>, CallOptions?]): Promise<void>;
12
+ unsubscribe(consumer: Consumer<T[K]>, ...parameters: [...Parameters<T[K]>, CallOptions?]): Promise<void>;
13
+ } : T[K] extends object ? ServicesWithSubscriptions<T[K]> : never;
14
+ };