diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 8a1297856..000000000 --- a/.eslintignore +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-FileCopyrightText: 2023 XWiki CryptPad Team and contributors -# -# SPDX-License-Identifier: AGPL-3.0-or-later - -node_modules/ -www/components/ -www/bower_components/ -www/common/onlyoffice/dist -www/common/onlyoffice/x2t -onlyoffice-dist/ - -www/scratch -www/accounts -www/lib -www/accounts -www/worker -www/todo - -#lib/plugins/ - -www/common/hyperscript.js - -www/pad/wysiwygarea-plugin.js -www/pad/mediatag-plugin.js -www/pad/mediatag-plugin-dialog.js -www/pad/disable-base64.js -www/pad/wordcount/ - -www/kanban/jkanban.js -www/common/jscolor.js - -www/common/media-tag-nacl.min.js - -customize/ - -www/debug/chainpad.dist.js - -www/pad/mathjax/ -www/code/mermaid*.js -www/code/orgmode.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 924eddfc3..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: 2024 XWiki CryptPad Team and contributors -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -module.exports = { - 'env': { - 'browser': true, - 'es2021': true, - 'node': true - }, - 'plugins': ['compat'], - 'extends': ['eslint:recommended', 'plugin:compat/recommended'], - "globals": { - "define": "readonly", - }, - 'overrides': [ - { - 'env': { - 'node': true - }, - 'files': [ - '.eslintrc.{js,cjs}' - ], - 'parserOptions': { - 'sourceType': 'script' - } - } - ], - 'parserOptions': { - 'ecmaVersion': 'latest' - }, - 'rules': { - 'indent': [ - 'off', // TODO enable this check - 4 - ], - 'linebreak-style': [ - 'off', // git handles linebreak conversion for us - 'unix' - ], - 'quotes': [ - 'off', // TODO enable this check - 'single' - ], - 'semi': [ - 'error', - 'always' - ], - - // TODO remove these exceptions from the eslint defaults - 'no-irregular-whitespace': ['off'], - 'no-self-assign': ['off'], - 'no-empty': ['off'], - 'no-useless-escape': ['off'], - 'no-extra-boolean-cast': ['off'], - 'no-prototype-builtins': ['off'], - } -}; diff --git a/.gitignore b/.gitignore index bac376dcd..013a3e931 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,8 @@ www/common/onlyoffice/v* /onlyoffice-conf/ /onlyoffice-dist/ +_build + # ---> Node # Logs logs diff --git a/customize.dist/pages/index.js b/customize.dist/pages/index.js index b732d2558..43e2b44d5 100644 --- a/customize.dist/pages/index.js +++ b/customize.dist/pages/index.js @@ -167,13 +167,20 @@ define([ let popup = h('div.cp-extensions-popups'); let utils = { h, Util, Hash }; - Extensions.getExtensions('HOMEPAGE_POPUP').forEach(ext => { - if (typeof(ext.check) === "function" && !ext.check()) { return; } - ext.getContent(utils, content => { - $(popup).append(h('div.cp-extensions-popup', content)); + + Extensions.getExtensions('HOMEPAGE_POPUP').forEach(_ext => { + _ext.then(ext => { + if (ext) { + ext.getContent(utils, content => { + $(popup).append(h('div.cp-extensions-popup', content)); + }); + } + }).catch(error => { + console.error(error); }); }); + return [ h('div#cp-main', [ Pages.infopageTopbar(), diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 9d11dde7d..e61d9fbda 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -734,10 +734,6 @@ color: inherit; } } - .cp-notifications-empty { - color: @cp_dropdown-fg; - padding: 5px; - } button { position: relative; .cp-dropdown-button-title { @@ -765,6 +761,10 @@ margin: 0 -5px; padding: 0; } + .cp-notifications-empty { + color: @cp_dropdown-fg; + padding: 0.3em; + } } } .cp-toolbar-link { diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..eba722d94 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2024 XWiki CryptPad Team and contributors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +const compatPlugin = require("eslint-plugin-compat"); +const globals = require("globals"); +const js = require("@eslint/js"); +const FlatCompat = require("@eslint/eslintrc").FlatCompat; + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +module.exports = [{ + ignores: [ + "**/node_modules/", + "www/components/", + "www/bower_components/", + "www/common/onlyoffice/dist", + "www/common/onlyoffice/x2t", + "**/onlyoffice-dist/", + "www/scratch", + "www/accounts", + "www/lib", + "www/accounts", + "www/worker", + "www/todo", + "**/*worker.bundle.js", + "**/_build", + "www/common/hyperscript.js", + "www/pad/wysiwygarea-plugin.js", + "www/pad/mediatag-plugin.js", + "www/pad/mediatag-plugin-dialog.js", + "www/pad/disable-base64.js", + "www/pad/wordcount/", + "www/kanban/jkanban.js", + "www/common/jscolor.js", + "www/common/media-tag-nacl.min.js", + "**/customize/", + "www/debug/chainpad.dist.js", + "www/pad/mathjax/", + "www/code/mermaid*.js", + "www/code/orgmode.js", + ], +}, ...compat.extends("eslint:recommended", "plugin:compat/recommended"), { + plugins: { + compatPlugin, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + define: "readonly", + }, + + ecmaVersion: "latest", + sourceType: "commonjs", + }, + + rules: { + indent: ["off", 4], + "linebreak-style": ["off", "unix"], + quotes: ["off", "single"], + semi: ["error", "always"], + "no-irregular-whitespace": ["off"], + "no-self-assign": ["off"], + "no-empty": ["off"], + "no-useless-escape": ["off"], + "no-extra-boolean-cast": ["off"], + "no-prototype-builtins": ["off"], + "no-use-before-define": ["error"], + "no-unused-vars": [ + "error", + { + caughtErrors: "none" + } + ] + }, +}, { + files: ["**/.eslintrc.{js,cjs}"], + + languageOptions: { + globals: { + ...globals.node, + }, + + ecmaVersion: 5, + sourceType: "commonjs", + }, +}]; diff --git a/lib/api.js b/lib/api.js index bccf917f8..df3206b1e 100644 --- a/lib/api.js +++ b/lib/api.js @@ -108,7 +108,7 @@ nThen(function (w) { }; // spawn ws server and attach netflux event handlers - let Server = NetfluxSrv.create(new WebSocketServer({ server: Env.httpServer})) + let Server = Env.Server = NetfluxSrv.create(new WebSocketServer({ server: Env.httpServer})) .on('channelClose', historyKeeper.channelClose) .on('channelMessage', historyKeeper.channelMessage) .on('channelOpen', historyKeeper.channelOpen) diff --git a/lib/hk-util.js b/lib/hk-util.js index 93c3f9c0e..e9d177968 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -321,6 +321,7 @@ const storeMessage = function (Env, channel, msg, isCp, optionalMessageHash, tim // Store the message first, and update the index only once it's stored. // store.messageBin can be async so updating the index first may // result in a wrong cpIndex + Env.plugins?.MONITORING?.increment(`storeMessage`); nThen((waitFor) => { Env.store.messageBin(id, msgBin, waitFor(function (err) { if (err) { @@ -392,6 +393,8 @@ const storeMessage = function (Env, channel, msg, isCp, optionalMessageHash, tim var msgLength = msgBin.length; index.size += msgLength; + Env.plugins?.MONITORING?.increment('broadcastMessage', (channel.length-1)); + // handle the next element in the queue next(); @@ -522,6 +525,7 @@ const getHistoryAsync = (Env, channelName, lastKnownHash, beforeHash, handler, c const store = Env.store; let offset = -1; + Env.plugins?.MONITORING?.increment(`getHistoryAsync`); nThen((waitFor) => { getHistoryOffset(Env, channelName, lastKnownHash, waitFor((err, os) => { if (err) { @@ -773,6 +777,10 @@ const handleGetHistoryRange = function (Env, Server, seq, userId, parsed) { Env.getOlderHistory(channelName, oldestKnownHash, untilHash, desiredMessages, desiredCheckpoint, function (err, toSend) { if (err && err.code !== 'ENOENT') { Env.Log.error("HK_GET_OLDER_HISTORY", err); + Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, + JSON.stringify(['HISTORY_RANGE_ERROR', txid, err]) + ]); + return; } if (Array.isArray(toSend)) { diff --git a/lib/http-worker.js b/lib/http-worker.js index b93120d74..9cb88ada0 100644 --- a/lib/http-worker.js +++ b/lib/http-worker.js @@ -35,7 +35,7 @@ const guid = () => { return Util.guid(response._pending); }; -const sendMessage = (msg, cb, opt) => { +const sendMessage = Env.sendMessage = (msg, cb, opt) => { var txid = guid(); var timeout = (opt && opt.timeout) || DEFAULT_QUERY_TIMEOUT; var obj = { @@ -71,6 +71,7 @@ EVENTS.ENV_UPDATE = function (data /*, cb */) { Env = JSON.parse(data); Env.Log = Log; Env.plugins = plugins; + Env.sendMessage = sendMessage; Env.incrementBytesWritten = function () {}; } catch (err) { Log.error('HTTP_WORKER_ENV_UPDATE', Util.serializeError(err)); @@ -91,6 +92,23 @@ EVENTS.FLUSH_CACHE = function (data) { }); }; +Object.keys(plugins || {}).forEach(name => { + let plugin = plugins[name]; + if (!plugin.addHttpEvents) { return; } + try { + let events = plugin.addHttpEvents(Env); + Object.keys(events || {}).forEach(cmd => { + // Uppercase event name? + if (cmd !== cmd.toUpperCase()) { return; } + // Event is a function? + if (typeof(events[cmd]) !== "function") { return; } + // Event doesn't already exists? + if (EVENTS[cmd]) { return; } + EVENTS[cmd] = events[cmd]; + }); + } catch (e) {} +}); + process.on('message', msg => { if (!(msg && msg.txid)) { return; } if (msg.type === 'REPLY') { @@ -799,7 +817,12 @@ nThen(function (w) { })); }).nThen(function () { // TODO inform the parent process that this worker is ready - + Object.keys(Env.plugins || {}).forEach(name => { + let plugin = plugins[name]; + if (!plugin.initialize) { return; } + try { plugin.initialize(Env, "http-worker"); } + catch (e) {} + }); }); process.on('uncaughtException', function (err) { diff --git a/lib/rpc.js b/lib/rpc.js index 571272ab1..c28c5210a 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -34,6 +34,8 @@ var isUnauthenticateMessage = function (msg) { var handleUnauthenticatedMessage = function (Env, msg, respond, Server, netfluxId) { Env.Log.silly('LOG_RPC', msg[0]); + Env.plugins?.MONITORING?.increment(`rpc_${msg[0]}`); + var method = UNAUTHENTICATED_CALLS[msg[0]]; method(Env, msg[1], function (err, value) { if (err) { @@ -170,6 +172,8 @@ var rpc = function (Env, Server, userId, data, respond) { var command = msg[1]; + Env.plugins?.MONITORING?.increment(`rpc_${command}`); + if (command === 'UPLOAD') { // UPLOAD is a special case that skips signature validation // intentional fallthrough behaviour diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js index 398260d61..64376236f 100644 --- a/lib/workers/db-worker.js +++ b/lib/workers/db-worker.js @@ -17,11 +17,18 @@ const Tasks = require("../storage/tasks"); const Nacl = require('tweetnacl/nacl-fast'); const Eviction = require("../eviction"); const CPCrypto = require('../crypto'); +const plugins = require("../plugin-manager"); const Env = { Log: {}, }; +const Monitoring = plugins && plugins.MONITORING; +const monitoringIncrement = key => { + if (!Monitoring || !Monitoring.increment) { return; } + Monitoring.increment(key); +}; + // support the usual log API but pass it to the main process Logger.levels.forEach(function (level) { Env.Log[level] = function (label, info) { @@ -33,6 +40,8 @@ Logger.levels.forEach(function (level) { }; }); +const HISTORY_SIZE_LIMIT = 1024 * 1024 * 1024; // XXX 1GB + var DETAIL = 1000; var round = function (n) { return Math.floor(n * DETAIL) / DETAIL; @@ -57,6 +66,17 @@ const init = function (config, _cb) { Env.archiveRetentionTime = config.archiveRetentionTime; Env.accountRetentionTime = config.accountRetentionTime; + Env.sendMessage = data => { + process.send(data); + }; + + Object.keys(plugins || {}).forEach(name => { + let plugin = plugins[name]; + if (!plugin.initialize) { return; } + try { plugin.initialize(Env, "db-worker"); } + catch (e) {} + }); + nThen(function (w) { Store.create(config, w(function (err, _store) { if (err) { @@ -277,6 +297,8 @@ const computeIndex = function (data, cb) { const channelName = data.channel; const CB = Util.once(cb); + monitoringIncrement('computeIndex'); + var start = 0; nThen(function (w) { store.getOffset(channelName, w(function (err, obj) { @@ -298,6 +320,7 @@ const computeIndex = function (data, cb) { }); } w.abort(); + monitoringIncrement('computeIndexFromOffset'); CB(err, index); })); }).nThen(function (w) { @@ -306,6 +329,7 @@ const computeIndex = function (data, cb) { store.clearOffset(channelName, w()); }).nThen(function () { // now get the history as though it were the first time + monitoringIncrement('computeIndexFromStart'); computeIndexFromOffset(channelName, 0, CB); }); }; @@ -313,6 +337,7 @@ const computeIndex = function (data, cb) { const computeMetadata = function (data, cb) { const ref = {}; const lineHandler = Meta.createLineHandler(ref, Env.Log.error); + monitoringIncrement('computeMetadata'); return void store.readChannelMetadata(data.channel, lineHandler, function (err) { if (err) { // stream errors? @@ -322,6 +347,31 @@ const computeMetadata = function (data, cb) { }); }; +const _getFileSize = function (channel, _cb) { + var cb = Util.once(Util.mkAsync(_cb)); + if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } + if (channel.length === HK.STANDARD_CHANNEL_LENGTH || + channel.length === HK.ADMIN_CHANNEL_LENGTH) { + return void store.getChannelSize(channel, function (e, size) { + if (e) { + if (e.code === 'ENOENT') { return void cb(void 0, 0); } + return void cb(e.code); + } + cb(void 0, size); + }); + } + + // 'channel' refers to a file, so you need another API + blobStore.size(channel, function (e, size) { + if (typeof(size) === 'undefined') { return void cb(e); } + cb(void 0, size); + }); +}; + +const getFileSize = function (data, cb) { + _getFileSize(data.channel, cb); +}; + /* getOlderHistory * allows clients to query for all messages until a known hash is read * stores all messages in history as they are read @@ -339,6 +389,7 @@ const getOlderHistory = function (data, cb) { const desiredMessages = data.desiredMessages; const desiredCheckpoint = data.desiredCheckpoint; + var next = () => { var messages = []; var found = false; store.getMessages(channelName, function (msgStr) { @@ -384,6 +435,15 @@ const getOlderHistory = function (data, cb) { } cb(err, toSend); }); + }; + + _getFileSize(channelName, function (err, size) { + if (err) { return void cb(err); } + if (size > HISTORY_SIZE_LIMIT) { + return void cb('HISTORY_TOO_LARGE'); + } + next(); + }); }; const getPinState = function (data, cb) { @@ -393,6 +453,7 @@ const getPinState = function (data, cb) { var lineHandler = Pins.createLineHandler(ref, Env.Log.error); // if channels aren't in memory. load them from disk + monitoringIncrement('getPin'); pinStore.readMessagesBin(safeKey, 0, (msgObj, readMore) => { lineHandler(msgObj.buff.toString('utf8')); readMore(); @@ -401,31 +462,6 @@ const getPinState = function (data, cb) { }); }; -const _getFileSize = function (channel, _cb) { - var cb = Util.once(Util.mkAsync(_cb)); - if (!Core.isValidId(channel)) { return void cb('INVALID_CHAN'); } - if (channel.length === HK.STANDARD_CHANNEL_LENGTH || - channel.length === HK.ADMIN_CHANNEL_LENGTH) { - return void store.getChannelSize(channel, function (e, size) { - if (e) { - if (e.code === 'ENOENT') { return void cb(void 0, 0); } - return void cb(e.code); - } - cb(void 0, size); - }); - } - - // 'channel' refers to a file, so you need another API - blobStore.size(channel, function (e, size) { - if (typeof(size) === 'undefined') { return void cb(e); } - cb(void 0, size); - }); -}; - -const getFileSize = function (data, cb) { - _getFileSize(data.channel, cb); -}; - const _iterateFiles = function (channels, handler, cb) { if (!Array.isArray(channels)) { return cb('INVALID_LIST'); } var L = channels.length; @@ -449,6 +485,7 @@ const _iterateFiles = function (channels, handler, cb) { const getTotalSize = function (data, cb) { var bytes = 0; + monitoringIncrement('getTotalSize'); _iterateFiles(data.channels, function (channel, next) { _getFileSize(channel, function (err, size) { if (!err) { bytes += size; } @@ -494,6 +531,7 @@ const getHashOffset = function (data, cb) { const lastKnownHash = data.hash; if (typeof(lastKnownHash) !== 'string') { return void cb("INVALID_HASH"); } + monitoringIncrement('getHashOffset'); var offset = -1; store.readMessagesBin(channelName, 0, (msgObj, readMore, abort) => { // tryParse return a parsed message or undefined @@ -592,6 +630,8 @@ const completeUpload = function (data, cb) { var arg = data.arg; var size = data.size; + monitoringIncrement('uploadedBlob'); + var method; var label; if (owned) { @@ -671,6 +711,7 @@ const COMMANDS = { }; COMMANDS.INLINE = function (data, cb) { + monitoringIncrement('inlineValidation'); var signedMsg; try { signedMsg = Nacl.util.decodeBase64(data.msg); @@ -695,6 +736,7 @@ COMMANDS.INLINE = function (data, cb) { const checkDetachedSignature = function (signedMsg, signature, publicKey) { if (!(signedMsg && publicKey)) { return false; } + monitoringIncrement('detachedValidation'); var signedBuffer; var pubBuffer; @@ -758,13 +800,28 @@ COMMANDS.HASH_CHANNEL_LIST = function (data, cb) { }; COMMANDS.VALIDATE_ANCESTOR_PROOF = function (data, cb) { + monitoringIncrement('validateAncestorProof'); Block.validateAncestorProof(Env, data && data.proof, cb); }; COMMANDS.VALIDATE_LOGIN_BLOCK = function (data, cb) { + monitoringIncrement('validateLoginBlock'); Block.validateLoginBlock(Env, data.publicKey, data.signature, data.block, cb); }; +Object.keys(plugins || {}).forEach(name => { + let plugin = plugins[name]; + if (!plugin.addWorkerCommands) { return; } + try { + let events = plugin.addWorkerCommands(Env); + Object.keys(events || {}).forEach(cmd => { + if (typeof(events[cmd]) !== "function") { return; } + if (COMMANDS[cmd]) { return; } + COMMANDS[cmd] = events[cmd]; + }); + } catch (e) {} +}); + process.on('message', function (data) { if (!data || !data.txid || !data.pid) { return void process.send({ @@ -773,6 +830,13 @@ process.on('message', function (data) { }); } + const command = COMMANDS[data.command]; + + // Command broadcasted to all workers: no callback expected + if (data.type === 'broadcast') { + return void command(data); + } + const cb = function (err, value) { process.send({ error: Util.serializeError(err), @@ -790,7 +854,6 @@ process.on('message', function (data) { }); } - const command = COMMANDS[data.command]; if (typeof(command) !== 'function') { return void cb("E_BAD_COMMAND"); } diff --git a/lib/workers/index.js b/lib/workers/index.js index 55487c848..5bdbd5d7a 100644 --- a/lib/workers/index.js +++ b/lib/workers/index.js @@ -152,9 +152,34 @@ Workers.initialize = function (Env, config, _cb) { // default to timing out affter 180s if no explicit timeout is passed var timeout = typeof(opt.timeout) !== 'undefined'? opt.timeout: DEFAULT_QUERY_TIMEOUT; response.expect(txid, cb, timeout); + + delete msg._cb; + delete msg._opt; state.worker.send(msg); + + // Add original callback to message data in case we need + // to resend the command. setTimeout to avoid interfering + // with worker.send + setTimeout(function () { + msg._cb = _cb; + msg._opt = opt; + }); }; + const pluginsResponses = {}; + Object.keys(Env.plugins || {}).forEach(name => { + let plugin = Env.plugins[name]; + if (!plugin.addWorkerResponses) { return; } + try { + let res = plugin.addWorkerResponses(Env); + Object.keys(res || {}).forEach(key => { + if (typeof(res[key]) !== "function") { return; } + if (pluginsResponses[key]) { return; } + pluginsResponses[key] = res[key]; + }); + } catch (e) {} + }); + var handleResponse = function (state, res) { if (!res) { return; } // handle log messages before checking if it was addressed to your PID @@ -162,6 +187,17 @@ Workers.initialize = function (Env, config, _cb) { if (res.log) { return void handleLog(res.log, res.label, res.info); } + + // handle plugins + if (res.plugin) { + Object.keys(pluginsResponses).some(key => { + if (res.type !== key) { return; } + pluginsResponses[key](res.data); + return true; + }); + return; + } + // but don't bother handling things addressed to other processes // since it's basically guaranteed not to work if (res.pid !== PID) { @@ -226,7 +262,15 @@ Workers.initialize = function (Env, config, _cb) { handleResponse(state, res); }); + let pid = worker.pid; var substituteWorker = Util.once(function () { + Object.keys(Env.plugins || {}).forEach(name => { + let plugin = Env.plugins[name]; + if (!plugin.onWorkerClosed) { return; } + try { plugin.onWorkerClosed("db-worker", pid); } + catch (e) {} + }); + Env.Log.info("SUBSTITUTE_DB_WORKER", ''); var idx = workers.indexOf(state); if (idx !== -1) { @@ -237,26 +281,36 @@ Workers.initialize = function (Env, config, _cb) { const cb = response.expectation(txid); if (typeof(cb) !== 'function') { return; } const task = state.tasks[txid]; - if (!(task && task.msg)) { return; } + if (!task) { return; } response.clear(txid); - Log.info('DB_WORKER_RESEND', task.msg); - sendCommand(task.msg, cb); + Log.info('DB_WORKER_RESEND', task); + sendCommand(task, task._cb || cb, task._opt); }); var w = fork(DB_PATH); - initWorker(w, function (err, state) { + initWorker(w, function (err) { if (err) { throw new Error(err); } - workers.push(state); }); }); - worker.on('exit', substituteWorker); - worker.on('close', substituteWorker); + worker.on('exit', function () { + substituteWorker(); + Env.Log.error("DB_WORKER_EXIT", { + pid: state.pid, + }); + }); + worker.on('close', function () { + substituteWorker(); + Env.Log.error("DB_WORKER_CLOSE", { + pid: state.pid, + }); + }); worker.on('error', function (err) { substituteWorker(); Env.Log.error("DB_WORKER_ERROR", { + pid: state.pid, error: err, }); }); @@ -282,6 +336,18 @@ Workers.initialize = function (Env, config, _cb) { })); }); }).nThen(function () { + Env.broadcastWorkerCommand = (data) => { + workers.forEach(state => { + state.worker.send({ + type: 'broadcast', + pid: PID, + command: data.command, + txid: data.txid + }); + }); + return workers; + }; + Env.computeIndex = function (Env, channel, cb) { Env.store.getWeakLock(channel, function (next) { sendCommand({ diff --git a/package-lock.json b/package-lock.json index faa58a38e..f5038d672 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cryptpad", - "version": "2024.9.0", + "version": "2024.9.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cryptpad", - "version": "2024.9.0", + "version": "2024.9.1", "license": "AGPL-3.0+", "dependencies": { "@mcrowe/minibloom": "^0.2.0", @@ -19,23 +19,23 @@ "chainpad-crypto": "^0.2.5", "chainpad-listmap": "^1.1.0", "chainpad-netflux": "^1.2.0", - "chainpad-server": "^5.2.2", + "chainpad-server": "^5.2.4", "ckeditor": "npm:ckeditor4@~4.22.1", "codemirror": "^5.19.0", "components-font-awesome": "^4.6.3", - "cookie-parser": "^1.4.6", + "cookie-parser": "^1.4.7", "croppie": "^2.5.0", "dragula": "3.7.2", "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+5", - "express": "~4.21.0", + "express": "~4.21.1", "file-saver": "1.3.1", "fs-extra": "^7.0.0", "get-folder-size": "^2.0.1", "html2canvas": "^1.4.0", - "http-proxy-middleware": "^3.0.2", + "http-proxy-middleware": "^3.0.3", "hyper-json": "~1.4.0", "jquery": "3.6.0", - "json.sortify": "~2.1.0", + "json.sortify": "github:cryptpad/JSON.sortify", "jsonwebtoken": "^9.0.0", "jszip": "3.10.1", "localforage": "^1.5.2", @@ -64,8 +64,8 @@ "x2js": "^3.4.4" }, "devDependencies": { - "eslint": "^8.57.0", - "eslint-plugin-compat": "^4.2.0", + "eslint": "^9.16.0", + "eslint-plugin-compat": "^6.0.1", "stylelint": "^16.9.0", "stylelint-config-standard-less": "^3.0.1" }, @@ -303,24 +303,70 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/@eslint/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -328,25 +374,19 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -357,106 +397,76 @@ } } }, - "node_modules/@eslint/eslintrc/node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", @@ -471,11 +481,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", @@ -483,9 +500,9 @@ "integrity": "sha512-hce9MTbEkVIutibAkXAQddXCU9gMP/3OfcRaNo2V0v485iEzBRlniJG0ZTKumL8RbUA/fhpIGvrURiEZc+Crrg==" }, "node_modules/@mdn/browser-compat-data": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.12.tgz", - "integrity": "sha512-/AHFqy6OeNHS2NNZGFVRgQh+pnW8iAoV3d1fiO9b2PuQ3HzZpC30MrMrHtq1uOGy1/zcK4uPQEyI31jkM0NNAA==", + "version": "5.6.21", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.6.21.tgz", + "integrity": "sha512-yFGyNC6llnRbCELh1vH5mhrdSkQCrBs+wOyFjcYa3E9K3qzz6aDKnUSlDfWx+7pMeVr/iSKIdl1P60g2Jxs5sg==", "dev": true }, "node_modules/@node-saml/node-saml": { @@ -590,6 +607,12 @@ "@types/ms": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, "node_modules/@types/express": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", @@ -625,6 +648,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", @@ -705,12 +734,6 @@ "@types/node": "*" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -1133,6 +1156,12 @@ "node": ">=0.10.0" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", @@ -1294,9 +1323,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -1313,10 +1342,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1357,9 +1386,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001660", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", - "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "version": "1.0.30001686", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", + "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", "dev": true, "funding": [ { @@ -1405,6 +1434,14 @@ "json.sortify": "~2.1.0" } }, + "node_modules/chainpad-listmap/node_modules/json.sortify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json.sortify/-/json.sortify-2.1.0.tgz", + "integrity": "sha512-otSldRQcu9PaQJJDeB1qGZUIoL7C4nxZunUVHieWPUMJvvVxIUhsMQUhR+r4OUZBwA1McnbS7sqDf5dYHzJsbw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/chainpad-netflux": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/chainpad-netflux/-/chainpad-netflux-1.2.0.tgz", @@ -1414,24 +1451,9 @@ } }, "node_modules/chainpad-server": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/chainpad-server/-/chainpad-server-5.2.2.tgz", - "integrity": "sha512-fUCffhnd8PlO92A6cYH5lSIiiI6bpJymP0yC3O2KI+4NPyxFK7I2iuadMrC7RzK3eAI1w72Y1nbMN8rQImppoQ==", - "dependencies": { - "nthen": "0.1.8", - "pull-stream": "^3.6.9", - "stream-to-pull-stream": "^1.7.3", - "ws": "^3.3.1" - } - }, - "node_modules/chainpad/node_modules/json.sortify": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/json.sortify/-/json.sortify-2.2.2.tgz", - "integrity": "sha512-wwFLdDffs747s5cqLA3htIKp9wdID2rWNofJKxwDjFo+rqqt5Vg7SnYOh7mc7MW6Iw43rrOFhr6MKytOtNceSA==", - "engines": { - "node": ">=4.0.0", - "npm": "~1.0.20" - } + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/chainpad-server/-/chainpad-server-5.2.4.tgz", + "integrity": "sha512-f4eErhcmIE67vfN9Dkfh0hX/IZDWERmfjdcfPEesXIHKu441jA84H0autvTAFsMTSPimlil7eeGnx4GLBVrR5Q==" }, "node_modules/chalk": { "version": "4.1.2", @@ -1570,19 +1592,19 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", "dependencies": { - "cookie": "0.4.1", + "cookie": "0.7.2", "cookie-signature": "1.0.6" }, "engines": { @@ -1590,9 +1612,9 @@ } }, "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "engines": { "node": ">= 0.6" } @@ -1621,9 +1643,9 @@ "integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ==" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -1774,18 +1796,6 @@ "defined": "^1.0.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dragula": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/dragula/-/dragula-3.7.2.tgz", @@ -1813,9 +1823,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.687", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz", - "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==", + "version": "1.5.68", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz", + "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==", "dev": true }, "node_modules/emoji-regex": { @@ -1878,9 +1888,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -1904,92 +1914,109 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-compat": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz", - "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.1.tgz", + "integrity": "sha512-0MeIEuoy8kWkOhW38kK8hU4vkb6l/VvyjpuYDymYOXmUY9NvTgyErF16lYuX+HPS5hkmym7lfA+XpYZiWYWmYA==", "dev": true, "dependencies": { - "@mdn/browser-compat-data": "^5.3.13", + "@mdn/browser-compat-data": "^5.5.35", "ast-metadata-inferer": "^0.8.0", - "browserslist": "^4.21.10", - "caniuse-lite": "^1.0.30001524", + "browserslist": "^4.23.1", + "caniuse-lite": "^1.0.30001639", "find-up": "^5.0.0", + "globals": "^15.7.0", "lodash.memoize": "^4.1.2", - "semver": "^7.5.4" + "semver": "^7.6.2" }, "engines": { - "node": ">=14.x" + "node": ">=18.x" }, "peerDependencies": { - "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-compat/node_modules/globals": { + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", + "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2007,21 +2034,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/eslint/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2039,6 +2051,18 @@ } } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2051,57 +2075,33 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/eslint/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2119,6 +2119,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", @@ -2187,16 +2199,16 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -2288,15 +2300,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-saver": { @@ -2357,17 +2369,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -2443,12 +2454,6 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2492,26 +2497,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -2572,15 +2557,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2635,12 +2617,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2747,9 +2723,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.2.tgz", - "integrity": "sha512-fBLFpmvDzlxdckwZRjM0wWtwDZ4KBtQ8NFqhrFKoEtK4myzuiumBuNTxD+F4cVbXfOZljIbrynmvByofDzT7Ag==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", + "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", @@ -2821,6 +2797,22 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2830,16 +2822,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/info-symbol": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/info-symbol/-/info-symbol-0.1.0.tgz", @@ -2955,15 +2937,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3021,6 +2994,18 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3046,11 +3031,12 @@ "dev": true }, "node_modules/json.sortify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json.sortify/-/json.sortify-2.1.0.tgz", - "integrity": "sha512-otSldRQcu9PaQJJDeB1qGZUIoL7C4nxZunUVHieWPUMJvvVxIUhsMQUhR+r4OUZBwA1McnbS7sqDf5dYHzJsbw==", + "version": "2.2.2", + "resolved": "git+ssh://git@github.com/cryptpad/JSON.sortify.git#0a96f91c3f3b127c3040bbc2d3eb6ae803cb2dfd", + "license": "Apache-2.0", "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0", + "npm": ">=1.0.20" } }, "node_modules/jsonfile": { @@ -3611,9 +3597,9 @@ "integrity": "sha512-8oQOyEyh0MCnifNIfyvkNXpEELlVRzDleRivRgsDGh+5ZDG109axweVZ0RIOIpkQmTZk4/xVsBk/oLXpMSWEOw==" }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/normalize-path": { @@ -3731,15 +3717,6 @@ "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/open-sans-fontface": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/open-sans-fontface/-/open-sans-fontface-1.4.0.tgz", @@ -3858,15 +3835,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4398,6 +4366,15 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", "integrity": "sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg==" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4408,21 +4385,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4486,12 +4448,9 @@ "integrity": "sha512-BtT7+xPLdoeXsh6wOblaq6sRy/AsffFXgcwBNGtQJXeNgm9UD3HM3nWEmAERjdCNfE6jWglAtRbAPZ7rc2WtsQ==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -4793,6 +4752,18 @@ "node": ">=0.10.0" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stylelint": { "version": "16.9.0", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.9.0.tgz", @@ -4967,12 +4938,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/stylelint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/stylelint/node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -5104,31 +5069,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylelint/node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/stylelint/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5147,18 +5087,6 @@ "node": ">=0.10.0" } }, - "node_modules/stylelint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/stylelint/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5405,12 +5333,6 @@ "utrie": "^1.0.2" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/thirty-two": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", @@ -5514,18 +5436,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -5568,9 +5478,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -5587,8 +5497,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -5703,12 +5613,6 @@ "node": ">=0.4.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "node_modules/write-file-atomic": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", diff --git a/package.json b/package.json index c7cc84e99..f236c225a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cryptpad", "description": "a collaborative office suite that is end-to-end encrypted and open-source", - "version": "2024.9.0", + "version": "2024.9.1", "license": "AGPL-3.0+", "repository": { "type": "git", @@ -22,23 +22,23 @@ "chainpad-crypto": "^0.2.5", "chainpad-listmap": "^1.1.0", "chainpad-netflux": "^1.2.0", - "chainpad-server": "^5.2.2", + "chainpad-server": "^5.2.4", "ckeditor": "npm:ckeditor4@~4.22.1", "codemirror": "^5.19.0", "components-font-awesome": "^4.6.3", - "cookie-parser": "^1.4.6", + "cookie-parser": "^1.4.7", "croppie": "^2.5.0", "dragula": "3.7.2", "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+5", - "express": "~4.21.0", + "express": "~4.21.1", "file-saver": "1.3.1", "fs-extra": "^7.0.0", "get-folder-size": "^2.0.1", "html2canvas": "^1.4.0", - "http-proxy-middleware": "^3.0.2", + "http-proxy-middleware": "^3.0.3", "hyper-json": "~1.4.0", "jquery": "3.6.0", - "json.sortify": "~2.1.0", + "json.sortify": "github:cryptpad/JSON.sortify", "jsonwebtoken": "^9.0.0", "jszip": "3.10.1", "localforage": "^1.5.2", @@ -67,8 +67,8 @@ "x2js": "^3.4.4" }, "devDependencies": { - "eslint": "^8.57.0", - "eslint-plugin-compat": "^4.2.0", + "eslint": "^9.16.0", + "eslint-plugin-compat": "^6.0.1", "stylelint": "^16.9.0", "stylelint-config-standard-less": "^3.0.1" }, diff --git a/server.js b/server.js index f240b1cd9..407f10f43 100644 --- a/server.js +++ b/server.js @@ -25,6 +25,13 @@ var app = Express(); } }()); +Object.keys(Env.plugins || {}).forEach(name => { + let plugin = Env.plugins[name]; + if (!plugin.initialize) { return; } + try { plugin.initialize(Env, "main"); } + catch (e) {} +}); + var COMMANDS = {}; COMMANDS.LOG = function (msg, cb) { @@ -49,6 +56,25 @@ COMMANDS.GET_PROFILING_DATA = function (msg, cb) { cb(void 0, Env.bytesWritten); }; +Object.keys(Env.plugins || {}).forEach(name => { + let plugin = Env.plugins[name]; + if (!plugin.addMainCommands) { return; } + try { + let commands = plugin.addMainCommands(Env); + Object.keys(commands || {}).forEach(cmd => { + // Uppercase command name? + if (cmd !== cmd.toUpperCase()) { return; } + // Command is a function? + if (typeof(commands[cmd]) !== "function") { return; } + // Command doesn't already exists? + if (COMMANDS[cmd]) { return; } + + COMMANDS[cmd] = commands[cmd]; + }); + } catch (e) {} +}); + + nThen(function (w) { require("./lib/log").create(config, w(function (_log) { Env.Log = _log; @@ -93,6 +119,7 @@ nThen(function (w) { var launchWorker = (online) => { var worker = Cluster.fork(workerState); + var pid = worker.process.pid; worker.on('online', () => { online(); }); @@ -122,6 +149,13 @@ nThen(function (w) { }); worker.on('exit', (code, signal) => { + Object.keys(Env.plugins || {}).forEach(name => { + let plugin = Env.plugins[name]; + if (!plugin.onWorkerClosed) { return; } + try { plugin.onWorkerClosed("http-worker", pid); } + catch (e) {} + }); + if (!signal && code === 0) { return; } // relaunch http workers if they crash Env.Log.error('HTTP_WORKER_EXIT', { @@ -147,10 +181,11 @@ nThen(function (w) { }); }; - var broadcast = (command, data/*, cb*/) => { + var broadcast = Env.broadcast = (command, data/*, cb*/) => { for (const worker of Object.values(Cluster.workers)) { sendCommand(worker, command, data /*, cb */); } + return Object.values(Cluster.workers); }; var throttledEnvChange = Util.throttle(function () { diff --git a/www/admin/inner.js b/www/admin/inner.js index a7b587266..9153436e5 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -172,7 +172,7 @@ define([ const blocks = sidebar.blocks; // EXTENSION_POINT:ADMIN_CATEGORY - common.getExtensions('ADMIN_CATEGORY').forEach(ext => { + common.getExtensionsSync('ADMIN_CATEGORY').forEach(ext => { if (!ext || !ext.id || !ext.name || !ext.content) { return console.error('Invalid extension point', 'ADMIN_CATEGORY', ext); } @@ -187,6 +187,7 @@ define([ }; }); + const flushCache = (cb) => { cb = cb || function () {}; sFrameChan.query('Q_ADMIN_RPC', { @@ -967,12 +968,7 @@ define([ }); }; - let btn = blocks.activeButton('primary', '', - Messages.admin_colorChange, (done) => { - let color = $input.val(); - setColor(color, done); - }); - + let $input = $(); let onColorPicked = () => { require(['/lib/less.min.js'], (Less) => { let color = $input.val(); @@ -994,7 +990,14 @@ define([ $preview.find('.cp-admin-color-preview-light a').attr('style', `color: ${color} !important`); }); }; - let $input = $(input).on('change', onColorPicked).addClass('cp-admin-color-picker'); + $input = $(input).on('change', onColorPicked).addClass('cp-admin-color-picker'); + + let btn = blocks.activeButton('primary', '', + Messages.admin_colorChange, (done) => { + let color = $input.val(); + setColor(color, done); + }); + UI.confirmButton($remove, { classes: 'btn-danger', @@ -3184,6 +3187,7 @@ define([ labelEnd, ], blocks.nav([button])); + let send = function () {}; var refresh = getApi(function (Broadcast) { $active.empty(); var removeButton = blocks.button('danger', '', Messages.admin_maintenanceCancel); @@ -3245,7 +3249,7 @@ define([ }; }; - var send = function (data) { + send = function (data) { disable($button); sFrameChan.query('Q_ADMIN_RPC', { cmd: 'ADMIN_DECREE', @@ -3924,16 +3928,15 @@ define([ // EXTENSION_POINT:ADMIN_ITEM let utils = { - h, Util, Hash + h, Util, Hash, UIElements }; - common.getExtensions('ADMIN_ITEM').forEach(ext => { + common.getExtensionsSync('ADMIN_ITEM').forEach(ext => { if (!ext || !ext.id || typeof(ext.getContent) !== "function") { return console.error('Invalid extension point', 'ADMIN_CATEGORY', ext); } if (sidebar.hasItem(ext.id)) { return console.error('Extension point ID already used', ext); } - sidebar.addItem(ext.id, cb => { ext.getContent(common, blocks, utils, content => { cb(content); @@ -3946,12 +3949,8 @@ define([ }); }); - - sidebar.makeLeftside(categories); }; - - var updateStatus = APP.updateStatus = function (cb) { sFrameChan.query('Q_ADMIN_RPC', { cmd: 'INSTANCE_STATUS', diff --git a/www/common/application_config_internal.js b/www/common/application_config_internal.js index 662db522c..07a7c2f80 100644 --- a/www/common/application_config_internal.js +++ b/www/common/application_config_internal.js @@ -132,7 +132,7 @@ define(function() { // en: "Hello world", // fr: "Bonjour le monde", // de: "Hallo Welt", - // "pt-br": "Olá Mundo"< + // "pt-br": "Olá Mundo" }; /* Cryptpad apps use a common API to display notifications to users diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index ae0dea302..f4c21b05c 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2525,6 +2525,7 @@ define([ window.setTimeout(function () { modal.show(); $modal.focus(); + next(); }); }; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index e2d6a3746..ada56e9be 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -2713,7 +2713,7 @@ define([ window.addEventListener('unload', function () { postMsg('CLOSE'); }); - // eslint-disable-next-line no-constant-condition + // eslint-disable-next-line no-constant-condition,no-constant-binary-expression } else if (false && !noWorker && !noSharedWorker && 'serviceWorker' in navigator) { var initializing = true; var stopWaiting = waitFor2(); // Call this function when we're ready diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 135b0eae0..1768137e4 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -990,6 +990,9 @@ define([ // Arrow keys to modify the selection var onWindowKeydown = function (e) { if (!$content.is(':visible')) { return; } + if ($('.cp-modal').is(':visible')) { + return; + } var $searchBar = $tree.find('#cp-app-drive-tree-search-input'); if (document.activeElement && document.activeElement.nodeName === 'INPUT') { return; } if ($searchBar.is(':focus') && $searchBar.val()) { return; } @@ -2968,6 +2971,16 @@ define([ }); UI.openCustomModal(m); }; + + var triggerEnter = function (selector, $context) { + $context.find(selector).on('keypress', function (event) { + if (event.which === 13) { // enter + event.preventDefault(); + $(this).trigger('click'); // the keypress event triggers the click event + } + }); + }; + var addNewPadHandlers = function ($block, isInRoot) { // Handlers if (isInRoot) { @@ -2983,56 +2996,51 @@ define([ refresh(); }; $block.find('a.cp-app-drive-new-folder, li.cp-app-drive-new-folder') - .on('click keypress', function (event) { - if (event.type === 'click' || (event.type === 'keypress' && event.which === 13)) { - event.preventDefault(); - manager.addFolder(currentPath, null, onCreated); - } + .on('click', function (event) { + event.preventDefault(); + manager.addFolder(currentPath, null, onCreated); }); + triggerEnter('a.cp-app-drive-new-folder, li.cp-app-drive-new-folder', $block); if (!APP.disableSF && !manager.isInSharedFolder(currentPath)) { $block.find('a.cp-app-drive-new-shared-folder, li.cp-app-drive-new-shared-folder') - .on('click keypress', function (event) { - if (event.type === 'click' || (event.type === 'keypress' && event.which === 13)) { - event.preventDefault(); - addSharedFolderModal(function (obj) { - if (!obj) { return; } - manager.addSharedFolder(currentPath, obj, refresh); - }); - } + .on('click', function (event) { + event.preventDefault(); + addSharedFolderModal(function (obj) { + if (!obj) { return; } + manager.addSharedFolder(currentPath, obj, refresh); + }); }); + triggerEnter('a.cp-app-drive-new-shared-folder, li.cp-app-drive-new-shared-folder', $block); } $block.find('a.cp-app-drive-new-fileupload, li.cp-app-drive-new-fileupload') - .on('click keypress', function (event) { - if (event.type === 'click' || (event.type === 'keypress' && event.which === 13)) { - event.preventDefault(); - showUploadFilesModal(); - } + .on('click', function (event) { + event.preventDefault(); + showUploadFilesModal(); }); + triggerEnter('a.cp-app-drive-new-fileupload, li.cp-app-drive-new-fileupload', $block); $block.find('a.cp-app-drive-new-folderupload, li.cp-app-drive-new-folderupload') - .on('click keypress', function (event) { - if (event.type === 'click' || (event.type === 'keypress' && event.which === 13)) { - event.preventDefault(); - showUploadFolderModal(); - } + .on('click', function (event) { + event.preventDefault(); + showUploadFolderModal(); }); + triggerEnter('a.cp-app-drive-new-folderupload, li.cp-app-drive-new-folderupload', $block); $block.find('a.cp-app-drive-new-link, li.cp-app-drive-new-link') - .on('click keypress', function (event) { - if (event.type === 'click' || (event.type === 'keypress' && event.which === 13)) { - event.preventDefault(); - showLinkModal(); - } + .on('click', function (event) { + event.preventDefault(); + showLinkModal(); }); + triggerEnter('a.cp-app-drive-new-link, li.cp-app-drive-new-link', $block); } $block.find('a.cp-app-drive-new-doc, li.cp-app-drive-new-doc') - .on('click auxclick keypress', function (event) { - if (event.type === 'click' || event.type === 'auxclick' || (event.type === 'keypress' && event.which === 13)) - { + .on('click auxclick', function (event) { + if (event.type === 'click' || event.type === 'auxclick') { event.preventDefault(); var type = $(this).attr('data-type') || 'pad'; var path = manager.isPathIn(currentPath, [TRASH]) ? '' : currentPath; openIn(type, path, APP.team); } }); + triggerEnter('a.cp-app-drive-new-doc, li.cp-app-drive-new-doc', $block); }; var getNewPadOptions = function (isInRoot) { var options = []; diff --git a/www/common/extensions.js b/www/common/extensions.js index 1a0a7d040..dd7e9b97f 100644 --- a/www/common/extensions.js +++ b/www/common/extensions.js @@ -10,9 +10,51 @@ define([ ext.getExtensions = id => { let e = ext[id]; if (!Array.isArray(e)) { e = []; } - return e; + return e.map(_ext => { + return new Promise((resolve, reject) => { + // If there's no check function, resolve immediately + if (typeof _ext.check !== "function") { + return resolve(_ext); + } + const checkResult = _ext.check(); + + checkResult + .then((extPassed) => { + if (!extPassed) { + // Reject if the check didn't pass + undefined (resolve()); + } else { + // Extension passed the check + resolve(_ext); + } + }) + .catch((error) => { + reject(error); + }); + }); + }); }; + ext.getExtensionsSync = id => { + let e = ext[id]; + if (!Array.isArray(e)) { e = []; } + + return e.map(_ext => { + if (typeof _ext.check !== "function") { + return _ext; + } + + const extPassed = _ext.check(); + + if (extPassed) { + return _ext; + } else { + return null; + } + }).filter(ext => ext !== null); + }; + + if (!Array.isArray(Extensions) || !Extensions.length) { return ext; } let all = Extensions.slice(); diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 569db9bff..e9eb8226a 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2343,6 +2343,12 @@ define([ if (completed) { return; } var parsed = parse(msg); if (parsed[1] !== txid) { console.log('bad txid'); return; } + if (parsed[0] === 'HISTORY_RANGE_ERROR') { + cb({ + error: parsed[2] + }); + return; + } if (parsed[0] === 'HISTORY_RANGE_END') { cb({ messages: msgs, diff --git a/www/common/outer/messenger.js b/www/common/outer/messenger.js index 1aec3d51d..ac3c756cd 100644 --- a/www/common/outer/messenger.js +++ b/www/common/outer/messenger.js @@ -382,7 +382,8 @@ define([ } // History cleared while we were offline // ==> we asked for an invalid last known hash - if (parsed.error && parsed.error === "EINVAL") { + if (parsed.error && (parsed.error === "EINVAL" + || parsed.error === "EUNKNOWN")) { setChannelHead(ctx, parsed.channel, '', function () { getChannelMessagesSince(ctx, channel, {}, {}); }); diff --git a/www/common/outer/support.js b/www/common/outer/support.js index 1e18c6442..912fa5d23 100644 --- a/www/common/outer/support.js +++ b/www/common/outer/support.js @@ -531,6 +531,11 @@ define([ if (last.sender) { entry.lastAdmin = !last.sender.blockLocation; } + if (last.close) { + doc.tickets.closed[data.channel] = entry; + delete doc.tickets.active[data.channel]; + notifyClient(ctx, true, 'UPDATE_TICKET', data.channel); + } /* let senderKey = last.sender && last.sender.edPublic; if (senderKey) { @@ -589,7 +594,9 @@ define([ doc.tickets.closed[data.channel] = entry; delete doc.tickets.active[data.channel]; delete doc.tickets.pending[data.channel]; - cb({closed: true}); + Realtime.whenRealtimeSyncs(ctx.adminDoc.realtime, function () { + cb({closed: true}); + }); }); }); }; diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 72ae77681..272b9a391 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -698,7 +698,7 @@ define([ } if (exp.isFolder(obj.element)) { fixRoot(obj.element); } if (typeof obj.element === "number") { - var data = files[FILES_DATA][obj.element]; + var data = files[FILES_DATA][obj.element] || files[STATIC_DATA][obj.element]; if (!data) { debug("An element in TRASH doesn't have associated data", obj.element, el); toClean.push(idx); diff --git a/www/common/sframe-common-history.js b/www/common/sframe-common-history.js index 943e3f225..e711d5265 100644 --- a/www/common/sframe-common-history.js +++ b/www/common/sframe-common-history.js @@ -212,6 +212,9 @@ define([ sharedFolder: config.sharedFolder }, function (err, data) { if (err) { return void console.error(err); } + if (data && data.error) { + return void cb(data.error); + } if (!Array.isArray(data.messages)) { return void console.error('Not an array!'); } lastKnownHash = data.lastKnownHash; isComplete = data.isFull; @@ -288,6 +291,14 @@ define([ UI.spinner($hist).get().show(); + let closeAll = () => { + History.state = false; + $hist.hide(); + $bottom.show(); + $cke.show(); + $(window).trigger('resize'); + }; + var update = function (newRt) { realtime = newRt; if (!realtime) { return []; } @@ -567,11 +578,7 @@ define([ var onKeyDown, onKeyUp; var closeUI = function () { - History.state = false; - $hist.hide(); - $bottom.show(); - $cke.show(); - $(window).trigger('resize'); + closeAll(); $(window).off('keydown', onKeyDown); $(window).off('keyup', onKeyUp); }; @@ -681,7 +688,12 @@ define([ loadMoreHistory(config, common, function (err, newRt, isFull) { History.readOnly = common.getMetadataMgr().getPrivateData().readOnly; History.loading = false; - if (err) { throw new Error(err); } + if (err) { + console.error(err); + UI.warn(`${Messages.error}: ${err}`); + closeAll(); + return; + } update(newRt); display(); if (isFull) { diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index b4031d155..8138aec2d 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -78,7 +78,6 @@ define([ requireConfig.urlArgs + '#' + encodeURIComponent(JSON.stringify(req))); $i.attr('allowfullscreen', 'true'); $i.attr('allow', 'clipboard-write'); - $i.attr('title', 'iframe'); $('iframe-placeholder').after($i).remove(); // This is a cheap trick to avoid loading sframe-channel in parallel with the @@ -1322,6 +1321,9 @@ define([ toHash: data.toHash, lastKnownHash: data.lastKnownHash }, function (data) { + if (data && data.error) { + return void cb(data); + } cb({ isFull: data.isFull, messages: data.messages.map(function (obj) { diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index c297b5273..8310deb27 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -778,6 +778,7 @@ define([ }; funcs.getExtensions = Ext.getExtensions; + funcs.getExtensionsSync = Ext.getExtensionsSync; funcs.mailbox = {}; diff --git a/www/common/toolbar.js b/www/common/toolbar.js index 2b0d2f648..e950b3981 100644 --- a/www/common/toolbar.js +++ b/www/common/toolbar.js @@ -1416,7 +1416,7 @@ MessengerUI, Messages, Pages, PadTypes) { tb['pad'] = function () { toolbar.$file.show(); - addElement([ + toolbar.addElement([ 'chat', 'collapse', 'userlist', 'title', 'useradmin', 'spinner', diff --git a/www/form/app-form.less b/www/form/app-form.less index 00fdfafb2..2042999ce 100644 --- a/www/form/app-form.less +++ b/www/form/app-form.less @@ -980,6 +980,7 @@ .cp-radio, .cp-checkmark { display: inline-flex; max-width: 100%; + padding: 0.313rem 0; } .cp-checkmark-label { word-break: break-word; @@ -1043,7 +1044,7 @@ } .cp-form-sort-order { border: 1px solid @cryptpad_text_col; - padding: 0 5px; + padding: 0 0.313rem; margin-right: 5px; } &:hover { @@ -1318,6 +1319,22 @@ } } } + .cp-radio { + margin: 0.2rem 0; + } + .cp-form-status { + margin-bottom: 0.2rem; + } + .cp-form-mute-radio { + margin-top: 0.2rem; + } + .cp-form-privacy-container { + margin-top: 0.8rem + } + .cp-form-results-type { + display: inline-block; + margin: 0.2rem 0 0.2rem 0; + } } } & > .flatpickr-calendar { diff --git a/www/form/inner.js b/www/form/inner.js index 3428d98b6..661b0ee98 100644 --- a/www/form/inner.js +++ b/www/form/inner.js @@ -1097,6 +1097,11 @@ define([ block = h('div.cp-form-edit-options-block', [t]); cm = SFCodeMirror.create("gfm", CMeditor, t); editor = cm.editor; + editor.setOption("extraKeys", { + "Esc": function () { + editor.display.input.blur(); + }, + }); editor.setOption('lineNumbers', true); editor.setOption('lineWrapping', true); editor.setOption('styleActiveLine', true); @@ -4928,7 +4933,7 @@ define([ // End date / Closed state var endDateContainer = h('div.cp-form-status-container'); - var endDateStr = h('div'); + var endDateStr = h('div.cp-form-status'); var $endDate = $(endDateContainer); var $endDateStr = $(endDateStr);