@aicore/cocodb-ws-client 1.0.22 → 1.0.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aicore/cocodb-ws-client",
3
- "version": "1.0.22",
3
+ "version": "1.0.25",
4
4
  "description": "Websocket client for cocoDb",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "repository": {
40
40
  "type": "git",
41
- "url": "git+https://github.com/aicore/template-nodejs.git"
41
+ "url": "git+https://github.com/aicore/cocoDbWsClient.git"
42
42
  },
43
43
  "author": "Charly, core.ai",
44
44
  "license": "AGPL-3.0-or-later",
@@ -47,23 +47,23 @@
47
47
  },
48
48
  "homepage": "https://github.com/aicore/cocoDbWsClient#readme",
49
49
  "devDependencies": {
50
- "@commitlint/cli": "19.6.0",
51
- "@commitlint/config-conventional": "19.6.0",
50
+ "@commitlint/cli": "19.8.1",
51
+ "@commitlint/config-conventional": "19.8.1",
52
52
  "c8": "10.1.3",
53
- "chai": "5.1.2",
53
+ "chai": "5.3.3",
54
54
  "cli-color": "2.0.4",
55
55
  "documentation": "14.0.3",
56
- "eslint": "9.16.0",
57
- "glob": "11.0.0",
56
+ "eslint": "9.39.2",
57
+ "glob": "11.1.0",
58
58
  "husky": "9.1.7",
59
- "mocha": "10.8.2"
59
+ "mocha": "11.7.5"
60
60
  },
61
61
  "dependencies": {
62
62
  "@aicore/libcommonutils": "1.0.20",
63
- "ws": "8.18.0"
63
+ "ws": "8.18.3"
64
64
  },
65
65
  "optionalDependencies": {
66
- "bufferutil": "4.0.8",
66
+ "bufferutil": "4.0.9",
67
67
  "utf-8-validate": "6.0.5"
68
68
  }
69
69
  }
package/src/utils/api.js CHANGED
@@ -288,13 +288,16 @@ export function deleteTable(tableName) {
288
288
 
289
289
  /**
290
290
  * do mathematical addition on given json fields by given values in jsonFieldsIncrements
291
+ * conditional operation is also supported.
291
292
  * @param {string} tableName - The name of the table you want to update.
292
293
  * @param {string} documentId - The document id of the document you want to update.
293
294
  * @param {Object} jsonFieldsIncrements - A JSON object with the fields to increment and the amount to
294
295
  * increment them by.
296
+ * @param {string} [condition] - Optional coco query condition of the form "$.cost<35" that must be satisfied
297
+ * for update to happen. See query API for more details on how to write coco query strings.
295
298
  * @returns {Promise} A promise.
296
299
  */
297
- export function mathAdd(tableName, documentId, jsonFieldsIncrements) {
300
+ export function mathAdd(tableName, documentId, jsonFieldsIncrements, condition) {
298
301
  if (isStringEmpty(tableName)) {
299
302
  throw new Error('Please provide valid table name');
300
303
  }
@@ -310,7 +313,8 @@ export function mathAdd(tableName, documentId, jsonFieldsIncrements) {
310
313
  request: {
311
314
  tableName: tableName,
312
315
  documentId: documentId,
313
- jsonFieldsIncrements: jsonFieldsIncrements
316
+ jsonFieldsIncrements: jsonFieldsIncrements,
317
+ condition: condition
314
318
  }
315
319
  });
316
320
  }
@@ -34,6 +34,7 @@ function _checkActivityForHibernation() {
34
34
  return;
35
35
  }
36
36
  if(!client || client.hibernating
37
+ || client.userClosedConnection
37
38
  || !client.connectionEstablished // cant hibernate if connection isnt already established/ is being establised
38
39
  || ID_TO_RESOLVE_REJECT_MAP.size > 0){ // if there are any pending responses, we cant hibernate
39
40
  return;
@@ -91,8 +92,18 @@ function _setupClientAndWaitForClose(connectedCb) {
91
92
  __receiveMessage(data);
92
93
  });
93
94
 
95
+ let terminated = false;
94
96
  function _connectionTerminated(reason) {
97
+ if (terminated) {
98
+ return;
99
+ }
100
+ terminated = true;
101
+
95
102
  console.log(reason);
103
+ // not set bufferRequests = true for unexpected failures.
104
+ // Real connection failures → reject immediately, don't buffer
105
+ // Hibernation → buffer and reconnect transparently
106
+
96
107
  client.connectionEstablished = false;
97
108
  for (let [sequenceNumber, handler] of ID_TO_RESOLVE_REJECT_MAP) {
98
109
  handler.reject(reason);
@@ -100,11 +111,20 @@ function _setupClientAndWaitForClose(connectedCb) {
100
111
  }
101
112
  resolve();
102
113
  }
103
- client.on('close', function () {
104
- // https://websockets.spec.whatwg.org/#eventdef-websocket-error
105
- // https://stackoverflow.com/questions/40084398/is-onclose-always-called-after-onerror-for-websocket
106
- // we do not need to listen for error event as an error event is immediately followed by a close event.
107
- _connectionTerminated('connection closed');
114
+
115
+ client.on('error', function (err) {
116
+ // ECONNREFUSED, ENOTFOUND, TLS errors, etc. can land here
117
+ _connectionTerminated(err);
118
+ });
119
+
120
+ client.on('close', function (code, reasonBuf) {
121
+ // reasonBuf may be a Buffer in ws; keep it simple
122
+ _connectionTerminated(`connection closed (${code})`);
123
+ });
124
+
125
+ // Optional but useful: HTTP-level failures (proxies, 401, 403, 502...)
126
+ client.on('unexpected-response', function (req, res) {
127
+ _connectionTerminated(`unexpected-response: ${res.statusCode}`);
108
128
  });
109
129
  });
110
130
  }
@@ -131,13 +151,14 @@ function _cancelBackoffTimer() {
131
151
  }
132
152
  }
133
153
 
134
- async function _setupAndMaintainConnection(firstConnectionCb, neverConnectedCB) {
154
+ async function _setupAndMaintainConnection(resolveOnFirstConnect, reject) {
135
155
  backoffTimer = null;
136
156
  function connected() {
137
157
  _resetBackoffTime();
138
- if(firstConnectionCb){
139
- firstConnectionCb("connected");
140
- firstConnectionCb = null;
158
+ if(resolveOnFirstConnect){
159
+ resolveOnFirstConnect("connected");
160
+ resolveOnFirstConnect = null;
161
+ reject = null;
141
162
  // setup hibernate timer on first connection
142
163
  activityInHibernateInterval = 1;
143
164
  hibernateTimer = setInterval(_checkActivityForHibernation, INACTIVITY_TIME_FOR_HIBERNATE);
@@ -160,8 +181,8 @@ async function _setupAndMaintainConnection(firstConnectionCb, neverConnectedCB)
160
181
  client && client.userClosedConnectionCB && client.userClosedConnectionCB();
161
182
  client = cocoDBEndPointURL = cocoAuthKey = null;
162
183
  id = 0;
163
- if(neverConnectedCB){
164
- neverConnectedCB(new Error("user Cancelled"));
184
+ if(reject){
185
+ reject(new Error("user Cancelled"));
165
186
  }
166
187
  }
167
188
 
@@ -219,7 +240,7 @@ export function close() {
219
240
  currentClient.userClosedConnection = true;
220
241
  currentClient.userClosedConnectionCB = function () {
221
242
  for(let entry of pendingSendMessages){
222
- entry.reject();
243
+ entry.reject(new Error('Connection closed'));
223
244
  }
224
245
  pendingSendMessages = [];
225
246
  resolve();
@@ -239,7 +260,7 @@ export function close() {
239
260
  * @returns {string} A function that increments the id variable and returns the new value as a hexadecimal string.
240
261
  */
241
262
  function getId() {
242
- id++;
263
+ id++; // Will take about 300 years to run out at 1 million sustained tps to db with Number.MAX_SAFE_INTEGER
243
264
  return id.toString(16);
244
265
  }
245
266
 
@@ -284,7 +305,7 @@ function _sendPendingMessages() {
284
305
  */
285
306
  export function sendMessage(message) {
286
307
  // make a copy as the user may start modifying the object while we are sending it.
287
- message = structuredClone(message);
308
+ message = JSON.parse(JSON.stringify(message)); // faster than structured clone for most cases
288
309
  return new Promise(function (resolve, reject) {
289
310
  if(bufferRequests){
290
311
  if(pendingSendMessages.length > MAX_PENDING_SEND_BUFFER_SIZE){