@testrigor/testrigor-cli 1.0.0 → 1.0.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/README.md +452 -0
- package/dist/commands/authenticate.js +1 -1
- package/dist/commands/test-suite/config.js +1 -1
- package/dist/commands/test-suite/run.js +18 -17
- package/dist/commands/test-suite/validate-syntax.js +3 -2
- package/dist/flags/chrome-extension.js +3 -2
- package/dist/types.d.ts +0 -1
- package/dist/util/appium.js +29 -25
- package/dist/util/certificate-uploader.js +5 -5
- package/dist/util/config.js +15 -15
- package/dist/util/parser.js +8 -8
- package/dist/util/request-builder.d.ts +1 -1
- package/dist/util/request-builder.js +7 -7
- package/dist/util/trtc.d.ts +2 -0
- package/dist/util/trtc.js +107 -38
- package/dist/util/tunnel.js +7 -6
- package/dist/util/type-guards.js +3 -4
- package/dist/util/utils.d.ts +3 -3
- package/dist/util/utils.js +23 -23
- package/dist/util/variable-file-uploader.js +7 -7
- package/dist/util/variables-path-parser.js +4 -4
- package/oclif.manifest.json +1 -1
- package/package.json +7 -7
package/dist/util/appium.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
exports.PID_FILE = exports.PID_DIR = exports.REQUIRED_DRIVERS = exports.DEFAULT_BASE_PATH = exports.DEFAULT_PORT = void 0;
|
|
4
|
+
exports.checkAppiumInstalled = checkAppiumInstalled;
|
|
5
|
+
exports.getDriverStatus = getDriverStatus;
|
|
6
|
+
exports.ensureDriver = ensureDriver;
|
|
7
|
+
exports.isProcessRunning = isProcessRunning;
|
|
8
|
+
exports.getRunningAppiumPid = getRunningAppiumPid;
|
|
9
|
+
exports.startAppium = startAppium;
|
|
10
|
+
exports.stopAppium = stopAppium;
|
|
11
|
+
const tslib_1 = require("tslib");
|
|
12
|
+
const childProcess = tslib_1.__importStar(require("child_process"));
|
|
13
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
14
|
+
const util = tslib_1.__importStar(require("util"));
|
|
15
|
+
const path = tslib_1.__importStar(require("path"));
|
|
16
|
+
const os = tslib_1.__importStar(require("os"));
|
|
17
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
10
18
|
const execFile = util.promisify(childProcess.execFile);
|
|
11
19
|
const PROJECT_ROOT = path.resolve(__dirname, "..", "..");
|
|
12
20
|
const APPIUM_HOME = path.join(PROJECT_ROOT, ".appium");
|
|
@@ -36,7 +44,7 @@ function getAppiumEnv() {
|
|
|
36
44
|
}
|
|
37
45
|
async function checkAppiumInstalled() {
|
|
38
46
|
const appiumBin = getAppiumBin();
|
|
39
|
-
if (!(await
|
|
47
|
+
if (!(await fs_1.default.exists(appiumBin))) {
|
|
40
48
|
throw new Error(`Appium binary not found at ${appiumBin}. Try reinstalling testrigor-cli.`);
|
|
41
49
|
}
|
|
42
50
|
try {
|
|
@@ -46,7 +54,6 @@ async function checkAppiumInstalled() {
|
|
|
46
54
|
throw new Error(`Appium binary at ${appiumBin} is not working. Try reinstalling testrigor-cli.`);
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
|
-
exports.checkAppiumInstalled = checkAppiumInstalled;
|
|
50
57
|
async function getDriverStatus(driverName, requiredVersion) {
|
|
51
58
|
const appiumBin = getAppiumBin();
|
|
52
59
|
try {
|
|
@@ -66,7 +73,6 @@ async function getDriverStatus(driverName, requiredVersion) {
|
|
|
66
73
|
return { installed: false, upToDate: false };
|
|
67
74
|
}
|
|
68
75
|
}
|
|
69
|
-
exports.getDriverStatus = getDriverStatus;
|
|
70
76
|
async function ensureDriver(driverName, requiredVersion) {
|
|
71
77
|
const appiumBin = getAppiumBin();
|
|
72
78
|
const env = getAppiumEnv();
|
|
@@ -86,10 +92,12 @@ async function ensureDriver(driverName, requiredVersion) {
|
|
|
86
92
|
}
|
|
87
93
|
catch (error) {
|
|
88
94
|
const raw = error instanceof Error ? error.message : String(error);
|
|
89
|
-
return raw
|
|
95
|
+
return raw
|
|
96
|
+
.split("\n")[0]
|
|
97
|
+
.replace(/^Command failed:.*?Error:\s*/, "")
|
|
98
|
+
.trim();
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
|
-
exports.ensureDriver = ensureDriver;
|
|
93
101
|
function isProcessRunning(pid) {
|
|
94
102
|
try {
|
|
95
103
|
process.kill(pid, 0);
|
|
@@ -99,24 +107,22 @@ function isProcessRunning(pid) {
|
|
|
99
107
|
return false;
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
|
-
exports.isProcessRunning = isProcessRunning;
|
|
103
110
|
function killSafe(pid) {
|
|
104
111
|
if (isProcessRunning(pid)) {
|
|
105
112
|
process.kill(pid);
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
async function getRunningAppiumPid() {
|
|
109
|
-
if (!(await
|
|
116
|
+
if (!(await fs_1.default.exists(PID_FILE))) {
|
|
110
117
|
return null;
|
|
111
118
|
}
|
|
112
|
-
const existingPid = Number((await
|
|
119
|
+
const existingPid = Number((await fs_1.default.content(PID_FILE)).trim());
|
|
113
120
|
if (isProcessRunning(existingPid)) {
|
|
114
121
|
return existingPid;
|
|
115
122
|
}
|
|
116
|
-
await
|
|
123
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
117
124
|
return null;
|
|
118
125
|
}
|
|
119
|
-
exports.getRunningAppiumPid = getRunningAppiumPid;
|
|
120
126
|
async function healthCheck(port, retries = 15, interval = 2000) {
|
|
121
127
|
const url = `http://127.0.0.1:${port}/wd/hub/status`;
|
|
122
128
|
let lastError = "";
|
|
@@ -161,29 +167,27 @@ async function startAppium(port = DEFAULT_PORT, logLevel = "debug") {
|
|
|
161
167
|
throw new Error("Failed to start Appium server: no PID returned");
|
|
162
168
|
}
|
|
163
169
|
appiumProcess.unref();
|
|
164
|
-
await
|
|
165
|
-
await
|
|
170
|
+
await fs_1.default.ensureDir(PID_DIR);
|
|
171
|
+
await fs_1.default.writeFile(PID_FILE, String(pid));
|
|
166
172
|
try {
|
|
167
173
|
await healthCheck(port);
|
|
168
174
|
}
|
|
169
175
|
catch (err) {
|
|
170
176
|
killSafe(pid);
|
|
171
|
-
await
|
|
177
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
172
178
|
throw err;
|
|
173
179
|
}
|
|
174
180
|
return { pid, alreadyRunning: false };
|
|
175
181
|
}
|
|
176
|
-
exports.startAppium = startAppium;
|
|
177
182
|
async function stopAppium() {
|
|
178
|
-
if (!(await
|
|
183
|
+
if (!(await fs_1.default.exists(PID_FILE))) {
|
|
179
184
|
return null;
|
|
180
185
|
}
|
|
181
|
-
const pidContent = (await
|
|
186
|
+
const pidContent = (await fs_1.default.content(PID_FILE)).trim();
|
|
182
187
|
const pid = Number(pidContent);
|
|
183
188
|
if (!isNaN(pid) && isProcessRunning(pid)) {
|
|
184
189
|
process.kill(pid, "SIGTERM");
|
|
185
190
|
}
|
|
186
|
-
await
|
|
191
|
+
await fs_1.default.removeFile(PID_FILE);
|
|
187
192
|
return pid;
|
|
188
193
|
}
|
|
189
|
-
exports.stopAppium = stopAppium;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uploadClientCertificate =
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
3
|
+
exports.uploadClientCertificate = uploadClientCertificate;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
const node_fetch_commonjs_1 = tslib_1.__importDefault(require("node-fetch-commonjs"));
|
|
7
8
|
const type_guards_1 = require("./type-guards");
|
|
8
9
|
async function uploadClientCertificate(api2BaseUrl, testSuiteId, token, localFilePath, password) {
|
|
9
10
|
const fileName = path.basename(localFilePath);
|
|
@@ -29,4 +30,3 @@ async function uploadClientCertificate(api2BaseUrl, testSuiteId, token, localFil
|
|
|
29
30
|
info: responseJson.data.info,
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
exports.uploadClientCertificate = uploadClientCertificate;
|
package/dist/util/config.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getConfigPath = getConfigPath;
|
|
4
|
+
exports.readConfig = readConfig;
|
|
5
|
+
exports.writeConfig = writeConfig;
|
|
6
|
+
exports.readConfigProperty = readConfigProperty;
|
|
7
|
+
exports.updateConfigProperty = updateConfigProperty;
|
|
8
|
+
exports.deleteConfigProperty = deleteConfigProperty;
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
4
10
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const
|
|
6
|
-
const path = require("path");
|
|
11
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
12
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
13
|
const yaml_1 = require("yaml");
|
|
8
14
|
const utils_1 = require("./utils");
|
|
9
15
|
/**
|
|
@@ -14,17 +20,16 @@ function getConfigPath() {
|
|
|
14
20
|
const configPath = path.join(homeDir, "testrigor.yml");
|
|
15
21
|
return { homeDir, configPath };
|
|
16
22
|
}
|
|
17
|
-
exports.getConfigPath = getConfigPath;
|
|
18
23
|
/**
|
|
19
24
|
* Read testRigor configuration from ~/.testrigor/testrigor.yml
|
|
20
25
|
*/
|
|
21
26
|
async function readConfig() {
|
|
22
27
|
const { configPath } = getConfigPath();
|
|
23
|
-
if (!(await
|
|
28
|
+
if (!(await fs_1.default.pathExists(configPath))) {
|
|
24
29
|
return {};
|
|
25
30
|
}
|
|
26
31
|
try {
|
|
27
|
-
const content = await
|
|
32
|
+
const content = await fs_1.default.content(configPath);
|
|
28
33
|
return (0, yaml_1.parse)(content.toString()) || {};
|
|
29
34
|
}
|
|
30
35
|
catch (error) {
|
|
@@ -34,26 +39,24 @@ async function readConfig() {
|
|
|
34
39
|
return {};
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
|
-
exports.readConfig = readConfig;
|
|
38
42
|
/**
|
|
39
43
|
* Write testRigor configuration to ~/.testrigor/testrigor.yml
|
|
40
44
|
*/
|
|
41
45
|
async function writeConfig(config) {
|
|
42
46
|
const { homeDir, configPath } = getConfigPath();
|
|
43
47
|
// Ensure the config directory exists
|
|
44
|
-
if (!(await
|
|
45
|
-
await
|
|
48
|
+
if (!(await fs_1.default.pathExists(homeDir))) {
|
|
49
|
+
await fs_1.default.ensureDir(homeDir);
|
|
46
50
|
}
|
|
47
51
|
// Avoid writing empty objects as "{}"
|
|
48
52
|
const configContent = Object.keys(config).length > 0 ? (0, yaml_1.stringify)(config) : "";
|
|
49
53
|
if (configContent.trim() === "") {
|
|
50
|
-
await
|
|
54
|
+
await fs_1.default.writeFile(configPath, "");
|
|
51
55
|
}
|
|
52
56
|
else {
|
|
53
|
-
await
|
|
57
|
+
await fs_1.default.writeFile(configPath, configContent);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
|
-
exports.writeConfig = writeConfig;
|
|
57
60
|
/**
|
|
58
61
|
* Read a specific property from testRigor configuration
|
|
59
62
|
*/
|
|
@@ -61,7 +64,6 @@ async function readConfigProperty(property) {
|
|
|
61
64
|
const config = await readConfig();
|
|
62
65
|
return config[property] || null;
|
|
63
66
|
}
|
|
64
|
-
exports.readConfigProperty = readConfigProperty;
|
|
65
67
|
/**
|
|
66
68
|
* Update a specific property in testRigor configuration
|
|
67
69
|
*/
|
|
@@ -75,7 +77,6 @@ async function updateConfigProperty(property, value) {
|
|
|
75
77
|
}
|
|
76
78
|
await writeConfig(config);
|
|
77
79
|
}
|
|
78
|
-
exports.updateConfigProperty = updateConfigProperty;
|
|
79
80
|
/**
|
|
80
81
|
* Delete a specific property from testRigor configuration
|
|
81
82
|
*/
|
|
@@ -84,4 +85,3 @@ async function deleteConfigProperty(property) {
|
|
|
84
85
|
delete config[property];
|
|
85
86
|
await writeConfig(config);
|
|
86
87
|
}
|
|
87
|
-
exports.deleteConfigProperty = deleteConfigProperty;
|
package/dist/util/parser.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
3
|
+
exports.parseTestCases = parseTestCases;
|
|
4
|
+
exports.parseRules = parseRules;
|
|
5
|
+
exports.parseSettings = parseSettings;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
5
8
|
const glob_1 = require("glob");
|
|
6
9
|
const yaml_1 = require("yaml");
|
|
7
10
|
const utils_1 = require("./utils");
|
|
@@ -10,7 +13,7 @@ async function parseTestCases(path) {
|
|
|
10
13
|
const files = await (0, glob_1.glob)(path, { withFileTypes: true });
|
|
11
14
|
for (const file of files) {
|
|
12
15
|
if (file.isFile()) {
|
|
13
|
-
const content = await
|
|
16
|
+
const content = await fs_1.default.content(file.fullpath());
|
|
14
17
|
if ((0, utils_1.isYamlFile)(file.name)) {
|
|
15
18
|
const json = (0, yaml_1.parse)(content.toString());
|
|
16
19
|
const testCase = {
|
|
@@ -39,13 +42,12 @@ async function parseTestCases(path) {
|
|
|
39
42
|
}
|
|
40
43
|
return result;
|
|
41
44
|
}
|
|
42
|
-
exports.parseTestCases = parseTestCases;
|
|
43
45
|
async function parseRules(path) {
|
|
44
46
|
const result = [];
|
|
45
47
|
const files = await (0, glob_1.glob)(path, { withFileTypes: true });
|
|
46
48
|
for (const file of files) {
|
|
47
49
|
if (file.isFile()) {
|
|
48
|
-
const content = await
|
|
50
|
+
const content = await fs_1.default.content(file.fullpath());
|
|
49
51
|
if ((0, utils_1.isYamlFile)(file.name)) {
|
|
50
52
|
const json = (0, yaml_1.parse)(content.toString());
|
|
51
53
|
const ruleName = (0, utils_1.removeExtension)(file.name);
|
|
@@ -69,9 +71,8 @@ async function parseRules(path) {
|
|
|
69
71
|
}
|
|
70
72
|
return result;
|
|
71
73
|
}
|
|
72
|
-
exports.parseRules = parseRules;
|
|
73
74
|
async function parseSettings(path) {
|
|
74
|
-
const content = await
|
|
75
|
+
const content = await fs_1.default.content(path);
|
|
75
76
|
if ((0, utils_1.isYamlFile)(path)) {
|
|
76
77
|
return (0, yaml_1.parse)(content.toString());
|
|
77
78
|
}
|
|
@@ -80,4 +81,3 @@ async function parseSettings(path) {
|
|
|
80
81
|
}
|
|
81
82
|
return {};
|
|
82
83
|
}
|
|
83
|
-
exports.parseSettings = parseSettings;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildChromeExtensionFormData =
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
3
|
+
exports.buildChromeExtensionFormData = buildChromeExtensionFormData;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const form_data_1 = tslib_1.__importDefault(require("form-data"));
|
|
6
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
7
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
8
|
function toChromeExtensionOverrideItem(input) {
|
|
8
9
|
try {
|
|
9
10
|
return {
|
|
10
11
|
name: input.name,
|
|
11
|
-
file:
|
|
12
|
+
file: fs_1.default.createReadStream(input.file),
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
catch (error) {
|
|
@@ -29,7 +30,7 @@ function toChromeExtensionOverridesRequest(extensionInputs) {
|
|
|
29
30
|
*/
|
|
30
31
|
function buildChromeExtensionFormData(chromeExtensions) {
|
|
31
32
|
const { request, streams } = toChromeExtensionOverridesRequest(chromeExtensions);
|
|
32
|
-
const form = new
|
|
33
|
+
const form = new form_data_1.default();
|
|
33
34
|
request.chromeExtensions.forEach((ext, index) => {
|
|
34
35
|
form.append(`chromeExtensions[${index}].name`, ext.name);
|
|
35
36
|
const fileName = path.basename(chromeExtensions[index].file);
|
|
@@ -46,4 +47,3 @@ function buildChromeExtensionFormData(chromeExtensions) {
|
|
|
46
47
|
};
|
|
47
48
|
return { form, cleanup };
|
|
48
49
|
}
|
|
49
|
-
exports.buildChromeExtensionFormData = buildChromeExtensionFormData;
|
package/dist/util/trtc.d.ts
CHANGED
package/dist/util/trtc.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
3
|
+
exports.extractZip = extractZip;
|
|
4
|
+
exports.extractTar = extractTar;
|
|
5
|
+
exports.download = download;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
8
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
9
|
+
const node_fetch_commonjs_1 = tslib_1.__importDefault(require("node-fetch-commonjs"));
|
|
10
|
+
const os = tslib_1.__importStar(require("os"));
|
|
11
|
+
const path = tslib_1.__importStar(require("path"));
|
|
12
|
+
const tar = tslib_1.__importStar(require("tar-stream"));
|
|
13
|
+
const unzip = tslib_1.__importStar(require("unzip-stream"));
|
|
14
|
+
const zlib = tslib_1.__importStar(require("zlib"));
|
|
12
15
|
const core_1 = require("@oclif/core");
|
|
13
16
|
const FILE_EXTENSION = {
|
|
14
17
|
darwin: "tar.gz",
|
|
@@ -56,39 +59,77 @@ function getUrl() {
|
|
|
56
59
|
}
|
|
57
60
|
throw new Error(`Unsupported platform ${platform} or architecture ${architecture}`);
|
|
58
61
|
}
|
|
62
|
+
const DOWNLOAD_ATTEMPTS = 3;
|
|
63
|
+
const DOWNLOAD_STALL_TIMEOUT_MS = 20000;
|
|
64
|
+
function errorMessage(error) {
|
|
65
|
+
return error instanceof Error ? error.message : String(error);
|
|
66
|
+
}
|
|
67
|
+
// Writes an archive entry to a temp file next to its destination and renames it over the
|
|
68
|
+
// destination once fully flushed, so on any OS the binary is never spawned half-written. It also
|
|
69
|
+
// replaces an existing binary with a new file instead of truncating and rewriting it in place,
|
|
70
|
+
// which an OS may refuse or penalise while that binary is running or cached from a previous run.
|
|
71
|
+
function writeEntry(entryPath, entry, mode) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const tmpPath = `${entryPath}.${process.pid}.tmp`;
|
|
74
|
+
const writeStream = fs.createWriteStream(tmpPath);
|
|
75
|
+
writeStream.on("error", reject);
|
|
76
|
+
writeStream.on("close", () => {
|
|
77
|
+
if (mode !== undefined) {
|
|
78
|
+
try {
|
|
79
|
+
fs.chmodSync(tmpPath, mode);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
core_1.ux.warn(`Could not set permissions for ${entryPath}: ${errorMessage(error)}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
fs.renameSync(tmpPath, entryPath);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
reject(error);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
resolve();
|
|
93
|
+
});
|
|
94
|
+
entry.pipe(writeStream);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
59
97
|
async function extractZip(dir, stream) {
|
|
98
|
+
const parser = unzip.Parse();
|
|
99
|
+
const writes = [];
|
|
60
100
|
return new Promise((resolve, reject) => {
|
|
61
|
-
stream
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.
|
|
101
|
+
stream.on("error", reject);
|
|
102
|
+
parser.on("error", reject);
|
|
103
|
+
parser.on("entry", (entry) => {
|
|
104
|
+
const entryPath = path.join(dir, entry.path);
|
|
105
|
+
if (entry.type === "Directory") {
|
|
106
|
+
fs.mkdirSync(entryPath, { recursive: true });
|
|
107
|
+
entry.autodrain();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
fs.mkdirSync(path.dirname(entryPath), { recursive: true });
|
|
111
|
+
writes.push(writeEntry(entryPath, entry));
|
|
112
|
+
});
|
|
113
|
+
parser.on("finish", () => Promise.all(writes).then(() => resolve(getBinaryPath(dir)), reject));
|
|
114
|
+
stream.pipe(parser);
|
|
65
115
|
});
|
|
66
116
|
}
|
|
67
117
|
async function extractTar(dir, stream) {
|
|
68
118
|
const extract = tar.extract();
|
|
69
119
|
return new Promise((resolve, reject) => {
|
|
120
|
+
stream.on("error", reject);
|
|
70
121
|
extract.on("error", reject);
|
|
71
122
|
extract.on("entry", (header, stream, next) => {
|
|
72
123
|
const entryPath = path.join(dir, header.name);
|
|
73
124
|
const opts = { mode: header.mode };
|
|
74
125
|
switch (header.type) {
|
|
75
126
|
case "directory":
|
|
76
|
-
|
|
127
|
+
fs_1.default.ensureDir(entryPath, opts);
|
|
77
128
|
next();
|
|
78
129
|
break;
|
|
79
|
-
case "file":
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
writeStream.on("close", () => {
|
|
83
|
-
try {
|
|
84
|
-
fs.chmodSync(entryPath, header.mode || 0o644);
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
core_1.ux.warn(`Could not set permissions for ${entryPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
130
|
+
case "file":
|
|
131
|
+
writeEntry(entryPath, stream, header.mode || 0o644).then(() => next(), reject);
|
|
132
|
+
return;
|
|
92
133
|
case "symlink":
|
|
93
134
|
// ignore symlinks since they will not work on windows
|
|
94
135
|
next();
|
|
@@ -103,18 +144,46 @@ async function extractTar(dir, stream) {
|
|
|
103
144
|
stream.pipe(zlib.createGunzip()).pipe(extract);
|
|
104
145
|
});
|
|
105
146
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
147
|
+
// Aborts the download when no data arrives for DOWNLOAD_STALL_TIMEOUT_MS, since a stalled
|
|
148
|
+
// connection would otherwise never settle.
|
|
149
|
+
async function downloadOnce(dir) {
|
|
150
|
+
const controller = new AbortController();
|
|
151
|
+
let stallTimer;
|
|
152
|
+
const armStallTimer = () => {
|
|
153
|
+
clearTimeout(stallTimer);
|
|
154
|
+
stallTimer = setTimeout(() => controller.abort(), DOWNLOAD_STALL_TIMEOUT_MS);
|
|
155
|
+
};
|
|
156
|
+
armStallTimer();
|
|
157
|
+
try {
|
|
158
|
+
const response = await (0, node_fetch_commonjs_1.default)(getUrl(), { signal: controller.signal });
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
throw new Error(`unexpected response ${response.statusText}`);
|
|
161
|
+
}
|
|
162
|
+
const stream = response.body;
|
|
163
|
+
if (stream == null) {
|
|
164
|
+
throw new Error("unexpected null response body");
|
|
165
|
+
}
|
|
166
|
+
const extraction = os.platform() === WIN32_PLATFORM
|
|
167
|
+
? extractZip(dir, stream)
|
|
168
|
+
: extractTar(dir, stream);
|
|
169
|
+
// Attached after the extractor has piped the body, so no chunk is consumed before it.
|
|
170
|
+
stream.on("data", armStallTimer);
|
|
171
|
+
return await extraction;
|
|
110
172
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
throw new Error("unexpected null response body");
|
|
173
|
+
finally {
|
|
174
|
+
clearTimeout(stallTimer);
|
|
114
175
|
}
|
|
115
|
-
|
|
116
|
-
|
|
176
|
+
}
|
|
177
|
+
async function download(dir) {
|
|
178
|
+
let lastError;
|
|
179
|
+
for (let attempt = 1; attempt <= DOWNLOAD_ATTEMPTS; attempt++) {
|
|
180
|
+
try {
|
|
181
|
+
// eslint-disable-next-line no-await-in-loop
|
|
182
|
+
return await downloadOnce(dir);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
lastError = error;
|
|
186
|
+
}
|
|
117
187
|
}
|
|
118
|
-
|
|
188
|
+
throw new Error(`Could not download the trtc binary after ${DOWNLOAD_ATTEMPTS} attempts: ${errorMessage(lastError)}`);
|
|
119
189
|
}
|
|
120
|
-
exports.download = download;
|
package/dist/util/tunnel.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
|
|
5
|
+
const childProcess = tslib_1.__importStar(require("child_process"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
7
|
const trtc_1 = require("./trtc");
|
|
7
8
|
const utils_1 = require("./utils");
|
|
8
9
|
function randomPort(min, max) {
|
|
@@ -17,12 +18,12 @@ type = "tcp"
|
|
|
17
18
|
remotePort = ${port}
|
|
18
19
|
[proxies.plugin]
|
|
19
20
|
type = "http_proxy"`;
|
|
20
|
-
await
|
|
21
|
+
await fs_1.default.writeFile(configPath, newConfigContent);
|
|
21
22
|
return configPath;
|
|
22
23
|
}
|
|
23
24
|
async function startTrtc(trtc, configPath) {
|
|
24
25
|
return new Promise((resolve, reject) => {
|
|
25
|
-
if (!
|
|
26
|
+
if (!fs_1.default.pathExistsSync(trtc)) {
|
|
26
27
|
reject(new Error(`Binary not found at ${trtc}`));
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
@@ -97,5 +98,5 @@ class Tunnel {
|
|
|
97
98
|
return this.port;
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
exports.default = Tunnel;
|
|
101
101
|
Tunnel.BINARY_DIRECTORY = "trtc";
|
|
102
|
+
exports.default = Tunnel;
|
package/dist/util/type-guards.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isPlainObject = isPlainObject;
|
|
4
|
+
exports.isSignedUrlApi2Response = isSignedUrlApi2Response;
|
|
5
|
+
exports.isCertificateUploadApi2Response = isCertificateUploadApi2Response;
|
|
4
6
|
function isPlainObject(value) {
|
|
5
7
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
8
|
}
|
|
7
|
-
exports.isPlainObject = isPlainObject;
|
|
8
9
|
function isSignedUrlApi2Response(value) {
|
|
9
10
|
return isPlainObject(value) && "status" in value;
|
|
10
11
|
}
|
|
11
|
-
exports.isSignedUrlApi2Response = isSignedUrlApi2Response;
|
|
12
12
|
function isCertificateUploadApi2Response(value) {
|
|
13
13
|
return isPlainObject(value) && "status" in value;
|
|
14
14
|
}
|
|
15
|
-
exports.isCertificateUploadApi2Response = isCertificateUploadApi2Response;
|
package/dist/util/utils.d.ts
CHANGED
|
@@ -3,13 +3,13 @@ export declare const UPLOAD_TIMEOUT_MS: number;
|
|
|
3
3
|
export declare function createDirectory(name: string): Promise<string>;
|
|
4
4
|
export declare function getHomeDir(): string;
|
|
5
5
|
export declare function pathExists(name: string | undefined): Promise<boolean>;
|
|
6
|
-
export declare function isRunningOnCi():
|
|
7
|
-
export declare function rendererToUse(): "
|
|
6
|
+
export declare function isRunningOnCi(): boolean;
|
|
7
|
+
export declare function rendererToUse(): "verbose" | "default";
|
|
8
8
|
export declare function isYamlFile(fileName: string): boolean;
|
|
9
9
|
export declare function isTextFile(fileName: string): boolean;
|
|
10
10
|
export declare function isJsonFile(fileName: string): boolean;
|
|
11
11
|
export declare function isValidFileExtensionToUpload(fileName: string): boolean;
|
|
12
|
-
export declare function getExtensionLength(fileName: string):
|
|
12
|
+
export declare function getExtensionLength(fileName: string): 5 | 4 | 0;
|
|
13
13
|
export declare function removeExtension(fileName: string): string;
|
|
14
14
|
export declare function extractUrlWithoutQueryParams(urlString: string): string;
|
|
15
15
|
export declare function extractRunIdFromDetailsUrl(detailsUrl: string | undefined): string;
|