@qodalis/cli-speed-test 0.0.4 → 2.0.0-beta.1
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/package.json +14 -30
- package/public-api.d.mts +33 -0
- package/public-api.d.ts +33 -2
- package/public-api.js +283 -0
- package/public-api.js.map +1 -0
- package/public-api.mjs +280 -0
- package/public-api.mjs.map +1 -0
- package/umd/cli-entrypoint.global.js +2954 -0
- package/README.md +0 -17
- package/esm2022/lib/cli-speed-test.module.mjs +0 -19
- package/esm2022/lib/processors/cli-speed-test-command-processor.mjs +0 -169
- package/esm2022/lib/version.mjs +0 -3
- package/esm2022/public-api.mjs +0 -6
- package/esm2022/qodalis-cli-speed-test.mjs +0 -5
- package/fesm2022/qodalis-cli-speed-test.mjs +0 -200
- package/fesm2022/qodalis-cli-speed-test.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/lib/cli-speed-test.module.d.ts +0 -6
- package/lib/processors/cli-speed-test-command-processor.d.ts +0 -23
- package/lib/version.d.ts +0 -1
- package/umd/index.js +0 -182
package/README.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Cli extension
|
|
2
|
-
|
|
3
|
-
The `@qodalis/cli-speed-test` package is a CLI extension designed to provide utilities for measuring network speed
|
|
4
|
-
|
|
5
|
-
# Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
packages add @qodalis/cli-speed-test
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
# Usage
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
speed-test run
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This command downloads and registers the extension for use within the CLI environment.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { NgModule } from '@angular/core';
|
|
2
|
-
import { resolveCommandProcessorProvider } from '@qodalis/angular-cli';
|
|
3
|
-
import { CliSpeedTestCommandProcessor } from './processors/cli-speed-test-command-processor';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export class CliSpeedTestModule {
|
|
6
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
7
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule }); }
|
|
8
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, providers: [resolveCommandProcessorProvider(CliSpeedTestCommandProcessor)] }); }
|
|
9
|
-
}
|
|
10
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, decorators: [{
|
|
11
|
-
type: NgModule,
|
|
12
|
-
args: [{
|
|
13
|
-
declarations: [],
|
|
14
|
-
imports: [],
|
|
15
|
-
exports: [],
|
|
16
|
-
providers: [resolveCommandProcessorProvider(CliSpeedTestCommandProcessor)],
|
|
17
|
-
}]
|
|
18
|
-
}] });
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLXNwZWVkLXRlc3QubW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc3BlZWQtdGVzdC9zcmMvbGliL2NsaS1zcGVlZC10ZXN0Lm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLCtDQUErQyxDQUFDOztBQVE3RixNQUFNLE9BQU8sa0JBQWtCOytHQUFsQixrQkFBa0I7Z0hBQWxCLGtCQUFrQjtnSEFBbEIsa0JBQWtCLGFBRmhCLENBQUMsK0JBQStCLENBQUMsNEJBQTRCLENBQUMsQ0FBQzs7NEZBRWpFLGtCQUFrQjtrQkFOOUIsUUFBUTttQkFBQztvQkFDTixZQUFZLEVBQUUsRUFBRTtvQkFDaEIsT0FBTyxFQUFFLEVBQUU7b0JBQ1gsT0FBTyxFQUFFLEVBQUU7b0JBQ1gsU0FBUyxFQUFFLENBQUMsK0JBQStCLENBQUMsNEJBQTRCLENBQUMsQ0FBQztpQkFDN0UiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgcmVzb2x2ZUNvbW1hbmRQcm9jZXNzb3JQcm92aWRlciB9IGZyb20gJ0Bxb2RhbGlzL2FuZ3VsYXItY2xpJztcbmltcG9ydCB7IENsaVNwZWVkVGVzdENvbW1hbmRQcm9jZXNzb3IgfSBmcm9tICcuL3Byb2Nlc3NvcnMvY2xpLXNwZWVkLXRlc3QtY29tbWFuZC1wcm9jZXNzb3InO1xuXG5ATmdNb2R1bGUoe1xuICAgIGRlY2xhcmF0aW9uczogW10sXG4gICAgaW1wb3J0czogW10sXG4gICAgZXhwb3J0czogW10sXG4gICAgcHJvdmlkZXJzOiBbcmVzb2x2ZUNvbW1hbmRQcm9jZXNzb3JQcm92aWRlcihDbGlTcGVlZFRlc3RDb21tYW5kUHJvY2Vzc29yKV0sXG59KVxuZXhwb3J0IGNsYXNzIENsaVNwZWVkVGVzdE1vZHVsZSB7fVxuIl19
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { CliForegroundColor, DefaultLibraryAuthor, } from '@qodalis/cli-core';
|
|
2
|
-
import axios from 'axios';
|
|
3
|
-
import { LIBRARY_VERSION } from '../version';
|
|
4
|
-
export class CliSpeedTestCommandProcessor {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.command = 'speed-test';
|
|
7
|
-
this.description = 'Run an internet speed test';
|
|
8
|
-
this.author = DefaultLibraryAuthor;
|
|
9
|
-
this.processors = [];
|
|
10
|
-
this.version = LIBRARY_VERSION;
|
|
11
|
-
this.metadata = {
|
|
12
|
-
icon: '🚀',
|
|
13
|
-
requiredCoreVersion: '0.0.16',
|
|
14
|
-
requiredCliVersion: '1.0.37',
|
|
15
|
-
};
|
|
16
|
-
this.processors = [
|
|
17
|
-
{
|
|
18
|
-
command: 'run',
|
|
19
|
-
description: 'Run the internet speed test',
|
|
20
|
-
parameters: [
|
|
21
|
-
{
|
|
22
|
-
name: 'download-url',
|
|
23
|
-
description: 'URL to download the file',
|
|
24
|
-
type: 'string',
|
|
25
|
-
required: false,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'upload-url',
|
|
29
|
-
description: 'URL to upload the file',
|
|
30
|
-
type: 'string',
|
|
31
|
-
required: false,
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
processCommand: async (command, context) => {
|
|
35
|
-
const source = axios.CancelToken.source();
|
|
36
|
-
const subscription = context.onAbort.subscribe(() => {
|
|
37
|
-
source.cancel('Speed test aborted by user');
|
|
38
|
-
subscription.unsubscribe();
|
|
39
|
-
});
|
|
40
|
-
new Promise(async (resolve, reject) => {
|
|
41
|
-
context.writer.writeInfo('Starting live speed test...');
|
|
42
|
-
const downloadUrl = command.args['download-url'] ||
|
|
43
|
-
'https://proxy.qodalis.com/proxy/https/nbg1-speed.hetzner.com/100MB.bin';
|
|
44
|
-
const uploadUrl = command.args['upload-url'] ||
|
|
45
|
-
'https://httpbin.org/post';
|
|
46
|
-
try {
|
|
47
|
-
await this.runDownloadSpeedTest(downloadUrl, context, source.token);
|
|
48
|
-
await this.runUploadSpeedTest(uploadUrl, context, source);
|
|
49
|
-
context.writer.writeInfo('Speed test completed');
|
|
50
|
-
resolve();
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
context.writer.writeError(`Speed test failed: ${error?.toString()}`);
|
|
54
|
-
reject(error);
|
|
55
|
-
}
|
|
56
|
-
subscription.unsubscribe();
|
|
57
|
-
context.showPrompt();
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
|
-
async processCommand(command, context) {
|
|
64
|
-
await context.executor.showHelp(command, context);
|
|
65
|
-
}
|
|
66
|
-
writeDescription(context) {
|
|
67
|
-
const { writer } = context;
|
|
68
|
-
writer.writeln(this.description);
|
|
69
|
-
writer.writeln();
|
|
70
|
-
writer.writeln('📋 Usage:');
|
|
71
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run', CliForegroundColor.Cyan)} Run download & upload test`);
|
|
72
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run --download-url=<url>', CliForegroundColor.Cyan)} Custom download URL`);
|
|
73
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run --upload-url=<url>', CliForegroundColor.Cyan)} Custom upload URL`);
|
|
74
|
-
writer.writeln();
|
|
75
|
-
writer.writeln(`💡 Press ${writer.wrapInColor('Ctrl+C', CliForegroundColor.Yellow)} to abort the test`);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Run the download speed test with live updates.
|
|
79
|
-
* @param context CLI execution context.
|
|
80
|
-
*/
|
|
81
|
-
async runDownloadSpeedTest(url, context, cancelToken) {
|
|
82
|
-
const startTime = performance.now();
|
|
83
|
-
let previousTime = startTime;
|
|
84
|
-
let previousLoaded = 0;
|
|
85
|
-
await axios.get(url, {
|
|
86
|
-
responseType: 'arraybuffer',
|
|
87
|
-
cancelToken: cancelToken,
|
|
88
|
-
headers: {
|
|
89
|
-
Origin: null,
|
|
90
|
-
},
|
|
91
|
-
onDownloadProgress: (progressEvent) => {
|
|
92
|
-
if (!!cancelToken.reason) {
|
|
93
|
-
throw new Error('Speed test aborted by user');
|
|
94
|
-
}
|
|
95
|
-
const currentTime = performance.now();
|
|
96
|
-
const elapsedTime = (currentTime - previousTime) / 1000;
|
|
97
|
-
const bytesSinceLastUpdate = progressEvent.loaded - previousLoaded;
|
|
98
|
-
if (elapsedTime > 0) {
|
|
99
|
-
const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second
|
|
100
|
-
const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps
|
|
101
|
-
context.writer.writeln(`Download Speed: ${speedInMbps.toFixed(2)} Mbps (Progress: ${((progressEvent.loaded / progressEvent.total) *
|
|
102
|
-
100).toFixed(2)}%)`);
|
|
103
|
-
}
|
|
104
|
-
// Update previous values
|
|
105
|
-
previousTime = currentTime;
|
|
106
|
-
previousLoaded = progressEvent.loaded;
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
const endTime = performance.now();
|
|
110
|
-
const totalTime = (endTime - startTime) / 1000;
|
|
111
|
-
context.writer.writeSuccess(`Download test completed in ${totalTime.toFixed(2)} seconds`);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Run the upload speed test with live updates.
|
|
115
|
-
* @param context CLI execution context.
|
|
116
|
-
*/
|
|
117
|
-
async runUploadSpeedTest(url, context, source) {
|
|
118
|
-
const testData = new Uint8Array(20 * 1024 * 1024); // 20 MB of random data
|
|
119
|
-
testData.fill(0);
|
|
120
|
-
const startTime = performance.now();
|
|
121
|
-
let previousTime = startTime;
|
|
122
|
-
let previousUploaded = 0;
|
|
123
|
-
let uploadComplete = false;
|
|
124
|
-
try {
|
|
125
|
-
await axios.post(url, testData, {
|
|
126
|
-
headers: { 'Content-Type': 'application/octet-stream' },
|
|
127
|
-
cancelToken: source.token,
|
|
128
|
-
responseType: 'stream',
|
|
129
|
-
onUploadProgress: (progressEvent) => {
|
|
130
|
-
if (!!source.token.reason) {
|
|
131
|
-
throw new Error('Speed test aborted by user');
|
|
132
|
-
}
|
|
133
|
-
const currentTime = performance.now();
|
|
134
|
-
const elapsedTime = (currentTime - previousTime) / 1000; // Time since last update
|
|
135
|
-
const bytesSinceLastUpdate = progressEvent.loaded - previousUploaded;
|
|
136
|
-
if (elapsedTime > 0) {
|
|
137
|
-
const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second
|
|
138
|
-
const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps
|
|
139
|
-
context.writer.writeln(`Upload Speed: ${speedInMbps.toFixed(2)} Mbps (Progress: ${((progressEvent.loaded / progressEvent.total) *
|
|
140
|
-
100).toFixed(2)}%)`);
|
|
141
|
-
}
|
|
142
|
-
// Update previous values
|
|
143
|
-
previousTime = currentTime;
|
|
144
|
-
previousUploaded = progressEvent.loaded;
|
|
145
|
-
if (progressEvent.loaded >= progressEvent.total) {
|
|
146
|
-
uploadComplete = true;
|
|
147
|
-
source.cancel('Upload test completed');
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
catch (e) {
|
|
153
|
-
if (axios.isCancel(e)) {
|
|
154
|
-
if (!uploadComplete) {
|
|
155
|
-
context.writer.writeError('Upload test aborted by user');
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
const endTime = performance.now();
|
|
159
|
-
const totalTime = (endTime - startTime) / 1000;
|
|
160
|
-
context.writer.writeSuccess(`Upload test completed in ${totalTime.toFixed(2)} seconds`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
throw e;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLXNwZWVkLXRlc3QtY29tbWFuZC1wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVlZC10ZXN0L3NyYy9saWIvcHJvY2Vzc29ycy9jbGktc3BlZWQtdGVzdC1jb21tYW5kLXByb2Nlc3Nvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0gsa0JBQWtCLEVBRWxCLG9CQUFvQixHQUN2QixNQUFNLG1CQUFtQixDQUFDO0FBTTNCLE9BQU8sS0FBeUMsTUFBTSxPQUFPLENBQUM7QUFDOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUU3QyxNQUFNLE9BQU8sNEJBQTRCO0lBaUJyQztRQWhCQSxZQUFPLEdBQUcsWUFBWSxDQUFDO1FBRXZCLGdCQUFXLEdBQUcsNEJBQTRCLENBQUM7UUFFM0MsV0FBTSxHQUFHLG9CQUFvQixDQUFDO1FBRTlCLGVBQVUsR0FBd0MsRUFBRSxDQUFDO1FBRXJELFlBQU8sR0FBRyxlQUFlLENBQUM7UUFFMUIsYUFBUSxHQUFzQztZQUMxQyxJQUFJLEVBQUUsSUFBSTtZQUNWLG1CQUFtQixFQUFFLFFBQVE7WUFDN0Isa0JBQWtCLEVBQUUsUUFBUTtTQUMvQixDQUFDO1FBR0UsSUFBSSxDQUFDLFVBQVUsR0FBRztZQUNkO2dCQUNJLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFdBQVcsRUFBRSw2QkFBNkI7Z0JBQzFDLFVBQVUsRUFBRTtvQkFDUjt3QkFDSSxJQUFJLEVBQUUsY0FBYzt3QkFDcEIsV0FBVyxFQUFFLDBCQUEwQjt3QkFDdkMsSUFBSSxFQUFFLFFBQVE7d0JBQ2QsUUFBUSxFQUFFLEtBQUs7cUJBQ2xCO29CQUNEO3dCQUNJLElBQUksRUFBRSxZQUFZO3dCQUNsQixXQUFXLEVBQUUsd0JBQXdCO3dCQUNyQyxJQUFJLEVBQUUsUUFBUTt3QkFDZCxRQUFRLEVBQUUsS0FBSztxQkFDbEI7aUJBQ0o7Z0JBQ0QsY0FBYyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUU7b0JBQ3ZDLE1BQU0sTUFBTSxHQUNSLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBRS9CLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTt3QkFDaEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO3dCQUU1QyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQy9CLENBQUMsQ0FBQyxDQUFDO29CQUVILElBQUksT0FBTyxDQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7d0JBQ3hDLE9BQU8sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLDZCQUE2QixDQUFDLENBQUM7d0JBRXhELE1BQU0sV0FBVyxHQUNiLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDOzRCQUM1Qix3RUFBd0UsQ0FBQzt3QkFFN0UsTUFBTSxTQUFTLEdBQ1gsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7NEJBQzFCLDBCQUEwQixDQUFDO3dCQUUvQixJQUFJOzRCQUNBLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUMzQixXQUFXLEVBQ1gsT0FBTyxFQUNQLE1BQU0sQ0FBQyxLQUFLLENBQ2YsQ0FBQzs0QkFFRixNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FDekIsU0FBUyxFQUNULE9BQU8sRUFDUCxNQUFNLENBQ1QsQ0FBQzs0QkFFRixPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDOzRCQUVqRCxPQUFPLEVBQUUsQ0FBQzt5QkFDYjt3QkFBQyxPQUFPLEtBQUssRUFBRTs0QkFDWixPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FDckIsc0JBQXNCLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUM1QyxDQUFDOzRCQUVGLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzt5QkFDakI7d0JBRUQsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO3dCQUUzQixPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7b0JBQ3pCLENBQUMsQ0FBQyxDQUFDO2dCQUNQLENBQUM7YUFDSjtTQUNKLENBQUM7SUFDTixDQUFDO0lBRUQsS0FBSyxDQUFDLGNBQWMsQ0FDaEIsT0FBMEIsRUFDMUIsT0FBNkI7UUFFN0IsTUFBTSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVELGdCQUFnQixDQUFDLE9BQTZCO1FBQzFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDM0IsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDakMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLE1BQU0sQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLHNEQUFzRCxDQUFDLENBQUM7UUFDekksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLE1BQU0sQ0FBQyxXQUFXLENBQUMscUNBQXFDLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDbEksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLE1BQU0sQ0FBQyxXQUFXLENBQUMsbUNBQW1DLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDaEksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM1RyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssS0FBSyxDQUFDLG9CQUFvQixDQUM5QixHQUFXLEVBQ1gsT0FBNkIsRUFDN0IsV0FBd0I7UUFFeEIsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3BDLElBQUksWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUM3QixJQUFJLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFFdkIsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtZQUNqQixZQUFZLEVBQUUsYUFBYTtZQUMzQixXQUFXLEVBQUUsV0FBVztZQUN4QixPQUFPLEVBQUU7Z0JBQ0wsTUFBTSxFQUFFLElBQUk7YUFDZjtZQUNELGtCQUFrQixFQUFFLENBQUMsYUFBYSxFQUFFLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUU7b0JBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQztpQkFDakQ7Z0JBRUQsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUN0QyxNQUFNLFdBQVcsR0FBRyxDQUFDLFdBQVcsR0FBRyxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUM7Z0JBQ3hELE1BQU0sb0JBQW9CLEdBQ3RCLGFBQWEsQ0FBQyxNQUFNLEdBQUcsY0FBYyxDQUFDO2dCQUUxQyxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUU7b0JBQ2pCLE1BQU0sVUFBVSxHQUFHLG9CQUFvQixHQUFHLFdBQVcsQ0FBQyxDQUFDLG1CQUFtQjtvQkFDMUUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxrQkFBa0I7b0JBQ3hFLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUNsQixtQkFBbUIsV0FBVyxDQUFDLE9BQU8sQ0FDbEMsQ0FBQyxDQUNKLG9CQUFvQixDQUNqQixDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLEtBQU0sQ0FBQzt3QkFDN0MsR0FBRyxDQUNOLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ25CLENBQUM7aUJBQ0w7Z0JBRUQseUJBQXlCO2dCQUN6QixZQUFZLEdBQUcsV0FBVyxDQUFDO2dCQUMzQixjQUFjLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQztZQUMxQyxDQUFDO1NBQ0osQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sU0FBUyxHQUFHLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQztRQUMvQyxPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FDdkIsOEJBQThCLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FDL0QsQ0FBQztJQUNOLENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsa0JBQWtCLENBQzVCLEdBQVcsRUFDWCxPQUE2QixFQUM3QixNQUF5QjtRQUV6QixNQUFNLFFBQVEsR0FBRyxJQUFJLFVBQVUsQ0FBQyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsdUJBQXVCO1FBQzFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakIsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3BDLElBQUksWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUM3QixJQUFJLGdCQUFnQixHQUFHLENBQUMsQ0FBQztRQUV6QixJQUFJLGNBQWMsR0FBRyxLQUFLLENBQUM7UUFFM0IsSUFBSTtZQUNBLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFO2dCQUM1QixPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUU7Z0JBQ3ZELFdBQVcsRUFBRSxNQUFNLENBQUMsS0FBSztnQkFDekIsWUFBWSxFQUFFLFFBQVE7Z0JBQ3RCLGdCQUFnQixFQUFFLENBQUMsYUFBYSxFQUFFLEVBQUU7b0JBQ2hDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO3dCQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7cUJBQ2pEO29CQUVELE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztvQkFDdEMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMseUJBQXlCO29CQUNsRixNQUFNLG9CQUFvQixHQUN0QixhQUFhLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDO29CQUU1QyxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUU7d0JBQ2pCLE1BQU0sVUFBVSxHQUFHLG9CQUFvQixHQUFHLFdBQVcsQ0FBQyxDQUFDLG1CQUFtQjt3QkFDMUUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxrQkFBa0I7d0JBQ3hFLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUNsQixpQkFBaUIsV0FBVyxDQUFDLE9BQU8sQ0FDaEMsQ0FBQyxDQUNKLG9CQUFvQixDQUNqQixDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLEtBQU0sQ0FBQzs0QkFDN0MsR0FBRyxDQUNOLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ25CLENBQUM7cUJBQ0w7b0JBRUQseUJBQXlCO29CQUN6QixZQUFZLEdBQUcsV0FBVyxDQUFDO29CQUMzQixnQkFBZ0IsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDO29CQUV4QyxJQUFJLGFBQWEsQ0FBQyxNQUFNLElBQUksYUFBYSxDQUFDLEtBQU0sRUFBRTt3QkFDOUMsY0FBYyxHQUFHLElBQUksQ0FBQzt3QkFDdEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO3FCQUMxQztnQkFDTCxDQUFDO2FBQ0osQ0FBQyxDQUFDO1NBQ047UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDbkIsSUFBSSxDQUFDLGNBQWMsRUFBRTtvQkFDakIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsNkJBQTZCLENBQUMsQ0FBQztpQkFDNUQ7cUJBQU07b0JBQ0gsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO29CQUNsQyxNQUFNLFNBQVMsR0FBRyxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUM7b0JBQy9DLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUN2Qiw0QkFBNEIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUM3RCxDQUFDO2lCQUNMO2FBQ0o7aUJBQU07Z0JBQ0gsTUFBTSxDQUFDLENBQUM7YUFDWDtTQUNKO0lBQ0wsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDbGlGb3JlZ3JvdW5kQ29sb3IsXG4gICAgQ2xpUHJvY2Vzc29yTWV0YWRhdGEsXG4gICAgRGVmYXVsdExpYnJhcnlBdXRob3IsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcbmltcG9ydCB7XG4gICAgQ2xpUHJvY2Vzc0NvbW1hbmQsXG4gICAgSUNsaUNvbW1hbmRQcm9jZXNzb3IsXG4gICAgSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcbmltcG9ydCBheGlvcywgeyBDYW5jZWxUb2tlbiwgQ2FuY2VsVG9rZW5Tb3VyY2UgfSBmcm9tICdheGlvcyc7XG5pbXBvcnQgeyBMSUJSQVJZX1ZFUlNJT04gfSBmcm9tICcuLi92ZXJzaW9uJztcblxuZXhwb3J0IGNsYXNzIENsaVNwZWVkVGVzdENvbW1hbmRQcm9jZXNzb3IgaW1wbGVtZW50cyBJQ2xpQ29tbWFuZFByb2Nlc3NvciB7XG4gICAgY29tbWFuZCA9ICdzcGVlZC10ZXN0JztcblxuICAgIGRlc2NyaXB0aW9uID0gJ1J1biBhbiBpbnRlcm5ldCBzcGVlZCB0ZXN0JztcblxuICAgIGF1dGhvciA9IERlZmF1bHRMaWJyYXJ5QXV0aG9yO1xuXG4gICAgcHJvY2Vzc29ycz86IElDbGlDb21tYW5kUHJvY2Vzc29yW10gfCB1bmRlZmluZWQgPSBbXTtcblxuICAgIHZlcnNpb24gPSBMSUJSQVJZX1ZFUlNJT047XG5cbiAgICBtZXRhZGF0YT86IENsaVByb2Nlc3Nvck1ldGFkYXRhIHwgdW5kZWZpbmVkID0ge1xuICAgICAgICBpY29uOiAn8J+agCcsXG4gICAgICAgIHJlcXVpcmVkQ29yZVZlcnNpb246ICcwLjAuMTYnLFxuICAgICAgICByZXF1aXJlZENsaVZlcnNpb246ICcxLjAuMzcnLFxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5wcm9jZXNzb3JzID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6ICdydW4nLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUnVuIHRoZSBpbnRlcm5ldCBzcGVlZCB0ZXN0JyxcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICdkb3dubG9hZC11cmwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICdVUkwgdG8gZG93bmxvYWQgdGhlIGZpbGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICd1cGxvYWQtdXJsJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVVJMIHRvIHVwbG9hZCB0aGUgZmlsZScsXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHByb2Nlc3NDb21tYW5kOiBhc3luYyAoY29tbWFuZCwgY29udGV4dCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2U6IENhbmNlbFRva2VuU291cmNlID1cbiAgICAgICAgICAgICAgICAgICAgICAgIGF4aW9zLkNhbmNlbFRva2VuLnNvdXJjZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IGNvbnRleHQub25BYm9ydC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlLmNhbmNlbCgnU3BlZWQgdGVzdCBhYm9ydGVkIGJ5IHVzZXInKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlPHZvaWQ+KGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlSW5mbygnU3RhcnRpbmcgbGl2ZSBzcGVlZCB0ZXN0Li4uJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRvd25sb2FkVXJsID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21tYW5kLmFyZ3NbJ2Rvd25sb2FkLXVybCddIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vcHJveHkucW9kYWxpcy5jb20vcHJveHkvaHR0cHMvbmJnMS1zcGVlZC5oZXR6bmVyLmNvbS8xMDBNQi5iaW4nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cGxvYWRVcmwgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1hbmQuYXJnc1sndXBsb2FkLXVybCddIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vaHR0cGJpbi5vcmcvcG9zdCc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5ydW5Eb3dubG9hZFNwZWVkVGVzdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bmxvYWRVcmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZS50b2tlbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5ydW5VcGxvYWRTcGVlZFRlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwbG9hZFVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUluZm8oJ1NwZWVkIHRlc3QgY29tcGxldGVkJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBTcGVlZCB0ZXN0IGZhaWxlZDogJHtlcnJvcj8udG9TdHJpbmcoKX1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC5zaG93UHJvbXB0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIGFzeW5jIHByb2Nlc3NDb21tYW5kKFxuICAgICAgICBjb21tYW5kOiBDbGlQcm9jZXNzQ29tbWFuZCxcbiAgICAgICAgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0b3Iuc2hvd0hlbHAoY29tbWFuZCwgY29udGV4dCk7XG4gICAgfVxuXG4gICAgd3JpdGVEZXNjcmlwdGlvbihjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCk6IHZvaWQge1xuICAgICAgICBjb25zdCB7IHdyaXRlciB9ID0gY29udGV4dDtcbiAgICAgICAgd3JpdGVyLndyaXRlbG4odGhpcy5kZXNjcmlwdGlvbik7XG4gICAgICAgIHdyaXRlci53cml0ZWxuKCk7XG4gICAgICAgIHdyaXRlci53cml0ZWxuKCfwn5OLIFVzYWdlOicpO1xuICAgICAgICB3cml0ZXIud3JpdGVsbihgICAke3dyaXRlci53cmFwSW5Db2xvcignc3BlZWQtdGVzdCBydW4nLCBDbGlGb3JlZ3JvdW5kQ29sb3IuQ3lhbil9ICAgICAgICAgICAgICAgICAgICAgICAgICBSdW4gZG93bmxvYWQgJiB1cGxvYWQgdGVzdGApO1xuICAgICAgICB3cml0ZXIud3JpdGVsbihgICAke3dyaXRlci53cmFwSW5Db2xvcignc3BlZWQtdGVzdCBydW4gLS1kb3dubG9hZC11cmw9PHVybD4nLCBDbGlGb3JlZ3JvdW5kQ29sb3IuQ3lhbil9ICAgICBDdXN0b20gZG93bmxvYWQgVVJMYCk7XG4gICAgICAgIHdyaXRlci53cml0ZWxuKGAgICR7d3JpdGVyLndyYXBJbkNvbG9yKCdzcGVlZC10ZXN0IHJ1biAtLXVwbG9hZC11cmw9PHVybD4nLCBDbGlGb3JlZ3JvdW5kQ29sb3IuQ3lhbil9ICAgICAgIEN1c3RvbSB1cGxvYWQgVVJMYCk7XG4gICAgICAgIHdyaXRlci53cml0ZWxuKCk7XG4gICAgICAgIHdyaXRlci53cml0ZWxuKGDwn5KhIFByZXNzICR7d3JpdGVyLndyYXBJbkNvbG9yKCdDdHJsK0MnLCBDbGlGb3JlZ3JvdW5kQ29sb3IuWWVsbG93KX0gdG8gYWJvcnQgdGhlIHRlc3RgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSdW4gdGhlIGRvd25sb2FkIHNwZWVkIHRlc3Qgd2l0aCBsaXZlIHVwZGF0ZXMuXG4gICAgICogQHBhcmFtIGNvbnRleHQgQ0xJIGV4ZWN1dGlvbiBjb250ZXh0LlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgcnVuRG93bmxvYWRTcGVlZFRlc3QoXG4gICAgICAgIHVybDogc3RyaW5nLFxuICAgICAgICBjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgY2FuY2VsVG9rZW46IENhbmNlbFRva2VuLFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgbGV0IHByZXZpb3VzVGltZSA9IHN0YXJ0VGltZTtcbiAgICAgICAgbGV0IHByZXZpb3VzTG9hZGVkID0gMDtcblxuICAgICAgICBhd2FpdCBheGlvcy5nZXQodXJsLCB7XG4gICAgICAgICAgICByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicsXG4gICAgICAgICAgICBjYW5jZWxUb2tlbjogY2FuY2VsVG9rZW4sXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgT3JpZ2luOiBudWxsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRG93bmxvYWRQcm9ncmVzczogKHByb2dyZXNzRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjYW5jZWxUb2tlbi5yZWFzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTcGVlZCB0ZXN0IGFib3J0ZWQgYnkgdXNlcicpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZWxhcHNlZFRpbWUgPSAoY3VycmVudFRpbWUgLSBwcmV2aW91c1RpbWUpIC8gMTAwMDtcbiAgICAgICAgICAgICAgICBjb25zdCBieXRlc1NpbmNlTGFzdFVwZGF0ZSA9XG4gICAgICAgICAgICAgICAgICAgIHByb2dyZXNzRXZlbnQubG9hZGVkIC0gcHJldmlvdXNMb2FkZWQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoZWxhcHNlZFRpbWUgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwZWVkSW5CcHMgPSBieXRlc1NpbmNlTGFzdFVwZGF0ZSAvIGVsYXBzZWRUaW1lOyAvLyBCeXRlcyBwZXIgc2Vjb25kXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwZWVkSW5NYnBzID0gKHNwZWVkSW5CcHMgKiA4KSAvICgxMDI0ICogMTAyNCk7IC8vIENvbnZlcnQgdG8gTWJwc1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKFxuICAgICAgICAgICAgICAgICAgICAgICAgYERvd25sb2FkIFNwZWVkOiAke3NwZWVkSW5NYnBzLnRvRml4ZWQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMixcbiAgICAgICAgICAgICAgICAgICAgICAgICl9IE1icHMgKFByb2dyZXNzOiAkeyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJvZ3Jlc3NFdmVudC5sb2FkZWQgLyBwcm9ncmVzc0V2ZW50LnRvdGFsISkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwMFxuICAgICAgICAgICAgICAgICAgICAgICAgKS50b0ZpeGVkKDIpfSUpYCxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgcHJldmlvdXMgdmFsdWVzXG4gICAgICAgICAgICAgICAgcHJldmlvdXNUaW1lID0gY3VycmVudFRpbWU7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNMb2FkZWQgPSBwcm9ncmVzc0V2ZW50LmxvYWRlZDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGVuZFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgY29uc3QgdG90YWxUaW1lID0gKGVuZFRpbWUgLSBzdGFydFRpbWUpIC8gMTAwMDtcbiAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVTdWNjZXNzKFxuICAgICAgICAgICAgYERvd25sb2FkIHRlc3QgY29tcGxldGVkIGluICR7dG90YWxUaW1lLnRvRml4ZWQoMil9IHNlY29uZHNgLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJ1biB0aGUgdXBsb2FkIHNwZWVkIHRlc3Qgd2l0aCBsaXZlIHVwZGF0ZXMuXG4gICAgICogQHBhcmFtIGNvbnRleHQgQ0xJIGV4ZWN1dGlvbiBjb250ZXh0LlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgcnVuVXBsb2FkU3BlZWRUZXN0KFxuICAgICAgICB1cmw6IHN0cmluZyxcbiAgICAgICAgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgIHNvdXJjZTogQ2FuY2VsVG9rZW5Tb3VyY2UsXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHRlc3REYXRhID0gbmV3IFVpbnQ4QXJyYXkoMjAgKiAxMDI0ICogMTAyNCk7IC8vIDIwIE1CIG9mIHJhbmRvbSBkYXRhXG4gICAgICAgIHRlc3REYXRhLmZpbGwoMCk7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgICAgICBsZXQgcHJldmlvdXNUaW1lID0gc3RhcnRUaW1lO1xuICAgICAgICBsZXQgcHJldmlvdXNVcGxvYWRlZCA9IDA7XG5cbiAgICAgICAgbGV0IHVwbG9hZENvbXBsZXRlID0gZmFsc2U7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGF4aW9zLnBvc3QodXJsLCB0ZXN0RGF0YSwge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nIH0sXG4gICAgICAgICAgICAgICAgY2FuY2VsVG9rZW46IHNvdXJjZS50b2tlbixcbiAgICAgICAgICAgICAgICByZXNwb25zZVR5cGU6ICdzdHJlYW0nLFxuICAgICAgICAgICAgICAgIG9uVXBsb2FkUHJvZ3Jlc3M6IChwcm9ncmVzc0V2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghIXNvdXJjZS50b2tlbi5yZWFzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU3BlZWQgdGVzdCBhYm9ydGVkIGJ5IHVzZXInKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsYXBzZWRUaW1lID0gKGN1cnJlbnRUaW1lIC0gcHJldmlvdXNUaW1lKSAvIDEwMDA7IC8vIFRpbWUgc2luY2UgbGFzdCB1cGRhdGVcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnl0ZXNTaW5jZUxhc3RVcGRhdGUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NFdmVudC5sb2FkZWQgLSBwcmV2aW91c1VwbG9hZGVkO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGFwc2VkVGltZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwZWVkSW5CcHMgPSBieXRlc1NpbmNlTGFzdFVwZGF0ZSAvIGVsYXBzZWRUaW1lOyAvLyBCeXRlcyBwZXIgc2Vjb25kXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcGVlZEluTWJwcyA9IChzcGVlZEluQnBzICogOCkgLyAoMTAyNCAqIDEwMjQpOyAvLyBDb252ZXJ0IHRvIE1icHNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlbG4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFVwbG9hZCBTcGVlZDogJHtzcGVlZEluTWJwcy50b0ZpeGVkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICl9IE1icHMgKFByb2dyZXNzOiAkeyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByb2dyZXNzRXZlbnQubG9hZGVkIC8gcHJvZ3Jlc3NFdmVudC50b3RhbCEpICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKS50b0ZpeGVkKDIpfSUpYCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgcHJldmlvdXMgdmFsdWVzXG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVGltZSA9IGN1cnJlbnRUaW1lO1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1VwbG9hZGVkID0gcHJvZ3Jlc3NFdmVudC5sb2FkZWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2dyZXNzRXZlbnQubG9hZGVkID49IHByb2dyZXNzRXZlbnQudG90YWwhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGxvYWRDb21wbGV0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UuY2FuY2VsKCdVcGxvYWQgdGVzdCBjb21wbGV0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGF4aW9zLmlzQ2FuY2VsKGUpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF1cGxvYWRDb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKCdVcGxvYWQgdGVzdCBhYm9ydGVkIGJ5IHVzZXInKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvdGFsVGltZSA9IChlbmRUaW1lIC0gc3RhcnRUaW1lKSAvIDEwMDA7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlU3VjY2VzcyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGBVcGxvYWQgdGVzdCBjb21wbGV0ZWQgaW4gJHt0b3RhbFRpbWUudG9GaXhlZCgyKX0gc2Vjb25kc2AsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIl19
|
package/esm2022/lib/version.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// Automatically generated during build
|
|
2
|
-
export const LIBRARY_VERSION = '0.0.4';
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3NwZWVkLXRlc3Qvc3JjL2xpYi92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLHVDQUF1QztBQUN2QyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiXG4vLyBBdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBkdXJpbmcgYnVpbGRcbmV4cG9ydCBjb25zdCBMSUJSQVJZX1ZFUlNJT04gPSAnMC4wLjQnO1xuICAiXX0=
|
package/esm2022/public-api.mjs
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Public API Surface of speed-test
|
|
3
|
-
*/
|
|
4
|
-
export * from './lib/cli-speed-test.module';
|
|
5
|
-
export * from './lib/processors/cli-speed-test-command-processor';
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3NwZWVkLXRlc3Qvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLDZCQUE2QixDQUFDO0FBRTVDLGNBQWMsbURBQW1ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIHNwZWVkLXRlc3RcbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jbGktc3BlZWQtdGVzdC5tb2R1bGUnO1xuXG5leHBvcnQgKiBmcm9tICcuL2xpYi9wcm9jZXNzb3JzL2NsaS1zcGVlZC10ZXN0LWNvbW1hbmQtcHJvY2Vzc29yJztcbiJdfQ==
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generated bundle index. Do not edit.
|
|
3
|
-
*/
|
|
4
|
-
export * from './public-api';
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicW9kYWxpcy1jbGktc3BlZWQtdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3NwZWVkLXRlc3Qvc3JjL3FvZGFsaXMtY2xpLXNwZWVkLXRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { NgModule } from '@angular/core';
|
|
3
|
-
import { resolveCommandProcessorProvider } from '@qodalis/angular-cli';
|
|
4
|
-
import { DefaultLibraryAuthor, CliForegroundColor } from '@qodalis/cli-core';
|
|
5
|
-
import axios from 'axios';
|
|
6
|
-
|
|
7
|
-
// Automatically generated during build
|
|
8
|
-
const LIBRARY_VERSION = '0.0.4';
|
|
9
|
-
|
|
10
|
-
class CliSpeedTestCommandProcessor {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.command = 'speed-test';
|
|
13
|
-
this.description = 'Run an internet speed test';
|
|
14
|
-
this.author = DefaultLibraryAuthor;
|
|
15
|
-
this.processors = [];
|
|
16
|
-
this.version = LIBRARY_VERSION;
|
|
17
|
-
this.metadata = {
|
|
18
|
-
icon: '🚀',
|
|
19
|
-
requiredCoreVersion: '0.0.16',
|
|
20
|
-
requiredCliVersion: '1.0.37',
|
|
21
|
-
};
|
|
22
|
-
this.processors = [
|
|
23
|
-
{
|
|
24
|
-
command: 'run',
|
|
25
|
-
description: 'Run the internet speed test',
|
|
26
|
-
parameters: [
|
|
27
|
-
{
|
|
28
|
-
name: 'download-url',
|
|
29
|
-
description: 'URL to download the file',
|
|
30
|
-
type: 'string',
|
|
31
|
-
required: false,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'upload-url',
|
|
35
|
-
description: 'URL to upload the file',
|
|
36
|
-
type: 'string',
|
|
37
|
-
required: false,
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
processCommand: async (command, context) => {
|
|
41
|
-
const source = axios.CancelToken.source();
|
|
42
|
-
const subscription = context.onAbort.subscribe(() => {
|
|
43
|
-
source.cancel('Speed test aborted by user');
|
|
44
|
-
subscription.unsubscribe();
|
|
45
|
-
});
|
|
46
|
-
new Promise(async (resolve, reject) => {
|
|
47
|
-
context.writer.writeInfo('Starting live speed test...');
|
|
48
|
-
const downloadUrl = command.args['download-url'] ||
|
|
49
|
-
'https://proxy.qodalis.com/proxy/https/nbg1-speed.hetzner.com/100MB.bin';
|
|
50
|
-
const uploadUrl = command.args['upload-url'] ||
|
|
51
|
-
'https://httpbin.org/post';
|
|
52
|
-
try {
|
|
53
|
-
await this.runDownloadSpeedTest(downloadUrl, context, source.token);
|
|
54
|
-
await this.runUploadSpeedTest(uploadUrl, context, source);
|
|
55
|
-
context.writer.writeInfo('Speed test completed');
|
|
56
|
-
resolve();
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
context.writer.writeError(`Speed test failed: ${error?.toString()}`);
|
|
60
|
-
reject(error);
|
|
61
|
-
}
|
|
62
|
-
subscription.unsubscribe();
|
|
63
|
-
context.showPrompt();
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
];
|
|
68
|
-
}
|
|
69
|
-
async processCommand(command, context) {
|
|
70
|
-
await context.executor.showHelp(command, context);
|
|
71
|
-
}
|
|
72
|
-
writeDescription(context) {
|
|
73
|
-
const { writer } = context;
|
|
74
|
-
writer.writeln(this.description);
|
|
75
|
-
writer.writeln();
|
|
76
|
-
writer.writeln('📋 Usage:');
|
|
77
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run', CliForegroundColor.Cyan)} Run download & upload test`);
|
|
78
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run --download-url=<url>', CliForegroundColor.Cyan)} Custom download URL`);
|
|
79
|
-
writer.writeln(` ${writer.wrapInColor('speed-test run --upload-url=<url>', CliForegroundColor.Cyan)} Custom upload URL`);
|
|
80
|
-
writer.writeln();
|
|
81
|
-
writer.writeln(`💡 Press ${writer.wrapInColor('Ctrl+C', CliForegroundColor.Yellow)} to abort the test`);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Run the download speed test with live updates.
|
|
85
|
-
* @param context CLI execution context.
|
|
86
|
-
*/
|
|
87
|
-
async runDownloadSpeedTest(url, context, cancelToken) {
|
|
88
|
-
const startTime = performance.now();
|
|
89
|
-
let previousTime = startTime;
|
|
90
|
-
let previousLoaded = 0;
|
|
91
|
-
await axios.get(url, {
|
|
92
|
-
responseType: 'arraybuffer',
|
|
93
|
-
cancelToken: cancelToken,
|
|
94
|
-
headers: {
|
|
95
|
-
Origin: null,
|
|
96
|
-
},
|
|
97
|
-
onDownloadProgress: (progressEvent) => {
|
|
98
|
-
if (!!cancelToken.reason) {
|
|
99
|
-
throw new Error('Speed test aborted by user');
|
|
100
|
-
}
|
|
101
|
-
const currentTime = performance.now();
|
|
102
|
-
const elapsedTime = (currentTime - previousTime) / 1000;
|
|
103
|
-
const bytesSinceLastUpdate = progressEvent.loaded - previousLoaded;
|
|
104
|
-
if (elapsedTime > 0) {
|
|
105
|
-
const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second
|
|
106
|
-
const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps
|
|
107
|
-
context.writer.writeln(`Download Speed: ${speedInMbps.toFixed(2)} Mbps (Progress: ${((progressEvent.loaded / progressEvent.total) *
|
|
108
|
-
100).toFixed(2)}%)`);
|
|
109
|
-
}
|
|
110
|
-
// Update previous values
|
|
111
|
-
previousTime = currentTime;
|
|
112
|
-
previousLoaded = progressEvent.loaded;
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
const endTime = performance.now();
|
|
116
|
-
const totalTime = (endTime - startTime) / 1000;
|
|
117
|
-
context.writer.writeSuccess(`Download test completed in ${totalTime.toFixed(2)} seconds`);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Run the upload speed test with live updates.
|
|
121
|
-
* @param context CLI execution context.
|
|
122
|
-
*/
|
|
123
|
-
async runUploadSpeedTest(url, context, source) {
|
|
124
|
-
const testData = new Uint8Array(20 * 1024 * 1024); // 20 MB of random data
|
|
125
|
-
testData.fill(0);
|
|
126
|
-
const startTime = performance.now();
|
|
127
|
-
let previousTime = startTime;
|
|
128
|
-
let previousUploaded = 0;
|
|
129
|
-
let uploadComplete = false;
|
|
130
|
-
try {
|
|
131
|
-
await axios.post(url, testData, {
|
|
132
|
-
headers: { 'Content-Type': 'application/octet-stream' },
|
|
133
|
-
cancelToken: source.token,
|
|
134
|
-
responseType: 'stream',
|
|
135
|
-
onUploadProgress: (progressEvent) => {
|
|
136
|
-
if (!!source.token.reason) {
|
|
137
|
-
throw new Error('Speed test aborted by user');
|
|
138
|
-
}
|
|
139
|
-
const currentTime = performance.now();
|
|
140
|
-
const elapsedTime = (currentTime - previousTime) / 1000; // Time since last update
|
|
141
|
-
const bytesSinceLastUpdate = progressEvent.loaded - previousUploaded;
|
|
142
|
-
if (elapsedTime > 0) {
|
|
143
|
-
const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second
|
|
144
|
-
const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps
|
|
145
|
-
context.writer.writeln(`Upload Speed: ${speedInMbps.toFixed(2)} Mbps (Progress: ${((progressEvent.loaded / progressEvent.total) *
|
|
146
|
-
100).toFixed(2)}%)`);
|
|
147
|
-
}
|
|
148
|
-
// Update previous values
|
|
149
|
-
previousTime = currentTime;
|
|
150
|
-
previousUploaded = progressEvent.loaded;
|
|
151
|
-
if (progressEvent.loaded >= progressEvent.total) {
|
|
152
|
-
uploadComplete = true;
|
|
153
|
-
source.cancel('Upload test completed');
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
catch (e) {
|
|
159
|
-
if (axios.isCancel(e)) {
|
|
160
|
-
if (!uploadComplete) {
|
|
161
|
-
context.writer.writeError('Upload test aborted by user');
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
const endTime = performance.now();
|
|
165
|
-
const totalTime = (endTime - startTime) / 1000;
|
|
166
|
-
context.writer.writeSuccess(`Upload test completed in ${totalTime.toFixed(2)} seconds`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
throw e;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
class CliSpeedTestModule {
|
|
177
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
178
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule }); }
|
|
179
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, providers: [resolveCommandProcessorProvider(CliSpeedTestCommandProcessor)] }); }
|
|
180
|
-
}
|
|
181
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliSpeedTestModule, decorators: [{
|
|
182
|
-
type: NgModule,
|
|
183
|
-
args: [{
|
|
184
|
-
declarations: [],
|
|
185
|
-
imports: [],
|
|
186
|
-
exports: [],
|
|
187
|
-
providers: [resolveCommandProcessorProvider(CliSpeedTestCommandProcessor)],
|
|
188
|
-
}]
|
|
189
|
-
}] });
|
|
190
|
-
|
|
191
|
-
/*
|
|
192
|
-
* Public API Surface of speed-test
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Generated bundle index. Do not edit.
|
|
197
|
-
*/
|
|
198
|
-
|
|
199
|
-
export { CliSpeedTestCommandProcessor, CliSpeedTestModule };
|
|
200
|
-
//# sourceMappingURL=qodalis-cli-speed-test.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qodalis-cli-speed-test.mjs","sources":["../../../projects/speed-test/src/lib/version.ts","../../../projects/speed-test/src/lib/processors/cli-speed-test-command-processor.ts","../../../projects/speed-test/src/lib/cli-speed-test.module.ts","../../../projects/speed-test/src/public-api.ts","../../../projects/speed-test/src/qodalis-cli-speed-test.ts"],"sourcesContent":["\n// Automatically generated during build\nexport const LIBRARY_VERSION = '0.0.4';\n ","import {\n CliForegroundColor,\n CliProcessorMetadata,\n DefaultLibraryAuthor,\n} from '@qodalis/cli-core';\nimport {\n CliProcessCommand,\n ICliCommandProcessor,\n ICliExecutionContext,\n} from '@qodalis/cli-core';\nimport axios, { CancelToken, CancelTokenSource } from 'axios';\nimport { LIBRARY_VERSION } from '../version';\n\nexport class CliSpeedTestCommandProcessor implements ICliCommandProcessor {\n command = 'speed-test';\n\n description = 'Run an internet speed test';\n\n author = DefaultLibraryAuthor;\n\n processors?: ICliCommandProcessor[] | undefined = [];\n\n version = LIBRARY_VERSION;\n\n metadata?: CliProcessorMetadata | undefined = {\n icon: '🚀',\n requiredCoreVersion: '0.0.16',\n requiredCliVersion: '1.0.37',\n };\n\n constructor() {\n this.processors = [\n {\n command: 'run',\n description: 'Run the internet speed test',\n parameters: [\n {\n name: 'download-url',\n description: 'URL to download the file',\n type: 'string',\n required: false,\n },\n {\n name: 'upload-url',\n description: 'URL to upload the file',\n type: 'string',\n required: false,\n },\n ],\n processCommand: async (command, context) => {\n const source: CancelTokenSource =\n axios.CancelToken.source();\n\n const subscription = context.onAbort.subscribe(() => {\n source.cancel('Speed test aborted by user');\n\n subscription.unsubscribe();\n });\n\n new Promise<void>(async (resolve, reject) => {\n context.writer.writeInfo('Starting live speed test...');\n\n const downloadUrl =\n command.args['download-url'] ||\n 'https://proxy.qodalis.com/proxy/https/nbg1-speed.hetzner.com/100MB.bin';\n\n const uploadUrl =\n command.args['upload-url'] ||\n 'https://httpbin.org/post';\n\n try {\n await this.runDownloadSpeedTest(\n downloadUrl,\n context,\n source.token,\n );\n\n await this.runUploadSpeedTest(\n uploadUrl,\n context,\n source,\n );\n\n context.writer.writeInfo('Speed test completed');\n\n resolve();\n } catch (error) {\n context.writer.writeError(\n `Speed test failed: ${error?.toString()}`,\n );\n\n reject(error);\n }\n\n subscription.unsubscribe();\n\n context.showPrompt();\n });\n },\n },\n ];\n }\n\n async processCommand(\n command: CliProcessCommand,\n context: ICliExecutionContext,\n ): Promise<void> {\n await context.executor.showHelp(command, context);\n }\n\n writeDescription(context: ICliExecutionContext): void {\n const { writer } = context;\n writer.writeln(this.description);\n writer.writeln();\n writer.writeln('📋 Usage:');\n writer.writeln(` ${writer.wrapInColor('speed-test run', CliForegroundColor.Cyan)} Run download & upload test`);\n writer.writeln(` ${writer.wrapInColor('speed-test run --download-url=<url>', CliForegroundColor.Cyan)} Custom download URL`);\n writer.writeln(` ${writer.wrapInColor('speed-test run --upload-url=<url>', CliForegroundColor.Cyan)} Custom upload URL`);\n writer.writeln();\n writer.writeln(`💡 Press ${writer.wrapInColor('Ctrl+C', CliForegroundColor.Yellow)} to abort the test`);\n }\n\n /**\n * Run the download speed test with live updates.\n * @param context CLI execution context.\n */\n private async runDownloadSpeedTest(\n url: string,\n context: ICliExecutionContext,\n cancelToken: CancelToken,\n ): Promise<void> {\n const startTime = performance.now();\n let previousTime = startTime;\n let previousLoaded = 0;\n\n await axios.get(url, {\n responseType: 'arraybuffer',\n cancelToken: cancelToken,\n headers: {\n Origin: null,\n },\n onDownloadProgress: (progressEvent) => {\n if (!!cancelToken.reason) {\n throw new Error('Speed test aborted by user');\n }\n\n const currentTime = performance.now();\n const elapsedTime = (currentTime - previousTime) / 1000;\n const bytesSinceLastUpdate =\n progressEvent.loaded - previousLoaded;\n\n if (elapsedTime > 0) {\n const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second\n const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps\n context.writer.writeln(\n `Download Speed: ${speedInMbps.toFixed(\n 2,\n )} Mbps (Progress: ${(\n (progressEvent.loaded / progressEvent.total!) *\n 100\n ).toFixed(2)}%)`,\n );\n }\n\n // Update previous values\n previousTime = currentTime;\n previousLoaded = progressEvent.loaded;\n },\n });\n\n const endTime = performance.now();\n const totalTime = (endTime - startTime) / 1000;\n context.writer.writeSuccess(\n `Download test completed in ${totalTime.toFixed(2)} seconds`,\n );\n }\n\n /**\n * Run the upload speed test with live updates.\n * @param context CLI execution context.\n */\n private async runUploadSpeedTest(\n url: string,\n context: ICliExecutionContext,\n source: CancelTokenSource,\n ): Promise<void> {\n const testData = new Uint8Array(20 * 1024 * 1024); // 20 MB of random data\n testData.fill(0);\n const startTime = performance.now();\n let previousTime = startTime;\n let previousUploaded = 0;\n\n let uploadComplete = false;\n\n try {\n await axios.post(url, testData, {\n headers: { 'Content-Type': 'application/octet-stream' },\n cancelToken: source.token,\n responseType: 'stream',\n onUploadProgress: (progressEvent) => {\n if (!!source.token.reason) {\n throw new Error('Speed test aborted by user');\n }\n\n const currentTime = performance.now();\n const elapsedTime = (currentTime - previousTime) / 1000; // Time since last update\n const bytesSinceLastUpdate =\n progressEvent.loaded - previousUploaded;\n\n if (elapsedTime > 0) {\n const speedInBps = bytesSinceLastUpdate / elapsedTime; // Bytes per second\n const speedInMbps = (speedInBps * 8) / (1024 * 1024); // Convert to Mbps\n context.writer.writeln(\n `Upload Speed: ${speedInMbps.toFixed(\n 2,\n )} Mbps (Progress: ${(\n (progressEvent.loaded / progressEvent.total!) *\n 100\n ).toFixed(2)}%)`,\n );\n }\n\n // Update previous values\n previousTime = currentTime;\n previousUploaded = progressEvent.loaded;\n\n if (progressEvent.loaded >= progressEvent.total!) {\n uploadComplete = true;\n source.cancel('Upload test completed');\n }\n },\n });\n } catch (e) {\n if (axios.isCancel(e)) {\n if (!uploadComplete) {\n context.writer.writeError('Upload test aborted by user');\n } else {\n const endTime = performance.now();\n const totalTime = (endTime - startTime) / 1000;\n context.writer.writeSuccess(\n `Upload test completed in ${totalTime.toFixed(2)} seconds`,\n );\n }\n } else {\n throw e;\n }\n }\n }\n}\n","import { NgModule } from '@angular/core';\nimport { resolveCommandProcessorProvider } from '@qodalis/angular-cli';\nimport { CliSpeedTestCommandProcessor } from './processors/cli-speed-test-command-processor';\n\n@NgModule({\n declarations: [],\n imports: [],\n exports: [],\n providers: [resolveCommandProcessorProvider(CliSpeedTestCommandProcessor)],\n})\nexport class CliSpeedTestModule {}\n","/*\n * Public API Surface of speed-test\n */\n\nexport * from './lib/cli-speed-test.module';\n\nexport * from './lib/processors/cli-speed-test-command-processor';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import * as i0 from "@angular/core";
|
|
2
|
-
export declare class CliSpeedTestModule {
|
|
3
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<CliSpeedTestModule, never>;
|
|
4
|
-
static ɵmod: i0.ɵɵNgModuleDeclaration<CliSpeedTestModule, never, never, never>;
|
|
5
|
-
static ɵinj: i0.ɵɵInjectorDeclaration<CliSpeedTestModule>;
|
|
6
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { CliProcessorMetadata } from '@qodalis/cli-core';
|
|
2
|
-
import { CliProcessCommand, ICliCommandProcessor, ICliExecutionContext } from '@qodalis/cli-core';
|
|
3
|
-
export declare class CliSpeedTestCommandProcessor implements ICliCommandProcessor {
|
|
4
|
-
command: string;
|
|
5
|
-
description: string;
|
|
6
|
-
author: import("@qodalis/cli-core").ICliCommandAuthor;
|
|
7
|
-
processors?: ICliCommandProcessor[] | undefined;
|
|
8
|
-
version: string;
|
|
9
|
-
metadata?: CliProcessorMetadata | undefined;
|
|
10
|
-
constructor();
|
|
11
|
-
processCommand(command: CliProcessCommand, context: ICliExecutionContext): Promise<void>;
|
|
12
|
-
writeDescription(context: ICliExecutionContext): void;
|
|
13
|
-
/**
|
|
14
|
-
* Run the download speed test with live updates.
|
|
15
|
-
* @param context CLI execution context.
|
|
16
|
-
*/
|
|
17
|
-
private runDownloadSpeedTest;
|
|
18
|
-
/**
|
|
19
|
-
* Run the upload speed test with live updates.
|
|
20
|
-
* @param context CLI execution context.
|
|
21
|
-
*/
|
|
22
|
-
private runUploadSpeedTest;
|
|
23
|
-
}
|
package/lib/version.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const LIBRARY_VERSION = "0.0.4";
|