mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
Refactor lib/ to be native Typescript (#5217)
This commit is contained in:
parent
8c25d8dad6
commit
6e122d5d74
|
|
@ -2,4 +2,4 @@ server/tournaments/lib/
|
|||
logs/
|
||||
dev-tools/globals.js
|
||||
node_modules/
|
||||
.sim-dist/
|
||||
.*-dist/
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -10,7 +10,7 @@ npm-debug.log
|
|||
package-lock.json
|
||||
|
||||
# Typescript build artifacts
|
||||
.sim-dist/
|
||||
.*-dist/
|
||||
|
||||
# visual studio live share
|
||||
.vs
|
||||
|
|
|
|||
3
.lib-dist/README.md
Normal file
3
.lib-dist/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
**NOTE**: This folder contains the compiled output of the `lib/` directory.
|
||||
You should be editing the `.ts` files there and then running `npm run build` or
|
||||
`./pokemon-showdown` to force these `.js` files to be recreated.
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
**NOTE**: This folder contains the compiled output of the `sim/` directory.
|
||||
You should be editting the `.ts` files there and then running `npm run build` or
|
||||
You should be editing the `.ts` files there and then running `npm run build` or
|
||||
`./pokemon-showdown` to force these `.js` files to be recreated.
|
||||
|
|
|
|||
7
build
7
build
|
|
@ -12,6 +12,9 @@ var fs = require('fs');
|
|||
var path = require('path');
|
||||
|
||||
function shell(cmd) { child_process.execSync(cmd, {stdio: 'inherit', cwd: __dirname}); }
|
||||
function sucrase(src, out) {
|
||||
shell(`npx sucrase -q ${src} -d ${out} --transforms typescript,imports --enable-legacy-typescript-module-interop`);
|
||||
}
|
||||
|
||||
try {
|
||||
require.resolve('sucrase');
|
||||
|
|
@ -20,7 +23,9 @@ try {
|
|||
shell('npm install');
|
||||
}
|
||||
|
||||
shell('npx sucrase -q ./sim -d ./.sim-dist --transforms typescript,imports --enable-legacy-typescript-module-interop');
|
||||
sucrase('./sim', './.sim-dist');
|
||||
sucrase('./lib', './.lib-dist');
|
||||
shell('npx replace --silent \'(require\\\(.*?)(lib)(.*?\\\))\' \'$1.lib-dist$3\' .sim-dist/*');
|
||||
|
||||
// Make sure config.js exists. If not, copy it over synchronously from
|
||||
// config-example.js, since it's needed before we can start the server
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class RandomGen3Teams extends RandomGen4Teams {
|
|||
template = this.getTemplate('unown');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../../../lib/crashlogger')(err, 'The gen 3 randbat set generator');
|
||||
Monitor.crashlog(err, 'The gen 3 randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) species = template.baseSpecies;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class RandomGen4Teams extends RandomGen5Teams {
|
|||
template = this.getTemplate('unown');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../../../lib/crashlogger')(err, 'The gen 4 randbat set generator');
|
||||
Monitor.crashlog(err, 'The gen 4 randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) species = template.baseSpecies;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class RandomGen5Teams extends RandomGen6Teams {
|
|||
template = this.getTemplate('unown');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../../../lib/crashlogger')(err, 'The gen 5 randbat set generator');
|
||||
Monitor.crashlog(err, 'The gen 5 randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class RandomGen6Teams extends RandomTeams {
|
|||
template = this.getTemplate('unown');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../../../lib/crashlogger')(err, 'The gen 6 randbat set generator');
|
||||
Monitor.crashlog(err, 'The gen 6 randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class RandomLetsGoTeams extends RandomTeams {
|
|||
template = this.getTemplate('bulbasaur');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../../../lib/crashlogger')(err, 'The Let\'s Go randbat set generator');
|
||||
Monitor.crashlog(err, 'The Let\'s Go randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) {
|
||||
|
|
|
|||
|
|
@ -611,7 +611,7 @@ class RandomTeams extends Dex.ModdedDex {
|
|||
template = this.getTemplate('unown');
|
||||
|
||||
let err = new Error('Template incompatible with random battles: ' + species);
|
||||
require('../lib/crashlogger')(err, 'The randbat set generator');
|
||||
Monitor.crashlog(err, 'The randbat set generator');
|
||||
}
|
||||
|
||||
if (template.battleOnly) {
|
||||
|
|
|
|||
2
dev-tools/global.d.ts
vendored
2
dev-tools/global.d.ts
vendored
|
|
@ -18,7 +18,7 @@ import UsersType = require('./../server/users');
|
|||
import PunishmentsType = require('./../server/punishments');
|
||||
import ChatType = require('./../server/chat');
|
||||
|
||||
import StreamsType = require('./../lib/streams');
|
||||
import * as StreamsType from './../lib/streams';
|
||||
|
||||
declare global {
|
||||
// modules
|
||||
|
|
|
|||
|
|
@ -8,45 +8,38 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const CRASH_EMAIL_THROTTLE = 5 * 60 * 1000; // 5 minutes
|
||||
const LOCKDOWN_PERIOD = 30 * 60 * 1000; // 30 minutes
|
||||
|
||||
const logPath = path.resolve(__dirname, '../logs/errors.txt');
|
||||
let lastCrashLog = 0;
|
||||
/** @type {any} */
|
||||
let transport;
|
||||
let transport: any;
|
||||
|
||||
/**
|
||||
* Logs when a crash happens to console, then e-mails those who are configured
|
||||
* to receive them.
|
||||
*
|
||||
* @param {Error | string} err
|
||||
* @param {string} description
|
||||
* @param {?Object} [data = null]
|
||||
* @return {?string}
|
||||
*/
|
||||
module.exports = function crashlogger(err, description, data = null) {
|
||||
export = function crashlogger(error: Error | string, description: string, data: object | null = null): string | null {
|
||||
const datenow = Date.now();
|
||||
|
||||
let stack = typeof err === 'string' ? err : err.stack;
|
||||
let stack = typeof error === 'string' ? error : error.stack;
|
||||
if (data) {
|
||||
stack += `\n\nAdditional information:\n`;
|
||||
for (let k in data) {
|
||||
// @ts-ignore
|
||||
stack += ` ${k} = ${data[k]}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(`\nCRASH: ${stack}\n`);
|
||||
let out = fs.createWriteStream(logPath, {'flags': 'a'});
|
||||
let out = fs.createWriteStream(logPath, {flags: 'a'});
|
||||
out.on('open', () => {
|
||||
out.write(`\n${stack}\n`);
|
||||
out.end();
|
||||
}).on('error', /** @param {Error} err */ err => {
|
||||
}).on('error', (err: Error) => {
|
||||
console.error(`\nSUBCRASH: ${err.stack}\n`);
|
||||
});
|
||||
|
||||
|
|
@ -69,6 +62,7 @@ module.exports = function crashlogger(err, description, data = null) {
|
|||
text += `again with this stack trace:\n${stack}`;
|
||||
} else {
|
||||
try {
|
||||
// tslint:disable-next-line:no-implicit-dependencies
|
||||
transport = require('nodemailer').createTransport(Config.crashguardemail.options);
|
||||
} catch (e) {
|
||||
throw new Error("Failed to start nodemailer; are you sure you've configured Config.crashguardemail correctly?");
|
||||
|
|
@ -82,7 +76,7 @@ module.exports = function crashlogger(err, description, data = null) {
|
|||
to: Config.crashguardemail.to,
|
||||
subject: Config.crashguardemail.subject,
|
||||
text,
|
||||
}, /** @param {?Error} err */ err => {
|
||||
}, (err: Error | null) => {
|
||||
if (err) console.error(`Error sending email: ${err}`);
|
||||
});
|
||||
}
|
||||
|
|
@ -12,8 +12,6 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const CODE_MAP = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
const UNSAFE_MAP = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
|
|
@ -31,19 +29,14 @@ const UNSAFE_MAP = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
|||
* An object representing a Dashycode bitstream.
|
||||
* The stream can be either a read stream or a write stream, but not
|
||||
* both simultaneously.
|
||||
*
|
||||
* @typedef {Object} DashyStream
|
||||
* @property {string} codeBuf
|
||||
* @property {number} buf
|
||||
* @property {number} bufLength
|
||||
*/
|
||||
interface DashyStream {
|
||||
codeBuf: string;
|
||||
buf: number;
|
||||
bufLength: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DashyStream} stream
|
||||
* @param {number} writeBufLength in bits
|
||||
* @param {number} writeBuf
|
||||
*/
|
||||
function streamWrite(stream, writeBufLength, writeBuf) {
|
||||
function streamWrite(stream: DashyStream, writeBufLength: number, writeBuf: number) {
|
||||
stream.buf += (writeBuf << stream.bufLength);
|
||||
stream.bufLength += writeBufLength;
|
||||
while (stream.bufLength >= 5) {
|
||||
|
|
@ -52,10 +45,8 @@ function streamWrite(stream, writeBufLength, writeBuf) {
|
|||
stream.bufLength -= 5;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {DashyStream} stream
|
||||
*/
|
||||
function streamGetCode(stream) {
|
||||
|
||||
function streamGetCode(stream: DashyStream) {
|
||||
const buf = stream.codeBuf + CODE_MAP.charAt(stream.buf);
|
||||
|
||||
// truncate trailing `2`s (0b00000 chunks)
|
||||
|
|
@ -64,12 +55,7 @@ function streamGetCode(stream) {
|
|||
return end2Len ? buf.slice(0, -end2Len) : buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DashyStream} stream
|
||||
* @param {number} readLength
|
||||
* @param {number} readMask passed for "perf"
|
||||
*/
|
||||
function streamPeek(stream, readLength, readMask = 0xFFFF >> (16 - readLength)) {
|
||||
function streamPeek(stream: DashyStream, readLength: number, readMask: number = 0xFFFF >> (16 - readLength)) {
|
||||
while (stream.bufLength < readLength && stream.codeBuf.length) {
|
||||
const next5Bits = CODE_MAP.indexOf(stream.codeBuf.charAt(0));
|
||||
if (next5Bits < 0) throw new Error("Invalid character in coded buffer");
|
||||
|
|
@ -79,12 +65,8 @@ function streamPeek(stream, readLength, readMask = 0xFFFF >> (16 - readLength))
|
|||
}
|
||||
return stream.buf & readMask;
|
||||
}
|
||||
/**
|
||||
* @param {DashyStream} stream
|
||||
* @param {number} readLength
|
||||
* @param {number} readMask passed for "perf"
|
||||
*/
|
||||
function streamRead(stream, readLength, readMask = 0xFFFF >> (16 - readLength)) {
|
||||
|
||||
function streamRead(stream: DashyStream, readLength: number, readMask: number = 0xFFFF >> (16 - readLength)) {
|
||||
const output = streamPeek(stream, readLength, readMask);
|
||||
// Note: bufLength can go negative! Streams have infinite trailing 0s
|
||||
stream.buf >>= readLength;
|
||||
|
|
@ -92,17 +74,14 @@ function streamRead(stream, readLength, readMask = 0xFFFF >> (16 - readLength))
|
|||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
*/
|
||||
function encode(str, allowCaps = false) {
|
||||
export function encode(str: string, allowCaps: boolean = false) {
|
||||
if (!str) return '0--0';
|
||||
let safePart = '';
|
||||
let unsafeStream = /** @type {DashyStream} */ ({
|
||||
let unsafeStream: DashyStream = {
|
||||
codeBuf: '',
|
||||
buf: 0x0,
|
||||
bufLength: 0,
|
||||
});
|
||||
};
|
||||
let isSafe = true;
|
||||
let alphaIndex = 0;
|
||||
let capBuffer = 0x0;
|
||||
|
|
@ -169,6 +148,7 @@ function encode(str, allowCaps = false) {
|
|||
streamWrite(unsafeStream, 2, 0x0);
|
||||
} else if (curCharCode === 32) { // space
|
||||
streamWrite(unsafeStream, 3, 0x3);
|
||||
// tslint:disable-next-line:no-conditional-assignment
|
||||
} else if ((unsafeMapIndex = UNSAFE_MAP.indexOf(str.charAt(i))) >= 0) {
|
||||
curCharCode = (unsafeMapIndex << 2) + 0x2;
|
||||
streamWrite(unsafeStream, 7, curCharCode);
|
||||
|
|
@ -194,10 +174,7 @@ function encode(str, allowCaps = false) {
|
|||
return safePart + '--' + unsafePart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} codedStr
|
||||
*/
|
||||
function decode(codedStr) {
|
||||
export function decode(codedStr: string) {
|
||||
let str = '';
|
||||
let lastDashIndex = codedStr.lastIndexOf('--');
|
||||
if (lastDashIndex < 0) {
|
||||
|
|
@ -216,11 +193,11 @@ function decode(codedStr) {
|
|||
codedStr = '-' + codedStr.slice(0, -1);
|
||||
lastDashIndex += 1;
|
||||
}
|
||||
let unsafeStream = /** @type {DashyStream} */ ({
|
||||
let unsafeStream: DashyStream = {
|
||||
codeBuf: codedStr.slice(lastDashIndex + 2),
|
||||
buf: 0x0,
|
||||
bufLength: 0,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Status:
|
||||
* 1 : awaiting next read
|
||||
|
|
@ -289,10 +266,7 @@ function decode(codedStr) {
|
|||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} codeBuf
|
||||
*/
|
||||
function vizStream(codeBuf, translate = true) {
|
||||
export function vizStream(codeBuf: string, translate: boolean = true) {
|
||||
let spacedStream = '';
|
||||
if (codeBuf.charAt(0) === '0') {
|
||||
codeBuf = codeBuf.slice(1);
|
||||
|
|
@ -302,16 +276,18 @@ function vizStream(codeBuf, translate = true) {
|
|||
codeBuf = codeBuf.slice(0, -1);
|
||||
spacedStream = ' [start unsafe]' + spacedStream;
|
||||
}
|
||||
let stream = /** @type {DashyStream} */ ({
|
||||
let stream: DashyStream = {
|
||||
codeBuf,
|
||||
buf: 0x0,
|
||||
bufLength: 0,
|
||||
});
|
||||
function vizBlock(/** @type {DashyStream} */ stream, /** @type {number} */ bufLen) {
|
||||
const buf = streamRead(stream, bufLen);
|
||||
};
|
||||
|
||||
function vizBlock(s: DashyStream, bufLen: number) {
|
||||
const buf = streamRead(s, bufLen);
|
||||
// @ts-ignore
|
||||
return buf.toString(2).padStart(bufLen, '0');
|
||||
}
|
||||
|
||||
while (stream.bufLength > 0 || stream.codeBuf) {
|
||||
switch (streamRead(stream, 2)) {
|
||||
case 0x0:
|
||||
|
|
@ -338,9 +314,3 @@ function vizStream(codeBuf, translate = true) {
|
|||
}
|
||||
return spacedStream;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
encode,
|
||||
decode,
|
||||
vizStream,
|
||||
};
|
||||
|
|
@ -23,71 +23,64 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const pathModule = require('path');
|
||||
const fs = require('fs');
|
||||
const Streams = require('./streams');
|
||||
const WriteStream = Streams.WriteStream;
|
||||
import * as fs from 'fs';
|
||||
import * as pathModule from 'path';
|
||||
import { ReadStream, WriteStream } from './streams';
|
||||
|
||||
const ROOT_PATH = pathModule.resolve(__dirname, '..');
|
||||
|
||||
/*eslint no-unused-expressions: ["error", { "allowTernary": true }]*/
|
||||
interface PendingUpdate {
|
||||
isWriting: boolean; // true: waiting on a call to FS.write, false: waiting on a throttle
|
||||
pendingDataFetcher: (() => string | Buffer) | null;
|
||||
pendingOptions: object | null;
|
||||
throttleTime: number; // throttling until time (0 for no throttle)
|
||||
throttleTimer: NodeJS.Timer | null;
|
||||
}
|
||||
|
||||
const pendingUpdates: Map<string, PendingUpdate> = new Map();
|
||||
|
||||
class FSPath {
|
||||
/**
|
||||
* @param {string} path
|
||||
*/
|
||||
constructor(path) {
|
||||
path: string;
|
||||
|
||||
constructor(path: string) {
|
||||
this.path = pathModule.resolve(ROOT_PATH, path);
|
||||
}
|
||||
|
||||
parentDir() {
|
||||
return new FSPath(pathModule.dirname(this.path));
|
||||
}
|
||||
/**
|
||||
* @param {AnyObject | string} [options]
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
read(options = 'utf8') {
|
||||
|
||||
read(options: AnyObject | string = 'utf8'): Promise<string> {
|
||||
if (typeof options !== 'string' && options.encoding === undefined) {
|
||||
options.encoding = 'utf8';
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(this.path, options, (err, data) => {
|
||||
err ? reject(err) : resolve(/** @type {string} */ (data));
|
||||
err ? reject(err) : resolve(data as string);
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {AnyObject | string} [options]
|
||||
* @return {string}
|
||||
*/
|
||||
readSync(/** @type {AnyObject | string} */ options = 'utf8') {
|
||||
|
||||
readSync(options: AnyObject | string = 'utf8'): string {
|
||||
if (typeof options !== 'string' && options.encoding === undefined) {
|
||||
options.encoding = 'utf8';
|
||||
}
|
||||
return /** @type {string} */ (fs.readFileSync(this.path, options));
|
||||
return fs.readFileSync(this.path, options) as string;
|
||||
}
|
||||
/**
|
||||
* @param {AnyObject | string} [options]
|
||||
* @return {Promise<Buffer>}
|
||||
*/
|
||||
readBuffer(/** @type {AnyObject | string} */ options = {}) {
|
||||
|
||||
readBuffer(options: AnyObject | string = {}): Promise<Buffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(this.path, options, (err, data) => {
|
||||
err ? reject(err) : resolve(/** @type {Buffer} */ (data));
|
||||
err ? reject(err) : resolve(data as Buffer);
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {AnyObject | string} [options]
|
||||
* @return {Buffer}
|
||||
*/
|
||||
readBufferSync(/** @type {AnyObject | string} */ options = {}) {
|
||||
return /** @type {Buffer} */ (fs.readFileSync(this.path, options));
|
||||
|
||||
readBufferSync(options: AnyObject | string = {}) {
|
||||
return fs.readFileSync(this.path, options) as Buffer;
|
||||
}
|
||||
/**
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
readIfExists() {
|
||||
|
||||
readIfExists(): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(this.path, 'utf8', (err, data) => {
|
||||
if (err && err.code === 'ENOENT') return resolve('');
|
||||
|
|
@ -95,6 +88,7 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
readIfExistsSync() {
|
||||
try {
|
||||
return fs.readFileSync(this.path, 'utf8');
|
||||
|
|
@ -103,11 +97,8 @@ class FSPath {
|
|||
}
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
write(data, options = {}) {
|
||||
|
||||
write(data: string | Buffer, options: object = {}) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(this.path, data, options, err => {
|
||||
|
|
@ -115,44 +106,34 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
writeSync(data, options = {}) {
|
||||
|
||||
writeSync(data: string | Buffer, options: object = {}) {
|
||||
if (Config.nofswriting) return;
|
||||
return fs.writeFileSync(this.path, data, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to a new file before renaming to replace an old file. If
|
||||
* the process crashes while writing, the old file won't be lost.
|
||||
* Does not protect against simultaneous writing; use writeUpdate
|
||||
* for that.
|
||||
*
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
async safeWrite(data, options = {}) {
|
||||
async safeWrite(data: string | Buffer, options: object = {}) {
|
||||
await FS(this.path + '.NEW').write(data, options);
|
||||
await FS(this.path + '.NEW').rename(this.path);
|
||||
}
|
||||
/**
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
safeWriteSync(data, options = {}) {
|
||||
|
||||
safeWriteSync(data: string | Buffer, options: object = {}) {
|
||||
FS(this.path + '.NEW').writeSync(data, options);
|
||||
FS(this.path + '.NEW').renameSync(this.path);
|
||||
}
|
||||
/**
|
||||
* @param {number} time
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
waitUntil(time) {
|
||||
|
||||
waitUntil(time: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => resolve(), time - Date.now());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Safest way to update a file with in-memory state. Pass a callback
|
||||
* that fetches the data to be written. It will write an update,
|
||||
|
|
@ -164,15 +145,12 @@ class FSPath {
|
|||
*
|
||||
* No synchronous version because there's no risk of race conditions
|
||||
* with synchronous code; just use `safeWriteSync`.
|
||||
*
|
||||
* @param {() => string | Buffer} dataFetcher
|
||||
* @param {Object} options
|
||||
*/
|
||||
writeUpdate(dataFetcher, options = {}) {
|
||||
writeUpdate(dataFetcher: () => string | Buffer, options: object = {}) {
|
||||
if (Config.nofswriting) return;
|
||||
/** @type {PendingUpdate | undefined} */
|
||||
let pendingUpdate = FS.pendingUpdates.get(this.path);
|
||||
let pendingUpdate: PendingUpdate | undefined = pendingUpdates.get(this.path);
|
||||
|
||||
// @ts-ignore
|
||||
const throttleTime = options.throttle ? Date.now() + options.throttle : 0;
|
||||
|
||||
if (pendingUpdate) {
|
||||
|
|
@ -188,38 +166,36 @@ class FSPath {
|
|||
|
||||
this.writeUpdateNow(dataFetcher, options);
|
||||
}
|
||||
/**
|
||||
* @param {() => string | Buffer} dataFetcher
|
||||
* @param {Object} options
|
||||
*/
|
||||
writeUpdateNow(dataFetcher, options) {
|
||||
|
||||
writeUpdateNow(dataFetcher: () => string | Buffer, options: object) {
|
||||
// @ts-ignore
|
||||
const throttleTime = options.throttle ? Date.now() + options.throttle : 0;
|
||||
const update = {
|
||||
isWriting: true,
|
||||
pendingDataFetcher: null,
|
||||
pendingOptions: null,
|
||||
throttleTime: throttleTime,
|
||||
throttleTime,
|
||||
throttleTimer: null,
|
||||
};
|
||||
FS.pendingUpdates.set(this.path, update);
|
||||
pendingUpdates.set(this.path, update);
|
||||
this.safeWrite(dataFetcher(), options).then(() => this.finishUpdate());
|
||||
}
|
||||
checkNextUpdate() {
|
||||
let pendingUpdate = FS.pendingUpdates.get(this.path);
|
||||
let pendingUpdate = pendingUpdates.get(this.path);
|
||||
if (!pendingUpdate) throw new Error(`FS: Pending update not found`);
|
||||
if (pendingUpdate.isWriting) throw new Error(`FS: Conflicting update`);
|
||||
|
||||
const {pendingDataFetcher: dataFetcher, pendingOptions: options} = pendingUpdate;
|
||||
if (!dataFetcher || !options) {
|
||||
// no pending update
|
||||
FS.pendingUpdates.delete(this.path);
|
||||
pendingUpdates.delete(this.path);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writeUpdateNow(dataFetcher, options);
|
||||
}
|
||||
finishUpdate() {
|
||||
let pendingUpdate = FS.pendingUpdates.get(this.path);
|
||||
let pendingUpdate = pendingUpdates.get(this.path);
|
||||
if (!pendingUpdate) throw new Error(`FS: Pending update not found`);
|
||||
if (!pendingUpdate.isWriting) throw new Error(`FS: Conflicting update`);
|
||||
|
||||
|
|
@ -232,11 +208,8 @@ class FSPath {
|
|||
|
||||
pendingUpdate.throttleTimer = setTimeout(() => this.checkNextUpdate(), throttleTime - Date.now());
|
||||
}
|
||||
/**
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
append(data, options = {}) {
|
||||
|
||||
append(data: string | Buffer, options: object = {}) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.appendFile(this.path, data, options, err => {
|
||||
|
|
@ -244,18 +217,13 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string | Buffer} data
|
||||
* @param {Object} options
|
||||
*/
|
||||
appendSync(data, options = {}) {
|
||||
|
||||
appendSync(data: string | Buffer, options: object = {}) {
|
||||
if (Config.nofswriting) return;
|
||||
return fs.appendFileSync(this.path, data, options);
|
||||
}
|
||||
/**
|
||||
* @param {string} target
|
||||
*/
|
||||
symlinkTo(target) {
|
||||
|
||||
symlinkTo(target: string) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.symlink(target, this.path, err => {
|
||||
|
|
@ -263,17 +231,13 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string} target
|
||||
*/
|
||||
symlinkToSync(target) {
|
||||
|
||||
symlinkToSync(target: string) {
|
||||
if (Config.nofswriting) return;
|
||||
return fs.symlinkSync(target, this.path);
|
||||
}
|
||||
/**
|
||||
* @param {string} target
|
||||
*/
|
||||
rename(target) {
|
||||
|
||||
rename(target: string) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.rename(this.path, target, err => {
|
||||
|
|
@ -281,30 +245,29 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string} target
|
||||
*/
|
||||
renameSync(target) {
|
||||
|
||||
renameSync(target: string) {
|
||||
if (Config.nofswriting) return;
|
||||
return fs.renameSync(this.path, target);
|
||||
}
|
||||
readdir() {
|
||||
|
||||
readdir(): Promise<string[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readdir(this.path, (err, data) => {
|
||||
err ? reject(err) : resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
readdirSync() {
|
||||
return fs.readdirSync(this.path);
|
||||
}
|
||||
|
||||
createReadStream() {
|
||||
return new FileReadStream(this.path);
|
||||
}
|
||||
/**
|
||||
* @return {WriteStream}
|
||||
*/
|
||||
createWriteStream(options = {}) {
|
||||
|
||||
createWriteStream(options = {}): WriteStream {
|
||||
if (Config.nofswriting) {
|
||||
// @ts-ignore
|
||||
return new WriteStream({write() {}});
|
||||
|
|
@ -312,10 +275,8 @@ class FSPath {
|
|||
// @ts-ignore
|
||||
return new WriteStream(fs.createWriteStream(this.path, options));
|
||||
}
|
||||
/**
|
||||
* @return {WriteStream}
|
||||
*/
|
||||
createAppendStream(options = {}) {
|
||||
|
||||
createAppendStream(options = {}): WriteStream {
|
||||
if (Config.nofswriting) {
|
||||
// @ts-ignore
|
||||
return new WriteStream({write() {}});
|
||||
|
|
@ -325,6 +286,7 @@ class FSPath {
|
|||
// @ts-ignore
|
||||
return new WriteStream(fs.createWriteStream(this.path, options));
|
||||
}
|
||||
|
||||
unlinkIfExists() {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -334,6 +296,7 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
unlinkIfExistsSync() {
|
||||
if (Config.nofswriting) return;
|
||||
try {
|
||||
|
|
@ -342,10 +305,8 @@ class FSPath {
|
|||
if (err.code !== 'ENOENT') throw err;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
mkdir(mode = 0o755) {
|
||||
|
||||
mkdir(mode: string | number = 0o755) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.mkdir(this.path, mode, err => {
|
||||
|
|
@ -353,17 +314,13 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
mkdirSync(mode = 0o755) {
|
||||
|
||||
mkdirSync(mode: string | number = 0o755) {
|
||||
if (Config.nofswriting) return;
|
||||
return fs.mkdirSync(this.path, mode);
|
||||
}
|
||||
/**
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
mkdirIfNonexistent(mode = 0o755) {
|
||||
|
||||
mkdirIfNonexistent(mode: string | number = 0o755) {
|
||||
if (Config.nofswriting) return Promise.resolve();
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.mkdir(this.path, mode, err => {
|
||||
|
|
@ -372,10 +329,8 @@ class FSPath {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
mkdirIfNonexistentSync(mode = 0o755) {
|
||||
|
||||
mkdirIfNonexistentSync(mode: string | number = 0o755) {
|
||||
if (Config.nofswriting) return;
|
||||
try {
|
||||
fs.mkdirSync(this.path, mode);
|
||||
|
|
@ -383,12 +338,12 @@ class FSPath {
|
|||
if (err.code !== 'EEXIST') throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the directory (and any parent directories if necessary).
|
||||
* Does not throw if the directory already exists.
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
async mkdirp(mode = 0o755) {
|
||||
async mkdirp(mode: string | number = 0o755) {
|
||||
try {
|
||||
await this.mkdirIfNonexistent(mode);
|
||||
} catch (err) {
|
||||
|
|
@ -397,12 +352,12 @@ class FSPath {
|
|||
await this.mkdirIfNonexistent(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the directory (and any parent directories if necessary).
|
||||
* Does not throw if the directory already exists. Synchronous.
|
||||
* @param {string | number} mode
|
||||
*/
|
||||
mkdirpSync(mode = 0o755) {
|
||||
mkdirpSync(mode: string | number = 0o755) {
|
||||
try {
|
||||
this.mkdirIfNonexistentSync(mode);
|
||||
} catch (err) {
|
||||
|
|
@ -411,36 +366,33 @@ class FSPath {
|
|||
this.mkdirIfNonexistentSync(mode);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Calls the callback if the file is modified.
|
||||
* @param {function (): void} callback
|
||||
*/
|
||||
onModify(callback) {
|
||||
|
||||
/** Calls the callback if the file is modified. */
|
||||
onModify(callback: () => void) {
|
||||
fs.watchFile(this.path, (curr, prev) => {
|
||||
if (curr.mtime > prev.mtime) return callback();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Clears callbacks added with onModify()
|
||||
*/
|
||||
|
||||
/** Clears callbacks added with onModify(). */
|
||||
unwatch() {
|
||||
fs.unwatchFile(this.path);
|
||||
}
|
||||
}
|
||||
|
||||
class FileReadStream extends Streams.ReadStream {
|
||||
/**
|
||||
* @param {string} file
|
||||
*/
|
||||
constructor(file) {
|
||||
class FileReadStream extends ReadStream {
|
||||
fd: Promise<number>;
|
||||
|
||||
constructor(file: string) {
|
||||
super();
|
||||
/** @type {Promise<number>} */
|
||||
this.fd = new Promise((resolve, reject) => {
|
||||
fs.open(file, 'r', (err, fd) => err ? reject(err) : resolve(fd));
|
||||
});
|
||||
this.atEOF = false;
|
||||
}
|
||||
_read(size = 16384) {
|
||||
|
||||
// @ts-ignore
|
||||
_read(size: number = 16384) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.atEOF) return resolve(false);
|
||||
this.ensureCapacity(size);
|
||||
|
|
@ -460,38 +412,20 @@ class FileReadStream extends Streams.ReadStream {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
_destroy() {
|
||||
return /** @type {Promise<void>} */ (new Promise(resolve => {
|
||||
return new Promise(resolve => {
|
||||
this.fd.then(fd => {
|
||||
fs.close(fd, () => resolve());
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
*/
|
||||
function getFs(path) {
|
||||
function getFs(path: string) {
|
||||
return new FSPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {object} PendingUpdate
|
||||
* @property {boolean} isWriting true: waiting on a call to FS.write, false: waiting on a throttle
|
||||
* @property {(() => string | Buffer)?} pendingDataFetcher
|
||||
* @property {Object?} pendingOptions
|
||||
* @property {number} throttleTime throttling until time (0 for no throttle)
|
||||
* @property {NodeJS.Timer?} throttleTimer
|
||||
*/
|
||||
|
||||
const FS = Object.assign(getFs, {
|
||||
export const FS = Object.assign(getFs, {
|
||||
FileReadStream,
|
||||
|
||||
/**
|
||||
* @type {Map<string, PendingUpdate>}
|
||||
*/
|
||||
pendingUpdates: new Map(),
|
||||
});
|
||||
|
||||
module.exports = FS;
|
||||
|
|
@ -9,25 +9,23 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import * as child_process from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as Streams from './streams';
|
||||
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
const Streams = require('./streams');
|
||||
const ROOT_DIR = path.resolve(__dirname, '..');
|
||||
|
||||
export const processManagers: ProcessManager[] = [];
|
||||
export const disabled = false;
|
||||
|
||||
class SubprocessStream extends Streams.ObjectReadWriteStream {
|
||||
/**
|
||||
* @param {ChildProcess} process
|
||||
* @param {number} taskId
|
||||
*/
|
||||
constructor(process, taskId) {
|
||||
constructor(public process: ChildProcess, public taskId: number) {
|
||||
super();
|
||||
this.process = process;
|
||||
this.taskId = taskId;
|
||||
this.process.send(`${taskId}\nNEW`);
|
||||
}
|
||||
_write(/** @type {string} */ message) {
|
||||
_write(message: string) {
|
||||
if (!this.process.connected) return;
|
||||
this.process.send(`${this.taskId}\nWRITE\n${message}`);
|
||||
// responses are handled in ProcessWrapper
|
||||
|
|
@ -38,27 +36,27 @@ class SubprocessStream extends Streams.ObjectReadWriteStream {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ProcessWrapper
|
||||
* @property {number} load
|
||||
* @property {() => Promise<void>} release
|
||||
*/
|
||||
interface ProcessWrapper {
|
||||
load: number;
|
||||
release: () => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the process object in the PARENT process
|
||||
*/
|
||||
class QueryProcessWrapper {
|
||||
constructor(/** @type {string} */ file) {
|
||||
/** Wraps the process object in the PARENT process. */
|
||||
export class QueryProcessWrapper {
|
||||
process: ChildProcess;
|
||||
taskId: number;
|
||||
pendingTasks: Map<number, (resp: string) => void>;
|
||||
pendingRelease: Promise<void> | null;
|
||||
resolveRelease: (() => void) | null;
|
||||
|
||||
constructor(file: string) {
|
||||
this.process = child_process.fork(file, [], {cwd: ROOT_DIR});
|
||||
this.taskId = 0;
|
||||
/** @type {Map<number, (resp: string) => void>} */
|
||||
this.pendingTasks = new Map();
|
||||
/** @type {Promise<void>?} */
|
||||
this.pendingRelease = null;
|
||||
/** @type {(() => void)?} */
|
||||
this.resolveRelease = null;
|
||||
|
||||
this.process.on('message', /** @param {string} message */ message => {
|
||||
this.process.on('message', (message: string) => {
|
||||
const nlLoc = message.indexOf('\n');
|
||||
if (nlLoc <= 0) throw new Error(`Invalid response ${message}`);
|
||||
if (message.slice(0, nlLoc) === 'THROW') {
|
||||
|
|
@ -67,7 +65,7 @@ class QueryProcessWrapper {
|
|||
throw error;
|
||||
}
|
||||
|
||||
const taskId = parseInt(message.slice(0, nlLoc));
|
||||
const taskId = parseInt(message.slice(0, nlLoc), 10);
|
||||
const resolve = this.pendingTasks.get(taskId);
|
||||
if (!resolve) throw new Error(`Invalid taskId ${message.slice(0, nlLoc)}`);
|
||||
this.pendingTasks.delete(taskId);
|
||||
|
|
@ -84,11 +82,7 @@ class QueryProcessWrapper {
|
|||
return this.pendingTasks.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} input
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
query(input) {
|
||||
query(input: any): Promise<any> {
|
||||
this.taskId++;
|
||||
const taskId = this.taskId;
|
||||
this.process.send(`${taskId}\n${JSON.stringify(input)}`);
|
||||
|
|
@ -97,10 +91,7 @@ class QueryProcessWrapper {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
release() {
|
||||
release(): Promise<void> {
|
||||
if (this.pendingRelease) return this.pendingRelease;
|
||||
if (!this.load) {
|
||||
this.destroy();
|
||||
|
|
@ -109,7 +100,7 @@ class QueryProcessWrapper {
|
|||
this.resolveRelease = resolve;
|
||||
});
|
||||
}
|
||||
return /** @type {Promise<void>} */ (this.pendingRelease);
|
||||
return this.pendingRelease as Promise<void>;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
|
@ -132,21 +123,22 @@ class QueryProcessWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the process object in the PARENT process
|
||||
*/
|
||||
class StreamProcessWrapper {
|
||||
constructor(/** @type {string} */ file) {
|
||||
/** Wraps the process object in the PARENT process. */
|
||||
export class StreamProcessWrapper {
|
||||
process: ChildProcess;
|
||||
taskId: number;
|
||||
activeStreams: Map<number, SubprocessStream>;
|
||||
pendingRelease: Promise<void> | null;
|
||||
resolveRelease: (() => void) | null;
|
||||
|
||||
constructor(file: string) {
|
||||
this.process = child_process.fork(file, [], {cwd: ROOT_DIR});
|
||||
this.taskId = 0;
|
||||
/** @type {Map<number, SubprocessStream>} */
|
||||
this.activeStreams = new Map();
|
||||
/** @type {Promise<void>?} */
|
||||
this.pendingRelease = null;
|
||||
/** @type {(() => void)?} */
|
||||
this.resolveRelease = null;
|
||||
|
||||
this.process.on('message', /** @param {string} message */ message => {
|
||||
this.process.on('message', (message: string) => {
|
||||
let nlLoc = message.indexOf('\n');
|
||||
if (nlLoc <= 0) throw new Error(`Invalid response ${message}`);
|
||||
if (message.slice(0, nlLoc) === 'THROW') {
|
||||
|
|
@ -155,7 +147,7 @@ class StreamProcessWrapper {
|
|||
throw error;
|
||||
}
|
||||
|
||||
const taskId = parseInt(message.slice(0, nlLoc));
|
||||
const taskId = parseInt(message.slice(0, nlLoc), 10);
|
||||
const stream = this.activeStreams.get(taskId);
|
||||
if (!stream) throw new Error(`Invalid taskId ${message.slice(0, nlLoc)}`);
|
||||
|
||||
|
|
@ -183,7 +175,7 @@ class StreamProcessWrapper {
|
|||
});
|
||||
}
|
||||
|
||||
deleteStream(/** @type {number} */ taskId) {
|
||||
deleteStream(taskId: number) {
|
||||
this.activeStreams.delete(taskId);
|
||||
// try to release
|
||||
if (this.resolveRelease && !this.load) this.destroy();
|
||||
|
|
@ -193,10 +185,7 @@ class StreamProcessWrapper {
|
|||
return this.activeStreams.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {SubprocessStream}
|
||||
*/
|
||||
createStream() {
|
||||
createStream(): SubprocessStream {
|
||||
this.taskId++;
|
||||
const taskId = this.taskId;
|
||||
const stream = new SubprocessStream(this.process, taskId);
|
||||
|
|
@ -204,10 +193,7 @@ class StreamProcessWrapper {
|
|||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
release() {
|
||||
release(): Promise<void> {
|
||||
if (this.pendingRelease) return this.pendingRelease;
|
||||
if (!this.load) {
|
||||
this.destroy();
|
||||
|
|
@ -216,7 +202,7 @@ class StreamProcessWrapper {
|
|||
this.resolveRelease = resolve;
|
||||
});
|
||||
}
|
||||
return /** @type {Promise<void>} */ (this.pendingRelease);
|
||||
return this.pendingRelease as Promise<void>;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
|
@ -242,19 +228,22 @@ class StreamProcessWrapper {
|
|||
* A ProcessManager wraps a query function: A function that takes a
|
||||
* string and returns a string or Promise<string>.
|
||||
*/
|
||||
class ProcessManager {
|
||||
/**
|
||||
* @param {NodeJS.Module} module
|
||||
*/
|
||||
constructor(module) {
|
||||
/** @type {ProcessWrapper[]} */
|
||||
export class ProcessManager {
|
||||
processes: ProcessWrapper[];
|
||||
releasingProcesses: ProcessWrapper[];
|
||||
// @ts-ignore
|
||||
module: NodeJs.Module;
|
||||
filename: string;
|
||||
basename: string;
|
||||
isParentProcess: boolean;
|
||||
|
||||
// @ts-ignore
|
||||
constructor(module: NodeJs.Module) {
|
||||
this.processes = [];
|
||||
/** @type {ProcessWrapper[]} */
|
||||
this.releasingProcesses = [];
|
||||
this.module = module;
|
||||
this.filename = module.filename;
|
||||
this.basename = path.basename(module.filename);
|
||||
|
||||
this.isParentProcess = (process.mainModule !== module || !process.send);
|
||||
|
||||
this.listen();
|
||||
|
|
@ -285,48 +274,41 @@ class ProcessManager {
|
|||
}
|
||||
spawn(count = 1) {
|
||||
if (!this.isParentProcess) return;
|
||||
if (PMLib.disabled) return;
|
||||
if (disabled) return;
|
||||
while (this.processes.length < count) {
|
||||
this.processes.push(this.createProcess());
|
||||
}
|
||||
}
|
||||
respawn(/** @type {number?} */ count = null) {
|
||||
respawn(count: number | null = null) {
|
||||
if (count === null) count = this.processes.length;
|
||||
this.unspawn();
|
||||
this.spawn(count);
|
||||
}
|
||||
/**
|
||||
* @return {ProcessWrapper}
|
||||
*/
|
||||
createProcess() {
|
||||
createProcess(): ProcessWrapper {
|
||||
throw new Error(`implemented by subclass`);
|
||||
}
|
||||
listen() {
|
||||
throw new Error(`implemented by subclass`);
|
||||
}
|
||||
destroy() {
|
||||
const index = PMLib.processManagers.indexOf(this);
|
||||
if (index) PMLib.processManagers.splice(index, 1);
|
||||
const index = processManagers.indexOf(this);
|
||||
if (index) processManagers.splice(index, 1);
|
||||
this.unspawn();
|
||||
}
|
||||
}
|
||||
|
||||
class QueryProcessManager extends ProcessManager {
|
||||
/**
|
||||
* @param {NodeJS.Module} module
|
||||
* @param {(input: any) => any} query
|
||||
*/
|
||||
constructor(module, query) {
|
||||
export class QueryProcessManager extends ProcessManager {
|
||||
// tslint:disable-next-line:variable-name
|
||||
_query: (input: any) => any;
|
||||
|
||||
constructor(module: NodeJS.Module, query: (input: any) => any) {
|
||||
super(module);
|
||||
this._query = query;
|
||||
|
||||
PMLib.processManagers.push(this);
|
||||
processManagers.push(this);
|
||||
}
|
||||
/**
|
||||
* @param {any} input
|
||||
*/
|
||||
query(input) {
|
||||
const process = /** @type {QueryProcessWrapper} */ (this.acquire());
|
||||
query(input: any) {
|
||||
const process = this.acquire() as QueryProcessWrapper;
|
||||
if (!process) return Promise.resolve(this._query(input));
|
||||
return process.query(input);
|
||||
}
|
||||
|
|
@ -336,15 +318,17 @@ class QueryProcessManager extends ProcessManager {
|
|||
listen() {
|
||||
if (this.isParentProcess) return;
|
||||
// child process
|
||||
process.on('message', async (/** @type {string} */ message) => {
|
||||
process.on('message', async (message: string) => {
|
||||
let nlLoc = message.indexOf('\n');
|
||||
if (nlLoc <= 0) throw new Error(`Invalid response ${message}`);
|
||||
const taskId = message.slice(0, nlLoc);
|
||||
message = message.slice(nlLoc + 1);
|
||||
|
||||
if (taskId.startsWith('EVAL')) {
|
||||
/* tslint:disable:no-eval */
|
||||
// @ts-ignore guaranteed to be defined here
|
||||
process.send(`${taskId}\n` + eval(message));
|
||||
/* tslint:enable:no-eval */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -357,37 +341,36 @@ class QueryProcessManager extends ProcessManager {
|
|||
});
|
||||
}
|
||||
}
|
||||
class StreamProcessManager extends ProcessManager {
|
||||
/**
|
||||
* @param {NodeJS.Module} module
|
||||
* @param {() => ObjectReadWriteStream} createStream
|
||||
*/
|
||||
constructor(module, createStream) {
|
||||
|
||||
export class StreamProcessManager extends ProcessManager {
|
||||
/* taskid: stream used only in child process */
|
||||
activeStreams: Map<string, Streams.ObjectReadWriteStream>;
|
||||
// tslint:disable-next-line:variable-name
|
||||
_createStream: () => Streams.ObjectReadWriteStream;
|
||||
|
||||
constructor(module: NodeJS.Module, createStream: () => Streams.ObjectReadWriteStream) {
|
||||
super(module);
|
||||
/** @type {Map<string, ObjectReadWriteStream>} taskid: stream used only in child process */
|
||||
this.activeStreams = new Map();
|
||||
this._createStream = createStream;
|
||||
|
||||
PMLib.processManagers.push(this);
|
||||
processManagers.push(this);
|
||||
}
|
||||
createStream() {
|
||||
const process = /** @type {StreamProcessWrapper} */ (this.acquire());
|
||||
const process = this.acquire() as StreamProcessWrapper;
|
||||
if (!process) return this._createStream();
|
||||
return process.createStream();
|
||||
}
|
||||
createProcess() {
|
||||
return new StreamProcessWrapper(this.filename);
|
||||
}
|
||||
/**
|
||||
* @param {string} taskId
|
||||
* @param {ObjectReadStream} stream
|
||||
*/
|
||||
async pipeStream(taskId, stream) {
|
||||
async pipeStream(taskId: string, stream: Streams.ObjectReadStream) {
|
||||
/* tslint:disable */
|
||||
let value, done;
|
||||
while (({value, done} = await stream.next(), !done)) {
|
||||
// @ts-ignore Guaranteed to be a child process
|
||||
process.send(`${taskId}\nPUSH\n${value}`);
|
||||
}
|
||||
/* tslint:enable */
|
||||
// @ts-ignore Guaranteed to be a child process
|
||||
process.send(`${taskId}\nEND`);
|
||||
this.activeStreams.delete(taskId);
|
||||
|
|
@ -395,7 +378,7 @@ class StreamProcessManager extends ProcessManager {
|
|||
listen() {
|
||||
if (this.isParentProcess) return;
|
||||
// child process
|
||||
process.on('message', async (/** @type {string} */ message) => {
|
||||
process.on('message', async (message: string) => {
|
||||
let nlLoc = message.indexOf('\n');
|
||||
if (nlLoc <= 0) throw new Error(`Invalid request ${message}`);
|
||||
const taskId = message.slice(0, nlLoc);
|
||||
|
|
@ -408,8 +391,10 @@ class StreamProcessManager extends ProcessManager {
|
|||
message = message.slice(nlLoc + 1);
|
||||
|
||||
if (taskId.startsWith('EVAL')) {
|
||||
/* tslint:disable:no-eval */
|
||||
// @ts-ignore guaranteed to be a child process
|
||||
process.send(`${taskId}\n` + eval(message));
|
||||
/* tslint:enable:no-eval */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -434,17 +419,3 @@ class StreamProcessManager extends ProcessManager {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
const PMLib = {
|
||||
QueryProcessWrapper,
|
||||
StreamProcessWrapper,
|
||||
ProcessManager,
|
||||
QueryProcessManager,
|
||||
StreamProcessManager,
|
||||
|
||||
/** @type {ProcessManager[]} */
|
||||
processManagers: [],
|
||||
disabled: false,
|
||||
};
|
||||
// @ts-ignore Typescript bug
|
||||
module.exports = PMLib;
|
||||
|
|
@ -8,21 +8,18 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import * as fs from 'fs';
|
||||
import * as net from 'net';
|
||||
import * as path from 'path';
|
||||
import * as repl from 'repl';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const net = require('net');
|
||||
const repl = require('repl');
|
||||
|
||||
const Repl = {
|
||||
export const Repl = new class {
|
||||
/**
|
||||
* Contains the pathnames of all active REPL sockets.
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
socketPathnames: new Set(),
|
||||
socketPathnames: Set<string> = new Set();
|
||||
|
||||
listenersSetup: false,
|
||||
listenersSetup: boolean = false;
|
||||
|
||||
setupListeners() {
|
||||
if (Repl.listenersSetup) return;
|
||||
|
|
@ -44,17 +41,14 @@ const Repl = {
|
|||
if (!process.listeners('SIGINT').length) {
|
||||
process.once('SIGINT', () => process.exit(128 + 2));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a REPL server, using a UNIX socket for IPC. The eval function
|
||||
* parametre is passed in because there is no other way to access a file's
|
||||
* non-global context.
|
||||
*
|
||||
* @param {string} filename
|
||||
* @param {(input: string) => any} evalFunction
|
||||
*/
|
||||
start(filename, evalFunction) {
|
||||
start(filename: string, evalFunction: (input: string) => any) {
|
||||
if ('repl' in Config && !Config.repl) return;
|
||||
|
||||
// TODO: Windows does support the REPL when using named pipes. For now,
|
||||
|
|
@ -84,14 +78,8 @@ const Repl = {
|
|||
repl.start({
|
||||
input: socket,
|
||||
output: socket,
|
||||
/**
|
||||
* @param {string} cmd
|
||||
* @param {any} context
|
||||
* @param {string} filename
|
||||
* @param {Function} callback
|
||||
* @return {any}
|
||||
*/
|
||||
eval(cmd, context, filename, callback) {
|
||||
// tslint:disable-next-line:ban-types
|
||||
eval(cmd: string, context: any, unusedFilename: string, callback: Function): any {
|
||||
try {
|
||||
return callback(null, evalFunction(cmd));
|
||||
} catch (e) {
|
||||
|
|
@ -108,8 +96,9 @@ const Repl = {
|
|||
Repl.socketPathnames.add(pathname);
|
||||
});
|
||||
|
||||
server.once('error', /** @param {NodeJS.ErrnoException} err */ err => {
|
||||
server.once('error', (err: NodeJS.ErrnoException) => {
|
||||
if (err.code === "EADDRINUSE") {
|
||||
// tslint:disable-next-line:variable-name
|
||||
fs.unlink(pathname, _err => {
|
||||
if (_err && _err.code !== "ENOENT") {
|
||||
require('./crashlogger')(_err, `REPL: ${filename}`);
|
||||
|
|
@ -126,7 +115,5 @@ const Repl = {
|
|||
Repl.socketPathnames.delete(pathname);
|
||||
Repl.start(filename, evalFunction);
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Repl;
|
||||
|
|
@ -10,33 +10,35 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const BUF_SIZE = 65536 * 4;
|
||||
|
||||
class ReadStream {
|
||||
/** @param {{[k: string]: any} | NodeJS.ReadableStream | string | Buffer} optionsOrStreamLike */
|
||||
constructor(optionsOrStreamLike = {}) {
|
||||
export class ReadStream {
|
||||
buf: Buffer;
|
||||
bufStart: number;
|
||||
bufEnd: number;
|
||||
bufCapacity: number;
|
||||
readSize: number;
|
||||
atEOF: boolean;
|
||||
encoding: string;
|
||||
isReadable: boolean;
|
||||
isWritable: boolean;
|
||||
nodeReadableStream: NodeJS.ReadableStream | null;
|
||||
nextPushResolver: (() => void) | null;
|
||||
nextPush: Promise<void>;
|
||||
awaitingPush: boolean;
|
||||
|
||||
constructor(optionsOrStreamLike: {[k: string]: any} | NodeJS.ReadableStream | string | Buffer = {}) {
|
||||
this.buf = Buffer.allocUnsafe(BUF_SIZE);
|
||||
this.bufStart = 0;
|
||||
this.bufEnd = 0;
|
||||
this.bufCapacity = BUF_SIZE;
|
||||
// TypeScript bug: can't infer type
|
||||
/** @type {number} */
|
||||
this.readSize = 0;
|
||||
this.atEOF = false;
|
||||
this.encoding = 'utf8';
|
||||
|
||||
/** @type {true} */
|
||||
this.isReadable = true;
|
||||
this.isWritable = false;
|
||||
|
||||
/** @type {NodeJS.ReadableStream?} */
|
||||
this.nodeReadableStream = null;
|
||||
|
||||
/** @type {(() => void)?} */
|
||||
this.nextPushResolver = null;
|
||||
/** @type {Promise<void>} */
|
||||
this.nextPush = new Promise(resolve => {
|
||||
this.nextPushResolver = resolve;
|
||||
});
|
||||
|
|
@ -47,13 +49,13 @@ class ReadStream {
|
|||
options = {buffer: optionsOrStreamLike};
|
||||
} else if (optionsOrStreamLike instanceof Buffer) {
|
||||
options = {buffer: optionsOrStreamLike};
|
||||
} else if (typeof /** @type {any} */ (optionsOrStreamLike)._readableState === 'object') {
|
||||
options = {nodeStream: /** @type {NodeJS.ReadableStream} */ (optionsOrStreamLike)};
|
||||
} else if (typeof (optionsOrStreamLike as any)._readableState === 'object') {
|
||||
options = {nodeStream: optionsOrStreamLike as NodeJS.ReadableStream};
|
||||
} else {
|
||||
options = optionsOrStreamLike;
|
||||
}
|
||||
if (options.nodeStream) {
|
||||
const nodeStream = /** @type {NodeJS.ReadableStream} */ (options.nodeStream);
|
||||
const nodeStream: NodeJS.ReadableStream = options.nodeStream;
|
||||
this.nodeReadableStream = nodeStream;
|
||||
nodeStream.on('data', data => {
|
||||
this.push(data);
|
||||
|
|
@ -61,19 +63,13 @@ class ReadStream {
|
|||
nodeStream.on('end', () => {
|
||||
this.push(null);
|
||||
});
|
||||
/**
|
||||
* @this {ReadStream}
|
||||
* @param {number} bytes
|
||||
*/
|
||||
options.read = function (bytes) {
|
||||
this.nodeReadableStream.resume();
|
||||
|
||||
options.read = function (this: ReadStream, unusedBytes: number) {
|
||||
this.nodeReadableStream!.resume();
|
||||
};
|
||||
/**
|
||||
* @this {ReadStream}
|
||||
* @param {number} bytes
|
||||
*/
|
||||
options.pause = function (bytes) {
|
||||
this.nodeReadableStream.pause();
|
||||
|
||||
options.pause = function (this: ReadStream, unusedBytes: number) {
|
||||
this.nodeReadableStream!.pause();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -86,9 +82,11 @@ class ReadStream {
|
|||
this.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
get bufSize() {
|
||||
return this.bufEnd - this.bufStart;
|
||||
}
|
||||
|
||||
moveBuf() {
|
||||
if (this.bufStart !== this.bufEnd) {
|
||||
this.buf.copy(this.buf, 0, this.bufStart, this.bufEnd);
|
||||
|
|
@ -96,6 +94,7 @@ class ReadStream {
|
|||
this.bufEnd -= this.bufStart;
|
||||
this.bufStart = 0;
|
||||
}
|
||||
|
||||
expandBuf(newCapacity = this.bufCapacity * 2) {
|
||||
const newBuf = Buffer.allocUnsafe(newCapacity);
|
||||
this.buf.copy(newBuf, 0, this.bufStart, this.bufEnd);
|
||||
|
|
@ -103,10 +102,8 @@ class ReadStream {
|
|||
this.bufStart = 0;
|
||||
this.buf = newBuf;
|
||||
}
|
||||
/**
|
||||
* @param {number} additionalCapacity
|
||||
*/
|
||||
ensureCapacity(additionalCapacity) {
|
||||
|
||||
ensureCapacity(additionalCapacity: number) {
|
||||
if (this.bufEnd + additionalCapacity <= this.bufCapacity) return;
|
||||
const capacity = this.bufEnd - this.bufStart + additionalCapacity;
|
||||
if (capacity <= this.bufCapacity) {
|
||||
|
|
@ -116,10 +113,8 @@ class ReadStream {
|
|||
while (newCapacity < capacity) newCapacity *= 2;
|
||||
this.expandBuf(newCapacity);
|
||||
}
|
||||
/**
|
||||
* @param {Buffer | string | null} buf
|
||||
*/
|
||||
push(buf, encoding = this.encoding) {
|
||||
|
||||
push(buf: Buffer | string | null, encoding: string = this.encoding) {
|
||||
let size;
|
||||
if (this.atEOF) return;
|
||||
if (buf === null) {
|
||||
|
|
@ -139,6 +134,7 @@ class ReadStream {
|
|||
if (this.bufSize > this.readSize && size * 2 < this.bufSize) this._pause();
|
||||
this.resolvePush();
|
||||
}
|
||||
|
||||
resolvePush() {
|
||||
if (!this.nextPushResolver) throw new Error(`Push after end of read stream`);
|
||||
this.nextPushResolver();
|
||||
|
|
@ -150,23 +146,18 @@ class ReadStream {
|
|||
this.nextPushResolver = resolve;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {number} [size]
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
_read(size = 0) {
|
||||
|
||||
_read(size: number = 0): void | Promise<void> {
|
||||
throw new Error(`ReadStream needs to be subclassed and the _read function needs to be implemented.`);
|
||||
}
|
||||
|
||||
_destroy() {}
|
||||
_pause() {}
|
||||
/**
|
||||
* @param {number?} byteCount
|
||||
*/
|
||||
async loadIntoBuffer(byteCount = null) {
|
||||
|
||||
async loadIntoBuffer(byteCount: number | null = null) {
|
||||
if (byteCount === 0) return;
|
||||
this.readSize = Math.max(byteCount || (this.bufSize + 1), this.readSize);
|
||||
/** @type {number?} */
|
||||
let bytes = this.readSize - this.bufSize;
|
||||
let bytes: number | null = this.readSize - this.bufSize;
|
||||
if (bytes === Infinity || byteCount === null) bytes = null;
|
||||
while (!this.atEOF && this.bufSize < this.readSize) {
|
||||
if (bytes) this._read(bytes);
|
||||
|
|
@ -174,10 +165,8 @@ class ReadStream {
|
|||
await this.nextPush;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {number?} byteCount
|
||||
*/
|
||||
async peek(byteCount = null, encoding = this.encoding) {
|
||||
|
||||
async peek(byteCount: number | null = null, encoding: string = this.encoding) {
|
||||
if (byteCount === null && this.bufSize) return this.buf.toString(encoding, this.bufStart, this.bufEnd);
|
||||
await this.loadIntoBuffer(byteCount);
|
||||
if (byteCount === null) return this.buf.toString(encoding, this.bufStart, this.bufEnd);
|
||||
|
|
@ -185,10 +174,8 @@ class ReadStream {
|
|||
if (!this.bufSize) return null;
|
||||
return this.buf.toString(encoding, this.bufStart, this.bufStart + byteCount);
|
||||
}
|
||||
/**
|
||||
* @param {number?} byteCount
|
||||
*/
|
||||
async peekBuffer(byteCount = null) {
|
||||
|
||||
async peekBuffer(byteCount: number | null = null) {
|
||||
if (byteCount === null && this.bufSize) return this.buf.slice(this.bufStart, this.bufEnd);
|
||||
await this.loadIntoBuffer(byteCount);
|
||||
if (byteCount === null) return this.buf.slice(this.bufStart, this.bufEnd);
|
||||
|
|
@ -196,10 +183,8 @@ class ReadStream {
|
|||
if (!this.bufSize) return null;
|
||||
return this.buf.slice(this.bufStart, this.bufStart + byteCount);
|
||||
}
|
||||
/**
|
||||
* @param {number? | string} byteCount
|
||||
*/
|
||||
async read(byteCount = null, encoding = this.encoding) {
|
||||
|
||||
async read(byteCount: number | string | null = null, encoding = this.encoding) {
|
||||
if (typeof byteCount === 'string') {
|
||||
encoding = byteCount;
|
||||
byteCount = null;
|
||||
|
|
@ -213,10 +198,8 @@ class ReadStream {
|
|||
}
|
||||
return out;
|
||||
}
|
||||
/**
|
||||
* @param {number?} byteCount
|
||||
*/
|
||||
async readBuffer(byteCount = null) {
|
||||
|
||||
async readBuffer(byteCount: number | null = null) {
|
||||
const out = await this.peekBuffer(byteCount);
|
||||
if (byteCount === null || byteCount >= this.bufSize) {
|
||||
this.bufStart = 0;
|
||||
|
|
@ -226,10 +209,8 @@ class ReadStream {
|
|||
}
|
||||
return out;
|
||||
}
|
||||
/**
|
||||
* @param {string} symbol
|
||||
*/
|
||||
async indexOf(symbol, encoding = this.encoding) {
|
||||
|
||||
async indexOf(symbol: string, encoding: string = this.encoding) {
|
||||
let idx = this.buf.indexOf(symbol, this.bufStart, encoding);
|
||||
while (!this.atEOF && (idx >= this.bufEnd || idx < 0)) {
|
||||
await this.loadIntoBuffer();
|
||||
|
|
@ -238,16 +219,16 @@ class ReadStream {
|
|||
if (idx >= this.bufEnd) return -1;
|
||||
return idx - this.bufStart;
|
||||
}
|
||||
|
||||
async readAll(encoding = this.encoding) {
|
||||
return (await this.read(Infinity, encoding)) || '';
|
||||
}
|
||||
|
||||
peekAll(encoding = this.encoding) {
|
||||
return this.peek(Infinity, encoding);
|
||||
}
|
||||
/**
|
||||
* @param {string} symbol
|
||||
*/
|
||||
async readDelimitedBy(symbol, encoding = this.encoding) {
|
||||
|
||||
async readDelimitedBy(symbol: string, encoding: string = this.encoding) {
|
||||
if (this.atEOF && !this.bufSize) return null;
|
||||
const idx = await this.indexOf(symbol, encoding);
|
||||
if (idx < 0) {
|
||||
|
|
@ -258,12 +239,14 @@ class ReadStream {
|
|||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
async readLine(encoding = this.encoding) {
|
||||
if (!encoding) throw new Error(`readLine must have an encoding`);
|
||||
let line = await this.readDelimitedBy('\n', encoding);
|
||||
if (line && line.endsWith('\r')) line = line.slice(0, -1);
|
||||
return line;
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
this.atEOF = true;
|
||||
this.bufStart = 0;
|
||||
|
|
@ -271,54 +254,52 @@ class ReadStream {
|
|||
if (this.nextPushResolver) this.resolvePush();
|
||||
return this._destroy();
|
||||
}
|
||||
/**
|
||||
* @param {string | number | null} [byteCount]
|
||||
*/
|
||||
async next(byteCount = null) {
|
||||
|
||||
async next(byteCount: string | number | null = null) {
|
||||
const value = await this.read(byteCount);
|
||||
return {value, done: value === null};
|
||||
}
|
||||
/**
|
||||
* @param {WriteStream} outStream
|
||||
* @param {{noEnd?: boolean}} [options]
|
||||
*/
|
||||
async pipeTo(outStream, options = {}) {
|
||||
|
||||
async pipeTo(outStream: WriteStream, options: {noEnd?: boolean} = {}) {
|
||||
/* tslint:disable */
|
||||
let value, done;
|
||||
while (({value, done} = await this.next(), !done)) {
|
||||
await outStream.write(value);
|
||||
}
|
||||
/* tslint:enable */
|
||||
if (!options.noEnd) outStream.end();
|
||||
}
|
||||
}
|
||||
|
||||
class WriteStream {
|
||||
/**
|
||||
* @param {{_writableState?: any, nodeStream?: NodeJS.ReadableStream, write?: (this: WriteStream, data: string | Buffer) => (Promise<any> | undefined), end?: () => Promise<any>}} options
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
interface WriteStreamOptions {
|
||||
writableState?: any;
|
||||
nodeStream?: NodeJS.ReadableStream;
|
||||
write?: (this: WriteStream, data: string | Buffer) => (Promise<any> | undefined);
|
||||
end?: () => Promise<any>;
|
||||
}
|
||||
|
||||
export class WriteStream {
|
||||
isReadable: boolean;
|
||||
isWritable: true;
|
||||
encoding: string;
|
||||
nodeWritableStream: NodeJS.ReadableStream | null;
|
||||
drainListeners: (() => void)[];
|
||||
|
||||
constructor(options: WriteStreamOptions = {}) {
|
||||
this.isReadable = false;
|
||||
/** @type {true} */
|
||||
this.isWritable = true;
|
||||
this.encoding = 'utf8';
|
||||
|
||||
/** @type {NodeJS.ReadableStream?} */
|
||||
this.nodeWritableStream = null;
|
||||
/** @type {(() => void)[]} */
|
||||
this.drainListeners = [];
|
||||
|
||||
if (options._writableState) {
|
||||
if ((options as any)._writableState) {
|
||||
// @ts-ignore
|
||||
options = {nodeStream: options};
|
||||
}
|
||||
if (options.nodeStream) {
|
||||
const nodeStream = /** @type {NodeJS.ReadableStream} */ (options.nodeStream);
|
||||
const nodeStream: NodeJS.ReadableStream = options.nodeStream;
|
||||
this.nodeWritableStream = nodeStream;
|
||||
/**
|
||||
* @this {WriteStream}
|
||||
* @param {string | Buffer} data
|
||||
*/
|
||||
// @ts-ignore TypeScript bug
|
||||
options.write = function (data) {
|
||||
options.write = function (this: WriteStream, data: string | Buffer) {
|
||||
// @ts-ignore
|
||||
const result = this.nodeWritableStream.write(data);
|
||||
if (result !== false) return undefined;
|
||||
|
|
@ -344,11 +325,8 @@ class WriteStream {
|
|||
if (options.write) this._write = options.write;
|
||||
if (options.end) this._end = options.end;
|
||||
}
|
||||
/**
|
||||
* @param {Buffer | string | null} chunk
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
async write(chunk) {
|
||||
|
||||
async write(chunk: Buffer | string | null): Promise<boolean> {
|
||||
if (chunk === null) {
|
||||
await this.end();
|
||||
return false;
|
||||
|
|
@ -356,31 +334,22 @@ class WriteStream {
|
|||
await this._write(chunk);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param {string | null} chunk
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
async writeLine(chunk) {
|
||||
|
||||
async writeLine(chunk: string | null): Promise<boolean> {
|
||||
if (chunk === null) {
|
||||
await this.end();
|
||||
return false;
|
||||
}
|
||||
return this.write(chunk + '\n');
|
||||
}
|
||||
/**
|
||||
* @param {Buffer | string} chunk
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
_write(chunk) {
|
||||
|
||||
_write(chunk: Buffer | string): void | Promise<void> {
|
||||
throw new Error(`WriteStream needs to be subclassed and the _write function needs to be implemented.`);
|
||||
}
|
||||
/** @return {void | Promise<void>} */
|
||||
_end() {}
|
||||
/**
|
||||
* @param {string | null} chunk
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async end(chunk = null) {
|
||||
|
||||
_end(): void | Promise<void> {}
|
||||
|
||||
async end(chunk: string | null = null): Promise<void> {
|
||||
if (chunk) {
|
||||
await this.write(chunk);
|
||||
}
|
||||
|
|
@ -388,68 +357,54 @@ class WriteStream {
|
|||
}
|
||||
}
|
||||
|
||||
class ReadWriteStream extends ReadStream {
|
||||
export class ReadWriteStream extends ReadStream {
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
/** @type {true} */
|
||||
this.isReadable = true;
|
||||
/** @type {true} */
|
||||
this.isWritable = true;
|
||||
}
|
||||
/**
|
||||
* @param {Buffer | string} chunk
|
||||
* @return {Promise<void> | void}
|
||||
*/
|
||||
write(chunk) {
|
||||
|
||||
write(chunk: Buffer | string): Promise<void> | void {
|
||||
return this._write(chunk);
|
||||
}
|
||||
/**
|
||||
* @param {string} chunk
|
||||
* @return {Promise<void> | void}
|
||||
*/
|
||||
writeLine(chunk) {
|
||||
|
||||
writeLine(chunk: string): Promise<void> | void {
|
||||
return this.write(chunk + '\n');
|
||||
}
|
||||
/**
|
||||
* @param {Buffer | string} chunk
|
||||
* @return {Promise<void> | void}
|
||||
*/
|
||||
_write(chunk) {
|
||||
|
||||
_write(chunk: Buffer | string): Promise<void> | void {
|
||||
throw new Error(`WriteStream needs to be subclassed and the _write function needs to be implemented.`);
|
||||
}
|
||||
/**
|
||||
* In a ReadWriteStream, _read does not need to be implemented
|
||||
*/
|
||||
|
||||
/** In a ReadWriteStream, _read does not need to be implemented. */
|
||||
_read() {}
|
||||
/** @return {void | Promise<void>} */
|
||||
_end() {}
|
||||
|
||||
_end(): void | Promise<void> {}
|
||||
|
||||
async end() {
|
||||
return this._end();
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectReadStream {
|
||||
/**
|
||||
* @param {{[k: string]: any} | NodeJS.ReadableStream | any[]} optionsOrStreamLike
|
||||
*/
|
||||
constructor(optionsOrStreamLike = {}) {
|
||||
/** @type {any[]} */
|
||||
export class ObjectReadStream {
|
||||
buf: any[];
|
||||
readSize: number;
|
||||
atEOF: boolean;
|
||||
isReadable: boolean;
|
||||
isWritable: boolean;
|
||||
nodeReadableStream: NodeJS.ReadableStream | null;
|
||||
nextPushResolver: (() => void) | null;
|
||||
nextPush: Promise<void>;
|
||||
awaitingPush: boolean;
|
||||
|
||||
constructor(optionsOrStreamLike: {[k: string]: any} | NodeJS.ReadableStream | any[] = {}) {
|
||||
this.buf = [];
|
||||
// TypeScript bug: can't infer type
|
||||
/** @type {number} */
|
||||
this.readSize = 0;
|
||||
this.atEOF = false;
|
||||
|
||||
/** @type {true} */
|
||||
this.isReadable = true;
|
||||
this.isWritable = false;
|
||||
|
||||
/** @type {NodeJS.ReadableStream?} */
|
||||
this.nodeReadableStream = null;
|
||||
|
||||
/** @type {(() => void)?} */
|
||||
this.nextPushResolver = null;
|
||||
/** @type {Promise<void>} */
|
||||
this.nextPush = new Promise(resolve => {
|
||||
this.nextPushResolver = resolve;
|
||||
});
|
||||
|
|
@ -458,13 +413,13 @@ class ObjectReadStream {
|
|||
let options;
|
||||
if (Array.isArray(optionsOrStreamLike)) {
|
||||
options = {buffer: optionsOrStreamLike};
|
||||
} else if (typeof /** @type {any} */ (optionsOrStreamLike)._readableState === 'object') {
|
||||
options = {nodeStream: /** @type {NodeJS.ReadableStream} */ (optionsOrStreamLike)};
|
||||
} else if (typeof (optionsOrStreamLike as any)._readableState === 'object') {
|
||||
options = {nodeStream: optionsOrStreamLike as NodeJS.ReadableStream};
|
||||
} else {
|
||||
options = optionsOrStreamLike;
|
||||
}
|
||||
if (options.nodeStream) {
|
||||
const nodeStream = /** @type {NodeJS.ReadableStream} */ (options.nodeStream);
|
||||
const nodeStream: NodeJS.ReadableStream = options.nodeStream;
|
||||
this.nodeReadableStream = nodeStream;
|
||||
nodeStream.on('data', data => {
|
||||
this.push(data);
|
||||
|
|
@ -472,19 +427,13 @@ class ObjectReadStream {
|
|||
nodeStream.on('end', () => {
|
||||
this.push(null);
|
||||
});
|
||||
/**
|
||||
* @this {ReadStream}
|
||||
* @param {number} bytes
|
||||
*/
|
||||
options.read = function (bytes) {
|
||||
this.nodeReadableStream.resume();
|
||||
|
||||
options.read = function (this: ReadStream, unusedBytes: number) {
|
||||
this.nodeReadableStream!.resume();
|
||||
};
|
||||
/**
|
||||
* @this {ReadStream}
|
||||
* @param {number} bytes
|
||||
*/
|
||||
options.pause = function (bytes) {
|
||||
this.nodeReadableStream.pause();
|
||||
|
||||
options.pause = function (this: ReadStream, unusedBytes: number) {
|
||||
this.nodeReadableStream!.pause();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -496,10 +445,8 @@ class ObjectReadStream {
|
|||
this.push(null);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {any} elem
|
||||
*/
|
||||
push(elem) {
|
||||
|
||||
push(elem: any) {
|
||||
if (this.atEOF) return;
|
||||
if (elem === null) {
|
||||
this.atEOF = true;
|
||||
|
|
@ -511,6 +458,7 @@ class ObjectReadStream {
|
|||
if (this.buf.length > this.readSize && this.buf.length >= 16) this._pause();
|
||||
this.resolvePush();
|
||||
}
|
||||
|
||||
resolvePush() {
|
||||
if (!this.nextPushResolver) throw new Error(`Push after end of read stream`);
|
||||
this.nextPushResolver();
|
||||
|
|
@ -522,19 +470,15 @@ class ObjectReadStream {
|
|||
this.nextPushResolver = resolve;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {number} [size]
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
_read(size = 0) {
|
||||
|
||||
_read(size: number = 0): void | Promise<void> {
|
||||
throw new Error(`ReadStream needs to be subclassed and the _read function needs to be implemented.`);
|
||||
}
|
||||
|
||||
_destroy() {}
|
||||
_pause() {}
|
||||
/**
|
||||
* @param {number} count
|
||||
*/
|
||||
async loadIntoBuffer(count = 1) {
|
||||
|
||||
async loadIntoBuffer(count: number = 1) {
|
||||
if (this.buf.length >= count) return;
|
||||
this.readSize = Math.max(count, this.readSize);
|
||||
while (!this.atEOF && this.buf.length < this.readSize) {
|
||||
|
|
@ -547,81 +491,84 @@ class ObjectReadStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
async peek() {
|
||||
if (this.buf.length) return this.buf[0];
|
||||
await this.loadIntoBuffer();
|
||||
return this.buf[0];
|
||||
}
|
||||
|
||||
async read() {
|
||||
if (this.buf.length) return this.buf.shift();
|
||||
await this.loadIntoBuffer();
|
||||
if (!this.buf.length) return null;
|
||||
return this.buf.shift();
|
||||
}
|
||||
/**
|
||||
* @param {number?} [count]
|
||||
*/
|
||||
async peekArray(count = null) {
|
||||
|
||||
async peekArray(count: number | null = null) {
|
||||
await this.loadIntoBuffer(count || 1);
|
||||
if (count === null || count === Infinity) {
|
||||
return this.buf.slice();
|
||||
}
|
||||
return this.buf.slice(0, count);
|
||||
}
|
||||
/**
|
||||
* @param {number?} [count]
|
||||
*/
|
||||
async readArray(count = null) {
|
||||
|
||||
async readArray(count: number | null = null) {
|
||||
let out = await this.peekArray(count);
|
||||
this.buf = this.buf.slice(out.length);
|
||||
return out;
|
||||
}
|
||||
|
||||
async readAll() {
|
||||
await this.loadIntoBuffer(Infinity);
|
||||
let out = this.buf;
|
||||
this.buf = [];
|
||||
return out;
|
||||
}
|
||||
|
||||
async peekAll() {
|
||||
await this.loadIntoBuffer(Infinity);
|
||||
return this.buf.slice();
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
this.atEOF = true;
|
||||
this.buf = [];
|
||||
this.resolvePush();
|
||||
return this._destroy();
|
||||
}
|
||||
|
||||
async next() {
|
||||
const value = await this.read();
|
||||
return {value, done: value === null};
|
||||
}
|
||||
/**
|
||||
* @param {WriteStream} outStream
|
||||
* @param {{noEnd?: boolean}} options
|
||||
*/
|
||||
async pipeTo(outStream, options = {}) {
|
||||
|
||||
async pipeTo(outStream: WriteStream, options: {noEnd?: boolean} = {}) {
|
||||
/* tslint:disable */
|
||||
let value, done;
|
||||
while (({value, done} = await this.next(), !done)) {
|
||||
await outStream.write(value);
|
||||
}
|
||||
/* tslint:enable */
|
||||
if (!options.noEnd) outStream.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
class ObjectWriteStream {
|
||||
/**
|
||||
* @param {{_writableState?: any, nodeStream?: NodeJS.ReadableStream, write?: (this: WriteStream, data: T) => Promise<any> | undefined, end?: () => Promise<any>}} options
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.isReadable = false;
|
||||
/** @type {true} */
|
||||
this.isWritable = true;
|
||||
interface ObjectWriteStreamOptions<T> {
|
||||
_writableState?: any;
|
||||
nodeStream?: NodeJS.ReadableStream;
|
||||
write?: (this: WriteStream, data: T) => Promise<any> | undefined;
|
||||
end?: () => Promise<any>;
|
||||
}
|
||||
|
||||
/** @type {NodeJS.ReadableStream?} */
|
||||
export class ObjectWriteStream<T> {
|
||||
isReadable: boolean;
|
||||
isWritable: true;
|
||||
nodeWritableStream: NodeJS.ReadableStream | null;
|
||||
|
||||
constructor(options: ObjectWriteStreamOptions<T> = {}) {
|
||||
this.isReadable = false;
|
||||
this.isWritable = true;
|
||||
this.nodeWritableStream = null;
|
||||
|
||||
if (options._writableState) {
|
||||
|
|
@ -629,15 +576,12 @@ class ObjectWriteStream {
|
|||
options = {nodeStream: options};
|
||||
}
|
||||
if (options.nodeStream) {
|
||||
const nodeStream = /** @type {NodeJS.ReadableStream} */ (options.nodeStream);
|
||||
const nodeStream: NodeJS.ReadableStream = options.nodeStream;
|
||||
this.nodeWritableStream = nodeStream;
|
||||
/**
|
||||
* @this {WriteStream}
|
||||
* @param {T} data
|
||||
*/
|
||||
options.write = function (data) {
|
||||
|
||||
options.write = function (this: WriteStream, data: T) {
|
||||
// @ts-ignore
|
||||
const result = this.nodeWritableStream.write(data);
|
||||
const result = this.nodeWritableStream!.write(data);
|
||||
if (result === false) {
|
||||
return new Promise(resolve => {
|
||||
// @ts-ignore
|
||||
|
|
@ -647,6 +591,7 @@ class ObjectWriteStream {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
options.end = function () {
|
||||
return new Promise(resolve => {
|
||||
// @ts-ignore
|
||||
|
|
@ -658,11 +603,8 @@ class ObjectWriteStream {
|
|||
if (options.write) this._write = options.write;
|
||||
if (options.end) this._end = options.end;
|
||||
}
|
||||
/**
|
||||
* @param {T?} elem
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
async write(elem) {
|
||||
|
||||
async write(elem: T | null): Promise<boolean> {
|
||||
if (elem === null) {
|
||||
await this.end();
|
||||
return false;
|
||||
|
|
@ -670,20 +612,14 @@ class ObjectWriteStream {
|
|||
await this._write(elem);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param {T} elem
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
_write(elem) {
|
||||
|
||||
_write(elem: T): void | Promise<void> {
|
||||
throw new Error(`WriteStream needs to be subclassed and the _write function needs to be implemented.`);
|
||||
}
|
||||
/** @return {void | Promise<void>} */
|
||||
_end() {}
|
||||
/**
|
||||
* @param {T?} elem
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async end(elem = null) {
|
||||
|
||||
_end(): void | Promise<void> {}
|
||||
|
||||
async end(elem: T | null = null): Promise<void> {
|
||||
if (elem) {
|
||||
await this.write(elem);
|
||||
}
|
||||
|
|
@ -691,57 +627,40 @@ class ObjectWriteStream {
|
|||
}
|
||||
}
|
||||
|
||||
class ObjectReadWriteStream extends ObjectReadStream {
|
||||
/**
|
||||
* @param {{write?: (this: WriteStream, data: string) => Promise<any> | undefined | void, end?: () => Promise<any> | undefined | void}} options
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
interface ObjectReadWriteStreamOptions {
|
||||
write?: (this: WriteStream, data: string) => Promise<any> | undefined | void;
|
||||
end?: () => Promise<any> | undefined | void;
|
||||
}
|
||||
|
||||
export class ObjectReadWriteStream extends ObjectReadStream {
|
||||
isReadable: true;
|
||||
isWritable: true;
|
||||
|
||||
constructor(options: ObjectReadWriteStreamOptions = {}) {
|
||||
super(options);
|
||||
/** @type {true} */
|
||||
this.isReadable = true;
|
||||
/** @type {true} */
|
||||
this.isWritable = true;
|
||||
if (options.write) this._write = options.write;
|
||||
if (options.end) this._end = options.end;
|
||||
}
|
||||
/**
|
||||
* @param {any} elem
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
write(elem) {
|
||||
|
||||
write(elem: any): void | Promise<void> {
|
||||
return this._write(elem);
|
||||
}
|
||||
/**
|
||||
* @param {any} elem
|
||||
* @return {void | Promise<void>}
|
||||
*/
|
||||
_write(elem) {
|
||||
|
||||
_write(elem: any): void | Promise<void> {
|
||||
throw new Error(`WriteStream needs to be subclassed and the _write function needs to be implemented.`);
|
||||
}
|
||||
/**
|
||||
* In a ReadWriteStream, _read does not need to be implemented
|
||||
*/
|
||||
/** In a ReadWriteStream, _read does not need to be implemented. */
|
||||
_read() {}
|
||||
/** @return {void | Promise<void>} */
|
||||
_end() {}
|
||||
|
||||
_end(): void | Promise<void> {}
|
||||
|
||||
async end() {
|
||||
return this._end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ReadStream,
|
||||
WriteStream,
|
||||
ReadWriteStream,
|
||||
ObjectReadStream,
|
||||
ObjectWriteStream,
|
||||
ObjectReadWriteStream,
|
||||
|
||||
/**
|
||||
* @param {NodeJS.ReadableStream} nodeStream
|
||||
* @param {*} encoding
|
||||
*/
|
||||
readAll(nodeStream, encoding = undefined) {
|
||||
return new ReadStream(nodeStream).readAll(encoding);
|
||||
},
|
||||
};
|
||||
export function readAll(nodeStream: NodeJS.ReadableStream, encoding?: any) {
|
||||
return new ReadStream(nodeStream).readAll(encoding);
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
"version": "0.11.2",
|
||||
"dependencies": {
|
||||
"probe-image-size": "^4.0.0",
|
||||
"replace": "^1.0.1",
|
||||
"sockjs": "0.3.18",
|
||||
"sucrase": "^3.9.5"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
|
|||
var Dex = require('./.sim-dist/dex');
|
||||
var TeamValidator = require('./.sim-dist/team-validator');
|
||||
var validator = TeamValidator(process.argv[3]);
|
||||
var Streams = require('./lib/streams');
|
||||
var Streams = require('./.lib-dist/streams');
|
||||
var stdin = new Streams.ReadStream(process.stdin);
|
||||
|
||||
stdin.readLine().then(function (textTeam) {
|
||||
|
|
@ -97,7 +97,7 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
|
|||
case 'simulate-battle':
|
||||
{
|
||||
var BattleTextStream = require('./.sim-dist/battle-stream').BattleTextStream;
|
||||
var Streams = require('./lib/streams');
|
||||
var Streams = require('./.lib-dist/streams');
|
||||
var stdin = new Streams.ReadStream(process.stdin);
|
||||
var stdout = new Streams.WriteStream(process.stdout);
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
|
|||
case 'unpack-team':
|
||||
{
|
||||
var Dex = require('./.sim-dist/dex');
|
||||
var Streams = require('./lib/streams');
|
||||
var Streams = require('./.lib-dist/streams');
|
||||
var stdin = new Streams.ReadStream(process.stdin);
|
||||
|
||||
stdin.readLine().then(function (packedTeam) {
|
||||
|
|
@ -129,7 +129,7 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
|
|||
case 'pack-team':
|
||||
{
|
||||
var Dex = require('./.sim-dist/dex');
|
||||
var Streams = require('./lib/streams');
|
||||
var Streams = require('./.lib-dist/streams');
|
||||
var stdin = new Streams.ReadStream(process.stdin);
|
||||
|
||||
stdin.readLine().then(function (unpackedTeam) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
/* eslint no-else-return: "error" */
|
||||
|
||||
const crypto = require('crypto');
|
||||
const FS = require('../lib/fs');
|
||||
const FS = require('../.lib-dist/fs').FS;
|
||||
|
||||
const MAX_REASON_LENGTH = 300;
|
||||
const MUTE_LENGTH = 7 * 60 * 1000;
|
||||
|
|
@ -3005,7 +3005,7 @@ const commands = {
|
|||
|
||||
Chat.destroy();
|
||||
|
||||
const processManagers = require('../lib/process-manager').processManagers;
|
||||
const processManagers = require('../.lib-dist/process-manager').processManagers;
|
||||
for (let manager of processManagers.slice()) {
|
||||
if (manager.filename.startsWith(FS('server/chat-plugins').path)) {
|
||||
manager.destroy();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const MONITOR_FILE = 'config/chat-plugins/chat-monitor.tsv';
|
||||
const WRITE_THROTTLE_TIME = 5 * 60 * 1000;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const DAY = 24 * 60 * 60 * 1000;
|
||||
const SPOTLIGHT_FILE = 'config/chat-plugins/spotlights.json';
|
||||
|
|
|
|||
|
|
@ -1580,7 +1580,7 @@ function runSearch(query) {
|
|||
* Process manager
|
||||
*********************************************************/
|
||||
|
||||
const QueryProcessManager = require('../../lib/process-manager').QueryProcessManager;
|
||||
const QueryProcessManager = require('../../.lib-dist/process-manager').QueryProcessManager;
|
||||
|
||||
const PM = new QueryProcessManager(module, async query => {
|
||||
try {
|
||||
|
|
@ -1599,7 +1599,7 @@ const PM = new QueryProcessManager(module, async query => {
|
|||
return null;
|
||||
}
|
||||
} catch (err) {
|
||||
require('../../lib/crashlogger')(err, 'A search query', query);
|
||||
Monitor.crashlog(err, 'A search query', query);
|
||||
}
|
||||
return {error: "Sorry! Our search engine crashed on your query. We've been automatically notified and will fix this crash."};
|
||||
});
|
||||
|
|
@ -1607,10 +1607,22 @@ const PM = new QueryProcessManager(module, async query => {
|
|||
if (!PM.isParentProcess) {
|
||||
// This is a child process!
|
||||
global.Config = require('../../config/config');
|
||||
|
||||
// @ts-ignore ???
|
||||
global.Monitor = {
|
||||
/**
|
||||
* @param {Error} error
|
||||
* @param {string} source
|
||||
* @param {{}?} details
|
||||
*/
|
||||
crashlog(error, source = 'A datasearch process', details = null) {
|
||||
const repr = JSON.stringify([error.name, error.message, source, details]);
|
||||
// @ts-ignore
|
||||
process.send(`THROW\n@!!@${repr}\n${error.stack}`);
|
||||
},
|
||||
};
|
||||
if (Config.crashguard) {
|
||||
process.on('uncaughtException', err => {
|
||||
require('../../lib/crashlogger')(err, 'A dexsearch process');
|
||||
Monitor.crashlog(err, 'A dexsearch process');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1619,7 +1631,7 @@ if (!PM.isParentProcess) {
|
|||
Dex.includeData();
|
||||
global.TeamValidator = require('../../.sim-dist/team-validator').TeamValidator;
|
||||
|
||||
require('../../lib/repl').start('dexsearch', cmd => eval(cmd));
|
||||
require('../../.lib-dist/repl').Repl.start('dexsearch', cmd => eval(cmd));
|
||||
} else {
|
||||
PM.spawn(MAX_PROCESSES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
const TICKET_FILE = 'config/tickets.json';
|
||||
const TICKET_CACHE_TIME = 24 * 60 * 60 * 1000; // 24 hours
|
||||
const TICKET_BAN_DURATION = 48 * 60 * 60 * 1000; // 48 hours
|
||||
|
|
|
|||
|
|
@ -1749,8 +1749,8 @@ const commands = {
|
|||
for (const worker of Sockets.workers.values()) {
|
||||
buf += `<strong>${worker.pid || worker.process.pid}</strong> - Sockets ${worker.id}<br />`;
|
||||
}
|
||||
|
||||
const processManagers = require('../../lib/process-manager').processManagers;
|
||||
/** @type {typeof import('../../lib/process-manager').processManagers} */
|
||||
const processManagers = require(/** @type {any} */('../../.lib-dist/process-manager')).processManagers;
|
||||
for (const manager of processManagers) {
|
||||
for (const [i, process] of manager.processes.entries()) {
|
||||
buf += `<strong>${process.process.pid}</strong> - ${manager.basename} ${i} (load ${process.load})<br />`;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@
|
|||
* @property {Object} picks
|
||||
*/
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
const LOGS_FILE = 'config/chat-plugins/mafia-logs.json';
|
||||
const BANS_FILE = 'config/chat-plugins/mafia-bans.json';
|
||||
const MafiaData = require('./mafia-data.js');
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
const FS = require('../../.lib-dist/fs').FS;
|
||||
const path = require('path');
|
||||
const Dashycode = require('../../lib/dashycode');
|
||||
const Dashycode = require('../../.lib-dist/dashycode');
|
||||
const util = require('util');
|
||||
const execFile = util.promisify(require('child_process').execFile);
|
||||
|
||||
|
|
@ -559,7 +559,7 @@ exports.commands = {
|
|||
* Process manager
|
||||
*********************************************************/
|
||||
|
||||
const QueryProcessManager = require('../../lib/process-manager').QueryProcessManager;
|
||||
const QueryProcessManager = require('../../.lib-dist/process-manager').QueryProcessManager;
|
||||
|
||||
const PM = new QueryProcessManager(module, async data => {
|
||||
switch (data.cmd) {
|
||||
|
|
@ -568,7 +568,7 @@ const PM = new QueryProcessManager(module, async data => {
|
|||
try {
|
||||
return await runModlog(roomidList, searchString, exactSearch, maxLines);
|
||||
} catch (err) {
|
||||
require('../../lib/crashlogger')(err, 'A modlog query', {
|
||||
Monitor.crashlog(err, 'A modlog query', {
|
||||
roomidList,
|
||||
searchString,
|
||||
exactSearch,
|
||||
|
|
@ -581,7 +581,7 @@ const PM = new QueryProcessManager(module, async data => {
|
|||
try {
|
||||
return await runBattleSearch(userid, turnLimit, month, tierid, date);
|
||||
} catch (err) {
|
||||
require('../../lib/crashlogger')(err, 'A battle search query', {
|
||||
Monitor.crashlog(err, 'A battle search query', {
|
||||
userid,
|
||||
turnLimit,
|
||||
month,
|
||||
|
|
@ -597,15 +597,28 @@ const PM = new QueryProcessManager(module, async data => {
|
|||
if (!PM.isParentProcess) {
|
||||
// This is a child process!
|
||||
global.Config = require('../../config/config');
|
||||
// @ts-ignore ???
|
||||
global.Monitor = {
|
||||
/**
|
||||
* @param {Error} error
|
||||
* @param {string} source
|
||||
* @param {{}?} details
|
||||
*/
|
||||
crashlog(error, source = 'A modlog process', details = null) {
|
||||
const repr = JSON.stringify([error.name, error.message, source, details]);
|
||||
// @ts-ignore
|
||||
process.send(`THROW\n@!!@${repr}\n${error.stack}`);
|
||||
},
|
||||
};
|
||||
process.on('uncaughtException', err => {
|
||||
if (Config.crashguard) {
|
||||
require('../../lib/crashlogger')(err, 'A modlog child process');
|
||||
Monitor.crashlog(err, 'A modlog child process');
|
||||
}
|
||||
});
|
||||
global.Dex = require('../../.sim-dist/dex');
|
||||
global.toId = Dex.getId;
|
||||
|
||||
require('../../lib/repl').start('modlog', cmd => eval(cmd));
|
||||
require('../../.lib-dist/repl').Repl.start('modlog', cmd => eval(cmd));
|
||||
} else {
|
||||
PM.spawn(MAX_PROCESSES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const ROOMFAQ_FILE = 'config/chat-plugins/faqs.json';
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
const FS = require('../../.lib-dist/fs').FS;
|
||||
|
||||
const RATED_TYPES = ['official', 'regular', 'mini'];
|
||||
const DEFAULT_POINTS = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const DISHES_FILE = 'config/chat-plugins/thecafe-foodfight.json';
|
||||
const FOODFIGHT_COOLDOWN = 5 * 60 * 1000;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const MINUTE = 60 * 1000;
|
||||
const ROOMIDS = ['thestudio', 'jubilifetvfilms', 'youtube', 'thelibrary', 'prowrestling'];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
const MAIN_CATEGORIES = {
|
||||
ae: 'Arts and Entertainment',
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../../lib/fs');
|
||||
/** @type {typeof import('../../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../../.lib-dist/fs')).FS;
|
||||
|
||||
Punishments.roomPunishmentTypes.set('GIVEAWAYBAN', 'banned from giveaways');
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ const BROADCAST_TOKEN = '!';
|
|||
|
||||
const TRANSLATION_DIRECTORY = 'translations/';
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
/** @type {(url: string) => Promise<{width: number, height: number}>} */
|
||||
// @ts-ignore ignoring until there is a ts typedef available for this module.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
const BLOCKLISTS = ['sbl.spamhaus.org', 'rbl.efnetrbl.org'];
|
||||
|
||||
const dns = require('dns');
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
let Dnsbl = module.exports;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ try {
|
|||
throw new Error("Dependencies are unmet; run `node build` before launching Pokemon Showdown again.");
|
||||
}
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
const FS = require('../.lib-dist/fs').FS;
|
||||
|
||||
/*********************************************************
|
||||
* Load configuration
|
||||
|
|
@ -151,4 +151,4 @@ TeamValidatorAsync.PM.spawn();
|
|||
* Start up the REPL server
|
||||
*********************************************************/
|
||||
|
||||
require('../lib/repl').start('app', cmd => eval(cmd));
|
||||
require('../.lib-dist/repl').Repl.start('app', cmd => eval(cmd));
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
// ladderCaches = {formatid: ladder OR Promise(ladder)}
|
||||
// Use Ladders(formatid).ladder to guarantee a Promise(ladder).
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ const LOGIN_SERVER_BATCH_TIME = 1000;
|
|||
const http = Config.loginserver.startsWith('http:') ? require("http") : require("https");
|
||||
const url = require('url');
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
const Streams = require('../lib/streams');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
/** @type {typeof import('../lib/streams')} */
|
||||
const Streams = require(/** @type {any} */('../.lib-dist/streams'));
|
||||
|
||||
/**
|
||||
* A custom error type used when requests to the login server take too long.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
const MONITOR_CLEAN_TIMEOUT = 2 * 60 * 60 * 1000;
|
||||
|
||||
|
|
@ -54,7 +55,8 @@ if (('Config' in global) &&
|
|||
Config.loglevel = 2;
|
||||
}
|
||||
|
||||
let crashlogger = require('../lib/crashlogger');
|
||||
/** @type {typeof import('../lib/crashlogger')} */
|
||||
let crashlogger = require(/** @type {any} */('../.lib-dist/crashlogger'));
|
||||
|
||||
const Monitor = module.exports = {
|
||||
/*********************************************************
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
let Punishments = module.exports;
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
const PUNISHMENT_FILE = 'config/punishments.tsv';
|
||||
const ROOM_PUNISHMENT_FILE = 'config/room-punishments.tsv';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
/** 5 seconds */
|
||||
const TICK_TIME = 5;
|
||||
|
|
@ -1022,7 +1023,8 @@ exports.RoomBattle = Battle;
|
|||
* Process manager
|
||||
*********************************************************/
|
||||
|
||||
const StreamProcessManager = require('../lib/process-manager').StreamProcessManager;
|
||||
/** @type {typeof import('../lib/process-manager').StreamProcessManager} */
|
||||
const StreamProcessManager = require(/** @type {any} */('../.lib-dist/process-manager')).StreamProcessManager;
|
||||
|
||||
const PM = new StreamProcessManager(module, () => {
|
||||
/** @type {typeof import('../sim/battle-stream').BattleStream} */
|
||||
|
|
@ -1067,7 +1069,9 @@ if (!PM.isParentProcess) {
|
|||
});
|
||||
}
|
||||
|
||||
require('../lib/repl').start(`sim-${process.pid}`, cmd => eval(cmd));
|
||||
/** @type {typeof import('../lib/repl').Repl} */
|
||||
const Repl = require(/** @type {any} */('../.lib-dist/repl')).Repl;
|
||||
Repl.start(`sim-${process.pid}`, cmd => eval(cmd));
|
||||
} else {
|
||||
PM.spawn(global.Config ? Config.simulatorprocesses : 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
/**
|
||||
* Most rooms have three logs:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ const LAST_BATTLE_WRITE_THROTTLE = 10;
|
|||
/** @type {null} */
|
||||
const RETRY_AFTER_LOGIN = null;
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
const Roomlogs = require('./roomlogs');
|
||||
|
||||
/*********************************************************
|
||||
|
|
@ -483,7 +484,7 @@ class GlobalRoom extends BasicRoom {
|
|||
// Prevent there from being two possible hidden classes an instance
|
||||
// of GlobalRoom can have.
|
||||
// @ts-ignore
|
||||
this.ladderIpLog = new (require('../lib/streams')).WriteStream({write() {}});
|
||||
this.ladderIpLog = new (require(/** @type {any} */('../.lib-dist/streams'))).WriteStream({write() {}});
|
||||
}
|
||||
|
||||
let lastBattle;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ const MINUTES = 60 * 1000;
|
|||
|
||||
const cluster = require('cluster');
|
||||
const fs = require('fs');
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
const Monitor = {
|
||||
crashlog: require(/** @type {any} */('../.lib-dist/crashlogger')),
|
||||
};
|
||||
|
||||
if (cluster.isMaster) {
|
||||
cluster.setupMaster({
|
||||
|
|
@ -77,7 +82,7 @@ if (cluster.isMaster) {
|
|||
workers.delete(worker.id);
|
||||
} else if (code > 0) {
|
||||
// Worker was killed abnormally, likely because of a crash.
|
||||
require('../lib/crashlogger')(new Error(`Worker ${worker.id} abruptly died with code ${code} and signal ${signal}`), "The main process");
|
||||
Monitor.crashlog(new Error(`Worker ${worker.id} abruptly died with code ${code} and signal ${signal}`), "The main process");
|
||||
// Don't delete the worker so it can be inspected if need be.
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +286,7 @@ if (cluster.isMaster) {
|
|||
if (Config.crashguard) {
|
||||
// graceful crash
|
||||
process.on('uncaughtException', err => {
|
||||
require('../lib/crashlogger')(err, `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
Monitor.crashlog(err, `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +301,7 @@ if (cluster.isMaster) {
|
|||
try {
|
||||
key = fs.readFileSync(key);
|
||||
} catch (e) {
|
||||
require('../lib/crashlogger')(new Error(`Failed to read the configured SSL private key PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
Monitor.crashlog(new Error(`Failed to read the configured SSL private key PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('SSL private key config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.');
|
||||
|
|
@ -310,7 +315,7 @@ if (cluster.isMaster) {
|
|||
try {
|
||||
cert = fs.readFileSync(cert);
|
||||
} catch (e) {
|
||||
require('../lib/crashlogger')(new Error(`Failed to read the configured SSL certificate PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
Monitor.crashlog(new Error(`Failed to read the configured SSL certificate PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('SSL certificate config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.');
|
||||
|
|
@ -322,7 +327,7 @@ if (cluster.isMaster) {
|
|||
// In case there are additional SSL config settings besides the key and cert...
|
||||
appssl = require('https').createServer(Object.assign({}, Config.ssl.options, {key, cert}));
|
||||
} catch (e) {
|
||||
require('../lib/crashlogger')(`The SSL settings are misconfigured:\n${e.stack}`, `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
Monitor.crashlog(new Error(`The SSL settings are misconfigured:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -404,7 +409,7 @@ if (cluster.isMaster) {
|
|||
// @ts-ignore
|
||||
options.faye_server_options = {extensions: [deflate]};
|
||||
} catch (e) {
|
||||
require('../lib/crashlogger')(new Error("Dependency permessage-deflate is not installed or is otherwise unaccessable. No message compression will take place until server restart."), "Sockets");
|
||||
Monitor.crashlog(new Error("Dependency permessage-deflate is not installed or is otherwise unaccessable. No message compression will take place until server restart."), "Sockets");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,5 +712,7 @@ if (cluster.isMaster) {
|
|||
|
||||
console.log(`Test your server at http://${Config.bindaddress === '0.0.0.0' ? 'localhost' : Config.bindaddress}:${Config.port}`);
|
||||
|
||||
require('../lib/repl').start(`sockets-${cluster.worker.id}-${process.pid}`, cmd => eval(cmd));
|
||||
/** @type {typeof import('../lib/repl').Repl} */
|
||||
const Repl = require(/** @type {any} */('../.lib-dist/repl')).Repl;
|
||||
Repl.start(`sockets-${cluster.worker.id}-${process.pid}`, cmd => eval(cmd));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ class ValidatorAsync {
|
|||
* Process manager
|
||||
*********************************************************/
|
||||
|
||||
const QueryProcessManager = require('../lib/process-manager').QueryProcessManager;
|
||||
/** @type {typeof import('../lib/process-manager').QueryProcessManager} */
|
||||
const QueryProcessManager = require(/** @type {any} */('../.lib-dist/process-manager')).QueryProcessManager;
|
||||
|
||||
/**@type {QueryProcessManager} */
|
||||
/** @type {QueryProcessManager} */
|
||||
// @ts-ignore
|
||||
const PM = new QueryProcessManager(module, async message => {
|
||||
let {formatid, removeNicknames, team} = message;
|
||||
|
|
@ -44,7 +45,7 @@ const PM = new QueryProcessManager(module, async message => {
|
|||
try {
|
||||
problems = TeamValidator(formatid).validateTeam(parsedTeam, removeNicknames);
|
||||
} catch (err) {
|
||||
require('../lib/crashlogger')(err, 'A team validation', {
|
||||
require(/** @type {any} */('../.lib-dist/crashlogger'))(err, 'A team validation', {
|
||||
formatid: formatid,
|
||||
team: team,
|
||||
});
|
||||
|
|
@ -93,7 +94,9 @@ if (!PM.isParentProcess) {
|
|||
global.toId = Dex.getId;
|
||||
global.Chat = require('./chat');
|
||||
|
||||
require('../lib/repl').start(`team-validator-${process.pid}`, cmd => eval(cmd));
|
||||
/** @type {typeof import('../lib/repl').Repl} */
|
||||
const Repl = require(/** @type {any} */('../.lib-dist/repl')).Repl;
|
||||
Repl.start(`team-validator-${process.pid}`, cmd => eval(cmd));
|
||||
} else {
|
||||
PM.spawn(global.Config ? Config.validatorprocesses : 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ const PERMALOCK_CACHE_TIME = 30 * 24 * 60 * 60 * 1000;
|
|||
|
||||
const DEFAULT_TRAINER_SPRITES = [1, 2, 101, 102, 169, 170, 265, 266];
|
||||
|
||||
const FS = require('../lib/fs');
|
||||
/** @type {typeof import('../lib/fs').FS} */
|
||||
const FS = require(/** @type {any} */('../.lib-dist/fs')).FS;
|
||||
|
||||
/*********************************************************
|
||||
* Utility functions
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ const crypto = require('crypto');
|
|||
* Process manager
|
||||
*********************************************************/
|
||||
|
||||
const QueryProcessManager = require('../lib/process-manager').QueryProcessManager;
|
||||
/** @type {typeof import('../lib/process-manager').QueryProcessManager} */
|
||||
const QueryProcessManager = require(/** @type {any} */('../.lib-dist/process-manager')).QueryProcessManager;
|
||||
|
||||
/**@type {QueryProcessManager} */
|
||||
// @ts-ignore
|
||||
|
|
@ -39,7 +40,9 @@ if (!PM.isParentProcess) {
|
|||
// This is a child process!
|
||||
// @ts-ignore This file doesn't exist on the repository, so Travis checks fail if this isn't ignored
|
||||
global.Config = require('../config/config');
|
||||
require('../lib/repl').start('verifier', /** @param {string} cmd */ cmd => eval(cmd));
|
||||
/** @type {typeof import('../lib/repl').Repl} */
|
||||
const Repl = require(/** @type {any} */('../.lib-dist/repl')).Repl;
|
||||
Repl.start('verifier', /** @param {string} cmd */ cmd => eval(cmd));
|
||||
} else {
|
||||
PM.spawn(global.Config ? Config.verifierprocesses : 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ before('initialization', function () {
|
|||
} finally {
|
||||
config = require('../config/config');
|
||||
}
|
||||
require('./../lib/process-manager').disabled = true;
|
||||
require('./../.lib-dist/process-manager').disabled = true;
|
||||
|
||||
Object.assign(config, require('../config/config-example'));
|
||||
// Actually crash if we crash
|
||||
|
|
@ -39,7 +39,7 @@ before('initialization', function () {
|
|||
config.fakeladder = false;
|
||||
|
||||
// Don't create a REPL
|
||||
require('../lib/repl').start = noop;
|
||||
require('../.lib-dist/repl').Repl.start = noop;
|
||||
|
||||
// Start the server.
|
||||
require('../server');
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"types": ["node"],
|
||||
"exclude": [
|
||||
"./.sim-dist/*",
|
||||
"./.*-dist/*",
|
||||
"./server/index.js",
|
||||
"./server/chat-commands.js"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -54,6 +54,6 @@
|
|||
},
|
||||
"rulesDirectory": [],
|
||||
"linterOptions": {
|
||||
"exclude": ["node_modules/**/*", "**/*.js", "dev-tools/*", ".sim-dist/*"]
|
||||
"exclude": ["node_modules/**/*", "**/*.js", "dev-tools/*", ".*-dist/*"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user