bdy 1.25.6-dev → 1.25.8-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 (46) hide show
  1. package/distTs/package.json +1 -1
  2. package/distTs/src/cliCommand.js +43 -0
  3. package/distTs/src/cliIndex.js +10 -0
  4. package/distTs/src/command/agent/uninstall.js +1 -1
  5. package/distTs/src/command/artifact/delete.js +1 -2
  6. package/distTs/src/command/artifact/version/delete.js +1 -2
  7. package/distTs/src/command/context/add.js +38 -0
  8. package/distTs/src/command/context/list.js +33 -0
  9. package/distTs/src/command/context/remove.js +35 -0
  10. package/distTs/src/command/context/show.js +35 -0
  11. package/distTs/src/command/context/use.js +25 -0
  12. package/distTs/src/command/context.js +22 -0
  13. package/distTs/src/command/distro/delete.js +1 -2
  14. package/distTs/src/command/distro/route/delete.js +1 -2
  15. package/distTs/src/command/environment/delete.js +1 -2
  16. package/distTs/src/command/login.js +1 -0
  17. package/distTs/src/command/logout.js +1 -0
  18. package/distTs/src/command/pipeline/delete.js +1 -2
  19. package/distTs/src/command/pipeline/run/approve.js +3 -2
  20. package/distTs/src/command/pipeline/run/cancel.js +3 -2
  21. package/distTs/src/command/pipeline/run/find.js +87 -0
  22. package/distTs/src/command/pipeline/run/findFilters.js +68 -0
  23. package/distTs/src/command/pipeline/run/retry.js +5 -2
  24. package/distTs/src/command/pipeline/run/start.js +3 -2
  25. package/distTs/src/command/pipeline/run/status.js +3 -2
  26. package/distTs/src/command/pipeline/run.js +3 -0
  27. package/distTs/src/command/project/link.js +1 -0
  28. package/distTs/src/command/register.js +1 -0
  29. package/distTs/src/command/sandbox/destroy.js +1 -2
  30. package/distTs/src/command/sandbox/endpoint/delete.js +1 -2
  31. package/distTs/src/command/sandbox/exec/kill.js +1 -2
  32. package/distTs/src/command/sandbox/snapshot/delete.js +1 -2
  33. package/distTs/src/command/target/delete.js +1 -1
  34. package/distTs/src/command/target/exec/kill.js +2 -3
  35. package/distTs/src/command/whoami.js +7 -10
  36. package/distTs/src/command/workspace/get.js +2 -2
  37. package/distTs/src/command/workspace/set.js +1 -0
  38. package/distTs/src/input.js +240 -26
  39. package/distTs/src/output/pipeline.js +84 -13
  40. package/distTs/src/output.js +24 -5
  41. package/distTs/src/project/context.js +97 -0
  42. package/distTs/src/texts.js +275 -29
  43. package/distTs/src/tunnel/cfg.js +43 -4
  44. package/distTs/src/types/context.js +2 -0
  45. package/distTs/src/types/pipelineRunFind.js +2 -0
  46. package/package.json +1 -1
@@ -14,7 +14,7 @@ const client_1 = require("../../../api/client");
14
14
  const commandPipelineRunStart = (0, utils_1.newCommand)('start', texts_1.DESC_COMMAND_PIPELINE_RUN_START, {
15
15
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_RUN],
16
16
  examples: texts_1.EXAMPLE_PIPELINE_RUN_START,
17
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
17
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
18
18
  });
19
19
  commandPipelineRunStart.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
20
20
  commandPipelineRunStart.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
