@runeya/runeya 1.33.20 → 1.33.23
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/node-red-contrib-runeya.tar +0 -0
- package/package.json +1 -1
- package/public/assets/{App-BVTb2f1U.css → App-BGPtogo-.css} +1 -1
- package/public/assets/App-Bj3c8ECd.js +101 -0
- package/public/assets/Bugs-B6LM8YSZ.js +1 -0
- package/public/assets/Bugs-DZVuTDKA.css +1 -0
- package/public/assets/Configs-CRGDsvnb.js +464 -0
- package/public/assets/Configs-DdBteQMK.css +1 -0
- package/public/assets/CurrentEditor-DI0XEvLu.js +1 -0
- package/public/assets/DynamicComponent-CmXZUvVU.js +1 -0
- package/public/assets/DynamicComponent-DgxRO4Pl.css +1 -0
- package/public/assets/{Editor-Ck3cFVn3.js → Editor-CBZeVePs.js} +7 -7
- package/public/assets/{Editor-BC23IeB6.css → Editor-CPPFMOjb.css} +1 -1
- package/public/assets/Git-Cf-zgTWr.js +11 -0
- package/public/assets/Git-UQIt5ANe.css +1 -0
- package/public/assets/ImportCreate-DZSPN5cY.js +1 -0
- package/public/assets/Index-BJieQWaU.js +1 -0
- package/public/assets/Index-BcFahN3S.css +1 -0
- package/public/assets/Index-BrbegLuT.js +1 -0
- package/public/assets/Index-C3gFkhHj.js +1 -0
- package/public/assets/Index-C66tLKvy.css +1 -0
- package/public/assets/Index-Cd-qd5VG.css +1 -0
- package/public/assets/Index-Cg-pTjT5.js +1 -0
- package/public/assets/Index-CvhWs0kp.css +1 -0
- package/public/assets/Index-D67OAIVa.js +314 -0
- package/public/assets/Index-DZ8CXixy.js +1 -0
- package/public/assets/{Init-Lt-2DFbi.js → Init-BILP6lrr.js} +1 -1
- package/public/assets/{LeftLogo-fTp83qX1.js → LeftLogo-BCYb654E.js} +1 -1
- package/public/assets/Logs-BfqPcp-L.js +74 -0
- package/public/assets/Logs-BhdfGaw5.css +32 -0
- package/public/assets/{Markdown-CNWZoHio.js → Markdown-CuewGlVj.js} +19 -103
- package/public/assets/Modal-CGUZawhK.css +1 -0
- package/public/assets/Modal-DmKdmCtc.js +1 -0
- package/public/assets/Modals-BHTrmB19.js +1 -0
- package/public/assets/NotUpToDate-CnmuPdX-.js +1 -0
- package/public/assets/NotUpToDate-Dh9RbAwK.css +1 -0
- package/public/assets/Npm-HBPCi13F.js +1 -0
- package/public/assets/Npm-KBzO1DYv.css +1 -0
- package/public/assets/Overview-CRtTdDEz.js +1 -0
- package/public/assets/Overview-DZIOmzKx.css +1 -0
- package/public/assets/{Section-BC6pA1HZ.js → Section-OccJuk7A.js} +1 -1
- package/public/assets/{Settings-Dp_ktsgs.js → Settings-CgEyOTsE.js} +6 -6
- package/public/assets/{Settings-BBbk67zT.css → Settings-DUCkJDco.css} +1 -1
- package/public/assets/Spinner-BMGbc3X9.js +1 -0
- package/public/assets/Spinner-BZXOybIg.css +1 -0
- package/public/assets/StackChooser-DBof37zx.js +1 -0
- package/public/assets/{StackChooser-CsNxPvyi.js → StackChooser-PJ4_aCX-.js} +1 -1
- package/public/assets/StackMultiple-CiXqkibR.css +1 -0
- package/public/assets/{StackMultiple-BeZmv6DX.js → StackMultiple-D0bM6dXR.js} +17 -17
- package/public/assets/{StackSingle-DBZX9nN_.css → StackSingle-BVHxvisP.css} +1 -1
- package/public/assets/StackSingle-D1Yk8PXD.js +1 -0
- package/public/assets/{Tabs-fu2myJd9.css → Tabs-BGPqRkjE.css} +1 -1
- package/public/assets/Tabs-DQDvjS5y.js +1 -0
- package/public/assets/Theme-CzHFcMoz.js +1 -0
- package/public/assets/Toolbox-B5KXz4eX.css +1 -0
- package/public/assets/Toolbox-C5XEPDmg.js +1 -0
- package/public/assets/_baseFor-DiPelG4M.js +1 -0
- package/public/assets/_commonjsHelpers-D6-XlEtG.js +1 -0
- package/public/assets/{cssMode-DptFVzSA.js → cssMode-CccHpseG.js} +1 -1
- package/public/assets/currentEditor-DKB6Zox9.js +1 -0
- package/public/assets/dayjs.min-CfWDS3UC.js +1 -0
- package/public/assets/{freemarker2-Nj-3NhAz.js → freemarker2-DSPhVVzD.js} +1 -1
- package/public/assets/fs-CwxHstJI.js +1 -0
- package/public/assets/{handlebars-DccXq6O-.js → handlebars-1zANa-F3.js} +1 -1
- package/public/assets/{html-BFezHwqy.js → html-fsS26eC3.js} +1 -1
- package/public/assets/{htmlMode-8pIWMfce.js → htmlMode-DvnqyT9t.js} +1 -1
- package/public/assets/index-0X67tmWL.js +82 -0
- package/public/assets/index-B3Vh_zdc.js +1454 -0
- package/public/assets/index-B614CRIK.js +201 -0
- package/public/assets/index-BO82C_5u.js +720 -0
- package/public/assets/index-Brqxsm84.js +308 -0
- package/public/assets/index-CILDVkDy.js +310 -0
- package/public/assets/{index--FPUu8lq.css → index-D9v3u7Fv.css} +1 -1
- package/public/assets/index-DcbuCmxJ.js +84 -0
- package/public/assets/{index-DVXSyllr.js → index-G_rNbFve.js} +2 -2
- package/public/assets/index-d75RPzOA.js +176 -0
- package/public/assets/index-uWoKtv9r.js +2 -0
- package/public/assets/{javascript-B0mQdjwH.js → javascript-DRHvp6-v.js} +1 -1
- package/public/assets/json-tree-view-vue3.es-DVJTi2Rq.js +1 -0
- package/public/assets/{jsonMode-BuKXiIei.js → jsonMode-CJHmEzcn.js} +1 -1
- package/public/assets/{liquid-9G58QM1k.js → liquid-V1Od9uns.js} +1 -1
- package/public/assets/lodash-D2RHCRSL.js +27 -0
- package/public/assets/{mdx-DWeREtqy.js → mdx-DlWa4FFs.js} +1 -1
- package/public/assets/{python-BZtttaDe.js → python-DawPqpxL.js} +1 -1
- package/public/assets/{razor-CIhED9yj.js → razor-CrbHGO04.js} +1 -1
- package/public/assets/router-DPuc_QdV.css +1 -0
- package/public/assets/router-Dzu6a_zz.js +103 -0
- package/public/assets/sort-BibmqbFD.js +1 -0
- package/public/assets/{system-IAlLmFx7.js → system-BqvwX5_3.js} +1 -1
- package/public/assets/{tsMode-BMdhWjVC.js → tsMode-Cb1yqXWI.js} +1 -1
- package/public/assets/{typescript-DurNSXGF.js → typescript-CnZCKV3a.js} +1 -1
- package/public/assets/{xml-Ckok0faQ.js → xml-B90p6BQJ.js} +1 -1
- package/public/assets/{yaml-C2OtFevY.js → yaml-Bkk9HYtt.js} +1 -1
- package/public/index.html +1 -1
- package/www.js +744 -692
- package/www.js.map +1 -1
- package/public/assets/App-CxWYnNM-.js +0 -101
- package/public/assets/CurrentEditor-C38cqf-Z.js +0 -1
- package/public/assets/ImportCreate-DFEf3KiI.js +0 -1
- package/public/assets/Overview-BaSpvlXu.css +0 -1
- package/public/assets/Overview-DR4QmO04.js +0 -1
- package/public/assets/StackChooser-vHgodEvA.js +0 -1
- package/public/assets/StackMultiple-Dw-7UAYX.css +0 -1
- package/public/assets/StackSingle-Bza6Vusw.js +0 -1
- package/public/assets/Tabs-DMteuptw.js +0 -1
- package/public/assets/router-BIesWMTV.css +0 -32
- package/public/assets/router-BaBuIyxA.js +0 -4232
package/www.js
CHANGED
|
@@ -104,9 +104,12 @@ var require_args = __commonJS({
|
|
|
104
104
|
var { hideBin } = require("yargs/helpers");
|
|
105
105
|
var { existsSync } = require("fs");
|
|
106
106
|
var yarg = yargs(hideBin(process.argv)).usage("Usage: <path-to-your-stack> [options]").alias("pe", "pull-env").describe("pe", "Pull env from a service (need --environment and --service)").default("pe", false).alias("e", "environment").describe("e", "Choose your environment").default("e", void 0).alias("s", "service").describe("s", "Service").default("s", void 0).alias("ss", "services").describe("ss", "Services").default("ss", []).boolean(["pe"]).string(["e", "s"]).array(["ss"]).help("h").alias("h", "help").parse();
|
|
107
|
+
var rootPath = path.resolve(yarg["_"]?.[0] || ".");
|
|
107
108
|
var args2 = Object.assign({
|
|
108
|
-
rootPath
|
|
109
|
-
initialCwd: ""
|
|
109
|
+
rootPath,
|
|
110
|
+
initialCwd: "",
|
|
111
|
+
runeyaConfigPath: path.resolve(rootPath, ".runeya"),
|
|
112
|
+
runeyaGlobalConfigPath: path.resolve(require("os").homedir(), ".runeya-global")
|
|
110
113
|
}, yarg);
|
|
111
114
|
if (!existsSync(args2.rootPath)) {
|
|
112
115
|
console.error("Error: Runeya was launched with an invalid root path that does not exist. Please check your launch command. \nPath: ", args2.rootPath);
|
|
@@ -128,6 +131,99 @@ var require_args = __commonJS({
|
|
|
128
131
|
}
|
|
129
132
|
});
|
|
130
133
|
|
|
134
|
+
// helpers/migrateStackMonitor.js
|
|
135
|
+
var require_migrateStackMonitor = __commonJS({
|
|
136
|
+
"helpers/migrateStackMonitor.js"(exports2, module2) {
|
|
137
|
+
"use strict";
|
|
138
|
+
var pathfs = require("path");
|
|
139
|
+
var { existsSync } = require("fs");
|
|
140
|
+
var { cp } = require("fs/promises");
|
|
141
|
+
var args2 = require_args();
|
|
142
|
+
module2.exports = async function migrateStackMonitor2() {
|
|
143
|
+
const localLegacyPath = pathfs.resolve(args2.runeyaConfigPath, "../.stackmonitor");
|
|
144
|
+
const localNewPath = args2.runeyaConfigPath;
|
|
145
|
+
if (existsSync(localLegacyPath) && !existsSync(localNewPath)) {
|
|
146
|
+
console.log("Legacy path found, copy to new path");
|
|
147
|
+
await cp(localLegacyPath, localNewPath, { recursive: true, force: true });
|
|
148
|
+
}
|
|
149
|
+
const globalLegacyPath = pathfs.resolve(args2.runeyaGlobalConfigPath, "../.stackmonitor");
|
|
150
|
+
const globalNewPath = args2.runeyaGlobalConfigPath;
|
|
151
|
+
if (existsSync(globalLegacyPath) && !existsSync(globalNewPath)) {
|
|
152
|
+
console.log("Legacy path found, copy to new path");
|
|
153
|
+
await cp(globalLegacyPath, globalNewPath, { recursive: true, force: true });
|
|
154
|
+
}
|
|
155
|
+
if (existsSync(localLegacyPath) && !existsSync(pathfs.resolve(args2.runeyaConfigPath, "dbs/overrides"))) {
|
|
156
|
+
console.log("Legacy path found, copy to new path");
|
|
157
|
+
await cp(pathfs.resolve(localLegacyPath, "dbs/overrides"), pathfs.resolve(args2.runeyaConfigPath, "dbs/overrides"), { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
if (existsSync(localLegacyPath) && !existsSync(pathfs.resolve(args2.runeyaConfigPath, "dbs/encryption-key.json"))) {
|
|
160
|
+
console.log("Legacy path found, copy to new path");
|
|
161
|
+
await cp(pathfs.resolve(localLegacyPath, "dbs/encryption-key.json"), pathfs.resolve(args2.runeyaConfigPath, "dbs/encryption-key.json"), { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// helpers/conflictStorage.js
|
|
168
|
+
var require_conflictStorage = __commonJS({
|
|
169
|
+
"helpers/conflictStorage.js"(exports2, module2) {
|
|
170
|
+
"use strict";
|
|
171
|
+
var pendingConflicts = [];
|
|
172
|
+
function storeConflict(conflict) {
|
|
173
|
+
const conflictId = Date.now().toString();
|
|
174
|
+
pendingConflicts.push({
|
|
175
|
+
id: conflictId,
|
|
176
|
+
timestamp: Date.now(),
|
|
177
|
+
...conflict
|
|
178
|
+
});
|
|
179
|
+
if (pendingConflicts.length > 20) {
|
|
180
|
+
pendingConflicts.shift();
|
|
181
|
+
}
|
|
182
|
+
return conflictId;
|
|
183
|
+
}
|
|
184
|
+
function getPendingConflicts() {
|
|
185
|
+
return pendingConflicts;
|
|
186
|
+
}
|
|
187
|
+
function removeConflict(conflictId) {
|
|
188
|
+
const index = pendingConflicts.findIndex((c) => c.id === conflictId);
|
|
189
|
+
if (index !== -1) {
|
|
190
|
+
pendingConflicts.splice(index, 1);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
module2.exports = {
|
|
194
|
+
storeConflict,
|
|
195
|
+
getPendingConflicts,
|
|
196
|
+
removeConflict
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// helpers/reencrypt-nodered.js
|
|
202
|
+
var require_reencrypt_nodered = __commonJS({
|
|
203
|
+
"helpers/reencrypt-nodered.js"(exports2, module2) {
|
|
204
|
+
"use strict";
|
|
205
|
+
var crypto = require("crypto");
|
|
206
|
+
var { readFile, writeFile } = require("fs/promises");
|
|
207
|
+
var encryptionAlgorithm = "aes-256-ctr";
|
|
208
|
+
module2.exports = async function decryptCreds(oldSecret, newScret, path) {
|
|
209
|
+
const oldKey = crypto.createHash("sha256").update(oldSecret).digest();
|
|
210
|
+
const newKey = crypto.createHash("sha256").update(newScret).digest();
|
|
211
|
+
const cipher = JSON.parse(await readFile(path, "utf-8"));
|
|
212
|
+
let flows = cipher["$"];
|
|
213
|
+
const vector = Buffer.from(flows.substring(0, 32), "hex");
|
|
214
|
+
flows = flows.substring(32);
|
|
215
|
+
const decipher = crypto.createDecipheriv(encryptionAlgorithm, oldKey, vector);
|
|
216
|
+
const decrypted = decipher.update(flows, "base64", "utf8") + decipher.final("utf8");
|
|
217
|
+
const newVector = crypto.randomBytes(16);
|
|
218
|
+
const newCipher = crypto.createCipheriv(encryptionAlgorithm, newKey, newVector);
|
|
219
|
+
const encrypted = newCipher.update(decrypted, "utf8", "base64") + newCipher.final("base64");
|
|
220
|
+
await writeFile(path, JSON.stringify({
|
|
221
|
+
"$": newVector.toString("hex") + encrypted
|
|
222
|
+
}, null, 2), "utf-8");
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
131
227
|
// ../../modules/bugs/backend/routes.js
|
|
132
228
|
var require_routes = __commonJS({
|
|
133
229
|
"../../modules/bugs/backend/routes.js"(exports2, module2) {
|
|
@@ -198,724 +294,281 @@ var require_backend2 = __commonJS({
|
|
|
198
294
|
}
|
|
199
295
|
});
|
|
200
296
|
|
|
201
|
-
//
|
|
202
|
-
var
|
|
203
|
-
"
|
|
297
|
+
// ../../modules/documentation/backend/Documentation.js
|
|
298
|
+
var require_Documentation = __commonJS({
|
|
299
|
+
"../../modules/documentation/backend/Documentation.js"(exports2, module2) {
|
|
204
300
|
"use strict";
|
|
205
|
-
var
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
301
|
+
var PromiseB2 = require("bluebird");
|
|
302
|
+
var { randomUUID: randomUUID2 } = require("crypto");
|
|
303
|
+
var dbs2 = require_dbs();
|
|
304
|
+
var db = dbs2.getDb(`documentations`);
|
|
305
|
+
var dbDocumentationTree = dbs2.getDb(`documentations-tree`, { encrypted: true, defaultData: [] }).alasql;
|
|
306
|
+
var Documentation = class {
|
|
307
|
+
/**
|
|
308
|
+
* @param {import('@runeya/common-typings').NonFunctionProperties<Documentation>} documentation
|
|
309
|
+
*/
|
|
310
|
+
constructor(documentation) {
|
|
311
|
+
this.id = documentation.id || "";
|
|
312
|
+
this.text = documentation.text || "";
|
|
215
313
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
314
|
+
static async load(id) {
|
|
315
|
+
}
|
|
316
|
+
static async all() {
|
|
317
|
+
return db.alasql.select("Select * from ?");
|
|
318
|
+
}
|
|
319
|
+
static async find(envId) {
|
|
320
|
+
const documentations = await this.all();
|
|
321
|
+
return documentations.find((env) => env.id === envId);
|
|
322
|
+
}
|
|
323
|
+
async save() {
|
|
324
|
+
const obj = this.toStorage();
|
|
325
|
+
await dbs2.getDb(`documentations/${this.id}`).write(obj);
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
async update(env) {
|
|
329
|
+
this.transform = env.transform;
|
|
330
|
+
this.label = env.label;
|
|
331
|
+
await dbs2.getDb(`documentations/${this.id}`).write(this.toStorage());
|
|
332
|
+
}
|
|
333
|
+
async delete() {
|
|
334
|
+
await dbs2.getDb(`documentations/${this.id}`).delete();
|
|
335
|
+
}
|
|
336
|
+
toStorage() {
|
|
337
|
+
return {
|
|
338
|
+
id: this.id,
|
|
339
|
+
label: this.label,
|
|
340
|
+
transform: this.transform
|
|
341
|
+
};
|
|
225
342
|
}
|
|
226
|
-
}
|
|
227
|
-
module2.exports = {
|
|
228
|
-
storeConflict,
|
|
229
|
-
getPendingConflicts,
|
|
230
|
-
removeConflict
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
// helpers/reencrypt-nodered.js
|
|
236
|
-
var require_reencrypt_nodered = __commonJS({
|
|
237
|
-
"helpers/reencrypt-nodered.js"(exports2, module2) {
|
|
238
|
-
"use strict";
|
|
239
|
-
var crypto = require("crypto");
|
|
240
|
-
var { readFile, writeFile } = require("fs/promises");
|
|
241
|
-
var encryptionAlgorithm = "aes-256-ctr";
|
|
242
|
-
module2.exports = async function decryptCreds(oldSecret, newScret, path) {
|
|
243
|
-
const oldKey = crypto.createHash("sha256").update(oldSecret).digest();
|
|
244
|
-
const newKey = crypto.createHash("sha256").update(newScret).digest();
|
|
245
|
-
const cipher = JSON.parse(await readFile(path, "utf-8"));
|
|
246
|
-
let flows = cipher["$"];
|
|
247
|
-
const vector = Buffer.from(flows.substring(0, 32), "hex");
|
|
248
|
-
flows = flows.substring(32);
|
|
249
|
-
const decipher = crypto.createDecipheriv(encryptionAlgorithm, oldKey, vector);
|
|
250
|
-
const decrypted = decipher.update(flows, "base64", "utf8") + decipher.final("utf8");
|
|
251
|
-
const newVector = crypto.randomBytes(16);
|
|
252
|
-
const newCipher = crypto.createCipheriv(encryptionAlgorithm, newKey, newVector);
|
|
253
|
-
const encrypted = newCipher.update(decrypted, "utf8", "base64") + newCipher.final("base64");
|
|
254
|
-
await writeFile(path, JSON.stringify({
|
|
255
|
-
"$": newVector.toString("hex") + encrypted
|
|
256
|
-
}, null, 2), "utf-8");
|
|
257
343
|
};
|
|
344
|
+
module2.exports = Documentation;
|
|
258
345
|
}
|
|
259
346
|
});
|
|
260
347
|
|
|
261
|
-
//
|
|
262
|
-
var
|
|
263
|
-
"
|
|
348
|
+
// ../../modules/documentation/backend/Leaf.js
|
|
349
|
+
var require_Leaf = __commonJS({
|
|
350
|
+
"../../modules/documentation/backend/Leaf.js"(exports2, module2) {
|
|
264
351
|
"use strict";
|
|
265
|
-
var
|
|
266
|
-
var path = require("path");
|
|
267
|
-
var { writeFile, readFile, appendFile } = require("fs/promises");
|
|
352
|
+
var PromiseB2 = require("bluebird");
|
|
268
353
|
var { randomUUID: randomUUID2 } = require("crypto");
|
|
269
354
|
var dbs2 = require_dbs();
|
|
270
|
-
var {
|
|
271
|
-
var
|
|
272
|
-
var
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
constructor() {
|
|
277
|
-
|
|
278
|
-
this.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
this.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (!existsSync(gitignorePath)) {
|
|
285
|
-
writeFile(gitignorePath, "encryption-key.json");
|
|
286
|
-
} else {
|
|
287
|
-
const gitignoreFile = (await readFile(gitignorePath, "utf-8")).split("\n");
|
|
288
|
-
const gitignoreHasKey = (key) => gitignoreFile.some((line) => line.trim() === key);
|
|
289
|
-
if (!gitignoreHasKey("encryption-key.json")) await appendFile(gitignorePath, "\nencryption-key.json");
|
|
290
|
-
if (!gitignoreHasKey("overrides")) await appendFile(gitignorePath, "\noverrides");
|
|
291
|
-
}
|
|
355
|
+
var { v4 } = require("uuid");
|
|
356
|
+
var dbLeafTree = dbs2.getDb(`leafs-leafs`, { encrypted: true, defaultData: [] }).alasql;
|
|
357
|
+
var Leaf = class _Leaf {
|
|
358
|
+
/**
|
|
359
|
+
* @param {import('@runeya/common-typings').NonFunctionProperties<Leaf>} leaf
|
|
360
|
+
*/
|
|
361
|
+
constructor(leaf) {
|
|
362
|
+
this.id = leaf.id || v4();
|
|
363
|
+
this.docId = leaf.docId || "";
|
|
364
|
+
this.serviceId = leaf.serviceId || "";
|
|
365
|
+
this.label = leaf.label || "";
|
|
366
|
+
this.position = leaf.position || -1;
|
|
367
|
+
this.text = leaf.text || "";
|
|
368
|
+
this.parentId = leaf.parentId || "";
|
|
292
369
|
}
|
|
293
|
-
async
|
|
294
|
-
|
|
370
|
+
static async getTree(serviceLabel) {
|
|
371
|
+
const leafs = await dbLeafTree.read(`Select * from ${dbLeafTree.table} ${serviceLabel ? `where serviceId = '${serviceLabel}'` : `where serviceId=''`}`);
|
|
372
|
+
return leafs;
|
|
295
373
|
}
|
|
296
374
|
toStorage() {
|
|
297
375
|
return {
|
|
298
|
-
|
|
376
|
+
docId: this.docId,
|
|
377
|
+
position: this.position,
|
|
378
|
+
serviceId: this.serviceId,
|
|
379
|
+
label: this.label,
|
|
380
|
+
text: this.text,
|
|
381
|
+
parentId: this.parentId
|
|
299
382
|
};
|
|
300
383
|
}
|
|
301
|
-
async
|
|
302
|
-
return
|
|
384
|
+
async remove() {
|
|
385
|
+
return dbLeafTree.write(`DELETE from ${dbLeafTree.table} where id = '${this.id}'`);
|
|
303
386
|
}
|
|
304
|
-
async
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const result = await encrypt(variable, { encryptionKey });
|
|
308
|
-
const decrypted = await decrypt(result, { encryptionKey });
|
|
309
|
-
if (decrypted === variable) return true;
|
|
310
|
-
return false;
|
|
311
|
-
} catch (error) {
|
|
312
|
-
console.error(error);
|
|
313
|
-
return false;
|
|
314
|
-
}
|
|
387
|
+
static async find({ id }) {
|
|
388
|
+
const [leaf] = await dbLeafTree.read(`Select * from ${dbLeafTree.table} where id='${id}'`);
|
|
389
|
+
return leaf ? new _Leaf(leaf) : null;
|
|
315
390
|
}
|
|
316
|
-
async
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
await reencryptNodered(this.encryptionKey, key, pathfs.resolve(require_stack().getRootPath(), "nodered/flow_cred.json"));
|
|
323
|
-
await dbs2.reencrypt(this.encryptionKey, key);
|
|
324
|
-
}
|
|
325
|
-
;
|
|
326
|
-
} catch (error) {
|
|
327
|
-
console.error(error);
|
|
328
|
-
}
|
|
329
|
-
const shouldRestart = this.encryptionKey !== key;
|
|
330
|
-
this.encryptionKey = key;
|
|
331
|
-
await this.update();
|
|
332
|
-
if (!noReload) {
|
|
333
|
-
await require_stack().selectConf();
|
|
334
|
-
}
|
|
335
|
-
if (shouldRestart) {
|
|
336
|
-
console.log("Restart...");
|
|
337
|
-
require("child_process").spawn(process.argv[0], process.argv.slice(1), {
|
|
338
|
-
cwd: args2.initialCwd,
|
|
339
|
-
detached: true,
|
|
340
|
-
stdio: "inherit"
|
|
341
|
-
}).unref();
|
|
342
|
-
process.exit(0);
|
|
343
|
-
}
|
|
344
|
-
return key;
|
|
391
|
+
async save() {
|
|
392
|
+
const leafExists = await _Leaf.find({ id: this.id });
|
|
393
|
+
const storage = this.toStorage();
|
|
394
|
+
const set = dbLeafTree.buildUpdateQuery(storage);
|
|
395
|
+
await leafExists ? dbLeafTree.write(`update ${dbLeafTree.table} set ${set} where id='${this.id}'`) : dbLeafTree.write(`insert into ${dbLeafTree.table} (id, docId, position, serviceId, label, text, parentId) values ('${this.id}', '${this.docId}', ${this.position}, '${this.serviceId}', '${this.label.replace(/'/g, "''")}', '${this.text.replace(/'/g, "''")}', '${this.parentId}')`);
|
|
396
|
+
return this;
|
|
345
397
|
}
|
|
346
398
|
};
|
|
347
|
-
|
|
348
|
-
getDb_fn = function() {
|
|
349
|
-
return dbs2.getDb("encryption-key", { encrypted: false });
|
|
350
|
-
};
|
|
351
|
-
module2.exports = new EncryptionKey();
|
|
399
|
+
module2.exports = Leaf;
|
|
352
400
|
}
|
|
353
401
|
});
|
|
354
402
|
|
|
355
|
-
//
|
|
356
|
-
var
|
|
357
|
-
"
|
|
403
|
+
// ../../modules/documentation/backend/routes.js
|
|
404
|
+
var require_routes2 = __commonJS({
|
|
405
|
+
"../../modules/documentation/backend/routes.js"(exports2, module2) {
|
|
358
406
|
"use strict";
|
|
359
|
-
var
|
|
360
|
-
var
|
|
361
|
-
var
|
|
362
|
-
var
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
407
|
+
var express = require("express");
|
|
408
|
+
var Leaf = require_Leaf();
|
|
409
|
+
var PromiseB2 = require("bluebird");
|
|
410
|
+
var router = express.Router();
|
|
411
|
+
module2.exports = (runeya) => {
|
|
412
|
+
const { findService } = runeya;
|
|
413
|
+
router.get("/documentation/tree", async (req, res) => {
|
|
414
|
+
const service = findService(req.query.serviceId?.toString() || "");
|
|
415
|
+
const result = await Leaf.getTree(service?.label);
|
|
416
|
+
return res.send(result);
|
|
417
|
+
});
|
|
418
|
+
router.post("/documentation/tree/sort", async (req, res) => {
|
|
419
|
+
const leafs = await PromiseB2.mapSeries(req.body, async (_leaf, index) => {
|
|
420
|
+
const leaf = await Leaf.find({ id: _leaf.id });
|
|
421
|
+
if (!leaf) return;
|
|
422
|
+
leaf.position = index;
|
|
423
|
+
await leaf.save();
|
|
424
|
+
return leaf;
|
|
425
|
+
});
|
|
426
|
+
return res.send(leafs);
|
|
427
|
+
});
|
|
428
|
+
router.post("/documentation/tree", async (req, res) => {
|
|
429
|
+
const result = await new Leaf({
|
|
430
|
+
...req.body
|
|
431
|
+
}).save();
|
|
432
|
+
return res.send(result);
|
|
433
|
+
});
|
|
434
|
+
router.post("/documentation/tree/:key", async (req, res) => {
|
|
435
|
+
const result = await new Leaf({
|
|
436
|
+
...req.body,
|
|
437
|
+
id: req.params.key
|
|
438
|
+
}).save();
|
|
439
|
+
return res.send(result);
|
|
440
|
+
});
|
|
441
|
+
router.delete("/documentation/tree/:key", async (req, res) => {
|
|
442
|
+
const result = await Leaf.find({
|
|
443
|
+
id: req.params.key
|
|
444
|
+
});
|
|
445
|
+
if (result) return res.send(await result.remove());
|
|
446
|
+
return res.send();
|
|
447
|
+
});
|
|
448
|
+
return router;
|
|
398
449
|
};
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
if (!decrypted) {
|
|
422
|
-
throw new Error("Decryption failed");
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// ../../modules/documentation/backend/index.js
|
|
454
|
+
var require_backend3 = __commonJS({
|
|
455
|
+
"../../modules/documentation/backend/index.js"(exports2, module2) {
|
|
456
|
+
"use strict";
|
|
457
|
+
var { readFile } = require("fs/promises");
|
|
458
|
+
var PromiseB2 = require("bluebird");
|
|
459
|
+
var pathfs = require("path");
|
|
460
|
+
var Documentation = require_Documentation();
|
|
461
|
+
var plugin = {
|
|
462
|
+
enabled: true,
|
|
463
|
+
name: "Documentation",
|
|
464
|
+
displayName: "Documentation",
|
|
465
|
+
description: "Read documentation for a given service",
|
|
466
|
+
icon: "fas fa-book",
|
|
467
|
+
// export: Documentation,
|
|
468
|
+
placements: ["service"],
|
|
469
|
+
order: 6,
|
|
470
|
+
routes: require_routes2(),
|
|
471
|
+
finder: async (search, runeya) => {
|
|
423
472
|
}
|
|
424
|
-
return Buffer.from(decrypted).toString("utf-8");
|
|
425
473
|
};
|
|
426
|
-
|
|
427
|
-
const headMatch = conflictedData.match(/<<<<<<< HEAD\r?\n([\s\S]*?)\r?\n=======\r?\n([\s\S]*?)\r?\n>>>>>>>.*/);
|
|
428
|
-
if (!headMatch) {
|
|
429
|
-
throw new Error("Git conflict detected but could not be properly parsed");
|
|
430
|
-
}
|
|
431
|
-
try {
|
|
432
|
-
const ourVersion = headMatch[1];
|
|
433
|
-
const theirVersion = headMatch[2];
|
|
434
|
-
let ourDecrypted = "";
|
|
435
|
-
let theirDecrypted = "";
|
|
436
|
-
try {
|
|
437
|
-
ourDecrypted = await module2.exports.decrypt(ourVersion, options);
|
|
438
|
-
} catch (err) {
|
|
439
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
440
|
-
ourDecrypted = `[ERROR DECRYPTING OUR VERSION: ${errorMessage}]`;
|
|
441
|
-
}
|
|
442
|
-
try {
|
|
443
|
-
theirDecrypted = await module2.exports.decrypt(theirVersion, options);
|
|
444
|
-
} catch (err) {
|
|
445
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
446
|
-
theirDecrypted = `[ERROR DECRYPTING THEIR VERSION: ${errorMessage}]`;
|
|
447
|
-
}
|
|
448
|
-
const conflictData = {
|
|
449
|
-
original: conflictedData,
|
|
450
|
-
ourVersion: ourDecrypted,
|
|
451
|
-
theirVersion: theirDecrypted,
|
|
452
|
-
filePath: filePath || null,
|
|
453
|
-
filename: filePath ? path.basename(filePath) : null
|
|
454
|
-
};
|
|
455
|
-
const conflictId = conflictStorage.storeConflict(conflictData);
|
|
456
|
-
conflictData.id = conflictId;
|
|
457
|
-
sockets2.emit("crypto:conflict", conflictData);
|
|
458
|
-
return `${JSON.stringify({
|
|
459
|
-
ourVersion: ourDecrypted,
|
|
460
|
-
theirVersion: theirDecrypted
|
|
461
|
-
})}`;
|
|
462
|
-
} catch (error) {
|
|
463
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
464
|
-
console.error("Error handling git conflict:", errorMessage);
|
|
465
|
-
throw new Error(`Git conflict detected, but failed to process: ${errorMessage}`);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
474
|
+
module2.exports = plugin;
|
|
468
475
|
}
|
|
469
476
|
});
|
|
470
477
|
|
|
471
|
-
//
|
|
472
|
-
var
|
|
473
|
-
"
|
|
478
|
+
// ../../modules/finder/backend/routes.js
|
|
479
|
+
var require_routes3 = __commonJS({
|
|
480
|
+
"../../modules/finder/backend/routes.js"(exports2, module2) {
|
|
474
481
|
"use strict";
|
|
475
|
-
var
|
|
476
|
-
|
|
477
|
-
mkdirSync,
|
|
478
|
-
writeFileSync,
|
|
479
|
-
readFileSync,
|
|
480
|
-
unlinkSync
|
|
481
|
-
} = require("fs");
|
|
482
|
-
var pathfs = require("path");
|
|
483
|
-
var {
|
|
484
|
-
readdir,
|
|
485
|
-
mkdir,
|
|
486
|
-
writeFile,
|
|
487
|
-
readFile,
|
|
488
|
-
unlink
|
|
489
|
-
} = require("fs/promises");
|
|
490
|
-
var { fdir } = require("fdir");
|
|
482
|
+
var express = require("express");
|
|
483
|
+
var router = express.Router();
|
|
491
484
|
var PromiseB2 = require("bluebird");
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
return rootPath;
|
|
504
|
-
}
|
|
505
|
-
async getDbs(namespace = "") {
|
|
506
|
-
const pathToDbs = pathfs.resolve(this.getRootPath(), namespace);
|
|
507
|
-
if (!existsSync(pathToDbs)) await mkdir(pathToDbs, { recursive: true });
|
|
508
|
-
return (await readdir(pathToDbs)).map((id) => id.replace(pathfs.extname(id), "").replace(".encrypted", ""));
|
|
485
|
+
function pluginToUrl(plugin) {
|
|
486
|
+
for (let i = 0; i < plugin.placements.length; i += 1) {
|
|
487
|
+
const placement = plugin.placements[i];
|
|
488
|
+
if (typeof placement !== "string") {
|
|
489
|
+
if (placement.position === "toolbox") {
|
|
490
|
+
return `/toolbox${placement.goTo?.path || placement.goTo}`;
|
|
491
|
+
}
|
|
492
|
+
if (placement.position === "sidebar") {
|
|
493
|
+
return `${placement.goTo?.path || placement.goTo}`;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
509
496
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
sockets2.emit("system:wrongKey");
|
|
546
|
-
throw err;
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
} catch (err) {
|
|
550
|
-
console.error(path, err);
|
|
551
|
-
sockets2.emit("system:wrongKey");
|
|
552
|
-
throw err;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
this.cache[id] = JSON.parse(db);
|
|
556
|
-
if (!alasql.tables[table]) {
|
|
557
|
-
await alasql(`CREATE TABLE ${table}`);
|
|
558
|
-
}
|
|
559
|
-
alasql.tables[table].data = this.cache[id];
|
|
560
|
-
return this.cache[id];
|
|
561
|
-
};
|
|
562
|
-
const write = async (data) => {
|
|
563
|
-
let db = JSON.stringify(data, null, 2);
|
|
564
|
-
const path = await getPath();
|
|
565
|
-
const additionnalNonce = path.split(".runeya").pop();
|
|
566
|
-
if (encrypted) db = await encrypt(db, { additionnalNonce });
|
|
567
|
-
writeFileSync(path, db, "utf-8");
|
|
568
|
-
this.cache[id] = data;
|
|
569
|
-
if (alasql.tables[table]) {
|
|
570
|
-
alasql.tables[table].data = data;
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
const escapeQuote = (data) => {
|
|
574
|
-
if (typeof data === "string") {
|
|
575
|
-
return data.replace(/'/g, "''");
|
|
576
|
-
}
|
|
577
|
-
return data;
|
|
578
|
-
};
|
|
579
|
-
const setValue = (item) => {
|
|
580
|
-
if (item == null) {
|
|
581
|
-
return "NULL";
|
|
582
|
-
}
|
|
583
|
-
if (item instanceof Date && item.toISOString) {
|
|
584
|
-
return `'${item.toISOString()}'`;
|
|
585
|
-
}
|
|
586
|
-
if (typeof item === "string") {
|
|
587
|
-
return `'${escapeQuote(item)}'`;
|
|
588
|
-
}
|
|
589
|
-
return `${item}`;
|
|
590
|
-
};
|
|
591
|
-
return {
|
|
592
|
-
getPath,
|
|
593
|
-
alasql: {
|
|
594
|
-
table,
|
|
595
|
-
buildUpdateQuery(data) {
|
|
596
|
-
const set = [];
|
|
597
|
-
Object.keys(data).forEach((key) => {
|
|
598
|
-
set.push(`${key} = ${setValue(data[key])}`);
|
|
599
|
-
});
|
|
600
|
-
return set.join(", ");
|
|
601
|
-
},
|
|
602
|
-
read: async (sql) => {
|
|
603
|
-
await read();
|
|
604
|
-
return alasql.promise(sql);
|
|
605
|
-
},
|
|
606
|
-
/**
|
|
607
|
-
*
|
|
608
|
-
* @param {{where?: string, orderBy?: string, limit?: number, offset?: number}} param0
|
|
609
|
-
* @returns {Promise<any[]>}
|
|
610
|
-
*/
|
|
611
|
-
simpleSelect: async ({ where, orderBy, limit, offset }) => {
|
|
612
|
-
await read();
|
|
613
|
-
return alasql.promise(`SELECT * FROM ${table} ${where ? `WHERE ${where}` : ""} ${orderBy ? `ORDER BY ${orderBy}` : ""} ${limit ? `LIMIT ${limit}` : ""} ${offset ? `OFFSET ${offset}` : ""}`);
|
|
614
|
-
},
|
|
615
|
-
/** @param {string} where */
|
|
616
|
-
delete: async (where) => {
|
|
617
|
-
await read();
|
|
618
|
-
await alasql.promise(`DELETE FROM ${table} WHERE ${where}`);
|
|
619
|
-
await write(await alasql(`select * from ${table}`));
|
|
620
|
-
},
|
|
621
|
-
insertOne: async (data) => {
|
|
622
|
-
await read();
|
|
623
|
-
await alasql.promise(`INSERT INTO ${table} VALUES ${JSON.stringify(data)}`);
|
|
624
|
-
await write(await alasql(`select * from ${table}`));
|
|
625
|
-
},
|
|
626
|
-
write: async (sql, value) => {
|
|
627
|
-
await read();
|
|
628
|
-
await alasql.promise(sql, value);
|
|
629
|
-
await write(await alasql(`select * from ${table}`));
|
|
630
|
-
}
|
|
631
|
-
},
|
|
632
|
-
write,
|
|
633
|
-
read,
|
|
634
|
-
delete: async () => {
|
|
635
|
-
delete this.cache[id];
|
|
636
|
-
return unlink(await getPath());
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
}();
|
|
497
|
+
return "";
|
|
498
|
+
}
|
|
499
|
+
var routes = (runeya) => {
|
|
500
|
+
const {
|
|
501
|
+
getServices,
|
|
502
|
+
helpers: { searchString }
|
|
503
|
+
} = runeya;
|
|
504
|
+
router.get("/finder/search", async (req, res) => {
|
|
505
|
+
const search = req.query.q?.toString()?.toUpperCase() || "";
|
|
506
|
+
const services = getServices().filter((service) => searchString(service?.label, search)).map((service) => ({
|
|
507
|
+
title: service.label,
|
|
508
|
+
description: service.description,
|
|
509
|
+
group: "Service",
|
|
510
|
+
url: `/stack-single/${service.label}`
|
|
511
|
+
}));
|
|
512
|
+
const { plugins } = runeya;
|
|
513
|
+
const _plugins = (await PromiseB2.map(Object.keys(plugins), (key) => plugins[key]).map(async (plugin) => [
|
|
514
|
+
...await plugin?.finder?.(search, runeya)?.catch?.(() => []) || [],
|
|
515
|
+
...searchString(plugin.name, search) ? [{
|
|
516
|
+
title: plugin.displayName || plugin.name,
|
|
517
|
+
description: plugin.description,
|
|
518
|
+
group: "Plugin",
|
|
519
|
+
icon: plugin.icon,
|
|
520
|
+
url: pluginToUrl(plugin) || ""
|
|
521
|
+
}] : []
|
|
522
|
+
])).flat().filter((a) => a?.url);
|
|
523
|
+
const result = [
|
|
524
|
+
...services,
|
|
525
|
+
..._plugins
|
|
526
|
+
].filter((a) => a);
|
|
527
|
+
res.send(result);
|
|
528
|
+
});
|
|
529
|
+
return router;
|
|
530
|
+
};
|
|
531
|
+
module2.exports = routes;
|
|
641
532
|
}
|
|
642
533
|
});
|
|
643
534
|
|
|
644
|
-
// ../../modules/
|
|
645
|
-
var
|
|
646
|
-
"../../modules/
|
|
535
|
+
// ../../modules/finder/backend/index.js
|
|
536
|
+
var require_backend4 = __commonJS({
|
|
537
|
+
"../../modules/finder/backend/index.js"(exports2, module2) {
|
|
647
538
|
"use strict";
|
|
648
|
-
var
|
|
649
|
-
var
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
static async find(envId) {
|
|
667
|
-
const documentations = await this.all();
|
|
668
|
-
return documentations.find((env) => env.id === envId);
|
|
669
|
-
}
|
|
670
|
-
async save() {
|
|
671
|
-
const obj = this.toStorage();
|
|
672
|
-
await dbs2.getDb(`documentations/${this.id}`).write(obj);
|
|
673
|
-
return this;
|
|
674
|
-
}
|
|
675
|
-
async update(env) {
|
|
676
|
-
this.transform = env.transform;
|
|
677
|
-
this.label = env.label;
|
|
678
|
-
await dbs2.getDb(`documentations/${this.id}`).write(this.toStorage());
|
|
679
|
-
}
|
|
680
|
-
async delete() {
|
|
681
|
-
await dbs2.getDb(`documentations/${this.id}`).delete();
|
|
682
|
-
}
|
|
683
|
-
toStorage() {
|
|
684
|
-
return {
|
|
685
|
-
id: this.id,
|
|
686
|
-
label: this.label,
|
|
687
|
-
transform: this.transform
|
|
688
|
-
};
|
|
689
|
-
}
|
|
539
|
+
var commandExists = require("command-exists");
|
|
540
|
+
var plugin = {
|
|
541
|
+
enabled: true,
|
|
542
|
+
name: "Finder",
|
|
543
|
+
displayName: "Finder",
|
|
544
|
+
description: "Find all you want inside this app",
|
|
545
|
+
icon: "fab fa-git-alt",
|
|
546
|
+
export: null,
|
|
547
|
+
order: -1,
|
|
548
|
+
placements: ["global", {
|
|
549
|
+
position: "sidebar",
|
|
550
|
+
label: "Finder",
|
|
551
|
+
icon: "fas fa-search",
|
|
552
|
+
goTo: { path: "/Finder" },
|
|
553
|
+
active: "Finder"
|
|
554
|
+
}],
|
|
555
|
+
hidden: () => commandExists("git").then(() => false).catch(() => true),
|
|
556
|
+
routes: require_routes3()
|
|
690
557
|
};
|
|
691
|
-
module2.exports =
|
|
558
|
+
module2.exports = plugin;
|
|
692
559
|
}
|
|
693
560
|
});
|
|
694
561
|
|
|
695
|
-
//
|
|
696
|
-
var
|
|
697
|
-
"
|
|
562
|
+
// helpers/exec.js
|
|
563
|
+
var require_exec = __commonJS({
|
|
564
|
+
"helpers/exec.js"(exports2, module2) {
|
|
698
565
|
"use strict";
|
|
699
|
-
var
|
|
700
|
-
|
|
701
|
-
var dbs2 = require_dbs();
|
|
702
|
-
var { v4 } = require("uuid");
|
|
703
|
-
var dbLeafTree = dbs2.getDb(`leafs-leafs`, { encrypted: true, defaultData: [] }).alasql;
|
|
704
|
-
var Leaf = class _Leaf {
|
|
566
|
+
var { exec } = require("child_process");
|
|
567
|
+
module2.exports = {
|
|
705
568
|
/**
|
|
706
|
-
* @param {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
this.id = leaf.id || v4();
|
|
710
|
-
this.docId = leaf.docId || "";
|
|
711
|
-
this.serviceId = leaf.serviceId || "";
|
|
712
|
-
this.label = leaf.label || "";
|
|
713
|
-
this.position = leaf.position || -1;
|
|
714
|
-
this.text = leaf.text || "";
|
|
715
|
-
this.parentId = leaf.parentId || "";
|
|
716
|
-
}
|
|
717
|
-
static async getTree(serviceLabel) {
|
|
718
|
-
const leafs = await dbLeafTree.read(`Select * from ${dbLeafTree.table} ${serviceLabel ? `where serviceId = '${serviceLabel}'` : `where serviceId=''`}`);
|
|
719
|
-
return leafs;
|
|
720
|
-
}
|
|
721
|
-
toStorage() {
|
|
722
|
-
return {
|
|
723
|
-
docId: this.docId,
|
|
724
|
-
position: this.position,
|
|
725
|
-
serviceId: this.serviceId,
|
|
726
|
-
label: this.label,
|
|
727
|
-
text: this.text,
|
|
728
|
-
parentId: this.parentId
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
async remove() {
|
|
732
|
-
return dbLeafTree.write(`DELETE from ${dbLeafTree.table} where id = '${this.id}'`);
|
|
733
|
-
}
|
|
734
|
-
static async find({ id }) {
|
|
735
|
-
const [leaf] = await dbLeafTree.read(`Select * from ${dbLeafTree.table} where id='${id}'`);
|
|
736
|
-
return leaf ? new _Leaf(leaf) : null;
|
|
737
|
-
}
|
|
738
|
-
async save() {
|
|
739
|
-
const leafExists = await _Leaf.find({ id: this.id });
|
|
740
|
-
const storage = this.toStorage();
|
|
741
|
-
const set = dbLeafTree.buildUpdateQuery(storage);
|
|
742
|
-
await leafExists ? dbLeafTree.write(`update ${dbLeafTree.table} set ${set} where id='${this.id}'`) : dbLeafTree.write(`insert into ${dbLeafTree.table} (id, docId, position, serviceId, label, text, parentId) values ('${this.id}', '${this.docId}', ${this.position}, '${this.serviceId}', '${this.label.replace(/'/g, "''")}', '${this.text.replace(/'/g, "''")}', '${this.parentId}')`);
|
|
743
|
-
return this;
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
module2.exports = Leaf;
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
|
|
750
|
-
// ../../modules/documentation/backend/routes.js
|
|
751
|
-
var require_routes2 = __commonJS({
|
|
752
|
-
"../../modules/documentation/backend/routes.js"(exports2, module2) {
|
|
753
|
-
"use strict";
|
|
754
|
-
var express = require("express");
|
|
755
|
-
var Leaf = require_Leaf();
|
|
756
|
-
var PromiseB2 = require("bluebird");
|
|
757
|
-
var router = express.Router();
|
|
758
|
-
module2.exports = (runeya) => {
|
|
759
|
-
const { findService } = runeya;
|
|
760
|
-
router.get("/documentation/tree", async (req, res) => {
|
|
761
|
-
const service = findService(req.query.serviceId?.toString() || "");
|
|
762
|
-
const result = await Leaf.getTree(service?.label);
|
|
763
|
-
return res.send(result);
|
|
764
|
-
});
|
|
765
|
-
router.post("/documentation/tree/sort", async (req, res) => {
|
|
766
|
-
const leafs = await PromiseB2.mapSeries(req.body, async (_leaf, index) => {
|
|
767
|
-
const leaf = await Leaf.find({ id: _leaf.id });
|
|
768
|
-
if (!leaf) return;
|
|
769
|
-
leaf.position = index;
|
|
770
|
-
await leaf.save();
|
|
771
|
-
return leaf;
|
|
772
|
-
});
|
|
773
|
-
return res.send(leafs);
|
|
774
|
-
});
|
|
775
|
-
router.post("/documentation/tree", async (req, res) => {
|
|
776
|
-
const result = await new Leaf({
|
|
777
|
-
...req.body
|
|
778
|
-
}).save();
|
|
779
|
-
return res.send(result);
|
|
780
|
-
});
|
|
781
|
-
router.post("/documentation/tree/:key", async (req, res) => {
|
|
782
|
-
const result = await new Leaf({
|
|
783
|
-
...req.body,
|
|
784
|
-
id: req.params.key
|
|
785
|
-
}).save();
|
|
786
|
-
return res.send(result);
|
|
787
|
-
});
|
|
788
|
-
router.delete("/documentation/tree/:key", async (req, res) => {
|
|
789
|
-
const result = await Leaf.find({
|
|
790
|
-
id: req.params.key
|
|
791
|
-
});
|
|
792
|
-
if (result) return res.send(await result.remove());
|
|
793
|
-
return res.send();
|
|
794
|
-
});
|
|
795
|
-
return router;
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
});
|
|
799
|
-
|
|
800
|
-
// ../../modules/documentation/backend/index.js
|
|
801
|
-
var require_backend3 = __commonJS({
|
|
802
|
-
"../../modules/documentation/backend/index.js"(exports2, module2) {
|
|
803
|
-
"use strict";
|
|
804
|
-
var { readFile } = require("fs/promises");
|
|
805
|
-
var PromiseB2 = require("bluebird");
|
|
806
|
-
var pathfs = require("path");
|
|
807
|
-
var Documentation = require_Documentation();
|
|
808
|
-
var plugin = {
|
|
809
|
-
enabled: true,
|
|
810
|
-
name: "Documentation",
|
|
811
|
-
displayName: "Documentation",
|
|
812
|
-
description: "Read documentation for a given service",
|
|
813
|
-
icon: "fas fa-book",
|
|
814
|
-
// export: Documentation,
|
|
815
|
-
placements: ["service"],
|
|
816
|
-
order: 6,
|
|
817
|
-
routes: require_routes2(),
|
|
818
|
-
finder: async (search, runeya) => {
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
module2.exports = plugin;
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
|
|
825
|
-
// ../../modules/finder/backend/routes.js
|
|
826
|
-
var require_routes3 = __commonJS({
|
|
827
|
-
"../../modules/finder/backend/routes.js"(exports2, module2) {
|
|
828
|
-
"use strict";
|
|
829
|
-
var express = require("express");
|
|
830
|
-
var router = express.Router();
|
|
831
|
-
var PromiseB2 = require("bluebird");
|
|
832
|
-
function pluginToUrl(plugin) {
|
|
833
|
-
for (let i = 0; i < plugin.placements.length; i += 1) {
|
|
834
|
-
const placement = plugin.placements[i];
|
|
835
|
-
if (typeof placement !== "string") {
|
|
836
|
-
if (placement.position === "toolbox") {
|
|
837
|
-
return `/toolbox${placement.goTo?.path || placement.goTo}`;
|
|
838
|
-
}
|
|
839
|
-
if (placement.position === "sidebar") {
|
|
840
|
-
return `${placement.goTo?.path || placement.goTo}`;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
return "";
|
|
845
|
-
}
|
|
846
|
-
var routes = (runeya) => {
|
|
847
|
-
const {
|
|
848
|
-
getServices,
|
|
849
|
-
helpers: { searchString }
|
|
850
|
-
} = runeya;
|
|
851
|
-
router.get("/finder/search", async (req, res) => {
|
|
852
|
-
const search = req.query.q?.toString()?.toUpperCase() || "";
|
|
853
|
-
const services = getServices().filter((service) => searchString(service?.label, search)).map((service) => ({
|
|
854
|
-
title: service.label,
|
|
855
|
-
description: service.description,
|
|
856
|
-
group: "Service",
|
|
857
|
-
url: `/stack-single/${service.label}`
|
|
858
|
-
}));
|
|
859
|
-
const { plugins } = runeya;
|
|
860
|
-
const _plugins = (await PromiseB2.map(Object.keys(plugins), (key) => plugins[key]).map(async (plugin) => [
|
|
861
|
-
...await plugin?.finder?.(search, runeya)?.catch?.(() => []) || [],
|
|
862
|
-
...searchString(plugin.name, search) ? [{
|
|
863
|
-
title: plugin.displayName || plugin.name,
|
|
864
|
-
description: plugin.description,
|
|
865
|
-
group: "Plugin",
|
|
866
|
-
icon: plugin.icon,
|
|
867
|
-
url: pluginToUrl(plugin) || ""
|
|
868
|
-
}] : []
|
|
869
|
-
])).flat().filter((a) => a?.url);
|
|
870
|
-
const result = [
|
|
871
|
-
...services,
|
|
872
|
-
..._plugins
|
|
873
|
-
].filter((a) => a);
|
|
874
|
-
res.send(result);
|
|
875
|
-
});
|
|
876
|
-
return router;
|
|
877
|
-
};
|
|
878
|
-
module2.exports = routes;
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
|
|
882
|
-
// ../../modules/finder/backend/index.js
|
|
883
|
-
var require_backend4 = __commonJS({
|
|
884
|
-
"../../modules/finder/backend/index.js"(exports2, module2) {
|
|
885
|
-
"use strict";
|
|
886
|
-
var commandExists = require("command-exists");
|
|
887
|
-
var plugin = {
|
|
888
|
-
enabled: true,
|
|
889
|
-
name: "Finder",
|
|
890
|
-
displayName: "Finder",
|
|
891
|
-
description: "Find all you want inside this app",
|
|
892
|
-
icon: "fab fa-git-alt",
|
|
893
|
-
export: null,
|
|
894
|
-
order: -1,
|
|
895
|
-
placements: ["global", {
|
|
896
|
-
position: "sidebar",
|
|
897
|
-
label: "Finder",
|
|
898
|
-
icon: "fas fa-search",
|
|
899
|
-
goTo: { path: "/Finder" },
|
|
900
|
-
active: "Finder"
|
|
901
|
-
}],
|
|
902
|
-
hidden: () => commandExists("git").then(() => false).catch(() => true),
|
|
903
|
-
routes: require_routes3()
|
|
904
|
-
};
|
|
905
|
-
module2.exports = plugin;
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
// helpers/exec.js
|
|
910
|
-
var require_exec = __commonJS({
|
|
911
|
-
"helpers/exec.js"(exports2, module2) {
|
|
912
|
-
"use strict";
|
|
913
|
-
var { exec } = require("child_process");
|
|
914
|
-
module2.exports = {
|
|
915
|
-
/**
|
|
916
|
-
* @param {string} cmd
|
|
917
|
-
* @param {import('child_process').ExecOptions} options
|
|
918
|
-
* @returns {Promise<string>}
|
|
569
|
+
* @param {string} cmd
|
|
570
|
+
* @param {import('child_process').ExecOptions} options
|
|
571
|
+
* @returns {Promise<string>}
|
|
919
572
|
*/
|
|
920
573
|
execAsync(cmd, options) {
|
|
921
574
|
return new Promise((res, rej) => {
|
|
@@ -3601,7 +3254,7 @@ var require_stack = __commonJS({
|
|
|
3601
3254
|
var CustomObservable = require_CustomObservable();
|
|
3602
3255
|
var args2 = require_args();
|
|
3603
3256
|
var { existsSync, mkdirSync } = require("fs");
|
|
3604
|
-
var { rename } = require("fs/promises");
|
|
3257
|
+
var { rename, cp, rmdir, rm } = require("fs/promises");
|
|
3605
3258
|
var pathfs = require("path");
|
|
3606
3259
|
var { default: axios } = require("axios");
|
|
3607
3260
|
function Stack(stack) {
|
|
@@ -3672,7 +3325,6 @@ var require_stack = __commonJS({
|
|
|
3672
3325
|
};
|
|
3673
3326
|
Stack.getRootPath = () => {
|
|
3674
3327
|
const rootPath = pathfs.resolve(args2.rootPath, ".runeya");
|
|
3675
|
-
if (!existsSync(rootPath)) mkdirSync(rootPath, { recursive: true });
|
|
3676
3328
|
return rootPath;
|
|
3677
3329
|
};
|
|
3678
3330
|
Stack.parse = async function() {
|
|
@@ -3735,18 +3387,6 @@ var require_stack = __commonJS({
|
|
|
3735
3387
|
return Stack.findService(serviceLabel);
|
|
3736
3388
|
};
|
|
3737
3389
|
Stack.selectConf = async function() {
|
|
3738
|
-
const localLegacyPath = pathfs.resolve(require_stack().getRootPath(), "../.stackmonitor");
|
|
3739
|
-
const localNewPath = pathfs.resolve(require_stack().getRootPath(), ".runeya");
|
|
3740
|
-
if (existsSync(localLegacyPath) && !existsSync(localNewPath)) {
|
|
3741
|
-
console.log("Legacy path found, move to new path");
|
|
3742
|
-
await rename(localLegacyPath, localNewPath);
|
|
3743
|
-
}
|
|
3744
|
-
const globalLegacyPath = pathfs.resolve(require("os").homedir(), ".stackmonitor");
|
|
3745
|
-
const globalNewPath = pathfs.resolve(require("os").homedir(), ".runeya-global");
|
|
3746
|
-
if (existsSync(globalLegacyPath) && !existsSync(globalNewPath)) {
|
|
3747
|
-
console.log("Legacy path found, move to new path");
|
|
3748
|
-
await rename(globalLegacyPath, globalNewPath);
|
|
3749
|
-
}
|
|
3750
3390
|
await EncryptionKey.init();
|
|
3751
3391
|
if (!EncryptionKey.encryptionKey) {
|
|
3752
3392
|
await EncryptionKey.saveKey(await EncryptionKey.generateKey());
|
|
@@ -3806,6 +3446,414 @@ var require_stack = __commonJS({
|
|
|
3806
3446
|
}
|
|
3807
3447
|
});
|
|
3808
3448
|
|
|
3449
|
+
// models/EncryptionKey.js
|
|
3450
|
+
var require_EncryptionKey = __commonJS({
|
|
3451
|
+
"models/EncryptionKey.js"(exports2, module2) {
|
|
3452
|
+
"use strict";
|
|
3453
|
+
var { existsSync } = require("fs");
|
|
3454
|
+
var path = require("path");
|
|
3455
|
+
var { writeFile, readFile, appendFile } = require("fs/promises");
|
|
3456
|
+
var { randomUUID: randomUUID2 } = require("crypto");
|
|
3457
|
+
var dbs2 = require_dbs();
|
|
3458
|
+
var { generateKey, encrypt, decrypt } = require_crypto();
|
|
3459
|
+
var reencryptNodered = require_reencrypt_nodered();
|
|
3460
|
+
var pathfs = require("path");
|
|
3461
|
+
var args2 = require_args();
|
|
3462
|
+
var _EncryptionKey_instances, getDb_fn;
|
|
3463
|
+
var EncryptionKey = class {
|
|
3464
|
+
constructor() {
|
|
3465
|
+
__privateAdd(this, _EncryptionKey_instances);
|
|
3466
|
+
this.encryptionKey = "";
|
|
3467
|
+
}
|
|
3468
|
+
async init() {
|
|
3469
|
+
this.encryptionKey = (await __privateMethod(this, _EncryptionKey_instances, getDb_fn).call(this).read()).encryptionKey;
|
|
3470
|
+
}
|
|
3471
|
+
async update() {
|
|
3472
|
+
return __privateMethod(this, _EncryptionKey_instances, getDb_fn).call(this).write(this.toStorage());
|
|
3473
|
+
}
|
|
3474
|
+
toStorage() {
|
|
3475
|
+
return {
|
|
3476
|
+
encryptionKey: this.encryptionKey
|
|
3477
|
+
};
|
|
3478
|
+
}
|
|
3479
|
+
async generateKey() {
|
|
3480
|
+
return generateKey();
|
|
3481
|
+
}
|
|
3482
|
+
async testKey(encryptionKey) {
|
|
3483
|
+
try {
|
|
3484
|
+
const variable = randomUUID2();
|
|
3485
|
+
const result = await encrypt(variable, { encryptionKey });
|
|
3486
|
+
const decrypted = await decrypt(result, { encryptionKey });
|
|
3487
|
+
if (decrypted === variable) return true;
|
|
3488
|
+
return false;
|
|
3489
|
+
} catch (error) {
|
|
3490
|
+
console.error(error);
|
|
3491
|
+
return false;
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
async saveKey(key, { noReload } = { noReload: false }) {
|
|
3495
|
+
if (!await this.testKey(key)) throw new Error("Key not valid");
|
|
3496
|
+
try {
|
|
3497
|
+
const envSample = (await dbs2.getDbs("envs"))[0];
|
|
3498
|
+
if (envSample) await dbs2.getDb(`envs/${envSample}`).read();
|
|
3499
|
+
if (this.encryptionKey) {
|
|
3500
|
+
await reencryptNodered(this.encryptionKey, key, pathfs.resolve(require_stack().getRootPath(), "nodered/flow_cred.json"));
|
|
3501
|
+
await dbs2.reencrypt(this.encryptionKey, key);
|
|
3502
|
+
}
|
|
3503
|
+
;
|
|
3504
|
+
} catch (error) {
|
|
3505
|
+
console.error(error);
|
|
3506
|
+
}
|
|
3507
|
+
const shouldRestart = this.encryptionKey !== key;
|
|
3508
|
+
this.encryptionKey = key;
|
|
3509
|
+
await this.update();
|
|
3510
|
+
if (!noReload) {
|
|
3511
|
+
await require_stack().selectConf();
|
|
3512
|
+
}
|
|
3513
|
+
if (shouldRestart) {
|
|
3514
|
+
console.log("Restart...");
|
|
3515
|
+
require("child_process").spawn(process.argv[0], process.argv.slice(1), {
|
|
3516
|
+
cwd: args2.initialCwd,
|
|
3517
|
+
detached: true,
|
|
3518
|
+
stdio: "inherit"
|
|
3519
|
+
}).unref();
|
|
3520
|
+
process.exit(0);
|
|
3521
|
+
}
|
|
3522
|
+
return key;
|
|
3523
|
+
}
|
|
3524
|
+
};
|
|
3525
|
+
_EncryptionKey_instances = new WeakSet();
|
|
3526
|
+
getDb_fn = function() {
|
|
3527
|
+
return dbs2.getDb("encryption-key", { encrypted: false });
|
|
3528
|
+
};
|
|
3529
|
+
module2.exports = new EncryptionKey();
|
|
3530
|
+
}
|
|
3531
|
+
});
|
|
3532
|
+
|
|
3533
|
+
// helpers/crypto.js
|
|
3534
|
+
var require_crypto = __commonJS({
|
|
3535
|
+
"helpers/crypto.js"(exports2, module2) {
|
|
3536
|
+
"use strict";
|
|
3537
|
+
var _sodium = require("libsodium-wrappers");
|
|
3538
|
+
var crypto = require("crypto");
|
|
3539
|
+
var { sockets: sockets2 } = require_src();
|
|
3540
|
+
var conflictStorage = require_conflictStorage();
|
|
3541
|
+
var path = require("path");
|
|
3542
|
+
module2.exports.generateKey = async () => {
|
|
3543
|
+
await _sodium.ready;
|
|
3544
|
+
const sodium = _sodium;
|
|
3545
|
+
const key = sodium.crypto_aead_aegis256_keygen();
|
|
3546
|
+
return sodium.to_base64(key);
|
|
3547
|
+
};
|
|
3548
|
+
module2.exports.encrypt = async (data, { additionnalNonce = "", encryptionKey = "" } = {}) => {
|
|
3549
|
+
await _sodium.ready;
|
|
3550
|
+
const sodium = _sodium;
|
|
3551
|
+
if (!encryptionKey) encryptionKey = require_EncryptionKey().encryptionKey;
|
|
3552
|
+
const key = sodium.from_base64(encryptionKey);
|
|
3553
|
+
if (!key || key.length !== sodium.crypto_secretbox_KEYBYTES) {
|
|
3554
|
+
throw new Error("Invalid encryption key length");
|
|
3555
|
+
}
|
|
3556
|
+
let nonce;
|
|
3557
|
+
if (additionnalNonce) {
|
|
3558
|
+
const combinedHash = crypto.createHash("blake2b512").update(data + additionnalNonce).digest();
|
|
3559
|
+
nonce = combinedHash.slice(0, sodium.crypto_secretbox_NONCEBYTES);
|
|
3560
|
+
} else {
|
|
3561
|
+
nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
|
3562
|
+
}
|
|
3563
|
+
const dataStr = typeof data === "string" ? data : String(data);
|
|
3564
|
+
const dataArray = new TextEncoder().encode(dataStr);
|
|
3565
|
+
const ciphertext = sodium.crypto_secretbox_easy(dataArray, nonce, key);
|
|
3566
|
+
return Buffer.concat([
|
|
3567
|
+
Buffer.from(nonce.buffer, nonce.byteOffset, nonce.byteLength),
|
|
3568
|
+
Buffer.from(ciphertext.buffer, ciphertext.byteOffset, ciphertext.byteLength)
|
|
3569
|
+
]).toString("base64");
|
|
3570
|
+
};
|
|
3571
|
+
module2.exports.decryptFile = async (encryptedData, options = {}, filePath) => {
|
|
3572
|
+
if (typeof encryptedData === "string" && (encryptedData.includes("<<<<<<< HEAD") || encryptedData.includes("=======") || encryptedData.includes(">>>>>>>"))) {
|
|
3573
|
+
return await handleGitConflict(encryptedData, options, filePath);
|
|
3574
|
+
}
|
|
3575
|
+
return await module2.exports.decrypt(encryptedData, options);
|
|
3576
|
+
};
|
|
3577
|
+
module2.exports.decrypt = async (encryptedData, { additionnalNonce = "", encryptionKey = "" } = {}) => {
|
|
3578
|
+
if (typeof encryptedData === "string" && (encryptedData.includes("<<<<<<< HEAD") || encryptedData.includes("=======") || encryptedData.includes(">>>>>>>"))) {
|
|
3579
|
+
return await handleGitConflict(encryptedData, { additionnalNonce, encryptionKey });
|
|
3580
|
+
}
|
|
3581
|
+
await _sodium.ready;
|
|
3582
|
+
const sodium = _sodium;
|
|
3583
|
+
if (!encryptionKey) encryptionKey = require_EncryptionKey().encryptionKey;
|
|
3584
|
+
const key = sodium.from_base64(encryptionKey);
|
|
3585
|
+
if (!key || key.length !== sodium.crypto_secretbox_KEYBYTES) {
|
|
3586
|
+
throw new Error("Invalid decryption key length");
|
|
3587
|
+
}
|
|
3588
|
+
const encryptedBuffer = Buffer.from(encryptedData, "base64");
|
|
3589
|
+
const nonce = encryptedBuffer.slice(0, sodium.crypto_secretbox_NONCEBYTES);
|
|
3590
|
+
const ciphertext = encryptedBuffer.slice(sodium.crypto_secretbox_NONCEBYTES);
|
|
3591
|
+
let decrypted;
|
|
3592
|
+
try {
|
|
3593
|
+
const ciphertextArray = new Uint8Array(ciphertext);
|
|
3594
|
+
const nonceArray = new Uint8Array(nonce);
|
|
3595
|
+
decrypted = sodium.crypto_secretbox_open_easy(ciphertextArray, nonceArray, key);
|
|
3596
|
+
} catch (error) {
|
|
3597
|
+
throw new Error("Decryption failed");
|
|
3598
|
+
}
|
|
3599
|
+
if (!decrypted) {
|
|
3600
|
+
throw new Error("Decryption failed");
|
|
3601
|
+
}
|
|
3602
|
+
return Buffer.from(decrypted).toString("utf-8");
|
|
3603
|
+
};
|
|
3604
|
+
async function handleGitConflict(conflictedData, options, filePath) {
|
|
3605
|
+
const headMatch = conflictedData.match(/<<<<<<< HEAD\r?\n([\s\S]*?)\r?\n=======\r?\n([\s\S]*?)\r?\n>>>>>>>.*/);
|
|
3606
|
+
if (!headMatch) {
|
|
3607
|
+
throw new Error("Git conflict detected but could not be properly parsed");
|
|
3608
|
+
}
|
|
3609
|
+
try {
|
|
3610
|
+
const ourVersion = headMatch[1];
|
|
3611
|
+
const theirVersion = headMatch[2];
|
|
3612
|
+
let ourDecrypted = "";
|
|
3613
|
+
let theirDecrypted = "";
|
|
3614
|
+
try {
|
|
3615
|
+
ourDecrypted = await module2.exports.decrypt(ourVersion, options);
|
|
3616
|
+
} catch (err) {
|
|
3617
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
3618
|
+
ourDecrypted = `[ERROR DECRYPTING OUR VERSION: ${errorMessage}]`;
|
|
3619
|
+
}
|
|
3620
|
+
try {
|
|
3621
|
+
theirDecrypted = await module2.exports.decrypt(theirVersion, options);
|
|
3622
|
+
} catch (err) {
|
|
3623
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
3624
|
+
theirDecrypted = `[ERROR DECRYPTING THEIR VERSION: ${errorMessage}]`;
|
|
3625
|
+
}
|
|
3626
|
+
const conflictData = {
|
|
3627
|
+
original: conflictedData,
|
|
3628
|
+
ourVersion: ourDecrypted,
|
|
3629
|
+
theirVersion: theirDecrypted,
|
|
3630
|
+
filePath: filePath || null,
|
|
3631
|
+
filename: filePath ? path.basename(filePath) : null
|
|
3632
|
+
};
|
|
3633
|
+
const conflictId = conflictStorage.storeConflict(conflictData);
|
|
3634
|
+
conflictData.id = conflictId;
|
|
3635
|
+
sockets2.emit("crypto:conflict", conflictData);
|
|
3636
|
+
return `${JSON.stringify({
|
|
3637
|
+
ourVersion: ourDecrypted,
|
|
3638
|
+
theirVersion: theirDecrypted
|
|
3639
|
+
})}`;
|
|
3640
|
+
} catch (error) {
|
|
3641
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3642
|
+
console.error("Error handling git conflict:", errorMessage);
|
|
3643
|
+
throw new Error(`Git conflict detected, but failed to process: ${errorMessage}`);
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
});
|
|
3648
|
+
|
|
3649
|
+
// helpers/dbs.js
|
|
3650
|
+
var require_dbs = __commonJS({
|
|
3651
|
+
"helpers/dbs.js"(exports2, module2) {
|
|
3652
|
+
"use strict";
|
|
3653
|
+
var {
|
|
3654
|
+
existsSync,
|
|
3655
|
+
mkdirSync,
|
|
3656
|
+
writeFileSync,
|
|
3657
|
+
readFileSync,
|
|
3658
|
+
unlinkSync
|
|
3659
|
+
} = require("fs");
|
|
3660
|
+
var pathfs = require("path");
|
|
3661
|
+
var {
|
|
3662
|
+
readdir,
|
|
3663
|
+
mkdir,
|
|
3664
|
+
writeFile,
|
|
3665
|
+
readFile,
|
|
3666
|
+
unlink
|
|
3667
|
+
} = require("fs/promises");
|
|
3668
|
+
var { fdir } = require("fdir");
|
|
3669
|
+
var PromiseB2 = require("bluebird");
|
|
3670
|
+
var { sockets: sockets2 } = require_src();
|
|
3671
|
+
var args2 = require_args();
|
|
3672
|
+
var { encrypt, decrypt, decryptFile } = require_crypto();
|
|
3673
|
+
var alasql = require("alasql");
|
|
3674
|
+
module2.exports = new class {
|
|
3675
|
+
constructor() {
|
|
3676
|
+
__publicField(this, "cache", {});
|
|
3677
|
+
}
|
|
3678
|
+
getRootPath() {
|
|
3679
|
+
const rootPath = pathfs.resolve(args2.rootPath, ".runeya/dbs");
|
|
3680
|
+
if (!existsSync(rootPath)) mkdirSync(rootPath, { recursive: true });
|
|
3681
|
+
return rootPath;
|
|
3682
|
+
}
|
|
3683
|
+
async getDbs(namespace = "") {
|
|
3684
|
+
const pathToDbs = pathfs.resolve(this.getRootPath(), namespace);
|
|
3685
|
+
if (!existsSync(pathToDbs)) await mkdir(pathToDbs, { recursive: true });
|
|
3686
|
+
return (await readdir(pathToDbs)).map((id) => id.replace(pathfs.extname(id), "").replace(".encrypted", ""));
|
|
3687
|
+
}
|
|
3688
|
+
async reencrypt(oldKey, newKey) {
|
|
3689
|
+
const api = new fdir().withFullPaths().filter((path) => path.endsWith("encrypted.json")).crawl(this.getRootPath());
|
|
3690
|
+
await PromiseB2.map(api.withPromise(), async (file) => {
|
|
3691
|
+
const fileEncrypted = await readFile(file, "utf-8");
|
|
3692
|
+
const additionnalNonce = file.split(".runeya").pop();
|
|
3693
|
+
const fileDecrypted = await decrypt(fileEncrypted, { additionnalNonce, encryptionKey: oldKey });
|
|
3694
|
+
const fileReEncrypted = await encrypt(fileDecrypted, { additionnalNonce, encryptionKey: newKey });
|
|
3695
|
+
await writeFile(file, fileReEncrypted, "utf-8");
|
|
3696
|
+
});
|
|
3697
|
+
}
|
|
3698
|
+
getDb(id, { encrypted, defaultData } = { encrypted: true, defaultData: {} }) {
|
|
3699
|
+
const getPath = async () => {
|
|
3700
|
+
const persistencePath = pathfs.resolve(`${this.getRootPath()}/${id}${encrypted ? ".encrypted" : ""}.json`);
|
|
3701
|
+
if (!existsSync(pathfs.dirname(persistencePath))) await mkdirSync(pathfs.dirname(persistencePath), { recursive: true });
|
|
3702
|
+
if (!existsSync(persistencePath)) {
|
|
3703
|
+
let defaultDB = JSON.stringify(defaultData || [], null, 2);
|
|
3704
|
+
if (encrypted) defaultDB = await encrypt(defaultDB, { additionnalNonce: persistencePath.split(".runeya").pop() });
|
|
3705
|
+
await writeFile(persistencePath, defaultDB, "utf-8");
|
|
3706
|
+
this.cache[id] = defaultDB;
|
|
3707
|
+
}
|
|
3708
|
+
return persistencePath;
|
|
3709
|
+
};
|
|
3710
|
+
const table = id.replace(/[^a-z0-9]|\s+|\r?\n|\r/gmi, "_");
|
|
3711
|
+
const read = async () => {
|
|
3712
|
+
if (this.cache[id]) return this.cache[id];
|
|
3713
|
+
const path = await getPath();
|
|
3714
|
+
const additionnalNonce = path.split(".runeya").pop();
|
|
3715
|
+
let db = readFileSync(path, "utf-8");
|
|
3716
|
+
if (encrypted) {
|
|
3717
|
+
try {
|
|
3718
|
+
if (typeof db === "string" && (db.includes("<<<<<<< HEAD") || db.includes("=======") || db.includes(">>>>>>>"))) {
|
|
3719
|
+
db = await decryptFile(db, { additionnalNonce }, path);
|
|
3720
|
+
} else {
|
|
3721
|
+
db = await decrypt(db, { additionnalNonce }).catch((err) => {
|
|
3722
|
+
console.error(path, err);
|
|
3723
|
+
sockets2.emit("system:wrongKey");
|
|
3724
|
+
throw err;
|
|
3725
|
+
});
|
|
3726
|
+
}
|
|
3727
|
+
} catch (err) {
|
|
3728
|
+
console.error(path, err);
|
|
3729
|
+
sockets2.emit("system:wrongKey");
|
|
3730
|
+
throw err;
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
this.cache[id] = JSON.parse(db);
|
|
3734
|
+
if (!alasql.tables[table]) {
|
|
3735
|
+
await alasql(`CREATE TABLE ${table}`);
|
|
3736
|
+
}
|
|
3737
|
+
alasql.tables[table].data = this.cache[id];
|
|
3738
|
+
return this.cache[id];
|
|
3739
|
+
};
|
|
3740
|
+
const write = async (data) => {
|
|
3741
|
+
let db = JSON.stringify(data, null, 2);
|
|
3742
|
+
const path = await getPath();
|
|
3743
|
+
const additionnalNonce = path.split(".runeya").pop();
|
|
3744
|
+
if (encrypted) db = await encrypt(db, { additionnalNonce });
|
|
3745
|
+
writeFileSync(path, db, "utf-8");
|
|
3746
|
+
this.cache[id] = data;
|
|
3747
|
+
if (alasql.tables[table]) {
|
|
3748
|
+
alasql.tables[table].data = data;
|
|
3749
|
+
}
|
|
3750
|
+
};
|
|
3751
|
+
const escapeQuote = (data) => {
|
|
3752
|
+
if (typeof data === "string") {
|
|
3753
|
+
return data.replace(/'/g, "''");
|
|
3754
|
+
}
|
|
3755
|
+
return data;
|
|
3756
|
+
};
|
|
3757
|
+
const setValue = (item) => {
|
|
3758
|
+
if (item == null) {
|
|
3759
|
+
return "NULL";
|
|
3760
|
+
}
|
|
3761
|
+
if (item instanceof Date && item.toISOString) {
|
|
3762
|
+
return `'${item.toISOString()}'`;
|
|
3763
|
+
}
|
|
3764
|
+
if (typeof item === "string") {
|
|
3765
|
+
return `'${escapeQuote(item)}'`;
|
|
3766
|
+
}
|
|
3767
|
+
return `${item}`;
|
|
3768
|
+
};
|
|
3769
|
+
return {
|
|
3770
|
+
getPath,
|
|
3771
|
+
alasql: {
|
|
3772
|
+
table,
|
|
3773
|
+
buildUpdateQuery(data) {
|
|
3774
|
+
const set = [];
|
|
3775
|
+
Object.keys(data).forEach((key) => {
|
|
3776
|
+
set.push(`${key} = ${setValue(data[key])}`);
|
|
3777
|
+
});
|
|
3778
|
+
return set.join(", ");
|
|
3779
|
+
},
|
|
3780
|
+
read: async (sql) => {
|
|
3781
|
+
await read();
|
|
3782
|
+
return alasql.promise(sql);
|
|
3783
|
+
},
|
|
3784
|
+
/**
|
|
3785
|
+
*
|
|
3786
|
+
* @param {{where?: string, orderBy?: string, limit?: number, offset?: number}} param0
|
|
3787
|
+
* @returns {Promise<any[]>}
|
|
3788
|
+
*/
|
|
3789
|
+
simpleSelect: async ({ where, orderBy, limit, offset }) => {
|
|
3790
|
+
await read();
|
|
3791
|
+
return alasql.promise(`SELECT * FROM ${table} ${where ? `WHERE ${where}` : ""} ${orderBy ? `ORDER BY ${orderBy}` : ""} ${limit ? `LIMIT ${limit}` : ""} ${offset ? `OFFSET ${offset}` : ""}`);
|
|
3792
|
+
},
|
|
3793
|
+
/** @param {string} where */
|
|
3794
|
+
delete: async (where) => {
|
|
3795
|
+
await read();
|
|
3796
|
+
await alasql.promise(`DELETE FROM ${table} WHERE ${where}`);
|
|
3797
|
+
await write(await alasql(`select * from ${table}`));
|
|
3798
|
+
},
|
|
3799
|
+
insertOne: async (data) => {
|
|
3800
|
+
await read();
|
|
3801
|
+
await alasql.promise(`INSERT INTO ${table} VALUES ${JSON.stringify(data)}`);
|
|
3802
|
+
await write(await alasql(`select * from ${table}`));
|
|
3803
|
+
},
|
|
3804
|
+
write: async (sql, value) => {
|
|
3805
|
+
await read();
|
|
3806
|
+
await alasql.promise(sql, value);
|
|
3807
|
+
await write(await alasql(`select * from ${table}`));
|
|
3808
|
+
}
|
|
3809
|
+
},
|
|
3810
|
+
write,
|
|
3811
|
+
read,
|
|
3812
|
+
delete: async () => {
|
|
3813
|
+
delete this.cache[id];
|
|
3814
|
+
return unlink(await getPath());
|
|
3815
|
+
}
|
|
3816
|
+
};
|
|
3817
|
+
}
|
|
3818
|
+
}();
|
|
3819
|
+
}
|
|
3820
|
+
});
|
|
3821
|
+
|
|
3822
|
+
// helpers/createDefaultFiles.js
|
|
3823
|
+
var require_createDefaultFiles = __commonJS({
|
|
3824
|
+
"helpers/createDefaultFiles.js"(exports2, module2) {
|
|
3825
|
+
"use strict";
|
|
3826
|
+
var pathfs = require("path");
|
|
3827
|
+
var { existsSync } = require("fs");
|
|
3828
|
+
var { writeFile, readFile, appendFile } = require("fs/promises");
|
|
3829
|
+
var args2 = require_args();
|
|
3830
|
+
var dbs2 = require_dbs();
|
|
3831
|
+
module2.exports = async function createDefaultFiles2() {
|
|
3832
|
+
await createGitignore();
|
|
3833
|
+
await createPluginsGitignore();
|
|
3834
|
+
};
|
|
3835
|
+
async function createPluginsGitignore() {
|
|
3836
|
+
const gitignorePath = pathfs.resolve(args2.runeyaConfigPath, ".gitignore");
|
|
3837
|
+
if (!existsSync(gitignorePath)) await writeFile(gitignorePath, "");
|
|
3838
|
+
const gitignoreFile = (await readFile(gitignorePath, "utf-8")).split("\n");
|
|
3839
|
+
const gitignoreHasKey = (key) => gitignoreFile.some((line) => line.trim() === key);
|
|
3840
|
+
if (!gitignoreHasKey("plugins.json")) await appendFile(gitignorePath, "\nplugins.json");
|
|
3841
|
+
if (!gitignoreHasKey("plugins")) await appendFile(gitignorePath, "\nplugins");
|
|
3842
|
+
}
|
|
3843
|
+
async function createGitignore() {
|
|
3844
|
+
const dirname = pathfs.dirname(await dbs2.getDb("encryption-key", { encrypted: false, defaultData: {} }).getPath());
|
|
3845
|
+
const gitignorePath = pathfs.resolve(dirname, ".gitignore");
|
|
3846
|
+
if (!existsSync(gitignorePath)) {
|
|
3847
|
+
await writeFile(gitignorePath, "encryption-key.json");
|
|
3848
|
+
}
|
|
3849
|
+
const gitignoreFile = (await readFile(gitignorePath, "utf-8")).split("\n");
|
|
3850
|
+
const gitignoreHasKey = (key) => gitignoreFile.some((line) => line.trim() === key);
|
|
3851
|
+
if (!gitignoreHasKey("encryption-key.json")) await appendFile(gitignorePath, "\nencryption-key.json");
|
|
3852
|
+
if (!gitignoreHasKey("overrides")) await appendFile(gitignorePath, "\noverrides");
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
});
|
|
3856
|
+
|
|
3809
3857
|
// helpers/console.table.js
|
|
3810
3858
|
var require_console_table = __commonJS({
|
|
3811
3859
|
"helpers/console.table.js"(exports2, module2) {
|
|
@@ -3845,7 +3893,7 @@ var require_plugins2 = __commonJS({
|
|
|
3845
3893
|
var { tmpdir } = require("os");
|
|
3846
3894
|
var path = require("path");
|
|
3847
3895
|
var { existsSync } = require("fs");
|
|
3848
|
-
var { writeFile, mkdir, readFile, cp, rm, readdir } = require("fs/promises");
|
|
3896
|
+
var { writeFile, mkdir, readFile, cp, rm, readdir, appendFile } = require("fs/promises");
|
|
3849
3897
|
var { spawn } = require("child_process");
|
|
3850
3898
|
var dbs2 = require_dbs();
|
|
3851
3899
|
var HTTPError = require_src2();
|
|
@@ -5028,10 +5076,14 @@ var require_server = __commonJS({
|
|
|
5028
5076
|
|
|
5029
5077
|
// bin/www
|
|
5030
5078
|
var { sockets } = require_src();
|
|
5079
|
+
var migrateStackMonitor = require_migrateStackMonitor();
|
|
5080
|
+
var createDefaultFiles = require_createDefaultFiles();
|
|
5031
5081
|
process.title = "runeya";
|
|
5032
5082
|
var args = require_args();
|
|
5033
5083
|
require("dotenv").config();
|
|
5034
5084
|
(async () => {
|
|
5085
|
+
await migrateStackMonitor();
|
|
5086
|
+
await createDefaultFiles();
|
|
5035
5087
|
if (args["pull-env"]) {
|
|
5036
5088
|
await require_stack().selectConf();
|
|
5037
5089
|
const service = require_stack().findService(args.s);
|