@iobroker/db-objects-file 7.2.3 → 8.0.0-alpha.1-20260921-e5941ca8a
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/build/cjs/index.js +5 -3
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/lib/objects/objectsInMemFileDB.d.ts +288 -59
- package/build/cjs/lib/objects/objectsInMemFileDB.js +225 -109
- package/build/cjs/lib/objects/objectsInMemFileDB.js.map +3 -3
- package/build/cjs/lib/objects/objectsInMemServerClass.d.ts +41 -8
- package/build/cjs/lib/objects/objectsInMemServerClass.js +27 -2
- package/build/cjs/lib/objects/objectsInMemServerClass.js.map +3 -3
- package/build/cjs/lib/objects/objectsInMemServerRedis.d.ts +50 -30
- package/build/cjs/lib/objects/objectsInMemServerRedis.js +72 -37
- package/build/cjs/lib/objects/objectsInMemServerRedis.js.map +4 -4
- package/build/esm/lib/objects/objectsInMemFileDB.d.ts +288 -59
- package/build/esm/lib/objects/objectsInMemFileDB.d.ts.map +1 -1
- package/build/esm/lib/objects/objectsInMemFileDB.js +228 -126
- package/build/esm/lib/objects/objectsInMemFileDB.js.map +1 -1
- package/build/esm/lib/objects/objectsInMemServerClass.d.ts +41 -8
- package/build/esm/lib/objects/objectsInMemServerClass.d.ts.map +1 -1
- package/build/esm/lib/objects/objectsInMemServerClass.js +25 -1
- package/build/esm/lib/objects/objectsInMemServerClass.js.map +1 -1
- package/build/esm/lib/objects/objectsInMemServerRedis.d.ts +50 -30
- package/build/esm/lib/objects/objectsInMemServerRedis.d.ts.map +1 -1
- package/build/esm/lib/objects/objectsInMemServerRedis.js +89 -70
- package/build/esm/lib/objects/objectsInMemServerRedis.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +7 -7
|
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
9
|
var __export = (target, all) => {
|
|
9
10
|
for (var name in all)
|
|
10
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -42,6 +43,23 @@ var import_js_controller_common_db = require("@iobroker/js-controller-common-db"
|
|
|
42
43
|
var import_db_base2 = require("@iobroker/db-base");
|
|
43
44
|
var import_objectsInMemFileDB = require("./objectsInMemFileDB.js");
|
|
44
45
|
class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFileDB {
|
|
46
|
+
static {
|
|
47
|
+
__name(this, "ObjectsInMemoryServer");
|
|
48
|
+
}
|
|
49
|
+
serverConnections = {};
|
|
50
|
+
namespaceObjects;
|
|
51
|
+
namespaceFile;
|
|
52
|
+
namespaceObj;
|
|
53
|
+
namespaceSet;
|
|
54
|
+
namespaceSetLen;
|
|
55
|
+
namespaceFileLen;
|
|
56
|
+
namespaceObjLen;
|
|
57
|
+
namespaceMeta;
|
|
58
|
+
namespaceMetaLen;
|
|
59
|
+
knownScripts = {};
|
|
60
|
+
normalizeFileRegex1;
|
|
61
|
+
normalizeFileRegex2;
|
|
62
|
+
server;
|
|
45
63
|
/**
|
|
46
64
|
* Constructor
|
|
47
65
|
*
|
|
@@ -49,8 +67,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
49
67
|
*/
|
|
50
68
|
constructor(settings) {
|
|
51
69
|
super(settings);
|
|
52
|
-
this.
|
|
53
|
-
this.namespaceObjects = `${this.settings.redisNamespace || settings.connection && settings.connection.redisNamespace || "cfg"}.`;
|
|
70
|
+
this.namespaceObjects = `${this.settings.redisNamespace || settings.connection?.redisNamespace || "cfg"}.`;
|
|
54
71
|
this.namespaceFile = `${this.namespaceObjects}f.`;
|
|
55
72
|
this.namespaceObj = `${this.namespaceObjects}o.`;
|
|
56
73
|
this.namespaceSet = `${this.namespaceObjects}s.`;
|
|
@@ -59,12 +76,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
59
76
|
this.namespaceObjLen = this.namespaceObj.length;
|
|
60
77
|
this.namespaceMeta = `${this.settings.namespaceMeta || "meta"}.`;
|
|
61
78
|
this.namespaceMetaLen = this.namespaceMeta.length;
|
|
62
|
-
this.knownScripts = {};
|
|
63
79
|
this.normalizeFileRegex1 = new RegExp("^(.*)\\$%\\$(.*)\\$%\\$(meta|data)$");
|
|
64
80
|
this.normalizeFileRegex2 = new RegExp("^(.*)\\$%\\$(.*)\\/?\\*$");
|
|
65
|
-
this.open().then(() => {
|
|
66
|
-
return this._initRedisServer(this.settings.connection);
|
|
67
|
-
}).then(() => {
|
|
81
|
+
this.open().then(() => this._initRedisServer(this.settings.connection)).then(() => {
|
|
68
82
|
this.log.debug(`${this.namespace} ${settings.secure ? "Secure " : ""} Redis inMem-objects listening on port ${this.settings.connection.port || 9001}`);
|
|
69
83
|
if (typeof this.settings.connected === "function") {
|
|
70
84
|
setImmediate(() => this.settings.connected());
|
|
@@ -86,15 +100,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
86
100
|
let id = null;
|
|
87
101
|
let name = "";
|
|
88
102
|
let isMeta;
|
|
89
|
-
if (
|
|
90
|
-
const ids = [];
|
|
91
|
-
idWithNamespace.forEach((el) => {
|
|
92
|
-
const { id: id2, namespace } = this._normalizeId(el);
|
|
93
|
-
ids.push(id2);
|
|
94
|
-
ns = namespace;
|
|
95
|
-
});
|
|
96
|
-
id = ids;
|
|
97
|
-
} else if (typeof idWithNamespace === "string") {
|
|
103
|
+
if (typeof idWithNamespace === "string") {
|
|
98
104
|
id = idWithNamespace;
|
|
99
105
|
if (idWithNamespace.startsWith(this.namespaceObjects)) {
|
|
100
106
|
let idx = -1;
|
|
@@ -147,14 +153,14 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
147
153
|
* @returns Publish counter 0 or 1 depending on if send out or not
|
|
148
154
|
*/
|
|
149
155
|
publishToClients(client, type, id, obj) {
|
|
150
|
-
if (!client._subscribe
|
|
156
|
+
if (!client._subscribe?.[type]) {
|
|
151
157
|
return 0;
|
|
152
158
|
}
|
|
153
159
|
const s = client._subscribe[type];
|
|
154
160
|
const found = s.find((sub) => sub.regex.test(id));
|
|
155
161
|
if (found) {
|
|
156
162
|
if (type === "meta") {
|
|
157
|
-
this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${obj}`);
|
|
163
|
+
this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${JSON.stringify(obj)}`);
|
|
158
164
|
const sendPattern = this.namespaceMeta + found.pattern;
|
|
159
165
|
const sendId = this.namespaceMeta + id;
|
|
160
166
|
client.sendArray(null, ["pmessage", sendPattern, sendId, obj]);
|
|
@@ -234,11 +240,11 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
234
240
|
const scriptChecksum = shasum.digest("hex");
|
|
235
241
|
const scriptDesign = data[1].match(/^-- design: ([a-z0-9A-Z-.]+)\s/m);
|
|
236
242
|
const scriptFunc = data[1].match(/^-- func: (.+)$/m);
|
|
237
|
-
if (scriptDesign
|
|
243
|
+
if (scriptDesign?.[1]) {
|
|
238
244
|
const design = scriptDesign[1];
|
|
239
|
-
let search
|
|
245
|
+
let search;
|
|
240
246
|
const scriptSearch = data[1].match(/^-- search: ([a-z0-9A-Z-.]*)\s/m);
|
|
241
|
-
if (scriptSearch
|
|
247
|
+
if (scriptSearch?.[1]) {
|
|
242
248
|
search = scriptSearch[1];
|
|
243
249
|
}
|
|
244
250
|
this.knownScripts[scriptChecksum] = { design, search };
|
|
@@ -246,7 +252,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
246
252
|
this.log.silly(`${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
|
|
247
253
|
}
|
|
248
254
|
handler.sendBulk(responseId, scriptChecksum);
|
|
249
|
-
} else if (scriptFunc
|
|
255
|
+
} else if (scriptFunc?.[1]) {
|
|
250
256
|
this.knownScripts[scriptChecksum] = { func: scriptFunc[1] };
|
|
251
257
|
if (this.settings.connection.enhancedLogging) {
|
|
252
258
|
this.log.silly(`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
|
|
@@ -315,14 +321,14 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
315
321
|
});
|
|
316
322
|
handler.on("publish", (data, responseId) => {
|
|
317
323
|
const { id, namespace } = this._normalizeId(data[0]);
|
|
318
|
-
if (namespace === this.namespaceObj || namespace === this.namespaceMeta || namespace === this.namespaceFile) {
|
|
324
|
+
if (namespace === this.namespaceObj || namespace === this.namespaceMeta || namespace === this.namespaceFile || !id) {
|
|
319
325
|
return void handler.sendInteger(responseId, 0);
|
|
320
326
|
}
|
|
321
327
|
const publishCount = this.publishAll(namespace.substr(0, namespace.length - 1), id, JSON.parse(data[1]));
|
|
322
328
|
handler.sendInteger(responseId, publishCount);
|
|
323
329
|
});
|
|
324
330
|
handler.on("mget", (data, responseId) => {
|
|
325
|
-
if (!data
|
|
331
|
+
if (!data?.length) {
|
|
326
332
|
return void handler.sendArray(responseId, []);
|
|
327
333
|
}
|
|
328
334
|
const { namespace, isMeta } = this._normalizeId(data[0]);
|
|
@@ -343,14 +349,14 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
343
349
|
} catch (err) {
|
|
344
350
|
return void handler.sendError(responseId, new Error(`ERROR _getObjects: ${err.message}`));
|
|
345
351
|
}
|
|
346
|
-
|
|
347
|
-
handler.sendArray(responseId,
|
|
352
|
+
const resultObjs = result.map((el) => el ? JSON.stringify(el) : null);
|
|
353
|
+
handler.sendArray(responseId, resultObjs);
|
|
348
354
|
} else if (namespace === this.namespaceFile) {
|
|
349
355
|
if (isMeta) {
|
|
350
356
|
const response = [];
|
|
351
357
|
data.forEach((dataId) => {
|
|
352
358
|
const { id, namespace: namespace2, name } = this._normalizeId(dataId);
|
|
353
|
-
if (namespace2 !== this.namespaceFile) {
|
|
359
|
+
if (!id || namespace2 !== this.namespaceFile) {
|
|
354
360
|
response.push(null);
|
|
355
361
|
this.log.warn(`${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`);
|
|
356
362
|
return;
|
|
@@ -382,6 +388,10 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
382
388
|
});
|
|
383
389
|
handler.on("get", (data, responseId) => {
|
|
384
390
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
391
|
+
if (!id) {
|
|
392
|
+
handler.sendNull(responseId);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
385
395
|
if (namespace === this.namespaceObj) {
|
|
386
396
|
const result = this._getObject(id);
|
|
387
397
|
if (!result) {
|
|
@@ -413,14 +423,16 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
413
423
|
obj = {
|
|
414
424
|
mimeType: obj,
|
|
415
425
|
acl: {
|
|
416
|
-
owner: this.defaultNewAcl
|
|
417
|
-
ownerGroup: this.defaultNewAcl
|
|
418
|
-
permissions: this.defaultNewAcl
|
|
426
|
+
owner: this.defaultNewAcl?.owner || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_USER,
|
|
427
|
+
ownerGroup: this.defaultNewAcl?.ownerGroup || import_db_objects_redis.objectsUtils.CONSTS.SYSTEM_ADMIN_GROUP,
|
|
428
|
+
permissions: this.defaultNewAcl?.file || import_db_objects_redis.objectsUtils.CONSTS.ACCESS_USER_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_GROUP_ALL | import_db_objects_redis.objectsUtils.CONSTS.ACCESS_EVERY_ALL
|
|
419
429
|
// 777
|
|
420
|
-
}
|
|
430
|
+
},
|
|
431
|
+
stats
|
|
421
432
|
};
|
|
433
|
+
} else {
|
|
434
|
+
obj.stats = stats;
|
|
422
435
|
}
|
|
423
|
-
obj.stats = stats;
|
|
424
436
|
handler.sendBulk(responseId, JSON.stringify(obj));
|
|
425
437
|
} else {
|
|
426
438
|
let data2;
|
|
@@ -441,7 +453,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
441
453
|
}
|
|
442
454
|
} else if (namespace === this.namespaceMeta) {
|
|
443
455
|
if (id === "objects.primaryHost") {
|
|
444
|
-
handler.sendString(this.settings.hostname);
|
|
456
|
+
handler.sendString(responseId, this.settings.hostname);
|
|
445
457
|
} else {
|
|
446
458
|
const result = this.getMeta(id);
|
|
447
459
|
if (result === void 0 || result === null) {
|
|
@@ -456,6 +468,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
456
468
|
});
|
|
457
469
|
handler.on("set", (data, responseId) => {
|
|
458
470
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
471
|
+
if (!id) {
|
|
472
|
+
return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: id is null`));
|
|
473
|
+
}
|
|
459
474
|
if (namespace === this.namespaceObj) {
|
|
460
475
|
try {
|
|
461
476
|
const obj = JSON.parse(data[1].toString("utf-8"));
|
|
@@ -495,7 +510,10 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
495
510
|
handler.on("rename", (data, responseId) => {
|
|
496
511
|
const oldDetails = this._normalizeId(data[0]);
|
|
497
512
|
const newDetails = this._normalizeId(data[1]);
|
|
498
|
-
if (oldDetails.namespace === this.namespaceFile) {
|
|
513
|
+
if (!oldDetails.id || !newDetails.id || oldDetails.namespace === this.namespaceFile) {
|
|
514
|
+
if (!oldDetails.id || !newDetails.id) {
|
|
515
|
+
return void handler.sendError(responseId, new Error("ERROR renameObject: id needs to be not null"));
|
|
516
|
+
}
|
|
499
517
|
if (oldDetails.id !== newDetails.id) {
|
|
500
518
|
return void handler.sendError(responseId, new Error("ERROR renameObject: id needs to stay the same"));
|
|
501
519
|
}
|
|
@@ -515,6 +533,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
515
533
|
});
|
|
516
534
|
handler.on("del", (data, responseId) => {
|
|
517
535
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
536
|
+
if (!id) {
|
|
537
|
+
return void handler.sendError(responseId, new Error("id is null"));
|
|
538
|
+
}
|
|
518
539
|
if (namespace === this.namespaceObj) {
|
|
519
540
|
try {
|
|
520
541
|
this._delObject(id);
|
|
@@ -542,6 +563,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
542
563
|
return void handler.sendInteger(responseId, 0);
|
|
543
564
|
}
|
|
544
565
|
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
566
|
+
if (!id) {
|
|
567
|
+
return void handler.sendError(responseId, new Error("id is null"));
|
|
568
|
+
}
|
|
545
569
|
if (namespace === this.namespaceObj) {
|
|
546
570
|
let exists;
|
|
547
571
|
try {
|
|
@@ -593,6 +617,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
593
617
|
});
|
|
594
618
|
handler.on("psubscribe", (data, responseId) => {
|
|
595
619
|
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
620
|
+
if (!id) {
|
|
621
|
+
return void handler.sendError(responseId, new Error("id is null"));
|
|
622
|
+
}
|
|
596
623
|
if (namespace === this.namespaceObj) {
|
|
597
624
|
this._subscribeConfigForClient(handler, id);
|
|
598
625
|
handler.sendArray(responseId, ["psubscribe", data[0], 1]);
|
|
@@ -608,6 +635,9 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
608
635
|
});
|
|
609
636
|
handler.on("punsubscribe", (data, responseId) => {
|
|
610
637
|
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
638
|
+
if (!id) {
|
|
639
|
+
return void handler.sendError(responseId, new Error("id is null"));
|
|
640
|
+
}
|
|
611
641
|
if (namespace === this.namespaceObj) {
|
|
612
642
|
this._unsubscribeConfigForClient(handler, id);
|
|
613
643
|
handler.sendArray(responseId, ["punsubscribe", data[0], 1]);
|
|
@@ -650,6 +680,8 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
650
680
|
} else {
|
|
651
681
|
handler.sendNull(responseId);
|
|
652
682
|
}
|
|
683
|
+
} else if (typeof data[0] === "string" && data[0].toLowerCase() === "setinfo") {
|
|
684
|
+
handler.sendString(responseId, "OK");
|
|
653
685
|
} else {
|
|
654
686
|
handler.sendError(responseId, new Error(`CLIENT-UNSUPPORTED for ${JSON.stringify(data)}`));
|
|
655
687
|
}
|
|
@@ -659,7 +691,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
659
691
|
/**
|
|
660
692
|
* Return connected RedisHandlers/Connections
|
|
661
693
|
*
|
|
662
|
-
* @returns
|
|
694
|
+
* @returns the currently connected RedisHandlers/Connections
|
|
663
695
|
*/
|
|
664
696
|
getClients() {
|
|
665
697
|
return this.serverConnections;
|
|
@@ -692,11 +724,14 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
692
724
|
*
|
|
693
725
|
* @param handler RedisHandler instance
|
|
694
726
|
* @param pattern - pattern without namespace prefix
|
|
695
|
-
* @param responseId -
|
|
727
|
+
* @param responseId - ID where response will be sent to
|
|
696
728
|
* @param isScan - if used by "SCAN" this flag should be true
|
|
697
729
|
*/
|
|
698
730
|
_handleScanOrKeys(handler, pattern, responseId, isScan = false) {
|
|
699
731
|
const { id, namespace, name, isMeta } = this._normalizeId(pattern);
|
|
732
|
+
if (id === null) {
|
|
733
|
+
return void handler.sendError(responseId, new Error("id is null"));
|
|
734
|
+
}
|
|
700
735
|
let response = [];
|
|
701
736
|
if (namespace === this.namespaceObj || namespace === this.namespaceObjects) {
|
|
702
737
|
try {
|
|
@@ -713,7 +748,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
713
748
|
let res;
|
|
714
749
|
try {
|
|
715
750
|
res = this._readDir(id, name);
|
|
716
|
-
if (!res
|
|
751
|
+
if (!res?.length) {
|
|
717
752
|
res = [
|
|
718
753
|
{
|
|
719
754
|
file: "_data.json",
|
|
@@ -785,7 +820,7 @@ class ObjectsInMemoryServer extends import_objectsInMemFileDB.ObjectsInMemoryFil
|
|
|
785
820
|
* Initialize Redis Server
|
|
786
821
|
*
|
|
787
822
|
* @param settings Settings object
|
|
788
|
-
* @returns
|
|
823
|
+
* @returns a promise that resolves once the Redis server is listening
|
|
789
824
|
*/
|
|
790
825
|
_initRedisServer(settings) {
|
|
791
826
|
return new Promise((resolve, reject) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/lib/objects/objectsInMemServerRedis.
|
|
4
|
-
"sourcesContent": ["/**\n * Objects DB in memory - Server with Redis protocol\n *\n * Copyright 2013-2024 bluefox <dogafox@gmail.com>\n *\n * MIT License\n *\n */\n\nimport net from 'node:net';\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { objectsUtils as utils } from '@iobroker/db-objects-redis';\nimport { tools } from '@iobroker/db-base';\nimport { getLocalAddress } from '@iobroker/js-controller-common-db/tools';\nimport { EXIT_CODES } from '@iobroker/js-controller-common-db';\n\nimport { RedisHandler } from '@iobroker/db-base';\nimport { ObjectsInMemoryFileDB } from './objectsInMemFileDB.js';\n\n// settings = {\n// change: function (id, state) {},\n// connected: function (nameOfServer) {},\n// logger: {\n// silly: function (msg) {},\n// debug: function (msg) {},\n// info: function (msg) {},\n// warn: function (msg) {},\n// error: function (msg) {}\n// },\n// connection: {\n// dataDir: 'relative path'\n// },\n// auth: null, //unused\n// secure: true/false,\n// certificates: as required by createServer\n// port: 9001,\n// host: localhost\n// };\n//\n\n/**\n * This class inherits statesInMemoryFileDB class and adds redis communication layer\n * to access the methods via redis protocol\n */\nexport class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {\n /**\n * Constructor\n *\n * @param settings State and InMem-DB settings\n */\n constructor(settings) {\n super(settings);\n\n this.serverConnections = {};\n this.namespaceObjects = `${\n this.settings.redisNamespace || (settings.connection && settings.connection.redisNamespace) || 'cfg'\n }.`;\n this.namespaceFile = `${this.namespaceObjects}f.`;\n this.namespaceObj = `${this.namespaceObjects}o.`;\n this.namespaceSet = `${this.namespaceObjects}s.`;\n this.namespaceSetLen = this.namespaceSet.length;\n\n // this.namespaceObjectsLen = this.namespaceObjects.length;\n this.namespaceFileLen = this.namespaceFile.length;\n this.namespaceObjLen = this.namespaceObj.length;\n this.namespaceMeta = `${this.settings.namespaceMeta || 'meta'}.`;\n this.namespaceMetaLen = this.namespaceMeta.length;\n\n this.knownScripts = {};\n\n this.normalizeFileRegex1 = new RegExp('^(.*)\\\\$%\\\\$(.*)\\\\$%\\\\$(meta|data)$');\n this.normalizeFileRegex2 = new RegExp('^(.*)\\\\$%\\\\$(.*)\\\\/?\\\\*$');\n\n this.open()\n .then(() => {\n return this._initRedisServer(this.settings.connection);\n })\n .then(() => {\n this.log.debug(\n `${this.namespace} ${settings.secure ? 'Secure ' : ''} Redis inMem-objects listening on port ${\n this.settings.connection.port || 9001\n }`,\n );\n\n if (typeof this.settings.connected === 'function') {\n setImmediate(() => this.settings.connected());\n }\n })\n .catch(e => {\n this.log.error(\n `${this.namespace} Cannot start inMem-objects on port ${this.settings.connection.port || 9001}: ${e.message}`,\n );\n process.exit(EXIT_CODES.NO_CONNECTION_TO_OBJ_DB);\n });\n }\n\n /**\n * Separate Namespace from ID and return both\n *\n * @param idWithNamespace ID or Array of IDs containing a redis namespace and the real ID\n * @returns Object with namespace and the\n * ID/Array of IDs without the namespace\n */\n _normalizeId(idWithNamespace) {\n let ns = this.namespaceObjects;\n let id = null;\n let name = '';\n let isMeta;\n if (Array.isArray(idWithNamespace)) {\n const ids = [];\n idWithNamespace.forEach(el => {\n const { id, namespace } = this._normalizeId(el);\n ids.push(id);\n ns = namespace; // we ignore the pot. case from arrays with different namespaces\n });\n id = ids;\n } else if (typeof idWithNamespace === 'string') {\n id = idWithNamespace;\n if (idWithNamespace.startsWith(this.namespaceObjects)) {\n let idx = -1;\n if (idWithNamespace.startsWith(this.namespaceObj)) {\n idx = this.namespaceObjLen;\n } else if (idWithNamespace.startsWith(this.namespaceFile)) {\n idx = this.namespaceFileLen;\n } else if (idWithNamespace.startsWith(this.namespaceSet)) {\n idx = this.namespaceSetLen;\n }\n\n if (idx !== -1) {\n ns = idWithNamespace.substr(0, idx);\n id = idWithNamespace.substr(idx);\n }\n if (ns === this.namespaceFile) {\n let fileIdDetails = id.match(this.normalizeFileRegex1);\n if (fileIdDetails) {\n id = fileIdDetails[1];\n name = fileIdDetails[2] || '';\n isMeta = fileIdDetails[3] === 'meta';\n } else {\n fileIdDetails = id.match(this.normalizeFileRegex2);\n if (fileIdDetails) {\n id = fileIdDetails[1];\n name = fileIdDetails[2] || '';\n isMeta = undefined;\n } else {\n name = '';\n isMeta = undefined;\n }\n }\n }\n } else if (idWithNamespace.startsWith(this.namespaceMeta)) {\n const idx = this.namespaceMetaLen;\n if (idx !== -1) {\n ns = idWithNamespace.substr(0, idx);\n id = idWithNamespace.substr(idx);\n }\n }\n }\n return { id, namespace: ns, name, isMeta };\n }\n\n /**\n * Publish a subscribed value to one of the redis connections in redis format\n *\n * @param client Instance of RedisHandler\n * @param type Type of subscribed key\n * @param id Subscribed ID\n * @param obj Object to publish\n * @returns Publish counter 0 or 1 depending on if send out or not\n */\n publishToClients(client, type, id, obj) {\n if (!client._subscribe || !client._subscribe[type]) {\n return 0;\n }\n const s = client._subscribe[type];\n\n const found = s.find(sub => sub.regex.test(id));\n\n if (found) {\n if (type === 'meta') {\n this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${obj}`);\n const sendPattern = this.namespaceMeta + found.pattern;\n const sendId = this.namespaceMeta + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, obj]);\n } else if (type === 'files') {\n const objString = JSON.stringify(obj);\n this.log.silly(`${this.namespace} Redis Publish File ${id}=${objString}`);\n const sendPattern = this.namespaceFile + found.pattern;\n const sendId = this.namespaceFile + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);\n } else {\n const objString = JSON.stringify(obj);\n this.log.silly(`${this.namespace} Redis Publish Object ${id}=${objString}`);\n const sendPattern = (type === 'objects' ? '' : this.namespaceObjects) + found.pattern;\n const sendId = (type === 'objects' ? this.namespaceObj : this.namespaceObjects) + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);\n }\n return 1;\n }\n return 0;\n }\n\n /**\n * Generate ID for a File\n *\n * @param id ID of the File\n * @param name Name of the file\n * @param isMeta generate a META ID or a Data ID?\n * @returns File-ID\n */\n getFileId(id, name, isMeta) {\n // e.g. ekey.admin and admin/ekey.png\n if (id.endsWith('.admin')) {\n if (name.startsWith('admin/')) {\n name = name.replace(/^admin\\//, '');\n } else if (name.match(/^iobroker.[-\\d\\w]\\/admin\\//i)) {\n // e.g. ekey.admin and iobroker.ekey/admin/ekey.png\n name = name.replace(/^iobroker.[-\\d\\w]\\/admin\\//i, '');\n }\n }\n\n return `${this.namespaceFile + id}$%$${name}${isMeta !== undefined ? (isMeta ? '$%$meta' : '$%$data') : ''}`;\n }\n\n /**\n * Register all event listeners for Handler and implement the relevant logic\n *\n * @param handler RedisHandler instance\n */\n _socketEvents(handler) {\n let connectionName = null;\n let namespaceLog = this.namespace;\n\n // Handle Redis \"INFO\" request\n handler.on('info', (_data, responseId) => {\n let infoString = '# Server\\r\\n';\n infoString += 'redis_version:3.0.0-iobroker\\r\\n';\n infoString += '# Clients\\r\\n';\n infoString += '# Memory\\r\\n';\n infoString += '# Persistence\\r\\n';\n infoString += '# Stats\\r\\n';\n infoString += '# Replication\\r\\n';\n infoString += '# CPU\\r\\n';\n infoString += '# Cluster\\r\\n';\n infoString += '# Keyspace\\r\\n';\n infoString += `db0:keys=${Object.keys(this.dataset).length},expires=0,avg_ttl=98633637897`;\n handler.sendBulk(responseId, infoString);\n });\n\n // Handle Redis \"QUIT\" request\n handler.on('quit', (_data, responseId) => {\n this.log.silly(`${namespaceLog} Redis QUIT received, close connection`);\n handler.sendString(responseId, 'OK');\n handler.close();\n });\n\n // Handle Redis \"SCRIPT\" request\n handler.on('script', (data, responseId) => {\n data[0] = data[0].toLowerCase();\n if (data[0] === 'exists') {\n data.shift();\n const scripts = [];\n data.forEach(checksum => scripts.push(this.knownScripts[checksum] ? 1 : 0));\n handler.sendArray(responseId, scripts);\n } else if (data[0] === 'load') {\n const shasum = crypto.createHash('sha1');\n const buf = Buffer.from(data[1]);\n shasum.update(buf);\n const scriptChecksum = shasum.digest('hex');\n\n const scriptDesign = data[1].match(/^-- design: ([a-z0-9A-Z-.]+)\\s/m);\n const scriptFunc = data[1].match(/^-- func: (.+)$/m);\n if (scriptDesign && scriptDesign[1]) {\n const design = scriptDesign[1];\n let search = null;\n const scriptSearch = data[1].match(/^-- search: ([a-z0-9A-Z-.]*)\\s/m);\n if (scriptSearch && scriptSearch[1]) {\n search = scriptSearch[1];\n }\n\n this.knownScripts[scriptChecksum] = { design: design, search: search };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else if (scriptFunc && scriptFunc[1]) {\n this.knownScripts[scriptChecksum] = { func: scriptFunc[1] };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else if (data[1].includes('-- REDLOCK SCRIPT')) {\n // redlock scripts are currently not needed for Simulator\n this.knownScripts[scriptChecksum] = { redlock: true };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else {\n handler.sendError(responseId, new Error(`Unknown LUA script ${data[1]}`));\n }\n } else {\n handler.sendError(responseId, new Error(`Unsupported Script command ${data[0]}`));\n }\n });\n\n // Handle Redis \"EVALSHA\" request\n handler.on('evalsha', (data, responseId) => {\n if (!this.knownScripts[data[0]]) {\n return void handler.sendError(responseId, new Error(`Unknown Script ${data[0]}`));\n }\n if (this.knownScripts[data[0]].design) {\n const scriptDesign = this.knownScripts[data[0]].design;\n if (typeof data[2] === 'string' && data[2].startsWith(this.namespaceObj) && data.length > 4) {\n let scriptSearch = this.knownScripts[data[0]].search;\n if (scriptDesign === 'system' && !scriptSearch && data[5]) {\n scriptSearch = data[5];\n }\n if (!scriptSearch) {\n scriptSearch = 'state';\n }\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`,\n );\n }\n let objs;\n try {\n objs = this._getObjectView(scriptDesign, scriptSearch, {\n startkey: data[3],\n endkey: data[4],\n include_docs: true,\n });\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`_getObjectView Error for ${scriptDesign}/${scriptSearch}: ${err.message}`),\n );\n }\n\n const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));\n handler.sendArray(responseId, res);\n }\n } else if (this.knownScripts[data[0]].func && data.length > 4) {\n const scriptFunc = { map: this.knownScripts[data[0]].func.replace('%1', data[5]) };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(`${namespaceLog} Script transformed into _applyView: func=${scriptFunc.map}`);\n }\n const objs = this._applyView(scriptFunc, {\n startkey: data[3],\n endkey: data[4],\n include_docs: true,\n });\n const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));\n\n return void handler.sendArray(responseId, res);\n } else if (this.knownScripts[data[0]].redlock) {\n // just return a dummy\n return void handler.sendArray(responseId, [0]);\n } else {\n handler.sendError(responseId, new Error(`Unknown LUA script eval call ${JSON.stringify(data)}`));\n }\n });\n\n // Handle Redis \"PUBLISH\" request\n handler.on('publish', (data, responseId) => {\n const { id, namespace } = this._normalizeId(data[0]);\n\n if (\n namespace === this.namespaceObj ||\n namespace === this.namespaceMeta ||\n namespace === this.namespaceFile\n ) {\n // a \"set\" always comes afterwards, so do not publish\n return void handler.sendInteger(responseId, 0); // do not publish for now\n }\n const publishCount = this.publishAll(namespace.substr(0, namespace.length - 1), id, JSON.parse(data[1]));\n handler.sendInteger(responseId, publishCount);\n });\n\n // Handle Redis \"MGET\" requests\n handler.on('mget', (data, responseId) => {\n if (!data || !data.length) {\n return void handler.sendArray(responseId, []);\n }\n const { namespace, isMeta } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n const keys = [];\n data.forEach(dataId => {\n const { id, namespace } = this._normalizeId(dataId);\n if (namespace !== this.namespaceObj) {\n keys.push(null);\n this.log.warn(\n `${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`,\n );\n return;\n }\n keys.push(id);\n });\n let result;\n try {\n result = this._getObjects(keys);\n } catch (err) {\n return void handler.sendError(responseId, new Error(`ERROR _getObjects: ${err.message}`));\n }\n result = result.map(el => (el ? JSON.stringify(el) : null));\n handler.sendArray(responseId, result);\n } else if (namespace === this.namespaceFile) {\n // Handle request for Meta data for files\n if (isMeta) {\n const response = [];\n data.forEach(dataId => {\n const { id, namespace, name } = this._normalizeId(dataId);\n if (namespace !== this.namespaceFile) {\n response.push(null);\n this.log.warn(\n `${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`,\n );\n return;\n }\n this._loadFileSettings(id);\n if (!this.fileOptions[id] || !this.fileOptions[id][name]) {\n response.push(null);\n return;\n }\n const obj = this._clone(this.fileOptions[id][name]);\n try {\n obj.stats = fs.statSync(path.join(this.objectsDir, id, name));\n } catch (err) {\n if (!name.endsWith('/_data.json')) {\n this.log.warn(\n `${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`,\n );\n }\n response.push(null);\n return;\n }\n response.push(JSON.stringify(obj));\n });\n handler.sendArray(responseId, response);\n } else {\n // Handle request for File data\n handler.sendError(responseId, new Error('MGET-UNSUPPORTED for file data'));\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`MGET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"GET\" requests\n handler.on('get', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n const result = this._getObject(id);\n if (!result) {\n handler.sendNull(responseId);\n } else {\n handler.sendBulk(responseId, JSON.stringify(result));\n }\n } else if (namespace === this.namespaceFile) {\n // Handle request for Meta data for files\n if (isMeta) {\n let stats;\n try {\n stats = fs.statSync(path.join(this.objectsDir, id, name));\n } catch {\n return void handler.sendNull(responseId);\n }\n if (stats.isDirectory()) {\n return void handler.sendBulk(\n responseId,\n JSON.stringify({\n file: name,\n stats: {},\n isDir: true,\n }),\n );\n }\n this._loadFileSettings(id);\n if (!this.fileOptions[id] || !this.fileOptions[id][name]) {\n return void handler.sendNull(responseId);\n }\n\n let obj = this._clone(this.fileOptions[id][name]);\n if (typeof obj !== 'object') {\n obj = {\n mimeType: obj,\n acl: {\n owner:\n (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,\n ownerGroup:\n (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||\n utils.CONSTS.SYSTEM_ADMIN_GROUP,\n permissions:\n (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||\n utils.CONSTS.ACCESS_USER_ALL |\n utils.CONSTS.ACCESS_GROUP_ALL |\n utils.CONSTS.ACCESS_EVERY_ALL, // 777\n },\n };\n }\n obj.stats = stats;\n handler.sendBulk(responseId, JSON.stringify(obj));\n } else {\n // Handle request for File data\n let data;\n try {\n data = this._readFile(id, name);\n } catch {\n return void handler.sendNull(responseId);\n }\n if (data.fileContent === undefined || data.fileContent === null) {\n return void handler.sendNull(responseId);\n }\n let fileData = data.fileContent;\n if (!Buffer.isBuffer(fileData) && tools.isObject(fileData)) {\n // if its an invalid object, stringify it and log warning\n fileData = JSON.stringify(fileData);\n this.log.warn(\n `${namespaceLog} Data of \"${id}/${name}\" has invalid structure at file data request: ${fileData}`,\n );\n }\n handler.sendBufBulk(responseId, Buffer.from(fileData));\n }\n } else if (namespace === this.namespaceMeta) {\n // special handling for the primaryHost\n if (id === 'objects.primaryHost') {\n // we are the server -> we are primary\n handler.sendString(this.settings.hostname);\n } else {\n const result = this.getMeta(id);\n if (result === undefined || result === null) {\n handler.sendNull(responseId);\n } else {\n handler.sendBulk(responseId, result);\n }\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`GET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"SET\" requests\n handler.on('set', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n try {\n const obj = JSON.parse(data[1].toString('utf-8'));\n this._setObjectDirect(id, obj);\n } catch (err) {\n return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: ${err.message}`));\n }\n handler.sendString(responseId, 'OK');\n } else if (namespace === this.namespaceFile) {\n // Handle request to set meta-data, we ignore it because\n // will be set when data are written\n if (isMeta) {\n this._loadFileSettings(id);\n\n try {\n fs.ensureDirSync(path.join(this.objectsDir, id, path.dirname(name)));\n\n // only set if the meta-object is already/still existing\n if (this.fileOptions[id]) {\n this.fileOptions[id][name] = JSON.parse(data[1].toString('utf-8'));\n fs.writeFileSync(\n path.join(this.objectsDir, id, '_data.json'),\n JSON.stringify(this.fileOptions[id]),\n );\n }\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`),\n );\n }\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request to write the file\n try {\n this._writeFile(id, name, data[1]);\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`ERROR writeFile id=${id}: ${err.message}`),\n );\n }\n handler.sendString(responseId, 'OK');\n }\n } else if (namespace === this.namespaceMeta) {\n this.setMeta(id, data[1].toString('utf-8'));\n handler.sendString(responseId, 'OK');\n } else {\n handler.sendError(\n responseId,\n new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"RENAME\" requests\n handler.on('rename', (data, responseId) => {\n const oldDetails = this._normalizeId(data[0]);\n const newDetails = this._normalizeId(data[1]);\n\n if (oldDetails.namespace === this.namespaceFile) {\n if (oldDetails.id !== newDetails.id) {\n return void handler.sendError(\n responseId,\n new Error('ERROR renameObject: id needs to stay the same'),\n );\n }\n\n // Handle request for Meta data for files\n if (oldDetails.isMeta) {\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request for File data\n try {\n this._rename(oldDetails.id, oldDetails.name, newDetails.name);\n } catch {\n return void handler.sendNull(responseId);\n }\n handler.sendString(responseId, 'OK');\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"DEL\" request for state and session namespace\n handler.on('del', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n try {\n this._delObject(id);\n } catch (err) {\n return void handler.sendError(responseId, err);\n }\n handler.sendInteger(responseId, 1);\n } else if (namespace === this.namespaceFile) {\n // Handle request to delete meta-data, we ignore it because\n // will be removed when data are deleted\n if (isMeta) {\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request to remove the file\n try {\n this._unlink(id, name);\n } catch (err) {\n return void handler.sendError(responseId, err);\n }\n handler.sendString(responseId, 'OK');\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n handler.on('exists', (data, responseId) => {\n if (!data || !data.length) {\n return void handler.sendInteger(responseId, 0);\n }\n\n // Note: we only simulate single key existence check\n const { id, namespace, name } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n let exists;\n try {\n exists = this._objectExists(id);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n handler.sendInteger(responseId, exists ? 1 : 0);\n } else if (namespace === this.namespaceFile) {\n let exists;\n try {\n exists = this._fileExists(id, name);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n handler.sendInteger(responseId, exists ? 1 : 0);\n } else if (namespace === this.namespaceSet) {\n // we are not using sets in simulator, so just say it exists\n return void handler.sendInteger(responseId, 1);\n } else {\n handler.sendError(responseId, new Error(`EXISTS-UNSUPPORTED for namespace ${namespace}`));\n }\n });\n\n // handle Redis \"SCAN\" request for objects namespace\n handler.on('scan', (data, responseId) => {\n if (!data || data.length < 3) {\n return void handler.sendArray(responseId, ['0', []]);\n }\n\n return this._handleScanOrKeys(handler, data[2], responseId, true);\n });\n\n // Handle Redis \"KEYS\" request for state namespace\n handler.on('keys', (data, responseId) => {\n if (!data || !data.length) {\n return void handler.sendArray(responseId, []);\n }\n\n return this._handleScanOrKeys(handler, data[0], responseId);\n });\n\n // commands for redis SETS, just dummies\n handler.on('sadd', (data, responseId) => {\n return void handler.sendInteger(responseId, 1);\n });\n\n handler.on('srem', (data, responseId) => {\n return void handler.sendInteger(responseId, 1);\n });\n\n handler.on('eval', (data, responseId) => {\n return void handler.sendNull(responseId);\n });\n\n handler.on('sscan', (data, responseId) => {\n // for file DB it does the same as scan but data looks different\n if (!data || data.length < 4) {\n return void handler.sendArray(responseId, ['0', []]);\n }\n\n return this._handleScanOrKeys(handler, data[3], responseId, true);\n });\n\n // Handle Redis \"PSUBSCRIBE\" request for state, log and session namespace\n handler.on('psubscribe', (data, responseId) => {\n const { id, namespace, name } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n this._subscribeConfigForClient(handler, id);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else if (namespace === this.namespaceMeta) {\n this._subscribeMeta(handler, id);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else if (namespace === this.namespaceFile) {\n this._subscribeFileForClient(handler, id, name);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else {\n handler.sendError(\n responseId,\n new Error(`PSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"UNSUBSCRIBE\" request for state, log and session namespace\n handler.on('punsubscribe', (data, responseId) => {\n const { id, namespace, name } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n this._unsubscribeConfigForClient(handler, id);\n handler.sendArray(responseId, ['punsubscribe', data[0], 1]);\n } else if (namespace === this.namespaceFile) {\n this._unsubscribeFileForClient(handler, id, name);\n handler.sendArray(responseId, ['punsubscribe', data[0], 1]);\n } else {\n handler.sendError(\n responseId,\n new Error(`PUNSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"SUBSCRIBE\" ... currently mainly ignored\n handler.on('subscribe', (data, responseId) => {\n if (data[0].startsWith('__keyevent@')) {\n // we ignore these type of events because we publish expires anyway directly\n handler.sendArray(responseId, ['subscribe', data[0], 1]);\n } else {\n handler.sendError(responseId, new Error(`SUBSCRIBE-UNSUPPORTED for ${data[0]}`));\n }\n });\n\n // Handle Redis \"CONFIG\" ... currently mainly ignored\n handler.on('config', (data, responseId) => {\n const command = typeof data[0] === 'string' ? data[0].toLowerCase() : data[0].toString().toLowerCase();\n if (command === 'set' && data[1] === 'notify-keyspace-events') {\n // we ignore these type of commands for now, should only be to subscribe to keyspace events\n handler.sendString(responseId, 'OK');\n } else if (command === 'set' && data[1] === 'lua-time-limit') {\n // we ignore these type of commands for now, irrelevant\n handler.sendString(responseId, 'OK');\n } else {\n handler.sendError(responseId, new Error(`CONFIG-UNSUPPORTED for ${JSON.stringify(data)}`));\n }\n });\n\n // handle client SETNAME/GETNAME\n handler.on('client', (data, responseId) => {\n if (data[0] === 'setname' && typeof data[1] === 'string') {\n if (data[1] === '') {\n // on empty string redis sets null again and sends 'OK'\n connectionName = null;\n } else {\n connectionName = data[1];\n namespaceLog = connectionName;\n }\n handler.sendString(responseId, 'OK');\n } else if (data[0] === 'getname') {\n if (typeof connectionName === 'string' && connectionName !== '') {\n handler.sendString(responseId, connectionName);\n } else {\n // redis sends null if no name defined\n handler.sendNull(responseId);\n }\n } else {\n handler.sendError(responseId, new Error(`CLIENT-UNSUPPORTED for ${JSON.stringify(data)}`));\n }\n });\n\n handler.on('error', err => this.log.warn(`${namespaceLog} Redis objects: ${err}`));\n }\n\n /**\n * Return connected RedisHandlers/Connections\n *\n * @returns\n */\n getClients() {\n return this.serverConnections;\n }\n\n /**\n * Destructor of the class. Called by shutting down.\n */\n async destroy() {\n if (this.server) {\n Object.keys(this.serverConnections).forEach(s => {\n this.serverConnections[s].close();\n delete this.serverConnections[s];\n });\n\n await new Promise(resolve => {\n if (!this.server) {\n return void resolve();\n }\n try {\n this.server.close(() => resolve());\n } catch (e) {\n console.log(e.message);\n resolve();\n }\n });\n }\n\n await super.destroy();\n }\n\n /**\n * Get keys matching pattern and send it to given responseId, for \"SCAN\" and \"KEYS\" - Objects and files supported\n *\n * @param handler RedisHandler instance\n * @param pattern - pattern without namespace prefix\n * @param responseId - Id where response will be sent to\n * @param isScan - if used by \"SCAN\" this flag should be true\n */\n _handleScanOrKeys(handler, pattern, responseId, isScan = false) {\n const { id, namespace, name, isMeta } = this._normalizeId(pattern);\n\n let response = [];\n if (namespace === this.namespaceObj || namespace === this.namespaceObjects) {\n try {\n response = this._getKeys(id).map(val => this.namespaceObj + val);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n\n // if scan, we send the cursor as first argument\n if (namespace !== this.namespaceObjects) {\n // When it was not the full DB namespace send out response\n return void handler.sendArray(responseId, isScan ? ['0', response] : response);\n }\n }\n if (namespace === this.namespaceFile || namespace === this.namespaceObjects) {\n // Handle request to get meta data keys\n if (isMeta === undefined) {\n let res;\n try {\n res = this._readDir(id, name);\n if (!res || !res.length) {\n res = [\n {\n file: '_data.json',\n stats: {},\n isDir: false,\n virtualFile: true,\n notExists: true,\n },\n ];\n }\n } catch (e) {\n if (!e.message.endsWith(utils.ERRORS.ERROR_NOT_FOUND)) {\n return void handler.sendError(responseId, new Error(`ERROR readDir id=${id}: ${e.message}`));\n }\n res = [];\n }\n let baseName = name || '';\n if (baseName.length && !baseName.endsWith('/')) {\n baseName += '/';\n }\n res.forEach(arr => {\n let entryId = id;\n if (arr.isDir) {\n if (entryId === '' || entryId === '*') {\n entryId = arr.file;\n arr.file = '_data.json'; // We return a \"virtual file\" to mark the directory as existing\n } else {\n arr.file += '/_data.json'; // We return a \"virtual file\" to mark the directory as existing\n }\n }\n // We need to simulate the Meta data here, so return both\n response.push(this.getFileId(entryId, baseName + arr.file, true));\n response.push(this.getFileId(entryId, baseName + arr.file, false));\n });\n handler.sendArray(responseId, isScan ? ['0', response] : response); // send out file or full db response\n } else {\n // such a request should never happen\n handler.sendArray(responseId, isScan ? ['0', []] : []); // send out file or full db response\n }\n } else if (namespace === this.namespaceSet) {\n handler.sendArray(responseId, isScan ? ['0', []] : []); // send out empty array, we have no sets\n } else {\n handler.sendError(\n responseId,\n new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`),\n );\n }\n }\n\n /**\n * Initialize RedisHandler for a new network connection\n *\n * @param socket Network socket\n */\n _initSocket(socket) {\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(`${this.namespace} Handling new Redis Objects connection`);\n }\n const options = {\n log: this.log,\n logScope: `${this.settings.namespace || ''} Objects`,\n handleAsBuffers: true,\n enhancedLogging: this.settings.connection.enhancedLogging,\n };\n const handler = new RedisHandler(socket, options);\n this._socketEvents(handler);\n\n this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`] = handler;\n socket.on('close', () => {\n if (this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`]) {\n delete this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`];\n }\n });\n }\n\n /**\n * Initialize Redis Server\n *\n * @param settings Settings object\n * @returns\n */\n _initRedisServer(settings) {\n return new Promise((resolve, reject) => {\n if (settings.secure) {\n reject(new Error('Secure Redis unsupported for File-DB'));\n }\n try {\n this.server = net.createServer();\n this.server.on('error', err =>\n this.log.info(\n `${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${\n settings.port || 9001\n }: ${err}`,\n ),\n );\n this.server.on('connection', socket => this._initSocket(socket));\n\n this.server.listen(\n settings.port || 9001,\n settings.host === 'localhost' ? getLocalAddress() : settings.host ? settings.host : undefined,\n () => resolve(),\n );\n } catch (err) {\n reject(err);\n }\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_db_base", "
|
|
3
|
+
"sources": ["../../../../src/lib/objects/objectsInMemServerRedis.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Objects DB in memory - Server with Redis protocol\n *\n * Copyright 2013-2024 bluefox <dogafox@gmail.com>\n *\n * MIT License\n *\n */\n\nimport net from 'node:net';\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { objectsUtils as utils } from '@iobroker/db-objects-redis';\nimport { tools } from '@iobroker/db-base';\nimport { getLocalAddress } from '@iobroker/js-controller-common-db/tools';\nimport { EXIT_CODES } from '@iobroker/js-controller-common-db';\n\nimport { RedisHandler, type ConnectionOptions, type FileDbSettings } from '@iobroker/db-base';\nimport { type FileOptions, ObjectsInMemoryFileDB } from './objectsInMemFileDB.js';\n\n// settings = {\n// change: function (id, state) {},\n// connected: function (nameOfServer) {},\n// logger: {\n// silly: function (msg) {},\n// debug: function (msg) {},\n// info: function (msg) {},\n// warn: function (msg) {},\n// error: function (msg) {}\n// },\n// connection: {\n// dataDir: 'relative path'\n// },\n// auth: null, //unused\n// secure: true/false,\n// certificates: as required by createServer\n// port: 9001,\n// host: localhost\n// };\n//\ntype RedisHandlerInternal = RedisHandler & {\n _subscribe?: Record<\n string,\n {\n pattern: string;\n regex: RegExp;\n }[]\n >;\n};\n\n/**\n * This class inherits statesInMemoryFileDB class and adds redis communication layer\n * to access the methods via redis protocol\n */\nexport class ObjectsInMemoryServer extends ObjectsInMemoryFileDB<RedisHandlerInternal> {\n private readonly serverConnections: Record<string, RedisHandler> = {};\n private readonly namespaceObjects: string;\n private readonly namespaceFile: string;\n private readonly namespaceObj: string;\n private readonly namespaceSet: string;\n private readonly namespaceSetLen: number;\n private readonly namespaceFileLen: number;\n private readonly namespaceObjLen: number;\n private readonly namespaceMeta: string;\n private readonly namespaceMetaLen: number;\n private readonly knownScripts: Record<\n string,\n { design?: string; search?: string; redlock?: boolean; func?: string }\n > = {};\n private readonly normalizeFileRegex1: RegExp;\n private readonly normalizeFileRegex2: RegExp;\n private server: net.Server | undefined;\n\n /**\n * Constructor\n *\n * @param settings State and InMem-DB settings\n */\n constructor(settings: FileDbSettings<ioBroker.AnyObject>) {\n super(settings);\n\n this.namespaceObjects = `${this.settings.redisNamespace || settings.connection?.redisNamespace || 'cfg'}.`;\n this.namespaceFile = `${this.namespaceObjects}f.`;\n this.namespaceObj = `${this.namespaceObjects}o.`;\n this.namespaceSet = `${this.namespaceObjects}s.`;\n this.namespaceSetLen = this.namespaceSet.length;\n\n // this.namespaceObjectsLen = this.namespaceObjects.length;\n this.namespaceFileLen = this.namespaceFile.length;\n this.namespaceObjLen = this.namespaceObj.length;\n this.namespaceMeta = `${this.settings.namespaceMeta || 'meta'}.`;\n this.namespaceMetaLen = this.namespaceMeta.length;\n\n this.normalizeFileRegex1 = new RegExp('^(.*)\\\\$%\\\\$(.*)\\\\$%\\\\$(meta|data)$');\n this.normalizeFileRegex2 = new RegExp('^(.*)\\\\$%\\\\$(.*)\\\\/?\\\\*$');\n\n this.open()\n .then(() => this._initRedisServer(this.settings.connection))\n .then(() => {\n this.log.debug(\n `${this.namespace} ${settings.secure ? 'Secure ' : ''} Redis inMem-objects listening on port ${\n (this.settings.connection.port as number) || 9001\n }`,\n );\n\n if (typeof this.settings.connected === 'function') {\n setImmediate(() => this.settings.connected());\n }\n })\n .catch(e => {\n this.log.error(\n `${this.namespace} Cannot start inMem-objects on port ${(this.settings.connection.port as number) || 9001}: ${e.message}`,\n );\n process.exit(EXIT_CODES.NO_CONNECTION_TO_OBJ_DB);\n });\n }\n\n /**\n * Separate Namespace from ID and return both\n *\n * @param idWithNamespace ID or Array of IDs containing a redis namespace and the real ID\n * @returns Object with namespace and the\n * ID/Array of IDs without the namespace\n */\n _normalizeId(idWithNamespace: string): {\n id: string | null;\n namespace: string;\n name: string;\n isMeta: boolean | undefined;\n } {\n let ns = this.namespaceObjects;\n let id: string | null = null;\n let name = '';\n let isMeta;\n if (typeof idWithNamespace === 'string') {\n id = idWithNamespace;\n if (idWithNamespace.startsWith(this.namespaceObjects)) {\n let idx = -1;\n if (idWithNamespace.startsWith(this.namespaceObj)) {\n idx = this.namespaceObjLen;\n } else if (idWithNamespace.startsWith(this.namespaceFile)) {\n idx = this.namespaceFileLen;\n } else if (idWithNamespace.startsWith(this.namespaceSet)) {\n idx = this.namespaceSetLen;\n }\n\n if (idx !== -1) {\n ns = idWithNamespace.substr(0, idx);\n id = idWithNamespace.substr(idx);\n }\n if (ns === this.namespaceFile) {\n let fileIdDetails = id.match(this.normalizeFileRegex1);\n if (fileIdDetails) {\n id = fileIdDetails[1];\n name = fileIdDetails[2] || '';\n isMeta = fileIdDetails[3] === 'meta';\n } else {\n fileIdDetails = id.match(this.normalizeFileRegex2);\n if (fileIdDetails) {\n id = fileIdDetails[1];\n name = fileIdDetails[2] || '';\n isMeta = undefined;\n } else {\n name = '';\n isMeta = undefined;\n }\n }\n }\n } else if (idWithNamespace.startsWith(this.namespaceMeta)) {\n const idx = this.namespaceMetaLen;\n if (idx !== -1) {\n ns = idWithNamespace.substr(0, idx);\n id = idWithNamespace.substr(idx);\n }\n }\n }\n return { id, namespace: ns, name, isMeta };\n }\n\n /**\n * Publish a subscribed value to one of the redis connections in redis format\n *\n * @param client Instance of RedisHandler\n * @param type Type of subscribed key\n * @param id Subscribed ID\n * @param obj Object to publish\n * @returns Publish counter 0 or 1 depending on if send out or not\n */\n publishToClients(\n client: RedisHandlerInternal,\n type: string,\n id: string,\n obj: ioBroker.AnyObject | ioBroker.DesignObject,\n ): number {\n if (!client._subscribe?.[type]) {\n return 0;\n }\n const s = client._subscribe[type];\n\n const found = s.find(sub => sub.regex.test(id));\n\n if (found) {\n if (type === 'meta') {\n this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${JSON.stringify(obj)}`);\n const sendPattern = this.namespaceMeta + found.pattern;\n const sendId = this.namespaceMeta + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, obj]);\n } else if (type === 'files') {\n const objString = JSON.stringify(obj);\n this.log.silly(`${this.namespace} Redis Publish File ${id}=${objString}`);\n const sendPattern = this.namespaceFile + found.pattern;\n const sendId = this.namespaceFile + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);\n } else {\n const objString = JSON.stringify(obj);\n this.log.silly(`${this.namespace} Redis Publish Object ${id}=${objString}`);\n const sendPattern = (type === 'objects' ? '' : this.namespaceObjects) + found.pattern;\n const sendId = (type === 'objects' ? this.namespaceObj : this.namespaceObjects) + id;\n client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);\n }\n return 1;\n }\n return 0;\n }\n\n /**\n * Generate ID for a File\n *\n * @param id ID of the File\n * @param name Name of the file\n * @param isMeta generate a META ID or a Data ID?\n * @returns File-ID\n */\n getFileId(id: string, name: string, isMeta?: boolean): string {\n // e.g. ekey.admin and admin/ekey.png\n if (id.endsWith('.admin')) {\n if (name.startsWith('admin/')) {\n name = name.replace(/^admin\\//, '');\n } else if (name.match(/^iobroker.[-\\d\\w]\\/admin\\//i)) {\n // e.g. ekey.admin and iobroker.ekey/admin/ekey.png\n name = name.replace(/^iobroker.[-\\d\\w]\\/admin\\//i, '');\n }\n }\n\n return `${this.namespaceFile + id}$%$${name}${isMeta !== undefined ? (isMeta ? '$%$meta' : '$%$data') : ''}`;\n }\n\n /**\n * Register all event listeners for Handler and implement the relevant logic\n *\n * @param handler RedisHandler instance\n */\n _socketEvents(handler: RedisHandler): void {\n let connectionName: string | null = null;\n let namespaceLog = this.namespace;\n\n // Handle Redis \"INFO\" request\n handler.on('info', (_data, responseId) => {\n let infoString = '# Server\\r\\n';\n infoString += 'redis_version:3.0.0-iobroker\\r\\n';\n infoString += '# Clients\\r\\n';\n infoString += '# Memory\\r\\n';\n infoString += '# Persistence\\r\\n';\n infoString += '# Stats\\r\\n';\n infoString += '# Replication\\r\\n';\n infoString += '# CPU\\r\\n';\n infoString += '# Cluster\\r\\n';\n infoString += '# Keyspace\\r\\n';\n infoString += `db0:keys=${Object.keys(this.dataset).length},expires=0,avg_ttl=98633637897`;\n handler.sendBulk(responseId, infoString);\n });\n\n // Handle Redis \"QUIT\" request\n handler.on('quit', (_data, responseId) => {\n this.log.silly(`${namespaceLog} Redis QUIT received, close connection`);\n handler.sendString(responseId, 'OK');\n handler.close();\n });\n\n // Handle Redis \"SCRIPT\" request\n handler.on('script', (data: [command: 'exists' | 'load', buffer: string], responseId) => {\n data[0] = data[0].toLowerCase() as 'exists' | 'load';\n if (data[0] === 'exists') {\n data.shift();\n const scripts: number[] = [];\n data.forEach((checksum: string) => scripts.push(this.knownScripts[checksum] ? 1 : 0));\n handler.sendArray(responseId, scripts);\n } else if (data[0] === 'load') {\n const shasum = crypto.createHash('sha1');\n const buf = Buffer.from(data[1]);\n shasum.update(buf);\n const scriptChecksum = shasum.digest('hex');\n\n const scriptDesign = data[1].match(/^-- design: ([a-z0-9A-Z-.]+)\\s/m);\n const scriptFunc = data[1].match(/^-- func: (.+)$/m);\n if (scriptDesign?.[1]) {\n const design = scriptDesign[1];\n let search: string | undefined;\n const scriptSearch = data[1].match(/^-- search: ([a-z0-9A-Z-.]*)\\s/m);\n if (scriptSearch?.[1]) {\n search = scriptSearch[1];\n }\n\n this.knownScripts[scriptChecksum] = { design, search };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else if (scriptFunc?.[1]) {\n this.knownScripts[scriptChecksum] = { func: scriptFunc[1] };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else if (data[1].includes('-- REDLOCK SCRIPT')) {\n // redlock scripts are currently not needed for Simulator\n this.knownScripts[scriptChecksum] = { redlock: true };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(\n this.knownScripts[scriptChecksum],\n )}`,\n );\n }\n handler.sendBulk(responseId, scriptChecksum);\n } else {\n handler.sendError(responseId, new Error(`Unknown LUA script ${data[1]}`));\n }\n } else {\n handler.sendError(responseId, new Error(`Unsupported Script command ${data[0] as string}`));\n }\n });\n\n // Handle Redis \"EVALSHA\" request\n handler.on(\n 'evalsha',\n (\n data: [\n scriptId: string,\n ignore: string,\n name: string,\n startkey: string,\n endkey: string,\n search: string,\n ],\n responseId,\n ) => {\n if (!this.knownScripts[data[0]]) {\n return void handler.sendError(responseId, new Error(`Unknown Script ${data[0]}`));\n }\n if (this.knownScripts[data[0]].design) {\n const scriptDesign: string = this.knownScripts[data[0]].design!;\n if (typeof data[2] === 'string' && data[2].startsWith(this.namespaceObj) && data.length > 4) {\n let scriptSearch = this.knownScripts[data[0]].search;\n if (scriptDesign === 'system' && !scriptSearch && data[5]) {\n scriptSearch = data[5];\n }\n if (!scriptSearch) {\n scriptSearch = 'state';\n }\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(\n `${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`,\n );\n }\n let objs;\n try {\n objs = this._getObjectView(scriptDesign, scriptSearch, {\n startkey: data[3],\n endkey: data[4],\n include_docs: true,\n });\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`_getObjectView Error for ${scriptDesign}/${scriptSearch}: ${err.message}`),\n );\n }\n\n const res = objs.rows.map(obj =>\n JSON.stringify(this.dataset[(obj.value as ioBroker.AnyObject)._id || obj.id]),\n );\n handler.sendArray(responseId, res);\n }\n } else if (this.knownScripts[data[0]].func && data.length > 4) {\n const scriptFunc = { map: this.knownScripts[data[0]].func!.replace('%1', data[5]) };\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(`${namespaceLog} Script transformed into _applyView: func=${scriptFunc.map}`);\n }\n const objs = this._applyView(scriptFunc, {\n startkey: data[3],\n endkey: data[4],\n include_docs: true,\n });\n const res = objs.rows.map(obj =>\n JSON.stringify(this.dataset[(obj.value as ioBroker.AnyObject)._id || obj.id]),\n );\n\n return void handler.sendArray(responseId, res);\n } else if (this.knownScripts[data[0]].redlock) {\n // just return a dummy\n return void handler.sendArray(responseId, [0]);\n } else {\n handler.sendError(responseId, new Error(`Unknown LUA script eval call ${JSON.stringify(data)}`));\n }\n },\n );\n\n // Handle Redis \"PUBLISH\" request\n handler.on('publish', (data: [addr: string, obj: string], responseId) => {\n const { id, namespace } = this._normalizeId(data[0]);\n\n if (\n namespace === this.namespaceObj ||\n namespace === this.namespaceMeta ||\n namespace === this.namespaceFile ||\n !id\n ) {\n // a \"set\" always comes afterwards, so do not publish\n return void handler.sendInteger(responseId, 0); // do not publish for now\n }\n const publishCount = this.publishAll(namespace.substr(0, namespace.length - 1), id, JSON.parse(data[1]));\n handler.sendInteger(responseId, publishCount);\n });\n\n // Handle Redis \"MGET\" requests\n handler.on('mget', (data: string[], responseId) => {\n if (!data?.length) {\n return void handler.sendArray(responseId, []);\n }\n const { namespace, isMeta } = this._normalizeId(data[0]);\n\n if (namespace === this.namespaceObj) {\n const keys: (string | null)[] = [];\n data.forEach((dataId: string) => {\n const { id, namespace } = this._normalizeId(dataId);\n if (namespace !== this.namespaceObj) {\n keys.push(null);\n this.log.warn(\n `${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`,\n );\n return;\n }\n keys.push(id);\n });\n let result: (ioBroker.AnyObject | ioBroker.DesignObject | Record<string, string> | undefined)[];\n try {\n result = this._getObjects(keys);\n } catch (err) {\n return void handler.sendError(responseId, new Error(`ERROR _getObjects: ${err.message}`));\n }\n const resultObjs = result.map(el => (el ? JSON.stringify(el) : null));\n handler.sendArray(responseId, resultObjs);\n } else if (namespace === this.namespaceFile) {\n // Handle request for Metadata for files\n if (isMeta) {\n const response: (string | null)[] = [];\n data.forEach((dataId: string) => {\n const { id, namespace, name } = this._normalizeId(dataId);\n if (!id || namespace !== this.namespaceFile) {\n response.push(null);\n this.log.warn(\n `${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`,\n );\n return;\n }\n this._loadFileSettings(id);\n if (!this.fileOptions[id] || !this.fileOptions[id][name]) {\n response.push(null);\n return;\n }\n const obj: FileOptions = this._clone(this.fileOptions[id][name]);\n try {\n obj.stats = fs.statSync(path.join(this.objectsDir, id, name));\n } catch (err) {\n if (!name.endsWith('/_data.json')) {\n this.log.warn(\n `${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`,\n );\n }\n response.push(null);\n return;\n }\n response.push(JSON.stringify(obj));\n });\n handler.sendArray(responseId, response);\n } else {\n // Handle request for File data\n handler.sendError(responseId, new Error('MGET-UNSUPPORTED for file data'));\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`MGET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"GET\" requests\n handler.on('get', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (!id) {\n handler.sendNull(responseId);\n return;\n }\n if (namespace === this.namespaceObj) {\n const result = this._getObject(id);\n if (!result) {\n handler.sendNull(responseId);\n } else {\n handler.sendBulk(responseId, JSON.stringify(result));\n }\n } else if (namespace === this.namespaceFile) {\n // Handle request for Metadata for files\n if (isMeta) {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(path.join(this.objectsDir, id, name));\n } catch {\n return void handler.sendNull(responseId);\n }\n if (stats.isDirectory()) {\n return void handler.sendBulk(\n responseId,\n JSON.stringify({\n file: name,\n stats: {},\n isDir: true,\n }),\n );\n }\n this._loadFileSettings(id);\n if (!this.fileOptions[id] || !this.fileOptions[id][name]) {\n return void handler.sendNull(responseId);\n }\n\n let obj: FileOptions = this._clone(this.fileOptions[id][name]);\n if (typeof obj !== 'object') {\n obj = {\n mimeType: obj,\n acl: {\n owner: this.defaultNewAcl?.owner || utils.CONSTS.SYSTEM_ADMIN_USER,\n ownerGroup: this.defaultNewAcl?.ownerGroup || utils.CONSTS.SYSTEM_ADMIN_GROUP,\n permissions:\n this.defaultNewAcl?.file ||\n utils.CONSTS.ACCESS_USER_ALL |\n utils.CONSTS.ACCESS_GROUP_ALL |\n utils.CONSTS.ACCESS_EVERY_ALL, // 777\n },\n stats,\n };\n } else {\n obj.stats = stats;\n }\n handler.sendBulk(responseId, JSON.stringify(obj));\n } else {\n // Handle request for File data\n let data;\n try {\n data = this._readFile(id, name);\n } catch {\n return void handler.sendNull(responseId);\n }\n if (data.fileContent === undefined || data.fileContent === null) {\n return void handler.sendNull(responseId);\n }\n let fileData = data.fileContent;\n if (!Buffer.isBuffer(fileData) && tools.isObject(fileData)) {\n // if it's an invalid object, stringify it and log warning\n fileData = JSON.stringify(fileData);\n this.log.warn(\n `${namespaceLog} Data of \"${id}/${name}\" has invalid structure at file data request: ${fileData}`,\n );\n }\n handler.sendBufBulk(responseId, Buffer.from(fileData));\n }\n } else if (namespace === this.namespaceMeta) {\n // special handling for the primaryHost\n if (id === 'objects.primaryHost') {\n // we are the server -> we are primary\n handler.sendString(responseId, this.settings.hostname as string);\n } else {\n const result = this.getMeta(id);\n if (result === undefined || result === null) {\n handler.sendNull(responseId);\n } else {\n handler.sendBulk(responseId, result);\n }\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`GET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"SET\" requests\n handler.on('set', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (!id) {\n return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: id is null`));\n }\n\n if (namespace === this.namespaceObj) {\n try {\n const obj = JSON.parse(data[1].toString('utf-8'));\n this._setObjectDirect(id, obj);\n } catch (err) {\n return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: ${err.message}`));\n }\n handler.sendString(responseId, 'OK');\n } else if (namespace === this.namespaceFile) {\n // Handle request to set meta-data, we ignore it because\n // will be set when data are written\n if (isMeta) {\n this._loadFileSettings(id);\n\n try {\n fs.ensureDirSync(path.join(this.objectsDir, id, path.dirname(name)));\n\n // only set if the meta-object is already/still existing\n if (this.fileOptions[id]) {\n this.fileOptions[id][name] = JSON.parse(data[1].toString('utf-8'));\n fs.writeFileSync(\n path.join(this.objectsDir, id, '_data.json'),\n JSON.stringify(this.fileOptions[id]),\n );\n }\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`),\n );\n }\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request to write the file\n try {\n this._writeFile(id, name, data[1]);\n } catch (err) {\n return void handler.sendError(\n responseId,\n new Error(`ERROR writeFile id=${id}: ${err.message}`),\n );\n }\n handler.sendString(responseId, 'OK');\n }\n } else if (namespace === this.namespaceMeta) {\n this.setMeta(id, data[1].toString('utf-8'));\n handler.sendString(responseId, 'OK');\n } else {\n handler.sendError(\n responseId,\n new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"RENAME\" requests\n handler.on('rename', (data, responseId) => {\n const oldDetails = this._normalizeId(data[0]);\n const newDetails = this._normalizeId(data[1]);\n\n if (!oldDetails.id || !newDetails.id || oldDetails.namespace === this.namespaceFile) {\n if (!oldDetails.id || !newDetails.id) {\n return void handler.sendError(responseId, new Error('ERROR renameObject: id needs to be not null'));\n }\n if (oldDetails.id !== newDetails.id) {\n return void handler.sendError(\n responseId,\n new Error('ERROR renameObject: id needs to stay the same'),\n );\n }\n\n // Handle request for Metadata for files\n if (oldDetails.isMeta) {\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request for File data\n try {\n this._rename(oldDetails.id, oldDetails.name, newDetails.name);\n } catch {\n return void handler.sendNull(responseId);\n }\n handler.sendString(responseId, 'OK');\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"DEL\" request for state and session namespace\n handler.on('del', (data, responseId) => {\n const { id, namespace, name, isMeta } = this._normalizeId(data[0]);\n\n if (!id) {\n return void handler.sendError(responseId, new Error('id is null'));\n }\n if (namespace === this.namespaceObj) {\n try {\n this._delObject(id);\n } catch (err) {\n return void handler.sendError(responseId, err);\n }\n handler.sendInteger(responseId, 1);\n } else if (namespace === this.namespaceFile) {\n // Handle request to delete meta-data, we ignore it because\n // will be removed when data are deleted\n if (isMeta) {\n handler.sendString(responseId, 'OK');\n } else {\n // Handle request to remove the file\n try {\n this._unlink(id, name);\n } catch (err) {\n return void handler.sendError(responseId, err);\n }\n handler.sendString(responseId, 'OK');\n }\n } else {\n handler.sendError(\n responseId,\n new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n handler.on('exists', (data, responseId) => {\n if (!data || !data.length) {\n return void handler.sendInteger(responseId, 0);\n }\n\n // Note: we only simulate single key existence check\n const { id, namespace, name } = this._normalizeId(data[0]);\n if (!id) {\n return void handler.sendError(responseId, new Error('id is null'));\n }\n if (namespace === this.namespaceObj) {\n let exists;\n try {\n exists = this._objectExists(id);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n handler.sendInteger(responseId, exists ? 1 : 0);\n } else if (namespace === this.namespaceFile) {\n let exists;\n try {\n exists = this._fileExists(id, name);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n handler.sendInteger(responseId, exists ? 1 : 0);\n } else if (namespace === this.namespaceSet) {\n // we are not using sets in simulator, so just say it exists\n return void handler.sendInteger(responseId, 1);\n } else {\n handler.sendError(responseId, new Error(`EXISTS-UNSUPPORTED for namespace ${namespace}`));\n }\n });\n\n // handle Redis \"SCAN\" request for objects namespace\n handler.on('scan', (data, responseId) => {\n if (!data || data.length < 3) {\n return void handler.sendArray(responseId, ['0', []]);\n }\n\n return this._handleScanOrKeys(handler, data[2], responseId, true);\n });\n\n // Handle Redis \"KEYS\" request for state namespace\n handler.on('keys', (data, responseId) => {\n if (!data || !data.length) {\n return void handler.sendArray(responseId, []);\n }\n\n return this._handleScanOrKeys(handler, data[0], responseId);\n });\n\n // commands for redis SETS, just dummies\n handler.on('sadd', (data, responseId) => {\n return void handler.sendInteger(responseId, 1);\n });\n\n handler.on('srem', (data, responseId) => {\n return void handler.sendInteger(responseId, 1);\n });\n\n handler.on('eval', (data, responseId) => {\n return void handler.sendNull(responseId);\n });\n\n handler.on('sscan', (data, responseId) => {\n // for file DB it does the same as scan but data looks different\n if (!data || data.length < 4) {\n return void handler.sendArray(responseId, ['0', []]);\n }\n\n return this._handleScanOrKeys(handler, data[3], responseId, true);\n });\n\n // Handle Redis \"PSUBSCRIBE\" request for state, log and session namespace\n handler.on('psubscribe', (data, responseId) => {\n const { id, namespace, name } = this._normalizeId(data[0]);\n if (!id) {\n return void handler.sendError(responseId, new Error('id is null'));\n }\n if (namespace === this.namespaceObj) {\n this._subscribeConfigForClient(handler, id);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else if (namespace === this.namespaceMeta) {\n this._subscribeMeta(handler, id);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else if (namespace === this.namespaceFile) {\n this._subscribeFileForClient(handler, id, name);\n handler.sendArray(responseId, ['psubscribe', data[0], 1]);\n } else {\n handler.sendError(\n responseId,\n new Error(`PSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"UNSUBSCRIBE\" request for state, log and session namespace\n handler.on('punsubscribe', (data, responseId) => {\n const { id, namespace, name } = this._normalizeId(data[0]);\n if (!id) {\n return void handler.sendError(responseId, new Error('id is null'));\n }\n if (namespace === this.namespaceObj) {\n this._unsubscribeConfigForClient(handler, id);\n handler.sendArray(responseId, ['punsubscribe', data[0], 1]);\n } else if (namespace === this.namespaceFile) {\n this._unsubscribeFileForClient(handler, id, name);\n handler.sendArray(responseId, ['punsubscribe', data[0], 1]);\n } else {\n handler.sendError(\n responseId,\n new Error(`PUNSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`),\n );\n }\n });\n\n // Handle Redis \"SUBSCRIBE\" ... currently mainly ignored\n handler.on('subscribe', (data, responseId) => {\n if (data[0].startsWith('__keyevent@')) {\n // we ignore these type of events because we publish expires anyway directly\n handler.sendArray(responseId, ['subscribe', data[0], 1]);\n } else {\n handler.sendError(responseId, new Error(`SUBSCRIBE-UNSUPPORTED for ${data[0]}`));\n }\n });\n\n // Handle Redis \"CONFIG\" ... currently mainly ignored\n handler.on('config', (data, responseId) => {\n const command = typeof data[0] === 'string' ? data[0].toLowerCase() : data[0].toString().toLowerCase();\n if (command === 'set' && data[1] === 'notify-keyspace-events') {\n // we ignore these type of commands for now, should only be to subscribe to keyspace events\n handler.sendString(responseId, 'OK');\n } else if (command === 'set' && data[1] === 'lua-time-limit') {\n // we ignore these type of commands for now, irrelevant\n handler.sendString(responseId, 'OK');\n } else {\n handler.sendError(responseId, new Error(`CONFIG-UNSUPPORTED for ${JSON.stringify(data)}`));\n }\n });\n\n // handle client SETNAME/GETNAME\n handler.on('client', (data, responseId) => {\n if (data[0] === 'setname' && typeof data[1] === 'string') {\n if (data[1] === '') {\n // on empty string redis sets null again and sends 'OK'\n connectionName = null;\n } else {\n connectionName = data[1];\n namespaceLog = connectionName;\n }\n handler.sendString(responseId, 'OK');\n } else if (data[0] === 'getname') {\n if (typeof connectionName === 'string' && connectionName !== '') {\n handler.sendString(responseId, connectionName);\n } else {\n // redis sends null if no name defined\n handler.sendNull(responseId);\n }\n } else if (typeof data[0] === 'string' && data[0].toLowerCase() === 'setinfo') {\n // ioredis >= 5.8 announces its lib-name/lib-ver via CLIENT SETINFO on connect.\n // Real Redis (>= 7.2) replies OK, so acknowledge it to stay compatible.\n handler.sendString(responseId, 'OK');\n } else {\n handler.sendError(responseId, new Error(`CLIENT-UNSUPPORTED for ${JSON.stringify(data)}`));\n }\n });\n\n handler.on('error', err => this.log.warn(`${namespaceLog} Redis objects: ${err}`));\n }\n\n /**\n * Return connected RedisHandlers/Connections\n *\n * @returns the currently connected RedisHandlers/Connections\n */\n getClients(): Record<string, RedisHandler> {\n return this.serverConnections;\n }\n\n /**\n * Destructor of the class. Called by shutting down.\n */\n async destroy(): Promise<void> {\n if (this.server) {\n Object.keys(this.serverConnections).forEach(s => {\n this.serverConnections[s].close();\n delete this.serverConnections[s];\n });\n\n await new Promise<void>(resolve => {\n if (!this.server) {\n return void resolve();\n }\n try {\n this.server.close(() => resolve());\n } catch (e) {\n console.log((e as Error).message);\n resolve();\n }\n });\n }\n\n await super.destroy();\n }\n\n /**\n * Get keys matching pattern and send it to given responseId, for \"SCAN\" and \"KEYS\" - Objects and files supported\n *\n * @param handler RedisHandler instance\n * @param pattern - pattern without namespace prefix\n * @param responseId - ID where response will be sent to\n * @param isScan - if used by \"SCAN\" this flag should be true\n */\n _handleScanOrKeys(handler: RedisHandler, pattern: string, responseId: number, isScan = false): void {\n const { id, namespace, name, isMeta } = this._normalizeId(pattern);\n // `_normalizeId` returns id === '' for a full-DB enumeration; only `null` means \"no id\".\n if (id === null) {\n return void handler.sendError(responseId, new Error('id is null'));\n }\n let response: string[] = [];\n if (namespace === this.namespaceObj || namespace === this.namespaceObjects) {\n try {\n response = this._getKeys(id).map(val => this.namespaceObj + val);\n } catch (e) {\n return void handler.sendError(responseId, e);\n }\n\n // if \"scan\", we send the cursor as first argument\n if (namespace !== this.namespaceObjects) {\n // When it was not the full DB namespace send out response\n return void handler.sendArray(responseId, isScan ? ['0', response] : response);\n }\n }\n if (namespace === this.namespaceFile || namespace === this.namespaceObjects) {\n // Handle request to get metadata keys\n if (isMeta === undefined) {\n let res: {\n file: string;\n stats: { size?: number };\n isDir: boolean;\n virtualFile?: boolean;\n notExists?: boolean;\n acl?: {\n read?: boolean;\n write?: boolean;\n owner: ioBroker.ObjectIDs.User;\n ownerGroup: ioBroker.ObjectIDs.Group;\n permissions: number;\n };\n modifiedAt?: number | undefined;\n createdAt?: undefined | number;\n }[];\n try {\n res = this._readDir(id, name);\n if (!res?.length) {\n res = [\n {\n file: '_data.json',\n stats: {},\n isDir: false,\n virtualFile: true,\n notExists: true,\n },\n ];\n }\n } catch (e) {\n if (!e.message.endsWith(utils.ERRORS.ERROR_NOT_FOUND)) {\n return void handler.sendError(responseId, new Error(`ERROR readDir id=${id}: ${e.message}`));\n }\n res = [];\n }\n let baseName = name || '';\n if (baseName.length && !baseName.endsWith('/')) {\n baseName += '/';\n }\n res.forEach(arr => {\n let entryId = id;\n if (arr.isDir) {\n if (entryId === '' || entryId === '*') {\n entryId = arr.file;\n arr.file = '_data.json'; // We return a \"virtual file\" to mark the directory as existing\n } else {\n arr.file += '/_data.json'; // We return a \"virtual file\" to mark the directory as existing\n }\n }\n // We need to simulate the Metadata here, so return both\n response.push(this.getFileId(entryId, baseName + arr.file, true));\n response.push(this.getFileId(entryId, baseName + arr.file, false));\n });\n handler.sendArray(responseId, isScan ? ['0', response] : response); // send out file or full db response\n } else {\n // such a request should never happen\n handler.sendArray(responseId, isScan ? ['0', []] : []); // send out file or full db response\n }\n } else if (namespace === this.namespaceSet) {\n handler.sendArray(responseId, isScan ? ['0', []] : []); // send out empty array, we have no sets\n } else {\n handler.sendError(\n responseId,\n new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`),\n );\n }\n }\n\n /**\n * Initialize RedisHandler for a new network connection\n *\n * @param socket Network socket\n */\n _initSocket(socket: net.Socket): void {\n if (this.settings.connection.enhancedLogging) {\n this.log.silly(`${this.namespace} Handling new Redis Objects connection`);\n }\n const options = {\n log: this.log,\n logScope: `${this.settings.namespace || ''} Objects`,\n handleAsBuffers: true,\n enhancedLogging: this.settings.connection.enhancedLogging,\n };\n const handler = new RedisHandler(socket, options);\n this._socketEvents(handler);\n\n this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`] = handler;\n socket.on('close', () => {\n if (this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`]) {\n delete this.serverConnections[`${socket.remoteAddress}:${socket.remotePort}`];\n }\n });\n }\n\n /**\n * Initialize Redis Server\n *\n * @param settings Settings object\n * @returns a promise that resolves once the Redis server is listening\n */\n _initRedisServer(settings: ConnectionOptions): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (settings.secure) {\n reject(new Error('Secure Redis unsupported for File-DB'));\n }\n try {\n this.server = net.createServer();\n this.server.on('error', err =>\n this.log.info(\n `${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${\n (settings.port as number) || 9001\n }: ${err}`,\n ),\n );\n this.server.on('connection', socket => this._initSocket(socket));\n\n this.server.listen(\n (settings.port as number) || 9001,\n settings.host === 'localhost'\n ? getLocalAddress()\n : settings.host\n ? (settings.host as string)\n : undefined,\n () => resolve(),\n );\n } catch (err) {\n reject(err as Error);\n }\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_db_base", "crypto", "namespace", "fs", "path", "utils", "data", "net"]
|
|
7
7
|
}
|