@nomalism-com/api 0.45.6 → 0.45.7

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/dist/index.js CHANGED
@@ -127,6 +127,132 @@ __export(main_exports, {
127
127
  import axios, { AxiosHeaders } from "axios";
128
128
  import Nomalism from "@nomalism-com/types";
129
129
 
130
+ // src/modules/view/webSocket.ts
131
+ var CLOSE_AUTH_REJECTED = 4401;
132
+ var CLOSE_AUTH_UNAVAILABLE = 4503;
133
+ var PING_INTERVAL_MS = 25e3;
134
+ var MAX_BACKOFF_MS = 3e4;
135
+ var BASE_BACKOFF_MS = 1e3;
136
+ var Service = class {
137
+ constructor({ route }) {
138
+ this.route = route;
139
+ }
140
+ openChatSocket({
141
+ token,
142
+ onEvent,
143
+ onOpen,
144
+ onReconnect,
145
+ onClose,
146
+ onAuthUnverified
147
+ }) {
148
+ let ws = null;
149
+ let attempts = 0;
150
+ let opensSoFar = 0;
151
+ let pingTimer = null;
152
+ let reconnectTimer = null;
153
+ let closedByCaller = false;
154
+ const subprotocol = `bearer.${token}`;
155
+ const stopPing = () => {
156
+ if (pingTimer !== null) {
157
+ window.clearInterval(pingTimer);
158
+ pingTimer = null;
159
+ }
160
+ };
161
+ const startPing = () => {
162
+ stopPing();
163
+ pingTimer = setInterval(() => {
164
+ if (ws?.readyState === WebSocket.OPEN) {
165
+ try {
166
+ ws.send(JSON.stringify({ type: "ping" }));
167
+ } catch (err) {
168
+ console.warn("[chatSocket] ping failed", err);
169
+ }
170
+ }
171
+ }, PING_INTERVAL_MS);
172
+ };
173
+ const scheduleReconnect = () => {
174
+ if (closedByCaller) return;
175
+ const delay = Math.min(MAX_BACKOFF_MS, BASE_BACKOFF_MS * 2 ** Math.min(attempts, 6));
176
+ attempts += 1;
177
+ reconnectTimer = setTimeout(connect, delay);
178
+ };
179
+ const connect = () => {
180
+ if (closedByCaller) return;
181
+ try {
182
+ ws = new WebSocket(this.route, [subprotocol]);
183
+ } catch (err) {
184
+ console.error("[chatSocket] WebSocket constructor threw", err);
185
+ scheduleReconnect();
186
+ return;
187
+ }
188
+ ws.onopen = () => {
189
+ attempts = 0;
190
+ opensSoFar += 1;
191
+ startPing();
192
+ if (opensSoFar === 1) {
193
+ onOpen?.();
194
+ } else {
195
+ onReconnect?.();
196
+ }
197
+ };
198
+ ws.onmessage = (msg) => {
199
+ let payload;
200
+ try {
201
+ payload = JSON.parse(msg.data);
202
+ } catch {
203
+ console.warn("[chatSocket] received non-JSON frame", msg.data);
204
+ return;
205
+ }
206
+ if (payload.type === "ping" || payload.type === "pong") return;
207
+ try {
208
+ onEvent(payload);
209
+ } catch (err) {
210
+ console.error("[chatSocket] event handler threw", err, payload);
211
+ }
212
+ };
213
+ ws.onerror = (err) => {
214
+ console.warn("[chatSocket] error", err);
215
+ };
216
+ ws.onclose = (e) => {
217
+ stopPing();
218
+ ws = null;
219
+ onClose?.();
220
+ if (e.code === CLOSE_AUTH_REJECTED) {
221
+ console.error("[chatSocket] auth rejected by server, not reconnecting");
222
+ closedByCaller = true;
223
+ return;
224
+ }
225
+ if (e.code === CLOSE_AUTH_UNAVAILABLE) {
226
+ console.warn("[chatSocket] auth verifier unavailable, retrying");
227
+ attempts = Math.min(attempts, 2);
228
+ onAuthUnverified?.();
229
+ scheduleReconnect();
230
+ return;
231
+ }
232
+ scheduleReconnect();
233
+ };
234
+ };
235
+ connect();
236
+ return {
237
+ close: () => {
238
+ closedByCaller = true;
239
+ if (reconnectTimer !== null) {
240
+ window.clearTimeout(reconnectTimer);
241
+ reconnectTimer = null;
242
+ }
243
+ stopPing();
244
+ if (ws && ws.readyState <= WebSocket.OPEN) {
245
+ try {
246
+ ws.close(1e3, "client unmount");
247
+ } catch {
248
+ }
249
+ }
250
+ ws = null;
251
+ }
252
+ };
253
+ }
254
+ };
255
+
130
256
  // src/modules/user/bankData.ts
131
257
  var bankData_exports = {};
132
258
  __export(bankData_exports, {
@@ -4206,6 +4332,7 @@ var API = class {
4206
4332
  api: this.client,
4207
4333
  route: `${this.services[service]}${module}/`
4208
4334
  });
4335
+ this.WebSocket = new Service(getModuleParams("view", "ws"));
4209
4336
  this.BankData = new Repository(getModuleParams("users", Nomalism.BankData.Route));
4210
4337
  this.Client = new Repository2(getModuleParams("users", Nomalism.Client.Route));
4211
4338
  this.ClientType = new Repository3(getModuleParams("users", Nomalism.ClientType.Route));
package/dist/main.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AxiosInstance } from 'axios';
2
+ import WebSocketClass from './modules/view/webSocket';
2
3
  import BankDataClass from './modules/user/bankData';
3
4
  import ClientClass from './modules/user/clients';
4
5
  import ClientTypeClass from './modules/user/clientType';
@@ -254,6 +255,7 @@ export declare class API {
254
255
  processEnvironment: IEnvironment;
255
256
  client: AxiosInstance;
256
257
  services: Record<IService, string>;
258
+ WebSocket: WebSocketClass;
257
259
  BankData: BankDataClass;
258
260
  Client: ClientClass;
259
261
  ClientType: ClientTypeClass;
@@ -0,0 +1,58 @@
1
+ import type Nomalism from '@nomalism-com/types';
2
+ import type { IModuleConstructor } from '../../main';
3
+ export type ChatSocketEvent = {
4
+ type: 'chat.translation.updated';
5
+ chat_id: string;
6
+ translation: string;
7
+ target_language_id: string;
8
+ } | {
9
+ type: 'chat.message.created';
10
+ balloon: Nomalism.Chat.IChatBalloon;
11
+ } | {
12
+ type: 'chat.message.updated';
13
+ chat_id: string;
14
+ patch: Partial<NonNullable<Nomalism.Chat.IChatBalloon['chat']>>;
15
+ } | {
16
+ type: 'chat.message.deleted';
17
+ chat_id: string;
18
+ } | {
19
+ type: 'chat.file.deleted';
20
+ file_id: string;
21
+ } | {
22
+ type: 'chat.read_state.updated';
23
+ chat_document_header_id: string;
24
+ client_read: boolean;
25
+ chat_id?: string;
26
+ file_id?: string;
27
+ } | {
28
+ type: 'chat.tags.updated';
29
+ chat_document_header_id: string;
30
+ tags: Nomalism.Portal.ITags[];
31
+ } | {
32
+ type: 'persona.updated';
33
+ persona: NonNullable<Nomalism.Portal.IPublicFindBySubscriberId['persona']>;
34
+ } | {
35
+ type: 'document.updated';
36
+ document: Nomalism.Portal.IPublicDocument;
37
+ } | {
38
+ type: 'ping';
39
+ } | {
40
+ type: 'pong';
41
+ };
42
+ interface ChatSocketOptions {
43
+ token: string;
44
+ onEvent: (evt: ChatSocketEvent) => void;
45
+ onOpen?: () => void;
46
+ onReconnect?: () => void;
47
+ onClose?: () => void;
48
+ onAuthUnverified?: () => void;
49
+ }
50
+ interface ChatSocketHandle {
51
+ close: () => void;
52
+ }
53
+ export default class Service {
54
+ route: string;
55
+ constructor({ route }: IModuleConstructor);
56
+ openChatSocket({ token, onEvent, onOpen, onReconnect, onClose, onAuthUnverified, }: ChatSocketOptions): ChatSocketHandle;
57
+ }
58
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nomalism-com/api",
3
3
  "description": "A nomalism API package for performing HTTP requests on API endpoints",
4
- "version": "0.45.6",
4
+ "version": "0.45.7",
5
5
  "author": "Nomalism <it.nomalism@gmail.com> (https://https://nomalism.com/)",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",