@pathscale/wss-adapter 1.0.13 → 2.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/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # @pathscale/wss-adapter
2
+
3
+ WebSocket adapter for PathScale WSS services.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @pathscale/wss-adapter
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import wssAdapter from '@pathscale/wss-adapter';
15
+
16
+ // Configure
17
+ wssAdapter.configure({
18
+ timeout: 30000,
19
+ services: {
20
+ app: {
21
+ remote: 'wss://api.example.com',
22
+ methods: {
23
+ '10001': { name: 'login', parameters: ['username', 'password'] },
24
+ '10002': { name: 'getUserProfile', parameters: ['userId'] },
25
+ },
26
+ onDisconnect: (event) => console.log('Disconnected:', event),
27
+ },
28
+ },
29
+ errors: {
30
+ language: 'en',
31
+ codes: [
32
+ { code: 40001, message: 'Invalid credentials' },
33
+ { code: 40002, message: 'Session expired' },
34
+ ],
35
+ },
36
+ onError: (message) => console.error('Error:', message),
37
+ });
38
+
39
+ // Connect
40
+ const result = await wssAdapter.services.app.connect(['token1', 'token2']);
41
+
42
+ // Call methods
43
+ const profile = await wssAdapter.sessions.app.getUserProfile({ userId: '123' });
44
+ const login = await wssAdapter.sessions.app.login({ username: 'user', password: 'pass' });
45
+
46
+ // Disconnect
47
+ wssAdapter.services.app.disconnect();
48
+ ```
49
+
50
+ ## Configuration Types
51
+
52
+ ```typescript
53
+ interface IConfiguration {
54
+ timeout: number;
55
+ services: Record<string, IServiceConfig>;
56
+ errors: IErrors;
57
+ onError?: (message: string) => void;
58
+ }
59
+
60
+ interface IServiceConfig {
61
+ remote: string;
62
+ methods: Record<string, IMethodInfo>;
63
+ subscriptions?: Record<string, (data: any) => void>;
64
+ onDisconnect?: (event: CloseEvent) => void;
65
+ }
66
+
67
+ interface IErrors {
68
+ language: string;
69
+ codes: IErrorCode[];
70
+ }
71
+ ```
72
+
73
+ ## Subscriptions
74
+
75
+ ```typescript
76
+ services: {
77
+ app: {
78
+ remote: 'wss://api.example.com',
79
+ methods: { /* ... */ },
80
+ subscriptions: {
81
+ 'notifications': (data) => console.log('Notification:', data),
82
+ 'updates': (data) => console.log('Update:', data),
83
+ },
84
+ },
85
+ }
86
+ ```
87
+
88
+ That's it.
@@ -0,0 +1,4 @@
1
+ export { default } from './wss-adapter.js';
2
+ export { default as wssAdapter } from './wss-adapter.js';
3
+ export type { IWssAdapter, IConfiguration, IServiceConfig, IServiceAdapter, IMethodInfo, IErrors, IStore, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,eAAe,EACf,WAAW,EACX,OAAO,EACP,MAAM,GACP,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { default } from './wss-adapter.js';
2
+ export { default as wssAdapter } from './wss-adapter.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,57 @@
1
+ export interface IMethodInfo {
2
+ name: string;
3
+ parameters: string[];
4
+ }
5
+ export interface IServiceConfig {
6
+ remote: string;
7
+ methods: Record<string, IMethodInfo>;
8
+ subscriptions?: Record<string, (data: any) => void>;
9
+ onDisconnect?: (event: CloseEvent) => void;
10
+ }
11
+ export interface IErrorCode {
12
+ code: number;
13
+ message: string;
14
+ }
15
+ export interface IErrors {
16
+ language: string;
17
+ codes: IErrorCode[];
18
+ }
19
+ export interface IConfiguration {
20
+ timeout: number;
21
+ services: Record<string, IServiceConfig>;
22
+ errors: IErrors;
23
+ onError?: (message: string) => void;
24
+ }
25
+ export interface IStore {
26
+ timeout: number;
27
+ errors: IErrors;
28
+ services: Record<string, IServiceConfig>;
29
+ subscriptions: Record<string, Record<string, (data: any) => void>>;
30
+ sequence: {
31
+ value: number;
32
+ getSeq(): number;
33
+ decreaseSeq(): void;
34
+ };
35
+ sessions: Record<string, WebSocket>;
36
+ pendingPromises: Record<number, {
37
+ resolve: (value: any) => void;
38
+ reject: (reason: any) => void;
39
+ toHandler: number;
40
+ methodName: string;
41
+ }>;
42
+ onError?: (message: string) => void;
43
+ }
44
+ export interface IServiceAdapter {
45
+ connect: <T>(payload?: string | string[], remote?: string) => Promise<T>;
46
+ disconnect: () => void;
47
+ }
48
+ export type ServiceName = "app";
49
+ export type ApiMethods = {
50
+ app: Record<string, (params?: any) => Promise<any>>;
51
+ };
52
+ export interface IWssAdapter {
53
+ services: Record<ServiceName, IServiceAdapter>;
54
+ sessions: ApiMethods;
55
+ configure: (configuration: IConfiguration) => void;
56
+ }
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC;IACnE,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,IAAI,MAAM,CAAC;QACjB,WAAW,IAAI,IAAI,CAAC;KACrB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,eAAe,EAAE,MAAM,CACrB,MAAM,EACN;QACE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;QAC9B,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;QAC9B,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CACF,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACzE,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC;AAEhC,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC/C,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,CAAC;CACpD"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { IWssAdapter } from './types.js';
2
+ declare const wssAdapter: IWssAdapter;
3
+ export default wssAdapter;
4
+ //# sourceMappingURL=wss-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wss-adapter.d.ts","sourceRoot":"","sources":["../src/wss-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,WAAW,EAEZ,MAAM,YAAY,CAAC;AACpB,QAAA,MAAM,UAAU,EAAE,WAIjB,CAAC;AAmRF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,203 @@
1
+ const wssAdapter = {
2
+ services: {},
3
+ sessions: {},
4
+ configure() { },
5
+ };
6
+ const store = {
7
+ timeout: 0,
8
+ errors: {
9
+ language: "en",
10
+ codes: [],
11
+ },
12
+ services: {},
13
+ subscriptions: {},
14
+ sequence: {
15
+ value: 1,
16
+ getSeq() {
17
+ store.sequence.value += 1;
18
+ return store.sequence.value;
19
+ },
20
+ decreaseSeq() {
21
+ store.sequence.value -= 1;
22
+ },
23
+ },
24
+ sessions: {},
25
+ pendingPromises: {},
26
+ };
27
+ wssAdapter.configure = (configuration) => {
28
+ const { timeout, services, errors, onError } = configuration;
29
+ store.timeout = timeout;
30
+ store.errors = errors;
31
+ store.services = services;
32
+ if (onError !== undefined) {
33
+ store.onError = onError;
34
+ }
35
+ for (const [serviceName, serviceConfig] of Object.entries(services)) {
36
+ const serviceNameTyped = serviceName;
37
+ wssAdapter.services[serviceNameTyped] = {
38
+ connect: (payload, remote) => connectHandler(serviceName, serviceConfig, payload, remote),
39
+ disconnect: () => disconnectHandler(serviceName),
40
+ };
41
+ if (serviceConfig.subscriptions) {
42
+ store.subscriptions[serviceName] = serviceConfig.subscriptions;
43
+ }
44
+ wssAdapter.sessions[serviceName] = new Proxy({}, {
45
+ get: (_target, methodName) => (payload) => sendHandler(serviceName, serviceConfig, methodName, payload),
46
+ });
47
+ }
48
+ };
49
+ const connectHandler = (serviceName, serviceConfig, payload, remote) => {
50
+ return new Promise((resolve, reject) => {
51
+ if (!payload || !Array.isArray(payload)) {
52
+ reject(new Error("WebSocket protocols required for authentication"));
53
+ return;
54
+ }
55
+ const protocols = payload;
56
+ const wsConnection = new WebSocket(remote || serviceConfig.remote, protocols);
57
+ store.sessions[serviceName] = wsConnection;
58
+ wsConnection.onmessage = (event) => {
59
+ const response = JSON.parse(event.data);
60
+ if (response.type === "Immediate" &&
61
+ response.method === 20000 &&
62
+ response.params?.accessToken) {
63
+ const session = store.sessions[serviceName];
64
+ if (session) {
65
+ session.onmessage = receiveHandler;
66
+ }
67
+ resolve(response.params);
68
+ return;
69
+ }
70
+ if (response.type === "Error" || response.code) {
71
+ const error = store.errors.codes.find((c) => c.code === response.code);
72
+ const errorMsg = response.params || error?.message || response.code;
73
+ if (store.onError) {
74
+ store.onError(String(errorMsg));
75
+ }
76
+ reject(new Error(String(errorMsg)));
77
+ return;
78
+ }
79
+ const session = store.sessions[serviceName];
80
+ if (session) {
81
+ session.onmessage = receiveHandler;
82
+ }
83
+ resolve(response.params);
84
+ };
85
+ wsConnection.onclose = (event) => {
86
+ if (!event.wasClean) {
87
+ reject(new Error(`WebSocket closed unexpectedly (code ${event.code || "unknown"})`));
88
+ }
89
+ serviceConfig.onDisconnect?.(event);
90
+ };
91
+ wsConnection.onerror = (event) => {
92
+ console.error("WebSocket error:", event);
93
+ reject(new Error("WebSocket connection failed"));
94
+ };
95
+ });
96
+ };
97
+ const disconnectHandler = (serviceName) => {
98
+ const session = store.sessions[serviceName];
99
+ if (session) {
100
+ session.close();
101
+ }
102
+ };
103
+ const sendHandler = (serviceName, serviceConfig, methodName, params = {}) => {
104
+ const methodEntry = Object.entries(serviceConfig.methods)
105
+ .map(([code, info]) => ({ code, info }))
106
+ .find(({ info }) => info.name === methodName);
107
+ if (!methodEntry) {
108
+ throw new Error(`method ${methodName} not available in ${serviceName} service`);
109
+ }
110
+ const methodCode = methodEntry.code;
111
+ const methodInfo = serviceConfig.methods[methodCode];
112
+ if (!methodInfo) {
113
+ throw new Error(`method configuration missing for ${methodName} in ${serviceName} service`);
114
+ }
115
+ const paramsArray = methodInfo.parameters.map((paramName) => params[paramName]);
116
+ const payload = {
117
+ method: Number.parseInt(methodCode),
118
+ seq: store.sequence.getSeq(),
119
+ params: paramsArray,
120
+ };
121
+ return new Promise((resolve, reject) => {
122
+ const session = store.sessions[serviceName];
123
+ if (!session) {
124
+ reject(new Error(`No active session for service ${serviceName}`));
125
+ return;
126
+ }
127
+ session.send(JSON.stringify(payload));
128
+ store.pendingPromises[payload.seq] = {
129
+ resolve,
130
+ reject,
131
+ toHandler: setTimeout(() => {
132
+ reject(new Error(`${methodName} took too long, aborting`));
133
+ }, store.timeout),
134
+ methodName,
135
+ };
136
+ });
137
+ };
138
+ const receiveHandler = (event) => {
139
+ const response = JSON.parse(event.data);
140
+ if (response.type === "Immediate" ||
141
+ (response.type === "Error" && response.method) ||
142
+ response.method === 0) {
143
+ const error = response.code ||
144
+ response.params?.success === false ||
145
+ response.params?.error;
146
+ const resolve = (payload) => {
147
+ const executor = store.pendingPromises[response.seq];
148
+ if (executor) {
149
+ clearTimeout(executor.toHandler);
150
+ delete store.pendingPromises[response.seq];
151
+ executor.resolve(payload);
152
+ }
153
+ };
154
+ if (error) {
155
+ onError(response);
156
+ }
157
+ else {
158
+ resolve(response);
159
+ }
160
+ }
161
+ else if (response.type === "Stream") {
162
+ console.log("Stream response:", response);
163
+ }
164
+ };
165
+ function onError(response) {
166
+ const error = store.errors.codes.find((c) => c.code === response.code);
167
+ const params = typeof response.params === "object" && response.params !== null
168
+ ? response.params
169
+ : {};
170
+ const errorMsg = params.reason ||
171
+ params.error ||
172
+ response.params ||
173
+ error?.message ||
174
+ response.code;
175
+ let methodName = "";
176
+ if (response.method) {
177
+ for (const serviceConfig of Object.values(store.services)) {
178
+ const methodKey = response.method.toString();
179
+ const method = serviceConfig.methods[methodKey];
180
+ if (method) {
181
+ methodName = method.name;
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ const fullErrorMsg = methodName
187
+ ? `${methodName}: ${errorMsg}`
188
+ : String(errorMsg);
189
+ if (store.onError) {
190
+ store.onError(fullErrorMsg);
191
+ }
192
+ const executor = store.pendingPromises[response.seq];
193
+ if (executor) {
194
+ clearTimeout(executor.toHandler);
195
+ executor.reject(new Error(`${executor.methodName || ""}: ${errorMsg}`));
196
+ delete store.pendingPromises[response.seq];
197
+ }
198
+ else {
199
+ throw new Error("Unknown request failed");
200
+ }
201
+ }
202
+ export default wssAdapter;
203
+ //# sourceMappingURL=wss-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wss-adapter.js","sourceRoot":"","sources":["../src/wss-adapter.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,GAAgB;IAC9B,QAAQ,EAAE,EAA0C;IACpD,QAAQ,EAAE,EAAgB;IAC1B,SAAS,KAAI,CAAC;CACf,CAAC;AAEF,MAAM,KAAK,GAAW;IACpB,OAAO,EAAE,CAAC;IACV,MAAM,EAAE;QACN,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,EAAE;KACV;IACD,QAAQ,EAAE,EAAE;IACZ,aAAa,EAAE,EAAE;IACjB,QAAQ,EAAE;QACR,KAAK,EAAE,CAAC;QACR,MAAM;YACJ,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;YAC1B,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC9B,CAAC;QACD,WAAW;YACT,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;QAC5B,CAAC;KACF;IACD,QAAQ,EAAE,EAAE;IACZ,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,UAAU,CAAC,SAAS,GAAG,CAAC,aAAa,EAAE,EAAE;IACvC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAE7D,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,KAAK,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpE,MAAM,gBAAgB,GAAG,WAA0B,CAAC;QAEpD,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG;YACtC,OAAO,EAAE,CAAI,OAA2B,EAAE,MAAe,EAAE,EAAE,CAC3D,cAAc,CAAI,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC;YAChE,UAAU,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC;SACjD,CAAC;QAEF,IAAI,aAAa,CAAC,aAAa,EAAE,CAAC;YAChC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,aAAa,CAAC;QACjE,CAAC;QAEA,UAAU,CAAC,QAAgB,CAAC,WAAW,CAAC,GAAG,IAAI,KAAK,CACnD,EAAE,EACF;YACE,GAAG,EACD,CAAC,OAAO,EAAE,UAAkB,EAAE,EAAE,CAAC,CAAC,OAAgC,EAAE,EAAE,CACpE,WAAW,CAAC,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC;SACjE,CACF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACrB,WAAmB,EACnB,aAA6B,EAC7B,OAAsC,EACtC,MAAe,EACf,EAAE;IACF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,OAAmB,CAAC;QAEtC,MAAM,YAAY,GAAG,IAAI,SAAS,CAChC,MAAM,IAAI,aAAa,CAAC,MAAM,EAC9B,SAAS,CACV,CAAC;QACF,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC;QAE3C,YAAY,CAAC,SAAS,GAAG,CAAC,KAAuB,EAAE,EAAE;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAExC,IACE,QAAQ,CAAC,IAAI,KAAK,WAAW;gBAC7B,QAAQ,CAAC,MAAM,KAAK,KAAK;gBACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,EAC5B,CAAC;gBACD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAC5C,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC;gBACrC,CAAC;gBACD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC;gBAEpE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAClB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAClC,CAAC;gBAED,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACpC,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC;YACrC,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC,CAAC;QAEF,YAAY,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC/B,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACpB,MAAM,CACJ,IAAI,KAAK,CACP,uCAAuC,KAAK,CAAC,IAAI,IAAI,SAAS,GAAG,CAClE,CACF,CAAC;YACJ,CAAC;YACD,aAAa,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC;QAEF,YAAY,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC/B,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC;IACJ,CAAC,CAAe,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,EAAE;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAClB,WAAmB,EACnB,aAA6B,EAC7B,UAAkB,EAClB,SAAkC,EAAE,EACpC,EAAE;IACF,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;SACtD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAEhD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,UAAU,UAAU,qBAAqB,WAAW,UAAU,CAC/D,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC;IACpC,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,oCAAoC,UAAU,OAAO,WAAW,UAAU,CAC3E,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAC3C,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CACjC,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;QACnC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;QAC5B,MAAM,EAAE,WAAW;KACpB,CAAC;IAEF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,WAAW,EAAE,CAAC,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG;YACnC,OAAO;YACP,MAAM;YACN,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE;gBACzB,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,UAAU,0BAA0B,CAAC,CAAC,CAAC;YAC7D,CAAC,EAAE,KAAK,CAAC,OAAO,CAAQ;YACxB,UAAU;SACX,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAuB,EAAE,EAAE;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAExC,IACE,QAAQ,CAAC,IAAI,KAAK,WAAW;QAC7B,CAAC,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC;QAC9C,QAAQ,CAAC,MAAM,KAAK,CAAC,EACrB,CAAC;QACD,MAAM,KAAK,GACT,QAAQ,CAAC,IAAI;YACb,QAAQ,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK;YAClC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;QAEzB,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE;YACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,QAAQ,EAAE,CAAC;gBACb,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACjC,OAAO,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC3C,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;SAAM,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC,CAAC;AAUF,SAAS,OAAO,CAAC,QAAmB;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,MAAM,GACV,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI;QAC7D,CAAC,CAAC,QAAQ,CAAC,MAAM;QACjB,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,KAAK;QACZ,QAAQ,CAAC,MAAM;QACf,KAAK,EAAE,OAAO;QACd,QAAQ,CAAC,IAAI,CAAC;IAEhB,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChD,IAAI,MAAM,EAAE,CAAC;gBACX,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;gBACzB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,UAAU;QAC7B,CAAC,CAAC,GAAG,UAAU,KAAK,QAAQ,EAAE;QAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAErB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACrD,IAAI,QAAQ,EAAE,CAAC;QACb,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACjC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,QAAQ,CAAC,UAAU,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,eAAe,UAAU,CAAC"}
package/package.json CHANGED
@@ -1,17 +1,49 @@
1
1
  {
2
2
  "name": "@pathscale/wss-adapter",
3
- "version": "1.0.13",
4
- "description": "Websocket adapter for the Pathscale WSS",
5
- "main": "dist/wssAdapter.js",
6
- "types": "dist/wssAdapter.d.ts",
3
+ "version": "2.0.0",
4
+ "description": "Modern WebSocket adapter for PathScale WSS services",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
7
17
  "scripts": {
8
- "build": "tsc"
18
+ "build": "tsc && tsc-alias",
19
+ "dev": "tsc --watch",
20
+ "clean": "rm -rf dist",
21
+ "prebuild": "npm run clean",
22
+ "test": "echo 'Tests coming soon'",
23
+ "lint": "biome check .",
24
+ "format": "biome format . --write",
25
+ "commit": "cz",
26
+ "prepare": "husky"
27
+ },
28
+ "lint-staged": {
29
+ "*.{ts,js,json}": [
30
+ "biome check --apply"
31
+ ]
9
32
  },
33
+ "config": {
34
+ "commitizen": {
35
+ "path": "@commitlint/cz-commitlint"
36
+ }
37
+ },
38
+ "keywords": [
39
+ "websocket",
40
+ "pathscale",
41
+ "wss",
42
+ "adapter",
43
+ "client"
44
+ ],
10
45
  "author": "PathScale",
11
46
  "license": "MIT",
12
- "devDependencies": {
13
- "typescript": "^4.5.5"
14
- },
15
47
  "repository": {
16
48
  "type": "git",
17
49
  "url": "git+https://github.com/pathscale/wss-adapter.git"
@@ -19,5 +51,20 @@
19
51
  "bugs": {
20
52
  "url": "https://github.com/pathscale/wss-adapter/issues"
21
53
  },
22
- "homepage": "https://github.com/pathscale/wss-adapter#readme"
23
- }
54
+ "homepage": "https://github.com/pathscale/wss-adapter#readme",
55
+ "devDependencies": {
56
+ "@commitlint/cli": "^19.0.3",
57
+ "@commitlint/config-conventional": "^19.0.3",
58
+ "@commitlint/cz-commitlint": "^19.8.1",
59
+ "@types/node": "^22.15.17",
60
+ "biome": "^0.3.3",
61
+ "commitizen": "^4.3.0",
62
+ "husky": "^9.1.7",
63
+ "lint-staged": "^16.0.0",
64
+ "tsc-alias": "^1.8.10",
65
+ "typescript": "^5.7.2"
66
+ },
67
+ "engines": {
68
+ "node": ">=18.0.0"
69
+ }
70
+ }
@@ -1,68 +0,0 @@
1
- interface IService {
2
- remote: string;
3
- methods: {
4
- [methodCode: string]: {
5
- name: string;
6
- parameters: string[];
7
- };
8
- };
9
- }
10
- declare type ISubscriptions = Record<string, unknown>;
11
- interface IServiceConfig extends IService {
12
- subscriptions?: ISubscriptions;
13
- onDisconnect: (event: {
14
- code: number;
15
- reason: string;
16
- wasClean: boolean;
17
- }) => void | null;
18
- }
19
- interface IServices {
20
- [serviceName: string]: IServiceConfig;
21
- }
22
- interface IErrors {
23
- [errorCode: number]: string;
24
- }
25
- interface IConfiguration {
26
- timeout: number;
27
- services: IServices;
28
- errors: IErrors;
29
- }
30
- interface IServiceConnect {
31
- connect<T>(payload: string | string[] | undefined, remote?: string): Promise<T>;
32
- disconnect: () => void;
33
- }
34
- interface IWssAdapter {
35
- services: {
36
- [serviceName: string]: IServiceConnect;
37
- };
38
- sessions: {
39
- [serviceName: string]: Record<string, <Response, Params = {}>(payload?: Params) => Promise<Response>>;
40
- };
41
- configure: (configuration: IConfiguration) => void;
42
- }
43
- interface ISequence {
44
- value: number;
45
- getSeq: () => number;
46
- decreaseSeq: () => void;
47
- }
48
- interface ISessions {
49
- [serviceName: string]: WebSocket;
50
- }
51
- interface IPendingPromises {
52
- [seq: number]: {
53
- resolve: (payload: unknown) => void;
54
- reject: (error: Error) => void;
55
- toHandler: ReturnType<typeof setTimeout>;
56
- methodName: string;
57
- };
58
- }
59
- interface IStore {
60
- timeout: number;
61
- errors: IErrors;
62
- services: IServices;
63
- sequence: ISequence;
64
- sessions: ISessions;
65
- subscriptions: ISubscriptions;
66
- pendingPromises: IPendingPromises;
67
- }
68
- export { IStore, IWssAdapter, IServiceConfig, IConfiguration, IErrors, IServices, IService, };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +0,0 @@
1
- import { IWssAdapter } from './types';
2
- declare const wssAdapter: IWssAdapter;
3
- export default wssAdapter;
@@ -1,174 +0,0 @@
1
- "use strict";
2
- /* eslint-disable compat/compat */
3
- /* eslint-disable promise/avoid-new */
4
- /* eslint-disable @typescript-eslint/no-empty-function */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- var wssAdapter = {
7
- services: {},
8
- sessions: {},
9
- configure: function () { },
10
- };
11
- var store = {
12
- timeout: 0,
13
- errors: {},
14
- services: {},
15
- subscriptions: {},
16
- sequence: {
17
- value: 1,
18
- getSeq: function () {
19
- store.sequence.value += 1;
20
- return store.sequence.value;
21
- },
22
- decreaseSeq: function () {
23
- store.sequence.value -= 1;
24
- },
25
- },
26
- sessions: {},
27
- pendingPromises: {},
28
- };
29
- wssAdapter.configure = function (configuration) {
30
- var timeout = configuration.timeout, services = configuration.services, errors = configuration.errors;
31
- // save some stuff for later retrieval
32
- store.timeout = timeout;
33
- store.errors = errors;
34
- store.services = services;
35
- var _loop_1 = function (serviceName, serviceConfig) {
36
- // construct services objects with two simple functions
37
- // intended use: `wssAdapter.services.admin.connect([1, 2, 3])` or `wssAdapter.services.auth.connect([1, 2, 3])`
38
- wssAdapter.services[serviceName] = {
39
- connect: function (payload, remote) {
40
- return connectHandler(serviceName, serviceConfig, payload, remote);
41
- },
42
- disconnect: function () { return disconnectHandler(serviceName); },
43
- };
44
- if (serviceConfig.subscriptions) {
45
- store.subscriptions[serviceName] = serviceConfig.subscriptions;
46
- }
47
- // construct sessions objects that contain a proxy so you can ask unknown property
48
- // intended use: `wssAdapter.sessions.admin.updatePassword({ newPassword: 'hotdog6737637' })`
49
- wssAdapter.sessions[serviceName] = new Proxy({}, {
50
- get: function (target, methodName) { return function (payload) {
51
- return sendHandler(serviceName, serviceConfig, methodName, payload);
52
- }; },
53
- });
54
- };
55
- for (var _i = 0, _a = Object.entries(services); _i < _a.length; _i++) {
56
- var _b = _a[_i], serviceName = _b[0], serviceConfig = _b[1];
57
- _loop_1(serviceName, serviceConfig);
58
- }
59
- };
60
- var connectHandler = function (serviceName, serviceConfig, payload, remote) {
61
- return new Promise(function (resolve, reject) {
62
- store.sessions[serviceName] = new WebSocket(remote || serviceConfig.remote, payload);
63
- store.sessions[serviceName].onmessage = function (event) {
64
- var _a;
65
- var response = JSON.parse(event.data);
66
- console.log(response);
67
- if (response.params.error) {
68
- reject(new Error((_a = store.errors[response.params.error]) !== null && _a !== void 0 ? _a : response.params.error));
69
- return;
70
- }
71
- store.sessions[serviceName].onmessage = receiveHandler;
72
- resolve(response.params);
73
- };
74
- store.sessions[serviceName].onclose = function (event) {
75
- var _a;
76
- (_a = serviceConfig.onDisconnect) === null || _a === void 0 ? void 0 : _a.call(serviceConfig, event);
77
- reject(new Error("code: ".concat(event.code, ", reason: ").concat(event.reason, ", wasClean: ").concat(event.wasClean)));
78
- };
79
- });
80
- };
81
- var disconnectHandler = function (serviceName) {
82
- var _a;
83
- (_a = store.sessions[serviceName]) === null || _a === void 0 ? void 0 : _a.close();
84
- };
85
- var sendHandler = function (serviceName, serviceConfig, methodName, params) {
86
- var _a;
87
- if (params === void 0) { params = {}; }
88
- var methodCode = (_a = Object.entries(serviceConfig.methods)
89
- .map(function (_a) {
90
- var code = _a[0], info = _a[1];
91
- return ({ code: code, info: info });
92
- })
93
- .find(function (_a) {
94
- var info = _a.info;
95
- return info.name === methodName;
96
- })) === null || _a === void 0 ? void 0 : _a.code;
97
- if (!methodCode) {
98
- throw new Error("method ".concat(methodName, " not available in ").concat(serviceName, " service"));
99
- }
100
- var payload = {
101
- method: Number.parseInt(methodCode),
102
- seq: store.sequence.getSeq(),
103
- params: params,
104
- };
105
- console.log("".concat(serviceName, "::").concat(methodName, " sends:"), payload);
106
- return new Promise(function (resolve, reject) {
107
- store.sessions[serviceName].send(JSON.stringify(payload));
108
- // save executor so that when response for this request comes the promise can be resolved
109
- store.pendingPromises[payload.seq] = {
110
- resolve: resolve,
111
- reject: reject,
112
- toHandler: setTimeout(function () {
113
- reject(new Error(methodName + ' took to long, aborting'));
114
- }, store.timeout),
115
- methodName: methodName,
116
- };
117
- });
118
- };
119
- var receiveHandler = function (event) {
120
- var _a;
121
- var response = JSON.parse(event.data);
122
- if (response.method || response.method === 0) {
123
- console.log("app::".concat(((_a = store.pendingPromises[response.seq]) === null || _a === void 0 ? void 0 : _a.methodName) || response.method, " got:"), response);
124
- var error = response.method === 0 || response.params.error;
125
- var done = response.method.toString().endsWith('1');
126
- var resolve = function (payload, code) {
127
- var executor = store.pendingPromises[response.seq];
128
- clearTimeout(store.pendingPromises[response.seq].toHandler);
129
- delete store.pendingPromises[response.seq];
130
- executor.resolve(payload);
131
- };
132
- // handle error
133
- if (error) {
134
- onError(response);
135
- }
136
- else if (done) {
137
- var code = response.method - 1;
138
- resolve(response, code);
139
- }
140
- }
141
- else if (response.resource) {
142
- var resource = response.resource.split('@')[0];
143
- //@ts-ignore
144
- var executor = store.subscriptions.app[resource];
145
- executor === null || executor === void 0 ? void 0 : executor(response);
146
- }
147
- };
148
- function onError(response) {
149
- var _a, _b;
150
- var errorCode = response.params.error;
151
- var errorMsg = (_a = store.errors[errorCode]) !== null && _a !== void 0 ? _a : errorCode;
152
- if ([45349638, 45349637].includes(errorCode)) {
153
- store.sequence.decreaseSeq();
154
- }
155
- // if there was only one executor saved in store.pendingPromises, then it was that request that failed
156
- if (Object.keys(store.pendingPromises).length === 1) {
157
- var onlyKey = Number.parseInt(Object.keys(store.pendingPromises)[0]);
158
- clearTimeout(store.pendingPromises[onlyKey].toHandler);
159
- store.pendingPromises[onlyKey].reject(new Error(errorMsg));
160
- console.error(store.pendingPromises[onlyKey].methodName + ' failed');
161
- delete store.pendingPromises[onlyKey];
162
- }
163
- else if (response.seq > 1 && store.pendingPromises[response.seq]) {
164
- var executor = store.pendingPromises[response.seq];
165
- clearTimeout(executor.toHandler);
166
- executor.reject(new Error("".concat((_b = executor.methodName) !== null && _b !== void 0 ? _b : '', ": ").concat(errorCode || JSON.stringify(response.params))));
167
- delete store.pendingPromises[response.seq];
168
- }
169
- // if there were more than one, there is no way of knowing who failed
170
- else {
171
- throw new Error('Unkown request failed');
172
- }
173
- }
174
- exports.default = wssAdapter;
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es5",
4
- "module": "commonjs",
5
- "lib": ["es2017", "es7", "es6", "dom"],
6
- "declaration": true,
7
- "outDir": "dist",
8
- "strict": true,
9
- "esModuleInterop": true
10
- },
11
- "exclude": [
12
- "node_modules",
13
- "dist"
14
- ]
15
- }
package/types/index.ts DELETED
@@ -1,84 +0,0 @@
1
- interface IService {
2
- remote: string
3
- methods: {
4
- [methodCode: string]: {
5
- name: string
6
- parameters: string[]
7
- }
8
- }
9
- }
10
-
11
- type ISubscriptions = Record<string, unknown>
12
-
13
- interface IServiceConfig extends IService {
14
- subscriptions?: ISubscriptions
15
- onDisconnect: (event: {
16
- code: number
17
- reason: string
18
- wasClean: boolean
19
- }) => void | null
20
- }
21
- interface IServices {
22
- [serviceName: string]: IServiceConfig
23
- }
24
- interface IErrors {
25
- [errorCode: number]: string
26
- }
27
- interface IConfiguration {
28
- timeout: number
29
- services: IServices
30
- errors: IErrors
31
- }
32
- interface IServiceConnect {
33
- connect<T>(
34
- payload: string | string[] | undefined,
35
- remote?: string
36
- ): Promise<T>
37
- disconnect: () => void
38
- }
39
- interface IWssAdapter {
40
- services: {
41
- [serviceName: string]: IServiceConnect
42
- }
43
- sessions: {
44
- [serviceName: string]: Record<
45
- string,
46
- <Response, Params = {}>(payload?: Params) => Promise<Response>
47
- >
48
- }
49
- configure: (configuration: IConfiguration) => void
50
- }
51
- interface ISequence {
52
- value: number
53
- getSeq: () => number
54
- decreaseSeq: () => void
55
- }
56
- interface ISessions {
57
- [serviceName: string]: WebSocket
58
- }
59
- interface IPendingPromises {
60
- [seq: number]: {
61
- resolve: (payload: unknown) => void
62
- reject: (error: Error) => void
63
- toHandler: ReturnType<typeof setTimeout>
64
- methodName: string
65
- }
66
- }
67
- interface IStore {
68
- timeout: number
69
- errors: IErrors
70
- services: IServices
71
- sequence: ISequence
72
- sessions: ISessions
73
- subscriptions: ISubscriptions
74
- pendingPromises: IPendingPromises
75
- }
76
- export {
77
- IStore,
78
- IWssAdapter,
79
- IServiceConfig,
80
- IConfiguration,
81
- IErrors,
82
- IServices,
83
- IService,
84
- }
package/wssAdapter.ts DELETED
@@ -1,236 +0,0 @@
1
- /* eslint-disable compat/compat */
2
- /* eslint-disable promise/avoid-new */
3
- /* eslint-disable @typescript-eslint/no-empty-function */
4
-
5
- import { IStore, IWssAdapter, IServiceConfig } from './types'
6
-
7
- const wssAdapter: IWssAdapter = {
8
- services: {},
9
- sessions: {},
10
- configure() {},
11
- }
12
-
13
- const store: IStore = {
14
- timeout: 0,
15
- errors: {},
16
- services: {},
17
- subscriptions: {},
18
-
19
- sequence: {
20
- value: 1,
21
- getSeq() {
22
- store.sequence.value += 1
23
- return store.sequence.value
24
- },
25
- decreaseSeq() {
26
- store.sequence.value -= 1
27
- },
28
- },
29
-
30
- sessions: {},
31
- pendingPromises: {},
32
- }
33
-
34
- wssAdapter.configure = (configuration) => {
35
- const { timeout, services, errors } = configuration
36
-
37
- // save some stuff for later retrieval
38
- store.timeout = timeout
39
- store.errors = errors
40
- store.services = services
41
-
42
- for (const [serviceName, serviceConfig] of Object.entries(services)) {
43
- // construct services objects with two simple functions
44
- // intended use: `wssAdapter.services.admin.connect([1, 2, 3])` or `wssAdapter.services.auth.connect([1, 2, 3])`
45
- wssAdapter.services[serviceName] = {
46
- connect: <T>(payload: string | string[] | undefined, remote?: string) =>
47
- connectHandler<T>(serviceName, serviceConfig, payload, remote),
48
- disconnect: () => disconnectHandler(serviceName),
49
- }
50
-
51
- if (serviceConfig.subscriptions) {
52
- store.subscriptions[serviceName] = serviceConfig.subscriptions
53
- }
54
-
55
- // construct sessions objects that contain a proxy so you can ask unknown property
56
- // intended use: `wssAdapter.sessions.admin.updatePassword({ newPassword: 'hotdog6737637' })`
57
- wssAdapter.sessions[serviceName] = new Proxy(
58
- {},
59
- {
60
- get:
61
- (target, methodName: string) => (payload: Record<string, unknown>) =>
62
- sendHandler(serviceName, serviceConfig, methodName, payload),
63
- }
64
- )
65
- }
66
- }
67
-
68
- const connectHandler = <T>(
69
- serviceName: string,
70
- serviceConfig: IServiceConfig,
71
- payload: string | string[] | undefined,
72
- remote?: string
73
- ) => {
74
- return new Promise((resolve, reject) => {
75
- store.sessions[serviceName] = new WebSocket(
76
- remote || serviceConfig.remote,
77
- payload
78
- )
79
-
80
- store.sessions[serviceName].onmessage = function (event: { data: string }) {
81
- const response = JSON.parse(event.data)
82
- console.log(response)
83
-
84
- if (response.params.error) {
85
- reject(
86
- new Error(
87
- store.errors[response.params.error] ?? response.params.error
88
- )
89
- )
90
- return
91
- }
92
-
93
- store.sessions[serviceName].onmessage = receiveHandler
94
- resolve(response.params)
95
- }
96
-
97
- store.sessions[serviceName].onclose = (event) => {
98
- serviceConfig.onDisconnect?.(event)
99
-
100
- reject(
101
- new Error(
102
- `code: ${event.code}, reason: ${event.reason}, wasClean: ${event.wasClean}`
103
- )
104
- )
105
- }
106
- }) as Promise<T>
107
- }
108
-
109
- const disconnectHandler = (serviceName: string) => {
110
- store.sessions[serviceName]?.close()
111
- }
112
-
113
- const sendHandler = (
114
- serviceName: string,
115
- serviceConfig: IServiceConfig,
116
- methodName: string,
117
- params: Record<string, unknown> = {}
118
- ) => {
119
- const methodCode = Object.entries(serviceConfig.methods)
120
- .map(([code, info]) => ({ code, info }))
121
- .find(({ info }) => info.name === methodName)?.code
122
-
123
- if (!methodCode) {
124
- throw new Error(
125
- `method ${methodName} not available in ${serviceName} service`
126
- )
127
- }
128
-
129
- const payload = {
130
- method: Number.parseInt(methodCode),
131
- seq: store.sequence.getSeq(),
132
- params: params,
133
- }
134
-
135
- console.log(`${serviceName}::${methodName} sends:`, payload)
136
-
137
- return new Promise((resolve, reject) => {
138
- store.sessions[serviceName].send(JSON.stringify(payload))
139
-
140
- // save executor so that when response for this request comes the promise can be resolved
141
- store.pendingPromises[payload.seq] = {
142
- resolve,
143
- reject,
144
- toHandler: setTimeout(() => {
145
- reject(new Error(methodName + ' took to long, aborting'))
146
- }, store.timeout),
147
- methodName,
148
- }
149
- })
150
- }
151
-
152
- const receiveHandler = (event: { data: string }) => {
153
- const response = JSON.parse(event.data)
154
-
155
- if (response.method || response.method === 0) {
156
- console.log(
157
- `app::${
158
- store.pendingPromises[response.seq]?.methodName || response.method
159
- } got:`,
160
- response
161
- )
162
-
163
- const error = response.method === 0 || response.params.error
164
- const done = response.method.toString().endsWith('1')
165
-
166
- const resolve = (payload: unknown, code: number) => {
167
- const executor = store.pendingPromises[response.seq]
168
- clearTimeout(store.pendingPromises[response.seq].toHandler)
169
- delete store.pendingPromises[response.seq]
170
- executor.resolve(payload)
171
- }
172
-
173
- // handle error
174
- if (error) {
175
- onError(response)
176
- } else if (done) {
177
- const code = response.method - 1
178
- resolve(response, code)
179
- }
180
- } else if (response.resource) {
181
- const resource = response.resource.split('@')[0]
182
- //@ts-ignore
183
- const executor = store.subscriptions.app[resource] as (
184
- payload: unknown
185
- ) => void
186
- executor?.(response)
187
- }
188
- }
189
-
190
- // if it was one of these guys
191
- // 1) protocol violation
192
- // 2) malformed request
193
- // seq must be decreased
194
-
195
- interface IResponse {
196
- params: {
197
- error: number
198
- }
199
- seq: number
200
- }
201
-
202
- function onError(response: IResponse) {
203
- const { error: errorCode } = response.params
204
- const errorMsg = store.errors[errorCode] ?? errorCode
205
-
206
- if ([45349638, 45349637].includes(errorCode)) {
207
- store.sequence.decreaseSeq()
208
- }
209
-
210
- // if there was only one executor saved in store.pendingPromises, then it was that request that failed
211
- if (Object.keys(store.pendingPromises).length === 1) {
212
- const onlyKey = Number.parseInt(Object.keys(store.pendingPromises)[0])
213
- clearTimeout(store.pendingPromises[onlyKey].toHandler)
214
- store.pendingPromises[onlyKey].reject(new Error(errorMsg))
215
- console.error(store.pendingPromises[onlyKey].methodName + ' failed')
216
- delete store.pendingPromises[onlyKey]
217
- } else if (response.seq > 1 && store.pendingPromises[response.seq]) {
218
- const executor = store.pendingPromises[response.seq]
219
-
220
- clearTimeout(executor.toHandler)
221
- executor.reject(
222
- new Error(
223
- `${executor.methodName ?? ''}: ${
224
- errorCode || JSON.stringify(response.params)
225
- }`
226
- )
227
- )
228
- delete store.pendingPromises[response.seq]
229
- }
230
- // if there were more than one, there is no way of knowing who failed
231
- else {
232
- throw new Error('Unkown request failed')
233
- }
234
- }
235
-
236
- export default wssAdapter