@@ -40,6 +40,7 @@ commandPipelineRunStart.option('--action <actions...>', texts_1.OPTION_PIPELINE_
40
40
  commandPipelineRunStart.option('-n,--no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
41
41
  commandPipelineRunStart.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
42
42
  commandPipelineRunStart.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
43
+ commandPipelineRunStart.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
43
44
  commandPipelineRunStart.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
44
45
  commandPipelineRunStart.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
45
46
  commandPipelineRunStart.usage('<identifier> [options]');
@@ -190,6 +191,6 @@ commandPipelineRunStart.action(async (identifier, options) => {
190
191
  body.payload_files = await uploadPayloadFiles(client, workspace, project, pipelineId, options.payload);
191
192
  const result = await client.pipelineRun(workspace, project, pipelineId, body);
192
193
  const OutputPipeline = require('../../../output/pipeline').default;
193
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, result.id, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
194
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, result.id, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
194
195
  });
195
196
  exports.default = commandPipelineRunStart;
@@ -10,13 +10,14 @@ const execution_1 = require("./execution");
10
10
  const commandPipelineRunStatus = (0, utils_1.newCommand)('status', texts_1.DESC_COMMAND_PIPELINE_RUN_STATUS, {
11
11
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_READ],
12
12
  examples: texts_1.EXAMPLE_PIPELINE_RUN_STATUS,
13
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
13
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
14
14
  });
15
15
  commandPipelineRunStatus.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
16
16
  commandPipelineRunStatus.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
17
17
  commandPipelineRunStatus.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
18
18
  commandPipelineRunStatus.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
19
19
  commandPipelineRunStatus.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
20
+ commandPipelineRunStatus.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
20
21
  commandPipelineRunStatus.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
21
22
  commandPipelineRunStatus.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
22
23
  commandPipelineRunStatus.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
@@ -27,6 +28,6 @@ commandPipelineRunStatus.action(async (identifier, runId, options) => {
27
28
  const rid = input_1.default.pipelineRunId(runId);
28
29
  const pipelineId = await (0, execution_1.resolvePipelineId)(client, workspace, project, identifier);
29
30
  const OutputPipeline = require('../../../output/pipeline').default;
30
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
31
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
31
32
  });
32
33
  exports.default = commandPipelineRunStatus;
@@ -11,6 +11,7 @@ const logs_1 = __importDefault(require("./run/logs"));
11
11
  const cancel_1 = __importDefault(require("./run/cancel"));
12
12
  const retry_1 = __importDefault(require("./run/retry"));
13
13
  const list_1 = __importDefault(require("./run/list"));
14
+ const find_1 = __importDefault(require("./run/find"));
14
15
  const approve_1 = __importDefault(require("./run/approve"));
15
16
  const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_PIPELINE_RUN, {
16
17
  examples: [
@@ -21,6 +22,7 @@ const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_P
21
22
  ...texts_1.EXAMPLE_PIPELINE_RUN_RETRY,
22
23
  ...texts_1.EXAMPLE_PIPELINE_RUN_APPLY,
23
24
  ...texts_1.EXAMPLE_PIPELINE_RUN_LIST,
25
+ ...texts_1.EXAMPLE_PIPELINE_RUN_FIND,
24
26
  ],
25
27
  });
26
28
  commandPipelineRun.addCommand(start_1.default);
@@ -30,4 +32,5 @@ commandPipelineRun.addCommand(cancel_1.default);
30
32
  commandPipelineRun.addCommand(retry_1.default);
31
33
  commandPipelineRun.addCommand(approve_1.default);
32
34
  commandPipelineRun.addCommand(list_1.default);
35
+ commandPipelineRun.addCommand(find_1.default);
33
36
  exports.default = commandPipelineRun;
@@ -10,6 +10,7 @@ const output_1 = __importDefault(require("../../output"));
10
10
  const node_path_1 = require("node:path");
11
11
  const node_fs_1 = __importDefault(require("node:fs"));
12
12
  const commandProjectLink = (0, utils_1.newCommand)('link', texts_1.DESC_COMMAND_PROJECT_LINK);
13
+ commandProjectLink.usesDefaultContext = true;
13
14
  commandProjectLink.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
14
15
  commandProjectLink.option('-r, --relink', texts_1.OPT_COMMAND_PROJECT_LINK_RELINK);
15
16
  commandProjectLink.option('-g, --git', texts_1.OPT_COMMAND_PROJECT_LINK_GIT);
@@ -8,6 +8,7 @@ const texts_1 = require("../texts");
8
8
  const output_1 = __importDefault(require("../output"));
9
9
  const login_1 = require("./login");
10
10
  const commandRegister = (0, utils_1.newCommand)('register', texts_1.DESC_COMMAND_REGISTER);
11
+ commandRegister.usesDefaultContext = true;
11
12
  commandRegister.alias('sign-up');
12
13
  commandRegister.option('--api <url>', texts_1.OPTION_REST_API_ENDPOINT);
13
14
  commandRegister.option('--region <region>', texts_1.OPTION_REST_API_REGION);
