♻️ Only use fat-arrow functions when immediately returning result
This commit is contained in:
parent
872b87a4e0
commit
9aff99ae86
19 changed files with 59 additions and 61 deletions
|
@ -5,7 +5,7 @@ import * as childProcess from 'child_process';
|
|||
* Takes as input the host domain name, the path and the file size
|
||||
*/
|
||||
export default function downloadWithCurl({ host, path, tempFileName }: {host: string, path: string, tempFileName: string}): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const url = `http://${host}${(path.substr(0, 1) === '/' ? '' : '/')}${path}`;
|
||||
|
||||
const parameters: string[] = [
|
||||
|
@ -21,11 +21,11 @@ export default function downloadWithCurl({ host, path, tempFileName }: {host: st
|
|||
const spawnedProcess = childProcess.spawn('curl', parameters);
|
||||
|
||||
spawnedProcess.stderr.setEncoding('utf8');
|
||||
spawnedProcess.stderr.on('data', (error) => {
|
||||
spawnedProcess.stderr.on('data', function(error) {
|
||||
reject(`Error in process:\n> curl ${parameters.join(' ')}\n${error}`);
|
||||
});
|
||||
|
||||
spawnedProcess.on('exit', (code) => {
|
||||
spawnedProcess.on('exit', function(code) {
|
||||
if (code === 0) {
|
||||
resolve(tempFileName);
|
||||
} else {
|
||||
|
|
|
@ -2,9 +2,9 @@ import * as fs from 'fs';
|
|||
|
||||
/** Checks if this file already exists on the local disk, so we don't need to download it again. */
|
||||
export default function checkLocalCache(fileName: string, size: number): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
//Check if file already exists
|
||||
fs.exists(fileName, (exists) => {
|
||||
fs.exists(fileName, function(exists) {
|
||||
if (exists) {
|
||||
const fileStats = fs.statSync(fileName);
|
||||
//check if file size matches
|
||||
|
@ -12,7 +12,7 @@ export default function checkLocalCache(fileName: string, size: number): Promise
|
|||
resolve(true);
|
||||
} else {
|
||||
//delete file so we can overwrite it
|
||||
fs.unlink(fileName, (error) => {
|
||||
fs.unlink(fileName, function(error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
|
|
@ -3,29 +3,29 @@ import * as path from 'path';
|
|||
|
||||
/** Recursively creates the given directory. */
|
||||
export default function createDirRecursively(folderName: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
//Try to create directory
|
||||
fs.mkdir(folderName, (error) => {
|
||||
fs.mkdir(folderName, function(error) {
|
||||
//If it fails, we first need to create parent directory
|
||||
if (error) {
|
||||
switch (error.code) {
|
||||
case 'ENOENT': //parent does not exist
|
||||
//Create parent
|
||||
const parentFolder = path.dirname(folderName);
|
||||
createDirRecursively(parentFolder).then(() => {
|
||||
createDirRecursively(parentFolder).then(function() {
|
||||
//Then try again
|
||||
try {
|
||||
resolve(createDirRecursively(folderName));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}).catch((parentError) => {
|
||||
}).catch(function(parentError) {
|
||||
reject(parentError);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'EEXIST': { //already exists (either as file or directory)
|
||||
fs.stat(folderName, (statError, stats) => {
|
||||
fs.stat(folderName, function(statError, stats) {
|
||||
if (statError) {
|
||||
reject(statError);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export default function handleResponse(
|
|||
//If we receive a part of the response, store it
|
||||
const chunkList: Buffer[] = [];
|
||||
let totalLength = 0;
|
||||
response.on('data', (chunk: Buffer) => {
|
||||
response.on('data', function(chunk: Buffer) {
|
||||
totalLength += chunk.length;
|
||||
|
||||
//Exit early if we received too much data
|
||||
|
@ -35,7 +35,7 @@ export default function handleResponse(
|
|||
});
|
||||
|
||||
//If we finished reading response, check for correctness, then return it
|
||||
response.on('end', () => {
|
||||
response.on('end', function() {
|
||||
//Check that length is correct
|
||||
if (totalLength !== headerLength) {
|
||||
return reject(`Expected length ${headerLength} but received ${totalLength}.`);
|
||||
|
|
|
@ -31,23 +31,23 @@ import * as dns from 'dns';
|
|||
import { IDnsResult } from '../../interfaces/IDnsResult';
|
||||
|
||||
//TODO: send e-mail with the error
|
||||
const assert = (condition: boolean) => { if (!condition) { console.warn('Assert failed'); } };
|
||||
const assert = function(condition: boolean) { if (!condition) { console.warn('Assert failed'); } };
|
||||
|
||||
/** Looks up the given domain and returns a list of IP addresses, along with their time-to-live */
|
||||
async function resolveDns(domain: string): Promise<IDnsResult[]> {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(function(resolve) {
|
||||
//check given string for correctness to prevent injection attacks
|
||||
if (domain.match(/^[a-z0-9]+(?:[-.]{1}[a-z0-9]+)*\.[a-z]{2,3}$/) === null) { return resolve([]); }
|
||||
|
||||
//Check Level3/North_America separately
|
||||
if (domain !== 'cdn-patch.swtor.com') {
|
||||
dns.resolve4(domain, { ttl: true }, (err, result) => {
|
||||
return resolve(result.map(({ address, ttl }) => ({ address, ttl, type: 'level3-us' as IDnsResult['type'] })));
|
||||
});
|
||||
dns.resolve4(domain, { ttl: true }, (err, result) => (
|
||||
resolve(result.map(({ address, ttl }) => ({ address, ttl, type: 'level3-us' as IDnsResult['type'] })))
|
||||
));
|
||||
} else {
|
||||
//Use bash so we get more information.
|
||||
//Also do plenty of asserts to ensure that overall CDN structure has stayed unchanged, and TODO send e-mail if it's different (max. once per hour)
|
||||
exec('dig +noall +answer "cdn-patch.swtor.com"', { timeout: 10000 }, (error, stdout) => {
|
||||
exec('dig +noall +answer "cdn-patch.swtor.com"', { timeout: 10000 }, function(error, stdout) {
|
||||
//check for error
|
||||
assert(!error);
|
||||
if (error) {
|
||||
|
|
|
@ -18,7 +18,7 @@ export default function saveResponse(
|
|||
response.pipe(writeStream);
|
||||
|
||||
//Wait until everything is written to disk, then return file name
|
||||
writeStream.on('close', () => {
|
||||
writeStream.on('close', function() {
|
||||
resolve(filePath);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import handleResponse from './funcs/handleResponse';
|
|||
|
||||
/** Downloads the given URL into memory and returns it as an ArrayBuffer. Throws error if download fails or file is too large to be handled in memory. */
|
||||
export default function getUrlContents({ host, path }: {host: string, path: string}): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
//Create HTTP request
|
||||
const request = http.request({
|
||||
family: 4,
|
||||
|
@ -12,7 +12,7 @@ export default function getUrlContents({ host, path }: {host: string, path: stri
|
|||
}, handleResponse.bind(null, resolve, (reason: string) => { request.abort(); reject(reason); }));
|
||||
|
||||
//In case of connection errors, exit early
|
||||
request.on('error', (error) => {
|
||||
request.on('error', function(error) {
|
||||
request.abort();
|
||||
reject(error);
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ async function heartbeatDns(domain: string) {
|
|||
|
||||
//Update array with new information
|
||||
dnsResults.forEach(
|
||||
({ address, type }, index) => {
|
||||
function({ address, type }, index) {
|
||||
//Calculate weight:
|
||||
//on cdn-patch.swtor.com: 3 if first, 2 if second, otherwise 1
|
||||
let weight = (index < 2) ? (3 - index) : 1;
|
||||
|
@ -60,14 +60,14 @@ async function heartbeatDns(domain: string) {
|
|||
//Decay weights - reduce them based on update frequency (-50% if full minute, but less if TTL was shorter than a minute)
|
||||
const decayFactor = 0.5 ** ((now - lastUpdate) / 60000);
|
||||
lastUpdate = now;
|
||||
servers.forEach((server) => { server.weight *= decayFactor; });
|
||||
servers.forEach(function(server) { server.weight *= decayFactor; });
|
||||
|
||||
//Sort the array by weight
|
||||
servers.sort((a, b) => b.weight - a.weight);
|
||||
|
||||
//Output current list
|
||||
let output = '';
|
||||
servers.forEach((server) => {
|
||||
servers.forEach(function(server) {
|
||||
//set colors based on server type, see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
//bright color if seen within last 5 minutes
|
||||
if (now - server.lastSeen < 300000) { output += '\x1b[1m'; } else { output += '\x1b[0m'; }
|
||||
|
|
|
@ -3,7 +3,7 @@ import updateKeys from './lib/updateKeys';
|
|||
export default function getDecryptor(decryptionKeys: [number, number, number]) {
|
||||
let [key0, key1, key2] = decryptionKeys;
|
||||
|
||||
return (chunk: Buffer) => {
|
||||
return function(chunk: Buffer) {
|
||||
for (let i = 0; i < chunk.length; i += 1) {
|
||||
//read byte
|
||||
let curChar = chunk.readUInt8(i);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//Karatsuba algorithm - https://stackoverflow.com/questions/31087787/javascript-32bit-integer-multiply-simulation
|
||||
const int32Mul = (x: number, y: number) => {
|
||||
export default function int32Mul(x: number, y: number) {
|
||||
// We use B = 2 and m = 16, because it will make sure that we only do multiplications with
|
||||
// 16 Bit per factor so that the result must have less than 32 Bit in total (which fits well
|
||||
// into a double).
|
||||
|
@ -13,6 +13,4 @@ const int32Mul = (x: number, y: number) => {
|
|||
// z1 + z0. We can discard z2 completely as it only contains a value out of our relevant bounds.
|
||||
// Both z1 and z0 are 32 Bit, but we shift out the top 16 Bit of z1.
|
||||
return (((x1 * y0 + x0 * y1) << 16) + (x0 * y0)) | 0;
|
||||
};
|
||||
|
||||
export default int32Mul;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export default async function extractFileAsStream(file: ISsnFileEntry, inputStre
|
|||
|
||||
//pipe into decompression
|
||||
const decompressTransform = zlib.createInflateRaw();
|
||||
decompressTransform.on('error', (error) => {
|
||||
decompressTransform.on('error', function(error) {
|
||||
//TODO: need to throw error sync, not async
|
||||
throw new Error(`Error during decompression of "${file.name}": ${error.message}`);
|
||||
});
|
||||
|
|
|
@ -79,7 +79,7 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
//--------------------------------------------------------------------------------------------------------------
|
||||
//Perform the patching
|
||||
|
||||
const extractAdded = async (file: ISsnFileEntry) => {
|
||||
const extractAdded = async function(file: ISsnFileEntry) {
|
||||
try {
|
||||
//create file write stream
|
||||
const outputName = path.join(targetDir, file.name);
|
||||
|
@ -89,7 +89,7 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
//start installation
|
||||
await launch(diskFilenames[file.diskNumberStart], file.offset, file.compressedSize, file.decryptionKeys, undefined, outputNameTemp);
|
||||
|
||||
fs.rename(outputNameTemp, outputName, (renameError) => {
|
||||
fs.rename(outputNameTemp, outputName, function(renameError) {
|
||||
if (renameError) {
|
||||
throw new Error(`Could not rename output file "${outputNameTemp}": ${renameError.message}`);
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
}
|
||||
};
|
||||
|
||||
const extractChanged = async (file: ISsnFileEntry) => {
|
||||
const extractChanged = async function(file: ISsnFileEntry) {
|
||||
try {
|
||||
const sourceFile = path.join(sourceDir, file.name);
|
||||
const outputName = path.join(targetDir, file.name);
|
||||
|
@ -113,18 +113,18 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
|
||||
//clean up: delete source file if necessary, and remove .tmp file extension
|
||||
if (sourceDir === targetDir) {
|
||||
fs.unlink(sourceFile, (deleteError) => {
|
||||
fs.unlink(sourceFile, function(deleteError) {
|
||||
if (deleteError) {
|
||||
throw new Error(`Could not delete old source file "${sourceFile}": ${deleteError.message}`);
|
||||
}
|
||||
fs.rename(outputNameTemp, outputName, (renameError) => {
|
||||
fs.rename(outputNameTemp, outputName, function(renameError) {
|
||||
if (renameError) {
|
||||
throw new Error(`Could not rename output file "${outputNameTemp}": ${renameError.message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
fs.rename(outputNameTemp, outputName, (renameError) => {
|
||||
fs.rename(outputNameTemp, outputName, function(renameError) {
|
||||
if (renameError) {
|
||||
throw new Error(`Could not rename output file "${outputNameTemp}": ${renameError.message}`);
|
||||
}
|
||||
|
@ -136,10 +136,10 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
}
|
||||
};
|
||||
|
||||
const deleteRemoved = async (file: ISsnFileEntry) => {
|
||||
const deleteRemoved = async function(file: ISsnFileEntry) {
|
||||
//delete file
|
||||
const fileName = path.join(targetDir, file.name);
|
||||
fs.unlink(fileName, (error) => {
|
||||
fs.unlink(fileName, function(error) {
|
||||
if (error) {
|
||||
console.error(`Could not delete removed file "${file.name}"`, error);
|
||||
}
|
||||
|
@ -147,12 +147,12 @@ export default async function installPatch({ product, from, to, sourceDirectory,
|
|||
//TODO: delete folder (and parent folders) that are empty
|
||||
};
|
||||
|
||||
const copyUnchanged = async (file: ISsnFileEntry) => {
|
||||
const copyUnchanged = async function(file: ISsnFileEntry) {
|
||||
//copy file
|
||||
const sourceName = path.join(sourceDir, file.name);
|
||||
const targetName = path.join(targetDir, file.name);
|
||||
await createDirRecursively(path.dirname(targetName));
|
||||
fs.copyFile(sourceName, targetName, (error) => {
|
||||
fs.copyFile(sourceName, targetName, function(error) {
|
||||
if (error) {
|
||||
console.error(`Could not copy unchanged file "${file.name}"`, error);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ export default function launchProcess(
|
|||
previousFile: string | undefined,
|
||||
output: string | fs.WriteStream,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const parameters = [
|
||||
'--disk', diskFile,
|
||||
'--offset', offset,
|
||||
|
@ -32,7 +32,7 @@ export default function launchProcess(
|
|||
|
||||
if (typeof output === 'string') {
|
||||
spawnedProcess.stdout.setEncoding('utf8');
|
||||
spawnedProcess.stdout.on('data', (chunk) => {
|
||||
spawnedProcess.stdout.on('data', function(chunk) {
|
||||
console.log(chunk);
|
||||
});
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ export default function launchProcess(
|
|||
spawnedProcess.stdout.on('end', resolve);
|
||||
|
||||
spawnedProcess.stderr.setEncoding('utf8');
|
||||
spawnedProcess.stderr.on('data', (error) => {
|
||||
spawnedProcess.stderr.on('data', function(error) {
|
||||
reject(`Error in process:\n> ${processPath} ${parameters.join(' ')}\n${error}`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
export default function taskManager(tasks: Array<() => Promise<void>>, maxConcurrentTasks: number): Promise<any[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const returnValues = Array(tasks.length);
|
||||
const remainingTasks = tasks;
|
||||
let currentlyRunningTasks = 0;
|
||||
|
||||
const startNewTask = () => {
|
||||
const startNewTask = function() {
|
||||
//Exit if we completed all tasks
|
||||
if (remainingTasks.length === 0) {
|
||||
if (currentlyRunningTasks === 0) {
|
||||
|
@ -15,11 +15,11 @@ export default function taskManager(tasks: Array<() => Promise<void>>, maxConcur
|
|||
const curTask = remainingTasks.pop() as () => Promise<void>;
|
||||
const curTaskIndex = remainingTasks.length;
|
||||
currentlyRunningTasks += 1;
|
||||
curTask().then((...result) => {
|
||||
curTask().then(function(...result) {
|
||||
returnValues[curTaskIndex] = result;
|
||||
currentlyRunningTasks -= 1;
|
||||
return startNewTask();
|
||||
}).catch((error) => {
|
||||
}).catch(function(error) {
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ export default function parsePatchManifest(manifestFile: any): IManifest {
|
|||
|
||||
//<Releases><Release><Id>0</Id><SHA1>53678f8057e52896a8145dca5c188ab3f24fa55f</SHA1></Release></Releases>
|
||||
const Releases = PatchManifest.elements[7];
|
||||
Releases.elements.forEach((Release: any) => {
|
||||
Releases.elements.forEach(function(Release: any) {
|
||||
const id = Release.elements[0].elements[0].text;
|
||||
const sha1 = Release.elements[1].elements[0].text;
|
||||
out.releases[id] = { sha1, from: [], to: [] };
|
||||
|
@ -20,7 +20,7 @@ export default function parsePatchManifest(manifestFile: any): IManifest {
|
|||
|
||||
//<ReleaseUpdatePaths><ReleaseUpdatePath><From>287</From><To>288</To><ExtraDataItem>...</ExtraDataItem></ReleaseUpdatePath></ReleaseUpdatePaths
|
||||
const ReleaseUpdatePaths = PatchManifest.elements[8];
|
||||
ReleaseUpdatePaths.elements.forEach((ReleaseUpdatePath: any) => {
|
||||
ReleaseUpdatePaths.elements.forEach(function(ReleaseUpdatePath: any) {
|
||||
const from = ReleaseUpdatePath.elements[0].elements[0].text;
|
||||
const to = ReleaseUpdatePath.elements[1].elements[0].text;
|
||||
//Release -1 does not exist but is a valid "from", e.g. for -1to0
|
||||
|
|
|
@ -2,8 +2,8 @@ import * as stream from 'stream';
|
|||
|
||||
/** Returns a promise that resolves as soon as the given stream has the given number of bytes ready for reading. */
|
||||
function waitReadableLength(inputStream: stream.Readable, minLength: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
return new Promise(function(resolve) {
|
||||
const interval = setInterval(function() {
|
||||
if (inputStream.readableLength >= minLength) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import * as stream from 'stream';
|
||||
|
||||
export default function streamToArrayBuffer(inputStream: stream.Readable): Promise<Buffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const chunks: Buffer[] = [];
|
||||
let totalSize = 0;
|
||||
|
||||
//Convert chunks to string
|
||||
inputStream.on('data', (chunk: Buffer) => {
|
||||
inputStream.on('data', function(chunk: Buffer) {
|
||||
chunks.push(chunk);
|
||||
totalSize += chunk.length;
|
||||
});
|
||||
|
||||
//Output final string
|
||||
inputStream.on('end', () => {
|
||||
inputStream.on('end', function() {
|
||||
const outBuffer = Buffer.concat(chunks, totalSize);
|
||||
resolve(outBuffer);
|
||||
});
|
||||
|
||||
//Exit on error
|
||||
inputStream.on('error', (error) => {
|
||||
inputStream.on('error', function(error) {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,22 +3,22 @@ import * as stream from 'stream';
|
|||
export default function streamToString(inputStream: stream.Readable): Promise<string> {
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const stringParts: string[] = [];
|
||||
|
||||
//Convert chunks to string
|
||||
inputStream.on('data', (chunk: Buffer) => {
|
||||
inputStream.on('data', function(chunk: Buffer) {
|
||||
stringParts.push(decoder.decode(chunk, { stream: true }));
|
||||
});
|
||||
|
||||
//Output final string
|
||||
inputStream.on('end', () => {
|
||||
inputStream.on('end', function() {
|
||||
stringParts.push(decoder.decode());
|
||||
resolve(stringParts.join(''));
|
||||
});
|
||||
|
||||
//Exit on error
|
||||
inputStream.on('error', (error) => {
|
||||
inputStream.on('error', function(error) {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ export default function verifyPatch(fileEntries: ISsnFileEntry[], product: Produ
|
|||
|
||||
//Patches from -1 must not have diff type NewFile
|
||||
if (from === -1) {
|
||||
fileEntries.filter((file) => file.diffType !== SsnDiffType.NewFile).forEach((file) => {
|
||||
fileEntries.filter((file) => file.diffType !== SsnDiffType.NewFile).forEach(function(file) {
|
||||
throw new Error(`Patches from -1 must be included in full, but this patch had a file "${file.name}" with diff type ${file.diffType}.`);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue