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.
Files changed (44) hide show
  1. package/distTs/package.json +1 -1
  2. package/distTs/src/api/client.js +2 -61
  3. package/distTs/src/command/pipeline/run.js +125 -22
  4. package/distTs/src/command/project/get.js +18 -0
  5. package/distTs/src/command/project/link.js +11 -11
  6. package/distTs/src/command/project/set.js +31 -0
  7. package/distTs/src/command/sandbox/get/yaml.js +30 -0
  8. package/distTs/src/command/vt/scrape.js +193 -0
  9. package/distTs/src/input.js +31 -14
  10. package/distTs/src/output.js +31 -149
  11. package/distTs/src/texts.js +33 -55
  12. package/distTs/src/tunnel/output/interactive/tunnel.js +2 -2
  13. package/package.json +1 -1
  14. package/distTs/src/command/crawl/link.js +0 -61
  15. package/distTs/src/command/crawl/run.js +0 -147
  16. package/distTs/src/command/crawl/validation.js +0 -154
  17. package/distTs/src/command/crawl.js +0 -13
  18. package/distTs/src/command/pipeline/run/apply.js +0 -62
  19. package/distTs/src/command/pipeline/run/approve.js +0 -62
  20. package/distTs/src/command/pipeline/run/cancel.js +0 -36
  21. package/distTs/src/command/pipeline/run/list.js +0 -52
  22. package/distTs/src/command/pipeline/run/logs.js +0 -37
  23. package/distTs/src/command/pipeline/run/retry.js +0 -36
  24. package/distTs/src/command/pipeline/run/start.js +0 -96
  25. package/distTs/src/command/pipeline/run/status.js +0 -35
  26. package/distTs/src/command/tests/capture/validation.js +0 -46
  27. package/distTs/src/command/tests/capture.js +0 -103
  28. package/distTs/src/command/tests/unit/link.js +0 -61
  29. package/distTs/src/command/tests/unit/upload.js +0 -91
  30. package/distTs/src/command/tests/unit.js +0 -13
  31. package/distTs/src/command/tests/visual/link.js +0 -61
  32. package/distTs/src/command/tests/visual/session/close.js +0 -32
  33. package/distTs/src/command/tests/visual/session/create.js +0 -86
  34. package/distTs/src/command/tests/visual/session.js +0 -13
  35. package/distTs/src/command/tests/visual/setup.js +0 -20
  36. package/distTs/src/command/tests/visual/shared/validation.js +0 -145
  37. package/distTs/src/command/tests/visual/upload.js +0 -141
  38. package/distTs/src/command/tests/visual.js +0 -17
  39. package/distTs/src/command/tests.js +0 -15
  40. package/distTs/src/crawl/requests.js +0 -141
  41. package/distTs/src/output/pipeline.js +0 -1527
  42. package/distTs/src/types/crawl.js +0 -2
  43. package/distTs/src/types/pipeline.js +0 -424
  44. package/distTs/src/unitTest/context.js +0 -26
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.19.1-dev-pipeline",
4
+ "version": "1.19.2-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "scripts": {
@@ -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 status_1 = __importDefault(require("./run/status"));
9
- const start_1 = __importDefault(require("./run/start"));
10
- const logs_1 = __importDefault(require("./run/logs"));
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.addCommand(start_1.default);
17
- commandPipelineRun.addCommand(status_1.default);
18
- commandPipelineRun.addCommand(logs_1.default);
19
- commandPipelineRun.addCommand(cancel_1.default);
20
- commandPipelineRun.addCommand(retry_1.default);
21
- commandPipelineRun.addCommand(approve_1.default);
22
- commandPipelineRun.addCommand(list_1.default);
23
- commandPipelineRun.addHelpText('after', `
24
- EXAMPLES:${texts_1.EXAMPLE_PIPELINE_RUN_START}
25
- ${texts_1.EXAMPLE_PIPELINE_RUN_STATUS}
26
- ${texts_1.EXAMPLE_PIPELINE_RUN_LOGS}
27
- ${texts_1.EXAMPLE_PIPELINE_RUN_CANCEL}
28
- ${texts_1.EXAMPLE_PIPELINE_RUN_RETRY}
29
- ${texts_1.EXAMPLE_PIPELINE_RUN_APPLY}
30
- ${texts_1.EXAMPLE_PIPELINE_RUN_LIST}`);
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.cyan(` ${url}`);
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.cyan('bdy tunnel http 3000 ', false);
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.cyan('bdy artifact publish . ', false);
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.cyan('bdy sandbox create --run "npm start" ', false);
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.cyan('origin ', false);
92
+ output_1.default.light('origin ', false);
93
93
  output_1.default.normal('set to ', false);
94
- output_1.default.cyan(remote);
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.cyan(remotes.origin);
99
+ output_1.default.light(remotes.origin);
100
100
  output_1.default.normal('Buddy project: ', false);
101
- output_1.default.cyan(remote);
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.cyan('buddy ', false);
130
+ output_1.default.light('buddy ', false);
131
131
  output_1.default.normal('set to ', false);
132
- output_1.default.cyan(remote);
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.cyan(remote);
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;
@@ -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 restApiBaseUrl(api = '', region = '') {
446
- let u = api || process.env.BUDDY_API_ENDPOINT;
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);