@@ -16,8 +16,7 @@ commandSandboxDestroy.action(async (identifier, options) => {
16
16
  const workspace = input_1.default.restApiWorkspace(options.workspace);
17
17
  const client = input_1.default.restApiTokenClient();
18
18
  const sandboxId = await input_1.default.sandboxId(client, workspace, options, identifier);
19
- const confirmed = options.force ||
20
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_DESTROY_CONFIRM)(identifier)));
19
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_DESTROY_CONFIRM)(identifier));
21
20
  if (!confirmed)
22
21
  output_1.default.exitNormal();
23
22
  await client.deleteSandbox(workspace, sandboxId);
@@ -24,8 +24,7 @@ commandSandboxEndpointDelete.action(async (identifier, endpointName, options) =>
24
24
  output_1.default.exitError(texts_1.ERR_SANDBOX_ENDPOINT_NOT_FOUND);
25
25
  }
26
26
  const updatedEndpoints = endpoints.filter((ep) => ep.name !== endpointName);
27
- const confirmed = options.force ||
28
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_ENDPOINT_DELETE_CONFIRM)(identifier, endpointName)));
27
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_ENDPOINT_DELETE_CONFIRM)(identifier, endpointName));
29
28
  if (!confirmed)
30
29
  output_1.default.exitNormal();
31
30
  await client.updateSandbox(workspace, sandboxId, {
@@ -16,8 +16,7 @@ commandSandboxExecKill.action(async (identifier, commandId, options) => {
16
16
  const workspace = input_1.default.restApiWorkspace(options.workspace);
17
17
  const client = input_1.default.restApiTokenClient();
18
18
  const sandboxId = await input_1.default.sandboxId(client, workspace, options, identifier);
19
- const confirmed = options.force ||
20
- (await output_1.default.confirm((0, texts_1.OPTION_SANDBOX_COMMAND_KILL_CONFIRM)(identifier, commandId)));
19
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.OPTION_SANDBOX_COMMAND_KILL_CONFIRM)(identifier, commandId));
21
20
  if (!confirmed)
22
21
  output_1.default.exitNormal();
23
22
  await client.terminateSandboxCommand(workspace, sandboxId, commandId);
@@ -23,8 +23,7 @@ commandSandboxSnapshotDelete.action(async (identifier, snapshotName, options) =>
23
23
  if (!foundSnapshot) {
24
24
  output_1.default.exitError(texts_1.ERR_SANDBOX_SNAPSHOT_NOT_FOUND);
25
25
  }
26
- const confirmed = options.force ||
27
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_SNAPSHOT_DELETE_CONFIRM)(identifier, snapshotName)));
26
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_SNAPSHOT_DELETE_CONFIRM)(identifier, snapshotName));
28
27
  if (!confirmed)
29
28
  output_1.default.exitNormal();
30
29
  await client.deleteSandboxSnapshot(workspace, sandboxId, foundSnapshot.id);
@@ -23,7 +23,7 @@ commandTargetDelete.action(async (identifier, options) => {
23
23
  const client = input_1.default.restApiTokenClient();
24
24
  const target_id = await (0, scope_1.resolveTargetId)(client, workspace, identifier, options,
25
25
  /* strictLine */ true);
26
- const confirmed = options.force || (await output_1.default.confirm((0, texts_1.TXT_TARGET_DELETE_CONFIRM)(identifier)));
26
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_TARGET_DELETE_CONFIRM)(identifier));
27
27
  if (!confirmed)
28
28
  output_1.default.exitNormal();
29
29
  await client.deleteTarget(workspace, target_id);
@@ -16,12 +16,11 @@ commandTargetExecKill.action(async (execId, options) => {
16
16
  const client = input_1.default.restApiTokenClient();
17
17
  // Resolve the exec before the prompt so a bad id fails the same way
18
18
  // (Resource not found, exit 1) with and without --force - otherwise the
19
- // auto-declined prompt exits 0 without ever checking the id. With --force
19
+ // confirmation error would hide the invalid id. With --force
20
20
  // the DELETE itself surfaces the 404, so the extra request is skipped.
21
21
  if (!options.force)
22
22
  await client.getTargetExec(workspace, execId);
23
- const confirmed = options.force ||
24
- (await output_1.default.confirm((0, texts_1.TXT_TARGET_EXEC_KILL_CONFIRM)(execId)));
23
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_TARGET_EXEC_KILL_CONFIRM)(execId));
25
24
  if (!confirmed)
