mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-05-07 23:55:12 -04:00
Converted more files to typescript.
This commit is contained in:
parent
93dffc0e37
commit
c24ae14cf4
14 changed files with 94 additions and 51 deletions
|
@ -47,13 +47,13 @@ exports.init = async () => {
|
|||
}
|
||||
for (const fn of ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove']) {
|
||||
const f = exports.db[fn];
|
||||
exports[fn] = async (...args) => await f.call(exports.db, ...args);
|
||||
exports[fn] = async (...args:string[]) => await f.call(exports.db, ...args);
|
||||
Object.setPrototypeOf(exports[fn], Object.getPrototypeOf(f));
|
||||
Object.defineProperties(exports[fn], Object.getOwnPropertyDescriptors(f));
|
||||
}
|
||||
};
|
||||
|
||||
exports.shutdown = async (hookName, context) => {
|
||||
exports.shutdown = async (hookName: string, context:any) => {
|
||||
if (exports.db != null) await exports.db.close();
|
||||
exports.db = null;
|
||||
logger.log('Database closed');
|
|
@ -34,9 +34,10 @@ class SessionStore extends Store {
|
|||
for (const {timeout} of this._expirations.values()) clearTimeout(timeout);
|
||||
}
|
||||
|
||||
async _updateExpirations(sid, sess, updateDbExp = true) {
|
||||
async _updateExpirations(sid: string, sess: any, updateDbExp = true) {
|
||||
const exp = this._expirations.get(sid) || {};
|
||||
clearTimeout(exp.timeout);
|
||||
// @ts-ignore
|
||||
const {cookie: {expires} = {}} = sess || {};
|
||||
if (expires) {
|
||||
const sessExp = new Date(expires).getTime();
|
||||
|
@ -63,23 +64,23 @@ class SessionStore extends Store {
|
|||
return sess;
|
||||
}
|
||||
|
||||
async _write(sid, sess) {
|
||||
async _write(sid: string, sess: any) {
|
||||
await DB.set(`sessionstorage:${sid}`, sess);
|
||||
}
|
||||
|
||||
async _get(sid) {
|
||||
async _get(sid: string) {
|
||||
logger.debug(`GET ${sid}`);
|
||||
const s = await DB.get(`sessionstorage:${sid}`);
|
||||
return await this._updateExpirations(sid, s);
|
||||
}
|
||||
|
||||
async _set(sid, sess) {
|
||||
async _set(sid: string, sess:any) {
|
||||
logger.debug(`SET ${sid}`);
|
||||
sess = await this._updateExpirations(sid, sess);
|
||||
if (sess != null) await this._write(sid, sess);
|
||||
}
|
||||
|
||||
async _destroy(sid) {
|
||||
async _destroy(sid:string) {
|
||||
logger.debug(`DESTROY ${sid}`);
|
||||
clearTimeout((this._expirations.get(sid) || {}).timeout);
|
||||
this._expirations.delete(sid);
|
||||
|
@ -89,7 +90,7 @@ class SessionStore extends Store {
|
|||
// Note: express-session might call touch() before it calls set() for the first time. Ideally this
|
||||
// would behave like set() in that case but it's OK if it doesn't -- express-session will call
|
||||
// set() soon enough.
|
||||
async _touch(sid, sess) {
|
||||
async _touch(sid: string, sess:any) {
|
||||
logger.debug(`TOUCH ${sid}`);
|
||||
sess = await this._updateExpirations(sid, sess, false);
|
||||
if (sess == null) return; // Already expired.
|
5
src/node/models/AsyncQueueTask.ts
Normal file
5
src/node/models/AsyncQueueTask.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export type AsyncQueueTask = {
|
||||
srcFile: string,
|
||||
destFile: string,
|
||||
type: string
|
||||
}
|
8
src/node/models/PromiseWithStd.ts
Normal file
8
src/node/models/PromiseWithStd.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import {Readable} from "node:stream";
|
||||
import {ChildProcess} from "node:child_process";
|
||||
|
||||
export type PromiseWithStd = {
|
||||
stdout?: Readable|null,
|
||||
stderr?: Readable|null,
|
||||
child?: ChildProcess
|
||||
} & Promise<any>
|
15
src/node/models/RunCMDOptions.ts
Normal file
15
src/node/models/RunCMDOptions.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
export type RunCMDOptions = {
|
||||
cwd?: string,
|
||||
stdio?: string[],
|
||||
env?: NodeJS.ProcessEnv
|
||||
}
|
||||
|
||||
export type RunCMDPromise = {
|
||||
stdout?:Function,
|
||||
stderr?:Function
|
||||
}
|
||||
|
||||
export type ErrorExtended = {
|
||||
code?: number|null,
|
||||
signal?: NodeJS.Signals|null
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
const securityManager = require('./db/SecurityManager');
|
||||
|
||||
// checks for padAccess
|
||||
module.exports = async (req, res) => {
|
||||
module.exports = async (req: { params?: any; cookies?: any; session?: any; }, res: { status: (arg0: number) => { (): any; new(): any; send: { (arg0: string): void; new(): any; }; }; }) => {
|
||||
const {session: {user} = {}} = req;
|
||||
const accessObj = await securityManager.checkAccess(
|
||||
req.params.pad, req.cookies.sessionID, req.cookies.token, user);
|
|
@ -4,6 +4,6 @@ const measured = require('measured-core');
|
|||
|
||||
module.exports = measured.createCollection();
|
||||
|
||||
module.exports.shutdown = async (hookName, context) => {
|
||||
module.exports.shutdown = async (hookName: string, context:any) => {
|
||||
module.exports.end();
|
||||
};
|
|
@ -19,6 +19,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {ChildProcess} from "node:child_process";
|
||||
import {AsyncQueueTask} from "../models/AsyncQueueTask";
|
||||
|
||||
const spawn = require('child_process').spawn;
|
||||
const async = require('async');
|
||||
const settings = require('./Settings');
|
||||
|
@ -27,13 +30,13 @@ const os = require('os');
|
|||
// on windows we have to spawn a process for each convertion,
|
||||
// cause the plugin abicommand doesn't exist on this platform
|
||||
if (os.type().indexOf('Windows') > -1) {
|
||||
exports.convertFile = async (srcFile, destFile, type) => {
|
||||
exports.convertFile = async (srcFile: string, destFile: string, type: string) => {
|
||||
const abiword = spawn(settings.abiword, [`--to=${destFile}`, srcFile]);
|
||||
let stdoutBuffer = '';
|
||||
abiword.stdout.on('data', (data) => { stdoutBuffer += data.toString(); });
|
||||
abiword.stderr.on('data', (data) => { stdoutBuffer += data.toString(); });
|
||||
await new Promise((resolve, reject) => {
|
||||
abiword.on('exit', (code) => {
|
||||
abiword.stdout.on('data', (data: string) => { stdoutBuffer += data.toString(); });
|
||||
abiword.stderr.on('data', (data: string) => { stdoutBuffer += data.toString(); });
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
abiword.on('exit', (code: number) => {
|
||||
if (code !== 0) return reject(new Error(`Abiword died with exit code ${code}`));
|
||||
if (stdoutBuffer !== '') {
|
||||
console.log(stdoutBuffer);
|
||||
|
@ -46,13 +49,13 @@ if (os.type().indexOf('Windows') > -1) {
|
|||
// communicate with it via stdin/stdout
|
||||
// thats much faster, about factor 10
|
||||
} else {
|
||||
let abiword;
|
||||
let stdoutCallback = null;
|
||||
let abiword: ChildProcess;
|
||||
let stdoutCallback: Function|null = null;
|
||||
const spawnAbiword = () => {
|
||||
abiword = spawn(settings.abiword, ['--plugin', 'AbiCommand']);
|
||||
let stdoutBuffer = '';
|
||||
let firstPrompt = true;
|
||||
abiword.stderr.on('data', (data) => { stdoutBuffer += data.toString(); });
|
||||
abiword.stderr!.on('data', (data) => { stdoutBuffer += data.toString(); });
|
||||
abiword.on('exit', (code) => {
|
||||
spawnAbiword();
|
||||
if (stdoutCallback != null) {
|
||||
|
@ -60,7 +63,7 @@ if (os.type().indexOf('Windows') > -1) {
|
|||
stdoutCallback = null;
|
||||
}
|
||||
});
|
||||
abiword.stdout.on('data', (data) => {
|
||||
abiword.stdout!.on('data', (data) => {
|
||||
stdoutBuffer += data.toString();
|
||||
// we're searching for the prompt, cause this means everything we need is in the buffer
|
||||
if (stdoutBuffer.search('AbiWord:>') !== -1) {
|
||||
|
@ -76,15 +79,15 @@ if (os.type().indexOf('Windows') > -1) {
|
|||
};
|
||||
spawnAbiword();
|
||||
|
||||
const queue = async.queue((task, callback) => {
|
||||
abiword.stdin.write(`convert ${task.srcFile} ${task.destFile} ${task.type}\n`);
|
||||
stdoutCallback = (err) => {
|
||||
const queue = async.queue((task: AsyncQueueTask, callback:Function) => {
|
||||
abiword.stdin!.write(`convert ${task.srcFile} ${task.destFile} ${task.type}\n`);
|
||||
stdoutCallback = (err: string) => {
|
||||
if (err != null) console.error('Abiword File failed to convert', err);
|
||||
callback(err);
|
||||
};
|
||||
}, 1);
|
||||
|
||||
exports.convertFile = async (srcFile, destFile, type) => {
|
||||
exports.convertFile = async (srcFile: string, destFile: string, type: string) => {
|
||||
await queue.pushAsync({srcFile, destFile, type});
|
||||
};
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const log4js = require('log4js');
|
||||
const path = require('path');
|
||||
const _ = require('underscore');
|
||||
|
@ -29,7 +28,7 @@ const absPathLogger = log4js.getLogger('AbsolutePaths');
|
|||
* findEtherpadRoot() computes its value only on first invocation.
|
||||
* Subsequent invocations are served from this variable.
|
||||
*/
|
||||
let etherpadRoot = null;
|
||||
let etherpadRoot: string|null = null;
|
||||
|
||||
/**
|
||||
* If stringArray's last elements are exactly equal to lastDesiredElements,
|
||||
|
@ -41,7 +40,7 @@ let etherpadRoot = null;
|
|||
* @return {string[]|boolean} The shortened array, or false if there was no
|
||||
* overlap.
|
||||
*/
|
||||
const popIfEndsWith = (stringArray, lastDesiredElements) => {
|
||||
const popIfEndsWith = (stringArray: string[], lastDesiredElements: string[]): string[] | false => {
|
||||
if (stringArray.length <= lastDesiredElements.length) {
|
||||
absPathLogger.debug(`In order to pop "${lastDesiredElements.join(path.sep)}" ` +
|
||||
`from "${stringArray.join(path.sep)}", it should contain at least ` +
|
||||
|
@ -131,7 +130,7 @@ exports.findEtherpadRoot = () => {
|
|||
* it is returned unchanged. Otherwise it is interpreted
|
||||
* relative to exports.root.
|
||||
*/
|
||||
exports.makeAbsolute = (somePath) => {
|
||||
exports.makeAbsolute = (somePath: string) => {
|
||||
if (path.isAbsolute(somePath)) {
|
||||
return somePath;
|
||||
}
|
||||
|
@ -150,10 +149,8 @@ exports.makeAbsolute = (somePath) => {
|
|||
* a subdirectory of the base one
|
||||
* @return {boolean}
|
||||
*/
|
||||
exports.isSubdir = (parent, arbitraryDir) => {
|
||||
exports.isSubdir = (parent: string, arbitraryDir: string): boolean => {
|
||||
// modified from: https://stackoverflow.com/questions/37521893/determine-if-a-path-is-subdirectory-of-another-in-node-js#45242825
|
||||
const relative = path.relative(parent, arbitraryDir);
|
||||
const isSubdir = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
||||
|
||||
return isSubdir;
|
||||
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
||||
};
|
|
@ -3,8 +3,8 @@
|
|||
* Generates a random String with the given length. Is needed to generate the
|
||||
* Author, Group, readonly, session Ids
|
||||
*/
|
||||
const crypto = require('crypto');
|
||||
const cryptoMod = require('crypto');
|
||||
|
||||
const randomString = (len) => crypto.randomBytes(len).toString('hex');
|
||||
const randomString = (len: string) => cryptoMod.randomBytes(len).toString('hex');
|
||||
|
||||
module.exports = randomString;
|
|
@ -1,5 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
import {ErrorExtended, RunCMDOptions, RunCMDPromise} from "../models/RunCMDOptions";
|
||||
import {ChildProcess} from "node:child_process";
|
||||
import {PromiseWithStd} from "../models/PromiseWithStd";
|
||||
import {Readable} from "node:stream";
|
||||
|
||||
const spawn = require('cross-spawn');
|
||||
const log4js = require('log4js');
|
||||
const path = require('path');
|
||||
|
@ -7,12 +12,12 @@ const settings = require('./Settings');
|
|||
|
||||
const logger = log4js.getLogger('runCmd');
|
||||
|
||||
const logLines = (readable, logLineFn) => {
|
||||
readable.setEncoding('utf8');
|
||||
const logLines = (readable: undefined | Readable | null, logLineFn: (arg0: (string | undefined)) => void) => {
|
||||
readable!.setEncoding('utf8');
|
||||
// The process won't necessarily write full lines every time -- it might write a part of a line
|
||||
// then write the rest of the line later.
|
||||
let leftovers = '';
|
||||
readable.on('data', (chunk) => {
|
||||
let leftovers: string| undefined = '';
|
||||
readable!.on('data', (chunk) => {
|
||||
const lines = chunk.split('\n');
|
||||
if (lines.length === 0) return;
|
||||
lines[0] = leftovers + lines[0];
|
||||
|
@ -21,7 +26,7 @@ const logLines = (readable, logLineFn) => {
|
|||
logLineFn(line);
|
||||
}
|
||||
});
|
||||
readable.on('end', () => {
|
||||
readable!.on('end', () => {
|
||||
if (leftovers !== '') logLineFn(leftovers);
|
||||
leftovers = '';
|
||||
});
|
||||
|
@ -69,7 +74,7 @@ const logLines = (readable, logLineFn) => {
|
|||
* - `stderr`: Similar to `stdout` but for stderr.
|
||||
* - `child`: The ChildProcess object.
|
||||
*/
|
||||
module.exports = exports = (args, opts = {}) => {
|
||||
module.exports = exports = (args: string[], opts:RunCMDOptions = {}) => {
|
||||
logger.debug(`Executing command: ${args.join(' ')}`);
|
||||
|
||||
opts = {cwd: settings.root, ...opts};
|
||||
|
@ -82,8 +87,8 @@ module.exports = exports = (args, opts = {}) => {
|
|||
: opts.stdio === 'string' ? [null, 'string', 'string']
|
||||
: Array(3).fill(opts.stdio);
|
||||
const cmdLogger = log4js.getLogger(`runCmd|${args[0]}`);
|
||||
if (stdio[1] == null) stdio[1] = (line) => cmdLogger.info(line);
|
||||
if (stdio[2] == null) stdio[2] = (line) => cmdLogger.error(line);
|
||||
if (stdio[1] == null) stdio[1] = (line: string) => cmdLogger.info(line);
|
||||
if (stdio[2] == null) stdio[2] = (line: string) => cmdLogger.error(line);
|
||||
const stdioLoggers = [];
|
||||
const stdioSaveString = [];
|
||||
for (const fd of [1, 2]) {
|
||||
|
@ -116,13 +121,13 @@ module.exports = exports = (args, opts = {}) => {
|
|||
|
||||
// Create an error object to use in case the process fails. This is done here rather than in the
|
||||
// process's `exit` handler so that we get a useful stack trace.
|
||||
const procFailedErr = new Error();
|
||||
const procFailedErr: Error & ErrorExtended = new Error();
|
||||
|
||||
const proc = spawn(args[0], args.slice(1), opts);
|
||||
const streams = [undefined, proc.stdout, proc.stderr];
|
||||
const proc: ChildProcess = spawn(args[0], args.slice(1), opts);
|
||||
const streams:[undefined, Readable|null, Readable|null] = [undefined, proc.stdout, proc.stderr];
|
||||
|
||||
let px;
|
||||
const p = new Promise((resolve, reject) => { px = {resolve, reject}; });
|
||||
let px: { reject: any; resolve: any; };
|
||||
const p:PromiseWithStd = new Promise<string>((resolve, reject) => { px = {resolve, reject}; });
|
||||
[, p.stdout, p.stderr] = streams;
|
||||
p.child = proc;
|
||||
|
||||
|
@ -132,9 +137,10 @@ module.exports = exports = (args, opts = {}) => {
|
|||
if (stdioLoggers[fd] != null) {
|
||||
logLines(streams[fd], stdioLoggers[fd]);
|
||||
} else if (stdioSaveString[fd]) {
|
||||
// @ts-ignore
|
||||
p[[null, 'stdout', 'stderr'][fd]] = stdioStringPromises[fd] = (async () => {
|
||||
const chunks = [];
|
||||
for await (const chunk of streams[fd]) chunks.push(chunk);
|
||||
for await (const chunk of streams[fd]!) chunks.push(chunk);
|
||||
return Buffer.concat(chunks).toString().replace(/\n+$/g, '');
|
||||
})();
|
||||
}
|
6
src/package-lock.json
generated
6
src/package-lock.json
generated
|
@ -409,6 +409,12 @@
|
|||
"integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/async": {
|
||||
"version": "3.2.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.24.tgz",
|
||||
"integrity": "sha512-8iHVLHsCCOBKjCF2KwFe0p9Z3rfM9mL+sSP8btyR5vTjJRAqpBYD28/ZLgXPf0pjG1VxOvtCV/BgXkQbpSe8Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
|
|
|
@ -68,17 +68,18 @@
|
|||
"terser": "^5.27.0",
|
||||
"threads": "^1.7.0",
|
||||
"tinycon": "0.6.8",
|
||||
"tsx": "^4.7.0",
|
||||
"ueberdb2": "^4.2.48",
|
||||
"underscore": "1.13.6",
|
||||
"unorm": "1.6.0",
|
||||
"wtfnode": "^0.9.1",
|
||||
"tsx": "^4.7.0"
|
||||
"wtfnode": "^0.9.1"
|
||||
},
|
||||
"bin": {
|
||||
"etherpad-healthcheck": "bin/etherpad-healthcheck",
|
||||
"etherpad-lite": "node/server.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/async": "^3.2.24",
|
||||
"typescript": "^5.3.3",
|
||||
"@types/node": "^20.11.5",
|
||||
"eslint": "^8.56.0",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
"moduleDetection": "force",
|
||||
"lib": ["es6"],
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
|
@ -11,7 +12,7 @@
|
|||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"target": "es6", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue