@runeya/runeya 1.0.7 → 1.0.14

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.
Files changed (89) hide show
  1. package/LICENSE.md +29 -0
  2. package/README.md +75 -0
  3. package/node-red-contrib-runeya.tar +0 -0
  4. package/package.json +1 -11
  5. package/public/assets/App-Bzzr3d8D.js +101 -0
  6. package/public/assets/App-ClT0daRA.css +1 -0
  7. package/public/assets/CurrentEditor-BgkRP7cS.js +1 -0
  8. package/public/assets/Editor-BC23IeB6.css +1 -0
  9. package/public/assets/Editor-BqvrNzb6.js +37826 -0
  10. package/public/assets/ImportCreate-B-lRmpLH.js +1 -0
  11. package/public/assets/Init-D3C4n99F.js +1 -0
  12. package/public/assets/LeftLogo-E7dYCAWT.js +1 -0
  13. package/public/assets/Markdown-CqAPHaPe.css +1 -0
  14. package/public/assets/Markdown-dzyZ7CTg.js +109 -0
  15. package/public/assets/Overview-YtPSCN3k.js +1 -0
  16. package/public/assets/{Section-eAe-gcF2.css → Section-Dz0BsVYl.css} +1 -1
  17. package/public/assets/{Section-8ldEsJSi.js → Section-YBL4Pzic.js} +1 -1
  18. package/public/assets/{Settings-Bsf3R9hf.css → Settings-BBbk67zT.css} +1 -1
  19. package/public/assets/Settings-DJaMzLUX.js +495 -0
  20. package/public/assets/StackChooser-BnNrvv4Y.js +1 -0
  21. package/public/assets/StackChooser-DAAV0Rat.js +1 -0
  22. package/public/assets/StackMultiple-D0ozn0Tf.js +30 -0
  23. package/public/assets/StackSingle-CHHH2rXO.js +1 -0
  24. package/public/assets/StackSingle-DBZX9nN_.css +1 -0
  25. package/public/assets/Tabs-D9ZNelJj.js +1 -0
  26. package/public/assets/Tabs-fu2myJd9.css +1 -0
  27. package/public/assets/{cssMode-CUrSSrg6.js → cssMode-BEnNoAFz.js} +1 -1
  28. package/public/assets/{freemarker2-dec3WQLB.js → freemarker2-z8zA5ezm.js} +1 -1
  29. package/public/assets/{handlebars-Da_reGXs.js → handlebars-DTrkysaX.js} +1 -1
  30. package/public/assets/{html-DiMqDoaf.js → html-BiGIRkmo.js} +1 -1
  31. package/public/assets/{htmlMode-wRbKtV-5.js → htmlMode-CGj06Oa8.js} +1 -1
  32. package/public/assets/index-CqmUSPWF.css +5 -0
  33. package/public/assets/index-G1ob8hK0.js +264 -0
  34. package/public/assets/{javascript-ByCKYcx1.js → javascript-DEAY-G4N.js} +1 -1
  35. package/public/assets/{jsonMode-BQtLraFt.js → jsonMode-CLJTah_r.js} +1 -1
  36. package/public/assets/{liquid-Ig1gPJ1q.js → liquid-Bt_q9jyv.js} +1 -1
  37. package/public/assets/{mdx-CYaZVbeY.js → mdx-BtbMy52t.js} +1 -1
  38. package/public/assets/{python-H9Bd9rT3.js → python-DIVYbK-C.js} +1 -1
  39. package/public/assets/{razor-Hy2I2roR.js → razor-ztrk2wBu.js} +1 -1
  40. package/public/assets/router-B2S_D5pC.js +4232 -0
  41. package/public/assets/router-imsD-DjM.css +32 -0
  42. package/public/assets/system-DYhoWbZ1.js +1 -0
  43. package/public/assets/{tsMode-C0bgKAt8.js → tsMode-Fc-Kxr3a.js} +1 -1
  44. package/public/assets/{typescript-B77iTojx.js → typescript-CHa_3xkF.js} +1 -1
  45. package/public/assets/{xml-uQhiANeS.js → xml-B2WXRoPu.js} +1 -1
  46. package/public/assets/{yaml-2OwCXstu.js → yaml-6vYkUkh3.js} +1 -1
  47. package/public/index.html +1 -1
  48. package/runeya.vsix +0 -0
  49. package/www.js +596 -2517
  50. package/www.js.map +1 -1
  51. package/public/assets/App-BE-jCGXm.css +0 -5
  52. package/public/assets/App-Bu4vGxO4.js +0 -94
  53. package/public/assets/CurrentEditor-yQstAvnQ.js +0 -1
  54. package/public/assets/Editor-BK8NbiL6.css +0 -1
  55. package/public/assets/Editor-DjNB5m3y.js +0 -721
  56. package/public/assets/ImportCreate-BkVY0Snd.js +0 -1
  57. package/public/assets/Init-PS5FZlf7.js +0 -1
  58. package/public/assets/LeftLogo-EmzH7l46.js +0 -1
  59. package/public/assets/Markdown-CpEumaO9.js +0 -103
  60. package/public/assets/Markdown-pSjwyqay.css +0 -1
  61. package/public/assets/Overview-BhYJL4nA.js +0 -1
  62. package/public/assets/Settings-bKLH4HnT.js +0 -188
  63. package/public/assets/StackChooser-CmoqSd4m.js +0 -1
  64. package/public/assets/StackChooser-D5EY2Av8.js +0 -1
  65. package/public/assets/StackMultiple-o8pd1Nmf.js +0 -1
  66. package/public/assets/StackSingle-BzrRRE-y.js +0 -1
  67. package/public/assets/StackSingle-DWbIQbAl.css +0 -1
  68. package/public/assets/Tabs-CZAdcV0_.css +0 -1
  69. package/public/assets/Tabs-Cpjfv5wC.js +0 -1
  70. package/public/assets/axios-BZk75tkI.js +0 -6
  71. package/public/assets/css.worker-7uusSYJx.js +0 -84
  72. package/public/assets/editor.worker-C6wdibMX.js +0 -11
  73. package/public/assets/fa-brands-400-C99Yv4gD.woff2 +0 -0
  74. package/public/assets/fa-brands-400-DtZKBM2a.ttf +0 -0
  75. package/public/assets/fa-regular-400-BMFokQJ2.ttf +0 -0
  76. package/public/assets/fa-regular-400-OOsPf1xj.woff2 +0 -0
  77. package/public/assets/fa-solid-900-DAI24fNt.woff2 +0 -0
  78. package/public/assets/fa-solid-900-DM0teJdg.ttf +0 -0
  79. package/public/assets/fa-v4compatibility-F0dlVTLQ.ttf +0 -0
  80. package/public/assets/fa-v4compatibility-aR9vOKaP.woff2 +0 -0
  81. package/public/assets/html.worker-BGQnBRGr.js +0 -458
  82. package/public/assets/index-DUMOL4cy.css +0 -1
  83. package/public/assets/index-aZm7xMRp.js +0 -233
  84. package/public/assets/json.worker-Be5ebZoT.js +0 -42
  85. package/public/assets/router-DdnNyrCa.css +0 -32
  86. package/public/assets/router-ZJYrvDkp.js +0 -4962
  87. package/public/assets/system-DC3M5FtK.js +0 -1
  88. package/public/assets/ts.worker-Dap_1Gm7.js +0 -37021
  89. package/public/assets/vue.runtime.esm-bundler-VmRDinbK.js +0 -9