26
25
  output_1.default.exitNormal();
27
26
  await client.cancelTargetExec(workspace, execId);
@@ -5,16 +5,13 @@ 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 cfg_1 = __importDefault(require("../tunnel/cfg"));
9
8
  const output_1 = __importDefault(require("../output"));
10
9
  const input_1 = __importDefault(require("../input"));
11
- const cfg_2 = __importDefault(require("../project/cfg"));
10
+ const cfg_1 = __importDefault(require("../project/cfg"));
12
11
  const commandWhoami = (0, utils_1.newCommand)('whoami', texts_1.DESC_COMMAND_WHOAMI);
13
12
  commandWhoami.option('--format <text|json>', texts_1.OPTION_FORMAT);
14
13
  commandWhoami.action(async (options) => {
15
- const workspace = cfg_1.default.getWorkspace();
16
- const localWorkspace = cfg_2.default.getWorkspace();
17
- const localProject = cfg_2.default.getProject();
14
+ const { workspace, project, localWorkspace } = input_1.default.accountScope();
18
15
  const client = input_1.default.restApiTokenClient();
19
16
  const user = await client.getInvoker();
20
17
  if (!user) {
@@ -30,12 +27,12 @@ commandWhoami.action(async (options) => {
30
27
  else {
31
28
  obj.Workspace = !workspace ? texts_1.TXT_WHOAMI_NO_WORKSPACE : workspace;
32
29
  }
33
- if (localProject) {
34
- obj.Project = localProject;
30
+ if (project) {
31
+ obj.Project = project;
35
32
  }
36
- const vtSuite = cfg_2.default.getVtSuite();
37
- const utSuite = cfg_2.default.getUtSuite();
38
- const crawlSuite = cfg_2.default.getCrawlSuite();
33
+ const vtSuite = cfg_1.default.getVtSuite();
34
+ const utSuite = cfg_1.default.getUtSuite();
35
+ const crawlSuite = cfg_1.default.getCrawlSuite();
39
36
  if (vtSuite) {
40
37
  obj['Visual test suite'] = vtSuite;
41
38
  }
@@ -3,13 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const cfg_1 = __importDefault(require("../../tunnel/cfg"));
6
+ const input_1 = __importDefault(require("../../input"));
7
7
  const output_1 = __importDefault(require("../../output"));
8
8
  const texts_1 = require("../../texts");
9
9
  const utils_1 = require("../../utils");
10
10
  const commandWorkspaceGet = (0, utils_1.newCommand)('get', texts_1.DESC_COMMAND_WORKSPACE_GET);
11
11
  commandWorkspaceGet.action(async () => {
12
- const workspace = cfg_1.default.getWorkspace();
12
+ const { workspace } = input_1.default.accountScope();
13
13
  if (!workspace) {
14
14
  output_1.default.exitError(texts_1.TXT_WORKSPACE_NONE);
15
15
  }
@@ -9,6 +9,7 @@ const texts_1 = require("../../texts");
9
9
  const utils_1 = require("../../utils");
10
10
  const input_1 = __importDefault(require("../../input"));
11
11
  const commandWorkspaceSet = (0, utils_1.newCommand)('set', texts_1.DESC_COMMAND_WORKSPACE_SET);
12
+ commandWorkspaceSet.usesDefaultContext = true;
12
13
  commandWorkspaceSet.argument('[workspace]', texts_1.ARG_COMMAND_WORKSPACE);
13
14
  commandWorkspaceSet.action(async (workspaceDomain) => {
14
15
  output_1.default.handleSignals();
@@ -36,6 +36,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ const pipeline_1 = require("./types/pipeline");
40
+ const cfg_1 = __importDefault(require("./project/cfg"));
41
+ const context_1 = require("./project/context");
39
42
  const cliError_1 = __importDefault(require("./cliError"));
40
43
  const output_1 = __importDefault(require("./output"));
41
44
  const netmask_1 = require("netmask");
@@ -48,10 +51,159 @@ const utils_1 = require("./utils");
48
51
  const texts_1 = require("./texts");
49
52
  const tunnel_1 = require("./types/tunnel");
50
53
  const node_path_1 = __importStar(require("node:path"));
51
- const cfg_1 = __importDefault(require("./tunnel/cfg"));
54
+ const cfg_2 = __importDefault(require("./tunnel/cfg"));
52
55
  const sandbox_1 = require("./types/sandbox");
53
56
  const distro_1 = require("./types/distro");
54
57
  class Input {
58
+ static contextOptions = {};
59
+ static resolvedContextScope;
60
+ static configureContext(options) {
61
+ this.contextOptions = options;
62
+ this.resolvedContextScope = undefined;
63
+ }
64
+ static contextName() {
65
+ return this.contextOptions.context || cfg_2.default.getActiveContext();
66
+ }
67
+ static context() {
68
+ return cfg_2.default.getContext(this.contextName());
69
+ }
70
+ static contextScope() {
71
+ const context = this.context();
72
+ if (!context)
73
+ return null;
74
+ this.resolvedContextScope ??= (0, context_1.resolveContextScope)(context, process.cwd());
75
+ return this.resolvedContextScope;
76
+ }
77
+ static contextEditableName(name) {
78
+ if (['default', 'git', 'link'].includes(name))
79
+ throw new cliError_1.default('usage_error', texts_1.ERR_CONTEXT_RESERVED);
80
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(name))
81
+ throw new cliError_1.default('usage_error', texts_1.ERR_CONTEXT_NAME);
82
+ return name;
83
+ }
84
+ static contextApiEndpoint(api) {
85
+ try {
86
+ const url = new URL(api.includes('://') ? api : `https://${api}`);
87
+ if (url.protocol !== 'https:' ||
88
+ url.username ||
89
+ url.password ||
90
+ url.pathname !== '/' ||
91
+ url.search ||
92
+ url.hash)
93
+ throw new Error();
94
+ return url.origin;
95
+ }
96
+ catch {
97
+ throw new cliError_1.default('usage_error', texts_1.ERR_CONTEXT_API);
98
+ }
99
+ }
100
+ static contextDefinition(options) {
101
+ if ((options.fromLink && options.fromGit) ||
102
+ ((options.fromLink || options.fromGit) &&
103
+ (options.workspace !== undefined || options.project !== undefined)) ||
104
+ (options.remote !== undefined && !options.fromGit))
105
+ throw new cliError_1.default('usage_error', texts_1.ERR_CONTEXT_SOURCE);
106
+ if (options.project && !options.workspace)
107
+ throw new cliError_1.default('usage_error', texts_1.ERR_CONTEXT_PROJECT);
108
+ const api = options.api !== undefined
109
+ ? this.contextApiEndpoint(options.api)
110
+ : undefined;
111
+ return {
112
+ source: options.fromGit ? 'git' : options.fromLink ? 'link' : 'explicit',
113
+ ...(options.workspace ? { workspace: options.workspace } : {}),
114
+ ...(options.project ? { project: options.project } : {}),
115
+ ...(options.token ? { token: options.token } : {}),
116
+ ...(api ? { api } : {}),
117
+ ...(options.fromGit ? { remote: options.remote || 'origin' } : {}),
118
+ };
119
+ }
120
+ // Account display preserves the legacy distinction between global and linked
121
+ // workspace, while named contexts own their entire scope.
122
+ static accountScope() {
123
+ if (this.context())
124
+ return {
125
+ workspace: this.restApiWorkspace(undefined, true),
126
+ project: this.restApiProject(undefined, true),
127
+ localWorkspace: '',
128
+ };
129
+ return {
130
+ workspace: cfg_2.default.getWorkspace(),
131
+ project: cfg_1.default.getProject(),
132
+ localWorkspace: cfg_1.default.getWorkspace(),
133
+ };
134
+ }
135
+ static showContext() {
136
+ const context = this.context();
137
+ const workspace = this.restApiWorkspace(this.contextOptions.workspace, true);
138
+ const project = this.restApiProject(this.contextOptions.project, true);
139
+ const auth = this.restApiToken(true, this.contextOptions.token);
140
+ const api = this.restApiBaseUrl(this.contextOptions.api, this.contextOptions.region, auth.token).origin;
141
+ const inSandbox = (0, utils_1.isInSandbox)();
142
+ const tokenSource = this.contextOptions.token
143
+ ? 'flag'
144
+ : context?.token
145
+ ? 'context'
146
+ : !inSandbox && process.env.BUDDY_TOKEN
147
+ ? 'environment'
148
+ : cfg_2.default.getApiToken()
149
+ ? 'config'
150
+ : process.env.BUDDY_TOKEN
151
+ ? 'environment'
152
+ : null;
153
+ const workspaceSource = this.contextOptions.workspace
154
+ ? 'flag'
155
+ : context
156
+ ? workspace
157
+ ? context.source
158
+ : null
159
+ : !inSandbox && process.env.BUDDY_WORKSPACE
160
+ ? 'environment'
161
+ : cfg_1.default.getWorkspace()
162
+ ? 'link'
163
+ : cfg_2.default.getWorkspace()
164
+ ? 'config'
165
+ : process.env.BUDDY_WORKSPACE
166
+ ? 'environment'
167
+ : null;
168
+ const projectSource = !project
169
+ ? null
170
+ : this.contextOptions.project
171
+ ? 'flag'
172
+ : context
173
+ ? context.source
174
+ : process.env.BUDDY_PROJECT
175
+ ? 'environment'
176
+ : 'link';
177
+ const apiSource = this.contextOptions.api
178
+ ? 'flag'
179
+ : context?.api
180
+ ? 'context'
181
+ : this.restApiBaseUrlFromToken(auth.token)
182
+ ? 'token'
183
+ : process.env.BUDDY_API_ENDPOINT
184
+ ? 'environment'
185
+ : cfg_2.default.getBaseUrl()
186
+ ? 'config'
187
+ : this.contextOptions.region
188
+ ? 'flag'
189
+ : process.env.BUDDY_REGION
190
+ ? 'environment'
191
+ : 'default';
192
+ return {
193
+ name: this.contextName(),
194
+ source: context?.source || 'default',
195
+ workspace,
196
+ project,
197
+ api,
198
+ remote: context?.source === 'git' ? context.remote || 'origin' : null,
199
+ token: { available: !!auth.token, source: tokenSource },
200
+ sources: {
201
+ workspace: workspaceSource,
202
+ project: projectSource,
203
+ api: apiSource,
204
+ },
205
+ };
206
+ }
55
207
  static timeout(timeout) {
56
208
  const t = parseInt(timeout, 10);
57
209
  if (isNaN(t) || t <= 0 || t > 999) {
@@ -344,7 +496,7 @@ class Input {
344
496
  // Inside a sandbox, cfg (written by an explicit `bdy login`) takes precedence
345
497
  // over the sandbox-injected BUDDY_TOKEN env var. Outside a sandbox, env beats cfg
346
498
  const tokenEnv = process.env.BUDDY_TOKEN;
347
- let t = token;
499
+ let t = token || this.context()?.token || '';
348
500
  if (!t && !inSandbox && tokenEnv)
349
501
  t = tokenEnv;
350
502
  let rf = '';
@@ -352,11 +504,11 @@ class Input {
352
504
  let cs = '';
353
505
  let ct = '';
354
506
  if (!t) {
355
- t = cfg_1.default.getApiToken();
356
- rf = cfg_1.default.getApiRefreshApiToken();
357
- cid = cfg_1.default.getApiClientId();
358
- cs = cfg_1.default.getApiClientSecret();
359
- ct = cfg_1.default.getApiClientToken();
507
+ t = cfg_2.default.getApiToken();
508
+ rf = cfg_2.default.getApiRefreshApiToken();
509
+ cid = cfg_2.default.getApiClientId();
510
+ cs = cfg_2.default.getApiClientSecret();
511
+ ct = cfg_2.default.getApiClientToken();
360
512
  }
361
513
  if (!t && inSandbox && tokenEnv)
362
514
  t = tokenEnv;
@@ -418,6 +570,41 @@ class Input {
418
570
  }
419
571
  output_1.default.exitError(texts_1.ERR_COMMAND_ARTIFACT_TYPE);
420
572
  }
573
+ static pipelineRunFind(options) {
574
+ const rawLast = options.last;
575
+ const last = Number(rawLast);
576
+ if (!/^\d+$/.test(rawLast) || last < 1 || last > 1000) {
577
+ throw new cliError_1.default('usage_error', texts_1.ERR_PIPELINE_RUN_FIND_LAST);
578
+ }
579
+ const { pipelineRunFindFilters } = require('./command/pipeline/run/findFilters');
580
+ const filters = {};
581
+ for (const { key, flag } of pipelineRunFindFilters) {
582
+ const value = options[key];
583
+ if (value === undefined)
584
+ continue;
585
+ if (!value.trim())
586
+ throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)(flag));
587
+ filters[key] = value;
588
+ }
589
+ if (filters.pr) {
590
+ if (!/^(?:pull\/)?[1-9]\d*$/.test(filters.pr))
591
+ throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--pr'));
592
+ filters.pr = 'pull/' + filters.pr.replace(/^pull\//, '');
593
+ }
594
+ if (filters.status) {
595
+ filters.status = filters.status.toUpperCase();
596
+ if (!Object.values(pipeline_1.PIPELINE_RUN_STATUS).includes(filters.status))
597
+ throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--status'));
598
+ }
599
+ if (filters.artifact?.includes(':')) {
600
+ const separator = filters.artifact.indexOf(':');
601
+ const version = filters.artifact.slice(separator + 1);
602
+ const identifier = filters.artifact.slice(0, separator);
603
+ if (!identifier.trim() || !version.trim())
604
+ throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--artifact'));
605
+ }
606
+ return { last, filters };
607
+ }
421
608
  static pipelineRunId(runId) {
422
609
  const r = parseInt(runId, 10);
423
610
  if (!isNaN(r))
@@ -869,13 +1056,13 @@ class Input {
869
1056
  return null;
870
1057
  }
871
1058
  static restApiBaseUrl(api = '', region = '', token = '') {
872
- let u = api;
1059
+ let u = api || this.context()?.api || '';
873
1060
  if (!u)
874
1061
  u = this.restApiBaseUrlFromToken(token);
875
1062
  if (!u)
876
1063
  u = process.env.BUDDY_API_ENDPOINT || null;
877
1064
  if (!u)
878
- u = cfg_1.default.getBaseUrl();
1065
+ u = cfg_2.default.getBaseUrl();
879
1066
  if (!u) {
880
1067
  const r = region || process.env.BUDDY_REGION;
881
1068
  if (r?.toLowerCase() === utils_1.REST_API_REGION.EU) {
@@ -907,18 +1094,25 @@ class Input {
907
1094
  return p;
908
1095
  }
909
1096
  static restApiWorkspace(workspace, allowNull, ignoreProjectConfig = false) {
1097
+ if (!ignoreProjectConfig && this.context()) {
1098
+ const value = workspace || this.contextScope()?.workspace;
1099
+ if (value)
1100
+ return value;
1101
+ if (allowNull)
1102
+ return null;
1103
+ throw new cliError_1.default('usage_error', texts_1.ERR_REST_API_WORKSPACE, texts_1.TXT_CONTEXT_WORKSPACE_HINT);
1104
+ }
910
1105
  // Inside a sandbox, cfg/project cfg (set by an explicit `bdy login` or .bdy/cfg.json)
911
1106
  // takes precedence over the sandbox-injected BUDDY_WORKSPACE env var.
912
1107
  // Outside a sandbox, env beats cfg.
913
- const ProjectCfg = require('./project/cfg').default;
914
1108
  let w = workspace;
915
1109
  const inSandbox = (0, utils_1.isInSandbox)();
916
1110
  if (!w && !inSandbox && process.env.BUDDY_WORKSPACE)
917
1111
  w = process.env.BUDDY_WORKSPACE;
918
1112
  if (!w && !ignoreProjectConfig)
919
- w = ProjectCfg.getWorkspace();
920
- if (!w)
921
1113
  w = cfg_1.default.getWorkspace();
1114
+ if (!w)
1115
+ w = cfg_2.default.getWorkspace();
922
1116
  if (!w && inSandbox && process.env.BUDDY_WORKSPACE)
923
1117
  w = process.env.BUDDY_WORKSPACE;
924
1118
  if (!w) {
@@ -1247,12 +1441,35 @@ class Input {
1247
1441
  return sandboxId;
1248
1442
  }
1249
1443
  static restApiProject(project, allowNull) {
1250
- const ProjectCfg = require('./project/cfg').default;
1444
+ const context = this.context();
1445
+ if (context) {
1446
+ let value = project;
1447
+ if (!value) {
1448
+ let scope;
1449
+ try {
1450
+ scope = this.contextScope();
1451
+ }
1452
+ catch (err) {
1453
+ // An explicit workspace is sufficient for workspace-scoped commands.
1454
+ // If the dynamic source is unavailable, none of its project can carry over.
1455
+ if (!this.contextOptions.workspace || context.source === 'explicit')
1456
+ throw err;
1457
+ }
1458
+ const changedWorkspace = this.contextOptions.workspace && this.contextOptions.workspace !== scope?.workspace;
1459
+ if (!changedWorkspace)
1460
+ value = scope?.project || '';
1461
+ }
1462
+ if (value)
1463
+ return value;
1464
+ if (allowNull)
1465
+ return null;
1466
+ throw new cliError_1.default('usage_error', texts_1.ERR_REST_API_PROJECT, texts_1.TXT_CONTEXT_PROJECT_HINT);
1467
+ }
1251
1468
  let p = process.env.BUDDY_PROJECT;
1252
1469
  if (project)
1253
1470
  p = project;
1254
1471
  if (!p)
1255
- p = ProjectCfg.getProject();
1472
+ p = cfg_1.default.getProject();
1256
1473
  if (!p) {
1257
1474
  if (allowNull)
1258
1475
  return null;
@@ -1330,14 +1547,14 @@ class Input {
1330
1547
  const workspace = Input.restApiWorkspace('', true);
1331
1548
  const project = Input.restApiProject('', true);
1332
1549
  let fromLogin = false;
1333
- if (!token && cfg_1.default.getApiToken() && workspace) {
1550
+ if (!token && (this.context() ? this.restApiToken(true).token : cfg_2.default.getApiToken()) && workspace) {
1334
1551
  const client = Input.restApiTokenClient();
1335
1552
  const result = await client.getTunnelToken(workspace, project);
1336
1553
  token = String(result?.token || '');
1337
1554
  fromLogin = true;
1338
1555
  }
1339
1556
  else if (!token) {
1340
- token = cfg_1.default.getToken();
1557
+ token = cfg_2.default.getToken();
1341
1558
  }
1342
1559
  if (!token)
1343
1560
  throw new Error(texts_1.ERR_TOKEN_NOT_PROVIDED);
@@ -1350,7 +1567,7 @@ class Input {
1350
1567
  throw new Error(texts_1.ERR_WRONG_TOKEN);
1351
1568
  }
1352
1569
  if (!fromLogin)
1353
- cfg_1.default.setToken(token);
1570
+ cfg_2.default.setToken(token);
1354
1571
  return {
1355
1572
  token,
1356
1573
  host: d.host,
@@ -1382,9 +1599,8 @@ class Input {
1382
1599
  const envToken = process.env.BUDDY_VT_TOKEN;
1383
1600
  if (envToken)
1384
1601
  return envToken;
1385
- const ProjectCfg = require('./project/cfg').default;
1386
- const suiteIdentifier = ProjectCfg.getVtSuite();
1387
- if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
1602
+ const suiteIdentifier = cfg_1.default.getVtSuite();
1603
+ if (suiteIdentifier && this.restApiToken(true).token) {
1388
1604
  const workspace = Input.restApiWorkspace('', true);
1389
1605
  const project = Input.restApiProject('', true);
1390
1606
  if (workspace && project) {
@@ -1402,9 +1618,8 @@ class Input {
1402
1618
  const envToken = process.env.BUDDY_CRAWL_TOKEN;
1403
1619
  if (envToken)
1404
1620
  return envToken;
1405
- const ProjectCfg = require('./project/cfg').default;
1406
- const suiteIdentifier = ProjectCfg.getCrawlSuite();
1407
- if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
1621
+ const suiteIdentifier = cfg_1.default.getCrawlSuite();
1622
+ if (suiteIdentifier && this.restApiToken(true).token) {
1408
1623
  const workspace = Input.restApiWorkspace('', true);
1409
1624
  const project = Input.restApiProject('', true);
1410
1625
  if (workspace && project) {
@@ -1422,9 +1637,8 @@ class Input {
1422
1637
  const envToken = process.env.BUDDY_UT_TOKEN;
1423
1638
  if (envToken)
1424
1639
  return envToken;
1425
- const ProjectCfg = require('./project/cfg').default;
1426
- const suiteIdentifier = ProjectCfg.getUtSuite();
1427
- if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
1640
+ const suiteIdentifier = cfg_1.default.getUtSuite();
1641
+ if (suiteIdentifier && this.restApiToken(true).token) {
1428
1642
  const workspace = Input.restApiWorkspace('', true);
1429
1643
  const project = Input.restApiProject('', true);
1430
1644
  if (workspace && project) {