pagespeed-quest 0.1.2 → 0.3.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/CHANGELOG.md +5 -0
- package/README.ja.md +22 -2
- package/README.md +21 -1
- package/package.json +25 -21
- package/build/main/adhoc.d.ts +0 -2
- package/build/main/adhoc.js +0 -48
- package/build/main/command.d.ts +0 -2
- package/build/main/command.js +0 -103
- package/build/main/common-types.d.ts +0 -41
- package/build/main/common-types.js +0 -3
- package/build/main/content-encoding.d.ts +0 -11
- package/build/main/content-encoding.js +0 -51
- package/build/main/encoding.d.ts +0 -11
- package/build/main/encoding.js +0 -51
- package/build/main/formatting.d.ts +0 -8
- package/build/main/formatting.js +0 -64
- package/build/main/http.d.ts +0 -27
- package/build/main/http.js +0 -106
- package/build/main/index.d.ts +0 -9
- package/build/main/index.js +0 -26
- package/build/main/inventory.d.ts +0 -39
- package/build/main/inventory.js +0 -171
- package/build/main/logger.d.ts +0 -20
- package/build/main/logger.js +0 -22
- package/build/main/playback/inventory.d.ts +0 -0
- package/build/main/playback/inventory.js +0 -47
- package/build/main/playback.d.ts +0 -22
- package/build/main/playback.js +0 -111
- package/build/main/proxy.d.ts +0 -40
- package/build/main/proxy.js +0 -111
- package/build/main/recording/proxy.d.ts +0 -28
- package/build/main/recording/proxy.js +0 -90
- package/build/main/recording.d.ts +0 -28
- package/build/main/recording.js +0 -95
- package/build/main/throttling.d.ts +0 -34
- package/build/main/throttling.js +0 -88
- package/build/main/url.d.ts +0 -3
- package/build/main/url.js +0 -67
- package/build/module/adhoc.d.ts +0 -2
- package/build/module/adhoc.js +0 -40
- package/build/module/command.d.ts +0 -2
- package/build/module/command.js +0 -98
- package/build/module/common-types.d.ts +0 -41
- package/build/module/common-types.js +0 -2
- package/build/module/content-encoding.d.ts +0 -11
- package/build/module/content-encoding.js +0 -43
- package/build/module/encoding.d.ts +0 -11
- package/build/module/encoding.js +0 -43
- package/build/module/formatting.d.ts +0 -8
- package/build/module/formatting.js +0 -55
- package/build/module/http.d.ts +0 -27
- package/build/module/http.js +0 -96
- package/build/module/index.d.ts +0 -9
- package/build/module/index.js +0 -10
- package/build/module/inventory.d.ts +0 -39
- package/build/module/inventory.js +0 -165
- package/build/module/logger.d.ts +0 -20
- package/build/module/logger.js +0 -15
- package/build/module/playback/inventory.d.ts +0 -0
- package/build/module/playback/inventory.js +0 -47
- package/build/module/playback.d.ts +0 -22
- package/build/module/playback.js +0 -102
- package/build/module/proxy.d.ts +0 -40
- package/build/module/proxy.js +0 -111
- package/build/module/recording/proxy.d.ts +0 -28
- package/build/module/recording/proxy.js +0 -85
- package/build/module/recording.d.ts +0 -28
- package/build/module/recording.js +0 -92
- package/build/module/throttling.d.ts +0 -34
- package/build/module/throttling.js +0 -89
- package/build/module/url.d.ts +0 -3
- package/build/module/url.js +0 -59
package/build/main/http.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
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.stringifyContentTypeHeader = exports.parseContentTypeHeader = exports.requestContentFilePath = exports.normalizeUrl = void 0;
|
|
7
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const DirectoryIndex = 'index.html';
|
|
10
|
-
const BasenameMaxLength = 196;
|
|
11
|
-
const HashLength = 8;
|
|
12
|
-
const IgnoreParams = process.env.IGNORE_PARAMS || 'ts';
|
|
13
|
-
const IgnoreParamsRegex = IgnoreParams.split(/\s*,\s*/).map((p) => new RegExp(`(?<=[?&]${p}=)[^&]*`, 'g'));
|
|
14
|
-
/**
|
|
15
|
-
* Remove IgnoreParams from URL
|
|
16
|
-
* Default: ts (timestamp) assumed different for each request
|
|
17
|
-
* @param url
|
|
18
|
-
* @returns
|
|
19
|
-
*/
|
|
20
|
-
function normalizeUrl(url) {
|
|
21
|
-
const urlObj = typeof url === 'string' ? new URL(url) : url;
|
|
22
|
-
// Remove dynamic params
|
|
23
|
-
if (urlObj.search !== '') {
|
|
24
|
-
urlObj.search = IgnoreParamsRegex.reduce((search, re) => {
|
|
25
|
-
return search.replace(re, '');
|
|
26
|
-
}, urlObj.search);
|
|
27
|
-
}
|
|
28
|
-
return urlObj;
|
|
29
|
-
}
|
|
30
|
-
exports.normalizeUrl = normalizeUrl;
|
|
31
|
-
/**
|
|
32
|
-
* Convert URL to content file path
|
|
33
|
-
* For example:
|
|
34
|
-
* https://example.com/foo/bar.html?hoge=123 -> example.com/foo/bar~hoge=123.html
|
|
35
|
-
* - Add directory index (index.html) if URL ends with slash
|
|
36
|
-
* - Shorten too long basename with short hash
|
|
37
|
-
* - Ignore dynamic params for example: ts=123
|
|
38
|
-
* @param url
|
|
39
|
-
* @returns
|
|
40
|
-
*/
|
|
41
|
-
function requestContentFilePath(method, url) {
|
|
42
|
-
const urlObj = normalizeUrl(url);
|
|
43
|
-
const protocol = urlObj.protocol.replace(/:/g, '');
|
|
44
|
-
const host = urlObj.host.replace(/:/g, '~');
|
|
45
|
-
// Directory Index (index.html)
|
|
46
|
-
let pathname = urlObj.pathname;
|
|
47
|
-
if (pathname.endsWith('/')) {
|
|
48
|
-
pathname += DirectoryIndex;
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
const ext = path_1.default.extname(pathname);
|
|
52
|
-
if (ext === '') {
|
|
53
|
-
pathname = path_1.default.join(pathname, DirectoryIndex);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const dir = path_1.default.dirname(pathname);
|
|
57
|
-
const ext = path_1.default.extname(pathname);
|
|
58
|
-
const base = path_1.default.basename(pathname, ext);
|
|
59
|
-
let filename = base;
|
|
60
|
-
// Search params
|
|
61
|
-
if (urlObj.search !== '') {
|
|
62
|
-
// Remove dynamic params
|
|
63
|
-
const search = IgnoreParamsRegex.reduce((search, re) => {
|
|
64
|
-
return search.replace(re, '');
|
|
65
|
-
}, urlObj.search);
|
|
66
|
-
filename = [filename, search.slice(1)].join('~');
|
|
67
|
-
}
|
|
68
|
-
// Shorten too long basename
|
|
69
|
-
if (filename.length > BasenameMaxLength) {
|
|
70
|
-
const trunk = filename.slice(0, BasenameMaxLength);
|
|
71
|
-
const hash = crypto_1.default.createHash('sha1');
|
|
72
|
-
hash.update(filename);
|
|
73
|
-
const digest = hash.digest('hex').slice(0, HashLength);
|
|
74
|
-
filename = [trunk, digest].join('_');
|
|
75
|
-
}
|
|
76
|
-
// Extension
|
|
77
|
-
filename += ext;
|
|
78
|
-
// Content file relative path
|
|
79
|
-
const relPath = path_1.default.join(dir, filename);
|
|
80
|
-
return path_1.default.join(method, protocol, host, relPath);
|
|
81
|
-
}
|
|
82
|
-
exports.requestContentFilePath = requestContentFilePath;
|
|
83
|
-
function parseContentTypeHeader(contentType) {
|
|
84
|
-
const [mime, ...params] = contentType.split(/;/).map((s) => s.trim());
|
|
85
|
-
const charsetParam = params.find((p) => p.startsWith('charset='));
|
|
86
|
-
return {
|
|
87
|
-
mime,
|
|
88
|
-
charset: charsetParam ? charsetParam.slice('charset='.length) : undefined,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
exports.parseContentTypeHeader = parseContentTypeHeader;
|
|
92
|
-
function stringifyContentTypeHeader(mime, charset, original) {
|
|
93
|
-
const params = original ? original.split(/;/).map((s) => s.trim()) : [];
|
|
94
|
-
if (mime)
|
|
95
|
-
params[0] = mime;
|
|
96
|
-
if (charset) {
|
|
97
|
-
const charsetParamIndex = params.findIndex((p) => p.startsWith('charset='));
|
|
98
|
-
if (charsetParamIndex >= 0)
|
|
99
|
-
params.splice(charsetParamIndex, 1, `charset=${charset}`);
|
|
100
|
-
else
|
|
101
|
-
params.splice(1, 0, `charset=${charset}`);
|
|
102
|
-
}
|
|
103
|
-
return params.join('; ');
|
|
104
|
-
}
|
|
105
|
-
exports.stringifyContentTypeHeader = stringifyContentTypeHeader;
|
|
106
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG9EQUEyQjtBQUMzQixnREFBdUI7QUFFdkIsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFBO0FBQ25DLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxDQUFBO0FBQzdCLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQTtBQUNwQixNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUE7QUFDdEQsTUFBTSxpQkFBaUIsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFBO0FBSTFHOzs7OztHQUtHO0FBQ0gsU0FBZ0IsWUFBWSxDQUFDLEdBQWlCO0lBQzVDLE1BQU0sTUFBTSxHQUFHLE9BQU8sR0FBRyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQTtJQUUzRCx3QkFBd0I7SUFDeEIsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLEVBQUUsRUFBRTtRQUN4QixNQUFNLENBQUMsTUFBTSxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUM5RCxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBQy9CLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7S0FDbEI7SUFFRCxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUM7QUFYRCxvQ0FXQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILFNBQWdCLHNCQUFzQixDQUFD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
|
package/build/main/index.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export * from './encoding';
|
|
2
|
-
export * from './formatting';
|
|
3
|
-
export * from './http';
|
|
4
|
-
export * from './inventory';
|
|
5
|
-
export * from './logger';
|
|
6
|
-
export * from './playback';
|
|
7
|
-
export * from './proxy';
|
|
8
|
-
export * from './recording';
|
|
9
|
-
export * from './throttling';
|
package/build/main/index.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./encoding"), exports);
|
|
18
|
-
__exportStar(require("./formatting"), exports);
|
|
19
|
-
__exportStar(require("./http"), exports);
|
|
20
|
-
__exportStar(require("./inventory"), exports);
|
|
21
|
-
__exportStar(require("./logger"), exports);
|
|
22
|
-
__exportStar(require("./playback"), exports);
|
|
23
|
-
__exportStar(require("./proxy"), exports);
|
|
24
|
-
__exportStar(require("./recording"), exports);
|
|
25
|
-
__exportStar(require("./throttling"), exports);
|
|
26
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZDQUEwQjtBQUMxQiwrQ0FBNEI7QUFDNUIseUNBQXNCO0FBQ3RCLDhDQUEyQjtBQUMzQiwyQ0FBd0I7QUFDeEIsNkNBQTBCO0FBQzFCLDBDQUF1QjtBQUN2Qiw4Q0FBMkI7QUFDM0IsK0NBQTRCIn0=
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { ContentEncodingType } from './encoding';
|
|
3
|
-
import { HttpHeaders } from './http';
|
|
4
|
-
export interface Resource {
|
|
5
|
-
method: string;
|
|
6
|
-
url: string;
|
|
7
|
-
ttfbMs: number;
|
|
8
|
-
mbps?: number;
|
|
9
|
-
statusCode?: number;
|
|
10
|
-
errorMessage?: string;
|
|
11
|
-
rawHeaders?: HttpHeaders;
|
|
12
|
-
contentEncoding?: ContentEncodingType;
|
|
13
|
-
contentTypeMime?: string;
|
|
14
|
-
contentTypeCharset?: string;
|
|
15
|
-
contentFilePath?: string;
|
|
16
|
-
minify?: boolean;
|
|
17
|
-
}
|
|
18
|
-
export interface Transaction {
|
|
19
|
-
method: string;
|
|
20
|
-
url: string;
|
|
21
|
-
ttfbMs: number;
|
|
22
|
-
statusCode?: number;
|
|
23
|
-
errorMessage?: string;
|
|
24
|
-
rawHeaders?: HttpHeaders;
|
|
25
|
-
content?: Buffer;
|
|
26
|
-
durationMs?: number;
|
|
27
|
-
}
|
|
28
|
-
export interface Inventory {
|
|
29
|
-
entryUrl?: string;
|
|
30
|
-
resources: Resource[];
|
|
31
|
-
}
|
|
32
|
-
export declare class InventoryRepository {
|
|
33
|
-
dirPath: string;
|
|
34
|
-
constructor(dirPath?: string);
|
|
35
|
-
saveInventory(inventory: Inventory): Promise<void>;
|
|
36
|
-
loadInventory(): Promise<Inventory>;
|
|
37
|
-
saveTransactions(transactions: Transaction[]): Promise<Resource[]>;
|
|
38
|
-
loadTransactions(resources: Resource[]): Promise<Transaction[]>;
|
|
39
|
-
}
|
package/build/main/inventory.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
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.InventoryRepository = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const encoding_1 = require("./encoding");
|
|
11
|
-
const formatting_1 = require("./formatting");
|
|
12
|
-
const http_1 = require("./http");
|
|
13
|
-
const logger_1 = require("./logger");
|
|
14
|
-
const InventoryDir = 'inventory';
|
|
15
|
-
const IndexFile = 'index.json';
|
|
16
|
-
class InventoryRepository {
|
|
17
|
-
constructor(dirPath) {
|
|
18
|
-
this.dirPath = dirPath || path_1.default.join(process.cwd(), InventoryDir);
|
|
19
|
-
}
|
|
20
|
-
async saveInventory(inventory) {
|
|
21
|
-
const inventoryJson = JSON.stringify(inventory, null, 2);
|
|
22
|
-
await promises_1.default.mkdir(this.dirPath, { recursive: true });
|
|
23
|
-
await promises_1.default.writeFile(path_1.default.join(this.dirPath, IndexFile), inventoryJson);
|
|
24
|
-
}
|
|
25
|
-
async loadInventory() {
|
|
26
|
-
const inventoryJson = await promises_1.default.readFile(path_1.default.join(this.dirPath, IndexFile), 'utf8');
|
|
27
|
-
const inventory = JSON.parse(inventoryJson);
|
|
28
|
-
return inventory;
|
|
29
|
-
}
|
|
30
|
-
async saveTransactions(transactions) {
|
|
31
|
-
// To keep transactions order in Promise.all,
|
|
32
|
-
// store transactions and resources in a map.
|
|
33
|
-
const map = new Map();
|
|
34
|
-
await promises_1.default.mkdir(this.dirPath, { recursive: true });
|
|
35
|
-
const saveTransaction = async (transaction) => {
|
|
36
|
-
const resource = {
|
|
37
|
-
method: transaction.method,
|
|
38
|
-
url: transaction.url,
|
|
39
|
-
ttfbMs: transaction.ttfbMs,
|
|
40
|
-
statusCode: transaction.statusCode,
|
|
41
|
-
errorMessage: transaction.errorMessage,
|
|
42
|
-
rawHeaders: transaction.rawHeaders,
|
|
43
|
-
};
|
|
44
|
-
// Headers
|
|
45
|
-
if (transaction.rawHeaders) {
|
|
46
|
-
if (transaction.rawHeaders['content-type']) {
|
|
47
|
-
const { mime, charset } = (0, http_1.parseContentTypeHeader)(transaction.rawHeaders['content-type']);
|
|
48
|
-
if (mime)
|
|
49
|
-
resource.contentTypeMime = mime;
|
|
50
|
-
if (charset)
|
|
51
|
-
resource.contentTypeCharset = charset;
|
|
52
|
-
}
|
|
53
|
-
if (transaction.rawHeaders['content-encoding']) {
|
|
54
|
-
const contentEncoding = transaction.rawHeaders['content-encoding'];
|
|
55
|
-
if (contentEncoding)
|
|
56
|
-
resource.contentEncoding = contentEncoding;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// Mbps
|
|
60
|
-
if (transaction.durationMs && transaction.content) {
|
|
61
|
-
const contentBits = transaction.content.length * 8;
|
|
62
|
-
const seconds = transaction.durationMs / 1000;
|
|
63
|
-
const mega = 1024 * 1024;
|
|
64
|
-
resource.mbps = contentBits / seconds / mega;
|
|
65
|
-
}
|
|
66
|
-
// Content
|
|
67
|
-
if (transaction.content) {
|
|
68
|
-
const steps = {};
|
|
69
|
-
const contentFilePath = (0, http_1.requestContentFilePath)(resource.method, resource.url);
|
|
70
|
-
const fullPath = path_1.default.join(this.dirPath, contentFilePath);
|
|
71
|
-
// Content-Encoding
|
|
72
|
-
steps.decoded = resource.contentEncoding
|
|
73
|
-
? await (0, encoding_1.decompress)(resource.contentEncoding, transaction.content)
|
|
74
|
-
: transaction.content;
|
|
75
|
-
// Try to make editable (utf8, beautify)
|
|
76
|
-
steps.editable = steps.decoded;
|
|
77
|
-
if ((0, formatting_1.isText)(resource.contentTypeMime)) {
|
|
78
|
-
try {
|
|
79
|
-
steps.editable = await (0, formatting_1.convertEditableText)(steps.decoded, resource.contentTypeMime, resource.contentTypeCharset);
|
|
80
|
-
resource.contentTypeCharset = 'utf-8';
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
(0, logger_1.logger)().error({ err, resource }, `Formatting failed ${transaction.url}: ${err.message}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
await promises_1.default.mkdir(path_1.default.dirname(fullPath), { recursive: true });
|
|
87
|
-
await promises_1.default.writeFile(fullPath, steps.editable);
|
|
88
|
-
resource.contentFilePath = contentFilePath;
|
|
89
|
-
}
|
|
90
|
-
map.set(transaction, resource);
|
|
91
|
-
};
|
|
92
|
-
const tryToSaveTransaction = async (transaction) => {
|
|
93
|
-
try {
|
|
94
|
-
await saveTransaction(transaction);
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
(0, logger_1.logger)().error({ err, method: transaction.method, url: transaction.url }, `Failed to save transaction ${transaction.url}: ${err.message}`);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
await Promise.all(transactions.map(tryToSaveTransaction));
|
|
101
|
-
// Restore transactions order after Promise.all
|
|
102
|
-
const resources = transactions.reduce((resources, transaction) => {
|
|
103
|
-
const resource = map.get(transaction);
|
|
104
|
-
if (resource)
|
|
105
|
-
resources.push(resource);
|
|
106
|
-
return resources;
|
|
107
|
-
}, []);
|
|
108
|
-
return resources;
|
|
109
|
-
}
|
|
110
|
-
async loadTransactions(resources) {
|
|
111
|
-
const map = new Map();
|
|
112
|
-
const loadTransaction = async (resource) => {
|
|
113
|
-
const transaction = {
|
|
114
|
-
method: resource.method,
|
|
115
|
-
url: resource.url,
|
|
116
|
-
ttfbMs: resource.ttfbMs,
|
|
117
|
-
statusCode: resource.statusCode,
|
|
118
|
-
errorMessage: resource.errorMessage,
|
|
119
|
-
rawHeaders: Object.assign({}, (resource.rawHeaders || {})),
|
|
120
|
-
};
|
|
121
|
-
// content
|
|
122
|
-
if (resource.contentFilePath) {
|
|
123
|
-
const fullPath = path_1.default.join(this.dirPath, resource.contentFilePath);
|
|
124
|
-
if (fs_1.default.existsSync(fullPath)) {
|
|
125
|
-
const content = await promises_1.default.readFile(fullPath);
|
|
126
|
-
// encoding
|
|
127
|
-
if (resource.contentEncoding) {
|
|
128
|
-
transaction.content = await (0, encoding_1.compress)(resource.contentEncoding, content);
|
|
129
|
-
transaction.rawHeaders['content-encoding'] = resource.contentEncoding;
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
transaction.content = content;
|
|
133
|
-
delete transaction.rawHeaders['content-encoding'];
|
|
134
|
-
}
|
|
135
|
-
// length
|
|
136
|
-
transaction.rawHeaders['content-length'] = `${transaction.content.length}`;
|
|
137
|
-
// duration
|
|
138
|
-
const bytesPerMs = resource.mbps ? (resource.mbps * 1024 * 1024) / 8 / 1000 : 0;
|
|
139
|
-
transaction.durationMs = bytesPerMs ? content.length / bytesPerMs : 0;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
transaction.rawHeaders['content-length'] = '0';
|
|
144
|
-
transaction.durationMs = 0;
|
|
145
|
-
}
|
|
146
|
-
// Content-Type
|
|
147
|
-
if (resource.contentTypeMime) {
|
|
148
|
-
transaction.rawHeaders['content-type'] = (0, http_1.stringifyContentTypeHeader)(resource.contentTypeMime, resource.contentTypeCharset);
|
|
149
|
-
}
|
|
150
|
-
map.set(resource, transaction);
|
|
151
|
-
};
|
|
152
|
-
const tryToLoadTransaction = async (resource) => {
|
|
153
|
-
try {
|
|
154
|
-
await loadTransaction(resource);
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
(0, logger_1.logger)().error({ err, resource }, `Loading transaction failed ${resource.url}: ${err.message}`);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
await Promise.all(resources.map(tryToLoadTransaction));
|
|
161
|
-
const transactions = resources.reduce((transactions, resource) => {
|
|
162
|
-
const transaction = map.get(resource);
|
|
163
|
-
if (transaction)
|
|
164
|
-
transactions.push(transaction);
|
|
165
|
-
return transactions;
|
|
166
|
-
}, []);
|
|
167
|
-
return transactions;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
exports.InventoryRepository = InventoryRepository;
|
|
171
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZW50b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludmVudG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw0Q0FBbUI7QUFDbkIsMkRBQTZCO0FBQzdCLGdEQUF1QjtBQUV2Qix5Q0FBc0U7QUFDdEUsNkNBQTBEO0FBQzFELGlDQUFnSDtBQUNoSCxxQ0FBaUM7QUFFakMsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFBO0FBQ2hDLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQTtBQWlDOUIsTUFBYSxtQkFBbUI7SUFHOUIsWUFBWSxPQUFnQjtRQUMxQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sSUFBSSxjQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQTtJQUNsRSxDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWEsQ0FBQyxTQUFvQjtRQUN0QyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUE7UUFDeEQsTUFBTSxrQkFBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7UUFDbEQsTUFBTSxrQkFBRyxDQUFDLFNBQVMsQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUE7SUFDeEUsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhO1FBQ2pCLE1BQU0sYUFBYSxHQUFHLE1BQU0sa0JBQUcsQ0FBQyxRQUFRLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3BGLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFB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
|
package/build/main/logger.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare const singleton: import("pino").Logger<{
|
|
2
|
-
transport: {
|
|
3
|
-
target: string;
|
|
4
|
-
options: {
|
|
5
|
-
levelFirst: boolean;
|
|
6
|
-
hideObject: boolean;
|
|
7
|
-
};
|
|
8
|
-
};
|
|
9
|
-
level: string;
|
|
10
|
-
}>;
|
|
11
|
-
export declare function logger(): import("pino").Logger<{
|
|
12
|
-
transport: {
|
|
13
|
-
target: string;
|
|
14
|
-
options: {
|
|
15
|
-
levelFirst: boolean;
|
|
16
|
-
hideObject: boolean;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
level: string;
|
|
20
|
-
}>;
|
package/build/main/logger.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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.logger = exports.singleton = void 0;
|
|
7
|
-
const pino_1 = __importDefault(require("pino"));
|
|
8
|
-
exports.singleton = (0, pino_1.default)({
|
|
9
|
-
transport: {
|
|
10
|
-
target: 'pino-pretty',
|
|
11
|
-
options: {
|
|
12
|
-
levelFirst: true,
|
|
13
|
-
hideObject: Boolean(!process.env.LOG_OBJECTS),
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
level: process.env.LOG_LEVEL || 'info',
|
|
17
|
-
});
|
|
18
|
-
function logger() {
|
|
19
|
-
return exports.singleton;
|
|
20
|
-
}
|
|
21
|
-
exports.logger = logger;
|
|
22
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxnREFBdUI7QUFFVixRQUFBLFNBQVMsR0FBRyxJQUFBLGNBQUksRUFBQztJQUM1QixTQUFTLEVBQUU7UUFDVCxNQUFNLEVBQUUsYUFBYTtRQUNyQixPQUFPLEVBQUU7WUFDUCxVQUFVLEVBQUUsSUFBSTtZQUNoQixVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUM7U0FDOUM7S0FDRjtJQUNELEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxNQUFNO0NBQ3ZDLENBQUMsQ0FBQTtBQUVGLFNBQWdCLE1BQU07SUFDcEIsT0FBTyxpQkFBUyxDQUFBO0FBQ2xCLENBQUM7QUFGRCx3QkFFQyJ9
|
|
File without changes
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// import Fsp from 'fs/promises'
|
|
2
|
-
// import Path from 'path'
|
|
3
|
-
// import { Inventory, PlaybackResource } from '../common'
|
|
4
|
-
// import { compress } from '../encoding'
|
|
5
|
-
// type ResourceIndex = Map<string, Map<string, PlaybackResource>>
|
|
6
|
-
// const ContentChunkSize = 16 * 1024
|
|
7
|
-
// export class PlaybackInventory {
|
|
8
|
-
// playbackResources: PlaybackResource[] = []
|
|
9
|
-
// playbackResourcesIndex: ResourceIndex = new Map()
|
|
10
|
-
// async load(dirPath: string) {
|
|
11
|
-
// const inventoryPath = Path.join(dirPath, 'inventory.json')
|
|
12
|
-
// const inventoryJson = await Fsp.readFile(inventoryPath, 'utf8')
|
|
13
|
-
// const inventory: Inventory = JSON.parse(inventoryJson)
|
|
14
|
-
// for (const resource of inventory.resources) {
|
|
15
|
-
// try {
|
|
16
|
-
// const playbackResource: PlaybackResource = {
|
|
17
|
-
// method: resource.method,
|
|
18
|
-
// url: resource.url,
|
|
19
|
-
// ttfbMs: resource.ttfbMs,
|
|
20
|
-
// statusCode: resource.statusCode,
|
|
21
|
-
// contentTypeMime: resource.contentTypeMime,
|
|
22
|
-
// contentEncoding: resource.contentEncoding,
|
|
23
|
-
// headers: resource.headers,
|
|
24
|
-
// contentChunks: [],
|
|
25
|
-
// contentLength: 0,
|
|
26
|
-
// durationMs: 0,
|
|
27
|
-
// }
|
|
28
|
-
// const content = await Fsp.readFile(Path.join(dirPath, resource.contentFilePath))
|
|
29
|
-
// const encoded = await compress(resource.contentEncoding, content)
|
|
30
|
-
// for (let i = 0; i < encoded.length; i += ContentChunkSize) {
|
|
31
|
-
// playbackResource.contentChunks.push(encoded.subarray(i, i + ContentChunkSize))
|
|
32
|
-
// }
|
|
33
|
-
// playbackResource.contentLength = encoded.length
|
|
34
|
-
// this.playbackResources.push(playbackResource)
|
|
35
|
-
// const urlIndex = (this.playbackResourcesIndex[resource.method] ??= new Map())
|
|
36
|
-
// urlIndex[resource.url] = playbackResource
|
|
37
|
-
// } catch (err) {
|
|
38
|
-
// // TODO error handling
|
|
39
|
-
// console.error(err)
|
|
40
|
-
// }
|
|
41
|
-
// }
|
|
42
|
-
// }
|
|
43
|
-
// find(method: string, url: string) {
|
|
44
|
-
// return this.playbackResourcesIndex.get(method)?.get(url)
|
|
45
|
-
// }
|
|
46
|
-
// }
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZW50b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BsYXliYWNrL2ludmVudG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxnQ0FBZ0M7QUFDaEMsMEJBQTBCO0FBRTFCLDBEQUEwRDtBQUMxRCx5Q0FBeUM7QUFFekMsa0VBQWtFO0FBQ2xFLHFDQUFxQztBQUVyQyxtQ0FBbUM7QUFDbkMsK0NBQStDO0FBRS9DLHNEQUFzRDtBQUV0RCxrQ0FBa0M7QUFDbEMsaUVBQWlFO0FBQ2pFLHNFQUFzRTtBQUN0RSw2REFBNkQ7QUFFN0Qsb0RBQW9EO0FBQ3BELGNBQWM7QUFDZCx1REFBdUQ7QUFDdkQscUNBQXFDO0FBQ3JDLCtCQUErQjtBQUMvQixxQ0FBcUM7QUFDckMsNkNBQTZDO0FBQzdDLHVEQUF1RDtBQUN2RCx1REFBdUQ7QUFDdkQsdUNBQXVDO0FBQ3ZDLCtCQUErQjtBQUMvQiw4QkFBOEI7QUFDOUIsMkJBQTJCO0FBQzNCLFlBQVk7QUFFWiwyRkFBMkY7QUFDM0YsNEVBQTRFO0FBQzVFLHVFQUF1RTtBQUN2RSwyRkFBMkY7QUFDM0YsWUFBWTtBQUNaLDBEQUEwRDtBQUUxRCx3REFBd0Q7QUFDeEQsd0ZBQXdGO0FBQ3hGLG9EQUFvRDtBQUNwRCx3QkFBd0I7QUFDeEIsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUM3QixVQUFVO0FBQ1YsUUFBUTtBQUNSLE1BQU07QUFFTix3Q0FBd0M7QUFDeEMsK0RBQStEO0FBQy9ELE1BQU07QUFDTixJQUFJIn0=
|
package/build/main/playback.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { HttpHeaders } from './http';
|
|
3
|
-
import { Inventory } from './inventory';
|
|
4
|
-
import { Proxy, WithProxyOptions } from './proxy';
|
|
5
|
-
export interface PlaybackTransaction {
|
|
6
|
-
method: string;
|
|
7
|
-
url: string;
|
|
8
|
-
ttfbMs: number;
|
|
9
|
-
statusCode?: number;
|
|
10
|
-
err?: Error;
|
|
11
|
-
rawHeaders?: HttpHeaders;
|
|
12
|
-
contentChunks: Buffer[];
|
|
13
|
-
contentLength: number;
|
|
14
|
-
durationMs: number;
|
|
15
|
-
}
|
|
16
|
-
export declare class PlaybackProxy extends Proxy {
|
|
17
|
-
transactionsMap: Map<string, Map<string, PlaybackTransaction>>;
|
|
18
|
-
loadTransactions(inventory: Inventory): Promise<void>;
|
|
19
|
-
setup(): Promise<void>;
|
|
20
|
-
shutdown(): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
export declare function withPlaybackProxy(fn: (proxy: PlaybackProxy) => Promise<void>, options?: WithProxyOptions): Promise<void | PlaybackProxy>;
|
package/build/main/playback.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withPlaybackProxy = exports.PlaybackProxy = void 0;
|
|
4
|
-
const logger_1 = require("./logger");
|
|
5
|
-
const proxy_1 = require("./proxy");
|
|
6
|
-
const ChunkSize = 1024 * 16;
|
|
7
|
-
class PlaybackProxy extends proxy_1.Proxy {
|
|
8
|
-
constructor() {
|
|
9
|
-
super(...arguments);
|
|
10
|
-
this.transactionsMap = new Map();
|
|
11
|
-
}
|
|
12
|
-
async loadTransactions(inventory) {
|
|
13
|
-
const transactions = await this.inventoryRepository.loadTransactions(inventory.resources);
|
|
14
|
-
for (const transaction of transactions) {
|
|
15
|
-
const playbackTransaction = {
|
|
16
|
-
method: transaction.method,
|
|
17
|
-
url: transaction.url,
|
|
18
|
-
ttfbMs: transaction.ttfbMs,
|
|
19
|
-
statusCode: transaction.statusCode,
|
|
20
|
-
err: transaction.errorMessage ? new Error(transaction.errorMessage) : undefined,
|
|
21
|
-
rawHeaders: transaction.rawHeaders || {},
|
|
22
|
-
contentChunks: [],
|
|
23
|
-
contentLength: 0,
|
|
24
|
-
durationMs: transaction.durationMs || 0,
|
|
25
|
-
};
|
|
26
|
-
if (transaction.content) {
|
|
27
|
-
const maxChunks = 10;
|
|
28
|
-
const minInterval = 10;
|
|
29
|
-
const chunks = Math.min(maxChunks, Math.floor(playbackTransaction.durationMs / minInterval));
|
|
30
|
-
playbackTransaction.contentChunks = [];
|
|
31
|
-
const chunkSize = Math.max(ChunkSize, Math.ceil(transaction.content.length / chunks));
|
|
32
|
-
for (let i = 0; i <= transaction.content.length; i += chunkSize) {
|
|
33
|
-
playbackTransaction.contentChunks.push(transaction.content.subarray(i, i + chunkSize));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (!this.transactionsMap.has(transaction.method)) {
|
|
37
|
-
this.transactionsMap.set(transaction.method, new Map());
|
|
38
|
-
}
|
|
39
|
-
this.transactionsMap.get(transaction.method).set(transaction.url, playbackTransaction);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async setup() {
|
|
43
|
-
const inventory = await this.inventoryRepository.loadInventory();
|
|
44
|
-
await this.loadTransactions(inventory);
|
|
45
|
-
if (inventory.entryUrl)
|
|
46
|
-
this.entryUrl = inventory.entryUrl;
|
|
47
|
-
let requestNumber = 1;
|
|
48
|
-
this.proxy.onRequest((ctx, onRequestComplete) => {
|
|
49
|
-
var _a;
|
|
50
|
-
const number = requestNumber++;
|
|
51
|
-
const identifier = proxy_1.Proxy.contextRequest(ctx);
|
|
52
|
-
const transaction = (_a = this.transactionsMap.get(identifier.method)) === null || _a === void 0 ? void 0 : _a.get(identifier.url);
|
|
53
|
-
if (!transaction) {
|
|
54
|
-
(0, logger_1.logger)().warn({ number, identifier }, `Request #${number} ${identifier.url} (${identifier.method}) not found in inventory`);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const contentStream = this.createThrottlingTransform() || ctx.proxyToClientResponse;
|
|
58
|
-
if (contentStream !== ctx.proxyToClientResponse) {
|
|
59
|
-
contentStream.pipe(ctx.proxyToClientResponse);
|
|
60
|
-
}
|
|
61
|
-
(0, logger_1.logger)().debug({ number, identifier }, `Request #${number} ${transaction.url} started`);
|
|
62
|
-
ctx.onError((_, err) => {
|
|
63
|
-
(0, logger_1.logger)().warn({ number, identifier, err }, `Request #${number} ${transaction.url} failed: ${err.message}`);
|
|
64
|
-
});
|
|
65
|
-
setTimeout(() => {
|
|
66
|
-
// Error
|
|
67
|
-
if (transaction.err) {
|
|
68
|
-
return onRequestComplete(transaction.err);
|
|
69
|
-
}
|
|
70
|
-
// Status code
|
|
71
|
-
ctx.proxyToClientResponse.statusCode = transaction.statusCode || 500;
|
|
72
|
-
// Headers
|
|
73
|
-
if (transaction.rawHeaders) {
|
|
74
|
-
for (const [key, value] of Object.entries(transaction.rawHeaders)) {
|
|
75
|
-
if (ctx.proxyToClientResponse.headersSent)
|
|
76
|
-
break;
|
|
77
|
-
ctx.proxyToClientResponse.setHeader(key, value);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Empty content body
|
|
81
|
-
if (!transaction.contentChunks || transaction.contentChunks.length === 0) {
|
|
82
|
-
contentStream.end();
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
// Content body
|
|
86
|
-
const chunks = [...transaction.contentChunks];
|
|
87
|
-
const intervalMs = transaction.durationMs / transaction.contentChunks.length;
|
|
88
|
-
const interval = setInterval(() => {
|
|
89
|
-
const chunk = chunks.shift();
|
|
90
|
-
if (chunk) {
|
|
91
|
-
contentStream.write(chunk);
|
|
92
|
-
}
|
|
93
|
-
if (chunks.length === 0) {
|
|
94
|
-
clearInterval(interval);
|
|
95
|
-
contentStream.end();
|
|
96
|
-
(0, logger_1.logger)().debug({ number, identifier }, `Request #${number} ${transaction.url} completed`);
|
|
97
|
-
}
|
|
98
|
-
}, intervalMs);
|
|
99
|
-
}, transaction.ttfbMs);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
async shutdown() {
|
|
103
|
-
// nothing to do
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
exports.PlaybackProxy = PlaybackProxy;
|
|
107
|
-
async function withPlaybackProxy(fn, options) {
|
|
108
|
-
return await (0, proxy_1.withProxy)(PlaybackProxy, fn, options || {});
|
|
109
|
-
}
|
|
110
|
-
exports.withPlaybackProxy = withPlaybackProxy;
|
|
111
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxheWJhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGxheWJhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEscUNBQWlDO0FBQ2pDLG1DQUE0RDtBQUU1RCxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0FBYzNCLE1BQWEsYUFBYyxTQUFRLGFBQUs7SUFBeEM7O1FBQ0Usb0JBQWUsR0FBa0QsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQWdINUUsQ0FBQztJQTlHQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsU0FBb0I7UUFDekMsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBRXpGLEtBQUssTUFBTSxXQUFXLElBQUksWUFBWSxFQUFFO1lBQ3RDLE1BQU0sbUJBQW1CLEdBQXdCO2dCQUMvQyxNQUFNLEVBQUUsV0FBVyxDQUFDLE1BQU07Z0JBQzFCLEdBQUcsRUFBRSxXQUFXLENBQUMsR0FBRztnQkFDcEIsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNO2dCQUMxQixVQUFVLEVBQUUsV0FBVyxDQUFDLFVBQVU7Z0JBQ2xDLEdBQUcsRUFBRSxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7Z0JBQy9FLFVBQVUsRUFBRSxXQUFXLENBQUMsVUFBVSxJQUFJLEVBQUU7Z0JBQ3hDLGFBQWEsRUFBRSxFQUFFO2dCQUNqQixhQUFhLEVBQUUsQ0FBQztnQkFDaEIsVUFBVSxFQUFFLFdBQVcsQ0FBQyxVQUFVLElBQUksQ0FBQzthQUN4QyxDQUFBO1lBRUQsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFO2dCQUN2QixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUE7Z0JBQ3BCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FB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
|