addons-scanner-utils 2.5.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/functions.js +4 -2
- package/dist/io/base.d.ts +2 -2
- package/dist/io/base.js +2 -2
- package/dist/io/crx.d.ts +18 -0
- package/dist/io/crx.js +68 -0
- package/dist/io/directory.d.ts +1 -1
- package/dist/io/directory.js +2 -2
- package/dist/io/index.d.ts +1 -0
- package/dist/io/index.js +1 -0
- package/dist/io/utils.d.ts +1 -1
- package/dist/io/utils.js +3 -3
- package/dist/io/xpi.d.ts +1 -1
- package/dist/io/xpi.js +2 -2
- package/dist/stdio.js +8 -4
- package/dist/test-helpers.d.ts +15 -0
- package/dist/test-helpers.js +22 -5
- package/package.json +17 -10
package/dist/functions.js
CHANGED
|
@@ -20,13 +20,14 @@ const express_1 = __importDefault(require("express"));
|
|
|
20
20
|
const body_parser_1 = __importDefault(require("body-parser"));
|
|
21
21
|
const download_1 = __importDefault(require("download"));
|
|
22
22
|
const safe_compare_1 = __importDefault(require("safe-compare"));
|
|
23
|
-
|
|
23
|
+
const createApiError = ({ message, extraInfo, status = 500, }) => {
|
|
24
24
|
const error = new Error(message);
|
|
25
25
|
error.status = status;
|
|
26
26
|
error.extraInfo = extraInfo;
|
|
27
27
|
return error;
|
|
28
28
|
};
|
|
29
|
-
exports.
|
|
29
|
+
exports.createApiError = createApiError;
|
|
30
|
+
const createExpressApp = ({ _console = console, _download = download_1.default, _process = process, _unlinkFile = fs_1.default.promises.unlink, apiKeyEnvVarName = 'LAMBDA_API_KEY', requiredApiKeyParam = 'api_key', requiredDownloadUrlParam = 'download_url', tmpDir = os_1.default.tmpdir(), xpiFilename = 'input.xpi', } = {}) => (handler) => {
|
|
30
31
|
const app = express_1.default();
|
|
31
32
|
const allowedOrigin = _process.env.ALLOWED_ORIGIN || null;
|
|
32
33
|
if (!allowedOrigin) {
|
|
@@ -126,3 +127,4 @@ exports.createExpressApp = ({ _console = console, _download = download_1.default
|
|
|
126
127
|
});
|
|
127
128
|
return app;
|
|
128
129
|
};
|
|
130
|
+
exports.createExpressApp = createExpressApp;
|
package/dist/io/base.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Stderr } from '../stdio';
|
|
|
4
4
|
declare type ScanFileFunction = (_path: string, isDirectory: boolean) => boolean;
|
|
5
5
|
declare type Files = Record<string, unknown>;
|
|
6
6
|
export declare type IOBaseConstructorParams = {
|
|
7
|
-
|
|
7
|
+
filePath: string;
|
|
8
8
|
stderr: Stderr;
|
|
9
9
|
};
|
|
10
10
|
export declare class IOBase {
|
|
@@ -14,7 +14,7 @@ export declare class IOBase {
|
|
|
14
14
|
entries: string[];
|
|
15
15
|
maxSizeBytes: number;
|
|
16
16
|
shouldScanFile: ScanFileFunction;
|
|
17
|
-
constructor({
|
|
17
|
+
constructor({ filePath, stderr }: IOBaseConstructorParams);
|
|
18
18
|
setScanFileCallback(callback: ScanFileFunction): void;
|
|
19
19
|
getFile(path: string, fileStreamType?: 'stream' | 'string' | 'chunk'): Promise<string> | Promise<Buffer> | Promise<Readable>;
|
|
20
20
|
getFilesByExt(...extensions: string[]): Promise<string[]>;
|
package/dist/io/base.js
CHANGED
|
@@ -16,8 +16,8 @@ const const_1 = require("./const");
|
|
|
16
16
|
* Base class for io operations for both an Xpi or a directory.
|
|
17
17
|
*/
|
|
18
18
|
class IOBase {
|
|
19
|
-
constructor({
|
|
20
|
-
this.path =
|
|
19
|
+
constructor({ filePath, stderr }) {
|
|
20
|
+
this.path = filePath;
|
|
21
21
|
this.stderr = stderr;
|
|
22
22
|
this.files = {};
|
|
23
23
|
this.entries = [];
|
package/dist/io/crx.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import defaultFs from 'fs';
|
|
3
|
+
import yauzl, { ZipFile } from 'yauzl';
|
|
4
|
+
import { IOBaseConstructorParams } from './base';
|
|
5
|
+
import { Xpi } from './xpi';
|
|
6
|
+
export declare function defaultParseCRX(buf: Buffer): Buffer;
|
|
7
|
+
declare type CrxConstructorParams = IOBaseConstructorParams & {
|
|
8
|
+
fs?: typeof defaultFs;
|
|
9
|
+
parseCRX?: typeof defaultParseCRX;
|
|
10
|
+
zipLib?: typeof yauzl;
|
|
11
|
+
};
|
|
12
|
+
export declare class Crx extends Xpi {
|
|
13
|
+
fs: typeof defaultFs;
|
|
14
|
+
parseCRX: typeof defaultParseCRX;
|
|
15
|
+
constructor({ filePath, stderr, fs, parseCRX, zipLib, }: CrxConstructorParams);
|
|
16
|
+
open(): Promise<ZipFile>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/dist/io/crx.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Crx = exports.defaultParseCRX = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const yauzl_1 = __importDefault(require("yauzl"));
|
|
9
|
+
const xpi_1 = require("./xpi");
|
|
10
|
+
function defaultParseCRX(buf) {
|
|
11
|
+
if (buf.readUInt32BE(0) !== 0x43723234) {
|
|
12
|
+
throw new Error('Invalid header: Does not start with Cr24.');
|
|
13
|
+
}
|
|
14
|
+
const version = buf.readUInt32LE(4);
|
|
15
|
+
if (version === 2) {
|
|
16
|
+
const publicKeyLength = buf.readUInt32LE(8);
|
|
17
|
+
const signatureLength = buf.readUInt32LE(12);
|
|
18
|
+
// 16 = Magic number (4), CRX format version (4), lengths (2x4)
|
|
19
|
+
return buf.slice(16 + publicKeyLength + signatureLength);
|
|
20
|
+
}
|
|
21
|
+
if (version === 3) {
|
|
22
|
+
const crx3HeaderLength = buf.readUInt32LE(8);
|
|
23
|
+
// 12 = Magic number (4), CRX format version (4), header length (4)
|
|
24
|
+
return buf.slice(12 + crx3HeaderLength);
|
|
25
|
+
}
|
|
26
|
+
throw new Error('Unexpected crx format version number.');
|
|
27
|
+
}
|
|
28
|
+
exports.defaultParseCRX = defaultParseCRX;
|
|
29
|
+
/*
|
|
30
|
+
* A CRX file is just a ZIP file (eg an XPI) with some extra header
|
|
31
|
+
* information. We handle opening the file with a CRX parser, then treat it
|
|
32
|
+
* like an XPI after that.
|
|
33
|
+
*/
|
|
34
|
+
class Crx extends xpi_1.Xpi {
|
|
35
|
+
constructor({ filePath, stderr, fs = fs_1.default, parseCRX = defaultParseCRX, zipLib = yauzl_1.default, }) {
|
|
36
|
+
super({ filePath, stderr, zipLib, autoClose: true });
|
|
37
|
+
this.fs = fs;
|
|
38
|
+
this.parseCRX = parseCRX;
|
|
39
|
+
}
|
|
40
|
+
open() {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
this.fs.readFile(this.path, (err, buf) => {
|
|
43
|
+
if (err) {
|
|
44
|
+
reject(err);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Parse out the CRX header data from the actual ZIP contents.
|
|
48
|
+
let zipBuffer;
|
|
49
|
+
try {
|
|
50
|
+
zipBuffer = this.parseCRX(buf);
|
|
51
|
+
this.stderr.debug('obtained zip data from CRX file');
|
|
52
|
+
}
|
|
53
|
+
catch (err2) {
|
|
54
|
+
reject(err2);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.zipLib.fromBuffer(zipBuffer, (err3, zipfile) => {
|
|
58
|
+
if (err3) {
|
|
59
|
+
reject(err3);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
resolve(zipfile);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.Crx = Crx;
|
package/dist/io/directory.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare type Files = {
|
|
|
10
10
|
declare type DirectoryConstructorParams = IOBaseConstructorParams;
|
|
11
11
|
export declare class Directory extends IOBase {
|
|
12
12
|
files: Files;
|
|
13
|
-
constructor({
|
|
13
|
+
constructor({ filePath, stderr }: DirectoryConstructorParams);
|
|
14
14
|
getFiles(_walkPromise?: typeof walkPromise): Promise<Files>;
|
|
15
15
|
getPath(_path: string): Promise<string>;
|
|
16
16
|
getFileAsStream(_path: string, { encoding }?: {
|
package/dist/io/directory.js
CHANGED
|
@@ -21,8 +21,8 @@ const common_tags_1 = require("common-tags");
|
|
|
21
21
|
const base_1 = require("./base");
|
|
22
22
|
const utils_1 = require("./utils");
|
|
23
23
|
class Directory extends base_1.IOBase {
|
|
24
|
-
constructor({
|
|
25
|
-
super({
|
|
24
|
+
constructor({ filePath, stderr }) {
|
|
25
|
+
super({ filePath, stderr });
|
|
26
26
|
this.files = {};
|
|
27
27
|
}
|
|
28
28
|
getFiles(_walkPromise = utils_1.walkPromise) {
|
package/dist/io/index.d.ts
CHANGED
package/dist/io/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
__exportStar(require("./const"), exports);
|
|
14
|
+
__exportStar(require("./crx"), exports);
|
|
14
15
|
__exportStar(require("./directory"), exports);
|
|
15
16
|
__exportStar(require("./utils"), exports);
|
|
16
17
|
__exportStar(require("./xpi"), exports);
|
package/dist/io/utils.d.ts
CHANGED
|
@@ -13,6 +13,6 @@ export declare function walkPromise(curPath: string, { shouldIncludePath, stderr
|
|
|
13
13
|
size: number;
|
|
14
14
|
};
|
|
15
15
|
}>;
|
|
16
|
-
export declare function checkFileExists(
|
|
16
|
+
export declare function checkFileExists(filePath: string, { _lstat }?: {
|
|
17
17
|
_lstat?: typeof fs.lstat.__promisify__ | undefined;
|
|
18
18
|
}): Promise<fs.Stats>;
|
package/dist/io/utils.js
CHANGED
|
@@ -51,11 +51,11 @@ function walkPromise(curPath, { shouldIncludePath = () => true, stderr }) {
|
|
|
51
51
|
return walk(curPath);
|
|
52
52
|
}
|
|
53
53
|
exports.walkPromise = walkPromise;
|
|
54
|
-
function checkFileExists(
|
|
54
|
+
function checkFileExists(filePath, { _lstat = exports.lstat } = {}) {
|
|
55
55
|
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
-
const invalidMessage = new Error(`Path "${
|
|
56
|
+
const invalidMessage = new Error(`Path "${filePath}" is not a file or directory or does not exist.`);
|
|
57
57
|
try {
|
|
58
|
-
const stats = yield _lstat(
|
|
58
|
+
const stats = yield _lstat(filePath);
|
|
59
59
|
if (stats.isFile() === true || stats.isDirectory() === true) {
|
|
60
60
|
return stats;
|
|
61
61
|
}
|
package/dist/io/xpi.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare class Xpi extends IOBase {
|
|
|
14
14
|
files: Files;
|
|
15
15
|
zipLib: typeof yauzl;
|
|
16
16
|
zipfile: ZipFile | undefined;
|
|
17
|
-
constructor({ autoClose,
|
|
17
|
+
constructor({ autoClose, filePath, stderr, zipLib, }: XpiConstructorParams);
|
|
18
18
|
open(): Promise<ZipFile>;
|
|
19
19
|
handleEntry(entry: Entry, reject: (error: Error) => void): void;
|
|
20
20
|
getFiles(_onEventsSubscribed?: () => void): Promise<Files>;
|
package/dist/io/xpi.js
CHANGED
|
@@ -28,8 +28,8 @@ const base_1 = require("./base");
|
|
|
28
28
|
* feature, so we can disable it if needed.
|
|
29
29
|
*/
|
|
30
30
|
class Xpi extends base_1.IOBase {
|
|
31
|
-
constructor({ autoClose = true,
|
|
32
|
-
super({
|
|
31
|
+
constructor({ autoClose = true, filePath, stderr, zipLib = yauzl_1.default, }) {
|
|
32
|
+
super({ filePath, stderr });
|
|
33
33
|
this.files = {};
|
|
34
34
|
this.autoClose = autoClose;
|
|
35
35
|
this.zipLib = zipLib;
|
package/dist/stdio.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.createInMemoryStdout = exports.createConsoleStdout = exports.createInMem
|
|
|
6
6
|
// `verboseLevel` argument (and the number of `-v` passed to the CLI).
|
|
7
7
|
//
|
|
8
8
|
// By default, only errors are shown.
|
|
9
|
-
|
|
9
|
+
const createConsoleStderr = ({ _console = console, programName, verboseLevel = 0, }) => {
|
|
10
10
|
const logWithPrefix = (message) => {
|
|
11
11
|
_console.error(`${programName}: ${message}`);
|
|
12
12
|
};
|
|
@@ -29,7 +29,8 @@ exports.createConsoleStderr = ({ _console = console, programName, verboseLevel =
|
|
|
29
29
|
};
|
|
30
30
|
return stderr;
|
|
31
31
|
};
|
|
32
|
-
exports.
|
|
32
|
+
exports.createConsoleStderr = createConsoleStderr;
|
|
33
|
+
const createInMemoryStderr = () => {
|
|
33
34
|
return {
|
|
34
35
|
messages: {
|
|
35
36
|
debug: [],
|
|
@@ -47,16 +48,18 @@ exports.createInMemoryStderr = () => {
|
|
|
47
48
|
},
|
|
48
49
|
};
|
|
49
50
|
};
|
|
51
|
+
exports.createInMemoryStderr = createInMemoryStderr;
|
|
50
52
|
// `stdout` should be used for final outputs, and usually once at the end of
|
|
51
53
|
// the command.
|
|
52
|
-
|
|
54
|
+
const createConsoleStdout = ({ _console = console } = {}) => {
|
|
53
55
|
return {
|
|
54
56
|
write(message) {
|
|
55
57
|
_console.log(message);
|
|
56
58
|
},
|
|
57
59
|
};
|
|
58
60
|
};
|
|
59
|
-
exports.
|
|
61
|
+
exports.createConsoleStdout = createConsoleStdout;
|
|
62
|
+
const createInMemoryStdout = () => {
|
|
60
63
|
return {
|
|
61
64
|
output: '',
|
|
62
65
|
write(message) {
|
|
@@ -64,3 +67,4 @@ exports.createInMemoryStdout = () => {
|
|
|
64
67
|
},
|
|
65
68
|
};
|
|
66
69
|
};
|
|
70
|
+
exports.createInMemoryStdout = createInMemoryStdout;
|
package/dist/test-helpers.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'stream';
|
|
2
|
+
import { ZipFile, RandomAccessReader } from 'yauzl';
|
|
2
3
|
import { Stderr, Stdout } from './stdio';
|
|
3
4
|
export declare const createFakeStdout: () => Stdout;
|
|
4
5
|
export declare const createFakeStderr: () => Stderr;
|
|
@@ -10,3 +11,17 @@ export declare const createFakeFsStats: ({ isFile, isDirectory, }?: {
|
|
|
10
11
|
isDirectory: () => boolean;
|
|
11
12
|
isFile: () => boolean;
|
|
12
13
|
};
|
|
14
|
+
declare class FakeRandomAccessReader extends RandomAccessReader {
|
|
15
|
+
}
|
|
16
|
+
export declare const createFakeZipFile: ({ autoClose, centralDirectoryOffset, comment, decodeStrings, entryCount, fileSize, lazyEntries, reader, validateEntrySizes, }?: {
|
|
17
|
+
autoClose?: boolean | undefined;
|
|
18
|
+
centralDirectoryOffset?: number | undefined;
|
|
19
|
+
comment?: string | undefined;
|
|
20
|
+
decodeStrings?: boolean | undefined;
|
|
21
|
+
entryCount?: number | undefined;
|
|
22
|
+
fileSize?: number | undefined;
|
|
23
|
+
lazyEntries?: boolean | undefined;
|
|
24
|
+
reader?: FakeRandomAccessReader | undefined;
|
|
25
|
+
validateEntrySizes?: boolean | undefined;
|
|
26
|
+
}) => ZipFile;
|
|
27
|
+
export {};
|
package/dist/test-helpers.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createFakeFsStats = exports.readStringFromStream = exports.createFakeStderr = exports.createFakeStdout = void 0;
|
|
4
|
-
|
|
3
|
+
exports.createFakeZipFile = exports.createFakeFsStats = exports.readStringFromStream = exports.createFakeStderr = exports.createFakeStdout = void 0;
|
|
4
|
+
const yauzl_1 = require("yauzl");
|
|
5
|
+
const createFakeStdout = () => {
|
|
5
6
|
return {
|
|
6
7
|
write: jest.fn(),
|
|
7
8
|
};
|
|
8
9
|
};
|
|
9
|
-
exports.
|
|
10
|
+
exports.createFakeStdout = createFakeStdout;
|
|
11
|
+
const createFakeStderr = () => {
|
|
10
12
|
return {
|
|
11
13
|
debug: jest.fn(),
|
|
12
14
|
error: jest.fn(),
|
|
13
15
|
info: jest.fn(),
|
|
14
16
|
};
|
|
15
17
|
};
|
|
16
|
-
exports.
|
|
18
|
+
exports.createFakeStderr = createFakeStderr;
|
|
19
|
+
const readStringFromStream = (readStream, encoding) => {
|
|
17
20
|
return new Promise((resolve, reject) => {
|
|
18
21
|
let content = '';
|
|
19
22
|
readStream.on('readable', () => {
|
|
@@ -29,9 +32,23 @@ exports.readStringFromStream = (readStream, encoding) => {
|
|
|
29
32
|
readStream.on('error', reject);
|
|
30
33
|
});
|
|
31
34
|
};
|
|
32
|
-
exports.
|
|
35
|
+
exports.readStringFromStream = readStringFromStream;
|
|
36
|
+
const createFakeFsStats = ({ isFile = false, isDirectory = false, } = {}) => {
|
|
33
37
|
return {
|
|
34
38
|
isDirectory: () => isDirectory,
|
|
35
39
|
isFile: () => isFile,
|
|
36
40
|
};
|
|
37
41
|
};
|
|
42
|
+
exports.createFakeFsStats = createFakeFsStats;
|
|
43
|
+
class FakeRandomAccessReader extends yauzl_1.RandomAccessReader {
|
|
44
|
+
}
|
|
45
|
+
const createFakeZipFile = ({ autoClose = true, centralDirectoryOffset = 0, comment = '', decodeStrings = true,
|
|
46
|
+
// This is set to `1` to avoid an error with `RandomAccessReader.unref()`
|
|
47
|
+
// because we are using a `FakeRandomAccessReader`
|
|
48
|
+
entryCount = 1, fileSize = 0,
|
|
49
|
+
// This is set to `true` to avoid an error due to the ZipFile trying to
|
|
50
|
+
// automatically load the entries (because `entryCount = 1` above).
|
|
51
|
+
lazyEntries = true, reader = new FakeRandomAccessReader(), validateEntrySizes = true, } = {}) => {
|
|
52
|
+
return new yauzl_1.ZipFile(reader, centralDirectoryOffset, fileSize, entryCount, comment, autoClose, lazyEntries, decodeStrings, validateEntrySizes);
|
|
53
|
+
};
|
|
54
|
+
exports.createFakeZipFile = createFakeZipFile;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "addons-scanner-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Various addons related helpers to build CLIs.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,21 +10,24 @@
|
|
|
10
10
|
"author": "Mozilla Add-ons Team",
|
|
11
11
|
"license": "MPL-2.0",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@types/download": "6.2.4",
|
|
14
13
|
"@types/yauzl": "2.9.1",
|
|
15
|
-
"body-parser": "1.19.0",
|
|
16
14
|
"common-tags": "1.8.0",
|
|
17
|
-
"download": "8.0.0",
|
|
18
|
-
"express": "4.17.1",
|
|
19
15
|
"first-chunk-stream": "3.0.0",
|
|
20
|
-
"safe-compare": "1.1.4",
|
|
21
16
|
"strip-bom-stream": "4.0.0",
|
|
22
|
-
"upath": "
|
|
17
|
+
"upath": "2.0.1",
|
|
23
18
|
"yauzl": "2.10.0"
|
|
24
19
|
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@types/download": "6.2.4",
|
|
22
|
+
"body-parser": "1.19.0",
|
|
23
|
+
"download": "8.0.0",
|
|
24
|
+
"express": "4.17.1",
|
|
25
|
+
"safe-compare": "1.1.4"
|
|
26
|
+
},
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"@types/common-tags": "^1.8.0",
|
|
27
|
-
"@types/
|
|
29
|
+
"@types/download": "6.2.4",
|
|
30
|
+
"@types/express": "4.17.9",
|
|
28
31
|
"@types/jest": "^26.0.0",
|
|
29
32
|
"@types/node": "^12.7.5",
|
|
30
33
|
"@types/safe-compare": "^1.1.0",
|
|
@@ -32,17 +35,21 @@
|
|
|
32
35
|
"@types/supertest": "^2.0.8",
|
|
33
36
|
"@typescript-eslint/eslint-plugin": "^4.0.0",
|
|
34
37
|
"@typescript-eslint/parser": "^4.0.0",
|
|
38
|
+
"body-parser": "1.19.0",
|
|
35
39
|
"codecov": "^3.5.0",
|
|
40
|
+
"download": "8.0.0",
|
|
36
41
|
"eslint": "^7.0.0",
|
|
37
42
|
"eslint-config-amo": "^3.0.0",
|
|
38
43
|
"eslint-config-prettier": "^6.3.0",
|
|
39
44
|
"eslint-plugin-amo": "^1.10.2",
|
|
45
|
+
"express": "4.17.1",
|
|
40
46
|
"jest": "^26.0.0",
|
|
41
|
-
"prettier": "2.1.
|
|
47
|
+
"prettier": "2.1.2",
|
|
42
48
|
"pretty-quick": "^3.0.0",
|
|
43
49
|
"rimraf": "^3.0.0",
|
|
50
|
+
"safe-compare": "1.1.4",
|
|
44
51
|
"sinon": "^9.0.0",
|
|
45
|
-
"supertest": "^
|
|
52
|
+
"supertest": "^6.0.0",
|
|
46
53
|
"ts-jest": "^26.0.0",
|
|
47
54
|
"type-coverage": "^2.3.0",
|
|
48
55
|
"typescript": "^4.0.0"
|