@iobroker/db-objects-file 4.0.21 → 4.1.0-alpha.0-20220819-74ceeddc

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.
@@ -6,9 +6,7 @@
6
6
  * MIT License
7
7
  *
8
8
  */
9
-
10
9
  /** @module objectsInRedis */
11
-
12
10
  /* jshint -W097 */
13
11
  /* jshint strict:false */
14
12
  /* jslint node: true */
@@ -19,10 +17,8 @@ const path = require('path');
19
17
  const crypto = require('crypto');
20
18
  const utils = require('@iobroker/db-objects-redis').objectsUtils;
21
19
  const tools = require('@iobroker/db-base').tools;
22
-
23
- const RedisHandler = require('@iobroker/db-base').redisHandler;
20
+ const { RedisHandler } = require('@iobroker/db-base');
24
21
  const ObjectsInMemoryFileDB = require('./objectsInMemFileDB');
25
-
26
22
  // settings = {
27
23
  // change: function (id, state) {},
28
24
  // connected: function (nameOfServer) {},
@@ -43,7 +39,6 @@ const ObjectsInMemoryFileDB = require('./objectsInMemFileDB');
43
39
  // host: localhost
44
40
  // };
45
41
  //
46
-
47
42
  /**
48
43
  * This class inherits statesInMemoryFileDB class and adds redis communication layer
49
44
  * to access the methods via redis protocol
@@ -55,11 +50,10 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
55
50
  */
56
51
  constructor(settings) {
57
52
  super(settings);
58
-
59
53
  this.serverConnections = {};
60
54
  this.namespaceObjects =
61
55
  (this.settings.redisNamespace || (settings.connection && settings.connection.redisNamespace) || 'cfg') +
62
- '.';
56
+ '.';
63
57
  this.namespaceFile = this.namespaceObjects + 'f.';
64
58
  this.namespaceObj = this.namespaceObjects + 'o.';
65
59
  this.namespaceSet = this.namespaceObjects + 's.';
@@ -67,39 +61,30 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
67
61
  // this.namespaceObjectsLen = this.namespaceObjects.length;
68
62
  this.namespaceFileLen = this.namespaceFile.length;
69
63
  this.namespaceObjLen = this.namespaceObj.length;
70
- this.metaNamespace = (this.settings.metaNamespace || 'meta') + '.';
71
- this.metaNamespaceLen = this.metaNamespace.length;
72
-
64
+ this.namespaceMeta = `${this.settings.namespaceMeta || 'meta'}.`;
65
+ this.namespaceMetaLen = this.namespaceMeta.length;
73
66
  this.knownScripts = {};
74
-
75
67
  this.normalizeFileRegex1 = new RegExp('^(.*)\\$%\\$(.*)\\$%\\$(meta|data)$');
76
68
  this.normalizeFileRegex2 = new RegExp('^(.*)\\$%\\$(.*)\\/?\\*$');
77
-
78
69
  this.open()
79
70
  .then(() => {
80
- return this._initRedisServer(this.settings.connection);
81
- })
71
+ return this._initRedisServer(this.settings.connection);
72
+ })
82
73
  .then(() => {
83
- this.log.debug(
84
- this.namespace +
85
- ' ' +
86
- (settings.secure ? 'Secure ' : '') +
87
- ' Redis inMem-objects listening on port ' +
88
- (settings.port || 9001)
89
- );
90
-
91
- if (typeof this.settings.connected === 'function') {
92
- setImmediate(() => this.settings.connected());
93
- }
94
- })
74
+ this.log.debug(this.namespace +
75
+ ' ' +
76
+ (settings.secure ? 'Secure ' : '') +
77
+ ' Redis inMem-objects listening on port ' +
78
+ (settings.port || 9001));
79
+ if (typeof this.settings.connected === 'function') {
80
+ setImmediate(() => this.settings.connected());
81
+ }
82
+ })
95
83
  .catch(e => {
96
- this.log.error(
97
- this.namespace + ' Cannot start inMem-objects on port ' + (settings.port || 9001) + ': ' + e.message
98
- );
99
- process.exit(24); // todo: replace it with exitcode
100
- });
84
+ this.log.error(`${this.namespace} Cannot start inMem-objects on port ${settings.port || 9001}: ${e.message}`);
85
+ process.exit(24); // todo: replace it with exitcode
86
+ });
101
87
  }
102
-
103
88
  /**
104
89
  * Separate Namespace from ID and return both
105
90
  * @param idWithNamespace ID or Array of IDs containing a redis namespace and the real ID
@@ -120,18 +105,20 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
120
105
  ns = namespace; // we ignore the pot. case from arrays with different namespaces
121
106
  });
122
107
  id = ids;
123
- } else if (typeof idWithNamespace === 'string') {
108
+ }
109
+ else if (typeof idWithNamespace === 'string') {
124
110
  id = idWithNamespace;
125
111
  if (idWithNamespace.startsWith(this.namespaceObjects)) {
126
112
  let idx = -1;
127
113
  if (idWithNamespace.startsWith(this.namespaceObj)) {
128
114
  idx = this.namespaceObjLen;
129
- } else if (idWithNamespace.startsWith(this.namespaceFile)) {
115
+ }
116
+ else if (idWithNamespace.startsWith(this.namespaceFile)) {
130
117
  idx = this.namespaceFileLen;
131
- } else if (idWithNamespace.startsWith(this.namespaceSet)) {
118
+ }
119
+ else if (idWithNamespace.startsWith(this.namespaceSet)) {
132
120
  idx = this.namespaceSetLen;
133
121
  }
134
-
135
122
  if (idx !== -1) {
136
123
  ns = idWithNamespace.substr(0, idx);
137
124
  id = idWithNamespace.substr(idx);
@@ -142,20 +129,23 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
142
129
  id = fileIdDetails[1];
143
130
  name = fileIdDetails[2] || '';
144
131
  isMeta = fileIdDetails[3] === 'meta';
145
- } else {
132
+ }
133
+ else {
146
134
  fileIdDetails = id.match(this.normalizeFileRegex2);
147
135
  if (fileIdDetails) {
148
136
  id = fileIdDetails[1];
149
137
  name = fileIdDetails[2] || '';
150
138
  isMeta = undefined;
151
- } else {
139
+ }
140
+ else {
152
141
  name = '';
153
142
  isMeta = undefined;
154
143
  }
155
144
  }
156
145
  }
157
- } else if (idWithNamespace.startsWith(this.metaNamespace)) {
158
- const idx = this.metaNamespaceLen;
146
+ }
147
+ else if (idWithNamespace.startsWith(this.namespaceMeta)) {
148
+ const idx = this.namespaceMetaLen;
159
149
  if (idx !== -1) {
160
150
  ns = idWithNamespace.substr(0, idx);
161
151
  id = idWithNamespace.substr(idx);
@@ -164,32 +154,37 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
164
154
  }
165
155
  return { id, namespace: ns, name, isMeta };
166
156
  }
167
-
168
157
  /**
169
158
  * Publish a subscribed value to one of the redis connections in redis format
170
159
  * @param client Instance of RedisHandler
171
160
  * @param type Type of subscribed key
172
161
  * @param id Subscribed ID
173
162
  * @param obj Object to publish
174
- * @returns {number} Publish counter 0 or 1 depending if send out or not
163
+ * @returns {number} Publish counter 0 or 1 depending on if send out or not
175
164
  */
176
165
  publishToClients(client, type, id, obj) {
177
166
  if (!client._subscribe || !client._subscribe[type]) {
178
167
  return 0;
179
168
  }
180
169
  const s = client._subscribe[type];
181
-
182
170
  const found = s.find(sub => sub.regex.test(id));
183
-
184
171
  if (found) {
185
172
  if (type === 'meta') {
186
173
  this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${obj}`);
187
- const sendPattern = this.metaNamespace + found.pattern;
188
- const sendId = this.metaNamespace + id;
174
+ const sendPattern = this.namespaceMeta + found.pattern;
175
+ const sendId = this.namespaceMeta + id;
189
176
  client.sendArray(null, ['pmessage', sendPattern, sendId, obj]);
190
- } else {
177
+ }
178
+ else if (type === 'files') {
191
179
  const objString = JSON.stringify(obj);
192
- this.log.silly(this.namespace + ' Redis Publish Object ' + id + '=' + objString);
180
+ this.log.silly(`${this.namespace} Redis Publish File ${id}=${objString}`);
181
+ const sendPattern = this.namespaceFile + found.pattern;
182
+ const sendId = this.namespaceFile + id;
183
+ client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);
184
+ }
185
+ else {
186
+ const objString = JSON.stringify(obj);
187
+ this.log.silly(`${this.namespace} Redis Publish Object ${id}=${objString}`);
193
188
  const sendPattern = (type === 'objects' ? '' : this.namespaceObjects) + found.pattern;
194
189
  const sendId = (type === 'objects' ? this.namespaceObj : this.namespaceObjects) + id;
195
190
  client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);
@@ -198,7 +193,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
198
193
  }
199
194
  return 0;
200
195
  }
201
-
202
196
  /**
203
197
  * Generate ID for a File
204
198
  * @param id ID of the File
@@ -211,15 +205,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
211
205
  if (id.endsWith('.admin')) {
212
206
  if (name.startsWith('admin/')) {
213
207
  name = name.replace(/^admin\//, '');
214
- } else if (name.match(/^iobroker.[-\d\w]\/admin\//i)) {
208
+ }
209
+ else if (name.match(/^iobroker.[-\d\w]\/admin\//i)) {
215
210
  // e.g. ekey.admin and iobroker.ekey/admin/ekey.png
216
211
  name = name.replace(/^iobroker.[-\d\w]\/admin\//i, '');
217
212
  }
218
213
  }
219
-
220
214
  return this.namespaceFile + id + '$%$' + name + (isMeta !== undefined ? (isMeta ? '$%$meta' : '$%$data') : '');
221
215
  }
222
-
223
216
  /**
224
217
  * Register all event listeners for Handler and implement the relevant logic
225
218
  * @param handler RedisHandler instance
@@ -228,7 +221,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
228
221
  _socketEvents(handler) {
229
222
  let connectionName = null;
230
223
  let namespaceLog = this.namespace;
231
-
232
224
  // Handle Redis "INFO" request
233
225
  handler.on('info', (_data, responseId) => {
234
226
  let infoString = '# Server\r\n';
@@ -241,17 +233,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
241
233
  infoString += '# CPU\r\n';
242
234
  infoString += '# Cluster\r\n';
243
235
  infoString += '# Keyspace\r\n';
244
- infoString += 'db0:keys=' + Object.keys(this.dataset).length + ',expires=0,avg_ttl=98633637897';
236
+ infoString += `db0:keys=${Object.keys(this.dataset).length},expires=0,avg_ttl=98633637897`;
245
237
  handler.sendBulk(responseId, infoString);
246
238
  });
247
-
248
239
  // Handle Redis "QUIT" request
249
240
  handler.on('quit', (_data, responseId) => {
250
241
  this.log.silly(namespaceLog + ' Redis QUIT received, close connection');
251
242
  handler.sendString(responseId, 'OK');
252
243
  handler.close();
253
244
  });
254
-
255
245
  // Handle Redis "SCRIPT" request
256
246
  handler.on('script', (data, responseId) => {
257
247
  data[0] = data[0].toLowerCase();
@@ -260,12 +250,12 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
260
250
  const scripts = [];
261
251
  data.forEach(checksum => scripts.push(this.knownScripts[checksum] ? 1 : 0));
262
252
  handler.sendArray(responseId, scripts);
263
- } else if (data[0] === 'load') {
253
+ }
254
+ else if (data[0] === 'load') {
264
255
  const shasum = crypto.createHash('sha1');
265
256
  const buf = Buffer.from(data[1]);
266
257
  shasum.update(buf);
267
258
  const scriptChecksum = shasum.digest('hex');
268
-
269
259
  const scriptDesign = data[1].match(/^-- design: ([a-z0-9A-Z-.]+)\s/m);
270
260
  const scriptFunc = data[1].match(/^-- func: (.+)$/m);
271
261
  if (scriptDesign && scriptDesign[1]) {
@@ -275,45 +265,35 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
275
265
  if (scriptSearch && scriptSearch[1]) {
276
266
  search = scriptSearch[1];
277
267
  }
278
-
279
268
  this.knownScripts[scriptChecksum] = { design: design, search: search };
280
269
  if (this.settings.connection.enhancedLogging) {
281
- this.log.silly(
282
- `${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(
283
- this.knownScripts[scriptChecksum]
284
- )}`
285
- );
270
+ this.log.silly(`${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
286
271
  }
287
272
  handler.sendBulk(responseId, scriptChecksum);
288
- } else if (scriptFunc && scriptFunc[1]) {
273
+ }
274
+ else if (scriptFunc && scriptFunc[1]) {
289
275
  this.knownScripts[scriptChecksum] = { func: scriptFunc[1] };
290
276
  if (this.settings.connection.enhancedLogging) {
291
- this.log.silly(
292
- `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(
293
- this.knownScripts[scriptChecksum]
294
- )}`
295
- );
277
+ this.log.silly(`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
296
278
  }
297
279
  handler.sendBulk(responseId, scriptChecksum);
298
- } else if (data[1].includes('-- REDLOCK SCRIPT')) {
280
+ }
281
+ else if (data[1].includes('-- REDLOCK SCRIPT')) {
299
282
  // redlock scripts are currently not needed for Simulator
300
283
  this.knownScripts[scriptChecksum] = { redlock: true };
301
284
  if (this.settings.connection.enhancedLogging) {
302
- this.log.silly(
303
- `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(
304
- this.knownScripts[scriptChecksum]
305
- )}`
306
- );
285
+ this.log.silly(`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
307
286
  }
308
287
  handler.sendBulk(responseId, scriptChecksum);
309
- } else {
288
+ }
289
+ else {
310
290
  handler.sendError(responseId, new Error(`Unknown LUA script ${data[1]}`));
311
291
  }
312
- } else {
292
+ }
293
+ else {
313
294
  handler.sendError(responseId, new Error(`Unsupported Script command ${data[0]}`));
314
295
  }
315
296
  });
316
-
317
297
  // Handle Redis "EVALSHA" request
318
298
  handler.on('evalsha', (data, responseId) => {
319
299
  if (!this.knownScripts[data[0]]) {
@@ -330,9 +310,7 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
330
310
  scriptSearch = 'state';
331
311
  }
332
312
  if (this.settings.connection.enhancedLogging) {
333
- this.log.silly(
334
- `${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`
335
- );
313
+ this.log.silly(`${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`);
336
314
  }
337
315
  let objs;
338
316
  try {
@@ -341,18 +319,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
341
319
  endkey: data[4],
342
320
  include_docs: true
343
321
  });
344
- } catch (err) {
345
- return void handler.sendError(
346
- responseId,
347
- new Error(
348
- '_getObjectView Error for ' + scriptDesign + '/' + scriptSearch + ': ' + err.message
349
- )
350
- );
322
+ }
323
+ catch (err) {
324
+ return void handler.sendError(responseId, new Error(`_getObjectView Error for ${scriptDesign}/${scriptSearch}: ${err.message}`));
351
325
  }
352
326
  const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));
353
327
  handler.sendArray(responseId, res);
354
328
  }
355
- } else if (this.knownScripts[data[0]].func && data.length > 4) {
329
+ }
330
+ else if (this.knownScripts[data[0]].func && data.length > 4) {
356
331
  const scriptFunc = { map: this.knownScripts[data[0]].func.replace('%1', data[5]) };
357
332
  if (this.settings.connection.enhancedLogging) {
358
333
  this.log.silly(`${namespaceLog} Script transformed into _applyView: func=${scriptFunc.map}`);
@@ -363,44 +338,41 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
363
338
  include_docs: true
364
339
  });
365
340
  const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));
366
-
367
341
  return void handler.sendArray(responseId, res);
368
- } else if (this.knownScripts[data[0]].redlock) {
342
+ }
343
+ else if (this.knownScripts[data[0]].redlock) {
369
344
  // just return a dummy
370
345
  return void handler.sendArray(responseId, [0]);
371
- } else {
346
+ }
347
+ else {
372
348
  handler.sendError(responseId, new Error(`Unknown LUA script eval call ${JSON.stringify(data)}`));
373
349
  }
