@lordbex/thelounge 4.4.4-blowfish → 4.5.1-blowfish

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 (140) hide show
  1. package/README.md +2 -2
  2. package/dist/defaults/config.js +31 -2
  3. package/dist/package.json +93 -91
  4. package/dist/server/client.js +188 -194
  5. package/dist/server/clientManager.js +65 -63
  6. package/dist/server/command-line/index.js +44 -43
  7. package/dist/server/command-line/install.js +37 -70
  8. package/dist/server/command-line/outdated.js +12 -17
  9. package/dist/server/command-line/start.js +25 -26
  10. package/dist/server/command-line/storage.js +26 -31
  11. package/dist/server/command-line/uninstall.js +16 -23
  12. package/dist/server/command-line/upgrade.js +20 -26
  13. package/dist/server/command-line/users/add.js +33 -40
  14. package/dist/server/command-line/users/edit.js +18 -24
  15. package/dist/server/command-line/users/index.js +12 -16
  16. package/dist/server/command-line/users/list.js +11 -39
  17. package/dist/server/command-line/users/remove.js +16 -22
  18. package/dist/server/command-line/users/reset.js +34 -35
  19. package/dist/server/command-line/utils.js +231 -87
  20. package/dist/server/config.js +61 -52
  21. package/dist/server/helper.js +29 -28
  22. package/dist/server/identification.js +39 -34
  23. package/dist/server/index.js +1 -3
  24. package/dist/server/log.js +19 -16
  25. package/dist/server/models/chan.js +36 -33
  26. package/dist/server/models/msg.js +15 -19
  27. package/dist/server/models/network.js +88 -86
  28. package/dist/server/models/prefix.js +4 -7
  29. package/dist/server/models/user.js +5 -10
  30. package/dist/server/path-helper.js +8 -0
  31. package/dist/server/plugins/auth/ldap.js +177 -112
  32. package/dist/server/plugins/auth/local.js +10 -15
  33. package/dist/server/plugins/auth.js +6 -35
  34. package/dist/server/plugins/changelog.js +30 -27
  35. package/dist/server/plugins/clientCertificate.js +33 -37
  36. package/dist/server/plugins/dev-server.js +15 -21
  37. package/dist/server/plugins/inputs/action.js +9 -14
  38. package/dist/server/plugins/inputs/away.js +1 -3
  39. package/dist/server/plugins/inputs/ban.js +9 -14
  40. package/dist/server/plugins/inputs/blow.js +9 -14
  41. package/dist/server/plugins/inputs/connect.js +5 -10
  42. package/dist/server/plugins/inputs/ctcp.js +7 -12
  43. package/dist/server/plugins/inputs/disconnect.js +1 -3
  44. package/dist/server/plugins/inputs/ignore.js +23 -29
  45. package/dist/server/plugins/inputs/ignorelist.js +12 -18
  46. package/dist/server/plugins/inputs/index.js +8 -34
  47. package/dist/server/plugins/inputs/invite.js +7 -12
  48. package/dist/server/plugins/inputs/kick.js +7 -12
  49. package/dist/server/plugins/inputs/kill.js +1 -3
  50. package/dist/server/plugins/inputs/list.js +1 -3
  51. package/dist/server/plugins/inputs/mode.js +10 -15
  52. package/dist/server/plugins/inputs/msg.js +13 -18
  53. package/dist/server/plugins/inputs/mute.js +9 -15
  54. package/dist/server/plugins/inputs/nick.js +9 -14
  55. package/dist/server/plugins/inputs/notice.js +5 -7
  56. package/dist/server/plugins/inputs/part.js +11 -16
  57. package/dist/server/plugins/inputs/quit.js +7 -13
  58. package/dist/server/plugins/inputs/rainbow.js +55 -0
  59. package/dist/server/plugins/inputs/raw.js +1 -3
  60. package/dist/server/plugins/inputs/rejoin.js +7 -12
  61. package/dist/server/plugins/inputs/topic.js +7 -12
  62. package/dist/server/plugins/inputs/whois.js +1 -3
  63. package/dist/server/plugins/irc-events/away.js +14 -20
  64. package/dist/server/plugins/irc-events/cap.js +16 -22
  65. package/dist/server/plugins/irc-events/chghost.js +14 -13
  66. package/dist/server/plugins/irc-events/connection.js +61 -63
  67. package/dist/server/plugins/irc-events/ctcp.js +22 -28
  68. package/dist/server/plugins/irc-events/error.js +20 -26
  69. package/dist/server/plugins/irc-events/help.js +7 -13
  70. package/dist/server/plugins/irc-events/info.js +7 -13
  71. package/dist/server/plugins/irc-events/invite.js +7 -13
  72. package/dist/server/plugins/irc-events/join.js +30 -27
  73. package/dist/server/plugins/irc-events/kick.js +21 -17
  74. package/dist/server/plugins/irc-events/link.js +75 -96
  75. package/dist/server/plugins/irc-events/list.js +23 -26
  76. package/dist/server/plugins/irc-events/message.js +46 -52
  77. package/dist/server/plugins/irc-events/mode.js +66 -63
  78. package/dist/server/plugins/irc-events/modelist.js +29 -35
  79. package/dist/server/plugins/irc-events/motd.js +10 -16
  80. package/dist/server/plugins/irc-events/names.js +3 -6
  81. package/dist/server/plugins/irc-events/nick.js +26 -23
  82. package/dist/server/plugins/irc-events/part.js +19 -15
  83. package/dist/server/plugins/irc-events/quit.js +17 -14
  84. package/dist/server/plugins/irc-events/sasl.js +9 -15
  85. package/dist/server/plugins/irc-events/spgroups.js +38 -0
  86. package/dist/server/plugins/irc-events/spjoin.js +52 -0
  87. package/dist/server/plugins/irc-events/topic.js +12 -18
  88. package/dist/server/plugins/irc-events/unhandled.js +12 -12
  89. package/dist/server/plugins/irc-events/welcome.js +7 -13
  90. package/dist/server/plugins/irc-events/whois.js +20 -24
  91. package/dist/server/plugins/massEventAggregator.js +214 -0
  92. package/dist/server/plugins/messageStorage/sqlite.js +322 -141
  93. package/dist/server/plugins/messageStorage/text.js +21 -26
  94. package/dist/server/plugins/packages/index.js +105 -74
  95. package/dist/server/plugins/packages/publicClient.js +7 -16
  96. package/dist/server/plugins/packages/themes.js +11 -16
  97. package/dist/server/plugins/storage.js +28 -33
  98. package/dist/server/plugins/sts.js +12 -17
  99. package/dist/server/plugins/uploader.js +40 -43
  100. package/dist/server/plugins/webpush.js +23 -51
  101. package/dist/server/server.js +318 -271
  102. package/dist/server/storageCleaner.js +29 -37
  103. package/dist/server/utils/fish.js +7 -14
  104. package/dist/shared/irc.js +3 -6
  105. package/dist/shared/linkify.js +7 -14
  106. package/dist/shared/types/chan.js +6 -9
  107. package/dist/shared/types/changelog.js +1 -2
  108. package/dist/shared/types/config.js +1 -2
  109. package/dist/shared/types/mention.js +1 -2
  110. package/dist/shared/types/msg.js +3 -5
  111. package/dist/shared/types/network.js +1 -2
  112. package/dist/shared/types/storage.js +1 -2
  113. package/dist/shared/types/user.js +1 -2
  114. package/index.js +14 -10
  115. package/package.json +93 -91
  116. package/public/css/style.css +9 -6
  117. package/public/css/style.css.map +1 -1
  118. package/public/fonts/font-awesome/fa-brands-400.ttf +0 -0
  119. package/public/fonts/font-awesome/fa-brands-400.woff2 +0 -0
  120. package/public/fonts/font-awesome/fa-duotone-900.ttf +0 -0
  121. package/public/fonts/font-awesome/fa-duotone-900.woff2 +0 -0
  122. package/public/fonts/font-awesome/fa-light-300.ttf +0 -0
  123. package/public/fonts/font-awesome/fa-light-300.woff2 +0 -0
  124. package/public/fonts/font-awesome/fa-regular-400.ttf +0 -0
  125. package/public/fonts/font-awesome/fa-regular-400.woff2 +0 -0
  126. package/public/fonts/font-awesome/fa-solid-900.ttf +0 -0
  127. package/public/fonts/font-awesome/fa-solid-900.woff2 +0 -0
  128. package/public/fonts/font-awesome/fa-thin-100.ttf +0 -0
  129. package/public/fonts/font-awesome/fa-thin-100.woff2 +0 -0
  130. package/public/fonts/font-awesome/fa-v4compatibility.ttf +0 -0
  131. package/public/fonts/font-awesome/fa-v4compatibility.woff2 +0 -0
  132. package/public/js/bundle.js +1 -1
  133. package/public/js/bundle.js.map +1 -1
  134. package/public/js/bundle.vendor.js +1 -1
  135. package/public/js/bundle.vendor.js.LICENSE.txt +24 -6
  136. package/public/js/bundle.vendor.js.map +1 -1
  137. package/public/service-worker.js +1 -1
  138. package/public/themes/default.css +1 -1
  139. package/public/themes/morning.css +1 -1
  140. package/dist/webpack.config.js +0 -224