package/www.js CHANGED
@@ -21,11 +21,16 @@ var require_args = __commonJS({
21
21
  var path = require("path");
22
22
  var yargs = require("yargs/yargs");
23
23
  var { hideBin } = require("yargs/helpers");
24
+ var { existsSync } = require("fs");
24
25
  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();
25
26
  var args2 = Object.assign({
26
27
  rootPath: path.resolve(yarg["_"]?.[0] || "."),
27
28
  initialCwd: ""
28
29
  }, yarg);
30
+ if (!existsSync(args2.rootPath)) {
31
+ console.error("Error: Runeya was launched with an invalid root path that does not exist. Please check your launch command. \nPath: ", args2.rootPath);
32
+ process.exit(1);
33
+ }
29
34
  if (args2.rootPath) {
30
35
  args2.initialCwd = process.cwd();
31
36
  process.chdir(args2.rootPath);
@@ -175,111 +180,8 @@ var require_backend = __commonJS({
175
180
  }
176
181
  });
177
182
 
178
- // ../../modules/base64/backend/Base64.js
179
- var require_Base64 = __commonJS({
180
- "../../modules/base64/backend/Base64.js"(exports2, module2) {
181
- "use strict";
182
- var Base64 = (runeya) => ({
183
- /**
184
- * Encode une chaîne en Base64
185
- * @param {string} value - La chaîne à encoder
186
- * @returns {string} - La chaîne encodée
187
- */
188
- encode: (value = "") => {
189
- try {
190
- const buffer = Buffer.from(value, "utf-8");
191
- return buffer.toString("base64");
192
- } catch (error) {
193
- console.error("Error encoding to base64:", error);
194
- return "";
195
- }
196
- },
197
- /**
198
- * Décode une chaîne Base64
199
- * @param {string} value - La chaîne Base64 à décoder
200
- * @returns {string} - La chaîne décodée
201
- */
202
- decode: (value = "") => {
203
- try {
204
- const buffer = Buffer.from(value, "base64");
205
- return buffer.toString("utf-8");
206
- } catch (error) {
207
- console.error("Error decoding from base64:", error);
208
- return "";
209
- }
210
- }
211
- });
212
- module2.exports = Base64;
213
- }
214
- });
215
-
216
- // ../../modules/base64/backend/routes.js
217
- var require_routes2 = __commonJS({
218
- "../../modules/base64/backend/routes.js"(exports2, module2) {
219
- "use strict";
220
- var express = require("express");
221
- var router = express.Router();
222
- var Base64 = require_Base64();
223
- module2.exports = (runeya) => {
224
- const base64 = Base64(runeya);
225
- router.post("/base64/encode", (req, res) => {
226
- try {
227
- const { value } = req.body;
228
- const result = base64.encode(value);
229
- res.json({ result });
230
- } catch (error) {
231
- res.status(500).json({
232
- error: true,
233
- message: error instanceof Error ? error.message : "Unknown error"
234
- });
235
- }
236
- });
237
- router.post("/base64/decode", (req, res) => {
238
- try {
239
- const { value } = req.body;
240
- const result = base64.decode(value);
241
- res.json({ result });
242
- } catch (error) {
243
- res.status(500).json({
244
- error: true,
245
- message: error instanceof Error ? error.message : "Unknown error"
246
- });
247
- }
248
- });
249
- return router;
250
- };
251
- }
252
- });
253
-
254
- // ../../modules/base64/backend/index.js
255
- var require_backend2 = __commonJS({
256
- "../../modules/base64/backend/index.js"(exports2, module2) {
257
- "use strict";
258
- var plugin = {
259
- enabled: true,
260
- name: "Base64",
261
- displayName: "Base64",
262
- description: "Encode and decode Base64 strings",
263
- icon: "fas fa-exchange-alt",
264
- placements: [
265
- {
266
- position: "toolbox",
267
- label: "Base64",
268
- icon: "fas fa-exchange-alt",
269
- goTo: { path: "/Base64" },
270
- active: "Base64"
271
- }
272
- ],
273
- export: require_Base64(),
274
- order: 8,
275
- routes: require_routes2()
276
- };
277
- module2.exports = plugin;
278
- }
279
- });
280
-
281
183
  // ../../modules/configuration/backend/index.js
282
- var require_backend3 = __commonJS({
184
+ var require_backend2 = __commonJS({
283
185
  "../../modules/configuration/backend/index.js"(exports2, module2) {
284
186
  "use strict";
285
187
  var plugin = {
@@ -296,73 +198,6 @@ var require_backend3 = __commonJS({
296
198
  }
297
199
  });
298
200
 
299
- // ../../modules/dev-ops/backend/index.js
300
- var require_backend4 = __commonJS({
301
- "../../modules/dev-ops/backend/index.js"(exports2, module2) {
302
- "use strict";
303
- var plugin = {
304
- enabled: false,
305
- name: "DevOps",
306
- displayName: "Dev ops",
307
- description: "Choose a tool used for dev ops purposes",
308
- icon: "fas fa-hard-hat",
309
- order: 7,
310
- export: null,
311
- placements: [{
312
- position: "sidebar",
313
- label: "DevOps",
314
- icon: "fas fa-hard-hat",
315
- goTo: { path: "/DevOps" },
316
- active: "DevOps"
317
- }]
318
- };
319
- module2.exports = plugin;
320
- }
321
- });
322
-
323
- // ../../modules/diff/backend/routes.js
324
- var require_routes3 = __commonJS({
325
- "../../modules/diff/backend/routes.js"(exports2, module2) {
326
- "use strict";
327
- var express = require("express");
328
- var router = express.Router();
329
- var { v4 } = require("uuid");
330
- module2.exports = () => {
331
- router.get("/diff", async (req, res) => {
332
- res.json(v4());
333
- });
334
- return router;
335
- };
336
- }
337
- });
338
-
339
- // ../../modules/diff/backend/index.js
340
- var require_backend5 = __commonJS({
341
- "../../modules/diff/backend/index.js"(exports2, module2) {
342
- "use strict";
343
- var plugin = {
344
- enabled: true,
345
- name: "Diff",
346
- displayName: "Differences",
347
- description: "Find differences between two strings",
348
- icon: "fas fa-columns",
349
- export: null,
350
- placements: [
351
- {
352
- position: "toolbox",
353
- label: "Diff",
354
- icon: "fas fa-columns",
355
- goTo: { path: "/Diff" },
356
- active: "Diff"
357
- }
358
- ],
359
- order: 6,
360
- routes: require_routes3()
361
- };
362
- module2.exports = plugin;
363
- }
364
- });
365
-
366
201
  // helpers/conflictStorage.js
367
202
  var require_conflictStorage = __commonJS({
368
203
  "helpers/conflictStorage.js"(exports2, module2) {
@@ -456,7 +291,6 @@ var require_EncryptionKey = __commonJS({
456
291
  }
457
292
  }
458
293
  async update() {
459
- console.log(JSON.stringify(["runeya", "update"], (_, v) => typeof v === "function" ? `[func]` : v));
460
294
  return __privateMethod(this, _EncryptionKey_instances, getDb_fn).call(this).write(this.toStorage());
461
295
  }
462
296
  toStorage() {
@@ -769,6 +603,26 @@ var require_dbs = __commonJS({
769
603
  await read();
770
604
  return alasql.promise(sql);
771
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
+ },
772
626
  write: async (sql, value) => {
773
627
  await read();
774
628
  await alasql.promise(sql, value);
@@ -894,7 +748,7 @@ var require_Leaf = __commonJS({
894
748
  });
895
749
 
896
750
  // ../../modules/documentation/backend/routes.js
897
- var require_routes4 = __commonJS({
751
+ var require_routes2 = __commonJS({
898
752
  "../../modules/documentation/backend/routes.js"(exports2, module2) {
899
753
  "use strict";
900
754
  var express = require("express");
@@ -944,7 +798,7 @@ var require_routes4 = __commonJS({
944
798
  });
945
799
 
946
800
  // ../../modules/documentation/backend/index.js
947
- var require_backend6 = __commonJS({
801
+ var require_backend3 = __commonJS({
948
802
  "../../modules/documentation/backend/index.js"(exports2, module2) {
949
803
  "use strict";
950
804
  var { readFile } = require("fs/promises");
@@ -960,7 +814,7 @@ var require_backend6 = __commonJS({
960
814
  // export: Documentation,
961
815
  placements: ["service"],
962
816
  order: 6,
963
- routes: require_routes4(),
817
+ routes: require_routes2(),
964
818
  finder: async (search, runeya) => {
965
819
  }
966
820
  };
@@ -969,7 +823,7 @@ var require_backend6 = __commonJS({
969
823
  });
970
824
 
971
825
  // ../../modules/finder/backend/routes.js
972
- var require_routes5 = __commonJS({
826
+ var require_routes3 = __commonJS({
973
827
  "../../modules/finder/backend/routes.js"(exports2, module2) {
974
828
  "use strict";
975
829
  var express = require("express");
@@ -1026,7 +880,7 @@ var require_routes5 = __commonJS({
1026
880
  });
1027
881
 
1028
882
  // ../../modules/finder/backend/index.js
1029
- var require_backend7 = __commonJS({
883
+ var require_backend4 = __commonJS({
1030
884
  "../../modules/finder/backend/index.js"(exports2, module2) {
1031
885
  "use strict";
1032
886
  var commandExists = require("command-exists");
@@ -1046,7 +900,7 @@ var require_backend7 = __commonJS({
1046
900
  active: "Finder"
1047
901
  }],
1048
902
  hidden: () => commandExists("git").then(() => false).catch(() => true),
1049
- routes: require_routes5()
903
+ routes: require_routes3()
1050
904
  };
1051
905
  module2.exports = plugin;
1052
906
  }
@@ -1115,7 +969,7 @@ var require_HTTPError = __commonJS({
1115
969
  /**
1116
970
  *
1117
971
  * @param {string} message
1118
- * @param {number} code
972
+ * @param {number | string} code
1119
973
  * @param {string} errorId
1120
974
  * @param {string} date
1121
975
  * @param {string} stack
@@ -1362,7 +1216,7 @@ var require_Git = __commonJS({
1362
1216
  });
1363
1217
 
1364
1218
  // ../../modules/git/backend/routes.js
1365
- var require_routes6 = __commonJS({
1219
+ var require_routes4 = __commonJS({
1366
1220
  "../../modules/git/backend/routes.js"(exports2, module2) {
1367
1221
  "use strict";
1368
1222
  var express = require("express");
@@ -1429,7 +1283,7 @@ var require_routes6 = __commonJS({
1429
1283
  });
1430
1284
 
1431
1285
  // ../../modules/git/backend/index.js
1432
- var require_backend8 = __commonJS({
1286
+ var require_backend5 = __commonJS({
1433
1287
  "../../modules/git/backend/index.js"(exports2, module2) {
1434
1288
  "use strict";
1435
1289
  var commandExists = require("command-exists");
@@ -1453,14 +1307,14 @@ var require_backend8 = __commonJS({
1453
1307
  if (placement === "service" && service?.git?.remote) return false;
1454
1308
  return true;
1455
1309
  },
1456
- routes: require_routes6()
1310
+ routes: require_routes4()
1457
1311
  };
1458
1312
  module2.exports = plugin;
1459
1313
  }
1460
1314
  });
1461
1315
 
1462
1316
  // ../../modules/github/backend/routes.js
1463
- var require_routes7 = __commonJS({
1317
+ var require_routes5 = __commonJS({
1464
1318
  "../../modules/github/backend/routes.js"(exports2, module2) {
1465
1319
  "use strict";
1466
1320
  var express = require("express");
@@ -1513,7 +1367,7 @@ var require_routes7 = __commonJS({
1513
1367
  });
1514
1368
 
1515
1369
  // ../../modules/github/backend/index.js
1516
- var require_backend9 = __commonJS({
1370
+ var require_backend6 = __commonJS({
1517
1371
  "../../modules/github/backend/index.js"(exports2, module2) {
1518
1372
  "use strict";
1519
1373
  var plugin = {
@@ -1530,1759 +1384,132 @@ var require_backend9 = __commonJS({
1530
1384
  if (!service) return true;
1531
1385
  return !service.git?.remote?.includes("github.com");
1532
1386
  },
1533
- routes: require_routes7()
1387
+ routes: require_routes5()
1534
1388
  };
1535
1389
  module2.exports = plugin;
1536
1390
  }
1537
1391
  });
1538
1392
 
1539
- // ../../modules/global-scripts/backend/GlobalScripts.js
1540
- var require_GlobalScripts = __commonJS({
1541
- "../../modules/global-scripts/backend/GlobalScripts.js"(exports2, module2) {
1393
+ // ../../modules/logs/backend/routes.js
1394
+ var require_routes6 = __commonJS({
1395
+ "../../modules/logs/backend/routes.js"(exports2, module2) {
1542
1396
  "use strict";
1397
+ var express = require("express");
1543
1398
  var { v4 } = require("uuid");
1544
- var globalScripts = [];
1545
- var currentScriptsByCommunicationId = {};
1546
- var GlobalScripts = (runeya) => {
1547
- const { Socket } = runeya;
1548
- return {
1549
- /** @param {GlobalScript} script */
1550
- addScript(script) {
1551
- const index = globalScripts.findIndex((s) => s.label === script.label);
1552
- if (index >= 0) {
1553
- globalScripts.splice(index, 1);
1554
- }
1555
- globalScripts.push(script);
1556
- runeya.Socket.emit("reloadScripts");
1557
- },
1558
- getScripts() {
1559
- return globalScripts;
1560
- },
1561
- /** @param {string} label */
1562
- getScript(label) {
1563
- const scripts = this.getScripts();
1564
- const script = scripts.find((s) => s.label === label);
1565
- return script;
1566
- },
1567
- /**
1568
- * @param {string} scriptId
1569
- * @param {string} stepLabel
1570
- */
1571
- getStep(scriptId, stepLabel) {
1572
- const script = this.getScript(scriptId);
1573
- if (!script) return null;
1574
- const step = script.pipeline.find((st) => st.id === stepLabel);
1575
- if (!step) return null;
1576
- return step;
1577
- },
1578
- /** @param {string} id */
1579
- launchScript(id) {
1580
- const script = this.getScript(id);
1581
- if (!script) throw new Error(`Script ${id} not found`);
1582
- const communicationId = v4();
1583
- const track = {
1584
- scriptId: script.label,
1585
- currentStep: script.pipeline[0].id,
1586
- loadingStep: script.pipeline[0].id,
1587
- steps: {},
1588
- output: {},
1589
- prompts: {}
1399
+ var router = express.Router();
1400
+ module2.exports = (runeya) => {
1401
+ const history = runeya.getSave("history.json", {
1402
+ /** @type {History[]} */
1403
+ history: []
1404
+ });
1405
+ const { findService, Socket } = runeya;
1406
+ router.get("/logs/:service/logs", (req, res) => {
1407
+ const service = findService(req.params.service);
1408
+ res.send(service ? service.store : []);
1409
+ });
1410
+ router.get("/logs/:service/autocomplete", (req, res) => {
1411
+ const msg = req.query.message;
1412
+ if (!msg && !req.query.force) return res.json([]);
1413
+ const historyToSend = groupBy(history.data.history, "raw").sort((a, b) => a.timestamp - b.timestamp).filter((a) => a?.raw?.startsWith(msg) || a.cmd?.startsWith(msg)).slice(-10);
1414
+ return res.json(historyToSend);
1415
+ });
1416
+ router.post("/logs/:service/prompt", async (req, res) => {
1417
+ const service = findService(req.params.service);
1418
+ let command = req.body.command || {};
1419
+ const pid = req.body.pid ? +req.body.pid : void 0;
1420
+ if (!command.spawnCmd) command.spawnCmd = "\n";
1421
+ let result = {
1422
+ id: v4(),
1423
+ pid,
1424
+ cmd: command.spawnCmd,
1425
+ args: [],
1426
+ raw: command.spawnCmd,
1427
+ timestamp: Date.now(),
1428
+ service: service.label || ""
1429
+ };
1430
+ if (pid) service.respondToProcess(pid, command.spawnCmd);
1431
+ else if (command) {
1432
+ const { spawnProcess, launchMessage } = await service.launchProcess(
1433
+ { spawnCmd: command.spawnCmd, spawnArgs: command.spawnArgs || [], spawnOptions: command.spawnOptions || {} },
1434
+ false
1435
+ );
1436
+ result = {
1437
+ ...result,
1438
+ pid: spawnProcess?.pid,
1439
+ raw: launchMessage.raw,
1440
+ timestamp: launchMessage.timestamp
1590
1441
  };
1591
- currentScriptsByCommunicationId[communicationId] = track;
1592
- function getStepIndex(step) {
1593
- return (script?.pipeline || []).indexOf(step);
1594
- }
1595
- Socket.on(communicationId, async (socket, event, data) => {
1596
- let step = null;
1597
- while (step = this.getStep(script.label, track.currentStep)) {
1598
- const index = getStepIndex(step);
1599
- const nextStep = index >= 0 ? script.pipeline[index + 1]?.id : "";
1600
- track.loadingStep = step.id;
1601
- track.steps[track.currentStep] = {
1602
- ...track.steps[track.currentStep],
1603
- isValidated: false,
1604
- error: void 0,
1605
- printData: void 0
1606
- };
1607
- socket.emit(communicationId, "track", track);
1608
- try {
1609
- if (step.skip) {
1610
- const shouldSkip = await step.skip(track.output, track.prompts);
1611
- if (shouldSkip) {
1612
- track.steps[track.currentStep].skipped = true;
1613
- track.loadingStep = "";
1614
- track.currentStep = nextStep;
1615
- socket.emit(communicationId, "track", track);
1616
- continue;
1617
- }
1618
- }
1619
- } catch (error) {
1620
- console.error("Script error");
1621
- console.error(error);
1622
- track.steps[track.currentStep].error = error.message || error;
1623
- break;
1624
- }
1625
- const shouldBreak = await prompt(step, track, event, data);
1626
- if (shouldBreak) break;
1627
- if (event === "validate-prompt") event = "";
1628
- if (step.script) {
1629
- try {
1630
- track.output[track.currentStep] = await step.script(track.output, track.prompts);
1631
- } catch (error) {
1632
- console.error("Script error");
1633
- console.error(error);
1634
- track.steps[track.currentStep].error = error.message || error;
1635
- break;
1636
- }
1637
- }
1638
- if (step.print) {
1639
- try {
1640
- track.steps[track.currentStep].printData = await step.print(track.output, track.prompts);
1641
- await new Promise((resolve) => setTimeout(() => {
1642
- resolve(null);
1643
- }, 0));
1644
- } catch (error) {
1645
- console.error("Print error");
1646
- console.error(error);
1647
- track.steps[track.currentStep].error = error.message || error;
1648
- break;
1649
- }
1650
- }
1651
- track.steps[track.currentStep].isValidated = true;
1652
- track.currentStep = nextStep;
1653
- }
1654
- track.loadingStep = "";
1655
- socket.emit(communicationId, "track", track);
1656
- });
1657
- return communicationId;
1658
- }
1659
- };
1660
- };
1661
- module2.exports = GlobalScripts;
1662
- async function prompt(step, track, event, data) {
1663
- if (!step.prompt) return false;
1664
- if (event === "validate-prompt") {
1665
- if (step.prompt?.validation) {
1666
- try {
1667
- const msgError = await step.prompt.validation(data);
1668
- if (msgError) {
1669
- track.steps[track.currentStep].error = msgError;
1670
- return true;
1671
- }
1672
- track.prompts[track.currentStep] = data;
1673
- } catch (error) {
1674
- console.error("Script error");
1675
- console.error(error);
1676
- track.steps[track.currentStep].error = error.message || error;
1677
- return true;
1678
- }
1679
- } else {
1680
- track.prompts[track.currentStep] = data;
1681
- }
1682
- return false;
1683
- }
1684
- if (step.prompt.defaultValue) {
1685
- try {
1686
- const defaultValue = await step.prompt.defaultValue(track.output);
1687
- track.steps[track.currentStep].promptValue = defaultValue;
1688
- } catch (error) {
1689
- console.error("Script error");
1690
- console.error(error);
1691
- track.steps[track.currentStep].error = error.message || error;
1692
- return true;
1693
- }
1694
- }
1695
- if (step.prompt.options) {
1696
- try {
1697
- const options = await step.prompt.options(track.output);
1698
- track.steps[track.currentStep].promptOptions = options;
1699
- } catch (error) {
1700
- console.error("Script error");
1701
- console.error(error);
1702
- track.steps[track.currentStep].error = error.message || error;
1703
- return true;
1442
+ history.data.history.push(result);
1443
+ history.save();
1704
1444
  }
1705
- }
1706
- return true;
1707
- }
1708
- }
1709
- });
1710
-
1711
- // ../../modules/global-scripts/backend/routes.js
1712
- var require_routes8 = __commonJS({
1713
- "../../modules/global-scripts/backend/routes.js"(exports2, module2) {
1714
- "use strict";
1715
- var express = require("express");
1716
- var router = express.Router();
1717
- module2.exports = (Stack) => {
1718
- const { globalScripts } = Stack;
1719
- router.get("/global-scripts/", async (req, res) => {
1720
- res.json(globalScripts.getScripts());
1445
+ res.json(result);
1721
1446
  });
1722
- router.get("/global-scripts/:id", async (req, res) => {
1723
- const script = await globalScripts.getScript(req.params.id);
1724
- res.json(script);
1447
+ router.post("/logs/:service/terminate", (req, res) => {
1448
+ const service = findService(req.params.service);
1449
+ const {
1450
+ /** @type {number | undefined} */
1451
+ pid,
1452
+ /** @type {boolean | undefined} */
1453
+ forceKill
1454
+ } = req.body;
1455
+ if (!pid) throw new Error("Pid is required");
1456
+ if (pid) service.terminate(pid, !!forceKill);
1457
+ Socket.emit("logs:update", []);
1458
+ res.send("ok");
1725
1459
  });
1726
- router.post("/global-scripts/:id", async (req, res) => {
1727
- const communicationId = await globalScripts.launchScript(req.params.id);
1728
- res.json(communicationId);
1460
+ router.delete("/logs/:service/logs", (req, res) => {
1461
+ const service = findService(req.params.service);
1462
+ service.store = [];
1463
+ Socket.emit("logs:clear", { label: service.label });
1464
+ res.send(service.store);
1729
1465
  });
1730
1466
  return router;
1731
1467
  };
1468
+ var groupBy = (xs, key) => {
1469
+ const group = xs.reduce((rv, x) => {
1470
+ if (!rv[x[key]]) rv[x[key]] = { ...x, number: 0, timestamps: [] };
1471
+ rv[x[key]].timestamps.push(x.timestamp);
1472
+ rv[x[key]].timestamp = x.timestamp;
1473
+ return rv;
1474
+ }, {});
1475
+ return Object.keys(group).map((key2) => group[key2]);
1476
+ };
1732
1477
  }
1733
1478
  });
1734
1479
 
1735
- // ../../modules/global-scripts/backend/index.js
1736
- var require_backend10 = __commonJS({
1737
- "../../modules/global-scripts/backend/index.js"(exports2, module2) {
1480
+ // ../../modules/logs/backend/index.js
1481
+ var require_backend7 = __commonJS({
1482
+ "../../modules/logs/backend/index.js"(exports2, module2) {
1738
1483
  "use strict";
1739
- var GlobalScripts = require_GlobalScripts();
1484
+ var dayjs = require("dayjs");
1740
1485
  var plugin = {
1741
1486
  enabled: true,
1742
- name: "Global scripts",
1743
- displayName: "Global scripts",
1744
- description: "Launch scripts and rule the world",
1745
- icon: "fas fa-columns",
1746
- export: GlobalScripts,
1747
- placements: [
1748
- {
1749
- position: "dev-ops",
1750
- label: "Global scripts",
1751
- iconText: "{}",
1752
- goTo: { path: "/GlobalScripts" },
1753
- active: "GlobalScripts"
1754
- }
1755
- ],
1756
- finder: (search, runeya) => {
1757
- const scripts = runeya.globalScripts.getScripts().filter((script) => script.label.toUpperCase()?.includes(search?.toUpperCase()));
1758
- return [
1759
- ...scripts.map((script) => ({
1760
- icon: "fas fa-cog",
1761
- title: script.label,
1762
- group: "Global scripts",
1763
- description: "",
1764
- secondaryTitle: "",
1765
- url: { path: "/DevOps/GlobalScripts", query: { script: script.label } }
1766
- }))
1767
- ];
1768
- },
1769
- routes: require_routes8()
1770
- };
1771
- module2.exports = plugin;
1772
- }
1773
- });
1774
-
1775
- // ../../modules/http-client/backend/HttpClient.js
1776
- var require_HttpClient = __commonJS({
1777
- "../../modules/http-client/backend/HttpClient.js"(exports2, module2) {
1778
- "use strict";
1779
- var axios = require("axios").default;
1780
- var HttpClient = (runeya) => ({
1781
- /**
1782
- * Send HTTP request
1783
- * @param {Object} options - Request options
1784
- * @param {string} options.method - HTTP method (GET, POST, PUT, DELETE, etc.)
1785
- * @param {string} options.url - Request URL
1786
- * @param {Object} [options.headers] - Request headers
1787
- * @param {Object|string} [options.body] - Request body
1788
- * @param {Object} [options.params] - Query parameters
1789
- * @returns {Promise<Object>} Response data
1790
- */
1791
- sendRequest: async ({ method, url, headers = {}, body = null, params = {} }) => {
1792
- try {
1793
- const config = {
1794
- method,
1795
- url,
1796
- headers,
1797
- params
1798
- };
1799
- if (body) {
1800
- config.data = body;
1801
- }
1802
- const startTime = Date.now();
1803
- const response = await axios(config);
1804
- const endTime = Date.now();
1805
- return {
1806
- status: response.status,
1807
- statusText: response.statusText,
1808
- headers: response.headers,
1809
- data: response.data,
1810
- responseTime: endTime - startTime
1811
- };
1812
- } catch (error) {
1813
- if (error && typeof error === "object" && "response" in error) {
1814
- const axiosError = (
1815
- /** @type {import('axios').AxiosError} */
1816
- error
1817
- );
1818
- return {
1819
- status: axiosError.response?.status,
1820
- statusText: axiosError.response?.statusText,
1821
- headers: axiosError.response?.headers,
1822
- data: axiosError.response?.data,
1823
- error: true
1824
- };
1825
- }
1826
- throw error;
1827
- }
1828
- }
1829
- });
1830
- module2.exports = HttpClient;
1831
- }
1832
- });
1833
-
1834
- // ../../modules/http-client/backend/routes.js
1835
- var require_routes9 = __commonJS({
1836
- "../../modules/http-client/backend/routes.js"(exports2, module2) {
1837
- "use strict";
1838
- var express = require("express");
1839
- var router = express.Router();
1840
- var HttpClient = require_HttpClient();
1841
- module2.exports = (runeya) => {
1842
- const httpClient = HttpClient(runeya);
1843
- router.post("/http-client/request", async (req, res) => {
1844
- try {
1845
- const { method, url, headers, body, params } = req.body;
1846
- const response = await httpClient.sendRequest({
1847
- method,
1848
- url,
1849
- headers,
1850
- body,
1851
- params
1852
- });
1853
- res.json(response);
1854
- } catch (error) {
1855
- res.status(500).json({
1856
- error: true,
1857
- message: error instanceof Error ? error.message : "Unknown error",
1858
- stack: error instanceof Error ? error.stack : void 0
1859
- });
1860
- }
1861
- });
1862
- router.get("/http-client/history", (req, res) => {
1863
- res.json([]);
1864
- });
1865
- router.post("/http-client/history", (req, res) => {
1866
- res.json({ success: true });
1867
- });
1868
- return router;
1869
- };
1870
- }
1871
- });
1872
-
1873
- // ../../modules/http-client/backend/index.js
1874
- var require_backend11 = __commonJS({
1875
- "../../modules/http-client/backend/index.js"(exports2, module2) {
1876
- "use strict";
1877
- var plugin = {
1878
- enabled: true,
1879
- name: "HttpClient",
1880
- displayName: "HTTP Client",
1881
- description: "Test HTTP endpoints like Postman",
1882
- icon: "fas fa-exchange-alt",
1883
- placements: [
1884
- {
1885
- position: "toolbox",
1886
- label: "HTTP Client",
1887
- icon: "fas fa-exchange-alt",
1888
- goTo: { path: "/HttpClient" },
1889
- active: "HttpClient"
1890
- }
1891
- ],
1892
- export: require_HttpClient(),
1893
- order: 7,
1894
- routes: require_routes9()
1895
- };
1896
- module2.exports = plugin;
1897
- }
1898
- });
1899
-
1900
- // ../../modules/json-formatter/backend/JSONFormatter.js
1901
- var require_JSONFormatter = __commonJS({
1902
- "../../modules/json-formatter/backend/JSONFormatter.js"(exports2, module2) {
1903
- "use strict";
1904
- var fs = require("fs");
1905
- var path = require("path");
1906
- var yaml = require("js-yaml");
1907
- var xmljs = require("xml-js");
1908
- var Ajv = require("ajv").default;
1909
- var JSONFormatter = class {
1910
- /**
1911
- * Validate JSON against a schema
1912
- * @param {Object} json - The JSON object to validate
1913
- * @param {Object} schema - The JSON schema
1914
- * @returns {Object} Validation result
1915
- */
1916
- validateSchema(json, schema) {
1917
- const ajv = new Ajv();
1918
- const validate = ajv.compile(schema);
1919
- const valid = validate(json);
1920
- return {
1921
- valid,
1922
- errors: validate.errors || []
1923
- };
1924
- }
1925
- /**
1926
- * Convert JSON to YAML
1927
- * @param {Object} json - The JSON object to convert
1928
- * @returns {string} YAML string
1929
- */
1930
- jsonToYaml(json) {
1931
- return yaml.dump(json);
1932
- }
1933
- /**
1934
- * Convert YAML to JSON
1935
- * @param {string} yamlStr - The YAML string to convert
1936
- * @returns {Object} JSON object
1937
- */
1938
- yamlToJson(yamlStr) {
1939
- return yaml.load(yamlStr);
1940
- }
1941
- /**
1942
- * Convert JSON to XML
1943
- * @param {Object} json - The JSON object to convert
1944
- * @returns {string} XML string
1945
- */
1946
- jsonToXml(json) {
1947
- return xmljs.js2xml(json, { compact: true, spaces: 2 });
1948
- }
1949
- /**
1950
- * Convert XML to JSON
1951
- * @param {string} xmlStr - The XML string to convert
1952
- * @returns {Object} JSON object
1953
- */
1954
- xmlToJson(xmlStr) {
1955
- return xmljs.xml2js(xmlStr, { compact: true });
1956
- }
1957
- /**
1958
- * Compress JSON (remove whitespace)
1959
- * @param {Object|string} json - The JSON object or string to compress
1960
- * @returns {string} Compressed JSON string
1961
- */
1962
- compressJson(json) {
1963
- const jsonObj = typeof json === "string" ? JSON.parse(json) : json;
1964
- return JSON.stringify(jsonObj);
1965
- }
1966
- /**
1967
- * Pretty print JSON (add indentation)
1968
- * @param {Object|string} json - The JSON object or string to format
1969
- * @param {number} indentation - Number of spaces for indentation
1970
- * @returns {string} Formatted JSON string
1971
- */
1972
- prettyPrintJson(json, indentation = 2) {
1973
- const jsonObj = typeof json === "string" ? JSON.parse(json) : json;
1974
- return JSON.stringify(jsonObj, null, indentation);
1975
- }
1976
- /**
1977
- * Calculate statistics about a JSON object
1978
- * @param {Object} json - The JSON object
1979
- * @returns {Object} Statistics object
1980
- */
1981
- getJsonStats(json) {
1982
- const stats = {
1983
- size: 0,
1984
- stringifiedSize: 0,
1985
- depth: 0,
1986
- keys: 0,
1987
- arrays: 0,
1988
- objects: 0,
1989
- primitives: 0
1990
- };
1991
- stats.stringifiedSize = JSON.stringify(json).length;
1992
- stats.size = Buffer.from(JSON.stringify(json)).length;
1993
- const traverse = (obj, depth = 0) => {
1994
- if (depth > stats.depth) stats.depth = depth;
1995
- if (Array.isArray(obj)) {
1996
- stats.arrays++;
1997
- for (const item of obj) {
1998
- if (typeof item === "object" && item !== null) {
1999
- traverse(item, depth + 1);
2000
- } else {
2001
- stats.primitives++;
2002
- }
2003
- }
2004
- } else if (typeof obj === "object" && obj !== null) {
2005
- stats.objects++;
2006
- const objKeys = Object.keys(obj);
2007
- stats.keys += objKeys.length;
2008
- for (const key of objKeys) {
2009
- if (typeof obj[key] === "object" && obj[key] !== null) {
2010
- traverse(obj[key], depth + 1);
2011
- } else {
2012
- stats.primitives++;
2013
- }
2014
- }
2015
- }
2016
- };
2017
- traverse(json);
2018
- return stats;
2019
- }
2020
- /**
2021
- * Query JSON using JSONPath
2022
- * @param {Object} json - The JSON object
2023
- * @param {string} query - JSONPath query
2024
- * @returns {Array} Query results
2025
- */
2026
- queryJson(json, query) {
2027
- if (query === "$") return json;
2028
- return [{ message: "JSONPath implementation would return results here" }];
2029
- }
2030
- };
2031
- module2.exports = new JSONFormatter();
2032
- }
2033
- });
2034
-
2035
- // ../../modules/json-formatter/backend/routes.js
2036
- var require_routes10 = __commonJS({
2037
- "../../modules/json-formatter/backend/routes.js"(exports2, module2) {
2038
- "use strict";
2039
- var express = require("express");
2040
- var router = express.Router();
2041
- var JSONFormatter = require_JSONFormatter();
2042
- module2.exports = function(runeya) {
2043
- router.post("/JSONFormatterEnhanced/validate", (req, res) => {
2044
- try {
2045
- const { json, schema } = req.body;
2046
- const result = JSONFormatter.validateSchema(json, schema);
2047
- res.json(result);
2048
- } catch (error) {
2049
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2050
- }
2051
- });
2052
- router.post("/JSONFormatterEnhanced/to-yaml", (req, res) => {
2053
- try {
2054
- const { json } = req.body;
2055
- const yaml = JSONFormatter.jsonToYaml(json);
2056
- res.json({ yaml });
2057
- } catch (error) {
2058
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2059
- }
2060
- });
2061
- router.post("/JSONFormatterEnhanced/from-yaml", (req, res) => {
2062
- try {
2063
- const { yaml } = req.body;
2064
- const json = JSONFormatter.yamlToJson(yaml);
2065
- res.json({ json });
2066
- } catch (error) {
2067
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2068
- }
2069
- });
2070
- router.post("/JSONFormatterEnhanced/to-xml", (req, res) => {
2071
- try {
2072
- const { json } = req.body;
2073
- const xml = JSONFormatter.jsonToXml(json);
2074
- res.json({ xml });
2075
- } catch (error) {
2076
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2077
- }
2078
- });
2079
- router.post("/JSONFormatterEnhanced/from-xml", (req, res) => {
2080
- try {
2081
- const { xml } = req.body;
2082
- const json = JSONFormatter.xmlToJson(xml);
2083
- res.json({ json });
2084
- } catch (error) {
2085
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2086
- }
2087
- });
2088
- router.post("/JSONFormatterEnhanced/stats", (req, res) => {
2089
- try {
2090
- const { json } = req.body;
2091
- const stats = JSONFormatter.getJsonStats(json);
2092
- res.json(stats);
2093
- } catch (error) {
2094
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2095
- }
2096
- });
2097
- router.post("/JSONFormatterEnhanced/query", (req, res) => {
2098
- try {
2099
- const { json, query } = req.body;
2100
- const results = JSONFormatter.queryJson(json, query);
2101
- res.json(results);
2102
- } catch (error) {
2103
- res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
2104
- }
2105
- });
2106
- return router;
2107
- };
2108
- }
2109
- });
2110
-
2111
- // ../../modules/json-formatter/backend/index.js
2112
- var require_backend12 = __commonJS({
2113
- "../../modules/json-formatter/backend/index.js"(exports2, module2) {
2114
- "use strict";
2115
- var plugin = {
2116
- enabled: true,
2117
- name: "JSONFormatter",
2118
- displayName: "JSON",
2119
- description: "View, edit, validate, transform and explore JSON data",
2120
- icon: "fas fa-brackets-curly",
2121
- export: require_JSONFormatter(),
2122
- placements: [
2123
- {
2124
- position: "toolbox",
2125
- label: "JSON",
2126
- iconText: "{}",
2127
- goTo: { path: "/JSONFormatter" },
2128
- active: "JSONFormatter"
2129
- }
2130
- ],
2131
- routes: require_routes10(),
2132
- order: 6
2133
- };
2134
- module2.exports = plugin;
2135
- }
2136
- });
2137
-
2138
- // ../../modules/jwt/backend/JWT.js
2139
- var require_JWT = __commonJS({
2140
- "../../modules/jwt/backend/JWT.js"(exports2, module2) {
2141
- "use strict";
2142
- var jsonwebtoken = require("jsonwebtoken");
2143
- var JWT = class {
2144
- /**
2145
- * Decode a JWT without verifying signature
2146
- * @param {string} token JWT token string
2147
- * @returns {object} Decoded JWT payload
2148
- */
2149
- decode(token) {
2150
- return jsonwebtoken.decode(token, { complete: true });
2151
- }
2152
- /**
2153
- * Verify and decode a JWT token
2154
- * @param {string} token JWT token string
2155
- * @param {string} secret Secret key for verification
2156
- * @param {object} options JWT verify options
2157
- * @returns {object} Decoded JWT if valid
2158
- */
2159
- verify(token, secret, options = {}) {
2160
- try {
2161
- return jsonwebtoken.verify(token, secret, options);
2162
- } catch (err) {
2163
- const error = err instanceof Error ? err.message : String(err);
2164
- return { error };
2165
- }
2166
- }
2167
- /**
2168
- * Generate a new JWT token
2169
- * @param {object} payload Data to encode in the token
2170
- * @param {string} secret Secret key for signing
2171
- * @param {object} options JWT sign options
2172
- * @returns {string} Signed JWT token
2173
- */
2174
- generate(payload, secret, options = {}) {
2175
- return jsonwebtoken.sign(payload, secret, options);
2176
- }
2177
- /**
2178
- * Analyze token structure and details
2179
- * @param {string} token JWT token string
2180
- * @returns {object} Analysis results
2181
- */
2182
- analyze(token) {
2183
- try {
2184
- const decoded = this.decode(token);
2185
- if (!decoded) return { error: "Invalid token format" };
2186
- const parts = token.split(".");
2187
- const analysis = {
2188
- structure: {
2189
- header: decoded.header,
2190
- payload: decoded.payload,
2191
- signature: parts[2] ? true : false
2192
- },
2193
- validation: {
2194
- hasExpiry: decoded.payload.exp ? true : false,
2195
- hasIssuedAt: decoded.payload.iat ? true : false,
2196
- hasNotBefore: decoded.payload.nbf ? true : false
2197
- }
2198
- };
2199
- if (analysis.validation.hasExpiry) {
2200
- const expiry = new Date(decoded.payload.exp * 1e3);
2201
- const now = /* @__PURE__ */ new Date();
2202
- analysis.validation.isExpired = now > expiry;
2203
- analysis.validation.expiresIn = analysis.validation.isExpired ? "Expired" : this.formatTimeRemaining(expiry.getTime() - now.getTime());
2204
- }
2205
- if (decoded.header.alg) {
2206
- analysis.security = {
2207
- algorithm: decoded.header.alg,
2208
- isSecure: decoded.header.alg !== "none" && !decoded.header.alg.startsWith("HS")
2209
- };
2210
- }
2211
- return analysis;
2212
- } catch (err) {
2213
- const error = err instanceof Error ? err.message : String(err);
2214
- return { error };
2215
- }
2216
- }
2217
- /**
2218
- * Format milliseconds to human readable time
2219
- * @param {number} ms Milliseconds
2220
- * @returns {string} Formatted time string
2221
- */
2222
- formatTimeRemaining(ms) {
2223
- if (ms <= 0) return "Expired";
2224
- const seconds = Math.floor(ms / 1e3);
2225
- const minutes = Math.floor(seconds / 60);
2226
- const hours = Math.floor(minutes / 60);
2227
- const days = Math.floor(hours / 24);
2228
- if (days > 0) return `${days} day(s)`;
2229
- if (hours > 0) return `${hours} hour(s)`;
2230
- if (minutes > 0) return `${minutes} minute(s)`;
2231
- return `${seconds} second(s)`;
2232
- }
2233
- };
2234
- module2.exports = new JWT();
2235
- }
2236
- });
2237
-
2238
- // ../../modules/jwt/backend/routes.js
2239
- var require_routes11 = __commonJS({
2240
- "../../modules/jwt/backend/routes.js"(exports2, module2) {
2241
- "use strict";
2242
- var express = require("express");
2243
- var JWT = require_JWT();
2244
- var router = express.Router();
2245
- module2.exports = () => {
2246
- router.post("/JWT/", async (req, res) => {
2247
- const { jwt } = req.body;
2248
- try {
2249
- res.json(JWT.decode(jwt));
2250
- } catch (err) {
2251
- res.status(400).json({ error: err instanceof Error ? err.message : String(err) });
2252
- }
2253
- });
2254
- router.post("/JWT/analyze", async (req, res) => {
2255
- const { jwt } = req.body;
2256
- try {
2257
- res.json(JWT.analyze(jwt));
2258
- } catch (err) {
2259
- res.status(400).json({ error: err instanceof Error ? err.message : String(err) });
2260
- }
2261
- });
2262
- router.post("/JWT/verify", async (req, res) => {
2263
- const { jwt, secret, options } = req.body;
2264
- try {
2265
- res.json(JWT.verify(jwt, secret, options));
2266
- } catch (err) {
2267
- res.status(400).json({ error: err instanceof Error ? err.message : String(err) });
2268
- }
2269
- });
2270
- router.post("/JWT/generate", async (req, res) => {
2271
- const { payload, secret, options } = req.body;
2272
- try {
2273
- const token = JWT.generate(payload, secret, options);
2274
- res.json({ token });
2275
- } catch (err) {
2276
- res.status(400).json({ error: err instanceof Error ? err.message : String(err) });
2277
- }
2278
- });
2279
- return router;
2280
- };
2281
- }
2282
- });
2283
-
2284
- // ../../modules/jwt/backend/index.js
2285
- var require_backend13 = __commonJS({
2286
- "../../modules/jwt/backend/index.js"(exports2, module2) {
2287
- "use strict";
2288
- var plugin = {
2289
- enabled: true,
2290
- name: "JWT",
2291
- displayName: "JWT",
2292
- description: "Decode, verify and create JSON Web Tokens",
2293
- icon: "fas fa-key",
2294
- export: require_JWT(),
2295
- placements: [
2296
- {
2297
- position: "toolbox",
2298
- label: "JWT",
2299
- icon: "fas fa-key",
2300
- goTo: { path: "/JWT" },
2301
- active: "JWT"
2302
- }
2303
- ],
2304
- order: 6,
2305
- routes: require_routes11()
2306
- };
2307
- module2.exports = plugin;
2308
- }
2309
- });
2310
-
2311
- // ../../modules/kanban/backend/save.js
2312
- var require_save = __commonJS({
2313
- "../../modules/kanban/backend/save.js"(exports2, module2) {
2314
- "use strict";
2315
- var kanban = {
2316
- /** @param {import('@runeya/common-typings').Runeya} runeya */
2317
- getSave(runeya) {
2318
- return runeya.getSave("kanban.json", {
2319
- /** @type {Partial<import('@runeya/common-typings').NonFunctionProperties<import('./Kanban').BoardType>['prototype']>[]} */
2320
- boards: [],
2321
- /** @type {Partial<import('@runeya/common-typings').NonFunctionProperties<import('./Kanban').ColumnType>['prototype']>[]} */
2322
- columns: [],
2323
- /** @type {Partial<import('@runeya/common-typings').NonFunctionProperties<import('./Kanban').CardType>['prototype']>[]} */
2324
- cards: []
2325
- }, {
2326
- afterGet(data) {
2327
- if (!data.boards) data.boards = [];
2328
- if (!data.columns) data.columns = [];
2329
- if (!data.cards) data.cards = [];
2330
- },
2331
- beforeSave(data) {
2332
- if (!data.boards) data.boards = [];
2333
- if (!data.columns) data.columns = [];
2334
- if (!data.cards) data.cards = [];
2335
- }
2336
- });
2337
- }
2338
- };
2339
- module2.exports = kanban;
2340
- }
2341
- });
2342
-
2343
- // ../../modules/kanban/backend/Kanban.js
2344
- var require_Kanban = __commonJS({
2345
- "../../modules/kanban/backend/Kanban.js"(exports2, module2) {
2346
- "use strict";
2347
- var { v4 } = require("uuid");
2348
- var { getSave: _getSave } = require_save();
2349
- var runeya = null;
2350
- function getSave() {
2351
- if (!runeya) throw new Error("Call init before");
2352
- const { data, save } = _getSave(runeya);
2353
- return { data, save };
2354
- }
2355
- var Board = class _Board {
2356
- /** @param {Partial<import('@runeya/common-typings').NonFunctionProperties<Board>>} board */
2357
- constructor(board = {}) {
2358
- this.id = board.id || v4();
2359
- this.name = board.name;
2360
- this.columnIds = board.columnIds || [];
2361
- }
2362
- /** @returns {Board[]} */
2363
- static all() {
2364
- const { data } = getSave();
2365
- return data.boards.map((b) => b ? new _Board(b) : null).filter((a) => a);
2366
- }
2367
- /** @param {string} id */
2368
- static get(id) {
2369
- const { data } = getSave();
2370
- const board = data.boards.find((d) => d?.id === id);
2371
- return board ? new _Board(board) : null;
2372
- }
2373
- /**
2374
- *
2375
- * @returns {Column[]}
2376
- */
2377
- getColumns() {
2378
- return this.columnIds.map((columnId) => Column.get(columnId)).filter((a) => a);
2379
- }
2380
- delete() {
2381
- const { data, save } = getSave();
2382
- this.getColumns().forEach((c) => c.delete());
2383
- data.boards = data.boards.filter((b) => b?.id !== this.id);
2384
- save();
2385
- }
2386
- /** @param {string} id */
2387
- getColumn(id) {
2388
- return this.getColumns().find((c) => c?.id === id);
2389
- }
2390
- /** @param {Partial<import('@runeya/common-typings').NonFunctionProperties<Column>>} column */
2391
- addColumn(column) {
2392
- const savedColumn = new Column({ ...column, boardId: this.id }).save();
2393
- this.columnIds = [.../* @__PURE__ */ new Set([...this.columnIds, savedColumn.id])];
2394
- this.save();
2395
- return savedColumn;
2396
- }
2397
- save() {
2398
- const { data, save } = getSave();
2399
- const existing = data.boards.find((b) => b?.id === this.id);
2400
- if (existing) {
2401
- Object.assign(existing, { ...this });
2402
- } else {
2403
- data.boards.push(this);
2404
- }
2405
- save();
2406
- return this;
2407
- }
2408
- };
2409
- var Column = class _Column {
2410
- /** @param {Partial<import('@runeya/common-typings').NonFunctionProperties<Column>>} column */
2411
- constructor(column = {}) {
2412
- this.id = column.id || v4();
2413
- this.name = column.name;
2414
- this.color = column.color;
2415
- this.boardId = column.boardId;
2416
- this.cardIds = column.cardIds || [];
2417
- }
2418
- /** @param {string} id */
2419
- static get(id) {
2420
- const { data } = getSave();
2421
- const column = data.columns.find((d) => d?.id === id);
2422
- return column ? new _Column(column) : null;
2423
- }
2424
- /** @returns {Card[]} */
2425
- getCards() {
2426
- return this.cardIds.map((columnId) => Card.get(columnId)).filter((a) => a);
2427
- }
2428
- /** @param {string} id */
2429
- getCard(id) {
2430
- return this.getCards().find((c) => c?.id === id);
2431
- }
2432
- /** @param {Partial<import('@runeya/common-typings').NonFunctionProperties<Card>>} card */
2433
- addCard(card) {
2434
- const savedColumn = new Card({ ...card, boardId: this.boardId, columnId: this.id }).save();
2435
- this.cardIds = [.../* @__PURE__ */ new Set([...this.cardIds, savedColumn.id])];
2436
- this.save();
2437
- return savedColumn;
2438
- }
2439
- delete() {
2440
- const { data, save } = getSave();
2441
- this.getCards().forEach((c) => c.delete());
2442
- data.columns = data.columns.filter((b) => b?.id !== this.id);
2443
- save();
2444
- }
2445
- save() {
2446
- const { data, save } = getSave();
2447
- const existing = data.columns.find((b) => b?.id === this.id);
2448
- if (existing) {
2449
- Object.assign(existing, { ...this });
2450
- } else {
2451
- data.columns.push(this);
2452
- }
2453
- save();
2454
- return this;
2455
- }
2456
- };
2457
- var Card = class _Card {
2458
- /** @param {Partial<import('@runeya/common-typings').NonFunctionProperties<Card>>} card */
2459
- constructor(card = {}) {
2460
- this.id = card.id || v4();
2461
- this.name = card.name;
2462
- this.description = card.description;
2463
- this.boardId = card.boardId;
2464
- this.columnId = card.columnId;
2465
- }
2466
- /** @param {string} id */
2467
- static get(id) {
2468
- const { data } = getSave();
2469
- const cards = data.cards.find((d) => d?.id === id);
2470
- return cards ? new _Card(cards) : null;
2471
- }
2472
- delete() {
2473
- const { data, save } = getSave();
2474
- data.cards = data.cards.filter((b) => b?.id !== this.id);
2475
- save();
2476
- }
2477
- save() {
2478
- const { data, save } = getSave();
2479
- const existing = data.cards.find((b) => b?.id === this.id);
2480
- if (existing) {
2481
- Object.assign(existing, { ...this });
2482
- } else {
2483
- data.cards.push(this);
2484
- }
2485
- save();
2486
- return this;
2487
- }
2488
- };
2489
- var Kanban = (_runeya) => {
2490
- runeya = _runeya;
2491
- return {
2492
- Card,
2493
- Column,
2494
- Board
2495
- };
2496
- };
2497
- module2.exports = Kanban;
2498
- }
2499
- });
2500
-
2501
- // ../../modules/kanban/backend/routes.js
2502
- var require_routes12 = __commonJS({
2503
- "../../modules/kanban/backend/routes.js"(exports2, module2) {
2504
- "use strict";
2505
- var express = require("express");
2506
- var router = express.Router();
2507
- module2.exports = (runeya) => {
2508
- const { Board } = require_Kanban()(runeya);
2509
- router.get("/kanban/boards", async (req, res) => {
2510
- res.json(Board.all());
2511
- });
2512
- router.post("/kanban/boards", async (req, res) => {
2513
- const board = new Board(req.body).save();
2514
- res.json(board);
2515
- });
2516
- router.delete("/kanban/boards/:boardId", async (req, res) => {
2517
- const board = Board.get(req.params.boardId);
2518
- board?.delete();
2519
- res.json(board);
2520
- });
2521
- router.get("/kanban/boards/:boardId/columns", async (req, res) => {
2522
- res.json(Board.get(req.params.boardId)?.getColumns());
2523
- });
2524
- router.get("/kanban/boards/:boardId/columns/:columnId", async (req, res) => {
2525
- res.json(Board.get(req.params.boardId)?.getColumn(req.params.columnId));
2526
- });
2527
- router.delete("/kanban/boards/:boardId/columns/:columnId", async (req, res) => {
2528
- const column = Board.get(req.params.boardId)?.getColumn(req.params.columnId);
2529
- column?.delete();
2530
- res.json(column);
2531
- });
2532
- router.post("/kanban/boards/:boardId/columns", async (req, res) => {
2533
- const board = Board.get(req.params.boardId)?.addColumn(req.body);
2534
- res.json(board);
2535
- });
2536
- router.get("/kanban/boards/:boardId/columns/:columnId/cards", async (req, res) => {
2537
- res.json(Board.get(req.params.boardId)?.getColumn(req.params.columnId)?.getCards());
2538
- });
2539
- router.delete("/kanban/boards/:boardId/columns/:columnId/cards/:cardId", async (req, res) => {
2540
- const card = Board.get(req.params.boardId)?.getColumn(req.params.columnId)?.getCard(req.params.cardId);
2541
- card?.delete();
2542
- res.json(card);
2543
- });
2544
- router.post("/kanban/boards/:boardId/columns/:columnId/cards", async (req, res) => {
2545
- res.json(Board.get(req.params.boardId)?.getColumn(req.params.columnId)?.addCard(req.body));
2546
- });
2547
- return router;
2548
- };
2549
- }
2550
- });
2551
-
2552
- // ../../modules/kanban/backend/index.js
2553
- var require_backend14 = __commonJS({
2554
- "../../modules/kanban/backend/index.js"(exports2, module2) {
2555
- "use strict";
2556
- var Kanban = require_Kanban();
2557
- var plugin = {
2558
- enabled: true,
2559
- name: "kanban",
2560
- displayName: "Kanban",
2561
- description: "Manage your project with cards",
2562
- icon: "fas fa-columns",
2563
- placements: [
2564
- {
2565
- position: "toolbox",
2566
- label: "Kanban",
2567
- icon: "fas fa-columns",
2568
- goTo: { path: "/kanban" },
2569
- active: "kanban"
2570
- }
2571
- ],
2572
- finder: (search, runeya) => {
2573
- const boards = Kanban(runeya).Board.all().filter((board) => runeya.helpers.searchString(board?.name || "", search));
2574
- const cards = Kanban(runeya).Board.all().flatMap((b) => b?.getColumns())?.flatMap((c) => c?.getCards())?.filter((board) => runeya.helpers.searchString(board?.name || "", search));
2575
- return [
2576
- ...boards.map((board) => ({
2577
- icon: "fas fa-columns",
2578
- title: board?.name || "",
2579
- group: "Kanban",
2580
- description: "Manage your project with cards",
2581
- secondaryTitle: "Board",
2582
- url: { path: "/toolbox/kanban", query: { boardId: board?.id } }
2583
- })),
2584
- ...cards.map((card) => ({
2585
- icon: "fas fa-columns",
2586
- title: card?.name || "",
2587
- group: "Kanban",
2588
- description: "Manage your project with cards",
2589
- secondaryTitle: "Card",
2590
- url: { path: "/toolbox/kanban", query: { boardId: card?.boardId, cardId: card?.id } }
2591
- }))
2592
- ];
2593
- },
2594
- export: Kanban,
2595
- order: 6,
2596
- routes: require_routes12()
2597
- };
2598
- module2.exports = plugin;
2599
- }
2600
- });
2601
-
2602
- // ../../modules/logs/backend/routes.js
2603
- var require_routes13 = __commonJS({
2604
- "../../modules/logs/backend/routes.js"(exports2, module2) {
2605
- "use strict";
2606
- var express = require("express");
2607
- var { v4 } = require("uuid");
2608
- var router = express.Router();
2609
- module2.exports = (runeya) => {
2610
- const history = runeya.getSave("history.json", {
2611
- /** @type {History[]} */
2612
- history: []
2613
- });
2614
- const { findService, Socket } = runeya;
2615
- router.get("/logs/:service/logs", (req, res) => {
2616
- const service = findService(req.params.service);
2617
- res.send(service ? service.store : []);
2618
- });
2619
- router.get("/logs/:service/autocomplete", (req, res) => {
2620
- const msg = req.query.message;
2621
- if (!msg && !req.query.force) return res.json([]);
2622
- const historyToSend = groupBy(history.data.history, "raw").sort((a, b) => a.timestamp - b.timestamp).filter((a) => a?.raw?.startsWith(msg) || a.cmd?.startsWith(msg)).slice(-10);
2623
- return res.json(historyToSend);
2624
- });
2625
- router.post("/logs/:service/prompt", async (req, res) => {
2626
- const service = findService(req.params.service);
2627
- let command = req.body.command || {};
2628
- const pid = req.body.pid ? +req.body.pid : void 0;
2629
- if (!command.spawnCmd) command.spawnCmd = "\n";
2630
- let result = {
2631
- id: v4(),
2632
- pid,
2633
- cmd: command.spawnCmd,
2634
- args: [],
2635
- raw: command.spawnCmd,
2636
- timestamp: Date.now(),
2637
- service: service.label || ""
2638
- };
2639
- if (pid) service.respondToProcess(pid, command.spawnCmd);
2640
- else if (command) {
2641
- const { spawnProcess, launchMessage } = await service.launchProcess(
2642
- { spawnCmd: command.spawnCmd, spawnArgs: command.spawnArgs || [], spawnOptions: command.spawnOptions || {} },
2643
- false
2644
- );
2645
- result = {
2646
- ...result,
2647
- pid: spawnProcess?.pid,
2648
- raw: launchMessage.raw,
2649
- timestamp: launchMessage.timestamp
2650
- };
2651
- history.data.history.push(result);
2652
- history.save();
2653
- }
2654
- res.json(result);
2655
- });
2656
- router.post("/logs/:service/terminate", (req, res) => {
2657
- const service = findService(req.params.service);
2658
- const {
2659
- /** @type {number | undefined} */
2660
- pid,
2661
- /** @type {boolean | undefined} */
2662
- forceKill
2663
- } = req.body;
2664
- if (!pid) throw new Error("Pid is required");
2665
- if (pid) service.terminate(pid, !!forceKill);
2666
- Socket.emit("logs:update", []);
2667
- res.send("ok");
2668
- });
2669
- router.delete("/logs/:service/logs", (req, res) => {
2670
- const service = findService(req.params.service);
2671
- service.store = [];
2672
- Socket.emit("logs:clear", { label: service.label });
2673
- res.send(service.store);
2674
- });
2675
- return router;
2676
- };
2677
- var groupBy = (xs, key) => {
2678
- const group = xs.reduce((rv, x) => {
2679
- if (!rv[x[key]]) rv[x[key]] = { ...x, number: 0, timestamps: [] };
2680
- rv[x[key]].timestamps.push(x.timestamp);
2681
- rv[x[key]].timestamp = x.timestamp;
2682
- return rv;
2683
- }, {});
2684
- return Object.keys(group).map((key2) => group[key2]);
2685
- };
2686
- }
2687
- });
2688
-
2689
- // ../../modules/logs/backend/index.js
2690
- var require_backend15 = __commonJS({
2691
- "../../modules/logs/backend/index.js"(exports2, module2) {
2692
- "use strict";
2693
- var dayjs = require("dayjs");
2694
- var plugin = {
2695
- enabled: true,
2696
- name: "Logs",
2697
- displayName: "Logs",
2698
- description: "Show, parse and communicate with logs produced by yours commands",
2699
- icon: "fas fa-terminal",
2700
- export: null,
2701
- placements: ["service"],
2702
- order: 1,
2703
- /**
2704
- * @param {*} search
2705
- * @param {import('@runeya/common-typings').Runeya} runeya
2706
- */
2707
- finder: (search, runeya) => {
2708
- const services = runeya.getServices()?.flatMap((s) => s.store?.slice(-300).reverse().map((line) => ({ log: line, service: s })))?.filter(({ log }) => runeya.helpers.searchString(log.raw, search));
2709
- return [
2710
- ...services.map((service) => ({
2711
- icon: "fas fa-terminal",
2712
- title: service.log.raw,
2713
- group: "Logs",
2714
- description: `Log from ${service.service.label}`,
2715
- secondaryTitle: service.service.label,
2716
- secondaryDescription: dayjs(service.log.timestamp).format("YYYY-DD-MM HH:mm:ss"),
2717
- url: { path: `/stack-single/${encodeURIComponent(service.service.label)}`, query: { tab: "Logs" } }
2718
- }))
2719
- ];
2720
- },
2721
- routes: require_routes13()
2722
- };
2723
- module2.exports = plugin;
2724
- }
2725
- });
2726
-
2727
- // ../../modules/mongo/backend/Mongo.js
2728
- var require_Mongo = __commonJS({
2729
- "../../modules/mongo/backend/Mongo.js"(exports2, module2) {
2730
- "use strict";
2731
- var { ObjectId } = require("mongodb");
2732
- var { MongoClient } = require("mongodb");
2733
- var MongoDB = class {
2734
- /**
2735
- * Generate a new ObjectId
2736
- * @returns {ObjectId} A new MongoDB ObjectId
2737
- */
2738
- generateObjectId() {
2739
- return new ObjectId();
2740
- }
2741
- /**
2742
- * Check if a string is a valid MongoDB ObjectId
2743
- * @param {string} id - The string to check
2744
- * @returns {boolean} True if valid, false otherwise
2745
- */
2746
- isValidObjectId(id) {
2747
- if (!id) return false;
2748
- try {
2749
- new ObjectId(id);
2750
- return true;
2751
- } catch (error) {
2752
- return false;
2753
- }
2754
- }
2755
- /**
2756
- * Decode an ObjectId to get its components
2757
- * @param {string} objectId - The ObjectId to decode
2758
- * @returns {Object} The decoded information
2759
- */
2760
- decodeObjectId(objectId) {
2761
- if (!this.isValidObjectId(objectId)) {
2762
- return {
2763
- isValid: false,
2764
- error: "Invalid ObjectId format"
2765
- };
2766
- }
2767
- try {
2768
- const timestamp = parseInt(objectId.substring(0, 8), 16);
2769
- const date = new Date(timestamp * 1e3);
2770
- const buffer = Buffer.from(objectId, "hex");
2771
- return {
2772
- isValid: true,
2773
- timestamp,
2774
- date,
2775
- machineId: objectId.substring(8, 14),
2776
- processId: objectId.substring(14, 18),
2777
- counter: objectId.substring(18, 24),
2778
- format: {
2779
- hex: objectId,
2780
- binary: buffer.toString("binary"),
2781
- base64: buffer.toString("base64")
2782
- }
2783
- };
2784
- } catch (error) {
2785
- const errorMessage = error instanceof Error ? error.message : String(error);
2786
- return {
2787
- isValid: false,
2788
- error: errorMessage
2789
- };
2790
- }
2791
- }
2792
- /**
2793
- * Create an ObjectId from a timestamp
2794
- * @param {Date|string} date - The date to use
2795
- * @returns {string} The generated ObjectId
2796
- */
2797
- objectIdFromDate(date) {
2798
- const timestamp = Math.floor(new Date(date).getTime() / 1e3);
2799
- return `${timestamp.toString(16)}0000000000000000`;
2800
- }
2801
- /**
2802
- * Compare two ObjectIds
2803
- * @param {string} objectId1 - First ObjectId
2804
- * @param {string} objectId2 - Second ObjectId
2805
- * @returns {Object} Comparison results
2806
- */
2807
- compareObjectIds(objectId1, objectId2) {
2808
- const obj1 = this.decodeObjectId(objectId1);
2809
- const obj2 = this.decodeObjectId(objectId2);
2810
- if (!obj1.isValid || !obj2.isValid) {
2811
- return {
2812
- isValid: false,
2813
- error: "One or both ObjectIds are invalid"
2814
- };
2815
- }
2816
- const timeDifference = obj1.timestamp - obj2.timestamp;
2817
- const millisecondsDiff = timeDifference * 1e3;
2818
- return {
2819
- isValid: true,
2820
- timeDifference: {
2821
- seconds: timeDifference,
2822
- milliseconds: millisecondsDiff,
2823
- humanReadable: this.formatTimeDifference(millisecondsDiff)
2824
- },
2825
- sameServer: obj1.machineId === obj2.machineId,
2826
- sameProcess: obj1.processId === obj2.processId,
2827
- counterDifference: parseInt(obj1.counter, 16) - parseInt(obj2.counter, 16)
2828
- };
2829
- }
2830
- /**
2831
- * Format time difference in a human readable format
2832
- * @param {number} milliseconds - Time difference in milliseconds
2833
- * @returns {string} Formatted time difference
2834
- */
2835
- formatTimeDifference(milliseconds) {
2836
- const absMs = Math.abs(milliseconds);
2837
- const prefix = milliseconds >= 0 ? "newer by " : "older by ";
2838
- if (absMs < 1e3) return `${prefix}${absMs} milliseconds`;
2839
- if (absMs < 6e4) return `${prefix}${Math.floor(absMs / 1e3)} seconds`;
2840
- if (absMs < 36e5) return `${prefix}${Math.floor(absMs / 6e4)} minutes`;
2841
- if (absMs < 864e5) return `${prefix}${Math.floor(absMs / 36e5)} hours`;
2842
- return `${prefix}${Math.floor(absMs / 864e5)} days`;
2843
- }
2844
- /**
2845
- * Test MongoDB connection
2846
- * @param {string} connectionString - MongoDB connection string
2847
- * @returns {Promise<Object>} Connection test results
2848
- */
2849
- async testConnection(connectionString) {
2850
- let client;
2851
- try {
2852
- client = new MongoClient(connectionString, {
2853
- serverSelectionTimeoutMS: 5e3,
2854
- connectTimeoutMS: 5e3
2855
- });
2856
- await client.connect();
2857
- const admin = client.db().admin();
2858
- const serverInfo = await admin.serverInfo();
2859
- const dbList = await client.db().admin().listDatabases();
2860
- return {
2861
- success: true,
2862
- version: serverInfo.version,
2863
- databases: dbList.databases.map((db) => ({
2864
- name: db.name,
2865
- sizeOnDisk: db.sizeOnDisk,
2866
- empty: db.empty
2867
- }))
2868
- };
2869
- } catch (error) {
2870
- const errorMessage = error instanceof Error ? error.message : String(error);
2871
- return {
2872
- success: false,
2873
- error: errorMessage
2874
- };
2875
- } finally {
2876
- if (client) await client.close();
2877
- }
2878
- }
2879
- };
2880
- module2.exports = new MongoDB();
2881
- }
2882
- });
2883
-
2884
- // ../../modules/mongo/backend/routes.js
2885
- var require_routes14 = __commonJS({
2886
- "../../modules/mongo/backend/routes.js"(exports2, module2) {
2887
- "use strict";
2888
- var express = require("express");
2889
- var MongoDB = require_Mongo();
2890
- var router = express.Router();
2891
- router.get("/mongo/generate", async (req, res) => {
2892
- res.json(MongoDB.generateObjectId());
2893
- });
2894
- router.post("/mongo/validate", async (req, res) => {
2895
- const { objectId } = req.body;
2896
- res.json({
2897
- isValid: MongoDB.isValidObjectId(objectId)
2898
- });
2899
- });
2900
- router.post("/mongo/decode", async (req, res) => {
2901
- const { objectId } = req.body;
2902
- res.json(MongoDB.decodeObjectId(objectId));
2903
- });
2904
- router.post("/mongo/from-date", async (req, res) => {
2905
- const { date } = req.body;
2906
- res.json({
2907
- objectId: MongoDB.objectIdFromDate(date)
2908
- });
2909
- });
2910
- router.post("/mongo/compare", async (req, res) => {
2911
- const { objectId1, objectId2 } = req.body;
2912
- res.json(MongoDB.compareObjectIds(objectId1, objectId2));
2913
- });
2914
- router.post("/mongo/test-connection", async (req, res) => {
2915
- const { connectionString } = req.body;
2916
- try {
2917
- const result = await MongoDB.testConnection(connectionString);
2918
- res.json(result);
2919
- } catch (error) {
2920
- res.status(500).json({
2921
- success: false,
2922
- error: error instanceof Error ? error.message : String(error)
2923
- });
2924
- }
2925
- });
2926
- module2.exports = () => router;
2927
- }
2928
- });
2929
-
2930
- // ../../modules/mongo/backend/index.js
2931
- var require_backend16 = __commonJS({
2932
- "../../modules/mongo/backend/index.js"(exports2, module2) {
2933
- "use strict";
2934
- var plugin = {
2935
- enabled: true,
2936
- name: "Mongo",
2937
- displayName: "MongoDB",
2938
- description: "MongoDB toolkit with ObjectID operations, validation, comparison and connection testing",
2939
- icon: "fab fa-envira",
2940
- export: null,
2941
- placements: [
2942
- {
2943
- position: "toolbox",
2944
- label: "MongoDB",
2945
- icon: "fab fa-envira",
2946
- goTo: { path: "/Mongo" },
2947
- active: "Mongo"
2948
- }
2949
- ],
2950
- order: 6,
2951
- routes: require_routes14()
2952
- };
2953
- module2.exports = plugin;
2954
- }
2955
- });
2956
-
2957
- // ../../modules/node-repl/backend/routes.js
2958
- var require_routes15 = __commonJS({
2959
- "../../modules/node-repl/backend/routes.js"(exports2, module2) {
2960
- "use strict";
2961
- var express = require("express");
2962
- var { v4 } = require("uuid");
2963
- var { mkdir, writeFile } = require("fs/promises");
2964
- var { writeFileSync, readFileSync, unlinkSync } = require("fs");
2965
- var pathfs = require("path");
2966
- var { mkdirSync, existsSync } = require("fs");
2967
- var { spawn } = require("child_process");
2968
- var { promisify } = require("util");
2969
- var setTimeoutAsync = promisify(setTimeout);
2970
- var prettier = require("prettier");
2971
- var { exec } = require("child_process");
2972
- var execAsync = promisify(exec);
2973
- var path = require("path");
2974
- var fs = require("fs").promises;
2975
- var router = express.Router();
2976
- var homedir = require("os").homedir();
2977
- var MAX_SCRIPT_SIZE = 1024 * 1024;
2978
- var MAX_EXECUTION_TIME = 3e4;
2979
- var MAX_MEMORY = 512 * 1024 * 1024;
2980
- var confDir = pathfs.resolve(homedir, ".runeya");
2981
- if (!existsSync(confDir)) mkdirSync(confDir);
2982
- var confPath = pathfs.resolve(confDir, "node-repl");
2983
- if (!existsSync(confPath)) writeFileSync(confPath, "{}", "utf-8");
2984
- var conf = JSON.parse(readFileSync(confPath, "utf-8"));
2985
- var packagesDir = pathfs.resolve(confDir, "node-repl-packages");
2986
- if (!existsSync(packagesDir)) mkdirSync(packagesDir);
2987
- function getRoomPackagesDir(room) {
2988
- return pathfs.resolve(packagesDir, room);
2989
- }
2990
- async function initRoomPackageJson(room) {
2991
- const roomDir = getRoomPackagesDir(room);
2992
- if (!existsSync(roomDir)) {
2993
- mkdirSync(roomDir, { recursive: true });
2994
- }
2995
- const packageJsonPath = pathfs.resolve(roomDir, "package.json");
2996
- if (!existsSync(packageJsonPath)) {
2997
- await fs.writeFile(packageJsonPath, JSON.stringify({ dependencies: {} }, null, 2), "utf-8");
2998
- }
2999
- return packageJsonPath;
3000
- }
3001
- async function cleanupRoomPackages(room) {
3002
- const roomDir = getRoomPackagesDir(room);
3003
- if (existsSync(roomDir)) {
3004
- try {
3005
- await fs.rm(roomDir, { recursive: true, force: true });
3006
- } catch (err) {
3007
- console.error(`Error cleaning up packages for room ${room}:`, err);
3008
- }
3009
- }
3010
- }
3011
- async function cleanupTempFiles() {
3012
- const sandboxDir = pathfs.resolve(__dirname, "sandbox-node-repl");
3013
- if (existsSync(sandboxDir)) {
3014
- const files = await promisify(require("fs").readdir)(sandboxDir);
3015
- for (const file of files) {
3016
- try {
3017
- await promisify(require("fs").unlink)(pathfs.join(sandboxDir, file));
3018
- } catch (err) {
3019
- console.error(`Error cleaning up file ${file}:`, err);
3020
- }
3021
- }
3022
- }
3023
- }
3024
- function validateScript(script) {
3025
- if (script.length > MAX_SCRIPT_SIZE) {
3026
- throw new Error(`Script too large. Maximum size is ${MAX_SCRIPT_SIZE / 1024 / 1024}MB`);
3027
- }
3028
- const dangerousImports = script.match(/require\(['"](?!${ALLOWED_MODULES.join('|')})['"]\)/g);
3029
- if (dangerousImports) {
3030
- throw new Error("Script contains unauthorized module imports");
3031
- }
3032
- return true;
3033
- }
3034
- async function checkNpmAvailable() {
3035
- try {
3036
- await execAsync("npm --version");
3037
- return true;
3038
- } catch (error) {
3039
- return false;
3040
- }
3041
- }
3042
- module2.exports = (runeya) => {
3043
- const { Socket } = runeya;
3044
- cleanupTempFiles().catch(console.error);
3045
- router.post("/node-repl/chat/:room", async (req, res) => {
3046
- try {
3047
- const { room } = req.params;
3048
- const { script } = req.body;
3049
- validateScript(script);
3050
- if (!conf.chat?.[room]) {
3051
- if (!conf.chat) conf.chat = {};
3052
- if (!conf.chat?.[room]) conf.chat[room] = {};
3053
- }
3054
- conf.chat[room].script = script;
3055
- await initRoomPackageJson(room);
3056
- const sessionId = v4();
3057
- const sessionDir = path.join(__dirname, "sandbox-node-repl", sessionId);
3058
- await fs.mkdir(sessionDir, { recursive: true });
3059
- const scriptPath = path.join(sessionDir, "script.js");
3060
- await fs.writeFile(scriptPath, script);
3061
- let result = "";
3062
- let error = null;
3063
- let timeoutId;
3064
- const customEnv = conf.chat[room]?.env || {};
3065
- const env = {
3066
- ...process.env,
3067
- ...customEnv,
3068
- NODE_OPTIONS: `--max-old-space-size=${MAX_MEMORY / 1024 / 1024}`,
3069
- NODE_PATH: path.join(getRoomPackagesDir(room), "node_modules")
3070
- };
3071
- const spawnCmd = spawn("node", [scriptPath], {
3072
- env,
3073
- cwd: sessionDir
3074
- });
3075
- timeoutId = setTimeout(() => {
3076
- spawnCmd.kill();
3077
- error = new Error("Script execution timed out");
3078
- }, MAX_EXECUTION_TIME);
3079
- Socket.emit("node-repl:update", { clear: true });
3080
- spawnCmd.stdout.on("data", (data) => {
3081
- const output = data.toString("utf-8");
3082
- Socket.emit("node-repl:update", { msg: output, type: "stdout" });
3083
- result += output;
3084
- });
3085
- spawnCmd.stderr.on("data", (data) => {
3086
- const output = data.toString("utf-8");
3087
- Socket.emit("node-repl:update", { msg: output, type: "stderr" });
3088
- result += output;
3089
- });
3090
- spawnCmd.on("error", (err) => {
3091
- error = err;
3092
- Socket.emit("node-repl:update", { msg: `Error: ${err.message}`, type: "error" });
3093
- });
3094
- spawnCmd.on("close", (code) => {
3095
- clearTimeout(timeoutId);
3096
- Socket.emit("node-repl:update", { close: true });
3097
- try {
3098
- conf.chat[room].result = result;
3099
- conf.chat[room].lastExecution = (/* @__PURE__ */ new Date()).toISOString();
3100
- conf.chat[room].error = error ? error.message : null;
3101
- save();
3102
- } catch (err) {
3103
- console.error("Error saving result:", err);
3104
- }
3105
- try {
3106
- require("fs").rmSync(sessionDir, { recursive: true, force: true });
3107
- } catch (err) {
3108
- console.error("Error cleaning up temporary directory:", err);
3109
- }
3110
- });
3111
- save();
3112
- res.json(sessionId);
3113
- } catch (err) {
3114
- Socket.emit("node-repl:update", {
3115
- msg: `Error: ${err.message}`,
3116
- type: "error",
3117
- clear: true
3118
- });
3119
- res.status(400).json({ error: err.message });
3120
- }
3121
- });
3122
- router.get("/node-repl/rooms", async (req, res) => {
3123
- res.json(Object.keys(conf?.chat || {}));
3124
- });
3125
- router.post("/node-repl/rooms", async (req, res) => {
3126
- const { room } = req.body;
3127
- if (!conf?.chat?.[room]) {
3128
- if (!conf?.chat) conf.chat = {};
3129
- if (!conf?.chat?.[room]) conf.chat[room] = {};
3130
- }
3131
- save();
3132
- res.json(Object.keys(conf?.chat || {}));
3133
- });
3134
- router.delete("/node-repl/rooms/:room", async (req, res) => {
3135
- const { room } = req.params;
3136
- if (conf?.chat?.[room]) {
3137
- delete conf.chat[room];
3138
- await cleanupRoomPackages(room);
3139
- }
3140
- save();
3141
- res.json(Object.keys(conf?.chat || {}));
3142
- });
3143
- router.get("/node-repl/chat/:room", async (req, res) => {
3144
- res.json(conf?.chat?.[req.params.room]);
3145
- });
3146
- router.post("/node-repl/format", async (req, res) => {
3147
- try {
3148
- const { code } = req.body;
3149
- if (!code) {
3150
- throw new Error("No code provided");
3151
- }
3152
- const formatted = await prettier.format(code, {
3153
- parser: "babel",
3154
- semi: true,
3155
- singleQuote: true,
3156
- trailingComma: "es5",
3157
- printWidth: 80,
3158
- tabWidth: 2,
3159
- useTabs: false,
3160
- bracketSpacing: true,
3161
- arrowParens: "avoid"
3162
- });
3163
- res.json({ formatted });
3164
- } catch (err) {
3165
- res.status(400).json({ error: err.message });
3166
- }
3167
- });
3168
- router.post("/node-repl/env", async (req, res) => {
3169
- try {
3170
- const { room, env } = req.body;
3171
- if (!room || !env) {
3172
- throw new Error("Room and environment variables are required");
3173
- }
3174
- if (!conf.chat?.[room]) {
3175
- if (!conf.chat) conf.chat = {};
3176
- if (!conf.chat?.[room]) conf.chat[room] = {};
3177
- }
3178
- conf.chat[room].env = env;
3179
- save();
3180
- res.json({ success: true });
3181
- } catch (err) {
3182
- res.status(400).json({ error: err.message });
3183
- }
3184
- });
3185
- router.get("/node-repl/env/:room", async (req, res) => {
3186
- try {
3187
- const { room } = req.params;
3188
- res.json(conf?.chat?.[room]?.env || {});
3189
- } catch (err) {
3190
- res.status(400).json({ error: err.message });
3191
- }
3192
- });
3193
- router.post("/node-repl/install", async (req, res) => {
3194
- try {
3195
- const { package: packageName, room } = req.body;
3196
- if (!packageName || !room) {
3197
- return res.status(400).json({ error: "Package name and room are required" });
3198
- }
3199
- const npmAvailable = await checkNpmAvailable();
3200
- if (!npmAvailable) {
3201
- return res.status(500).json({
3202
- error: "npm is not available in the system PATH. Please install Node.js and npm first."
3203
- });
3204
- }
3205
- const packageJsonPath = await initRoomPackageJson(room);
3206
- const roomDir = getRoomPackagesDir(room);
3207
- await execAsync(`npm install ${packageName}`, { cwd: roomDir });
3208
- const installedPackageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
3209
- res.json(installedPackageJson.dependencies || {});
3210
- } catch (error) {
3211
- console.error("Error installing package:", error);
3212
- res.status(500).json({ error: error.message });
3213
- }
3214
- });
3215
- router.get("/node-repl/packages/:room", async (req, res) => {
3216
- try {
3217
- const { room } = req.params;
3218
- const packageJsonPath = pathfs.resolve(getRoomPackagesDir(room), "package.json");
3219
- try {
3220
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
3221
- res.json(packageJson.dependencies || {});
3222
- } catch (err) {
3223
- res.json({});
3224
- }
3225
- } catch (error) {
3226
- console.error("Error listing packages:", error);
3227
- res.status(500).json({ error: error.message });
3228
- }
3229
- });
3230
- router.delete("/node-repl/packages/:room/:name", async (req, res) => {
3231
- try {
3232
- const { room, name } = req.params;
3233
- if (!name || !room) {
3234
- return res.status(400).json({ error: "Package name and room are required" });
3235
- }
3236
- const npmAvailable = await checkNpmAvailable();
3237
- if (!npmAvailable) {
3238
- return res.status(500).json({
3239
- error: "npm is not available in the system PATH. Please install Node.js and npm first."
3240
- });
3241
- }
3242
- const roomDir = getRoomPackagesDir(room);
3243
- const packageJsonPath = pathfs.resolve(roomDir, "package.json");
3244
- await execAsync(`npm uninstall ${name}`, { cwd: roomDir });
3245
- const updatedPackageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
3246
- res.json(updatedPackageJson.dependencies || {});
3247
- } catch (error) {
3248
- console.error("Error uninstalling package:", error);
3249
- res.status(500).json({ error: error.message });
3250
- }
3251
- });
3252
- function save() {
3253
- try {
3254
- writeFileSync(confPath, JSON.stringify(conf, null, 2), "utf-8");
3255
- } catch (err) {
3256
- console.error("Error saving configuration:", err);
3257
- }
3258
- }
3259
- return router;
3260
- };
3261
- }
3262
- });
3263
-
3264
- // ../../modules/node-repl/backend/index.js
3265
- var require_backend17 = __commonJS({
3266
- "../../modules/node-repl/backend/index.js"(exports2, module2) {
3267
- "use strict";
3268
- var plugin = {
3269
- enabled: true,
3270
- name: "NodeREPL",
3271
- displayName: "Node REPL",
3272
- description: "Create nodejs scripts for test purposes",
3273
- icon: "fab fa-node",
1487
+ name: "Logs",
1488
+ displayName: "Logs",
1489
+ description: "Show, parse and communicate with logs produced by yours commands",
1490
+ icon: "fas fa-terminal",
3274
1491
  export: null,
3275
- placements: [
3276
- {
3277
- position: "toolbox",
3278
- label: "Node Sandbox",
3279
- icon: "fab fa-node",
3280
- goTo: { path: "/NodeREPL" },
3281
- active: "NodeREPL"
3282
- }
3283
- ],
3284
- order: 6,
3285
- routes: require_routes15()
1492
+ placements: ["service"],
1493
+ order: 1,
1494
+ /**
1495
+ * @param {*} search
1496
+ * @param {import('@runeya/common-typings').Runeya} runeya
1497
+ */
1498
+ finder: (search, runeya) => {
1499
+ const services = runeya.getServices()?.flatMap((s) => s.store?.slice(-300).reverse().map((line) => ({ log: line, service: s })))?.filter(({ log }) => runeya.helpers.searchString(log.raw, search));
1500
+ return [
1501
+ ...services.map((service) => ({
1502
+ icon: "fas fa-terminal",
1503
+ title: service.log.raw,
1504
+ group: "Logs",
1505
+ description: `Log from ${service.service.label}`,
1506
+ secondaryTitle: service.service.label,
1507
+ secondaryDescription: dayjs(service.log.timestamp).format("YYYY-DD-MM HH:mm:ss"),
1508
+ url: { path: `/stack-single/${encodeURIComponent(service.service.label)}`, query: { tab: "Logs" } }
1509
+ }))
1510
+ ];
1511
+ },
1512
+ routes: require_routes6()
3286
1513
  };
3287
1514
  module2.exports = plugin;
3288
1515
  }
@@ -3431,498 +1658,115 @@ var require_Npm = __commonJS({
3431
1658
  this.service = service;
3432
1659
  }
3433
1660
  async isNpm(path) {
3434
- if (path) {
3435
- return existsSync(pathfs.resolve(path?.toString(), "package.json"));
3436
- }
3437
- return null;
3438
- }
3439
- getNpmPaths() {
3440
- return [
3441
- ...this.service.commands.filter((cmd) => cmd.spawnOptions.cwd?.toString()?.trim() && cmd.spawnOptions.cwd !== ".").map((cmd) => replaceEnvs(cmd.spawnOptions.cwd)),
3442
- this.service.getRootPath()
3443
- ].filter((cwd) => this.isNpm(cwd));
3444
- }
3445
- async packageJSON(path) {
3446
- if (path) {
3447
- return JSON.parse(await readFile(pathfs.resolve(path?.toString(), "package.json"), "utf-8"));
3448
- }
3449
- return {};
3450
- }
3451
- async packageLock(path) {
3452
- if (path) {
3453
- return JSON.parse(await readFile(pathfs.resolve(path?.toString(), "package-lock.json"), "utf-8")).catch((err) => {
3454
- console.error(err);
3455
- return {};
3456
- });
3457
- }
3458
- return {};
3459
- }
3460
- /**
3461
- * @returns {Promise<import('./index').Outdated>}
3462
- */
3463
- async outdated(path) {
3464
- const result = await execAsync("npm outdated --json || true", { cwd: path });
3465
- return JSON.parse(result);
3466
- }
3467
- };
3468
- module2.exports = Npm;
3469
- }
3470
- });
3471
-
3472
- // ../../modules/npm/backend/routes.js
3473
- var require_routes16 = __commonJS({
3474
- "../../modules/npm/backend/routes.js"(exports2, module2) {
3475
- "use strict";
3476
- var express = require("express");
3477
- var router = express.Router();
3478
- var Npm = require_Npm();
3479
- module2.exports = (runeya) => {
3480
- const { findService } = runeya;
3481
- router.get("/npm/:service", async (req, res) => {
3482
- const service = findService(req.params.service);
3483
- const npm = new Npm(service);
3484
- const isNpm = await npm.isNpm(req.query.cwd);
3485
- res.json(isNpm);
3486
- });
3487
- router.get("/npm/:service/paths", async (req, res) => {
3488
- const service = findService(req.params.service);
3489
- const npm = new Npm(service);
3490
- const paths = await npm.getNpmPaths();
3491
- res.json(paths);
3492
- });
3493
- router.get("/npm/:service/packagejson", async (req, res) => {
3494
- const service = findService(req.params.service);
3495
- const npm = new Npm(service);
3496
- const packagejson = await npm.packageJSON(req.query.cwd);
3497
- res.json(packagejson);
3498
- });
3499
- router.get("/npm/:service/outdated", async (req, res) => {
3500
- const service = findService(req.params.service);
3501
- const npm = new Npm(service);
3502
- const packagejson = await npm.outdated(req.query.cwd);
3503
- res.json(packagejson);
3504
- });
3505
- return router;
3506
- };
3507
- }
3508
- });
3509
-
3510
- // ../../modules/npm/backend/index.js
3511
- var require_backend18 = __commonJS({
3512
- "../../modules/npm/backend/index.js"(exports2, module2) {
3513
- "use strict";
3514
- var Npm = require_Npm();
3515
- var plugin = {
3516
- enabled: true,
3517
- name: "Npm",
3518
- displayName: "Npm",
3519
- description: "View your dependencies and execute your scripts on a service",
3520
- icon: "fab fa-npm",
3521
- export: Npm,
3522
- placements: ["service"],
3523
- order: 4,
3524
- /**
3525
- *
3526
- * @param {import('../../../servers/server/models/Service')} service
3527
- * @returns
3528
- */
3529
- hidden: async (service) => {
3530
- if (!service) return false;
3531
- const project = new Npm(service);
3532
- const serviceIsNpm = !!project.getNpmPaths().length;
3533
- return !serviceIsNpm;
3534
- },
3535
- routes: require_routes16()
3536
- };
3537
- module2.exports = plugin;
3538
- }
3539
- });
3540
-
3541
- // models/ports.js
3542
- var require_ports = __commonJS({
3543
- "models/ports.js"(exports2, module2) {
3544
- "use strict";
3545
- module2.exports = {
3546
- http: process.env.RUNEYA_HTTP_PORT || 0,
3547
- /** @param {number} port */
3548
- setHttpPort(port) {
3549
- if (!this.http) this.http = port;
3550
- }
3551
- };
3552
- }
3553
- });
3554
-
3555
- // ../../modules/openai/backend/routes.js
3556
- var require_routes17 = __commonJS({
3557
- "../../modules/openai/backend/routes.js"(exports2, module2) {
3558
- "use strict";
3559
- var express = require("express");
3560
- var pathfs = require("path");
3561
- var OpenAIApi = require("openai").OpenAI;
3562
- var {
3563
- existsSync,
3564
- mkdirSync,
3565
- createReadStream,
3566
- writeFileSync,
3567
- readFileSync
3568
- } = require("fs");
3569
- var { encode } = require("gpt-3-encoder");
3570
- var { v4 } = require("uuid");
3571
- var { writeFile, unlink } = require("fs/promises");
3572
- var homedir = require("os").homedir();
3573
- var axios = require("axios").default;
3574
- var PromiseB2 = require("bluebird");
3575
- var ports = require_ports();
3576
- var router = express.Router();
3577
- var confDir = pathfs.resolve(homedir, ".runeya");
3578
- if (!existsSync(confDir)) mkdirSync(confDir);
3579
- var openaiConfPath = pathfs.resolve(confDir, "openaiconf.json");
3580
- if (!existsSync(openaiConfPath)) writeFileSync(openaiConfPath, "{}", "utf-8");
3581
- var openaiStoragePath = pathfs.resolve(confDir, "storage");
3582
- if (!existsSync(openaiStoragePath)) mkdirSync(openaiStoragePath);
3583
- var openaiconf = JSON.parse(readFileSync(openaiConfPath, "utf-8"));
3584
- var openai = process.env.RUNEYA_OPENAI_APIKEY ? new OpenAIApi({
3585
- apiKey: process.env.RUNEYA_OPENAI_APIKEY
3586
- }) : null;
3587
- module2.exports = () => {
3588
- router.get("/openai", async (req, res) => {
3589
- res.json("hello");
3590
- });
3591
- router.get("/openai/image/:id", async (req, res) => {
3592
- res.setHeader("content-type", "image/png");
3593
- res.setHeader("content-disposition", "filename=image.png");
3594
- const path = pathfs.resolve(openaiStoragePath, `${req.params.id}.png`);
3595
- if (existsSync(path)) createReadStream(path).pipe(res);
3596
- else res.status(404).send("file not found");
3597
- });
3598
- router.get("/openai/models", async (req, res) => {
3599
- if (!openai) return res.status(400).send("Openai not initialized");
3600
- const models = await openai.models.list({});
3601
- return res.json(models.data);
3602
- });
3603
- router.post("/openai/tokenize", async (req, res) => {
3604
- const encoded = encode(req.body.data);
3605
- res.json({
3606
- nbTokens: encoded.length,
3607
- price: encoded.length * 2e-3 / 1e3
3608
- });
3609
- });
3610
- router.post("/openai/review", async (req, res) => {
3611
- if (!openai) return res.status(400).send("Openai not initialized");
3612
- const result = await openai.chat.completions.create({
3613
- model: "gpt-3.5-turbo",
3614
- temperature: 0,
3615
- n: 1,
3616
- max_tokens: Infinity,
3617
- messages: [
3618
- { role: "system", content: 'You are a developer for 10 years. You are expert in git and you should write a commit. I gave you a git diff after. Write me a resume of this diff and write me a commit for this diff in this format: "<fix|feat|major>: <your message not exceeding 60 characters>"' },
3619
- { role: "assistant", content: req.body.data }
3620
- ]
3621
- }).catch((err) => {
3622
- console.error(err.response.data);
3623
- return Promise.reject(err);
3624
- });
3625
- return res.json(result.choices[0]?.message?.content || "Cannot respond");
3626
- });
3627
- router.post("/openai/error", async (req, res) => {
3628
- if (!openai) return res.status(400).send("Openai not initialized");
3629
- const result = await openai.chat.completions.create({
3630
- model: "gpt-3.5-turbo",
3631
- temperature: 0,
3632
- n: 1,
3633
- max_tokens: Infinity,
3634
- messages: [
3635
- { role: "system", content: "You are a developer for 20 years. You are expert in it and you should find a solution to this following error. Resume the following error and try to fix it" },
3636
- { role: "assistant", content: req.body.data }
3637
- ]
3638
- }).catch((err) => {
3639
- console.error(err.response.data);
3640
- return Promise.reject(err);
3641
- });
3642
- return res.json(result.choices[0]?.message?.content || "Cannot respond");
3643
- });
3644
- router.post("/openai/chat/:room/image", async (req, res) => {
3645
- if (!openai) return res.status(400).send("Openai not initialized");
3646
- const { message, quality, resolution } = req.body;
3647
- if (!openaiconf?.chat) openaiconf.chat = {};
3648
- if (!openaiconf?.chat?.[req.params.room]) openaiconf.chat[req.params.room] = {};
3649
- if (!openaiconf?.chat?.[req.params.room]?.messages) {
3650
- openaiconf.chat[req.params.room].messages = [
3651
- { role: "system", content: "Tu es un assistant utile." }
3652
- ];
3653
- }
3654
- const messages = openaiconf?.chat[req.params.room]?.messages || [];
3655
- messages.push({
3656
- _id: v4(),
3657
- // @ts-ignore
3658
- role: "user",
3659
- content: message,
3660
- created_at: (/* @__PURE__ */ new Date()).toISOString()
3661
- });
3662
- const response = await openai.images.generate({
3663
- quality,
3664
- model: "dall-e-3",
3665
- prompt: message,
3666
- n: 1,
3667
- size: resolution
3668
- });
3669
- if (response?.data?.[0]?.url) {
3670
- const { url, revised_prompt } = response.data[0];
3671
- const uuid = v4();
3672
- const { data: fileBuffer } = await axios.get(url, {
3673
- responseType: "arraybuffer",
3674
- maxContentLength: Infinity,
3675
- maxBodyLength: Infinity
3676
- });
3677
- await writeFile(pathfs.resolve(openaiStoragePath, `${uuid}.png`), fileBuffer);
3678
- messages.push({
3679
- url: `http://localhost:${ports.http}/openai/image/${uuid}`,
3680
- contentId: uuid,
3681
- revised_prompt,
3682
- _id: v4(),
3683
- created_at: (/* @__PURE__ */ new Date()).toISOString()
3684
- });
3685
- save();
3686
- }
3687
- return res.json(response.data[0].url);
3688
- });
3689
- router.post("/openai/chat/:room", async (req, res) => {
3690
- if (!openai) return res.status(400).send("Openai not initialized");
3691
- const { message, model, temperature } = req.body;
3692
- if (!openaiconf?.chat) openaiconf.chat = {};
3693
- if (!openaiconf?.chat?.[req.params.room]) openaiconf.chat[req.params.room] = {};
3694
- if (!openaiconf?.chat?.[req.params.room]?.messages) {
3695
- openaiconf.chat[req.params.room].messages = [
3696
- { role: "system", content: "Tu es un assistant utile." }
3697
- ];
3698
- }
3699
- const messages = openaiconf?.chat[req.params.room]?.messages || [];
3700
- messages.push({
3701
- _id: v4(),
3702
- // @ts-ignore
3703
- role: "user",
3704
- content: message,
3705
- created_at: (/* @__PURE__ */ new Date()).toISOString()
3706
- });
3707
- const result = await openai.chat.completions.create({
3708
- model: model || "gpt-3.5-turbo",
3709
- temperature: Number.isNaN(+temperature) ? 0 : +temperature,
3710
- n: 1,
3711
- max_tokens: Infinity,
3712
- // @ts-ignore
3713
- messages: messages.filter((f) => f?.content).map((a) => ({ role: a.role || "user", content: a.content || "" })).slice(-15)
3714
- }).catch((err) => Promise.reject(err));
3715
- if (result?.choices?.[0]?.message) {
3716
- const { usage } = result;
3717
- const { message: message2 } = result.choices[0];
3718
- messages.push({
3719
- ...message2,
3720
- ...usage,
3721
- _id: v4(),
3722
- created_at: (/* @__PURE__ */ new Date()).toISOString()
3723
- });
3724
- }
3725
- save();
3726
- return res.json(messages);
3727
- });
3728
- router.get("/openai/rooms", async (req, res) => {
3729
- res.json(Object.keys(openaiconf?.chat || {}));
3730
- });
3731
- router.post("/openai/rooms", async (req, res) => {
3732
- const { room } = req.body;
3733
- if (!openaiconf?.chat?.[room]) {
3734
- if (!openaiconf?.chat) openaiconf.chat = {};
3735
- if (!openaiconf?.chat?.[room]) openaiconf.chat[room] = {};
3736
- }
3737
- save();
3738
- res.json(Object.keys(openaiconf?.chat || {}));
3739
- });
3740
- router.delete("/openai/rooms/:room", async (req, res) => {
3741
- const { room } = req.params;
3742
- if (openaiconf?.chat?.[room]) {
3743
- await PromiseB2.map(openaiconf?.chat?.[room].messages, async (message) => {
3744
- if (message.contentId && existsSync(pathfs.resolve(openaiStoragePath, `${message.contentId}.png`))) {
3745
- await unlink(pathfs.resolve(openaiStoragePath, `${message.contentId}.png`));
3746
- }
3747
- }, { concurrency: 4 });
3748
- delete openaiconf.chat[room];
3749
- }
3750
- save();
3751
- res.json(Object.keys(openaiconf?.chat || {}));
3752
- });
3753
- router.get("/openai/chat/:room", async (req, res) => {
3754
- res.json(openaiconf?.chat?.[req.params.room]?.messages);
3755
- });
3756
- router.post("/openai/apikey", async (req, res) => {
3757
- const { apikey } = req.body;
3758
- process.env.RUNEYA_OPENAI_APIKEY = apikey;
3759
- save();
3760
- openai = process.env.RUNEYA_OPENAI_APIKEY ? new OpenAIApi({
3761
- apiKey: process.env.RUNEYA_OPENAI_APIKEY
3762
- }) : null;
3763
- res.json(true);
3764
- });
3765
- router.get("/openai/ready", async (req, res) => {
3766
- if (!openai) return res.json(false);
3767
- console.log(process.env.RUNEYA_OPENAI_APIKEY, openaiconf?.apikey);
3768
- try {
3769
- const { data } = await openai.models.list({});
3770
- res.json(!!data?.length);
3771
- } catch (error) {
3772
- res.json(false);
3773
- }
3774
- return void 0;
3775
- });
3776
- function save() {
3777
- writeFileSync(openaiConfPath, JSON.stringify(openaiconf), "utf-8");
3778
- }
3779
- return router;
3780
- };
3781
- }
3782
- });
3783
-
3784
- // ../../modules/openai/backend/index.js
3785
- var require_backend19 = __commonJS({
3786
- "../../modules/openai/backend/index.js"(exports2, module2) {
3787
- "use strict";
3788
- var plugin = {
3789
- enabled: true,
3790
- name: "OpenAI",
3791
- displayName: "Open A.I.",
3792
- description: "Just chat with Chat GPT",
3793
- icon: "fas fa-brain",
3794
- export: null,
3795
- placements: [
3796
- {
3797
- position: "toolbox",
3798
- label: "OpenAi",
3799
- icon: "fas fa-brain",
3800
- goTo: { path: "/OpenAI" },
3801
- active: "OpenAI"
3802
- }
3803
- ],
3804
- order: 6,
3805
- routes: require_routes17()
3806
- };
3807
- module2.exports = plugin;
3808
- }
3809
- });
3810
-
3811
- // ../../modules/regex/backend/index.js
3812
- var require_backend20 = __commonJS({
3813
- "../../modules/regex/backend/index.js"(exports2, module2) {
3814
- "use strict";
3815
- var plugin = {
3816
- enabled: true,
3817
- name: "Regex",
3818
- displayName: "Regex",
3819
- description: "Test your regular expression",
3820
- icon: "fas fa-key",
3821
- export: null,
3822
- placements: [
3823
- {
3824
- position: "toolbox",
3825
- label: "Regex",
3826
- icon: "fas fa-key",
3827
- goTo: { path: "/Regex" },
3828
- active: "Regex"
1661
+ if (path) {
1662
+ return existsSync(pathfs.resolve(path?.toString(), "package.json"));
3829
1663
  }
3830
- ],
3831
- order: 6
3832
- };
3833
- module2.exports = plugin;
3834
- }
3835
- });
3836
-
3837
- // ../../modules/sql-beautifier/backend/SQLBeautifier.js
3838
- var require_SQLBeautifier = __commonJS({
3839
- "../../modules/sql-beautifier/backend/SQLBeautifier.js"(exports2, module2) {
3840
- "use strict";
3841
- var sqlFormatter = require("sql-formatter");
3842
- var SQLBeautifier = class {
3843
- /**
3844
- * Beautify SQL query
3845
- * @param {string} sql - The SQL query to beautify
3846
- * @returns {BeautifyResult} The beautified SQL query
3847
- * @throws {Error} If the SQL query is invalid or formatting fails
3848
- */
3849
- beautify(sql) {
3850
- if (!sql || typeof sql !== "string") {
3851
- throw new Error("SQL query must be a non-empty string");
1664
+ return null;
1665
+ }
1666
+ getNpmPaths() {
1667
+ return [
1668
+ ...this.service.commands.filter((cmd) => cmd.spawnOptions.cwd?.toString()?.trim() && cmd.spawnOptions.cwd !== ".").map((cmd) => replaceEnvs(cmd.spawnOptions.cwd)),
1669
+ this.service.getRootPath()
1670
+ ].filter((cwd) => this.isNpm(cwd));
1671
+ }
1672
+ async packageJSON(path) {
1673
+ if (path) {
1674
+ return JSON.parse(await readFile(pathfs.resolve(path?.toString(), "package.json"), "utf-8"));
3852
1675
  }
3853
- try {
3854
- const formattedSQL = sqlFormatter.format(sql);
3855
- return {
3856
- result: formattedSQL
3857
- };
3858
- } catch (error) {
3859
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
3860
- throw new Error(`Failed to beautify SQL: ${errorMessage}`);
1676
+ return {};
1677
+ }
1678
+ async packageLock(path) {
1679
+ if (path) {
1680
+ return JSON.parse(await readFile(pathfs.resolve(path?.toString(), "package-lock.json"), "utf-8")).catch((err) => {
1681
+ console.error(err);
1682
+ return {};
1683
+ });
3861
1684
  }
1685
+ return {};
1686
+ }
1687
+ /**
1688
+ * @returns {Promise<import('./index').Outdated>}
1689
+ */
1690
+ async outdated(path) {
1691
+ const result = await execAsync("npm outdated --json || true", { cwd: path });
1692
+ return JSON.parse(result);
3862
1693
  }
3863
1694
  };
3864
- module2.exports = new SQLBeautifier();
1695
+ module2.exports = Npm;
3865
1696
  }
3866
1697
  });
3867
1698
 
3868
- // ../../modules/sql-beautifier/backend/routes.js
3869
- var require_routes18 = __commonJS({
3870
- "../../modules/sql-beautifier/backend/routes.js"(exports2, module2) {
1699
+ // ../../modules/npm/backend/routes.js
1700
+ var require_routes7 = __commonJS({
1701
+ "../../modules/npm/backend/routes.js"(exports2, module2) {
3871
1702
  "use strict";
3872
1703
  var express = require("express");
3873
- var beautifier = require_SQLBeautifier();
3874
- function routes(runeya) {
3875
- const router = express.Router();
3876
- router.post("/sqlbeautifier/beautify", (req, res) => {
3877
- const { sql } = req.body;
3878
- if (!sql || typeof sql !== "string") {
3879
- return res.status(400).json({
3880
- error: "SQL query must be a non-empty string"
3881
- });
3882
- }
3883
- try {
3884
- const result = beautifier.beautify(sql);
3885
- res.json(result);
3886
- } catch (error) {
3887
- const errorMessage = error instanceof Error ? error.message : "An unknown error occurred while beautifying SQL";
3888
- res.status(500).json({ error: errorMessage });
3889
- }
1704
+ var router = express.Router();
1705
+ var Npm = require_Npm();
1706
+ module2.exports = (runeya) => {
1707
+ const { findService } = runeya;
1708
+ router.get("/npm/:service", async (req, res) => {
1709
+ const service = findService(req.params.service);
1710
+ const npm = new Npm(service);
1711
+ const isNpm = await npm.isNpm(req.query.cwd);
1712
+ res.json(isNpm);
1713
+ });
1714
+ router.get("/npm/:service/paths", async (req, res) => {
1715
+ const service = findService(req.params.service);
1716
+ const npm = new Npm(service);
1717
+ const paths = await npm.getNpmPaths();
1718
+ res.json(paths);
1719
+ });
1720
+ router.get("/npm/:service/packagejson", async (req, res) => {
1721
+ const service = findService(req.params.service);
1722
+ const npm = new Npm(service);
1723
+ const packagejson = await npm.packageJSON(req.query.cwd);
1724
+ res.json(packagejson);
1725
+ });
1726
+ router.get("/npm/:service/outdated", async (req, res) => {
1727
+ const service = findService(req.params.service);
1728
+ const npm = new Npm(service);
1729
+ const packagejson = await npm.outdated(req.query.cwd);
1730
+ res.json(packagejson);
3890
1731
  });
3891
1732
  return router;
3892
- }
3893
- module2.exports = routes;
1733
+ };
3894
1734
  }
3895
1735
  });
3896
1736
 
3897
- // ../../modules/sql-beautifier/backend/index.js
3898
- var require_backend21 = __commonJS({
3899
- "../../modules/sql-beautifier/backend/index.js"(exports2, module2) {
1737
+ // ../../modules/npm/backend/index.js
1738
+ var require_backend8 = __commonJS({
1739
+ "../../modules/npm/backend/index.js"(exports2, module2) {
3900
1740
  "use strict";
1741
+ var Npm = require_Npm();
3901
1742
  var plugin = {
3902
1743
  enabled: true,
3903
- name: "sqlbeautifier",
3904
- displayName: "SQL Beautifier",
3905
- description: "Format and beautify SQL queries with syntax highlighting and real-time updates",
3906
- icon: "fas fa-database",
3907
- order: 8,
3908
- export: require_SQLBeautifier(),
3909
- routes: require_routes18(),
3910
- placements: [
3911
- {
3912
- position: "toolbox",
3913
- label: "SQL Beautifier",
3914
- icon: "fas fa-database",
3915
- goTo: { path: "/SQLBeautifier" },
3916
- active: "SQLBeautifier"
3917
- }
3918
- ]
1744
+ name: "Npm",
1745
+ displayName: "Npm",
1746
+ description: "View your dependencies and execute your scripts on a service",
1747
+ icon: "fab fa-npm",
1748
+ export: Npm,
1749
+ placements: ["service"],
1750
+ order: 4,
1751
+ /**
1752
+ *
1753
+ * @param {import('../../../servers/server/models/Service')} service
1754
+ * @returns
1755
+ */
1756
+ hidden: async (service) => {
1757
+ if (!service) return false;
1758
+ const project = new Npm(service);
1759
+ const serviceIsNpm = !!project.getNpmPaths().length;
1760
+ return !serviceIsNpm;
1761
+ },
1762
+ routes: require_routes7()
3919
1763
  };
3920
1764
  module2.exports = plugin;
3921
1765
  }
3922
1766
  });
3923
1767
 
3924
1768
  // ../../modules/toolbox/backend/index.js
3925
- var require_backend22 = __commonJS({
1769
+ var require_backend9 = __commonJS({
3926
1770
  "../../modules/toolbox/backend/index.js"(exports2, module2) {
3927
1771
  "use strict";
3928
1772
  var plugin = {
@@ -3945,81 +1789,8 @@ var require_backend22 = __commonJS({
3945
1789
  }
3946
1790
  });
3947
1791
 
3948
- // ../../modules/uuid/backend/UUID.js
3949
- var require_UUID = __commonJS({
3950
- "../../modules/uuid/backend/UUID.js"(exports2, module2) {
3951
- "use strict";
3952
- var { v4 } = require("uuid");
3953
- var UUID = (runeya) => ({
3954
- generate: ({ count = 1, noDash = false, uppercase = false } = {}) => {
3955
- const uuids = Array(count).fill().map(() => {
3956
- let uuid = v4();
3957
- if (noDash) {
3958
- uuid = uuid.replace(/-/g, "");
3959
- }
3960
- if (uppercase) {
3961
- uuid = uuid.toUpperCase();
3962
- }
3963
- return uuid;
3964
- });
3965
- return count === 1 ? uuids[0] : uuids;
3966
- }
3967
- });
3968
- module2.exports = UUID;
3969
- }
3970
- });
3971
-
3972
- // ../../modules/uuid/backend/routes.js
3973
- var require_routes19 = __commonJS({
3974
- "../../modules/uuid/backend/routes.js"(exports2, module2) {
3975
- "use strict";
3976
- var express = require("express");
3977
- var router = express.Router();
3978
- var UUID = require_UUID();
3979
- module2.exports = (runeya) => {
3980
- const uuid = UUID(runeya);
3981
- router.get("/uuid/", async (req, res) => {
3982
- const { count, noDash, uppercase } = req.query;
3983
- res.json(uuid.generate({
3984
- count: count ? parseInt(count, 10) : void 0,
3985
- noDash: noDash === "true",
3986
- uppercase: uppercase === "true"
3987
- }));
3988
- });
3989
- return router;
3990
- };
3991
- }
3992
- });
3993
-
3994
- // ../../modules/uuid/backend/index.js
3995
- var require_backend23 = __commonJS({
3996
- "../../modules/uuid/backend/index.js"(exports2, module2) {
3997
- "use strict";
3998
- var plugin = {
3999
- enabled: true,
4000
- name: "UUID",
4001
- displayName: "UUID",
4002
- description: "Generate an UUID",
4003
- icon: "fas fa-random",
4004
- placements: [
4005
- {
4006
- position: "toolbox",
4007
- label: "UUID",
4008
- icon: "fas fa-random",
4009
- goTo: { path: "/UUID" },
4010
- active: "UUID"
4011
- }
4012
- ],
4013
- export: require_UUID(),
4014
- order: 6,
4015
- routes: require_routes19()
4016
- };
4017
- module2.exports = plugin;
4018
- }
4019
- });
4020
-
4021
1792
  // ../../modules/help/backend/index.js
4022
- var require_backend24 = __commonJS({
1793
+ var require_backend10 = __commonJS({
4023
1794
  "../../modules/help/backend/index.js"(exports2, module2) {
4024
1795
  "use strict";
4025
1796
  var plugin = {
@@ -4043,7 +1814,7 @@ var require_backend24 = __commonJS({
4043
1814
  });
4044
1815
 
4045
1816
  // ../../modules/openapi/backend/routes.js
4046
- var require_routes20 = __commonJS({
1817
+ var require_routes8 = __commonJS({
4047
1818
  "../../modules/openapi/backend/routes.js"(exports2, module2) {
4048
1819
  "use strict";
4049
1820
  var express = require("express");
@@ -4060,7 +1831,7 @@ var require_routes20 = __commonJS({
4060
1831
  });
4061
1832
 
4062
1833
  // ../../modules/openapi/backend/index.js
4063
- var require_backend25 = __commonJS({
1834
+ var require_backend11 = __commonJS({
4064
1835
  "../../modules/openapi/backend/index.js"(exports2, module2) {
4065
1836
  "use strict";
4066
1837
  var plugin = {
@@ -4076,14 +1847,14 @@ var require_backend25 = __commonJS({
4076
1847
  if (!service) return false;
4077
1848
  return !service?.openapiURL;
4078
1849
  },
4079
- routes: require_routes20()
1850
+ routes: require_routes8()
4080
1851
  };
4081
1852
  module2.exports = plugin;
4082
1853
  }
4083
1854
  });
4084
1855
 
4085
1856
  // ../../modules/vscode/backend/routes.js
4086
- var require_routes21 = __commonJS({
1857
+ var require_routes9 = __commonJS({
4087
1858
  "../../modules/vscode/backend/routes.js"(exports2, module2) {
4088
1859
  "use strict";
4089
1860
  var express = require("express");
@@ -4172,7 +1943,7 @@ var require_routes21 = __commonJS({
4172
1943
  });
4173
1944
 
4174
1945
  // ../../modules/vscode/backend/index.js
4175
- var require_backend26 = __commonJS({
1946
+ var require_backend12 = __commonJS({
4176
1947
  "../../modules/vscode/backend/index.js"(exports2, module2) {
4177
1948
  "use strict";
4178
1949
  var commandExists = require("command-exists");
@@ -4192,14 +1963,14 @@ var require_backend26 = __commonJS({
4192
1963
  active: "Vscode"
4193
1964
  }],
4194
1965
  hidden: () => commandExists("code").then(() => false).catch(() => true),
4195
- routes: require_routes21()
1966
+ routes: require_routes9()
4196
1967
  };
4197
1968
  module2.exports = plugin;
4198
1969
  }
4199
1970
  });
4200
1971
 
4201
1972
  // ../../modules/docker/backend/routes.js
4202
- var require_routes22 = __commonJS({
1973
+ var require_routes10 = __commonJS({
4203
1974
  "../../modules/docker/backend/routes.js"(exports2, module2) {
4204
1975
  "use strict";
4205
1976
  var express = require("express");
@@ -4247,7 +2018,7 @@ var require_routes22 = __commonJS({
4247
2018
  });
4248
2019
 
4249
2020
  // ../../modules/docker/backend/index.js
4250
- var require_backend27 = __commonJS({
2021
+ var require_backend13 = __commonJS({
4251
2022
  "../../modules/docker/backend/index.js"(exports2, module2) {
4252
2023
  "use strict";
4253
2024
  var plugin = {
@@ -4264,7 +2035,7 @@ var require_backend27 = __commonJS({
4264
2035
  if (!service?.container) return true;
4265
2036
  return !service.container.enabled;
4266
2037
  },
4267
- routes: require_routes22()
2038
+ routes: require_routes10()
4268
2039
  };
4269
2040
  module2.exports = plugin;
4270
2041
  }
@@ -4479,6 +2250,7 @@ var require_src6 = __commonJS({
4479
2250
  * baseUrl?: string,
4480
2251
  * helmetConf?: import('helmet').HelmetOptions | null,
4481
2252
  * corsConf?: import('cors').CorsOptions,
2253
+ * authApi?: (app: import('express').Express) => any,
4482
2254
  * beforeAll?: ({app, server}) => any,
4483
2255
  * afterAll?: () => any,
4484
2256
  * socket?: boolean,
@@ -4516,7 +2288,9 @@ var require_src6 = __commonJS({
4516
2288
  socket = false,
4517
2289
  apiPrefix = "/api",
4518
2290
  bodyLimit = "50mb",
4519
- healthPath = apiPrefix
2291
+ healthPath = apiPrefix,
2292
+ authApi = (app) => {
2293
+ }
4520
2294
  }) {
4521
2295
  const pkgJSONPath = pathfs.resolve(baseUrl, "package.json");
4522
2296
  const isPkgJSONExists = fs.existsSync(pkgJSONPath);
@@ -4537,6 +2311,7 @@ var require_src6 = __commonJS({
4537
2311
  }
4538
2312
  console.log("Enable cors...");
4539
2313
  app.use(cors(corsConf));
2314
+ await authApi(app);
4540
2315
  app.options("*", (req, res, next) => {
4541
2316
  res.setHeader("Access-Control-Allow-Credentials", "true");
4542
2317
  next();
@@ -4564,21 +2339,6 @@ var require_src6 = __commonJS({
4564
2339
  app.get("/", (req, res) => res.json({ appName, appVersion }));
4565
2340
  }
4566
2341
  afterControllers?.({ server, app });
4567
- if (process.env.NODE_ENV === "HFBXdZMJxLyJoua28asEaxRixJ6LriR7FnRzX6pwA7pFjZ") {
4568
- const createProxyMiddleware = require("http-proxy-middleware").createProxyMiddleware;
4569
- app.use("/", createProxyMiddleware({
4570
- target: "http://127.0.0.1:5173",
4571
- changeOrigin: false,
4572
- ws: true
4573
- }));
4574
- server.on("upgrade", (req, res) => {
4575
- if (req.url === "/") {
4576
- proxy.ws(req, res, {
4577
- target: "ws://127.0.0.1:5173"
4578
- });
4579
- }
4580
- });
4581
- }
4582
2342
  console.log("Enable error handling...");
4583
2343
  app.use(require_src4()());
4584
2344
  console.log("Enable 404 handling...");
@@ -4602,8 +2362,22 @@ var require_src6 = __commonJS({
4602
2362
  }
4603
2363
  });
4604
2364
 
2365
+ // models/ports.js
2366
+ var require_ports = __commonJS({
2367
+ "models/ports.js"(exports2, module2) {
2368
+ "use strict";
2369
+ module2.exports = {
2370
+ http: process.env.RUNEYA_HTTP_PORT || 0,
2371
+ /** @param {number} port */
2372
+ setHttpPort(port) {
2373
+ if (!this.http) this.http = port;
2374
+ }
2375
+ };
2376
+ }
2377
+ });
2378
+
4605
2379
  // ../../modules/workflows/backend/routes.js
4606
- var require_routes23 = __commonJS({
2380
+ var require_routes11 = __commonJS({
4607
2381
  "../../modules/workflows/backend/routes.js"(exports2, module2) {
4608
2382
  "use strict";
4609
2383
  var { express, getServer } = require_src6();
@@ -4710,7 +2484,7 @@ var require_routes23 = __commonJS({
4710
2484
  });
4711
2485
 
4712
2486
  // ../../modules/workflows/backend/index.js
4713
- var require_backend28 = __commonJS({
2487
+ var require_backend14 = __commonJS({
4714
2488
  "../../modules/workflows/backend/index.js"(exports2, module2) {
4715
2489
  "use strict";
4716
2490
  var Workflows = require_Workflows();
@@ -4734,7 +2508,7 @@ var require_backend28 = __commonJS({
4734
2508
  finder: (search, runeya) => {
4735
2509
  return [];
4736
2510
  },
4737
- routes: require_routes23()
2511
+ routes: require_routes11()
4738
2512
  };
4739
2513
  module2.exports = plugin;
4740
2514
  }
@@ -4746,33 +2520,19 @@ var require_plugins = __commonJS({
4746
2520
  "use strict";
4747
2521
  var plugins = {
4748
2522
  bugs: require_backend(),
4749
- base64: require_backend2(),
4750
- configuration: require_backend3(),
4751
- devOps: require_backend4(),
4752
- diff: require_backend5(),
4753
- documentation: require_backend6(),
4754
- finder: require_backend7(),
4755
- git: require_backend8(),
4756
- github: require_backend9(),
4757
- globalScripts: require_backend10(),
4758
- httpClient: require_backend11(),
4759
- jsonFormatter: require_backend12(),
4760
- jwt: require_backend13(),
4761
- kanban: require_backend14(),
4762
- logs: require_backend15(),
4763
- mongo: require_backend16(),
4764
- nodeRepl: require_backend17(),
4765
- npm: require_backend18(),
4766
- openai: require_backend19(),
4767
- regex: require_backend20(),
4768
- sqlBeautifier: require_backend21(),
4769
- toolbox: require_backend22(),
4770
- uuid: require_backend23(),
4771
- help: require_backend24(),
4772
- openapi: require_backend25(),
4773
- vscode: require_backend26(),
4774
- docker: require_backend27(),
4775
- nodered: require_backend28()
2523
+ configuration: require_backend2(),
2524
+ documentation: require_backend3(),
2525
+ finder: require_backend4(),
2526
+ git: require_backend5(),
2527
+ github: require_backend6(),
2528
+ logs: require_backend7(),
2529
+ npm: require_backend8(),
2530
+ toolbox: require_backend9(),
2531
+ help: require_backend10(),
2532
+ openapi: require_backend11(),
2533
+ vscode: require_backend12(),
2534
+ docker: require_backend13(),
2535
+ nodered: require_backend14()
4776
2536
  };
4777
2537
  module2.exports = Object.keys(plugins).reduce((acc, key) => {
4778
2538
  if (plugins[key].enabled) acc[key] = plugins[key];
@@ -6198,9 +3958,25 @@ var require_plugins2 = __commonJS({
6198
3958
  "use strict";
6199
3959
  var plugins = require_plugins();
6200
3960
  var Stack = require_stack();
3961
+ var { default: axios } = require("axios");
3962
+ var { tmpdir } = require("os");
3963
+ var path = require("path");
3964
+ var { writeFileSync, existsSync } = require("fs");
3965
+ var { writeFile, mkdir, readFile, cp, rm, readdir } = require("fs/promises");
3966
+ var dbs2 = require_dbs();
3967
+ var HTTPError = require_src2();
3968
+ var args2 = require_args();
3969
+ var tar = require("tar");
3970
+ var dbConfig = dbs2.getDb("plugins", { encrypted: false, defaultData: [] });
3971
+ var { sockets } = require_src();
3972
+ var stack = require_stack();
3973
+ var chokidar = require("chokidar");
3974
+ var debounce = require("debounce");
6201
3975
  var routes = [];
6202
3976
  var forService = [];
6203
3977
  var allPlugins = {};
3978
+ var loadedPlugins = {};
3979
+ var themes = {};
6204
3980
  Object.keys(plugins).map((key) => plugins[
6205
3981
  /** @type {keyof (typeof plugins)} */
6206
3982
  key
@@ -6225,7 +4001,248 @@ var require_plugins2 = __commonJS({
6225
4001
  });
6226
4002
  return plugin;
6227
4003
  });
4004
+ async function install(remotePath, force = false) {
4005
+ const rootPath = args2.rootPath;
4006
+ if (!existsSync(rootPath)) await mkdir(rootPath, { recursive: true });
4007
+ const runeyaPath = path.resolve(rootPath, ".runeya");
4008
+ if (!existsSync(runeyaPath)) await mkdir(runeyaPath, { recursive: true });
4009
+ const pluginsPath = path.resolve(runeyaPath, "plugins");
4010
+ if (!existsSync(pluginsPath)) await mkdir(pluginsPath, { recursive: true });
4011
+ const packageTmpPath = path.resolve(tmpdir(), `runeya-plugin-${Date.now()}`);
4012
+ if (!existsSync(packageTmpPath)) await mkdir(packageTmpPath, { recursive: true });
4013
+ const packageTmpFilePath = `${packageTmpPath}.tar.gz`;
4014
+ const { data } = await axios.get(remotePath, { responseType: "arraybuffer" });
4015
+ await writeFile(packageTmpFilePath, data);
4016
+ await tar.extract({ file: packageTmpFilePath, cwd: packageTmpPath });
4017
+ const config = JSON.parse(await readFile(path.join(packageTmpPath, "package.json"), "utf8"));
4018
+ const plugin = await getInstalledPlugin(config.name, config.version);
4019
+ console.log(config.version);
4020
+ if (plugin && !force) {
4021
+ throw new HTTPError("Plugin already installed", "400.68746854743512");
4022
+ }
4023
+ await dbConfig.alasql.delete(`name='${config.name}'`);
4024
+ const diskPath = path.resolve(pluginsPath, config.name);
4025
+ if (existsSync(diskPath)) await rm(diskPath, { recursive: true, force: true });
4026
+ await cp(path.resolve(packageTmpPath), diskPath, { recursive: true });
4027
+ await dbConfig.alasql.insertOne({
4028
+ name: config.name,
4029
+ version: config.version,
4030
+ diskPath,
4031
+ config,
4032
+ remotePath
4033
+ });
4034
+ await loadPlugin(config.name);
4035
+ sockets.emit("plugins:installed", {
4036
+ name: config.name,
4037
+ version: config.version,
4038
+ diskPath,
4039
+ config,
4040
+ remotePath
4041
+ });
4042
+ }
4043
+ async function getInstalledPlugins() {
4044
+ const installedPlugins = await dbConfig.alasql.simpleSelect({});
4045
+ if (process.env.NODE_ENV === "HFBXdZMJxLyJoua28asEaxRixJ6LriR7FnRzX6pwA7pFjZ") {
4046
+ const pluginsPath = path.resolve(__dirname, "../../../plugins");
4047
+ const pluginsDir = await readdir(pluginsPath);
4048
+ await Promise.all(pluginsDir.map(async (pluginDirName) => {
4049
+ const pluginPath = path.resolve(pluginsPath, pluginDirName);
4050
+ const packageJsonPath = path.resolve(pluginPath, "package.json");
4051
+ const config = JSON.parse(await readFile(packageJsonPath, "utf8"));
4052
+ installedPlugins.push({
4053
+ "name": config.name,
4054
+ "version": "development",
4055
+ "diskPath": pluginPath,
4056
+ "config": {
4057
+ ...config,
4058
+ runeya: {
4059
+ ...config.runeya,
4060
+ entries: {
4061
+ ...config.runeya.entries,
4062
+ front: {
4063
+ ...config.runeya.entries.front,
4064
+ js: "./front/dist/index.umd.js"
4065
+ }
4066
+ }
4067
+ }
4068
+ },
4069
+ "remotePath": "http://127.0.0.1:5469/api/plugins/download/%40runeya%2Fplugins-uuid/1.0.8"
4070
+ });
4071
+ }));
4072
+ }
4073
+ return installedPlugins;
4074
+ }
4075
+ async function getInstalledPlugin(name, version) {
4076
+ const [plugin] = (await getInstalledPlugins()).filter((plugin2) => plugin2.name === name);
4077
+ if (!plugin) throw new HTTPError("Plugin not found", "404.plugin.not.found");
4078
+ if (version && plugin.version !== version) return null;
4079
+ return plugin;
4080
+ }
4081
+ async function getInstalledToolboxPlugins() {
4082
+ const plugins2 = await getInstalledPlugins();
4083
+ const toolboxPlugins = plugins2.filter((plugin) => plugin?.config?.runeya?.toolbox);
4084
+ console.log(JSON.stringify(["runeya", plugins2], (_, v) => typeof v === "function" ? `[func]` : v));
4085
+ return [];
4086
+ }
4087
+ async function uninstall(name) {
4088
+ const [plugin] = await dbConfig.alasql.simpleSelect({ where: `name='${name}'` });
4089
+ if (!plugin) {
4090
+ throw new HTTPError("Plugin not found", "404.plugin.not.found");
4091
+ }
4092
+ if (plugin.diskPath && existsSync(plugin.diskPath)) {
4093
+ await rm(plugin.diskPath, { recursive: true, force: true });
4094
+ }
4095
+ await dbConfig.alasql.delete(`name='${name}'`);
4096
+ sockets.emit("plugins:uninstalled", {
4097
+ name
4098
+ });
4099
+ return { success: true, message: "Plugin uninstalled successfully" };
4100
+ }
4101
+ async function registerRoutes(router) {
4102
+ routes.forEach((route) => router.use(route));
4103
+ router.get("/api/plugins/themes", async (req, res) => {
4104
+ res.json(Object.keys(themes).reduce((acc, theme) => {
4105
+ themes[theme].forEach((t, i) => {
4106
+ acc[theme.replace("@", "").replace("/", "-") + "-" + i] = {
4107
+ ...t,
4108
+ group: theme + "-" + t.group
4109
+ };
4110
+ });
4111
+ return acc;
4112
+ }, {}));
4113
+ });
4114
+ }
4115
+ async function call(pluginName, method, args3) {
4116
+ if (!loadedPlugins[pluginName]) await loadPlugin(pluginName);
4117
+ const loadedPlugin = loadedPlugins[pluginName];
4118
+ if (!loadedPlugin) throw new HTTPError("Plugin not found", "404.plugin.not.found");
4119
+ return loadedPlugin[method](...args3);
4120
+ }
4121
+ function clearPluginCache(pluginPath) {
4122
+ const pluginDir = path.dirname(pluginPath);
4123
+ Object.keys(require.cache).forEach((cachedPath) => {
4124
+ if (cachedPath.startsWith(pluginDir)) {
4125
+ console.log("Clearing cache for:", cachedPath);
4126
+ delete require.cache[cachedPath];
4127
+ }
4128
+ });
4129
+ }
4130
+ async function loadPlugin(pluginName) {
4131
+ const plugin = await getInstalledPlugin(pluginName);
4132
+ let backendPath;
4133
+ let themePath;
4134
+ if (process.env.NODE_ENV === "HFBXdZMJxLyJoua28asEaxRixJ6LriR7FnRzX6pwA7pFjZ" && pluginName.startsWith("@runeya/")) {
4135
+ const pluginPath = path.resolve(__dirname, `../../../plugins/${pluginName.replace("@runeya/plugins-", "")}`);
4136
+ const frontPath = path.resolve(pluginPath, "front");
4137
+ const frontPathDist = path.resolve(`${frontPath}/dist`);
4138
+ backendPath = path.resolve(pluginPath, "backend/index.js");
4139
+ themePath = path.resolve(pluginPath, "theme/index.js");
4140
+ let frontWatcher;
4141
+ if (existsSync(frontPath) && existsSync(frontPathDist) && existsSync(backendPath)) {
4142
+ const debouncedFrontWatcher = debounce(async () => {
4143
+ sockets.emit("plugins:front:building", pluginName);
4144
+ console.log("Front changed", pluginName);
4145
+ }, 1e3);
4146
+ frontWatcher = chokidar.watch(frontPath, { ignored: frontPathDist, ignoreInitial: true }).on("all", debouncedFrontWatcher);
4147
+ }
4148
+ let frontDistWatcher;
4149
+ if (existsSync(frontPathDist)) {
4150
+ const debouncedFrontDistWatcher = debounce(async (a, b, c) => {
4151
+ sockets.emit("plugins:front:changed", pluginName);
4152
+ console.log("Front dist changed", pluginName);
4153
+ }, 1e3);
4154
+ frontDistWatcher = chokidar.watch(frontPathDist, { ignoreInitial: true }).on("all", debouncedFrontDistWatcher);
4155
+ }
4156
+ let backendWatcher;
4157
+ if (existsSync(backendPath)) {
4158
+ const debouncedBackendWatcher = debounce(async () => {
4159
+ await frontWatcher.close();
4160
+ await frontDistWatcher.close();
4161
+ await backendWatcher.close();
4162
+ loadPlugin(pluginName);
4163
+ console.log("Backend changed", pluginName);
4164
+ }, 1e3);
4165
+ backendWatcher = chokidar.watch(path.dirname(backendPath), { ignoreInitial: true }).on("all", debouncedBackendWatcher);
4166
+ } else {
4167
+ backendPath = null;
4168
+ }
4169
+ let themeWatcher;
4170
+ if (existsSync(themePath)) {
4171
+ const debouncedThemeWatcher = debounce(async () => {
4172
+ if (frontWatcher) await frontWatcher.close();
4173
+ if (frontDistWatcher) await frontDistWatcher.close();
4174
+ if (themeWatcher) await themeWatcher.close();
4175
+ loadPlugin(pluginName);
4176
+ console.log("Theme changed", pluginName);
4177
+ }, 1e3);
4178
+ themeWatcher = chokidar.watch(path.dirname(themePath), { ignoreInitial: true }).on("all", debouncedThemeWatcher);
4179
+ } else {
4180
+ themePath = null;
4181
+ }
4182
+ } else {
4183
+ backendPath = path.resolve(args2.rootPath, ".runeya", "plugins", pluginName, plugin.config.runeya.entries.backend);
4184
+ themePath = path.resolve(args2.rootPath, ".runeya", "plugins", pluginName, plugin.config.runeya.entries.theme);
4185
+ }
4186
+ if (backendPath) {
4187
+ clearPluginCache(backendPath);
4188
+ const loadedPlugin = require(backendPath);
4189
+ loadedPlugins[pluginName] = await loadedPlugin(stack, {
4190
+ socket: {
4191
+ emit: (event, ...args3) => {
4192
+ sockets.emit(encodeURIComponent(pluginName) + "-" + event, ...args3);
4193
+ },
4194
+ on: (event, callback) => {
4195
+ sockets.on(encodeURIComponent(pluginName) + "-" + event, callback);
4196
+ },
4197
+ off: (event, callback) => {
4198
+ sockets.off(encodeURIComponent(pluginName) + "-" + event, callback);
4199
+ }
4200
+ }
4201
+ });
4202
+ }
4203
+ if (themePath) {
4204
+ clearPluginCache(themePath);
4205
+ const loadedTheme = require(themePath);
4206
+ themes[pluginName] = await loadedTheme(stack, {
4207
+ socket: {
4208
+ emit: (event, ...args3) => {
4209
+ sockets.emit(encodeURIComponent(pluginName) + "-" + event, ...args3);
4210
+ },
4211
+ on: (event, callback) => {
4212
+ sockets.on(encodeURIComponent(pluginName) + "-" + event, callback);
4213
+ },
4214
+ off: (event, callback) => {
4215
+ sockets.off(encodeURIComponent(pluginName) + "-" + event, callback);
4216
+ }
4217
+ }
4218
+ });
4219
+ }
4220
+ return loadedPlugins[pluginName];
4221
+ }
4222
+ async function frontFile(pluginName) {
4223
+ const plugin = await getInstalledPlugin(pluginName);
4224
+ return await readFile(path.join(plugin.diskPath, plugin.config.runeya.entries.front.js), "utf8");
4225
+ }
4226
+ (async () => {
4227
+ const plugins2 = await getInstalledPlugins();
4228
+ await Promise.all(plugins2.map(async (plugin) => {
4229
+ try {
4230
+ await loadPlugin(plugin.name);
4231
+ console.log("loadedPlugin", plugin.name);
4232
+ } catch (error) {
4233
+ console.error(error);
4234
+ }
4235
+ }));
4236
+ })();
6228
4237
  module2.exports = {
4238
+ install,
4239
+ frontFile,
4240
+ call,
4241
+ uninstall,
4242
+ getInstalledPlugins,
4243
+ getInstalledPlugin,
4244
+ registerRoutes,
4245
+ getInstalledToolboxPlugins,
6229
4246
  forService,
6230
4247
  ...allPlugins,
6231
4248
  routes
@@ -6243,6 +4260,26 @@ var require_plugins3 = __commonJS({
6243
4260
  var { findService } = require_stack();
6244
4261
  var Stack = require_stack();
6245
4262
  var plugins = require_plugins2();
4263
+ var { readFile } = require("fs/promises");
4264
+ var path = require("path");
4265
+ var args2 = require_args();
4266
+ router.get("/", async (req, res) => {
4267
+ res.send(await plugins.getInstalledPlugins());
4268
+ });
4269
+ router.get("/front/:name", async (req, res) => {
4270
+ const plugin = await plugins.getInstalledPlugin(req.params.name);
4271
+ res.send(plugin);
4272
+ });
4273
+ router.post("/install", async (req, res) => {
4274
+ const { url } = req.body;
4275
+ const plugin = await plugins.install(url, req.query.force?.toString() === "true");
4276
+ res.send(plugin);
4277
+ });
4278
+ router.delete("/delete", async (req, res) => {
4279
+ const { name } = req.body;
4280
+ const result = await plugins.uninstall(name);
4281
+ res.send(result);
4282
+ });
6246
4283
  router.get("/services/:service", async (req, res) => {
6247
4284
  const service = findService(req.params.service);
6248
4285
  const services = await PromiseB2.filter(plugins.forService, async (plugin) => plugin.hidden ? !await plugin.hidden(service, Stack, "service") : true);
@@ -6258,6 +4295,15 @@ var require_plugins3 = __commonJS({
6258
4295
  services.sort((a, b) => (a.order || 1e3) - (b.order || 1e3));
6259
4296
  res.send(services);
6260
4297
  });
4298
+ router.get("/:plugin/js", async (req, res) => {
4299
+ const file = await plugins.frontFile(req.params.plugin);
4300
+ res.setHeader("Content-Type", "application/javascript");
4301
+ res.send(file);
4302
+ });
4303
+ router.post("/:plugin/call/:method", async (req, res) => {
4304
+ const result = await plugins.call(req.params.plugin, req.params.method, req.body?.args || []);
4305
+ res.json(result);
4306
+ });
6261
4307
  module2.exports = router;
6262
4308
  }
6263
4309
  });
@@ -6315,7 +4361,7 @@ var require_system = __commonJS({
6315
4361
  }, 500);
6316
4362
  });
6317
4363
  router.get("/proxy-img", async (req, res) => {
6318
- axios({
4364
+ await axios({
6319
4365
  method: "get",
6320
4366
  url: req.query.url,
6321
4367
  responseType: "stream"
@@ -6877,14 +4923,29 @@ var require_editors2 = __commonJS({
6877
4923
  }
6878
4924
  });
6879
4925
 
4926
+ // routes/config.js
4927
+ var require_config = __commonJS({
4928
+ "routes/config.js"(exports2, module2) {
4929
+ "use strict";
4930
+ var { express } = require_src6();
4931
+ var router = express.Router();
4932
+ router.get("/", async (req, res) => {
4933
+ res.send({
4934
+ pluginsUrl: process.env.APP_LANDING_URL ? process.env.APP_LANDING_URL + "/plugins" : "https://runeya.dev/plugins"
4935
+ });
4936
+ });
4937
+ module2.exports = router;
4938
+ }
4939
+ });
4940
+
6880
4941
  // routes/index.js
6881
- var require_routes24 = __commonJS({
4942
+ var require_routes12 = __commonJS({
6882
4943
  "routes/index.js"(exports2, module2) {
6883
4944
  "use strict";
6884
4945
  var { express } = require_src6();
6885
4946
  var router = express.Router();
6886
4947
  var plugins = require_plugins2();
6887
- plugins.routes.forEach((route) => router.use(route));
4948
+ plugins.registerRoutes(router);
6888
4949
  router.use("/plugins", require_plugins3());
6889
4950
  router.use("/system", require_system());
6890
4951
  router.use("/stack", require_stack2());
@@ -6892,6 +4953,7 @@ var require_routes24 = __commonJS({
6892
4953
  router.use("/crypto", require_crypto2());
6893
4954
  router.use("/parsers", require_parsers());
6894
4955
  router.use("/editors", require_editors2());
4956
+ router.use("/config", require_config());
6895
4957
  router.get("/version", async (req, res) => {
6896
4958
  res.send(require_version().version);
6897
4959
  });
@@ -6937,7 +4999,7 @@ var require_app = __commonJS({
6937
4999
  "use strict";
6938
5000
  require("express-async-errors");
6939
5001
  var { express } = require_src6();
6940
- var indexRouter = require_routes24();
5002
+ var indexRouter = require_routes12();
6941
5003
  var { stopCpu } = require_cpu();
6942
5004
  var { stopWatchers } = require_stack();
6943
5005
  var app = express();
@@ -6980,6 +5042,23 @@ var require_server = __commonJS({
6980
5042
  useDefaults: true
6981
5043
  }
6982
5044
  } : null,
5045
+ afterControllers({ server, app }) {
5046
+ if (process.env.NODE_ENV === "HFBXdZMJxLyJoua28asEaxRixJ6LriR7FnRzX6pwA7pFjZ") {
5047
+ const createProxyMiddleware = require("http-proxy-middleware").createProxyMiddleware;
5048
+ app.use("/", createProxyMiddleware({
5049
+ target: "http://127.0.0.1:5173",
5050
+ changeOrigin: false,
5051
+ ws: true
5052
+ }));
5053
+ server.on("upgrade", (req, res) => {
5054
+ if (req.url === "/") {
5055
+ proxy.ws(req, res, {
5056
+ target: "ws://127.0.0.1:5173"
5057
+ });
5058
+ }
5059
+ });
5060
+ }
5061
+ },
6983
5062
  onListening({ server }) {
6984
5063
  const addr = server.address();
6985
5064
  const port = typeof addr === "string" ? addr : addr?.port;