374
350
  });
375
-
376
351
  // Handle Redis "PUBLISH" request
377
352
  handler.on('publish', (data, responseId) => {
378
353
  const { id, namespace } = this._normalizeId(data[0]);
379
-
380
- if (namespace === this.namespaceObj || namespace === this.metaNamespace) {
354
+ if (namespace === this.namespaceObj ||
355
+ namespace === this.namespaceMeta ||
356
+ namespace === this.namespaceFile) {
381
357
  // a "set" always comes afterwards, so do not publish
382
358
  return void handler.sendInteger(responseId, 0); // do not publish for now
383
359
  }
384
360
  const publishCount = this.publishAll(namespace.substr(0, namespace.length - 1), id, JSON.parse(data[1]));
385
361
  handler.sendInteger(responseId, publishCount);
386
362
  });
387
-
388
363
  // Handle Redis "MGET" requests
389
364
  handler.on('mget', (data, responseId) => {
390
365
  if (!data || !data.length) {
391
366
  return void handler.sendArray(responseId, []);
392
367
  }
393
368
  const { namespace, isMeta } = this._normalizeId(data[0]);
394
-
395
369
  if (namespace === this.namespaceObj) {
396
370
  const keys = [];
397
371
  data.forEach(dataId => {
398
372
  const { id, namespace } = this._normalizeId(dataId);
399
373
  if (namespace !== this.namespaceObj) {
400
374
  keys.push(null);
401
- this.log.warn(
402
- `${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`
403
- );
375
+ this.log.warn(`${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`);
404
376
  return;
405
377
  }
406
378
  keys.push(id);
@@ -408,12 +380,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
408
380
  let result;
409
381
  try {
410
382
  result = this._getObjects(keys);
411
- } catch (err) {
383
+ }
384
+ catch (err) {
412
385
  return void handler.sendError(responseId, new Error('ERROR _getObjects: ' + err.message));
413
386
  }
414
387
  result = result.map(el => (el ? JSON.stringify(el) : null));
415
388
  handler.sendArray(responseId, result);
416
- } else if (namespace === this.namespaceFile) {
389
+ }
390
+ else if (namespace === this.namespaceFile) {
417
391
  // Handle request for Meta data for files
418
392
  if (isMeta) {
419
393
  const response = [];
@@ -421,9 +395,7 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
421
395
  const { id, namespace, name } = this._normalizeId(dataId);
422
396
  if (namespace !== this.namespaceFile) {
423
397
  response.push(null);
424
- this.log.warn(
425
- `${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`
426
- );
398
+ this.log.warn(`${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`);
427
399
  return;
428
400
  }
429
401
  this._loadFileSettings(id);
@@ -435,11 +407,10 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
435
407
  try {
436
408
  // @ts-ignore
437
409
  obj.stats = fs.statSync(path.join(this.objectsDir, id, name));
438
- } catch (err) {
410
+ }
411
+ catch (err) {
439
412
  if (!name.endsWith('/_data.json')) {
440
- this.log.warn(
441
- `${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`
442
- );
413
+ this.log.warn(`${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`);
443
414
  }
444
415
  response.push(null);
445
416
  return;
@@ -447,65 +418,58 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
447
418
  response.push(JSON.stringify(obj));
448
419
  });
449
420
  handler.sendArray(responseId, response);
450
- } else {
421
+ }
422
+ else {
451
423
  // Handle request for File data
452
424
  handler.sendError(responseId, new Error('MGET-UNSUPPORTED for file data'));
453
425
  }
454
- } else {
455
- handler.sendError(
456
- responseId,
457
- new Error('MGET-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
458
- );
426
+ }
427
+ else {
428
+ handler.sendError(responseId, new Error(`MGET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
459
429
  }
460
430
  });
461
-
462
431
  // Handle Redis "GET" requests
463
432
  handler.on('get', (data, responseId) => {
464
433
  const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
465
-
466
434
  if (namespace === this.namespaceObj) {
467
435
  const result = this._getObject(id);
468
436
  if (!result) {
469
437
  handler.sendNull(responseId);
470
- } else {
438
+ }
439
+ else {
471
440
  handler.sendBulk(responseId, JSON.stringify(result));
472
441
  }
473
- } else if (namespace === this.namespaceFile) {
442
+ }
443
+ else if (namespace === this.namespaceFile) {
474
444
  // Handle request for Meta data for files
475
445
  if (isMeta) {
476
446
  let stats;
477
447
  try {
478
448
  stats = fs.statSync(path.join(this.objectsDir, id, name));
479
- } catch {
449
+ }
450
+ catch {
480
451
  return void handler.sendNull(responseId);
481
452
  }
482
453
  if (stats.isDirectory()) {
483
- return void handler.sendBulk(
484
- responseId,
485
- JSON.stringify({
486
- file: name,
487
- stats: {},
488
- isDir: true
489
- })
490
- );
454
+ return void handler.sendBulk(responseId, JSON.stringify({
455
+ file: name,
456
+ stats: {},
457
+ isDir: true
458
+ }));
491
459
  }
492
460
  this._loadFileSettings(id);
493
461
  if (!this.fileOptions[id] || !this.fileOptions[id][name]) {
494
462
  return void handler.sendNull(responseId);
495
463
  }
496
-
497
464
  let obj = this._clone(this.fileOptions[id][name]);
498
465
  if (typeof obj !== 'object') {
499
466
  obj = {
500
467
  mimeType: obj,
501
468
  acl: {
502
- owner:
503
- (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
504
- ownerGroup:
505
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
469
+ owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
470
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
506
471
  utils.CONSTS.SYSTEM_ADMIN_GROUP,
507
- permissions:
508
- (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
472
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
509
473
  utils.CONSTS.ACCESS_USER_ALL |
510
474
  utils.CONSTS.ACCESS_GROUP_ALL |
511
475
  utils.CONSTS.ACCESS_EVERY_ALL // 777
@@ -514,12 +478,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
514
478
  }
515
479
  obj.stats = stats;
516
480
  handler.sendBulk(responseId, JSON.stringify(obj));
517
- } else {
481
+ }
482
+ else {
518
483
  // Handle request for File data
519
484
  let data;
520
485
  try {
521
486
  data = this._readFile(id, name);
522
- } catch {
487
+ }
488
+ catch {
523
489
  return void handler.sendNull(responseId);
524
490
  }
525
491
  if (data.fileContent === undefined || data.fileContent === null) {
@@ -529,308 +495,290 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
529
495
  if (!Buffer.isBuffer(fileData) && tools.isObject(fileData)) {
530
496
  // if its an invalid object, stringify it and log warning
531
497
  fileData = JSON.stringify(fileData);
532
- this.log.warn(
533
- `${namespaceLog} Data of "${id}/${name}" has invalid structure at file data request: ${fileData}`
534
- );
498
+ this.log.warn(`${namespaceLog} Data of "${id}/${name}" has invalid structure at file data request: ${fileData}`);
535
499
  }
536
500
  handler.sendBufBulk(responseId, Buffer.from(fileData));
537
501
  }
538
- } else if (namespace === this.metaNamespace) {
502
+ }
503
+ else if (namespace === this.namespaceMeta) {
539
504
  // special handling for the primaryHost
540
505
  if (id === 'objects.primaryHost') {
541
506
  // we are the server -> we are primary
542
507
  handler.sendString(this.settings.hostname);
543
- } else {
508
+ }
509
+ else {
544
510
  const result = this.getMeta(id);
545
511
  if (result === undefined || result === null) {
546
512
  handler.sendNull(responseId);
547
- } else {
513
+ }
514
+ else {
548
515
  handler.sendBulk(responseId, result);
549
516
  }
550
517
  }
551
- } else {
552
- handler.sendError(
553
- responseId,
554
- new Error('GET-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
555
- );
518
+ }
519
+ else {
520
+ handler.sendError(responseId, new Error(`GET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
556
521
  }
557
522
  });
558
-
559
523
  // Handle Redis "SET" requests
560
524
  handler.on('set', (data, responseId) => {
561
525
  const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
562
-
563
526
  if (namespace === this.namespaceObj) {
564
527
  try {
565
528
  const obj = JSON.parse(data[1].toString('utf-8'));
566
529
  this._setObjectDirect(id, obj);
567
- } catch (err) {
530
+ }
531
+ catch (err) {
568
532
  return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: ${err.message}`));
569
533
  }
570
534
  handler.sendString(responseId, 'OK');
571
- } else if (namespace === this.namespaceFile) {
572
- // Handle request to set meta data, we ignore it because
535
+ }
536
+ else if (namespace === this.namespaceFile) {
537
+ // Handle request to set meta-data, we ignore it because
573
538
  // will be set when data are written
574
539
  if (isMeta) {
575
540
  this._loadFileSettings(id);
576
-
577
541
  try {
578
542
  fs.ensureDirSync(path.join(this.objectsDir, id, path.dirname(name)));
579
-
580
- // only set if the meta object is already/still existing
543
+ // only set if the meta-object is already/still existing
581
544
  if (this.fileOptions[id]) {
582
545
  this.fileOptions[id][name] = JSON.parse(data[1].toString('utf-8'));
583
- fs.writeFileSync(
584
- path.join(this.objectsDir, id, '_data.json'),
585
- JSON.stringify(this.fileOptions[id])
586
- );
546
+ fs.writeFileSync(path.join(this.objectsDir, id, '_data.json'), JSON.stringify(this.fileOptions[id]));
587
547
  }
588
- } catch (err) {
589
- return void handler.sendError(
590
- responseId,
591
- new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`)
592
- );
548
+ }
549
+ catch (err) {
550
+ return void handler.sendError(responseId, new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`));
593
551
  }
594
552
  handler.sendString(responseId, 'OK');
595
- } else {
553
+ }
554
+ else {
596
555
  // Handle request to write the file
597
556
  try {
598
557
  this._writeFile(id, name, data[1]);
599
- } catch (err) {
600
- return void handler.sendError(
601
- responseId,
602
- new Error(`ERROR writeFile id=${id}: ${err.message}`)
603
- );
558
+ }
559
+ catch (err) {
560
+ return void handler.sendError(responseId, new Error(`ERROR writeFile id=${id}: ${err.message}`));
604
561
  }
605
562
  handler.sendString(responseId, 'OK');
606
563
  }
607
- } else if (namespace === this.metaNamespace) {
564
+ }
565
+ else if (namespace === this.namespaceMeta) {
608
566
  this.setMeta(id, data[1].toString('utf-8'));
609
567
  handler.sendString(responseId, 'OK');
610
- } else {
611
- handler.sendError(
612
- responseId,
613
- new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`)
614
- );
568
+ }
569
+ else {
570
+ handler.sendError(responseId, new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
615
571
  }
616
572
  });
617
-
618
573
  // Handle Redis "RENAME" requests
619
574
  handler.on('rename', (data, responseId) => {
620
575
  const oldDetails = this._normalizeId(data[0]);
621
576
  const newDetails = this._normalizeId(data[1]);
622
-
623
577
  if (oldDetails.namespace === this.namespaceFile) {
624
578
  if (oldDetails.id !== newDetails.id) {
625
- return void handler.sendError(
626
- responseId,
627
- new Error('ERROR renameObject: id needs to stay the same')
628
- );
579
+ return void handler.sendError(responseId, new Error('ERROR renameObject: id needs to stay the same'));
629
580
  }
630
-
631
581
  // Handle request for Meta data for files
632
582
  if (oldDetails.isMeta) {
633
583
  handler.sendString(responseId, 'OK');
634
- } else {
584
+ }
585
+ else {
635
586
  // Handle request for File data
636
587
  try {
637
588
  this._rename(oldDetails.id, oldDetails.name, newDetails.name);
638
- } catch {
589
+ }
590
+ catch {
639
591
  return void handler.sendNull(responseId);
640
592
  }
641
593
  handler.sendString(responseId, 'OK');
642
594
  }
643
- } else {
644
- handler.sendError(
645
- responseId,
646
- new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`)
647
- );
595
+ }
596
+ else {
597
+ handler.sendError(responseId, new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`));
648
598
  }
649
599
  });
650
-
651
600
  // Handle Redis "DEL" request for state and session namespace
652
601
  handler.on('del', (data, responseId) => {
653
602
  const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
654
-
655
603
  if (namespace === this.namespaceObj) {
656
604
  try {
657
605
  this._delObject(id);
658
- } catch (err) {
606
+ }
607
+ catch (err) {
659
608
  return void handler.sendError(responseId, err);
660
609
  }
661
610
  handler.sendInteger(responseId, 1);
662
- } else if (namespace === this.namespaceFile) {
663
- // Handle request to delete meta data, we ignore it because
611
+ }
612
+ else if (namespace === this.namespaceFile) {
613
+ // Handle request to delete meta-data, we ignore it because
664
614
  // will be removed when data are deleted
665
615
  if (isMeta) {
666
616
  handler.sendString(responseId, 'OK');
667
- } else {
617
+ }
618
+ else {
668
619
  // Handle request to remove the file
669
620
  try {
670
621
  this._unlink(id, name);
671
- } catch (err) {
622
+ }
623
+ catch (err) {
672
624
  return void handler.sendError(responseId, err);
673
625
  }
674
626
  handler.sendString(responseId, 'OK');
675
627
  }
676
- } else {
677
- handler.sendError(
678
- responseId,
679
- new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`)
680
- );
628
+ }
629
+ else {
630
+ handler.sendError(responseId, new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
681
631
  }
682
632
  });
683
-
684
633
  handler.on('exists', (data, responseId) => {
685
634
  if (!data || !data.length) {
686
635
  return void handler.sendInteger(responseId, 0);
687
636
  }
688
-
689
637
  // Note: we only simulate single key existence check
690
638
  const { id, namespace, name } = this._normalizeId(data[0]);
691
-
692
639
  if (namespace === this.namespaceObj) {
693
640
  let exists;
694
641
  try {
695
642
  exists = this._objectExists(id);
696
- } catch (e) {
643
+ }
644
+ catch (e) {
697
645
  return void handler.sendError(responseId, e);
698
646
  }
699
647
  handler.sendInteger(responseId, exists ? 1 : 0);
700
- } else if (namespace === this.namespaceFile) {
648
+ }
649
+ else if (namespace === this.namespaceFile) {
701
650
  let exists;
702
651
  try {
703
652
  exists = this._fileExists(id, name);
704
- } catch (e) {
653
+ }
654
+ catch (e) {
705
655
  return void handler.sendError(responseId, e);
706
656
  }
707
657
  handler.sendInteger(responseId, exists ? 1 : 0);
708
- } else if (namespace === this.namespaceSet) {
658
+ }
659
+ else if (namespace === this.namespaceSet) {
709
660
  // we are not using sets in simulator, so just say it exists
710
661
  return void handler.sendInteger(responseId, 1);
711
- } else {
662
+ }
663
+ else {
712
664
  handler.sendError(responseId, new Error(`EXISTS-UNSUPPORTED for namespace ${namespace}`));
713
665
  }
714
666
  });
715
-
716
667
  // handle Redis "SCAN" request for objects namespace
717
668
  handler.on('scan', (data, responseId) => {
718
669
  if (!data || data.length < 3) {
719
670
  return void handler.sendArray(responseId, ['0', []]);
720
671
  }
721
-
722
672
  return this._handleScanOrKeys(handler, data[2], responseId, true);
723
673
  });
724
-
725
674
  // Handle Redis "KEYS" request for state namespace
726
675
  handler.on('keys', (data, responseId) => {
727
676
  if (!data || !data.length) {
728
677
  return void handler.sendArray(responseId, []);
729
678
  }
730
-
731
679
  return this._handleScanOrKeys(handler, data[0], responseId);
732
680
  });
733
-
734
681
  // commands for redis SETS, just dummies
735
682
  handler.on('sadd', (data, responseId) => {
736
683
  return void handler.sendInteger(responseId, 1);
737
684
  });
738
-
739
685
  handler.on('srem', (data, responseId) => {
740
686
  return void handler.sendInteger(responseId, 1);
741
687
  });
742
-
743
688
  handler.on('sscan', (data, responseId) => {
744
689
  // for file DB it does the same as scan but data looks different
745
690
  if (!data || data.length < 4) {
746
691
  return void handler.sendArray(responseId, ['0', []]);
747
692
  }
748
-
749
693
  return this._handleScanOrKeys(handler, data[3], responseId, true);
750
694
  });
751
-
752
695
  // Handle Redis "PSUBSCRIBE" request for state, log and session namespace
753
696
  handler.on('psubscribe', (data, responseId) => {
754
- const { id, namespace } = this._normalizeId(data[0]);
755
-
697
+ const { id, namespace, name } = this._normalizeId(data[0]);
756
698
  if (namespace === this.namespaceObj) {
757
699
  this._subscribeConfigForClient(handler, id);
758
700
  handler.sendArray(responseId, ['psubscribe', data[0], 1]);
759
- } else if (namespace === this.metaNamespace) {
701
+ }
702
+ else if (namespace === this.namespaceMeta) {
760
703
  this._subscribeMeta(handler, id);
761
704
  handler.sendArray(responseId, ['psubscribe', data[0], 1]);
762
- } else {
763
- handler.sendError(
764
- responseId,
765
- new Error('PSUBSCRIBE-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
766
- );
705
+ }
706
+ else if (namespace === this.namespaceFile) {
707
+ this._subscribeFileForClient(handler, id, name);
708
+ handler.sendArray(responseId, ['psubscribe', data[0], 1]);
709
+ }
710
+ else {
711
+ handler.sendError(responseId, new Error(`PSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
767
712
  }
768
713
  });
769
-
770
714
  // Handle Redis "UNSUBSCRIBE" request for state, log and session namespace
771
715
  handler.on('punsubscribe', (data, responseId) => {
772
- const { id, namespace } = this._normalizeId(data[0]);
773
-
716
+ const { id, namespace, name } = this._normalizeId(data[0]);
774
717
  if (namespace === this.namespaceObj) {
775
718
  this._unsubscribeConfigForClient(handler, id);
776
719
  handler.sendArray(responseId, ['punsubscribe', data[0], 1]);
777
- } else {
778
- handler.sendError(
779
- responseId,
780
- new Error('PUNSUBSCRIBE-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
781
- );
720
+ }
721
+ else if (namespace === this.namespaceFile) {
722
+ this._unsubscribeFileForClient(handler, id, name);
723
+ handler.sendArray(responseId, ['punsubscribe', data[0], 1]);
724
+ }
725
+ else {
726
+ handler.sendError(responseId, new Error(`PUNSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
782
727
  }
783
728
  });
784
-
785
729
  // Handle Redis "SUBSCRIBE" ... currently mainly ignored
786
730
  handler.on('subscribe', (data, responseId) => {
787
731
  if (data[0].startsWith('__keyevent@')) {
788
732
  // we ignore these type of events because we publish expires anyway directly
789
733
  handler.sendArray(responseId, ['subscribe', data[0], 1]);
790
- } else {
734
+ }
735
+ else {
791
736
  handler.sendError(responseId, new Error(`SUBSCRIBE-UNSUPPORTED for ${data[0]}`));
792
737
  }
793
738
  });
794
-
795
739
  // Handle Redis "CONFIG" ... currently mainly ignored
796
740
  handler.on('config', (data, responseId) => {
797
- if (data[0] === 'set' && data[1] === 'notify-keyspace-events') {
741
+ const command = typeof data[0] === 'string' ? data[0].toLowerCase() : data[0].toString().toLowerCase();
742
+ if (command === 'set' && data[1] === 'notify-keyspace-events') {
798
743
  // we ignore these type of commands for now, should only be to subscribe to keyspace events
799
744
  handler.sendString(responseId, 'OK');
800
- } else if (data[0] === 'set' && data[1] === 'lua-time-limit') {
745
+ }
746
+ else if (command === 'set' && data[1] === 'lua-time-limit') {
801
747
  // we ignore these type of commands for now, irrelevant
802
748
  handler.sendString(responseId, 'OK');
803
- } else {
749
+ }
750
+ else {
804
751
  handler.sendError(responseId, new Error('CONFIG-UNSUPPORTED for ' + JSON.stringify(data)));
805
752
  }
806
753
  });
807
-
808
754
  // handle client SETNAME/GETNAME
809
755
  handler.on('client', (data, responseId) => {
810
756
  if (data[0] === 'setname' && typeof data[1] === 'string') {
811
757
  if (data[1] === '') {
812
758
  // on empty string redis sets null again and sends 'OK'
813
759
  connectionName = null;
814
- } else {
760
+ }
761
+ else {
815
762
  connectionName = data[1];
816
763
  namespaceLog = connectionName;
817
764
  }
818
765
  handler.sendString(responseId, 'OK');
819
- } else if (data[0] === 'getname') {
766
+ }
767
+ else if (data[0] === 'getname') {
820
768
  if (typeof connectionName === 'string' && connectionName !== '') {
821
769
  handler.sendString(responseId, connectionName);
822
- } else {
770
+ }
771
+ else {
823
772
  // redis sends null if no name defined
824
773
  handler.sendNull(responseId);
825
774
  }
826
- } else {
775
+ }
776
+ else {
827
777
  handler.sendError(responseId, new Error(`CLIENT-UNSUPPORTED for ${JSON.stringify(data)}`));
828
778
  }
829
779
  });
830
-
831
780
  handler.on('error', err => this.log.warn(`${namespaceLog} Redis objects: ${err}`));
832
781
  }
833
-
834
782
  /**
835
783
  * Return connected RedisHandlers/Connections
836
784
  * @returns {{}|*}
@@ -838,7 +786,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
838
786
  getClients() {
839
787
  return this.serverConnections;
840
788
  }
841
-
842
789
  /**
843
790
  * Destructor of the class. Called by shutting down.
844
791
  */
@@ -848,23 +795,21 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
848
795
  this.serverConnections[s].close();
849
796
  delete this.serverConnections[s];
850
797
  });
851
-
852
798
  await new Promise(resolve => {
853
799
  if (!this.server) {
854
800
  return void resolve();
855
801
  }
856
802
  try {
857
803
  this.server.close(() => resolve());
858
- } catch (e) {
804
+ }
805
+ catch (e) {
859
806
  console.log(e.message);
860
807
  resolve();
861
808
  }
862
809
  });
863
810
  }
864
-
865
811
  await super.destroy();
866
812
  }
867
-
868
813
  /**
869
814
  * Get keys matching pattern and send it to given responseId, for "SCAN" and "KEYS" - Objects and files supported
870
815
  *
@@ -876,7 +821,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
876
821
  */
877
822
  _handleScanOrKeys(handler, pattern, responseId, isScan = false) {
878
823
  const { id, namespace, name, isMeta } = this._normalizeId(pattern);
879
-
880
824
  let response = [];
881
825
  if (namespace === this.namespaceObj || namespace === this.namespaceObjects) {
882
826
  response = this._getKeys(id).map(val => this.namespaceObj + val);
@@ -903,7 +847,8 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
903
847
  }
904
848
  ];
905
849
  }
906
- } catch (err) {
850
+ }
851
+ catch (err) {
907
852
  if (!err.message.endsWith(utils.ERRORS.ERROR_NOT_FOUND)) {
908
853
  return void handler.sendError(responseId, new Error(`ERROR readDir id=${id}: ${err.message}`));
909
854
  }
@@ -919,7 +864,8 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
919
864
  if (entryId === '' || entryId === '*') {
920
865
  entryId = arr.file;
921
866
  arr.file = '_data.json'; // We return a "virtual file" to mark the directory as existing
922
- } else {
867
+ }
868
+ else {
923
869
  arr.file += '/_data.json'; // We return a "virtual file" to mark the directory as existing
924
870
  }
925
871
  }
@@ -928,20 +874,19 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
928
874
  response.push(this.getFileId(entryId, baseName + arr.file, false));
929
875
  });
930
876
  handler.sendArray(responseId, isScan ? ['0', response] : response); // send out file or full db response
931
- } else {
877
+ }
878
+ else {
932
879
  // such a request should never happen
933
880
  handler.sendArray(responseId, isScan ? ['0', []] : []); // send out file or full db response
934
881
  }
935
- } else if (namespace === this.namespaceSet) {
882
+ }
883
+ else if (namespace === this.namespaceSet) {
936
884
  handler.sendArray(responseId, isScan ? ['0', []] : []); // send out empty array, we have no sets
937
- } else {
938
- handler.sendError(
939
- responseId,
940
- new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`)
941
- );
885
+ }
886
+ else {
887
+ handler.sendError(responseId, new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`));
942
888
  }
943
889
  }
944
-
945
890
  /**
946
891
  * Initialize RedisHandler for a new network connection
947
892
  * @param socket Network socket
@@ -953,13 +898,12 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
953
898
  }
954
899
  const options = {
955
900
  log: this.log,
956
- logScope: (this.settings.namespace || '') + ' Objects',
901
+ logScope: `${this.settings.namespace || ''} Objects`,
957
902
  handleAsBuffers: true,
958
903
  enhancedLogging: this.settings.connection.enhancedLogging
959
904
  };
960
905
  const handler = new RedisHandler(socket, options);
961
906
  this._socketEvents(handler);
962
-
963
907
  this.serverConnections[socket.remoteAddress + ':' + socket.remotePort] = handler;
964
908
  socket.on('close', () => {
965
909
  if (this.serverConnections[socket.remoteAddress + ':' + socket.remotePort]) {
@@ -967,7 +911,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
967
911
  }
968
912
  });
969
913
  }
970
-
971
914
  /**
972
915
  * Initialize Redis Server
973
916
  * @param settings Settings object
@@ -981,25 +924,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
981
924
  }
982
925
  try {
983
926
  this.server = net.createServer();
984
- this.server.on('error', err =>
985
- this.log.info(
986
- `${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${
987
- settings.port || 9001
988
- }: ${err}`
989
- )
990
- );
927
+ this.server.on('error', err => this.log.info(`${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${settings.port || 9001}: ${err}`));
991
928
  this.server.on('connection', socket => this._initSocket(socket));
992
-
993
- this.server.listen(
994
- settings.port || 9001,
995
- settings.host === 'localhost' ? '127.0.0.1' : settings.host ? settings.host : undefined,
996
- () => resolve()
997
- );
998
- } catch (err) {
929
+ this.server.listen(settings.port || 9001, settings.host === 'localhost' ? '127.0.0.1' : settings.host ? settings.host : undefined, () => resolve());
930
+ }
931
+ catch (err) {
999
932
  reject(err);
1000
933
  }
1001
934
  });
1002
935
  }
1003
936
  }
1004
-
1005
937
  module.exports = ObjectsInMemoryServer;
938
+ //# sourceMappingURL=objectsInMemServerRedis.js.map