@@ -1,14 +1,9 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
1
  /* eslint-disable @typescript-eslint/restrict-template-expressions */
7
- const promises_1 = __importDefault(require("fs/promises"));
8
- const path_1 = __importDefault(require("path"));
9
- const filenamify_1 = __importDefault(require("filenamify"));
10
- const config_1 = __importDefault(require("../../config"));
11
- const msg_1 = require("../../../shared/types/msg");
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ import filenamify from "filenamify";
5
+ import Config from "../../config.js";
6
+ import { MessageType } from "../../../shared/types/msg.js";
12
7
  class TextFileMessageStorage {
13
8
  isEnabled;
14
9
  username;
@@ -28,9 +23,9 @@ class TextFileMessageStorage {
28
23
  if (!this.isEnabled) {
29
24
  return;
30
25
  }
31
- const logPath = path_1.default.join(config_1.default.getUserLogsPath(), this.username, TextFileMessageStorage.getNetworkFolderName(network));
26
+ const logPath = path.join(Config.getUserLogsPath(), this.username, TextFileMessageStorage.getNetworkFolderName(network));
32
27
  try {
33
- await promises_1.default.mkdir(logPath, { recursive: true });
28
+ await fs.mkdir(logPath, { recursive: true });
34
29
  }
35
30
  catch (e) {
36
31
  throw new Error(`Unable to create logs directory: ${e}`);
@@ -38,47 +33,47 @@ class TextFileMessageStorage {
38
33
  let line = `[${msg.time.toISOString()}] `;
39
34
  // message types from src/models/msg.js
40
35
  switch (msg.type) {
41
- case msg_1.MessageType.ACTION:
36
+ case MessageType.ACTION:
42
37
  // [2014-01-01 00:00:00] * @Arnold is eating cookies
43
38
  line += `* ${msg.from.mode}${msg.from.nick} ${msg.text}`;
44
39
  break;
45
- case msg_1.MessageType.JOIN:
40
+ case MessageType.JOIN:
46
41
  // [2014-01-01 00:00:00] *** Arnold (~arnold@foo.bar) joined
47
42
  line += `*** ${msg.from.nick} (${msg.hostmask}) joined`;
48
43
  break;
49
- case msg_1.MessageType.KICK:
44
+ case MessageType.KICK:
50
45
  // [2014-01-01 00:00:00] *** Arnold was kicked by Bernie (Don't steal my cookies!)
51
46
  line += `*** ${msg.target.nick} was kicked by ${msg.from.nick} (${msg.text})`;
52
47
  break;
53
- case msg_1.MessageType.MESSAGE:
48
+ case MessageType.MESSAGE:
54
49
  // [2014-01-01 00:00:00] <@Arnold> Put that cookie down.. Now!!
55
50
  line += `<${msg.from.mode}${msg.from.nick}> ${msg.text}`;
56
51
  break;
57
- case msg_1.MessageType.MODE:
52
+ case MessageType.MODE:
58
53
  // [2014-01-01 00:00:00] *** Arnold set mode +o Bernie
59
54
  line += `*** ${msg.from.nick} set mode ${msg.text}`;
60
55
  break;
61
- case msg_1.MessageType.NICK:
56
+ case MessageType.NICK:
62
57
  // [2014-01-01 00:00:00] *** Arnold changed nick to Bernie
63
58
  line += `*** ${msg.from.nick} changed nick to ${msg.new_nick}`;
64
59
  break;
65
- case msg_1.MessageType.NOTICE:
60
+ case MessageType.NOTICE:
66
61
  // [2014-01-01 00:00:00] -Arnold- pssst, I have cookies!
67
62
  line += `-${msg.from.nick}- ${msg.text}`;
68
63
  break;
69
- case msg_1.MessageType.PART:
64
+ case MessageType.PART:
70
65
  // [2014-01-01 00:00:00] *** Arnold (~arnold@foo.bar) left (Bye all!)
71
66
  line += `*** ${msg.from.nick} (${msg.hostmask}) left (${msg.text})`;
72
67
  break;
73
- case msg_1.MessageType.QUIT:
68
+ case MessageType.QUIT:
74
69
  // [2014-01-01 00:00:00] *** Arnold (~arnold@foo.bar) quit (Connection reset by peer)
75
70
  line += `*** ${msg.from.nick} (${msg.hostmask}) quit (${msg.text})`;
76
71
  break;
77
- case msg_1.MessageType.CHGHOST:
72
+ case MessageType.CHGHOST:
78
73
  // [2014-01-01 00:00:00] *** Arnold changed host to: new@fancy.host
79
74
  line += `*** ${msg.from.nick} changed host to '${msg.new_ident}@${msg.new_host}'`;
80
75
  break;
81
- case msg_1.MessageType.TOPIC:
76
+ case MessageType.TOPIC:
82
77
  // [2014-01-01 00:00:00] *** Arnold changed topic to: welcome everyone!
83
78
  line += `*** ${msg.from.nick} changed topic to '${msg.text}'`;
84
79
  break;
@@ -88,7 +83,7 @@ class TextFileMessageStorage {
88
83
  }
89
84
  line += "\n";
90
85
  try {
91
- await promises_1.default.appendFile(path_1.default.join(logPath, TextFileMessageStorage.getChannelFileName(channel)), line);
86
+ await fs.appendFile(path.join(logPath, TextFileMessageStorage.getChannelFileName(channel)), line);
92
87
  }
93
88
  catch (e) {
94
89
  throw new Error(`Failed to write user log: ${e}`);
@@ -116,9 +111,9 @@ class TextFileMessageStorage {
116
111
  return `${cleanFilename(channel.name)}.log`;
117
112
  }
118
113
  }
119
- exports.default = TextFileMessageStorage;
114
+ export default TextFileMessageStorage;
120
115
  function cleanFilename(name) {
121
- name = (0, filenamify_1.default)(name, { replacement: "_" });
116
+ name = filenamify(name, { replacement: "_" });
122
117
  name = name.toLowerCase();
123
118
  return name;
124
119
  }
@@ -1,19 +1,15 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const lodash_1 = __importDefault(require("lodash"));
7
- const log_1 = __importDefault(require("../../log"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const path_1 = __importDefault(require("path"));
10
- const semver_1 = __importDefault(require("semver"));
11
- const helper_1 = __importDefault(require("../../helper"));
12
- const config_1 = __importDefault(require("../../config"));
13
- const themes_1 = __importDefault(require("./themes"));
14
- const inputs_1 = __importDefault(require("../inputs"));
15
- const fs_1 = __importDefault(require("fs"));
16
- const utils_1 = __importDefault(require("../../command-line/utils"));
1
+ import _ from "lodash";
2
+ import log from "../../log.js";
3
+ import colors from "chalk";
4
+ import path from "path";
5
+ import semver from "semver";
6
+ import Helper from "../../helper.js";
7
+ import Config from "../../config.js";
8
+ import themes from "./themes.js";
9
+ import inputs from "../inputs/index.js";
10
+ import fs from "fs";
11
+ import Utils from "../../command-line/utils.js";
12
+ import { pathToFileURL } from "url";
17
13
  const packageMap = new Map();
18
14
  const stylesheets = [];
19
15
  const files = [];
@@ -22,12 +18,15 @@ const cache = {
22
18
  outdated: undefined,
23
19
  };
24
20
  let experimentalWarningPrinted = false;
25
- exports.default = {
21
+ let packageWatcher = null;
22
+ export default {
26
23
  getFiles,
27
24
  getStylesheets,
28
25
  getPackage,
29
26
  loadPackages,
30
27
  outdated,
28
+ stopWatching,
29
+ clearPackages,
31
30
  };
32
31
  // TODO: verify binds worked. Used to be 'this' instead of 'packageApis'
33
32
  const packageApis = function (packageInfo) {
@@ -39,18 +38,18 @@ const packageApis = function (packageInfo) {
39
38
  add: addFile.bind(packageApis, packageInfo.packageName),
40
39
  },
41
40
  Commands: {
42
- add: inputs_1.default.addPluginCommand.bind(packageApis, packageInfo),
41
+ add: inputs.addPluginCommand.bind(packageApis, packageInfo),
43
42
  runAsUser: (command, targetId, client) => client.inputLine({ target: targetId, text: command }),
44
43
  },
45
44
  Config: {
46
- getConfig: () => config_1.default.values,
45
+ getConfig: () => Config.values,
47
46
  getPersistentStorageDir: getPersistentStorageDir.bind(packageApis, packageInfo.packageName),
48
47
  },
49
48
  Logger: {
50
- error: (...args) => log_1.default.error(`[${packageInfo.packageName}]`, ...args),
51
- warn: (...args) => log_1.default.warn(`[${packageInfo.packageName}]`, ...args),
52
- info: (...args) => log_1.default.info(`[${packageInfo.packageName}]`, ...args),
53
- debug: (...args) => log_1.default.debug(`[${packageInfo.packageName}]`, ...args),
49
+ error: (...args) => log.error(`[${packageInfo.packageName}]`, ...args),
50
+ warn: (...args) => log.warn(`[${packageInfo.packageName}]`, ...args),
51
+ info: (...args) => log.info(`[${packageInfo.packageName}]`, ...args),
52
+ debug: (...args) => log.debug(`[${packageInfo.packageName}]`, ...args),
54
53
  },
55
54
  };
56
55
  };
@@ -69,43 +68,82 @@ function getFiles() {
69
68
  function getPackage(name) {
70
69
  return packageMap.get(name);
71
70
  }
71
+ function clearPackages() {
72
+ packageMap.clear();
73
+ stylesheets.length = 0;
74
+ files.length = 0;
75
+ experimentalWarningPrinted = false;
76
+ }
72
77
  function getEnabledPackages(packageJson) {
73
78
  try {
74
- const json = JSON.parse(fs_1.default.readFileSync(packageJson, "utf-8"));
79
+ const json = JSON.parse(fs.readFileSync(packageJson, "utf-8"));
75
80
  return Object.keys(json.dependencies);
76
81
  }
77
82
  catch (e) {
78
- log_1.default.error(`Failed to read packages/package.json: ${chalk_1.default.red(e)}`);
83
+ log.error(`Failed to read packages/package.json: ${colors.red(e)}`);
79
84
  }
80
85
  return [];
81
86
  }
82
87
  function getPersistentStorageDir(packageName) {
83
- const dir = path_1.default.join(config_1.default.getPackagesPath(), packageName);
84
- fs_1.default.mkdirSync(dir, { recursive: true }); // we don't care if it already exists or not
88
+ const dir = path.join(Config.getPackagesPath(), packageName);
89
+ fs.mkdirSync(dir, { recursive: true }); // we don't care if it already exists or not
85
90
  return dir;
86
91
  }
87
- function loadPackage(packageName) {
92
+ async function loadPackage(packageName) {
88
93
  let packageInfo;
89
94
  // TODO: type
90
95
  let packageFile;
91
96
  try {
92
- const packagePath = config_1.default.getPackageModulePath(packageName);
93
- packageInfo = JSON.parse(fs_1.default.readFileSync(path_1.default.join(packagePath, "package.json"), "utf-8"));
97
+ const packagePath = Config.getPackageModulePath(packageName);
98
+ packageInfo = JSON.parse(fs.readFileSync(path.join(packagePath, "package.json"), "utf-8"));
94
99
  if (!packageInfo.thelounge) {
95
- throw "'thelounge' is not present in package.json";
100
+ throw new Error("'thelounge' is not present in package.json");
96
101
  }
97
102
  if (packageInfo.thelounge.supports &&
98
- !semver_1.default.satisfies(helper_1.default.getVersionNumber(), packageInfo.thelounge.supports, {
103
+ !semver.satisfies(Helper.getVersionNumber(), packageInfo.thelounge.supports, {
99
104
  includePrerelease: true, // our pre-releases should respect the semver guarantees
100
105
  })) {
101
- throw `v${packageInfo.version} does not support this version of The Lounge. Supports: ${packageInfo.thelounge.supports}`;
106
+ throw new Error(`v${packageInfo.version} does not support this version of The Lounge. Supports: ${packageInfo.thelounge.supports}`);
107
+ }
108
+ // ESM requires importing a file, not a directory
109
+ // Determine the entry point from package.json
110
+ let entryPoint = "index.js";
111
+ if (typeof packageInfo.exports === "string") {
112
+ entryPoint = packageInfo.exports;
113
+ }
114
+ else if (packageInfo.exports && typeof packageInfo.exports === "object") {
115
+ // Handle exports map like { ".": "./index.js" } or { "import": "...", "require": "..." }
116
+ const exportsObj = packageInfo.exports;
117
+ if (typeof exportsObj["."] === "string") {
118
+ entryPoint = exportsObj["."];
119
+ }
120
+ else if (typeof exportsObj.import === "string") {
121
+ entryPoint = exportsObj.import;
122
+ }
123
+ else if (typeof exportsObj.require === "string") {
124
+ entryPoint = exportsObj.require;
125
+ }
126
+ else if (exportsObj["."] && typeof exportsObj["."] === "object") {
127
+ const dotExports = exportsObj["."];
128
+ entryPoint =
129
+ dotExports.import || dotExports.require || dotExports.default || "index.js";
130
+ }
131
+ }
132
+ else if (packageInfo.main) {
133
+ entryPoint = packageInfo.main;
102
134
  }
103
- packageFile = require(packagePath);
135
+ const isJSONImport = entryPoint.endsWith(".json");
136
+ const fullEntryPath = pathToFileURL(path.join(packagePath, entryPoint)).href;
137
+ const imported = isJSONImport
138
+ ? await import(fullEntryPath, { with: { type: "json" } })
139
+ : await import(fullEntryPath);
140
+ // Handle both ESM (direct exports) and CommonJS (wrapped in .default) modules
141
+ packageFile = imported.default || imported;
104
142
  }
105
143
  catch (e) {
106
- log_1.default.error(`Package ${chalk_1.default.bold(packageName)} could not be loaded: ${chalk_1.default.red(e)}`);
144
+ log.error(`Package ${colors.bold(packageName)} could not be loaded: ${colors.red(e)}`);
107
145
  if (e instanceof Error) {
108
- log_1.default.debug(e.stack ? e.stack : e.message);
146
+ log.debug(e.stack ? e.stack : e.message);
109
147
  }
110
148
  return;
111
149
  }
@@ -117,8 +155,8 @@ function loadPackage(packageName) {
117
155
  };
118
156
  packageMap.set(packageName, packageFile);
119
157
  if (packageInfo.type === "theme") {
120
- // @ts-expect-error Argument of type 'PackageInfo' is not assignable to parameter of type 'ThemeModule'.
121
- themes_1.default.addTheme(packageName, packageInfo);
158
+ // PackageInfo includes theme-specific fields when type === "theme"
159
+ themes.addTheme(packageName, packageInfo);
122
160
  if (packageInfo.files) {
123
161
  packageInfo.files.forEach((file) => addFile(packageName, file));
124
162
  }
@@ -126,68 +164,61 @@ function loadPackage(packageName) {
126
164
  if (packageFile.onServerStart) {
127
165
  packageFile.onServerStart(packageApis(packageInfo));
128
166
  }
129
- log_1.default.info(`Package ${chalk_1.default.bold(packageName)} ${chalk_1.default.green("v" + version)} loaded`);
167
+ log.info(`Package ${colors.bold(packageName)} ${colors.green("v" + version)} loaded`);
130
168
  if (packageInfo.type !== "theme" && !experimentalWarningPrinted) {
131
169
  experimentalWarningPrinted = true;
132
- log_1.default.info("There are packages using the experimental plugin API. " +
170
+ log.info("There are packages using the experimental plugin API. " +
133
171
  "Be aware that this API is not yet stable and may change in future The Lounge releases.");
134
172
  }
135
173
  }
136
- function loadPackages() {
137
- const packageJson = path_1.default.join(config_1.default.getPackagesPath(), "package.json");
174
+ async function loadPackages() {
175
+ const packageJson = path.join(Config.getPackagesPath(), "package.json");
138
176
  const packages = getEnabledPackages(packageJson);
139
- packages.forEach(loadPackage);
177
+ await Promise.all(packages.map((pkg) => loadPackage(pkg)));
140
178
  watchPackages(packageJson);
141
179
  }
142
180
  function watchPackages(packageJson) {
143
- fs_1.default.watch(packageJson, {
181
+ packageWatcher = fs.watch(packageJson, {
144
182
  persistent: false,
145
- }, lodash_1.default.debounce(() => {
146
- const updated = getEnabledPackages(packageJson);
147
- for (const packageName of updated) {
148
- if (packageMap.has(packageName)) {
149
- continue;
183
+ }, _.debounce(() => {
184
+ void (async () => {
185
+ const updated = getEnabledPackages(packageJson);
186
+ for (const packageName of updated) {
187
+ if (packageMap.has(packageName)) {
188
+ continue;
189
+ }
190
+ await loadPackage(packageName);
150
191
  }
151
- loadPackage(packageName);
152
- }
192
+ })();
153
193
  }, 1000, { maxWait: 10000 }));
154
194
  }
195
+ function stopWatching() {
196
+ if (packageWatcher) {
197
+ packageWatcher.close();
198
+ packageWatcher = null;
199
+ }
200
+ }
155
201
  async function outdated(cacheTimeout = TIME_TO_LIVE) {
156
202
  if (cache.outdated !== undefined) {
157
203
  return cache.outdated;
158
204
  }
159
205
  // Get paths to the location of packages directory
160
- const packagesPath = config_1.default.getPackagesPath();
161
- const packagesConfig = path_1.default.join(packagesPath, "package.json");
162
- const packagesList = JSON.parse(fs_1.default.readFileSync(packagesConfig, "utf-8")).dependencies;
163
- const argsList = [
164
- "outdated",
165
- "--latest",
166
- "--json",
167
- "--production",
168
- "--ignore-scripts",
169
- "--non-interactive",
170
- "--cwd",
171
- packagesPath,
172
- ];
206
+ const packagesPath = Config.getPackagesPath();
207
+ const packagesConfig = path.join(packagesPath, "package.json");
208
+ const packagesList = JSON.parse(fs.readFileSync(packagesConfig, "utf-8")).dependencies;
173
209
  // Check if the configuration file exists
174
210
  if (!Object.entries(packagesList).length) {
175
211
  // CLI calls outdated with zero TTL, so we can print the warning there
176
212
  if (!cacheTimeout) {
177
- log_1.default.warn("There are no packages installed.");
213
+ log.warn("There are no packages installed.");
178
214
  }
179
215
  return false;
180
216
  }
181
- const command = argsList.shift();
182
- const params = argsList;
183
- if (!command) {
184
- return;
185
- }
186
- // If we get an error from calling outdated and the code isn't 0, then there are no outdated packages
187
- // TODO: was (...argsList), verify this works
188
- await utils_1.default.executeYarnCommand(command, ...params)
217
+ // npm outdated returns exit code 1 when packages are outdated, 0 when all up to date
218
+ // executeYarnCommand handles this mapping
219
+ await Utils.executeYarnCommand("outdated")
189
220
  .then(() => updateOutdated(false))
190
- .catch((code) => updateOutdated(code !== 0));
221
+ .catch(() => updateOutdated(true));
191
222
  if (cacheTimeout > 0) {
192
223
  setTimeout(() => {
193
224
  delete cache.outdated;
@@ -1,11 +1,6 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const msg_1 = __importDefault(require("../../models/msg"));
7
- const msg_2 = require("../../../shared/types/msg");
8
- class PublicClient {
1
+ import Msg from "../../models/msg.js";
2
+ import { MessageType } from "../../../shared/types/msg.js";
3
+ export default class PublicClient {
9
4
  client;
10
5
  packageInfo;
11
6
  constructor(client, packageInfo) {
@@ -33,11 +28,8 @@ class PublicClient {
33
28
  * @param {String} event - Name of the event, must be something the browser will recognise
34
29
  * @param {Object} data - Body of the event, can be anything, but will need to be properly interpreted by the client
35
30
  */
36
- // FIXME: this is utterly bonkers
37
- // This needs to get wrapped into its own, typed plugin event
38
- // Plus it is completely insane to let a plugin inject arbitrary events like that
39
- sendToBrowser(event, data) {
40
- this.client.emit(event, data);
31
+ sendToBrowser(event, ...args) {
32
+ this.client.emit(event, ...args);
41
33
  }
42
34
  /**
43
35
  *
@@ -53,8 +45,8 @@ class PublicClient {
53
45
  * @param {Chan} chan the channel to send the message to
54
46
  */
55
47
  sendMessage(text, chan) {
56
- chan.pushMessage(this.client, new msg_1.default({
57
- type: msg_2.MessageType.PLUGIN,
48
+ chan.pushMessage(this.client, new Msg({
49
+ type: MessageType.PLUGIN,
58
50
  text: text,
59
51
  from: {
60
52
  nick: this.packageInfo.name || this.packageInfo.packageName,
@@ -63,4 +55,3 @@ class PublicClient {
63
55
  }));
64
56
  }
65
57
  }
66
- exports.default = PublicClient;
@@ -1,22 +1,17 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- const lodash_1 = __importDefault(require("lodash"));
9
- const config_1 = __importDefault(require("../../config"));
10
- const utils_1 = __importDefault(require("../../command-line/utils"));
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import _ from "lodash";
4
+ import Config from "../../config.js";
5
+ import Utils from "../../command-line/utils.js";
11
6
  const themes = new Map();
12
- exports.default = {
7
+ export default {
13
8
  addTheme,
14
9
  getAll,
15
10
  getByName,
16
11
  loadLocalThemes,
17
12
  };
18
13
  function loadLocalThemes() {
19
- const builtInThemes = fs_1.default.readdirSync(utils_1.default.getFileFromRelativeToRoot("public", "themes"));
14
+ const builtInThemes = fs.readdirSync(Utils.getFileFromRelativeToRoot("public", "themes"));
20
15
  builtInThemes
21
16
  .filter((theme) => theme.endsWith(".css"))
22
17
  .map(makeLocalThemeObject)
@@ -31,9 +26,9 @@ function addTheme(packageName, packageObject) {
31
26
  function getAll() {
32
27
  const filteredThemes = [];
33
28
  for (const theme of themes.values()) {
34
- filteredThemes.push(lodash_1.default.pick(theme, ["displayName", "name", "themeColor"]));
29
+ filteredThemes.push(_.pick(theme, ["displayName", "name", "themeColor"]));
35
30
  }
36
- return lodash_1.default.sortBy(filteredThemes, "displayName");
31
+ return _.sortBy(filteredThemes, "displayName");
37
32
  }
38
33
  function getByName(name) {
39
34
  return themes.get(name);
@@ -51,10 +46,10 @@ function makePackageThemeObject(moduleName, module) {
51
46
  return;
52
47
  }
53
48
  const themeColor = /^#[0-9A-F]{6}$/i.test(module.themeColor) ? module.themeColor : null;
54
- const modulePath = config_1.default.getPackageModulePath(moduleName);
49
+ const modulePath = Config.getPackageModulePath(moduleName);
55
50
  return {
56
51
  displayName: module.name || moduleName,
57
- filename: path_1.default.join(modulePath, module.css),
52
+ filename: path.join(modulePath, module.css),
58
53
  name: encodeURIComponent(moduleName),
59
54
  themeColor: themeColor,
60
55
  };
@@ -1,13 +1,8 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const log_1 = __importDefault(require("../log"));
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const crypto_1 = __importDefault(require("crypto"));
10
- const config_1 = __importDefault(require("../config"));
1
+ import log from "../log.js";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import crypto from "crypto";
5
+ import Config from "../config.js";
11
6
  class Storage {
12
7
  references;
13
8
  constructor() {
@@ -17,55 +12,55 @@ class Storage {
17
12
  // Ensures that a directory is empty.
18
13
  // Deletes directory contents if the directory is not empty.
19
14
  // If the directory does not exist, it is created.
20
- const dir = config_1.default.getStoragePath();
15
+ const dir = Config.getStoragePath();
21
16
  let items;
22
17
  try {
23
- items = fs_1.default.readdirSync(dir);
18
+ items = fs.readdirSync(dir);
24
19
  }
25
- catch (e) {
26
- fs_1.default.mkdirSync(dir, { recursive: true });
20
+ catch {
21
+ fs.mkdirSync(dir, { recursive: true });
27
22
  return;
28
23
  }
29
24
  // TODO: Use `fs.rmdirSync(dir, {recursive: true});` when it's stable (node 13+)
30
- items.forEach((item) => deleteFolder(path_1.default.join(dir, item)));
25
+ items.forEach((item) => deleteFolder(path.join(dir, item)));
31
26
  }
32
27
  dereference(url) {
33
28
  const references = (this.references.get(url) || 0) - 1;
34
29
  if (references < 0) {
35
- return log_1.default.warn("Tried to dereference a file that has no references", url);
30
+ return log.warn("Tried to dereference a file that has no references", url);
36
31
  }
37
32
  if (references > 0) {
38
33
  return this.references.set(url, references);
39
34
  }
40
35
  this.references.delete(url);
41
36
  // Drop "storage/" from url and join it with full storage path
42
- const filePath = path_1.default.join(config_1.default.getStoragePath(), url.substring(8));
43
- fs_1.default.unlink(filePath, (err) => {
37
+ const filePath = path.join(Config.getStoragePath(), url.substring(8));
38
+ fs.unlink(filePath, (err) => {
44
39
  if (err) {
45
- log_1.default.error("Failed to delete stored file", err.message);
40
+ log.error("Failed to delete stored file", err.message);
46
41
  }
47
42
  });
48
43
  }
49
44
  store(data, extension, callback) {
50
- const hash = crypto_1.default.createHash("sha256").update(data).digest("hex");
45
+ const hash = crypto.createHash("sha256").update(data).digest("hex");
51
46
  const a = hash.substring(0, 2);
52
47
  const b = hash.substring(2, 4);
53
- const folder = path_1.default.join(config_1.default.getStoragePath(), a, b);
54
- const filePath = path_1.default.join(folder, `${hash.substring(4)}.${extension}`);
48
+ const folder = path.join(Config.getStoragePath(), a, b);
49
+ const filePath = path.join(folder, `${hash.substring(4)}.${extension}`);
55
50
  const url = `storage/${a}/${b}/${hash.substring(4)}.${extension}`;
56
51
  this.references.set(url, 1 + (this.references.get(url) || 0));
57
52
  // If file with this name already exists, we don't need to write it again
58
- if (fs_1.default.existsSync(filePath)) {
53
+ if (fs.existsSync(filePath)) {
59
54
  return callback(url);
60
55
  }
61
- fs_1.default.mkdir(folder, { recursive: true }, (mkdirErr) => {
56
+ fs.mkdir(folder, { recursive: true }, (mkdirErr) => {
62
57
  if (mkdirErr) {
63
- log_1.default.error("Failed to create storage folder", mkdirErr.message);
58
+ log.error("Failed to create storage folder", mkdirErr.message);
64
59
  return callback("");
65
60
  }
66
- fs_1.default.writeFile(filePath, data, (err) => {
61
+ fs.writeFile(filePath, data, (err) => {
67
62
  if (err) {
68
- log_1.default.error("Failed to store a file", err.message);
63
+ log.error("Failed to store a file", err.message);
69
64
  return callback("");
70
65
  }
71
66
  callback(url);
@@ -73,16 +68,16 @@ class Storage {
73
68
  });
74
69
  }
75
70
  }
76
- exports.default = new Storage();
71
+ export default new Storage();
77
72
  function deleteFolder(dir) {
78
- fs_1.default.readdirSync(dir).forEach((item) => {
79
- item = path_1.default.join(dir, item);
80
- if (fs_1.default.lstatSync(item).isDirectory()) {
73
+ fs.readdirSync(dir).forEach((item) => {
74
+ item = path.join(dir, item);
75
+ if (fs.lstatSync(item).isDirectory()) {
81
76
  deleteFolder(item);
82
77
  }
83
78
  else {
84
- fs_1.default.unlinkSync(item);
79
+ fs.unlinkSync(item);
85
80
  }
86
81
  });
87
- fs_1.default.rmdirSync(dir);
82
+ fs.rmdirSync(dir);
88
83
  }