iobroker.javascript 8.9.2 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/admin/assets/{createSvgIcon-BdRvDw53.js → createSvgIcon-BQT-7-GS.js} +1 -1
- package/admin/assets/{docs-6na4NFtj.js → docs-BrInh2Pn.js} +2 -2
- package/admin/assets/index-B0RKH_iG.js +1329 -0
- package/admin/assets/index-CfuHVX2B.js +193 -0
- package/admin/assets/index-CuCs5aLs.js +5 -0
- package/admin/assets/index-tExaxF69.js +930 -0
- package/admin/assets/inheritsLoose--KnFDOw1.js +36 -0
- package/admin/assets/{useTheme-Cl1QmYFL.js → useTheme-DF6qfrtI.js} +1 -1
- package/admin/custom/assets/{Components-ChpTW7sE.js → Components-D9kRsHNY.js} +1 -1
- package/admin/custom/assets/{DefaultPropsProvider-CHpMCMgA.js → DefaultPropsProvider-9qubdy-V.js} +2 -2
- package/admin/custom/assets/{FilledInput-CtcQVKyj.js → FilledInput-BpuM_GyB.js} +1 -1
- package/admin/custom/assets/Tabs-CvEv0KOT.js +138 -0
- package/admin/custom/assets/ThemeProvider-DZTpMR8n.js +29 -0
- package/admin/custom/assets/{createSvgIcon-C_vAELFU.js → createSvgIcon-BQThUM-f.js} +1 -1
- package/admin/custom/assets/hostInit-CrAs5YZS.js +1 -1
- package/admin/custom/assets/{index-DwsbskQy.js → index-DIWNdd4a.js} +1 -1
- package/admin/custom/assets/index-DZqbj5K4.js +55 -0
- package/admin/custom/assets/{index-D5apCzjJ.js → index-Dbe-II7_.js} +6 -6
- package/admin/custom/assets/index-az76fZMP.js +904 -0
- package/admin/custom/assets/index-sawv1cUe.js +1399 -0
- package/admin/custom/assets/{virtualExposes-BPncCdUy.js → virtualExposes-BMKIjWrE.js} +2 -2
- package/admin/custom/customComponents.js +2 -2
- package/admin/custom/i18n/de.json +29 -29
- package/admin/custom/i18n/es.json +29 -29
- package/admin/custom/i18n/fr.json +29 -29
- package/admin/custom/i18n/it.json +29 -29
- package/admin/custom/i18n/nl.json +29 -29
- package/admin/custom/i18n/pl.json +29 -29
- package/admin/custom/i18n/pt.json +29 -29
- package/admin/custom/i18n/ru.json +29 -29
- package/admin/custom/i18n/uk.json +29 -29
- package/admin/custom/i18n/zh-cn.json +29 -29
- package/admin/google-blockly/blockly_compressed.js +875 -887
- package/admin/google-blockly/blocks_compressed.js +38 -41
- package/admin/google-blockly/javascript_compressed.js +19 -54
- package/admin/google-blockly/media/delete-icon.svg +1 -0
- package/admin/google-blockly/media/foldout-icon.svg +1 -0
- package/admin/google-blockly/media/resize-handle.svg +3 -0
- package/admin/jsonConfig.json +2 -0
- package/admin/mf-manifest.json +1 -1
- package/admin/remoteEntry.js +2 -2
- package/admin/tab.html +4 -4
- package/admin/vsFont/README.md +1 -1
- package/admin/vsFont/createJson.js +1 -1
- package/build-backend/lib/consts.js +346 -0
- package/build-backend/lib/consts.js.map +1 -0
- package/build-backend/lib/convert.js +120 -0
- package/build-backend/lib/convert.js.map +1 -0
- package/build-backend/lib/debug.js +163 -0
- package/build-backend/lib/debug.js.map +1 -0
- package/{lib → build-backend/lib}/debugger.js +261 -232
- package/build-backend/lib/debugger.js.map +1 -0
- package/build-backend/lib/eventObj.js +177 -0
- package/build-backend/lib/eventObj.js.map +1 -0
- package/build-backend/lib/inspect.js +728 -0
- package/build-backend/lib/inspect.js.map +1 -0
- package/build-backend/lib/javascript.d.ts +1972 -0
- package/{lib → build-backend/lib}/mirror.js +185 -182
- package/build-backend/lib/mirror.js.map +1 -0
- package/build-backend/lib/nodeModulesManagement.js +25 -0
- package/build-backend/lib/nodeModulesManagement.js.map +1 -0
- package/build-backend/lib/patternCompareFunctions.js +321 -0
- package/build-backend/lib/patternCompareFunctions.js.map +1 -0
- package/build-backend/lib/protectFs.js +477 -0
- package/build-backend/lib/protectFs.js.map +1 -0
- package/build-backend/lib/request.js +89 -0
- package/build-backend/lib/request.js.map +1 -0
- package/{lib → build-backend/lib}/sandbox.js +2046 -1852
- package/build-backend/lib/sandbox.js.map +1 -0
- package/build-backend/lib/scheduler.js +553 -0
- package/build-backend/lib/scheduler.js.map +1 -0
- package/build-backend/lib/tools.js +183 -0
- package/build-backend/lib/tools.js.map +1 -0
- package/build-backend/lib/typescriptSettings.js +39 -0
- package/build-backend/lib/typescriptSettings.js.map +1 -0
- package/build-backend/lib/typescriptTools.js +435 -0
- package/build-backend/lib/typescriptTools.js.map +1 -0
- package/build-backend/lib/utils.js +66 -0
- package/build-backend/lib/utils.js.map +1 -0
- package/{lib → build-backend/lib}/words.js +23 -30
- package/build-backend/lib/words.js.map +1 -0
- package/build-backend/main.js +2671 -0
- package/build-backend/main.js.map +1 -0
- package/build-backend/types.d.ts +742 -0
- package/docs/de/README.md +1 -1
- package/docs/en/README.md +1 -1
- package/docs/en/javascript.md +10 -6
- package/docs/ru/README.md +1 -1
- package/install/installTypings.js +34 -47
- package/io-package.json +14 -14
- package/package.json +14 -14
- package/admin/assets/index-DCkkMRRa.js +0 -1335
- package/admin/assets/index-DJfSBoBB.js +0 -192
- package/admin/assets/index-DTiA4WdK.js +0 -930
- package/admin/assets/index-qABB1JVe.js +0 -5
- package/admin/assets/inheritsLoose-BW-3V39H.js +0 -36
- package/admin/custom/assets/Tabs-C1KOyWRi.js +0 -137
- package/admin/custom/assets/ThemeProvider-Buvx5nSd.js +0 -29
- package/admin/custom/assets/index-BGCRznKh.js +0 -904
- package/admin/custom/assets/index-DfBPYXqA.js +0 -55
- package/admin/custom/assets/index-jIr6kOLK.js +0 -1398
- package/lib/adapter-config.d.ts +0 -16
- package/lib/consts.js +0 -83
- package/lib/convert.js +0 -106
- package/lib/debug.js +0 -154
- package/lib/eventObj.js +0 -201
- package/lib/inspect.js +0 -688
- package/lib/javascript.d.ts +0 -1858
- package/lib/nodeModulesManagement.js +0 -26
- package/lib/patternCompareFunctions.js +0 -391
- package/lib/protectFs.js +0 -401
- package/lib/request.js +0 -72
- package/lib/scheduler.js +0 -447
- package/lib/tools.js +0 -192
- package/lib/typescriptSettings.js +0 -44
- package/lib/typescriptTools.js +0 -529
- package/lib/utils.js +0 -87
- package/main.js +0 -2653
|
@@ -1,121 +1,122 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Mirror = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
5
6
|
const MODE_0777 = 511;
|
|
6
|
-
|
|
7
7
|
class Mirror {
|
|
8
|
+
adapter;
|
|
9
|
+
diskRoot;
|
|
10
|
+
from;
|
|
11
|
+
lastSyncID;
|
|
12
|
+
log;
|
|
13
|
+
watchedFolder = {};
|
|
14
|
+
diskList;
|
|
15
|
+
dbList = {};
|
|
8
16
|
constructor(options) {
|
|
9
|
-
if (!options || !options.diskRoot) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
17
|
if (!options.adapter) {
|
|
13
18
|
throw new Error('No adapter defined');
|
|
14
19
|
}
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
this.adapter = options.adapter;
|
|
21
|
+
this.diskRoot = (0, node_path_1.normalize)(options.diskRoot || '').replace(/\\/g, '/');
|
|
22
|
+
this.from = `system.adapter.${this.adapter.namespace}`;
|
|
23
|
+
this.lastSyncID = `${this.from}.lastSync`;
|
|
24
|
+
this.diskList = {};
|
|
25
|
+
if (options.log) {
|
|
26
|
+
this.log = options.log;
|
|
27
|
+
this.log.log = this.log.log || ((text) => console.log(text));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.log = {
|
|
31
|
+
silly: text => console.log(text),
|
|
32
|
+
debug: text => console.log(text),
|
|
33
|
+
info: text => console.log(text),
|
|
34
|
+
log: text => console.log(text),
|
|
35
|
+
warn: text => console.warn(text),
|
|
36
|
+
error: text => console.error(text),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!options.diskRoot || options.adapter.namespace !== 'javascript.0') {
|
|
17
40
|
// only instance 0 can sync objects
|
|
18
41
|
return;
|
|
19
42
|
}
|
|
20
|
-
|
|
21
|
-
this.adapter = options.adapter;
|
|
22
|
-
this.watchedFolder = {};
|
|
23
|
-
this.diskRoot = path.normalize(options.diskRoot).replace(/\\/g, '/');
|
|
24
|
-
this.from = `system.adapter.${this.adapter.namespace}`;
|
|
25
|
-
this.lastSyncID = `${this.from}.lastSync`;
|
|
26
|
-
|
|
27
|
-
this.log = options.log || {
|
|
28
|
-
silly: text => console.log(text),
|
|
29
|
-
debug: text => console.log(text),
|
|
30
|
-
info: text => console.log(text),
|
|
31
|
-
log: text => console.log(text),
|
|
32
|
-
warn: text => console.warn(text),
|
|
33
|
-
error: text => console.error(text),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
if (!fs.existsSync(this.diskRoot)) {
|
|
43
|
+
if (!(0, node_fs_1.existsSync)(this.diskRoot)) {
|
|
37
44
|
try {
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
45
|
+
(0, node_fs_1.mkdirSync)(this.diskRoot);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
this.log.error(`Cannot create directory ${this.diskRoot}: ${err}`);
|
|
49
|
+
return;
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
|
-
|
|
44
52
|
this.diskList = this.scanDisk();
|
|
45
53
|
this.checkLastSyncObject(lastSyncTime => {
|
|
46
54
|
this.scanDB(list => {
|
|
47
55
|
this.dbList = list;
|
|
48
56
|
this.sync(lastSyncTime);
|
|
49
|
-
|
|
50
57
|
this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
|
|
51
|
-
|
|
52
58
|
// monitor all folders
|
|
53
59
|
this.watchFolders(this.diskRoot);
|
|
54
60
|
});
|
|
55
61
|
});
|
|
56
62
|
}
|
|
57
|
-
|
|
58
63
|
watchFolders(root_) {
|
|
59
64
|
root_ = root_.endsWith('/') ? root_ : `${root_}/`;
|
|
60
|
-
|
|
61
65
|
// ignore all .xxx folders, like ".git", ".idea", so users may not have scripts starting with "."
|
|
62
66
|
try {
|
|
63
|
-
const files =
|
|
67
|
+
const files = (0, node_fs_1.readdirSync)(root_).filter(name => !name.startsWith('.'));
|
|
64
68
|
files.forEach(file => {
|
|
65
|
-
const name =
|
|
66
|
-
const stat =
|
|
67
|
-
|
|
69
|
+
const name = (0, node_path_1.join)(root_, file).replace(/\\/g, '/');
|
|
70
|
+
const stat = (0, node_fs_1.statSync)(name);
|
|
68
71
|
if (stat.isDirectory()) {
|
|
69
72
|
this.watchFolders(name);
|
|
70
|
-
}
|
|
71
|
-
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const lstat = (0, node_fs_1.lstatSync)(name);
|
|
72
76
|
if (!lstat.isSymbolicLink()) {
|
|
73
77
|
return;
|
|
74
78
|
}
|
|
75
|
-
|
|
76
|
-
const linkTarget = fs.realpathSync(name);
|
|
77
|
-
|
|
79
|
+
const linkTarget = (0, node_fs_1.realpathSync)(name);
|
|
78
80
|
this.log.info(`Watch symlinked file ${name} -> ${linkTarget}`);
|
|
79
|
-
|
|
81
|
+
(0, node_fs_1.watch)(linkTarget, (eventType /*, _filename*/) => {
|
|
80
82
|
// Pretend the symlink source was changed.
|
|
81
83
|
this.log.debug(`File ${name} ${eventType}`);
|
|
82
84
|
this.onFileChange(eventType, name);
|
|
83
85
|
});
|
|
84
86
|
}
|
|
85
87
|
});
|
|
86
|
-
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
87
90
|
return this.log.warn(`Error while trying to watch folder ${root_}: ${err}`);
|
|
88
91
|
}
|
|
89
|
-
|
|
90
92
|
if (!this.watchedFolder[root_]) {
|
|
91
93
|
this.log.info(`Watch ${root_}`);
|
|
92
94
|
try {
|
|
93
|
-
this.watchedFolder[root_] =
|
|
95
|
+
this.watchedFolder[root_] = (0, node_fs_1.watch)(root_, (eventType, fileName) => {
|
|
94
96
|
this.log.debug(`File ${root_}${fileName} ${eventType}`);
|
|
95
97
|
this.onFileChange(eventType, root_ + fileName);
|
|
96
98
|
});
|
|
97
|
-
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
98
101
|
this.log.error(`Could not watch folder ${root_}: ${err.message}`);
|
|
99
102
|
this.log.error(`Please check that no other processes change data in the mirror directory!`);
|
|
100
103
|
}
|
|
101
|
-
|
|
102
104
|
this.watchedFolder[root_].on('error', () => {
|
|
103
105
|
this.log.debug(`Folder ${root_} was deleted`);
|
|
104
106
|
try {
|
|
105
107
|
this.watchedFolder[root_] && this.watchedFolder[root_].close();
|
|
106
|
-
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
107
110
|
// ignore error
|
|
108
111
|
}
|
|
109
|
-
|
|
110
112
|
if (this.watchedFolder[root_]) {
|
|
111
113
|
delete this.watchedFolder[root_];
|
|
112
114
|
}
|
|
113
115
|
});
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
|
-
|
|
117
118
|
checkLastSyncObject(cb) {
|
|
118
|
-
this.adapter.getForeignObject(this.lastSyncID, (_err, obj) => {
|
|
119
|
+
void this.adapter.getForeignObject(this.lastSyncID, (_err, obj) => {
|
|
119
120
|
if (!obj) {
|
|
120
121
|
// create variable
|
|
121
122
|
const obj = {
|
|
@@ -129,23 +130,20 @@ class Mirror {
|
|
|
129
130
|
read: true,
|
|
130
131
|
},
|
|
131
132
|
type: 'state',
|
|
133
|
+
native: {},
|
|
132
134
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this.adapter.getForeignState(this.lastSyncID, (_err, state) =>
|
|
138
|
-
cb && cb(state && state.val));
|
|
135
|
+
this.adapter.setForeignObject(this.lastSyncID, obj, () => this.adapter.setForeignState(this.lastSyncID, 0, true, () => cb && cb(0)));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
void this.adapter.getForeignState(this.lastSyncID, (_err, state) => cb && cb(state?.val));
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
|
-
|
|
143
142
|
static getDBFolder(id) {
|
|
144
143
|
const parts = id.split('.');
|
|
145
144
|
parts.pop();
|
|
146
145
|
return parts.join('.');
|
|
147
146
|
}
|
|
148
|
-
|
|
149
147
|
static isBlockly(data) {
|
|
150
148
|
const pos = data.lastIndexOf('\n');
|
|
151
149
|
if (pos !== -1) {
|
|
@@ -159,7 +157,6 @@ class Mirror {
|
|
|
159
157
|
}
|
|
160
158
|
return false;
|
|
161
159
|
}
|
|
162
|
-
|
|
163
160
|
static isRules(data) {
|
|
164
161
|
const pos = data.lastIndexOf('\n');
|
|
165
162
|
if (pos !== -1) {
|
|
@@ -170,75 +167,68 @@ class Mirror {
|
|
|
170
167
|
}
|
|
171
168
|
return false;
|
|
172
169
|
}
|
|
173
|
-
|
|
174
170
|
static detectType(fileName, data) {
|
|
175
171
|
if (fileName.endsWith('.ts')) {
|
|
176
172
|
return 'TypeScript/ts';
|
|
177
|
-
} else {
|
|
178
|
-
return Mirror.isBlockly(data) ? 'Blockly' : (Mirror.isRules(data) ? 'Rules' : 'JavaScript/js');
|
|
179
173
|
}
|
|
174
|
+
return Mirror.isBlockly(data) ? 'Blockly' : Mirror.isRules(data) ? 'Rules' : 'JavaScript/js';
|
|
180
175
|
}
|
|
181
|
-
|
|
182
176
|
updateFolderTime(id) {
|
|
183
177
|
this.dbList[id].ts = Date.now();
|
|
184
178
|
this.dbList[id].from = this.from;
|
|
185
|
-
this.adapter.setForeignObject(id, this.dbList[id]);
|
|
179
|
+
void this.adapter.setForeignObject(id, this.dbList[id]);
|
|
186
180
|
}
|
|
187
|
-
|
|
188
181
|
_getDiskPath(pathDisk) {
|
|
189
|
-
return
|
|
182
|
+
return (0, node_path_1.join)(this.diskRoot, pathDisk.join('/')).replace(/\\/g, '/');
|
|
190
183
|
}
|
|
191
184
|
static _getDbPath(pathDB) {
|
|
192
185
|
if (!pathDB || !pathDB.length) {
|
|
193
186
|
return 'script.js';
|
|
194
|
-
} else {
|
|
195
|
-
return `script.js.${pathDB.join('.')}`;
|
|
196
187
|
}
|
|
188
|
+
return `script.js.${pathDB.join('.')}`;
|
|
197
189
|
}
|
|
198
|
-
|
|
199
190
|
_getFilesInPath(pathDisk) {
|
|
200
191
|
pathDisk = pathDisk.substring(this.diskRoot.length + 1);
|
|
201
192
|
const id = pathDisk.replace(/\./g, '\\.').replace(/[/\\]/g, '\\.');
|
|
202
193
|
const reg = new RegExp(`script\\.js${id ? `.${id}` : ''}\\.[^.]+$`);
|
|
203
194
|
return Object.keys(this.diskList)
|
|
204
195
|
.filter(file => reg.test(file))
|
|
205
|
-
.map(id => id.split('.').pop());
|
|
196
|
+
.map(id => id.split('.').pop() || '');
|
|
206
197
|
}
|
|
207
198
|
_getObjectsInPath(pathDB) {
|
|
208
|
-
const reg = new RegExp(pathDB.replace(/\./g, '\\.')
|
|
209
|
-
return Object.keys(this.dbList)
|
|
199
|
+
const reg = new RegExp(`${pathDB.replace(/\./g, '\\.')}\\.[^.]+$`);
|
|
200
|
+
return Object.keys(this.dbList)
|
|
201
|
+
.filter(id => reg.test(id))
|
|
202
|
+
.map(id => id.split('.').pop() || '');
|
|
210
203
|
}
|
|
211
|
-
|
|
212
204
|
/**
|
|
213
205
|
* Write file to disk, synchron, catch (and print) error.
|
|
214
|
-
*
|
|
215
|
-
* @
|
|
216
|
-
* @
|
|
206
|
+
*
|
|
207
|
+
* @param id of script
|
|
208
|
+
* @returns true if write was successful
|
|
217
209
|
*/
|
|
218
210
|
_writeFile(id) {
|
|
219
211
|
const diskListEntry = this.diskList[id];
|
|
220
212
|
try {
|
|
221
213
|
//check if the directory exists and create if not:
|
|
222
|
-
|
|
223
|
-
|
|
214
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(diskListEntry.name), { recursive: true, mode: MODE_0777 });
|
|
215
|
+
(0, node_fs_1.writeFileSync)(diskListEntry.name, diskListEntry.source, { mode: MODE_0777 });
|
|
224
216
|
diskListEntry.ts = Date.now();
|
|
225
217
|
return true;
|
|
226
|
-
}
|
|
227
|
-
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
this.log.error(`Cannot write file ${diskListEntry ? diskListEntry.name : id}: ${err}`);
|
|
228
221
|
return false;
|
|
229
222
|
}
|
|
230
223
|
}
|
|
231
|
-
|
|
232
224
|
sync(lastSyncTime, pathDisk, pathDB) {
|
|
233
225
|
lastSyncTime = lastSyncTime || 0;
|
|
234
226
|
pathDisk = pathDisk || [];
|
|
235
227
|
pathDB = pathDB || [];
|
|
236
|
-
|
|
237
228
|
const dirDisk = this._getDiskPath(pathDisk);
|
|
238
|
-
const dirDB
|
|
239
|
-
const files
|
|
229
|
+
const dirDB = Mirror._getDbPath(pathDB);
|
|
230
|
+
const files = this._getFilesInPath(dirDisk);
|
|
240
231
|
const objects = this._getObjectsInPath(dirDB);
|
|
241
|
-
|
|
242
232
|
for (let o = objects.length - 1; o >= 0; o--) {
|
|
243
233
|
// if folder
|
|
244
234
|
if (this.dbList[`${dirDB}.${objects[o]}`] && this.dbList[`${dirDB}.${objects[o]}`].type === 'channel') {
|
|
@@ -249,29 +239,31 @@ class Mirror {
|
|
|
249
239
|
nextPathDB.push(objects[o]);
|
|
250
240
|
objects.splice(o, 1);
|
|
251
241
|
this.sync(lastSyncTime, nextPathDisk, nextPathDB);
|
|
252
|
-
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
253
244
|
// try to find this DB script on disk
|
|
254
245
|
for (let f = files.length - 1; f >= 0; f--) {
|
|
255
246
|
if (objects[o] === files[f]) {
|
|
256
247
|
const id = `${dirDB}.${objects[o]}`;
|
|
257
|
-
|
|
258
248
|
if (!this.diskList[id]) {
|
|
259
249
|
continue;
|
|
260
250
|
}
|
|
261
|
-
|
|
262
|
-
|
|
251
|
+
if (!this.dbList[id].ts ||
|
|
252
|
+
(this.dbList[id].ts > this.diskList[id].ts &&
|
|
253
|
+
this.dbList[id].ts - this.diskList[id].ts > 2000)) {
|
|
263
254
|
// copy text to file
|
|
264
255
|
this.dbList[id].ts = Date.now();
|
|
265
256
|
this.diskList[id].source = this.dbList[id].common.source;
|
|
266
257
|
this.log.debug(`Update disk with ${this.diskList[id].name}`);
|
|
267
258
|
this._writeFile(id);
|
|
268
|
-
}
|
|
259
|
+
}
|
|
260
|
+
else if (this.dbList[id].ts && this.diskList[id].ts - this.dbList[id].ts > 2000) {
|
|
269
261
|
// copy file to DB
|
|
270
262
|
this.dbList[id].common.source = this.diskList[id].source;
|
|
271
263
|
this.dbList[id].ts = this.diskList[id].ts;
|
|
272
264
|
this.dbList[id].from = this.from;
|
|
273
265
|
this.log.debug(`Update DB with ${id}`);
|
|
274
|
-
this.adapter.setForeignObject(id, this.dbList[id]);
|
|
266
|
+
void this.adapter.setForeignObject(id, this.dbList[id]);
|
|
275
267
|
}
|
|
276
268
|
files.splice(f, 1);
|
|
277
269
|
objects.splice(o, 1);
|
|
@@ -280,16 +272,17 @@ class Mirror {
|
|
|
280
272
|
}
|
|
281
273
|
}
|
|
282
274
|
}
|
|
283
|
-
|
|
284
275
|
// go through objects, that does not exist on disk
|
|
285
276
|
for (let o = objects.length - 1; o >= 0; o--) {
|
|
286
277
|
const fileName = this._scriptId2FileName(`${dirDB}.${objects[o]}`, this.dbList[`${dirDB}.${objects[o]}`].common.engineType);
|
|
287
278
|
this.log.info(`Created script file on disk ${fileName}`);
|
|
288
|
-
const f = `script.js.${fileName
|
|
289
|
-
|
|
279
|
+
const f = `script.js.${fileName
|
|
280
|
+
.substring(this.diskRoot.length)
|
|
281
|
+
.replace(/[\\/]/g, '.')
|
|
282
|
+
.replace(/\.js$|\.ts$/g, '')}`;
|
|
283
|
+
this.diskList[f] = { name: fileName, source: this.dbList[`${dirDB}.${objects[o]}`].common.source, ts: 0 };
|
|
290
284
|
this._writeFile(f);
|
|
291
285
|
}
|
|
292
|
-
|
|
293
286
|
// go through files, that does not exist in DB
|
|
294
287
|
for (let f = files.length - 1; f >= 0; f--) {
|
|
295
288
|
// read creation time
|
|
@@ -309,22 +302,23 @@ class Mirror {
|
|
|
309
302
|
},
|
|
310
303
|
type: 'script',
|
|
311
304
|
ts: this.diskList[id].ts,
|
|
312
|
-
native: {}
|
|
305
|
+
native: {},
|
|
313
306
|
};
|
|
314
307
|
this.log.debug(`Create script in DB with ${id}`);
|
|
315
308
|
// ensure that every script has a folder and if not, then create it
|
|
316
309
|
this._checkIfAllFoldersAreExist(id, this.dbList);
|
|
317
|
-
this.adapter.setForeignObject(id, this.dbList[id]);
|
|
318
|
-
}
|
|
319
|
-
|
|
310
|
+
void this.adapter.setForeignObject(id, this.dbList[id]);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
this.log.warn(`Please delete file ${(0, node_path_1.join)(dirDisk, files[f])}`);
|
|
320
314
|
}
|
|
321
315
|
}
|
|
322
316
|
}
|
|
323
|
-
|
|
324
317
|
_scriptId2FileName(id, type) {
|
|
325
318
|
id = id.substring('script.js.'.length);
|
|
326
319
|
const parts = id.split('.');
|
|
327
|
-
return
|
|
320
|
+
return ((0, node_path_1.join)(this.diskRoot, parts.join('/')).replace(/\\/g, '/') +
|
|
321
|
+
(type && type.toLowerCase() === 'typescript/ts' ? '.ts' : '.js'));
|
|
328
322
|
}
|
|
329
323
|
_fileName2scriptId(file) {
|
|
330
324
|
file = file.substring(this.diskRoot.length).replace(/\.js$/g, '').replace(/\.ts$/g, '');
|
|
@@ -332,15 +326,14 @@ class Mirror {
|
|
|
332
326
|
if (!parts[0] && parts.length) {
|
|
333
327
|
parts.shift();
|
|
334
328
|
}
|
|
335
|
-
|
|
336
329
|
return `script.js.${parts.join('.')}`;
|
|
337
330
|
}
|
|
338
|
-
|
|
339
331
|
removeScriptsInFolder(folder) {
|
|
340
332
|
// get all files in this folder
|
|
341
333
|
const folderId = this._fileName2scriptId(folder);
|
|
342
334
|
for (const id in this.dbList) {
|
|
343
|
-
if (Object.prototype.hasOwnProperty.call(this.dbList, id) &&
|
|
335
|
+
if (Object.prototype.hasOwnProperty.call(this.dbList, id) &&
|
|
336
|
+
(id.startsWith(folderId) || id === folderId.replace(/\.$/, ''))) {
|
|
344
337
|
// delete it
|
|
345
338
|
if (this.dbList[id]) {
|
|
346
339
|
this.log.debug(`Delete script ${id} in DB`);
|
|
@@ -353,31 +346,31 @@ class Mirror {
|
|
|
353
346
|
}
|
|
354
347
|
}
|
|
355
348
|
}
|
|
356
|
-
|
|
357
349
|
onFileChange(event, file) {
|
|
358
350
|
let stats;
|
|
359
|
-
const exists =
|
|
351
|
+
const exists = (0, node_fs_1.existsSync)(file);
|
|
360
352
|
if (exists) {
|
|
361
353
|
try {
|
|
362
|
-
stats =
|
|
363
|
-
} catch (e) {
|
|
364
|
-
this.log.error(`Cannot read file ${file}: ${e}`);
|
|
354
|
+
stats = (0, node_fs_1.statSync)(file);
|
|
365
355
|
}
|
|
366
|
-
|
|
367
|
-
|
|
356
|
+
catch (err) {
|
|
357
|
+
this.log.error(`Cannot read file ${file}: ${err}`);
|
|
358
|
+
}
|
|
359
|
+
if (stats?.isDirectory()) {
|
|
368
360
|
file = file.endsWith('/') ? file : `${file}/`;
|
|
369
361
|
if (exists) {
|
|
370
362
|
!this.watchedFolder[file] && this.watchFolders(file);
|
|
371
363
|
try {
|
|
372
364
|
// scan folder anew
|
|
373
|
-
const files =
|
|
374
|
-
|
|
365
|
+
const files = (0, node_fs_1.readdirSync)(file).filter(name => !name.startsWith('.'));
|
|
375
366
|
// update all files in this directory
|
|
376
|
-
files.forEach(f => this.onFileChange('change',
|
|
377
|
-
}
|
|
367
|
+
files.forEach(f => this.onFileChange('change', (0, node_path_1.join)(file, f).replace(/\\/g, '/')));
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
378
370
|
this.log.error(`Error while checking files in directory ${file}: ${err}`);
|
|
379
371
|
}
|
|
380
|
-
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
381
374
|
if (this.watchedFolder[file]) {
|
|
382
375
|
this.watchedFolder[file].close();
|
|
383
376
|
delete this.watchedFolder[file];
|
|
@@ -386,58 +379,62 @@ class Mirror {
|
|
|
386
379
|
}
|
|
387
380
|
return;
|
|
388
381
|
}
|
|
389
|
-
}
|
|
382
|
+
}
|
|
383
|
+
else if (this.watchedFolder[file]) {
|
|
390
384
|
if (!exists) {
|
|
391
385
|
try {
|
|
392
386
|
if (this.watchedFolder[file]) {
|
|
393
387
|
this.watchedFolder[file].close();
|
|
394
388
|
delete this.watchedFolder[file];
|
|
395
389
|
}
|
|
396
|
-
}
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
397
392
|
// ignore error
|
|
398
393
|
}
|
|
399
394
|
this.removeScriptsInFolder(file);
|
|
400
395
|
}
|
|
401
396
|
return;
|
|
402
|
-
}
|
|
397
|
+
}
|
|
398
|
+
else if (this.watchedFolder[`${file}/`]) {
|
|
403
399
|
if (!exists) {
|
|
404
400
|
file = `${file}/`;
|
|
405
401
|
// delete all files in this folder
|
|
406
|
-
|
|
407
402
|
try {
|
|
408
403
|
if (this.watchedFolder[file]) {
|
|
409
404
|
this.watchedFolder[file].close();
|
|
410
405
|
delete this.watchedFolder[file];
|
|
411
406
|
}
|
|
412
|
-
}
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
413
409
|
// ignore error
|
|
414
410
|
}
|
|
415
411
|
this.removeScriptsInFolder(file);
|
|
416
412
|
}
|
|
417
413
|
return;
|
|
418
414
|
}
|
|
419
|
-
|
|
420
|
-
|
|
415
|
+
if (!file.match(/\.ts$|\.js$/)) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
421
418
|
const id = this._fileName2scriptId(file);
|
|
422
|
-
|
|
423
419
|
if (exists && (event === 'change' || event === 'create')) {
|
|
424
420
|
try {
|
|
425
|
-
stats = stats ||
|
|
426
|
-
const source =
|
|
427
|
-
const ts = stats
|
|
428
|
-
this.diskList[id] = {ts, source, name: file};
|
|
429
|
-
|
|
421
|
+
stats = stats || (0, node_fs_1.statSync)(file);
|
|
422
|
+
const source = (0, node_fs_1.readFileSync)(file).toString();
|
|
423
|
+
const ts = stats?.mtime.getTime() || 0;
|
|
424
|
+
this.diskList[id] = { ts, source, name: file };
|
|
430
425
|
if (this.dbList[id]) {
|
|
431
426
|
if (this.dbList[id].common.source !== source) {
|
|
432
427
|
this.dbList[id].common.source = source;
|
|
433
428
|
this.dbList[id].ts = ts;
|
|
434
429
|
this.log.debug(`Update script ${id} in DB`);
|
|
435
430
|
this.dbList[id].from = this.from;
|
|
436
|
-
this.adapter.setForeignObject(id, this.dbList[id]);
|
|
437
|
-
}
|
|
431
|
+
void this.adapter.setForeignObject(id, this.dbList[id]);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
438
434
|
this.dbList[id].ts = ts;
|
|
439
435
|
}
|
|
440
|
-
}
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
441
438
|
this.log.debug(`Create script ${id} in DB`);
|
|
442
439
|
const parts = id.split('.');
|
|
443
440
|
// new script
|
|
@@ -454,21 +451,24 @@ class Mirror {
|
|
|
454
451
|
},
|
|
455
452
|
type: 'script',
|
|
456
453
|
native: {},
|
|
457
|
-
ts: ts
|
|
454
|
+
ts: ts,
|
|
458
455
|
};
|
|
459
456
|
this._checkIfAllFoldersAreExist(id, this.dbList);
|
|
460
|
-
this.adapter.setForeignObject(id, this.dbList[id]);
|
|
457
|
+
void this.adapter.setForeignObject(id, this.dbList[id]);
|
|
461
458
|
}
|
|
462
|
-
} catch (e) {
|
|
463
|
-
this.log.error(`Cannot read file ${file}: ${e}`);
|
|
464
459
|
}
|
|
465
|
-
|
|
460
|
+
catch (err) {
|
|
461
|
+
this.log.error(`Cannot read file ${file}: ${err}`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
else if (event === 'delete' || event === 'rename') {
|
|
466
465
|
// there is a bug: just after creation of a script on disk from ioBroker, "rename" event is generated!
|
|
467
466
|
if (event === 'rename' && this.diskList[id] && Date.now() - this.diskList[id].ts < 200) {
|
|
468
467
|
console.log(`Interval: ${Date.now() - this.diskList[id].ts}`);
|
|
469
|
-
// 'rename is ignored
|
|
468
|
+
// 'rename' is ignored
|
|
470
469
|
this.log.debug(`Rename event for ${id} is ignored`);
|
|
471
|
-
}
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
472
|
if (this.dbList[id]) {
|
|
473
473
|
this.log.debug(`Delete script ${id} in DB`);
|
|
474
474
|
delete this.dbList[id];
|
|
@@ -481,14 +481,11 @@ class Mirror {
|
|
|
481
481
|
}
|
|
482
482
|
this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
|
|
483
483
|
}
|
|
484
|
-
|
|
485
484
|
onObjectChange(id, obj) {
|
|
486
485
|
if (!this.dbList || !id) {
|
|
487
486
|
return;
|
|
488
487
|
}
|
|
489
|
-
|
|
490
|
-
const file = this._scriptId2FileName(id, obj && obj.common && obj.common.engineType);
|
|
491
|
-
|
|
488
|
+
const file = this._scriptId2FileName(id, obj?.common?.engineType);
|
|
492
489
|
if (!obj || !obj.common) {
|
|
493
490
|
if (this.dbList[id]) {
|
|
494
491
|
delete this.dbList[id];
|
|
@@ -496,73 +493,75 @@ class Mirror {
|
|
|
496
493
|
if (this.dbList[folderId]) {
|
|
497
494
|
this.updateFolderTime(folderId);
|
|
498
495
|
}
|
|
499
|
-
|
|
500
|
-
if (fs.existsSync(file)) {
|
|
496
|
+
if ((0, node_fs_1.existsSync)(file)) {
|
|
501
497
|
try {
|
|
502
498
|
this.log.debug(`Delete ${file} on disk`);
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
|
|
499
|
+
(0, node_fs_1.unlinkSync)(file);
|
|
500
|
+
}
|
|
501
|
+
catch (err) {
|
|
502
|
+
this.log.error(`Cannot delete ${file}: ${err}`);
|
|
506
503
|
}
|
|
507
504
|
}
|
|
508
505
|
if (this.diskList[id]) {
|
|
509
506
|
delete this.diskList[id];
|
|
510
507
|
}
|
|
511
508
|
}
|
|
512
|
-
}
|
|
509
|
+
}
|
|
510
|
+
else if (obj.type === 'script' && id.startsWith('script.js.')) {
|
|
513
511
|
if (this.dbList[id]) {
|
|
514
512
|
if (this.dbList[id].common.source !== obj.common.source) {
|
|
515
513
|
this.dbList[id] = obj;
|
|
516
514
|
this.log.debug(`Update ${file} on disk`);
|
|
517
|
-
this.diskList[id] = {ts: 0, source: obj.common.source, name: file};
|
|
515
|
+
this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
|
|
518
516
|
this._writeFile(id);
|
|
519
|
-
}
|
|
517
|
+
}
|
|
518
|
+
else if (!this.diskList[id] || this.diskList[id].source !== obj.common.source) {
|
|
520
519
|
this.log.debug(`Update ${file} on disk`);
|
|
521
|
-
this.diskList[id] = {ts: 0, source: obj.common.source, name: file};
|
|
520
|
+
this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
|
|
522
521
|
this._writeFile(id);
|
|
523
522
|
}
|
|
524
|
-
}
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
525
|
// new script
|
|
526
526
|
this.dbList[id] = obj;
|
|
527
527
|
if (!this.diskList[id] || this.diskList[id].source !== obj.common.source) {
|
|
528
528
|
this.log.debug(`Create ${file} on disk`);
|
|
529
|
-
this.diskList[id] = {ts: 0, source: obj.common.source, name: file};
|
|
529
|
+
this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
|
|
530
530
|
this._writeFile(id);
|
|
531
531
|
}
|
|
532
532
|
}
|
|
533
533
|
this.dbList[id].ts = Date.now();
|
|
534
534
|
}
|
|
535
|
-
|
|
536
535
|
this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
|
|
537
536
|
}
|
|
538
|
-
|
|
539
537
|
scanDisk(dirPath, list) {
|
|
540
538
|
dirPath = dirPath || this.diskRoot;
|
|
541
539
|
list = list || {};
|
|
542
540
|
try {
|
|
543
|
-
if (dirPath && !dirPath.startsWith('.') &&
|
|
544
|
-
const files =
|
|
545
|
-
|
|
546
|
-
const fullName =
|
|
547
|
-
const stats =
|
|
541
|
+
if (dirPath && !dirPath.startsWith('.') && (0, node_fs_1.existsSync)(dirPath)) {
|
|
542
|
+
const files = (0, node_fs_1.readdirSync)(dirPath).filter(name => !name.startsWith('.'));
|
|
543
|
+
for (const file of files) {
|
|
544
|
+
const fullName = (0, node_path_1.join)(dirPath, file);
|
|
545
|
+
const stats = (0, node_fs_1.statSync)(fullName);
|
|
548
546
|
if (stats.isDirectory()) {
|
|
549
547
|
this.scanDisk(fullName.replace(/\\/g, '/'), list);
|
|
550
|
-
}
|
|
548
|
+
}
|
|
549
|
+
else if (file.match(/\.js$|\.ts$/)) {
|
|
551
550
|
const f = this._fileName2scriptId(fullName);
|
|
552
551
|
list[f] = {
|
|
553
|
-
ts:
|
|
554
|
-
source:
|
|
555
|
-
name: fullName
|
|
552
|
+
ts: stats.mtime.getTime(),
|
|
553
|
+
source: (0, node_fs_1.readFileSync)(fullName).toString(),
|
|
554
|
+
name: fullName,
|
|
556
555
|
};
|
|
557
556
|
}
|
|
558
|
-
}
|
|
557
|
+
}
|
|
559
558
|
}
|
|
560
|
-
}
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
561
|
this.log.error(`Error while checking files in directory ${dirPath}: ${err}`);
|
|
562
562
|
}
|
|
563
563
|
return list;
|
|
564
564
|
}
|
|
565
|
-
|
|
566
565
|
_checkIfAllFoldersAreExist(id, list) {
|
|
567
566
|
const parts = id.split('.');
|
|
568
567
|
for (let i = parts.length - 1; i >= 2; i--) {
|
|
@@ -579,26 +578,30 @@ class Mirror {
|
|
|
579
578
|
};
|
|
580
579
|
list[folderId] = obj;
|
|
581
580
|
try {
|
|
582
|
-
this.adapter.setForeignObject(folderId, obj, err =>
|
|
583
|
-
|
|
581
|
+
this.adapter.setForeignObject(folderId, obj, err => {
|
|
582
|
+
if (err) {
|
|
583
|
+
this.log.warn(`Error while checking script folder ${folderId} for id "${id}": ${err}`);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
584
588
|
this.log.warn(`Error while checking script folder ${folderId} for id "${id}": ${err}`);
|
|
585
589
|
}
|
|
586
590
|
}
|
|
587
591
|
}
|
|
588
592
|
}
|
|
589
|
-
|
|
590
593
|
scanDB(cb) {
|
|
591
594
|
this.adapter.getObjectView('system', 'channel', { startkey: 'script.js.', endkey: 'script.js.\u9999' }, (err, res) => {
|
|
592
595
|
// this is not required, because JavaScript subscribes on ALL objects
|
|
593
596
|
// adapter.subscribeForeignObjects('script.js.*');
|
|
594
597
|
const list = {};
|
|
595
598
|
if (err) {
|
|
596
|
-
this.log.error(
|
|
599
|
+
this.log.error(`Error while checking scripts channel from objects database: ${err}`);
|
|
597
600
|
}
|
|
598
|
-
if (res
|
|
601
|
+
if (res?.rows) {
|
|
599
602
|
for (let i = 0; i < res.rows.length; i++) {
|
|
600
603
|
const value = res.rows[i].value;
|
|
601
|
-
if (value
|
|
604
|
+
if (value?._id && value.common) {
|
|
602
605
|
list[res.rows[i].value._id] = res.rows[i].value;
|
|
603
606
|
}
|
|
604
607
|
}
|
|
@@ -607,10 +610,10 @@ class Mirror {
|
|
|
607
610
|
if (err) {
|
|
608
611
|
this.log.error(`Error while checking scripts javascript from objects database: ${err}`);
|
|
609
612
|
}
|
|
610
|
-
if (res
|
|
613
|
+
if (res?.rows) {
|
|
611
614
|
for (let i = 0; i < res.rows.length; i++) {
|
|
612
615
|
const value = res.rows[i].value;
|
|
613
|
-
if (value
|
|
616
|
+
if (value?._id && value.common) {
|
|
614
617
|
list[res.rows[i].value._id] = res.rows[i].value;
|
|
615
618
|
// ensure that every script has a folder and if not, then create it
|
|
616
619
|
this._checkIfAllFoldersAreExist(res.rows[i].value._id, list);
|
|
@@ -624,5 +627,5 @@ class Mirror {
|
|
|
624
627
|
});
|
|
625
628
|
}
|
|
626
629
|
}
|
|
627
|
-
|
|
628
|
-
|
|
630
|
+
exports.Mirror = Mirror;
|
|
631
|
+
//# sourceMappingURL=mirror.js.map
|