bdy 1.22.43-dev-distro → 1.22.43-dev
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/distTs/package.json +2 -3
- package/distTs/src/api/client.js +2 -73
- package/distTs/src/cliIndex.js +0 -2
- package/distTs/src/command/login.js +0 -1
- package/distTs/src/command/pipeline/list.js +1 -1
- package/distTs/src/command/project/get.js +18 -0
- package/distTs/src/command/project/set.js +31 -0
- package/distTs/src/command/sandbox/get/yaml.js +30 -0
- package/distTs/src/command/vt/scrape.js +193 -0
- package/distTs/src/input.js +1 -180
- package/distTs/src/output.js +0 -8
- package/distTs/src/texts.js +5 -79
- package/distTs/src/tunnel/tunnel.js +8 -0
- package/package.json +2 -3
- package/distTs/src/command/distro/create.js +0 -40
- package/distTs/src/command/distro/delete.js +0 -38
- package/distTs/src/command/distro/list.js +0 -35
- package/distTs/src/command/distro/route/create.js +0 -50
- package/distTs/src/command/distro/route/delete.js +0 -39
- package/distTs/src/command/distro/route/list.js +0 -45
- package/distTs/src/command/distro/route.js +0 -18
- package/distTs/src/command/distro.js +0 -23
- package/distTs/src/command/pipeline/run/apply.js +0 -62
- package/distTs/src/types/distro.js +0 -232
package/distTs/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bdy",
|
|
3
3
|
"preferGlobal": false,
|
|
4
|
-
"version": "1.22.43-dev
|
|
4
|
+
"version": "1.22.43-dev",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -20,8 +20,7 @@
|
|
|
20
20
|
"e2e:api": "vitest run --config e2e/vitest.config.ts e2e/modules/api/",
|
|
21
21
|
"e2e:pipeline": "vitest run --config e2e/vitest.config.ts e2e/modules/pipeline/",
|
|
22
22
|
"e2e:tunnel": "vitest run --config e2e/vitest.config.ts e2e/modules/tunnel/",
|
|
23
|
-
"e2e:agent": "vitest run --config e2e/vitest.config.ts e2e/modules/agent/"
|
|
24
|
-
"e2e:distro": "vitest run --config e2e/vitest.config.ts e2e/modules/distro/"
|
|
23
|
+
"e2e:agent": "vitest run --config e2e/vitest.config.ts e2e/modules/agent/"
|
|
25
24
|
},
|
|
26
25
|
"files": [
|
|
27
26
|
"distTs"
|
package/distTs/src/api/client.js
CHANGED
|
@@ -240,7 +240,7 @@ class ApiClient {
|
|
|
240
240
|
method: 'PATCH',
|
|
241
241
|
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/yaml`,
|
|
242
242
|
body,
|
|
243
|
-
parseResponseBody: true
|
|
243
|
+
parseResponseBody: true
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
246
|
async createPipeline(workspace, project, body) {
|
|
@@ -248,7 +248,7 @@ class ApiClient {
|
|
|
248
248
|
method: 'POST',
|
|
249
249
|
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines`,
|
|
250
250
|
body,
|
|
251
|
-
parseResponseBody: true
|
|
251
|
+
parseResponseBody: true
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
254
|
async getPipelines(workspace, project, page = 1, perPage = 10) {
|
|
@@ -438,77 +438,6 @@ class ApiClient {
|
|
|
438
438
|
parseResponseBody: false,
|
|
439
439
|
});
|
|
440
440
|
}
|
|
441
|
-
// Distro methods
|
|
442
|
-
async createDistro(workspace, body) {
|
|
443
|
-
return await this.request({
|
|
444
|
-
method: 'POST',
|
|
445
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions`,
|
|
446
|
-
body,
|
|
447
|
-
parseResponseBody: true,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
async deleteRoute(workspace, project, distributionId, routeId) {
|
|
451
|
-
const query = {};
|
|
452
|
-
if (project)
|
|
453
|
-
query.project_name = project;
|
|
454
|
-
return await this.request({
|
|
455
|
-
method: 'DELETE',
|
|
456
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions/${encodeURIComponent(distributionId)}/routes/${encodeURIComponent(routeId)}`,
|
|
457
|
-
query
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
async listRoutes(workspace, project, distributionId) {
|
|
461
|
-
const query = {};
|
|
462
|
-
if (project)
|
|
463
|
-
query.project_name = project;
|
|
464
|
-
return await this.request({
|
|
465
|
-
method: 'GET',
|
|
466
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions/${encodeURIComponent(distributionId)}/routes`,
|
|
467
|
-
query,
|
|
468
|
-
parseResponseBody: true
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
async createRoute(workspace, project, distributionId, body) {
|
|
472
|
-
const query = {};
|
|
473
|
-
if (project)
|
|
474
|
-
query.project_name = project;
|
|
475
|
-
return await this.request({
|
|
476
|
-
method: 'POST',
|
|
477
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions/${encodeURIComponent(distributionId)}/routes`,
|
|
478
|
-
query,
|
|
479
|
-
body,
|
|
480
|
-
parseResponseBody: true,
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
async deleteDistribution(workspace, project, distributionId) {
|
|
484
|
-
const query = {};
|
|
485
|
-
if (project)
|
|
486
|
-
query.project_name = project;
|
|
487
|
-
return await this.request({
|
|
488
|
-
method: 'DELETE',
|
|
489
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions/${encodeURIComponent(distributionId)}`,
|
|
490
|
-
query,
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
async getDistributions(workspace, project) {
|
|
494
|
-
const query = {};
|
|
495
|
-
if (project)
|
|
496
|
-
query.project_name = project;
|
|
497
|
-
return await this.request({
|
|
498
|
-
method: 'GET',
|
|
499
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/distributions`,
|
|
500
|
-
query,
|
|
501
|
-
parseResponseBody: true,
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
async getDistributionByIdentifier(workspace, project, identifier) {
|
|
505
|
-
const q = {
|
|
506
|
-
distribution: identifier,
|
|
507
|
-
};
|
|
508
|
-
if (project)
|
|
509
|
-
q.project = project;
|
|
510
|
-
return await this.getResourceByIdentifier(workspace, q);
|
|
511
|
-
}
|
|
512
441
|
// Sandbox methods
|
|
513
442
|
async createSandbox(workspace, project, body) {
|
|
514
443
|
return await this.request({
|
package/distTs/src/cliIndex.js
CHANGED
|
@@ -24,7 +24,6 @@ const artifact_1 = __importDefault(require("./command/artifact"));
|
|
|
24
24
|
const api_1 = __importDefault(require("./command/api"));
|
|
25
25
|
const domain_1 = __importDefault(require("./command/domain"));
|
|
26
26
|
const main_1 = __importDefault(require("./main"));
|
|
27
|
-
const distro_1 = __importDefault(require("./command/distro"));
|
|
28
27
|
function cliIndex() {
|
|
29
28
|
const program = (0, utils_1.newCommand)('', texts_1.DESC_PROGRAM);
|
|
30
29
|
program.hook('preAction', pre_1.default);
|
|
@@ -41,7 +40,6 @@ function cliIndex() {
|
|
|
41
40
|
program.addCommand(artifact_1.default);
|
|
42
41
|
program.addCommand(sandbox_1.default);
|
|
43
42
|
program.addCommand(domain_1.default);
|
|
44
|
-
program.addCommand(distro_1.default);
|
|
45
43
|
program.addCommand(login_1.default);
|
|
46
44
|
program.addCommand(whoami_1.default);
|
|
47
45
|
program.addCommand(logout_1.default);
|
|
@@ -23,7 +23,7 @@ commandPipelineList.action(async (options) => {
|
|
|
23
23
|
const client = input_1.default.restApiTokenClient();
|
|
24
24
|
const r = await client.getPipelines(workspace, project, page, perPage);
|
|
25
25
|
if (!r.pipelines.length) {
|
|
26
|
-
output_1.default.
|
|
26
|
+
output_1.default.exitError(texts_1.ERR_PIPELINES_NOT_FOUND);
|
|
27
27
|
}
|
|
28
28
|
if (options.format === 'json') {
|
|
29
29
|
output_1.default.json(r.pipelines);
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
const cfg_1 = __importDefault(require("../../tunnel/cfg"));
|
|
7
|
+
const output_1 = __importDefault(require("../../output"));
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const commandProjectGet = (0, utils_1.newCommand)('get', texts_1.DESC_COMMAND_PROJECT_GET);
|
|
11
|
+
commandProjectGet.action(async () => {
|
|
12
|
+
const project = cfg_1.default.getProject();
|
|
13
|
+
if (!project) {
|
|
14
|
+
output_1.default.exitError(texts_1.TXT_PROJECT_NONE);
|
|
15
|
+
}
|
|
16
|
+
output_1.default.exitNormal(project);
|
|
17
|
+
});
|
|
18
|
+
exports.default = commandProjectGet;
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
const cfg_1 = __importDefault(require("../../tunnel/cfg"));
|
|
7
|
+
const output_1 = __importDefault(require("../../output"));
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const input_1 = __importDefault(require("../../input"));
|
|
11
|
+
const commandProjectSet = (0, utils_1.newCommand)('set', texts_1.DESC_COMMAND_PROJECT_SET);
|
|
12
|
+
commandProjectSet.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
13
|
+
commandProjectSet.argument('[project]', texts_1.ARG_COMMAND_PROJECT_NAME);
|
|
14
|
+
commandProjectSet.action(async (project, options) => {
|
|
15
|
+
output_1.default.handleSignals();
|
|
16
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
17
|
+
const client = input_1.default.restApiTokenClient();
|
|
18
|
+
if (project) {
|
|
19
|
+
await client.getProject(workspace, project);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const response = await client.getProjects(workspace);
|
|
23
|
+
project = await output_1.default.selectProject(response.projects);
|
|
24
|
+
}
|
|
25
|
+
cfg_1.default.setProject(project);
|
|
26
|
+
if (!project)
|
|
27
|
+
output_1.default.exitSuccess(texts_1.TXT_PROJECT_SET_CLEARED);
|
|
28
|
+
else
|
|
29
|
+
output_1.default.exitSuccess((0, texts_1.TXT_PROJECT_SET_SUCCESS)(project));
|
|
30
|
+
});
|
|
31
|
+
exports.default = commandProjectSet;
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const texts_1 = require("../../../texts");
|
|
8
|
+
const input_1 = __importDefault(require("../../../input"));
|
|
9
|
+
const output_1 = __importDefault(require("../../../output"));
|
|
10
|
+
const commandSandboxGetYaml = (0, utils_1.newCommand)('yaml', texts_1.DESC_COMMAND_SANDBOX_GET_YAML);
|
|
11
|
+
commandSandboxGetYaml.hideVersionUpdate = true;
|
|
12
|
+
commandSandboxGetYaml.alias('yml');
|
|
13
|
+
commandSandboxGetYaml.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
14
|
+
commandSandboxGetYaml.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
|
|
15
|
+
commandSandboxGetYaml.argument('<identifier>', texts_1.OPTION_SANDBOX_IDENTIFIER);
|
|
16
|
+
commandSandboxGetYaml.action(async (identifier, options) => {
|
|
17
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
18
|
+
const project = input_1.default.restApiProject(options.project);
|
|
19
|
+
const client = input_1.default.restApiTokenClient();
|
|
20
|
+
let result = await client.listSandboxes(workspace, project);
|
|
21
|
+
const sandboxes = result.sandboxes || [];
|
|
22
|
+
const found = sandboxes.find((s) => s.identifier === identifier);
|
|
23
|
+
if (!found) {
|
|
24
|
+
output_1.default.exitError(texts_1.ERR_SANDBOX_NOT_FOUND);
|
|
25
|
+
}
|
|
26
|
+
const sandboxId = found.id;
|
|
27
|
+
result = await client.getSandboxYaml(workspace, sandboxId);
|
|
28
|
+
output_1.default.exitNormal(Buffer.from(result.yaml, 'base64').toString('utf8'));
|
|
29
|
+
});
|
|
30
|
+
exports.default = commandSandboxGetYaml;
|
|
@@ -0,0 +1,193 @@
|
|
|
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
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const validation_1 = require("../../visualTest/validation");
|
|
10
|
+
const output_1 = __importDefault(require("../../output"));
|
|
11
|
+
const requests_1 = require("../../visualTest/requests");
|
|
12
|
+
const zod_1 = require("zod");
|
|
13
|
+
const node_zlib_1 = require("node:zlib");
|
|
14
|
+
const tar_stream_1 = __importDefault(require("tar-stream"));
|
|
15
|
+
const promises_1 = require("node:stream/promises");
|
|
16
|
+
const node_fs_1 = require("node:fs");
|
|
17
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
18
|
+
const promises_2 = require("node:fs/promises");
|
|
19
|
+
const commandScrape = (0, utils_1.newCommand)('scrape', texts_1.DESC_COMMAND_VT_SCRAPE);
|
|
20
|
+
commandScrape.argument('<url>', texts_1.OPTION_SCRAPE_URL);
|
|
21
|
+
commandScrape.option('--follow', texts_1.OPTION_SCRAPE_FOLLOW, false);
|
|
22
|
+
commandScrape.addOption(new commander_1.Option('--outputType <type>', texts_1.OPTION_SCRAPE_OUTPUT_TYPE)
|
|
23
|
+
.choices(['jpeg', 'png', 'md', 'html'])
|
|
24
|
+
.makeOptionMandatory());
|
|
25
|
+
commandScrape.option('--quality <quality>', texts_1.OPTION_SCRAPE_QUALITY);
|
|
26
|
+
commandScrape.option('--fullPage', texts_1.OPTION_SCRAPE_FULL_PAGE, false);
|
|
27
|
+
commandScrape.option('--cssSelector <selector>', texts_1.OPTION_SCRAPE_CSS_SELECTOR);
|
|
28
|
+
commandScrape.option('--xpathSelector <selector>', texts_1.OPTION_SCRAPE_XPATH_SELECTOR);
|
|
29
|
+
commandScrape.addOption(new commander_1.Option('--browser <browser>', texts_1.OPTION_SCRAPE_BROWSER)
|
|
30
|
+
.choices(['chrome', 'firefox', 'safari'])
|
|
31
|
+
.default('chrome'));
|
|
32
|
+
commandScrape.option('--viewport <viewport>', texts_1.OPTION_SCRAPE_VIEWPORT, '1920x1080');
|
|
33
|
+
commandScrape.option('--devicePixelRatio <ratio>', texts_1.OPTION_SCRAPE_DEVICE_PIXEL_RATIO, '1');
|
|
34
|
+
commandScrape.option('--waitForElement <selector>', texts_1.OPTION_SCRAPE_WAIT_FOR_ELEMENT);
|
|
35
|
+
commandScrape.option('--darkMode', texts_1.OPTION_SCRAPE_DARK_MODE, false);
|
|
36
|
+
commandScrape.option('--delay <delay>', texts_1.OPTION_SCRAPE_DELAY, '0');
|
|
37
|
+
commandScrape.option('--outputDir <dir>', texts_1.OPTION_SCRAPE_OUTPUT_DIR, '.');
|
|
38
|
+
commandScrape.action(async (inputUrl, options) => {
|
|
39
|
+
if (!(0, validation_1.checkToken)()) {
|
|
40
|
+
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
41
|
+
}
|
|
42
|
+
const { url, follow, outputType, quality, outputDir, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement, } = validateInputAndOptions(inputUrl, options);
|
|
43
|
+
try {
|
|
44
|
+
const { buildId } = await (0, requests_1.sendScrap)(url, outputType, follow, quality, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement);
|
|
45
|
+
output_1.default.normal('Starting scrape session');
|
|
46
|
+
const status = await watchSessionStatus(buildId);
|
|
47
|
+
if (!status.ok) {
|
|
48
|
+
output_1.default.exitError(`Unexpected error while watching session status: ${status.error}`);
|
|
49
|
+
}
|
|
50
|
+
output_1.default.normal('Downloading scrape package');
|
|
51
|
+
const scrapPackageStream = await (0, requests_1.downloadScrapPackage)(buildId);
|
|
52
|
+
const brotliDecompressor = (0, node_zlib_1.createBrotliDecompress)();
|
|
53
|
+
const unpack = tar_stream_1.default.extract();
|
|
54
|
+
unpack.on('entry', async (header, stream, next) => {
|
|
55
|
+
const currentDir = process.cwd();
|
|
56
|
+
const preparedOutputDir = outputDir.startsWith('.')
|
|
57
|
+
? node_path_1.default.join(currentDir, outputDir)
|
|
58
|
+
: outputDir;
|
|
59
|
+
const newFilePath = node_path_1.default.join(preparedOutputDir, header.name);
|
|
60
|
+
try {
|
|
61
|
+
if (header.type === 'file') {
|
|
62
|
+
await (0, promises_2.mkdir)(node_path_1.default.dirname(newFilePath), { recursive: true });
|
|
63
|
+
const fileWriteStream = (0, node_fs_1.createWriteStream)(newFilePath);
|
|
64
|
+
await (0, promises_1.pipeline)(stream, fileWriteStream);
|
|
65
|
+
next();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
stream.resume();
|
|
69
|
+
next();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (entryError) {
|
|
73
|
+
output_1.default.error(`Error processing entry ${header.name}: ${entryError}`);
|
|
74
|
+
next(entryError);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await (0, promises_1.pipeline)(scrapPackageStream, brotliDecompressor, unpack);
|
|
78
|
+
output_1.default.exitSuccess('Downloading scrape package finished');
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
output_1.default.exitError(`${error}`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
function validateInputAndOptions(input, options) {
|
|
85
|
+
const urlSchema = zod_1.z.string().url();
|
|
86
|
+
const optionsSchema = zod_1.z.object({
|
|
87
|
+
follow: zod_1.z.boolean(),
|
|
88
|
+
outputType: zod_1.z.enum(['jpeg', 'png', 'md', 'html']),
|
|
89
|
+
quality: zod_1.z.coerce.number().min(1).max(100).optional(),
|
|
90
|
+
outputDir: zod_1.z.string().default('.'),
|
|
91
|
+
fullPage: zod_1.z.boolean().optional(),
|
|
92
|
+
cssSelector: zod_1.z.string().optional(),
|
|
93
|
+
xpathSelector: zod_1.z.string().optional(),
|
|
94
|
+
browser: zod_1.z.enum(['chrome', 'firefox', 'safari']),
|
|
95
|
+
viewport: zod_1.z
|
|
96
|
+
.string()
|
|
97
|
+
.refine((value) => {
|
|
98
|
+
const [width, height] = value.split('x');
|
|
99
|
+
return (width &&
|
|
100
|
+
height &&
|
|
101
|
+
!isNaN(Number(width)) &&
|
|
102
|
+
!isNaN(Number(height)) &&
|
|
103
|
+
Number(width) > 0 &&
|
|
104
|
+
Number(height) > 0);
|
|
105
|
+
}, 'Invalid viewport format, example: 1920x1080')
|
|
106
|
+
.transform((value) => {
|
|
107
|
+
const [width, height] = value.split('x');
|
|
108
|
+
return {
|
|
109
|
+
width: Number(width),
|
|
110
|
+
height: Number(height),
|
|
111
|
+
};
|
|
112
|
+
}),
|
|
113
|
+
devicePixelRatio: zod_1.z.coerce.number().min(1).max(4),
|
|
114
|
+
darkMode: zod_1.z.boolean(),
|
|
115
|
+
delay: zod_1.z.coerce.number().min(0).max(10000),
|
|
116
|
+
waitForElement: zod_1.z.string().optional(),
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
const url = urlSchema.parse(input);
|
|
120
|
+
const { follow, outputType, quality, outputDir, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement, } = optionsSchema.parse(options);
|
|
121
|
+
if (typeof quality === 'number' && outputType !== 'jpeg') {
|
|
122
|
+
output_1.default.exitError('Quality is only supported for jpeg output type, use --outputType jpeg');
|
|
123
|
+
}
|
|
124
|
+
if (cssSelector && xpathSelector) {
|
|
125
|
+
output_1.default.exitError('Only one of --cssSelector or --xpathSelector can be used');
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
url,
|
|
129
|
+
follow,
|
|
130
|
+
outputType,
|
|
131
|
+
quality,
|
|
132
|
+
outputDir,
|
|
133
|
+
fullPage,
|
|
134
|
+
cssSelector,
|
|
135
|
+
xpathSelector,
|
|
136
|
+
browser,
|
|
137
|
+
viewport,
|
|
138
|
+
devicePixelRatio,
|
|
139
|
+
darkMode,
|
|
140
|
+
delay,
|
|
141
|
+
waitForElement,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (error instanceof zod_1.ZodError) {
|
|
146
|
+
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function watchSessionStatus(buildId) {
|
|
154
|
+
return new Promise((resolve) => {
|
|
155
|
+
const eventSource = (0, requests_1.connectToScrapSession)(buildId);
|
|
156
|
+
eventSource.addEventListener('SESSION_STATUS', (event) => {
|
|
157
|
+
const data = JSON.parse(event.data);
|
|
158
|
+
if (data.status === 'GATHER_URLS_COMPLETED') {
|
|
159
|
+
output_1.default.normal(`Gathering URLs completed, found ${data.text} URLs`);
|
|
160
|
+
}
|
|
161
|
+
else if (data.status === 'GATHER_URLS_FAILED') {
|
|
162
|
+
output_1.default.error('Gathering URLs failed');
|
|
163
|
+
}
|
|
164
|
+
else if (data.status === 'SCRAPE_URL_COMPLETED') {
|
|
165
|
+
output_1.default.normal(`Scraping ${data.text} completed`);
|
|
166
|
+
}
|
|
167
|
+
else if (data.status === 'SCRAPE_URL_FAILED') {
|
|
168
|
+
output_1.default.error(`Scraping ${data.text} failed`);
|
|
169
|
+
}
|
|
170
|
+
else if (data.status === 'CREATE_PACKAGE_COMPLETED') {
|
|
171
|
+
output_1.default.normal('Package created');
|
|
172
|
+
}
|
|
173
|
+
else if (data.status === 'CREATE_PACKAGE_FAILED') {
|
|
174
|
+
output_1.default.error('Package creation failed');
|
|
175
|
+
}
|
|
176
|
+
else if (data.status === 'FINISHED') {
|
|
177
|
+
eventSource.close();
|
|
178
|
+
output_1.default.normal('Scrape session finished');
|
|
179
|
+
resolve({ ok: true });
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
eventSource.addEventListener('error', (event) => {
|
|
183
|
+
if (event.code) {
|
|
184
|
+
eventSource.close();
|
|
185
|
+
if (event.code === 410) {
|
|
186
|
+
output_1.default.normal('Scrape session finished');
|
|
187
|
+
}
|
|
188
|
+
resolve({ ok: event.code === 410, error: event.code });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
exports.default = commandScrape;
|
package/distTs/src/input.js
CHANGED
|
@@ -50,7 +50,6 @@ const node_path_1 = __importStar(require("node:path"));
|
|
|
50
50
|
const cfg_1 = __importDefault(require("./tunnel/cfg"));
|
|
51
51
|
const uuid_1 = require("uuid");
|
|
52
52
|
const sandbox_1 = require("./types/sandbox");
|
|
53
|
-
const distro_1 = require("./types/distro");
|
|
54
53
|
class Input {
|
|
55
54
|
static timeout(timeout) {
|
|
56
55
|
const t = parseInt(timeout, 10);
|
|
@@ -342,25 +341,11 @@ class Input {
|
|
|
342
341
|
const baseUrl = this.restApiBaseUrl(api, region, t);
|
|
343
342
|
return new ApiClient(baseUrl, t, refreshToken, clientId, clientSecret, clientToken);
|
|
344
343
|
}
|
|
345
|
-
static routeType(type) {
|
|
346
|
-
if (!type)
|
|
347
|
-
return distro_1.ROUTE_TYPE.PROXY;
|
|
348
|
-
if (Object.values(distro_1.ROUTE_TYPE).includes(type)) {
|
|
349
|
-
return type;
|
|
350
|
-
}
|
|
351
|
-
output_1.default.exitError(texts_1.ERR_COMMAND_ROUTE_TYPE);
|
|
352
|
-
}
|
|
353
|
-
static routePath(path) {
|
|
354
|
-
if (!path)
|
|
355
|
-
return '';
|
|
356
|
-
return path.replace(/^\/+/, '');
|
|
357
|
-
}
|
|
358
344
|
static artifactType(type) {
|
|
359
345
|
if (!type)
|
|
360
346
|
return utils_1.ARTIFACT_TYPE.BUCKET;
|
|
361
|
-
if (Object.values(utils_1.ARTIFACT_TYPE).includes(type))
|
|
347
|
+
if (Object.values(utils_1.ARTIFACT_TYPE).includes(type))
|
|
362
348
|
return type;
|
|
363
|
-
}
|
|
364
349
|
output_1.default.exitError(texts_1.ERR_COMMAND_ARTIFACT_TYPE);
|
|
365
350
|
}
|
|
366
351
|
static artifactScope(project) {
|
|
@@ -504,154 +489,6 @@ class Input {
|
|
|
504
489
|
});
|
|
505
490
|
return list;
|
|
506
491
|
}
|
|
507
|
-
static async routeTarget(client, workspace, project, targetList) {
|
|
508
|
-
if (!targetList || !Array.isArray(targetList) || !targetList.length) {
|
|
509
|
-
output_1.default.exitError(texts_1.ERR_COMMAND_ROUTE_NO_TARGET);
|
|
510
|
-
}
|
|
511
|
-
const targets = {};
|
|
512
|
-
const SEP = '\x00';
|
|
513
|
-
for (let j = 0; j < targetList.length; j += 1) {
|
|
514
|
-
const str = targetList[j];
|
|
515
|
-
let type = null;
|
|
516
|
-
let url = '';
|
|
517
|
-
let artifact = '';
|
|
518
|
-
let sandbox = '';
|
|
519
|
-
let region = null;
|
|
520
|
-
const parts = str
|
|
521
|
-
.replace(/\\,/g, SEP)
|
|
522
|
-
.split(',')
|
|
523
|
-
.map((p) => p.split(SEP).join(','));
|
|
524
|
-
for (let i = 0; i < parts.length; i += 1) {
|
|
525
|
-
const p = parts[i];
|
|
526
|
-
const idx = p.indexOf('=');
|
|
527
|
-
if (idx < 0) {
|
|
528
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'No key=val delimiter'));
|
|
529
|
-
}
|
|
530
|
-
const key = p.substring(0, idx).trim();
|
|
531
|
-
const val = p.substring(idx + 1).trim();
|
|
532
|
-
if (key === 'url' && val) {
|
|
533
|
-
if (url || type !== null) {
|
|
534
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Param url defined twice'));
|
|
535
|
-
}
|
|
536
|
-
type = distro_1.ROUTE_TARGET_TYPE.EXTERNAL;
|
|
537
|
-
url = val;
|
|
538
|
-
}
|
|
539
|
-
else if (key === 'artifact' && val) {
|
|
540
|
-
if (artifact || type !== null) {
|
|
541
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Param artifact defined twice'));
|
|
542
|
-
}
|
|
543
|
-
type = distro_1.ROUTE_TARGET_TYPE.ARTIFACT;
|
|
544
|
-
artifact = val;
|
|
545
|
-
}
|
|
546
|
-
else if (key === 'sandbox' && val) {
|
|
547
|
-
if (sandbox || type !== null) {
|
|
548
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Param sandbox defined twice'));
|
|
549
|
-
}
|
|
550
|
-
type = distro_1.ROUTE_TARGET_TYPE.SANDBOX;
|
|
551
|
-
sandbox = val;
|
|
552
|
-
}
|
|
553
|
-
else if (key === 'region' && val) {
|
|
554
|
-
if (region) {
|
|
555
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Param region defined twice'));
|
|
556
|
-
}
|
|
557
|
-
const match = Object.values(distro_1.ROUTE_REGION).find((r) => r.toLowerCase() === val.toLowerCase());
|
|
558
|
-
if (match) {
|
|
559
|
-
region = match;
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Wrong value of region'));
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Unknown param'));
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
if (!type) {
|
|
570
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Unrecognized type'));
|
|
571
|
-
}
|
|
572
|
-
if (!region) {
|
|
573
|
-
region = distro_1.ROUTE_REGION.Default;
|
|
574
|
-
}
|
|
575
|
-
if (targets[region]) {
|
|
576
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Region already used by another target'));
|
|
577
|
-
}
|
|
578
|
-
let target;
|
|
579
|
-
if (type === distro_1.ROUTE_TARGET_TYPE.EXTERNAL) {
|
|
580
|
-
target = {
|
|
581
|
-
type,
|
|
582
|
-
external_url: url,
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
else if (type === distro_1.ROUTE_TARGET_TYPE.ARTIFACT) {
|
|
586
|
-
const idx = artifact.indexOf(':');
|
|
587
|
-
if (idx < 0) {
|
|
588
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'artifact wrong format (identifier:version)'));
|
|
589
|
-
}
|
|
590
|
-
const identifier = artifact.substring(0, idx).trim();
|
|
591
|
-
const version = artifact.substring(idx + 1).trim();
|
|
592
|
-
if (!identifier || !version) {
|
|
593
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'artifact wrong format (identifier:version)'));
|
|
594
|
-
}
|
|
595
|
-
let result = await client.getArtifactVersionByIdentifier(workspace, project, identifier, version);
|
|
596
|
-
if (!result.artifact_id && project) {
|
|
597
|
-
// try in workspace scope
|
|
598
|
-
result = await client.getArtifactVersionByIdentifier(workspace, null, identifier, version);
|
|
599
|
-
}
|
|
600
|
-
if (!result.domain) {
|
|
601
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, texts_1.ERR_WORKSPACE_NOT_FOUND));
|
|
602
|
-
}
|
|
603
|
-
if (!result.artifact_id) {
|
|
604
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, texts_1.ERR_ARTIFACT_NOT_FOUND));
|
|
605
|
-
}
|
|
606
|
-
if (!result.artifact_version_id) {
|
|
607
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, texts_1.ERR_ARTIFACT_VERSION_NOT_FOUND));
|
|
608
|
-
}
|
|
609
|
-
target = {
|
|
610
|
-
type,
|
|
611
|
-
artifact: {
|
|
612
|
-
id: result.artifact_id,
|
|
613
|
-
version_id: result.artifact_version_id,
|
|
614
|
-
},
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
else if (type === distro_1.ROUTE_TARGET_TYPE.SANDBOX) {
|
|
618
|
-
const idx = sandbox.indexOf(':');
|
|
619
|
-
if (idx < 0) {
|
|
620
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'sandbox wrong format (identifier:endpoint)'));
|
|
621
|
-
}
|
|
622
|
-
const identifier = sandbox.substring(0, idx).trim();
|
|
623
|
-
const endpoint = sandbox.substring(idx + 1).trim();
|
|
624
|
-
if (!identifier || !endpoint) {
|
|
625
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'sandbox wrong format (identifier:endpoint)'));
|
|
626
|
-
}
|
|
627
|
-
if (!project) {
|
|
628
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'sandbox target can be used only in project'));
|
|
629
|
-
}
|
|
630
|
-
const result = await client.getSandboxByIdentifier(workspace, project, identifier);
|
|
631
|
-
if (!result.domain) {
|
|
632
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, texts_1.ERR_WORKSPACE_NOT_FOUND));
|
|
633
|
-
}
|
|
634
|
-
if (!result.sandbox_id) {
|
|
635
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, texts_1.ERR_SANDBOX_NOT_FOUND));
|
|
636
|
-
}
|
|
637
|
-
target = {
|
|
638
|
-
type,
|
|
639
|
-
sandbox: {
|
|
640
|
-
id: result.sandbox_id,
|
|
641
|
-
endpoint: endpoint,
|
|
642
|
-
},
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
else {
|
|
646
|
-
output_1.default.exitError((0, texts_1.ERR_WRONG_ROUTE_TARGET)(str, 'Unknown target type'));
|
|
647
|
-
}
|
|
648
|
-
targets[region] = target;
|
|
649
|
-
}
|
|
650
|
-
if (!targets[distro_1.ROUTE_REGION.Default]) {
|
|
651
|
-
output_1.default.exitError(texts_1.ERR_ROUTE_NO_DEFAULT);
|
|
652
|
-
}
|
|
653
|
-
return targets;
|
|
654
|
-
}
|
|
655
492
|
static sandboxFetch(fetchList) {
|
|
656
493
|
const fetch = [];
|
|
657
494
|
const SEP = '\x00';
|
|
@@ -1035,22 +872,6 @@ class Input {
|
|
|
1035
872
|
output_1.default.exitError(texts_1.ERR_API_WRONG_METHOD);
|
|
1036
873
|
return null;
|
|
1037
874
|
}
|
|
1038
|
-
static distroScope(project, scope) {
|
|
1039
|
-
if (scope) {
|
|
1040
|
-
if (scope === distro_1.DISTRO_SCOPE.WORKSPACE) {
|
|
1041
|
-
return scope;
|
|
1042
|
-
}
|
|
1043
|
-
if (scope === distro_1.DISTRO_SCOPE.PROJECT) {
|
|
1044
|
-
if (!project)
|
|
1045
|
-
output_1.default.exitError(texts_1.ERR_COMMAND_DISTRO_NO_PROJECT);
|
|
1046
|
-
return scope;
|
|
1047
|
-
}
|
|
1048
|
-
return output_1.default.exitError(texts_1.ERR_COMMAND_DISTRO_SCOPE);
|
|
1049
|
-
}
|
|
1050
|
-
if (project)
|
|
1051
|
-
return distro_1.DISTRO_SCOPE.PROJECT;
|
|
1052
|
-
return distro_1.DISTRO_SCOPE.WORKSPACE;
|
|
1053
|
-
}
|
|
1054
875
|
static restApiProject(project, allowNull) {
|
|
1055
876
|
const ProjectCfg = require('./project/cfg').default;
|
|
1056
877
|
let p = process.env.BUDDY_PROJECT;
|
package/distTs/src/output.js
CHANGED
|
@@ -158,14 +158,6 @@ class Output {
|
|
|
158
158
|
static cyan(txt, newLine = true) {
|
|
159
159
|
this.normal(this.getCyanColor(txt), newLine);
|
|
160
160
|
}
|
|
161
|
-
static identifier(identifier) {
|
|
162
|
-
Output.dim('Identifier: ', false);
|
|
163
|
-
Output.cyan(identifier);
|
|
164
|
-
}
|
|
165
|
-
static id(id) {
|
|
166
|
-
Output.dim('Id: ', false);
|
|
167
|
-
Output.cyan(id);
|
|
168
|
-
}
|
|
169
161
|
static debug(txt) {
|
|
170
162
|
const { debug } = require('./visualTest/context');
|
|
171
163
|
if (debug) {
|