bdy 1.16.12 → 1.16.14-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 (45) hide show
  1. package/distTs/package.json +4 -3
  2. package/distTs/src/api/client.js +173 -5
  3. package/distTs/src/command/login.js +130 -0
  4. package/distTs/src/command/logout.js +15 -0
  5. package/distTs/src/command/project/get.js +18 -0
  6. package/distTs/src/command/project/list.js +33 -0
  7. package/distTs/src/command/project/set.js +45 -0
  8. package/distTs/src/command/project.js +16 -0
  9. package/distTs/src/command/sandbox/cp.js +71 -0
  10. package/distTs/src/command/sandbox/create.js +147 -0
  11. package/distTs/src/command/sandbox/destroy.js +34 -0
  12. package/distTs/src/command/sandbox/endpoint/add.js +40 -0
  13. package/distTs/src/command/sandbox/endpoint/delete.js +41 -0
  14. package/distTs/src/command/sandbox/endpoint/get.js +101 -0
  15. package/distTs/src/command/sandbox/endpoint/list.js +48 -0
  16. package/distTs/src/command/sandbox/endpoint.js +18 -0
  17. package/distTs/src/command/sandbox/exec/command.js +72 -0
  18. package/distTs/src/command/sandbox/exec/kill.js +34 -0
  19. package/distTs/src/command/sandbox/exec/list.js +53 -0
  20. package/distTs/src/command/sandbox/exec/logs.js +59 -0
  21. package/distTs/src/command/sandbox/exec/status.js +43 -0
  22. package/distTs/src/command/sandbox/exec.js +19 -0
  23. package/distTs/src/command/sandbox/get.js +50 -0
  24. package/distTs/src/command/sandbox/list.js +41 -0
  25. package/distTs/src/command/sandbox/restart.js +48 -0
  26. package/distTs/src/command/sandbox/snapshot/create.js +56 -0
  27. package/distTs/src/command/sandbox/snapshot/delete.js +40 -0
  28. package/distTs/src/command/sandbox/snapshot/get.js +50 -0
  29. package/distTs/src/command/sandbox/snapshot/list.js +46 -0
  30. package/distTs/src/command/sandbox/snapshot.js +18 -0
  31. package/distTs/src/command/sandbox/start.js +48 -0
  32. package/distTs/src/command/sandbox/status.js +38 -0
  33. package/distTs/src/command/sandbox/stop.js +48 -0
  34. package/distTs/src/command/sandbox.js +34 -0
  35. package/distTs/src/command/workspace/get.js +18 -0
  36. package/distTs/src/command/workspace/list.js +32 -0
  37. package/distTs/src/command/workspace/set.js +40 -0
  38. package/distTs/src/command/workspace.js +16 -0
  39. package/distTs/src/index.js +10 -0
  40. package/distTs/src/input.js +142 -14
  41. package/distTs/src/output.js +44 -0
  42. package/distTs/src/texts.js +181 -8
  43. package/distTs/src/tunnel/cfg.js +47 -0
  44. package/distTs/src/utils.js +91 -3
  45. package/package.json +4 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.16.12",
4
+ "version": "1.16.14-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "scripts": {
@@ -31,6 +31,8 @@
31
31
  "eventsource": "4.0.0",
32
32
  "fastify": "4.28.1",
33
33
  "fdir": "6.5.0",
34
+ "fflate": "0.8.2",
35
+ "human-id": "^4.1.3",
34
36
  "isbinaryfile": "5.0.2",
35
37
  "jsonwebtoken": "9.0.2",
36
38
  "mime-db": "1.52.0",
@@ -52,8 +54,7 @@
52
54
  "uuid": "10.0.0",
53
55
  "which": "4.0.0",
54
56
  "ws": "8.18.0",
55
- "zod": "3.24.2",
56
- "fflate": "0.8.2"
57
+ "zod": "3.24.2"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@eslint/js": "9.13.0",
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const undici_1 = require("undici");
7
7
  const texts_1 = require("../texts");
8
8
  const logger_1 = __importDefault(require("../logger"));
