bdy 1.19.1-dev-pipeline → 1.19.2-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 +1 -1
- package/distTs/src/api/client.js +2 -61
- package/distTs/src/command/pipeline/run.js +125 -22
- package/distTs/src/command/project/get.js +18 -0
- package/distTs/src/command/project/link.js +11 -11
- 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 +31 -14
- package/distTs/src/output.js +31 -149
- package/distTs/src/texts.js +33 -55
- package/distTs/src/tunnel/output/interactive/tunnel.js +2 -2
- package/package.json +1 -1
- package/distTs/src/command/crawl/link.js +0 -61
- package/distTs/src/command/crawl/run.js +0 -147
- package/distTs/src/command/crawl/validation.js +0 -154
- package/distTs/src/command/crawl.js +0 -13
- package/distTs/src/command/pipeline/run/apply.js +0 -62
- package/distTs/src/command/pipeline/run/approve.js +0 -62
- package/distTs/src/command/pipeline/run/cancel.js +0 -36
- package/distTs/src/command/pipeline/run/list.js +0 -52
- package/distTs/src/command/pipeline/run/logs.js +0 -37
- package/distTs/src/command/pipeline/run/retry.js +0 -36
- package/distTs/src/command/pipeline/run/start.js +0 -96
- package/distTs/src/command/pipeline/run/status.js +0 -35
- package/distTs/src/command/tests/capture/validation.js +0 -46
- package/distTs/src/command/tests/capture.js +0 -103
- package/distTs/src/command/tests/unit/link.js +0 -61
- package/distTs/src/command/tests/unit/upload.js +0 -91
- package/distTs/src/command/tests/unit.js +0 -13
- package/distTs/src/command/tests/visual/link.js +0 -61
- package/distTs/src/command/tests/visual/session/close.js +0 -32
- package/distTs/src/command/tests/visual/session/create.js +0 -86
- package/distTs/src/command/tests/visual/session.js +0 -13
- package/distTs/src/command/tests/visual/setup.js +0 -20
- package/distTs/src/command/tests/visual/shared/validation.js +0 -145
- package/distTs/src/command/tests/visual/upload.js +0 -141
- package/distTs/src/command/tests/visual.js +0 -17
- package/distTs/src/command/tests.js +0 -15
- package/distTs/src/crawl/requests.js +0 -141
- package/distTs/src/output/pipeline.js +0 -1527
- package/distTs/src/types/crawl.js +0 -2
- package/distTs/src/types/pipeline.js +0 -424
- package/distTs/src/unitTest/context.js +0 -26
package/distTs/package.json
CHANGED
package/distTs/src/api/client.js
CHANGED
|
@@ -216,37 +216,6 @@ class ApiClient {
|
|
|
216
216
|
throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
-
async getPipelineRunActionLogs(workspace, project, pipelineId, executionId, actionExecutionId, offset, limit) {
|
|
220
|
-
const query = {
|
|
221
|
-
offset: String(offset),
|
|
222
|
-
limit: String(limit),
|
|
223
|
-
};
|
|
224
|
-
return await this.request({
|
|
225
|
-
method: 'GET',
|
|
226
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(executionId)}/action_executions/${encodeURIComponent(actionExecutionId)}/logs`,
|
|
227
|
-
query,
|
|
228
|
-
parseResponseBody: true,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
async getPipelineRunActionExecution(workspace, project, pipelineId, executionId, actionExecutionId) {
|
|
232
|
-
return await this.request({
|
|
233
|
-
method: 'GET',
|
|
234
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(executionId)}/action_executions/${encodeURIComponent(actionExecutionId)}`,
|
|
235
|
-
parseResponseBody: true,
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
async getPipelineRuns(workspace, project, pipelineId, page = 1, perPage = 10) {
|
|
239
|
-
const query = {
|
|
240
|
-
page: String(page),
|
|
241
|
-
per_page: String(perPage),
|
|
242
|
-
};
|
|
243
|
-
return await this.request({
|
|
244
|
-
method: 'GET',
|
|
245
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions`,
|
|
246
|
-
query,
|
|
247
|
-
parseResponseBody: true,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
219
|
async getPipelineRun(workspace, project, pipelineId, executionId) {
|
|
251
220
|
return await this.request({
|
|
252
221
|
method: 'GET',
|
|
@@ -287,34 +256,6 @@ class ApiClient {
|
|
|
287
256
|
parseResponseBody: true,
|
|
288
257
|
});
|
|
289
258
|
}
|
|
290
|
-
async pipelineRunRetry(workspace, project, pipelineId, runId) {
|
|
291
|
-
return await this.request({
|
|
292
|
-
method: 'PATCH',
|
|
293
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(runId)}`,
|
|
294
|
-
body: {
|
|
295
|
-
operation: 'RETRY',
|
|
296
|
-
},
|
|
297
|
-
parseResponseBody: true,
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
async pipelineRunApply(workspace, project, pipelineId, runId, body) {
|
|
301
|
-
return await this.request({
|
|
302
|
-
method: 'PATCH',
|
|
303
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(runId)}`,
|
|
304
|
-
body,
|
|
305
|
-
parseResponseBody: true,
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
async pipelineRunCancel(workspace, project, pipelineId, runId) {
|
|
309
|
-
return await this.request({
|
|
310
|
-
method: 'PATCH',
|
|
311
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(runId)}`,
|
|
312
|
-
body: {
|
|
313
|
-
operation: 'CANCEL',
|
|
314
|
-
},
|
|
315
|
-
parseResponseBody: true,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
259
|
async pipelineRun(workspace, project, pipelineId, body) {
|
|
319
260
|
return await this.request({
|
|
320
261
|
method: 'POST',
|
|
@@ -780,14 +721,14 @@ class ApiClient {
|
|
|
780
721
|
return await this.request({
|
|
781
722
|
method: 'POST',
|
|
782
723
|
path: `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/apps/${encodeURIComponent(appId)}/stop`,
|
|
783
|
-
parseResponseBody: true
|
|
724
|
+
parseResponseBody: true
|
|
784
725
|
});
|
|
785
726
|
}
|
|
786
727
|
async startSandboxApp(workspace, sandboxId, appId) {
|
|
787
728
|
return await this.request({
|
|
788
729
|
method: 'POST',
|
|
789
730
|
path: `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/apps/${encodeURIComponent(appId)}/start`,
|
|
790
|
-
parseResponseBody: true
|
|
731
|
+
parseResponseBody: true
|
|
791
732
|
});
|
|
792
733
|
}
|
|
793
734
|
async getSandboxAppLogs(workspace, sandboxId, appId, cursor) {
|
|
@@ -5,27 +5,130 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const texts_1 = require("../../texts");
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const cancel_1 = __importDefault(require("./run/cancel"));
|
|
12
|
-
const retry_1 = __importDefault(require("./run/retry"));
|
|
13
|
-
const list_1 = __importDefault(require("./run/list"));
|
|
14
|
-
const approve_1 = __importDefault(require("./run/approve"));
|
|
8
|
+
const output_1 = __importDefault(require("../../output"));
|
|
9
|
+
const input_1 = __importDefault(require("../../input"));
|
|
10
|
+
const format_1 = __importDefault(require("../../format"));
|
|
15
11
|
const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_PIPELINE_RUN);
|
|
16
|
-
commandPipelineRun.
|
|
17
|
-
commandPipelineRun.
|
|
18
|
-
commandPipelineRun.
|
|
19
|
-
commandPipelineRun.
|
|
20
|
-
commandPipelineRun.
|
|
21
|
-
commandPipelineRun.
|
|
22
|
-
commandPipelineRun.
|
|
23
|
-
commandPipelineRun.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
commandPipelineRun.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
13
|
+
commandPipelineRun.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
|
|
14
|
+
commandPipelineRun.option('-b, --branch <branch>', texts_1.OPTION_PIPELINE_RUN_BRANCH);
|
|
15
|
+
commandPipelineRun.option('-t, --tag <tag>', texts_1.OPTION_PIPELINE_RUN_TAG);
|
|
16
|
+
commandPipelineRun.option('-pr, --pull-request <pull request>', texts_1.OPTION_PIPELINE_RUN_PULL_REQUEST);
|
|
17
|
+
commandPipelineRun.option('-r, --revision <revision>', texts_1.OPTION_PIPELINE_RUN_REVISION);
|
|
18
|
+
commandPipelineRun.option('--comment <comment>', texts_1.OPTION_PIPELINE_RUN_COMMENT);
|
|
19
|
+
commandPipelineRun.option('-f, --refresh', texts_1.OPTION_PIPELINE_RUN_REFRESH);
|
|
20
|
+
commandPipelineRun.option('-c, --clear-cache', texts_1.OPTION_PIPELINE_RUN_CLEAR_CACHE);
|
|
21
|
+
commandPipelineRun.option('--priority <priority>', texts_1.OPTION_PIPELINE_RUN_PRIORITY);
|
|
22
|
+
commandPipelineRun.option('-v, --variable <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
23
|
+
commandPipelineRun.option('-vm, --variable-masked <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
24
|
+
commandPipelineRun.option('--schedule <date>', texts_1.OPTION_PIPELINE_RUN_DELAY);
|
|
25
|
+
commandPipelineRun.option('--action <actions...>', texts_1.OPTION_PIPELINE_RUN_ACTION);
|
|
26
|
+
commandPipelineRun.option('--wait [minutes]', texts_1.OPTION_PIPELINE_RUN_WAIT);
|
|
27
|
+
commandPipelineRun.argument('<identifier>', texts_1.OPTION_PIPELINE_RUN_ARGUMENT);
|
|
28
|
+
commandPipelineRun.usage('<identifier> [options]');
|
|
29
|
+
commandPipelineRun.addHelpText('after', texts_1.EXAMPLE_PIPELINE_RUN);
|
|
30
|
+
commandPipelineRun.action(async (identifier, options) => {
|
|
31
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
32
|
+
const project = input_1.default.restApiProject(options.project);
|
|
33
|
+
const client = input_1.default.restApiTokenClient();
|
|
34
|
+
const data = await client.getPipelineByIdentifier(workspace, project, identifier);
|
|
35
|
+
if (!data || !data.domain) {
|
|
36
|
+
output_1.default.exitError(texts_1.ERR_WORKSPACE_NOT_FOUND);
|
|
37
|
+
}
|
|
38
|
+
if (!data.project_identifier) {
|
|
39
|
+
output_1.default.exitError(texts_1.ERR_PROJECT_NOT_FOUND);
|
|
40
|
+
}
|
|
41
|
+
if (!data.pipeline_id) {
|
|
42
|
+
output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
|
|
43
|
+
}
|
|
44
|
+
const body = {};
|
|
45
|
+
if (options.branch) {
|
|
46
|
+
body.branch = {
|
|
47
|
+
name: options.branch,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (options.tag) {
|
|
51
|
+
body.tag = {
|
|
52
|
+
name: options.tag,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (options.pullRequest) {
|
|
56
|
+
body.pull_request = {
|
|
57
|
+
name: `pull/${options.pullRequest}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (options.revision) {
|
|
61
|
+
body.to_revision = {
|
|
62
|
+
revision: options.revision,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (options.comment) {
|
|
66
|
+
body.comment = options.comment;
|
|
67
|
+
}
|
|
68
|
+
if (options.refresh) {
|
|
69
|
+
body.refresh = true;
|
|
70
|
+
}
|
|
71
|
+
if (options.clearCache) {
|
|
72
|
+
body.clear_cache = true;
|
|
73
|
+
}
|
|
74
|
+
const priority = input_1.default.pipelineRunPriority(options.priority);
|
|
75
|
+
if (priority) {
|
|
76
|
+
body.priority = priority;
|
|
77
|
+
}
|
|
78
|
+
body.variables = [];
|
|
79
|
+
if (options.variable) {
|
|
80
|
+
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variable, false));
|
|
81
|
+
}
|
|
82
|
+
if (options.variableMasked) {
|
|
83
|
+
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variableMasked, true));
|
|
84
|
+
}
|
|
85
|
+
const delay = input_1.default.pipelineRunDelay(options.schedule);
|
|
86
|
+
if (delay) {
|
|
87
|
+
body.delay_until = delay;
|
|
88
|
+
}
|
|
89
|
+
const actions = input_1.default.pipelineRunAction(options.action);
|
|
90
|
+
if (actions) {
|
|
91
|
+
body.actions_to_run = actions;
|
|
92
|
+
}
|
|
93
|
+
const result = await client.pipelineRun(workspace, project, data.pipeline_id, body);
|
|
94
|
+
if (options.wait) {
|
|
95
|
+
const minutes = input_1.default.pipelineRunWaitTime(options.wait);
|
|
96
|
+
wait(minutes, workspace, project, data.pipeline_id, result.id, result.html_url, client);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
output_1.default.exitSuccess((0, texts_1.TXT_PIPELINE_RUN_SUCCESS)(result.html_url));
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const wait = (minutes, workspace, project, pipelineId, runId, htmlUrl, client) => {
|
|
103
|
+
const start = Date.now();
|
|
104
|
+
output_1.default.normal((0, texts_1.TXT_PIPELINE_RUN_WAIT)(minutes));
|
|
105
|
+
let fetchCounter = 1;
|
|
106
|
+
const ts1 = setTimeout(() => {
|
|
107
|
+
output_1.default.exitError(texts_1.ERR_RUN_PIPELINE_WAIT_TIMEOUT);
|
|
108
|
+
}, minutes * 60 * 1000);
|
|
109
|
+
const ts2 = setInterval(async () => {
|
|
110
|
+
output_1.default.clearPreviousLine();
|
|
111
|
+
output_1.default.normal((0, texts_1.TXT_PIPELINE_RUN_STILL_WAITING)(formatWaitTime(start)));
|
|
112
|
+
if (fetchCounter >= 3) {
|
|
113
|
+
const run = await client.getPipelineRun(workspace, project, pipelineId, runId);
|
|
114
|
+
if (!['INPROGRESS', 'ENQUEUED', 'TERMINATING'].includes(run.status)) {
|
|
115
|
+
clearTimeout(ts1);
|
|
116
|
+
clearInterval(ts2);
|
|
117
|
+
output_1.default.clearPreviousLine();
|
|
118
|
+
if (run.status === 'SUCCESSFUL') {
|
|
119
|
+
output_1.default.exitSuccess((0, texts_1.TXT_PIPELINE_RUN_FINISH_SUCCESSFULLY)(htmlUrl));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
output_1.default.exitError((0, texts_1.TXT_PIPELINE_RUN_FINISH_FAILED)(run.status, htmlUrl));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
fetchCounter = 0;
|
|
126
|
+
}
|
|
127
|
+
fetchCounter += 1;
|
|
128
|
+
}, 1000);
|
|
129
|
+
};
|
|
130
|
+
const formatWaitTime = (start) => {
|
|
131
|
+
const elapsed = Math.floor((Date.now() - start) / 1000);
|
|
132
|
+
return format_1.default.pipelineRunWaitTime(elapsed);
|
|
133
|
+
};
|
|
31
134
|
exports.default = commandPipelineRun;
|
|
@@ -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;
|
|
@@ -23,7 +23,7 @@ commandProjectLink.action(async (dir, options) => {
|
|
|
23
23
|
ProjectCfg.init(path, workspace, project);
|
|
24
24
|
output_1.default.okSign();
|
|
25
25
|
output_1.default.normal(texts_1.TXT_COMMAND_PROJECT_LINK_TO, false);
|
|
26
|
-
output_1.default.
|
|
26
|
+
output_1.default.light(` ${url}`);
|
|
27
27
|
await initRepo(workspace, project, path, git, options);
|
|
28
28
|
tryNow();
|
|
29
29
|
output_1.default.exitNormal();
|
|
@@ -54,13 +54,13 @@ const tryNow = () => {
|
|
|
54
54
|
output_1.default.arrowSign();
|
|
55
55
|
output_1.default.label(texts_1.OPT_COMMAND_PROJECT_LINK_TRY_NOW);
|
|
56
56
|
output_1.default.dim('$ ', false);
|
|
57
|
-
output_1.default.
|
|
57
|
+
output_1.default.light('bdy tunnel http 3000 ', false);
|
|
58
58
|
output_1.default.muted(' Expose localhost:3000 to the internet');
|
|
59
59
|
output_1.default.dim('$ ', false);
|
|
60
|
-
output_1.default.
|
|
60
|
+
output_1.default.light('bdy artifact publish . ', false);
|
|
61
61
|
output_1.default.muted(' Publish an artifact from the current project');
|
|
62
62
|
output_1.default.dim('$ ', false);
|
|
63
|
-
output_1.default.
|
|
63
|
+
output_1.default.light('bdy sandbox create --run "npm start" ', false);
|
|
64
64
|
output_1.default.muted(' Spin up a cloud sandbox and run your app');
|
|
65
65
|
};
|
|
66
66
|
const initRepo = async (workspace, project, path, git, options) => {
|
|
@@ -89,16 +89,16 @@ const initRepo = async (workspace, project, path, git, options) => {
|
|
|
89
89
|
});
|
|
90
90
|
output_1.default.okSign();
|
|
91
91
|
output_1.default.normal('Remote ', false);
|
|
92
|
-
output_1.default.
|
|
92
|
+
output_1.default.light('origin ', false);
|
|
93
93
|
output_1.default.normal('set to ', false);
|
|
94
|
-
output_1.default.
|
|
94
|
+
output_1.default.light(remote);
|
|
95
95
|
}
|
|
96
96
|
else if (remotes.origin !== remote) {
|
|
97
97
|
output_1.default.yellow(texts_1.OPT_COMMAND_PROJECT_LINK_HAS_REMOTE);
|
|
98
98
|
output_1.default.normal('Current origin: ', false);
|
|
99
|
-
output_1.default.
|
|
99
|
+
output_1.default.light(remotes.origin);
|
|
100
100
|
output_1.default.normal('Buddy project: ', false);
|
|
101
|
-
output_1.default.
|
|
101
|
+
output_1.default.light(remote);
|
|
102
102
|
const opt = await output_1.default.inputMenuAdv(texts_1.OPT_COMMAND_PROJECT_LINK_SET_GIT_REMOTE, [
|
|
103
103
|
{
|
|
104
104
|
name: 'Add buddy remote',
|
|
@@ -127,9 +127,9 @@ const initRepo = async (workspace, project, path, git, options) => {
|
|
|
127
127
|
});
|
|
128
128
|
output_1.default.okSign();
|
|
129
129
|
output_1.default.normal('Remote ', false);
|
|
130
|
-
output_1.default.
|
|
130
|
+
output_1.default.light('buddy ', false);
|
|
131
131
|
output_1.default.normal('set to ', false);
|
|
132
|
-
output_1.default.
|
|
132
|
+
output_1.default.light(remote);
|
|
133
133
|
}
|
|
134
134
|
else if (opt === 'origin') {
|
|
135
135
|
await (0, utils_1.execLocally)(`git remote rm origin`, {
|
|
@@ -140,7 +140,7 @@ const initRepo = async (workspace, project, path, git, options) => {
|
|
|
140
140
|
});
|
|
141
141
|
output_1.default.okSign();
|
|
142
142
|
output_1.default.normal('Origin replaced with ', false);
|
|
143
|
-
output_1.default.
|
|
143
|
+
output_1.default.light(remote);
|
|
144
144
|
}
|
|
145
145
|
else {
|
|
146
146
|
return;
|
|
@@ -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
|
@@ -334,8 +334,8 @@ class Input {
|
|
|
334
334
|
}
|
|
335
335
|
static restApiTokenClient(allowNoToken = false, api = '', region = '', token = '') {
|
|
336
336
|
const ApiClient = require('./api/client').default;
|
|
337
|
-
const baseUrl = this.restApiBaseUrl(api, region);
|
|
338
337
|
const { token: t, refreshToken, clientId, clientToken, clientSecret, } = this.restApiToken(allowNoToken, token);
|
|
338
|
+
const baseUrl = this.restApiBaseUrl(api, region, t);
|
|
339
339
|
return new ApiClient(baseUrl, t, refreshToken, clientId, clientSecret, clientToken);
|
|
340
340
|
}
|
|
341
341
|
static artifactType(type) {
|
|
@@ -350,17 +350,6 @@ class Input {
|
|
|
350
350
|
return utils_1.ARTIFACT_SCOPE.PROJECT;
|
|
351
351
|
return utils_1.ARTIFACT_SCOPE.WORKSPACE;
|
|
352
352
|
}
|
|
353
|
-
static pipelineRunId(runId) {
|
|
354
|
-
const r = parseInt(runId, 10);
|
|
355
|
-
if (!isNaN(r))
|
|
356
|
-
return r;
|
|
357
|
-
output_1.default.exitError(texts_1.ERR_RUN_PIPELINE_WRONG_RUN_ID);
|
|
358
|
-
}
|
|
359
|
-
static pipelineRunActionId(runActionId) {
|
|
360
|
-
if (runActionId)
|
|
361
|
-
return runActionId;
|
|
362
|
-
output_1.default.exitError(texts_1.ERR_RUN_PIPELINE_WRONG_RUN_ACTION_ID);
|
|
363
|
-
}
|
|
364
353
|
static pipelineRunPriority(priority) {
|
|
365
354
|
if (!priority)
|
|
366
355
|
return null;
|
|
@@ -442,8 +431,26 @@ class Input {
|
|
|
442
431
|
output_1.default.exitError(texts_1.ERR_REST_API_REGION);
|
|
443
432
|
}
|
|
444
433
|
}
|
|
445
|
-
static
|
|
446
|
-
|
|
434
|
+
static restApiBaseUrlFromToken(token) {
|
|
435
|
+
// bdy_sb_us_aHR0cHM6Ly9hcGkuc2Q1LmNvbQ_f92ml8f1p27nzo45806vczm6c78d0
|
|
436
|
+
const s = (token || '').split('_');
|
|
437
|
+
if (s.length > 1) {
|
|
438
|
+
const base = s[s.length - 2];
|
|
439
|
+
try {
|
|
440
|
+
return Buffer.from(base, 'base64').toString('utf8');
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
// do nothing
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
static restApiBaseUrl(api = '', region = '', token = '') {
|
|
449
|
+
let u = api;
|
|
450
|
+
if (!u)
|
|
451
|
+
u = this.restApiBaseUrlFromToken(token);
|
|
452
|
+
if (!u)
|
|
453
|
+
u = process.env.BUDDY_API_ENDPOINT || null;
|
|
447
454
|
if (!u)
|
|
448
455
|
u = cfg_1.default.getBaseUrl();
|
|
449
456
|
if (!u) {
|
|
@@ -468,6 +475,16 @@ class Input {
|
|
|
468
475
|
output_1.default.exitError(texts_1.ERR_REST_API_URL);
|
|
469
476
|
}
|
|
470
477
|
}
|
|
478
|
+
static pipelineRunWaitTime(time) {
|
|
479
|
+
let t = Number.parseInt(time, 10);
|
|
480
|
+
if (!t)
|
|
481
|
+
t = 1440;
|
|
482
|
+
else if (t < 0)
|
|
483
|
+
t = 1;
|
|
484
|
+
else if (t > 1440)
|
|
485
|
+
t = 1440;
|
|
486
|
+
return t;
|
|
487
|
+
}
|
|
471
488
|
static resolvePath(path) {
|
|
472
489
|
const p = (0, node_path_1.resolve)(path);
|
|
473
490
|
const exists = node_fs_1.default.existsSync(p);
|