9
+ const utils_1 = require("../utils");
10
+ const node_fs_1 = __importDefault(require("node:fs"));
9
11
  class ApiClient {
10
12
  client;
11
13
  token;
@@ -19,14 +21,19 @@ class ApiClient {
19
21
  },
20
22
  });
21
23
  }
22
- async request(method, path, body, parseResponseBody = false) {
24
+ async request(method, path, body, parseResponseBody = false, rawResponseBody = false) {
23
25
  const headers = {
24
26
  authorization: `Bearer ${this.token}`,
25
27
  };
26
28
  let bodyParsed = undefined;
27
29
  if (body) {
28
- headers['content-type'] = 'application/json; charset=utf-8';
29
- bodyParsed = JSON.stringify(body);
30
+ if (body instanceof undici_1.FormData) {
31
+ bodyParsed = body;
32
+ }
33
+ else {
34
+ headers['content-type'] = 'application/json; charset=utf-8';
35
+ bodyParsed = JSON.stringify(body);
36
+ }
30
37
  }
31
38
  const opts = {
32
39
  method,
@@ -48,6 +55,9 @@ class ApiClient {
48
55
  catch (err) {
49
56
  logger_1.default.debug('API CLIENT RESPONSE ERROR');
50
57
  logger_1.default.debug(err);
58
+ if (/ECONNREFUSED|ECONNRESET|ETIMEDOUT/.test(err.message)) {
59
+ throw new Error(texts_1.ERR_REST_API_CONNECT_ERROR);
60
+ }
51
61
  throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
52
62
  }
53
63
  if (status === 401) {
@@ -55,7 +65,19 @@ class ApiClient {
55
65
  throw new Error(texts_1.ERR_REST_API_WRONG_TOKEN);
56
66
  }
57
67
  if (status === 403) {
58
- await responseBody.dump();
68
+ let json;
69
+ try {
70
+ json = await responseBody.json();
71
+ logger_1.default.debug('API CLIENT PARSED RESPONSE:');
72
+ logger_1.default.debug(json);
73
+ }
74
+ catch {
75
+ await responseBody.dump();
76
+ throw new Error(texts_1.ERR_REST_API_RATE_LIMIT);
77
+ }
78
+ if (json.errors && json.errors[0] && json.errors[0].message) {
79
+ throw new Error(json.errors[0].message);
80
+ }
59
81
  throw new Error(texts_1.ERR_REST_API_RATE_LIMIT);
60
82
  }
61
83
  if ([400, 404].includes(status)) {
@@ -79,7 +101,7 @@ class ApiClient {
79
101
  else
80
102
  throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
81
103
  }
82
- if (status === 200) {
104
+ if (status === 200 || status === 201) {
83
105
  if (parseResponseBody) {
84
106
  try {
85
107
  const b = await responseBody.json();
@@ -93,11 +115,18 @@ class ApiClient {
93
115
  throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
94
116
  }
95
117
  }
118
+ else if (rawResponseBody) {
119
+ return responseBody;
120
+ }
96
121
  else {
97
122
  await responseBody.dump();
98
123
  return null;
99
124
  }
100
125
  }
126
+ else if (status === 204) {
127
+ await responseBody.dump();
128
+ return null;
129
+ }
101
130
  else {
102
131
  await responseBody.dump();
103
132
  throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
@@ -112,5 +141,144 @@ class ApiClient {
112
141
  async postPipelineRun(workspace, project, pipelineId, body) {
113
142
  return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions`, body, true);
114
143
  }
144
+ // Sandbox methods
145
+ async createSandbox(workspace, project, body) {
146
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes?project_name=${encodeURIComponent(project)}`, body, true);
147
+ }
148
+ async sandboxUploadFile(workspace, sandboxId, remotePath, localPath) {
149
+ const formData = new undici_1.FormData();
150
+ const file = await node_fs_1.default.openAsBlob(localPath);
151
+ formData.set('file', file);
152
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/content/upload${remotePath}`, formData, true);
153
+ }
154
+ async listSandboxes(workspace, project) {
155
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes?project_name=${encodeURIComponent(project)}`, null, true);
156
+ }
157
+ async getSandbox(workspace, sandboxId) {
158
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}`, null, true);
159
+ }
160
+ async deleteSandbox(workspace, sandboxId) {
161
+ return await this.request('DELETE', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}`, null, false);
162
+ }
163
+ async updateSandbox(workspace, sandboxId, body) {
164
+ return await this.request('PATCH', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}`, body, true);
165
+ }
166
+ async startSandbox(workspace, sandboxId) {
167
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/start`, {}, true);
168
+ }
169
+ async stopSandbox(workspace, sandboxId) {
170
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/stop`, {}, true);
171
+ }
172
+ async restartSandbox(workspace, sandboxId) {
173
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/restart`, {}, true);
174
+ }
175
+ async executeSandboxCommand(workspace, sandboxId, body) {
176
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands`, body, true);
177
+ }
178
+ async getSandboxCommand(workspace, sandboxId, commandId) {
179
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands/${encodeURIComponent(commandId)}`, null, true);
180
+ }
181
+ async listSandboxCommands(workspace, sandboxId) {
182
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands`, null, true);
183
+ }
184
+ async getSandboxCommandLogsUrl(workspace, sandboxId, commandId) {
185
+ return `${this.baseUrl.origin}/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands/${encodeURIComponent(commandId)}/logs`;
186
+ }
187
+ async streamSandboxCommandLogs(workspace, sandboxId, commandId, follow = true) {
188
+ let q = '';
189
+ if (follow)
190
+ q = '?follow=true';
191
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands/${encodeURIComponent(commandId)}/logs${q}`, null, false, true);
192
+ }
193
+ async terminateSandboxCommand(workspace, sandboxId, commandId) {
194
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/commands/${encodeURIComponent(commandId)}/terminate`, {}, true);
195
+ }
196
+ // Snapshot methods
197
+ async listSandboxSnapshots(workspace, sandboxId) {
198
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/snapshots`, null, true);
199
+ }
200
+ async createSandboxSnapshot(workspace, sandboxId, body) {
201
+ return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/snapshots`, body, true);
202
+ }
203
+ async getSandboxSnapshot(workspace, sandboxId, snapshotId) {
204
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/snapshots/${encodeURIComponent(snapshotId)}`, null, true);
205
+ }
206
+ async deleteSandboxSnapshot(workspace, sandboxId, snapshotId) {
207
+ return await this.request('DELETE', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/snapshots/${encodeURIComponent(snapshotId)}`, null, false);
208
+ }
209
+ async sandboxWaitForSnapshot(workspace, sandboxId, snapshotId, timeout = 300) {
210
+ const end = Date.now() + timeout * 1000;
211
+ for (;;) {
212
+ const sb = await this.getSandboxSnapshot(workspace, sandboxId, snapshotId);
213
+ if ([
214
+ utils_1.SANDBOX_SNAPSHOT_STATUS.FAILED,
215
+ utils_1.SANDBOX_SNAPSHOT_STATUS.CREATED,
216
+ ].includes(sb.status)) {
217
+ return sb.status;
218
+ }
219
+ if (Date.now() > end) {
220
+ throw new Error('timeout');
221
+ }
222
+ await this.waitSleep();
223
+ }
224
+ }
225
+ async sandboxWaitForRunning(workspace, sandboxId, timeout = 300) {
226
+ const end = Date.now() + timeout * 1000;
227
+ for (;;) {
228
+ const sb = await this.getSandbox(workspace, sandboxId);
229
+ if ([
230
+ utils_1.SANDBOX_STATUS.FAILED,
231
+ utils_1.SANDBOX_STATUS.RUNNING,
232
+ utils_1.SANDBOX_STATUS.STOPPED,
233
+ ].includes(sb.status)) {
234
+ return sb.status;
235
+ }
236
+ if (Date.now() > end) {
237
+ throw new Error('timeout');
238
+ }
239
+ await this.waitSleep();
240
+ }
241
+ }
242
+ async waitSleep(timeout = 3) {
243
+ return new Promise((resolve) => {
244
+ setTimeout(resolve, timeout * 1000);
245
+ });
246
+ }
247
+ async sandboxWaitForConfigured(workspace, sandboxId, timeout = 300) {
248
+ const end = Date.now() + timeout * 1000;
249
+ for (;;) {
250
+ const sb = await this.getSandbox(workspace, sandboxId);
251
+ if ([utils_1.SANDBOX_SETUP_STATUS.SUCCESS, utils_1.SANDBOX_SETUP_STATUS.FAILED].includes(sb.setup_status)) {
252
+ return sb.setup_status;
253
+ }
254
+ if (Date.now() > end) {
255
+ throw new Error('timeout');
256
+ }
257
+ await this.waitSleep();
258
+ }
259
+ }
260
+ async sandboxWaitForApp(workspace, sandboxId, timeout = 300) {
261
+ const end = Date.now() + timeout * 1000;
262
+ for (;;) {
263
+ const sb = await this.getSandbox(workspace, sandboxId);
264
+ if ([
265
+ utils_1.SANDBOX_APP_STATUS.RUNNING,
266
+ utils_1.SANDBOX_APP_STATUS.FAILED,
267
+ utils_1.SANDBOX_APP_STATUS.ENDED,
268
+ ].includes(sb.app_status)) {
269
+ return sb.app_status;
270
+ }
271
+ if (Date.now() > end) {
272
+ throw new Error('timeout');
273
+ }
274
+ await this.waitSleep();
275
+ }
276
+ }
277
+ async getWorkspaces() {
278
+ return await this.request('GET', '/workspaces', null, true);
279
+ }
280
+ async getProjects(workspace) {
281
+ return await this.request('GET', `/workspaces/${encodeURIComponent(workspace)}/projects`, null, true);
282
+ }
115
283
  }
116
284
  exports.default = ApiClient;
@@ -0,0 +1,130 @@
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 client_1 = __importDefault(require("../api/client"));
9
+ const texts_1 = require("../texts");
10
+ const utils_1 = require("../utils");
11
+ const input_1 = __importDefault(require("../input"));
12
+ function getSecurityUrl(region, baseUrl) {
13
+ switch (region) {
14
+ case utils_1.REST_API_REGION.US:
15
+ return 'https://app.buddy.works/security';
16
+ case utils_1.REST_API_REGION.EU:
17
+ return 'https://eu.buddy.works/security';
18
+ case utils_1.REST_API_REGION.AS:
19
+ return 'https://asia.buddy.works/security';
20
+ default:
21
+ return `https://${baseUrl}/security`;
22
+ }
23
+ }
24
+ function normalizeBaseUrl(url) {
25
+ let normalized = url.trim();
26
+ normalized = normalized.replace(/^https?:\/\//i, '');
27
+ normalized = normalized.replace(/\/+$/, '');
28
+ return normalized;
29
+ }
30
+ async function selectRegion() {
31
+ output_1.default.normal(texts_1.TXT_LOGIN_SELECT_REGION);
32
+ const index = await output_1.default.inputMenu([
33
+ 'US (default)',
34
+ 'EU',
35
+ 'Asia',
36
+ 'On-premises',
37
+ ]);
38
+ if (index === 0)
39
+ return utils_1.REST_API_REGION.US;
40
+ if (index === 1)
41
+ return utils_1.REST_API_REGION.EU;
42
+ if (index === 2)
43
+ return utils_1.REST_API_REGION.AS;
44
+ return utils_1.REST_API_REGION.ONPREM;
45
+ }
46
+ async function restApiBaseUrl() {
47
+ output_1.default.normal(texts_1.TXT_LOGIN_ENTER_BASE_URL);
48
+ const str = await output_1.default.inputString();
49
+ const normalized = normalizeBaseUrl(str);
50
+ if (!normalized) {
51
+ output_1.default.exitError(texts_1.ERR_LOGIN_INVALID_BASE_URL);
52
+ }
53
+ return `${normalized}/api`;
54
+ }
55
+ async function inputToken(region, baseUrl) {
56
+ const securityUrl = getSecurityUrl(region, baseUrl);
57
+ output_1.default.normal((0, texts_1.TXT_LOGIN_ENTER_TOKEN)(securityUrl));
58
+ return await output_1.default.inputString();
59
+ }
60
+ const commandLogin = (0, utils_1.newCommand)('login', texts_1.DESC_COMMAND_LOGIN);
61
+ commandLogin.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
62
+ commandLogin.option('--api <url>', texts_1.OPTION_REST_API_ENDPOINT);
63
+ commandLogin.option('--region <region>', texts_1.OPTION_REST_API_REGION);
64
+ commandLogin.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
65
+ commandLogin.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
66
+ commandLogin.action(async (options) => {
67
+ output_1.default.handleSignals();
68
+ cfg_1.default.clearLogin();
69
+ let api = options.api || process.env.BUDDY_API_ENDPOINT;
70
+ let region = options.region || process.env.BUDDY_REGION;
71
+ let token = options.token || process.env.BUDDY_TOKEN;
72
+ let workspace = options.workspace || process.env.BUDDY_WORKSPACE;
73
+ let project = options.project || process.env.BUDDY_PROJECT;
74
+ if (api) {
75
+ region = utils_1.REST_API_REGION.ONPREM;
76
+ }
77
+ else if (region) {
78
+ region = input_1.default.restApiRegion(region);
79
+ }
80
+ else {
81
+ region = await selectRegion();
82
+ }
83
+ if (!api) {
84
+ if (region === utils_1.REST_API_REGION.ONPREM) {
85
+ api = await restApiBaseUrl();
86
+ }
87
+ else if (region === utils_1.REST_API_REGION.AS) {
88
+ api = utils_1.REST_API_ENDPOINT.AS;
89
+ }
90
+ else if (region === utils_1.REST_API_REGION.EU) {
91
+ api = utils_1.REST_API_ENDPOINT.EU;
92
+ }
93
+ else {
94
+ api = utils_1.REST_API_ENDPOINT.US;
95
+ }
96
+ }
97
+ cfg_1.default.setBaseUrl(api);
98
+ if (!token) {
99
+ token = await inputToken(region, api);
100
+ }
101
+ const client = new client_1.default(new URL(`https://${api}`), token);
102
+ const w = await client.getWorkspaces();
103
+ if (!w.workspaces?.length) {
104
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACES);
105
+ }
106
+ if (workspace) {
107
+ const found = w.workspaces.find((w) => w.domain === workspace);
108
+ if (!found) {
109
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACE_FOUND);
110
+ }
111
+ }
112
+ else {
113
+ workspace = await output_1.default.selectWorkspace(w.workspaces);
114
+ }
115
+ cfg_1.default.setApiToken(token);
116
+ cfg_1.default.setWorkspace(workspace);
117
+ const p = await client.getProjects(workspace);
118
+ if (project) {
119
+ const found = p.projects.find((p) => p.name === project);
120
+ if (!found) {
121
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_PROJECT_FOUND);
122
+ }
123
+ }
124
+ else {
125
+ project = await output_1.default.selectProject(p.projects);
126
+ }
127
+ cfg_1.default.setProject(project);
128
+ output_1.default.exitSuccess(texts_1.TXT_LOGIN_SUCCESS);
129
+ });
130
+ exports.default = commandLogin;
@@ -0,0 +1,15 @@
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 commandLogout = (0, utils_1.newCommand)('logout', texts_1.DESC_COMMAND_LOGOUT);
11
+ commandLogout.action(async () => {
12
+ cfg_1.default.clearLogin();
13
+ output_1.default.exitSuccess(texts_1.TXT_LOGOUT_SUCCESS);
14
+ });
15
+ exports.default = commandLogout;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cfg_1 = __importDefault(require("../../tunnel/cfg"));
7
+ const output_1 = __importDefault(require("../../output"));
8
+ const texts_1 = require("../../texts");
9
+ const utils_1 = require("../../utils");
10
+ const commandProjectGet = (0, utils_1.newCommand)('get', texts_1.DESC_COMMAND_PROJECT_GET);
11
+ commandProjectGet.action(async () => {
12
+ const project = cfg_1.default.getProject();
13
+ if (!project) {
14
+ output_1.default.exitError(texts_1.TXT_PROJECT_NONE);
15
+ }
16
+ output_1.default.exitNormal(project);
17
+ });
18
+ exports.default = commandProjectGet;
@@ -0,0 +1,33 @@
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 output_1 = __importDefault(require("../../output"));
7
+ const client_1 = __importDefault(require("../../api/client"));
8
+ const texts_1 = require("../../texts");
9
+ const utils_1 = require("../../utils");
10
+ const input_1 = __importDefault(require("../../input"));
11
+ const commandProjectList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_PROJECT_LIST);
12
+ commandProjectList.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
13
+ commandProjectList.option('--api <url>', texts_1.OPTION_REST_API_ENDPOINT);
14
+ commandProjectList.option('--region <region>', texts_1.OPTION_REST_API_REGION);
15
+ commandProjectList.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
16
+ commandProjectList.alias('ls');
17
+ commandProjectList.action(async (options) => {
18
+ const token = input_1.default.restApiToken(options.token);
19
+ const baseUrl = input_1.default.restApiBaseUrl(options.api, options.region);
20
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
21
+ const client = new client_1.default(baseUrl, token);
22
+ const response = await client.getProjects(workspace);
23
+ if (!response.projects || response.projects.length === 0) {
24
+ output_1.default.exitError(texts_1.ERR_PROJECT_NO_PROJECTS);
25
+ }
26
+ const data = [['NAME', 'DISPLAY NAME', 'STATUS']];
27
+ for (const proj of response.projects) {
28
+ data.push([proj.name, proj.display_name, proj.status]);
29
+ }
30
+ output_1.default.table(data);
31
+ output_1.default.exitNormal();
32
+ });
33
+ exports.default = commandProjectList;
@@ -0,0 +1,45 @@
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 client_1 = __importDefault(require("../../api/client"));
9
+ const texts_1 = require("../../texts");
10
+ const utils_1 = require("../../utils");
11
+ const input_1 = __importDefault(require("../../input"));
12
+ const commandProjectSet = (0, utils_1.newCommand)('set', texts_1.DESC_COMMAND_PROJECT_SET);
13
+ commandProjectSet.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
14
+ commandProjectSet.option('--api <url>', texts_1.OPTION_REST_API_ENDPOINT);
15
+ commandProjectSet.option('--region <region>', texts_1.OPTION_REST_API_REGION);
16
+ commandProjectSet.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
17
+ commandProjectSet.argument('[project]', texts_1.ARG_COMMAND_PROJECT_NAME);
18
+ commandProjectSet.action(async (projectName, options) => {
19
+ output_1.default.handleSignals();
20
+ const token = input_1.default.restApiToken(options.token);
21
+ const baseUrl = input_1.default.restApiBaseUrl(options.api, options.region);
22
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
23
+ const client = new client_1.default(baseUrl, token);
24
+ const response = await client.getProjects(workspace);
25
+ if (!response.projects || response.projects.length === 0) {
26
+ output_1.default.exitError(texts_1.ERR_PROJECT_NO_PROJECTS);
27
+ }
28
+ let project;
29
+ if (projectName) {
30
+ const found = response.projects.find((p) => p.name === projectName);
31
+ if (!found) {
32
+ output_1.default.exitError((0, texts_1.ERR_PROJECT_NOT_FOUND)(projectName));
33
+ }
34
+ project = found.name;
35
+ }
36
+ else {
37
+ project = await output_1.default.selectProject(response.projects);
38
+ }
39
+ cfg_1.default.setProject(project);
40
+ if (!project)
41
+ output_1.default.exitSuccess(texts_1.TXT_PROJECT_SET_CLEARED);
42
+ else
43
+ output_1.default.exitSuccess((0, texts_1.TXT_PROJECT_SET_SUCCESS)(project));
44
+ });
45
+ exports.default = commandProjectSet;
@@ -0,0 +1,16 @@
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 texts_1 = require("../texts");
7
+ const utils_1 = require("../utils");
8
+ const list_1 = __importDefault(require("./project/list"));
9
+ const set_1 = __importDefault(require("./project/set"));
10
+ const get_1 = __importDefault(require("./project/get"));
11
+ const commandProject = (0, utils_1.newCommand)('project', texts_1.DESC_COMMAND_PROJECT);
12
+ commandProject.alias('proj');
13
+ commandProject.addCommand(list_1.default);
14
+ commandProject.addCommand(set_1.default);
15
+ commandProject.addCommand(get_1.default);
16
+ exports.default = commandProject;
@@ -0,0 +1,71 @@
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 output_1 = __importDefault(require("../../output"));
9
+ const input_1 = __importDefault(require("../../input"));
10
+ const client_1 = __importDefault(require("../../api/client"));
11
+ const fdir_1 = require("fdir");
12
+ const path_1 = require("path");
13
+ const commandSandboxCp = (0, utils_1.newCommand)('cp', texts_1.DESC_COMMAND_SANDBOX_CP);
14
+ commandSandboxCp.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
15
+ commandSandboxCp.option('--api <url>', texts_1.OPTION_REST_API_ENDPOINT);
16
+ commandSandboxCp.option('--region <region>', texts_1.OPTION_REST_API_REGION);
17
+ commandSandboxCp.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
18
+ commandSandboxCp.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
19
+ commandSandboxCp.option('-s, --silent', texts_1.OPTION_SANDBOX_CP_SILENT);
20
+ commandSandboxCp.argument('<source>', texts_1.OPTION_SANDBOX_CP_SOURCE);
21
+ commandSandboxCp.argument('<destination>', texts_1.OPTION_SANDBOX_CP_DEST);
22
+ commandSandboxCp.action(async (source, destination, options) => {
23
+ const token = input_1.default.restApiToken(options.token);
24
+ const baseUrl = input_1.default.restApiBaseUrl(options.api, options.region);
25
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
26
+ const project = input_1.default.restApiProject(options.project);
27
+ const client = new client_1.default(baseUrl, token);
28
+ const result = await client.listSandboxes(workspace, project);
29
+ const sandboxes = result.sandboxes || [];
30
+ const { identifier, remotePath } = input_1.default.restApiSandboxDestinationPath(destination);
31
+ const { sourcePath, sourceStats } = input_1.default.restApiSandboxSourcePath(source);
32
+ const silent = options.silent;
33
+ const found = sandboxes.find((s) => s.identifier === identifier);
34
+ if (!found) {
35
+ output_1.default.exitError(texts_1.ERR_SANDBOX_NOT_FOUND);
36
+ }
37
+ if (sourceStats.isFile()) {
38
+ // Single file copy
39
+ if (!silent) {
40
+ output_1.default.gray((0, texts_1.TXT_SANDBOX_CP_PROGRESS)(1, 1, (0, path_1.basename)(sourcePath)));
41
+ }
42
+ await client.sandboxUploadFile(workspace, found.id, remotePath, sourcePath);
43
+ output_1.default.exitSuccess((0, texts_1.TXT_SANDBOX_CP_DONE)(1));
44
+ }
45
+ else if (sourceStats.isDirectory()) {
46
+ // Directory copy - get all files recursively
47
+ const files = new fdir_1.fdir()
48
+ .withFullPaths()
49
+ .crawl(sourcePath)
50
+ .sync();
51
+ if (files.length === 0) {
52
+ output_1.default.exitSuccess((0, texts_1.TXT_SANDBOX_CP_DONE)(0));
53
+ }
54
+ if (!silent)
55
+ output_1.default.normal(`Copying ${files.length} file(s)...`);
56
+ for (let i = 0; i < files.length; i++) {
57
+ const localFile = files[i];
58
+ const relativePath = (0, path_1.relative)(sourcePath, localFile);
59
+ const remoteFile = (0, path_1.join)(remotePath, relativePath).replace(/\\/g, '/');
60
+ if (!silent) {
61
+ output_1.default.gray((0, texts_1.TXT_SANDBOX_CP_PROGRESS)(i + 1, files.length, relativePath));
62
+ }
63
+ await client.sandboxUploadFile(workspace, found.id, remoteFile, localFile);
64
+ }
65
+ output_1.default.exitSuccess((0, texts_1.TXT_SANDBOX_CP_DONE)(files.length));
66
+ }
67
+ else {
68
+ output_1.default.exitError((0, texts_1.ERR_SANDBOX_CP_SOURCE_NOT_FOUND)(source));
69
+ }
70
+ });
71
+ exports.default = commandSandboxCp;