@salesforce/b2c-cli 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -1
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +14 -1
- package/dist/commands/am/clients/create.d.ts +28 -0
- package/dist/commands/am/clients/create.js +158 -0
- package/dist/commands/am/clients/create.js.map +1 -0
- package/dist/commands/am/clients/delete.d.ts +13 -0
- package/dist/commands/am/clients/delete.js +29 -0
- package/dist/commands/am/clients/delete.js.map +1 -0
- package/dist/commands/am/clients/get.d.ts +26 -0
- package/dist/commands/am/clients/get.js +186 -0
- package/dist/commands/am/clients/get.js.map +1 -0
- package/dist/commands/am/clients/list.d.ts +18 -0
- package/dist/commands/am/clients/list.js +139 -0
- package/dist/commands/am/clients/list.js.map +1 -0
- package/dist/commands/am/clients/password.d.ts +16 -0
- package/dist/commands/am/clients/password.js +51 -0
- package/dist/commands/am/clients/password.js.map +1 -0
- package/dist/commands/am/clients/update.d.ts +34 -0
- package/dist/commands/am/clients/update.js +146 -0
- package/dist/commands/am/clients/update.js.map +1 -0
- package/dist/commands/am/orgs/get.d.ts +23 -0
- package/dist/commands/am/orgs/get.js +175 -0
- package/dist/commands/am/orgs/get.js.map +1 -0
- package/dist/commands/am/orgs/list.d.ts +18 -0
- package/dist/commands/am/orgs/list.js +149 -0
- package/dist/commands/am/orgs/list.js.map +1 -0
- package/dist/commands/am/roles/get.d.ts +15 -0
- package/dist/commands/am/roles/get.js +63 -0
- package/dist/commands/am/roles/get.js.map +1 -0
- package/dist/commands/am/roles/grant.d.ts +18 -0
- package/dist/commands/am/roles/grant.js +72 -0
- package/dist/commands/am/roles/grant.js.map +1 -0
- package/dist/commands/am/roles/list.d.ts +22 -0
- package/dist/commands/am/roles/list.js +142 -0
- package/dist/commands/am/roles/list.js.map +1 -0
- package/dist/commands/am/roles/revoke.d.ts +18 -0
- package/dist/commands/am/roles/revoke.js +72 -0
- package/dist/commands/am/roles/revoke.js.map +1 -0
- package/dist/commands/am/users/create.d.ts +17 -0
- package/dist/commands/am/users/create.js +67 -0
- package/dist/commands/am/users/create.js.map +1 -0
- package/dist/commands/am/users/delete.d.ts +16 -0
- package/dist/commands/am/users/delete.js +63 -0
- package/dist/commands/am/users/delete.js.map +1 -0
- package/dist/commands/am/users/get.d.ts +18 -0
- package/dist/commands/am/users/get.js +96 -0
- package/dist/commands/am/users/get.js.map +1 -0
- package/dist/commands/am/users/list.d.ts +21 -0
- package/dist/commands/am/users/list.js +162 -0
- package/dist/commands/am/users/list.js.map +1 -0
- package/dist/commands/am/users/reset.d.ts +13 -0
- package/dist/commands/am/users/reset.js +43 -0
- package/dist/commands/am/users/reset.js.map +1 -0
- package/dist/commands/am/users/update.d.ts +18 -0
- package/dist/commands/am/users/update.js +63 -0
- package/dist/commands/am/users/update.js.map +1 -0
- package/dist/commands/auth/token.js +1 -1
- package/dist/commands/auth/token.js.map +1 -1
- package/dist/commands/code/activate.d.ts +2 -1
- package/dist/commands/code/delete.d.ts +2 -1
- package/dist/commands/code/deploy.d.ts +2 -1
- package/dist/commands/code/watch.d.ts +2 -1
- package/dist/commands/content/export.d.ts +57 -0
- package/dist/commands/content/export.js +217 -0
- package/dist/commands/content/export.js.map +1 -0
- package/dist/commands/content/list.d.ts +56 -0
- package/dist/commands/content/list.js +133 -0
- package/dist/commands/content/list.js.map +1 -0
- package/dist/commands/docs/download.d.ts +2 -1
- package/dist/commands/ecdn/cache/purge.d.ts +2 -1
- package/dist/commands/ecdn/certificates/add.d.ts +2 -1
- package/dist/commands/ecdn/certificates/delete.d.ts +2 -1
- package/dist/commands/ecdn/certificates/list.d.ts +2 -1
- package/dist/commands/ecdn/certificates/update.d.ts +2 -1
- package/dist/commands/ecdn/certificates/validate.d.ts +2 -1
- package/dist/commands/ecdn/cipher-suites/get.d.ts +2 -1
- package/dist/commands/ecdn/cipher-suites/update.d.ts +2 -1
- package/dist/commands/ecdn/logpush/jobs/create.d.ts +2 -1
- package/dist/commands/ecdn/logpush/jobs/delete.d.ts +2 -1
- package/dist/commands/ecdn/logpush/jobs/get.d.ts +2 -1
- package/dist/commands/ecdn/logpush/jobs/list.d.ts +2 -1
- package/dist/commands/ecdn/logpush/jobs/update.d.ts +2 -1
- package/dist/commands/ecdn/logpush/ownership.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/create.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/delete.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/get.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/rules/delete.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/rules/update.d.ts +2 -1
- package/dist/commands/ecdn/mrt-rules/update.d.ts +2 -1
- package/dist/commands/ecdn/mtls/create.d.ts +2 -1
- package/dist/commands/ecdn/mtls/delete.d.ts +2 -1
- package/dist/commands/ecdn/mtls/get.d.ts +2 -1
- package/dist/commands/ecdn/mtls/list.d.ts +2 -1
- package/dist/commands/ecdn/origin-headers/delete.d.ts +2 -1
- package/dist/commands/ecdn/origin-headers/get.d.ts +2 -1
- package/dist/commands/ecdn/origin-headers/set.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/notifications/create.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/notifications/delete.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/notifications/list.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/policies/create.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/policies/delete.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/policies/get.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/policies/list.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/policies/update.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/scripts/get.d.ts +2 -1
- package/dist/commands/ecdn/page-shield/scripts/list.d.ts +2 -1
- package/dist/commands/ecdn/security/get.d.ts +2 -1
- package/dist/commands/ecdn/security/update.d.ts +2 -1
- package/dist/commands/ecdn/speed/get.d.ts +2 -1
- package/dist/commands/ecdn/speed/update.d.ts +2 -1
- package/dist/commands/ecdn/waf/groups/list.d.ts +2 -1
- package/dist/commands/ecdn/waf/groups/update.d.ts +2 -1
- package/dist/commands/ecdn/waf/managed-rules/list.d.ts +2 -1
- package/dist/commands/ecdn/waf/managed-rules/update.d.ts +2 -1
- package/dist/commands/ecdn/waf/migrate.d.ts +2 -1
- package/dist/commands/ecdn/waf/owasp/get.d.ts +2 -1
- package/dist/commands/ecdn/waf/owasp/update.d.ts +2 -1
- package/dist/commands/ecdn/waf/rules/get.d.ts +2 -1
- package/dist/commands/ecdn/waf/rules/list.d.ts +2 -1
- package/dist/commands/ecdn/waf/rules/update.d.ts +2 -1
- package/dist/commands/ecdn/waf/rulesets/list.d.ts +2 -1
- package/dist/commands/ecdn/waf/rulesets/update.d.ts +2 -1
- package/dist/commands/ecdn/zones/create.d.ts +2 -1
- package/dist/commands/ecdn/zones/list.d.ts +2 -1
- package/dist/commands/job/export.d.ts +2 -1
- package/dist/commands/job/import.d.ts +2 -1
- package/dist/commands/job/run.d.ts +2 -1
- package/dist/commands/job/search.d.ts +2 -1
- package/dist/commands/job/wait.d.ts +2 -1
- package/dist/commands/logs/get.d.ts +2 -1
- package/dist/commands/logs/list.d.ts +2 -1
- package/dist/commands/logs/tail.d.ts +2 -1
- package/dist/commands/mrt/bundle/deploy.js +24 -4
- package/dist/commands/mrt/bundle/deploy.js.map +1 -1
- package/dist/commands/mrt/tail-logs.d.ts +27 -0
- package/dist/commands/mrt/tail-logs.js +137 -0
- package/dist/commands/mrt/tail-logs.js.map +1 -0
- package/dist/commands/{ods → sandbox}/create.d.ts +8 -14
- package/dist/commands/{ods → sandbox}/create.js +112 -102
- package/dist/commands/sandbox/create.js.map +1 -0
- package/dist/commands/sandbox/delete.d.ts +19 -0
- package/dist/commands/sandbox/delete.js +141 -0
- package/dist/commands/sandbox/delete.js.map +1 -0
- package/dist/commands/{ods → sandbox}/get.d.ts +2 -1
- package/dist/commands/{ods → sandbox}/get.js +5 -4
- package/dist/commands/sandbox/get.js.map +1 -0
- package/dist/commands/{ods → sandbox}/info.d.ts +2 -1
- package/dist/commands/{ods → sandbox}/info.js +6 -5
- package/dist/commands/sandbox/info.js.map +1 -0
- package/dist/commands/{ods → sandbox}/list.d.ts +2 -1
- package/dist/commands/{ods → sandbox}/list.js +6 -5
- package/dist/commands/sandbox/list.js.map +1 -0
- package/dist/commands/{ods → sandbox}/restart.d.ts +7 -1
- package/dist/commands/sandbox/restart.js +107 -0
- package/dist/commands/sandbox/restart.js.map +1 -0
- package/dist/commands/{ods → sandbox}/start.d.ts +7 -1
- package/dist/commands/sandbox/start.js +108 -0
- package/dist/commands/sandbox/start.js.map +1 -0
- package/dist/commands/{ods → sandbox}/stop.d.ts +7 -1
- package/dist/commands/sandbox/stop.js +107 -0
- package/dist/commands/sandbox/stop.js.map +1 -0
- package/dist/commands/scaffold/generate.d.ts +22 -0
- package/dist/commands/scaffold/generate.js +74 -0
- package/dist/commands/scaffold/generate.js.map +1 -0
- package/dist/commands/scaffold/index.d.ts +24 -0
- package/dist/commands/scaffold/index.js +80 -0
- package/dist/commands/scaffold/index.js.map +1 -0
- package/dist/commands/scaffold/info.d.ts +24 -0
- package/dist/commands/scaffold/info.js +89 -0
- package/dist/commands/scaffold/info.js.map +1 -0
- package/dist/commands/scaffold/init.d.ts +29 -0
- package/dist/commands/scaffold/init.js +221 -0
- package/dist/commands/scaffold/init.js.map +1 -0
- package/dist/commands/scaffold/list.d.ts +38 -0
- package/dist/commands/scaffold/list.js +131 -0
- package/dist/commands/scaffold/list.js.map +1 -0
- package/dist/commands/scaffold/search.d.ts +32 -0
- package/dist/commands/scaffold/search.js +97 -0
- package/dist/commands/scaffold/search.js.map +1 -0
- package/dist/commands/scaffold/validate.d.ts +24 -0
- package/dist/commands/scaffold/validate.js +74 -0
- package/dist/commands/scaffold/validate.js.map +1 -0
- package/dist/commands/scapi/custom/status.d.ts +2 -1
- package/dist/commands/scapi/schemas/get.d.ts +2 -1
- package/dist/commands/scapi/schemas/list.d.ts +2 -1
- package/dist/commands/setup/index.d.ts +12 -0
- package/dist/commands/setup/index.js +34 -0
- package/dist/commands/setup/index.js.map +1 -0
- package/dist/commands/setup/{config.d.ts → inspect.d.ts} +5 -4
- package/dist/commands/setup/{config.js → inspect.js} +5 -3
- package/dist/commands/setup/inspect.js.map +1 -0
- package/dist/commands/setup/instance/create.d.ts +43 -0
- package/dist/commands/setup/instance/create.js +269 -0
- package/dist/commands/setup/instance/create.js.map +1 -0
- package/dist/commands/setup/instance/index.d.ts +9 -0
- package/dist/commands/setup/instance/index.js +22 -0
- package/dist/commands/setup/instance/index.js.map +1 -0
- package/dist/commands/setup/instance/list.d.ts +31 -0
- package/dist/commands/setup/instance/list.js +68 -0
- package/dist/commands/setup/instance/list.js.map +1 -0
- package/dist/commands/setup/instance/remove.d.ts +34 -0
- package/dist/commands/setup/instance/remove.js +75 -0
- package/dist/commands/setup/instance/remove.js.map +1 -0
- package/dist/commands/setup/instance/set-active.d.ts +33 -0
- package/dist/commands/setup/instance/set-active.js +78 -0
- package/dist/commands/setup/instance/set-active.js.map +1 -0
- package/dist/commands/slas/client/create.d.ts +2 -1
- package/dist/commands/slas/client/create.js +1 -0
- package/dist/commands/slas/client/create.js.map +1 -1
- package/dist/commands/slas/client/delete.d.ts +2 -1
- package/dist/commands/slas/client/get.d.ts +2 -1
- package/dist/commands/slas/client/list.d.ts +2 -1
- package/dist/commands/slas/client/list.js +8 -3
- package/dist/commands/slas/client/list.js.map +1 -1
- package/dist/commands/slas/client/update.d.ts +2 -1
- package/dist/commands/webdav/get.d.ts +2 -1
- package/dist/commands/webdav/rm.d.ts +2 -1
- package/dist/i18n/locales/en.d.ts +42 -0
- package/dist/i18n/locales/en.js +42 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/index.d.ts +42 -0
- package/dist/lib/scaffold/generate-helper.d.ts +47 -0
- package/dist/lib/scaffold/generate-helper.js +271 -0
- package/dist/lib/scaffold/generate-helper.js.map +1 -0
- package/dist/lib/scaffold/source-resolver.d.ts +25 -0
- package/dist/lib/scaffold/source-resolver.js +37 -0
- package/dist/lib/scaffold/source-resolver.js.map +1 -0
- package/dist/utils/am/resolve-org.d.ts +11 -0
- package/dist/utils/am/resolve-org.js +15 -0
- package/dist/utils/am/resolve-org.js.map +1 -0
- package/dist/utils/am/user-display.d.ts +5 -0
- package/dist/utils/am/user-display.js +100 -0
- package/dist/utils/am/user-display.js.map +1 -0
- package/dist/utils/ecdn/zone-command.d.ts +2 -1
- package/dist/utils/mrt-logs/format.d.ts +28 -0
- package/dist/utils/mrt-logs/format.js +90 -0
- package/dist/utils/mrt-logs/format.js.map +1 -0
- package/dist/utils/mrt-logs/index.d.ts +1 -0
- package/dist/utils/mrt-logs/index.js +7 -0
- package/dist/utils/mrt-logs/index.js.map +1 -0
- package/dist/utils/slas/client.d.ts +7 -0
- package/dist/utils/slas/client.js +26 -13
- package/dist/utils/slas/client.js.map +1 -1
- package/oclif.manifest.json +14039 -5107
- package/package.json +61 -19
- package/dist/commands/ods/create.js.map +0 -1
- package/dist/commands/ods/delete.d.ts +0 -15
- package/dist/commands/ods/delete.js +0 -86
- package/dist/commands/ods/delete.js.map +0 -1
- package/dist/commands/ods/get.js.map +0 -1
- package/dist/commands/ods/info.js.map +0 -1
- package/dist/commands/ods/list.js.map +0 -1
- package/dist/commands/ods/restart.js +0 -51
- package/dist/commands/ods/restart.js.map +0 -1
- package/dist/commands/ods/start.js +0 -51
- package/dist/commands/ods/start.js.map +0 -1
- package/dist/commands/ods/stop.js +0 -51
- package/dist/commands/ods/stop.js.map +0 -1
- package/dist/commands/setup/config.js.map +0 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Flags, ux } from '@oclif/core';
|
|
7
|
+
import { MrtCommand } from '@salesforce/b2c-tooling-sdk/cli';
|
|
8
|
+
import { getProfile, tailMrtLogs } from '@salesforce/b2c-tooling-sdk/operations/mrt';
|
|
9
|
+
import { t } from '../../i18n/index.js';
|
|
10
|
+
import { formatMrtEntry, colorLevel, colorHighlight } from '../../utils/mrt-logs/index.js';
|
|
11
|
+
export default class MrtTailLogs extends MrtCommand {
|
|
12
|
+
static description = t('commands.mrt.tail-logs.description', 'Tail application logs from a Managed Runtime environment');
|
|
13
|
+
static enableJsonFlag = true;
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %> -p my-storefront -e staging',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> -p my-storefront -e production --level ERROR --level WARN',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> -p my-storefront -e staging --json',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> -p my-storefront -e staging --search "timeout"',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> -p my-storefront -e staging --search "GET|POST"',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
...MrtCommand.baseFlags,
|
|
23
|
+
level: Flags.string({
|
|
24
|
+
description: 'Filter by log level (ERROR, WARN, INFO, DEBUG, etc.)',
|
|
25
|
+
multiple: true,
|
|
26
|
+
}),
|
|
27
|
+
search: Flags.string({
|
|
28
|
+
char: 'g',
|
|
29
|
+
description: 'Filter entries matching this regex pattern (case-insensitive)',
|
|
30
|
+
}),
|
|
31
|
+
'no-color': Flags.boolean({
|
|
32
|
+
description: 'Disable colored output',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
async run() {
|
|
37
|
+
this.requireMrtCredentials();
|
|
38
|
+
const { mrtProject: project, mrtEnvironment: environment, mrtOrigin: origin } = this.resolvedConfig.values;
|
|
39
|
+
if (!project) {
|
|
40
|
+
this.error('MRT project is required. Provide --project flag, set SFCC_MRT_PROJECT, or set mrtProject in dw.json.');
|
|
41
|
+
}
|
|
42
|
+
if (!environment) {
|
|
43
|
+
this.error('MRT environment is required. Provide --environment flag, set SFCC_MRT_ENVIRONMENT, or set mrtEnvironment in dw.json.');
|
|
44
|
+
}
|
|
45
|
+
const auth = this.getMrtAuth();
|
|
46
|
+
const useColor = !this.flags['no-color'] && process.stdout.isTTY && !this.jsonEnabled();
|
|
47
|
+
const levelFilter = this.flags.level;
|
|
48
|
+
const searchFilter = this.flags.search;
|
|
49
|
+
// Compile search regex (case-insensitive, global for highlighting)
|
|
50
|
+
let searchRegex;
|
|
51
|
+
if (searchFilter) {
|
|
52
|
+
try {
|
|
53
|
+
searchRegex = new RegExp(searchFilter, 'gi');
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
this.error(`Invalid search pattern: "${searchFilter}". Must be a valid regular expression.`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Pre-compute level filter set
|
|
60
|
+
const upperLevels = levelFilter && levelFilter.length > 0 ? new Set(levelFilter.map((l) => l.toUpperCase())) : null;
|
|
61
|
+
// Best-effort user email for WebSocket connection
|
|
62
|
+
let user;
|
|
63
|
+
try {
|
|
64
|
+
const profile = await getProfile({ origin }, auth);
|
|
65
|
+
user = profile.email;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Non-fatal: proceed without user email
|
|
69
|
+
}
|
|
70
|
+
if (!this.jsonEnabled()) {
|
|
71
|
+
this.log(t('commands.mrt.tail-logs.connecting', 'Connecting to {{project}}/{{environment}} logs...', {
|
|
72
|
+
project,
|
|
73
|
+
environment,
|
|
74
|
+
}));
|
|
75
|
+
// Log active filters
|
|
76
|
+
if (upperLevels) {
|
|
77
|
+
const levels = useColor ? [...upperLevels].map((l) => colorLevel(l)).join(', ') : [...upperLevels].join(', ');
|
|
78
|
+
this.log(t('commands.mrt.tail-logs.filterLevel', 'Filtering by level: {{levels}}', { levels }));
|
|
79
|
+
}
|
|
80
|
+
if (searchFilter) {
|
|
81
|
+
const pattern = useColor ? colorHighlight(searchFilter) : searchFilter;
|
|
82
|
+
this.log(t('commands.mrt.tail-logs.filterSearch', 'Filtering by pattern: {{pattern}}', { pattern }));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const { stop, done } = await tailMrtLogs({
|
|
86
|
+
projectSlug: project,
|
|
87
|
+
environmentSlug: environment,
|
|
88
|
+
origin,
|
|
89
|
+
user,
|
|
90
|
+
onEntry: (entry) => {
|
|
91
|
+
// Apply level filter
|
|
92
|
+
if (upperLevels && (!entry.level || !upperLevels.has(entry.level.toUpperCase())))
|
|
93
|
+
return;
|
|
94
|
+
// Apply search filter (regex match against message and raw)
|
|
95
|
+
if (searchRegex) {
|
|
96
|
+
// Reset lastIndex since we reuse the global regex
|
|
97
|
+
searchRegex.lastIndex = 0;
|
|
98
|
+
const matchesMessage = searchRegex.test(entry.message);
|
|
99
|
+
searchRegex.lastIndex = 0;
|
|
100
|
+
const matchesRaw = searchRegex.test(entry.raw);
|
|
101
|
+
if (!matchesMessage && !matchesRaw)
|
|
102
|
+
return;
|
|
103
|
+
// Reset for highlighting pass
|
|
104
|
+
searchRegex.lastIndex = 0;
|
|
105
|
+
}
|
|
106
|
+
if (this.jsonEnabled()) {
|
|
107
|
+
ux.stdout(JSON.stringify(entry));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
ux.stdout(formatMrtEntry(entry, { useColor, searchHighlight: searchRegex }));
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
onConnect: () => {
|
|
114
|
+
if (!this.jsonEnabled()) {
|
|
115
|
+
this.log(t('commands.mrt.tail-logs.connected', 'Connected. Waiting for log entries...'));
|
|
116
|
+
this.log(t('commands.mrt.tail-logs.interrupt', 'Press Ctrl+C to stop.\n'));
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
onError: (error) => {
|
|
120
|
+
this.warn(t('commands.mrt.tail-logs.error', 'WebSocket error: {{message}}', { message: error.message }));
|
|
121
|
+
},
|
|
122
|
+
onClose: (_code, _reason) => {
|
|
123
|
+
if (!this.jsonEnabled()) {
|
|
124
|
+
this.log(t('commands.mrt.tail-logs.disconnected', '\nDisconnected from log stream.'));
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
}, auth);
|
|
128
|
+
// Graceful shutdown on signals
|
|
129
|
+
const handleSignal = () => {
|
|
130
|
+
stop();
|
|
131
|
+
};
|
|
132
|
+
process.on('SIGINT', handleSignal);
|
|
133
|
+
process.on('SIGTERM', handleSignal);
|
|
134
|
+
await done;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=tail-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tail-logs.js","sourceRoot":"","sources":["../../../src/commands/mrt/tail-logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,8 @@ type SandboxModel = OdsComponents['schemas']['SandboxModel'];
|
|
|
4
4
|
/**
|
|
5
5
|
* Command to create a new on-demand sandbox.
|
|
6
6
|
*/
|
|
7
|
-
export default class
|
|
7
|
+
export default class SandboxCreate extends OdsCommand<typeof SandboxCreate> {
|
|
8
|
+
static aliases: string[];
|
|
8
9
|
static description: string;
|
|
9
10
|
static enableJsonFlag: boolean;
|
|
10
11
|
static examples: string[];
|
|
@@ -17,26 +18,19 @@ export default class OdsCreate extends OdsCommand<typeof OdsCreate> {
|
|
|
17
18
|
'poll-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
19
|
timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
20
|
'set-permissions': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
'permissions-client-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
'ocapi-settings': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
'webdav-settings': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
'start-scheduler': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
+
'stop-scheduler': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
26
|
};
|
|
21
27
|
run(): Promise<SandboxModel>;
|
|
22
28
|
/**
|
|
23
29
|
* Builds the sandbox settings object with OCAPI and WebDAV permissions.
|
|
24
|
-
* @param setPermissions - Whether to set permissions for the client ID
|
|
25
30
|
* @returns Settings object or undefined if permissions should not be set
|
|
26
31
|
*/
|
|
27
32
|
private buildSettings;
|
|
33
|
+
private parseJsonFlag;
|
|
28
34
|
private printSandboxSummary;
|
|
29
|
-
/**
|
|
30
|
-
* Sleep for a given number of milliseconds.
|
|
31
|
-
*/
|
|
32
|
-
private sleep;
|
|
33
|
-
/**
|
|
34
|
-
* Polls for sandbox status until it reaches a terminal state.
|
|
35
|
-
* @param sandboxId - The sandbox ID to poll
|
|
36
|
-
* @param pollIntervalSeconds - Interval between polls in seconds
|
|
37
|
-
* @param timeoutSeconds - Maximum time to wait (0 for no timeout)
|
|
38
|
-
* @returns The final sandbox state
|
|
39
|
-
*/
|
|
40
|
-
private waitForSandbox;
|
|
41
35
|
}
|
|
42
36
|
export {};
|
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
import { Flags, ux } from '@oclif/core';
|
|
7
7
|
import cliui from 'cliui';
|
|
8
8
|
import { OdsCommand } from '@salesforce/b2c-tooling-sdk/cli';
|
|
9
|
-
import { getApiErrorMessage } from '@salesforce/b2c-tooling-sdk';
|
|
9
|
+
import { getApiErrorMessage, SandboxPollingError, SandboxPollingTimeoutError, SandboxTerminalStateError, waitForSandbox, } from '@salesforce/b2c-tooling-sdk';
|
|
10
10
|
import { t, withDocs } from '../../i18n/index.js';
|
|
11
|
-
/** States that indicate sandbox creation has completed (success or failure) */
|
|
12
|
-
const TERMINAL_STATES = new Set(['deleted', 'failed', 'started']);
|
|
13
11
|
/**
|
|
14
12
|
* Default OCAPI resources to grant the client ID access to.
|
|
15
13
|
* These enable common CI/CD operations like code deployment and job execution.
|
|
@@ -33,8 +31,9 @@ const DEFAULT_WEBDAV_PERMISSIONS = [
|
|
|
33
31
|
/**
|
|
34
32
|
* Command to create a new on-demand sandbox.
|
|
35
33
|
*/
|
|
36
|
-
export default class
|
|
37
|
-
static
|
|
34
|
+
export default class SandboxCreate extends OdsCommand {
|
|
35
|
+
static aliases = ['ods:create'];
|
|
36
|
+
static description = withDocs(t('commands.sandbox.create.description', 'Create a new on-demand sandbox'), '/cli/sandbox.html#b2c-sandbox-create');
|
|
38
37
|
static enableJsonFlag = true;
|
|
39
38
|
static examples = [
|
|
40
39
|
'<%= config.bin %> <%= command.id %> --realm abcd',
|
|
@@ -84,6 +83,21 @@ export default class OdsCreate extends OdsCommand {
|
|
|
84
83
|
default: true,
|
|
85
84
|
allowNo: true,
|
|
86
85
|
}),
|
|
86
|
+
'permissions-client-id': Flags.string({
|
|
87
|
+
description: 'Client ID to use for default OCAPI/WebDAV permissions (defaults to auth client ID)',
|
|
88
|
+
}),
|
|
89
|
+
'ocapi-settings': Flags.string({
|
|
90
|
+
description: 'Custom OCAPI settings JSON array (replaces defaults). Format: [{"client_id":"...","resources":[...]}]',
|
|
91
|
+
}),
|
|
92
|
+
'webdav-settings': Flags.string({
|
|
93
|
+
description: 'Custom WebDAV settings JSON array (replaces defaults). Format: [{"client_id":"...","permissions":[...]}]',
|
|
94
|
+
}),
|
|
95
|
+
'start-scheduler': Flags.string({
|
|
96
|
+
description: 'Start schedule JSON. Format: {"weekdays":["MONDAY",...],"time":"08:00:00+03:00"}',
|
|
97
|
+
}),
|
|
98
|
+
'stop-scheduler': Flags.string({
|
|
99
|
+
description: 'Stop schedule JSON. Format: {"weekdays":["MONDAY",...],"time":"19:00:00Z"}',
|
|
100
|
+
}),
|
|
87
101
|
};
|
|
88
102
|
async run() {
|
|
89
103
|
const realm = this.flags.realm;
|
|
@@ -94,14 +108,29 @@ export default class OdsCreate extends OdsCommand {
|
|
|
94
108
|
const pollInterval = this.flags['poll-interval'];
|
|
95
109
|
const timeout = this.flags.timeout;
|
|
96
110
|
const setPermissions = this.flags['set-permissions'];
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
|
|
111
|
+
const permissionsClientId = this.flags['permissions-client-id'];
|
|
112
|
+
const ocapiSettingsRaw = this.flags['ocapi-settings'];
|
|
113
|
+
const webdavSettingsRaw = this.flags['webdav-settings'];
|
|
114
|
+
const startSchedulerRaw = this.flags['start-scheduler'];
|
|
115
|
+
const stopSchedulerRaw = this.flags['stop-scheduler'];
|
|
116
|
+
this.log(t('commands.sandbox.create.creating', 'Creating sandbox in realm {{realm}}...', { realm }));
|
|
117
|
+
this.log(t('commands.sandbox.create.profile', 'Profile: {{profile}}', { profile }));
|
|
118
|
+
this.log(t('commands.sandbox.create.ttl', 'TTL: {{ttl}} hours', { ttl: ttl === 0 ? 'infinite' : String(ttl) }));
|
|
100
119
|
// Build settings with OCAPI and WebDAV permissions if enabled
|
|
101
|
-
const settings = this.buildSettings(
|
|
120
|
+
const settings = this.buildSettings({
|
|
121
|
+
setPermissions,
|
|
122
|
+
permissionsClientId,
|
|
123
|
+
ocapiSettings: ocapiSettingsRaw,
|
|
124
|
+
webdavSettings: webdavSettingsRaw,
|
|
125
|
+
});
|
|
102
126
|
if (settings) {
|
|
103
|
-
|
|
127
|
+
const effectiveClientId = permissionsClientId || this.resolvedConfig.values.clientId;
|
|
128
|
+
const hasCustom = ocapiSettingsRaw || webdavSettingsRaw;
|
|
129
|
+
this.log(t('commands.sandbox.create.settingPermissions', 'Setting OCAPI and WebDAV permissions for client ID: {{clientId}}', { clientId: hasCustom ? 'custom settings' : effectiveClientId }));
|
|
104
130
|
}
|
|
131
|
+
// Parse scheduler flags
|
|
132
|
+
const startScheduler = startSchedulerRaw ? this.parseJsonFlag('start-scheduler', startSchedulerRaw) : undefined;
|
|
133
|
+
const stopScheduler = stopSchedulerRaw ? this.parseJsonFlag('stop-scheduler', stopSchedulerRaw) : undefined;
|
|
105
134
|
const result = await this.odsClient.POST('/sandboxes', {
|
|
106
135
|
body: {
|
|
107
136
|
realm,
|
|
@@ -110,19 +139,63 @@ export default class OdsCreate extends OdsCommand {
|
|
|
110
139
|
autoScheduled,
|
|
111
140
|
analyticsEnabled: false,
|
|
112
141
|
settings,
|
|
142
|
+
startScheduler,
|
|
143
|
+
stopScheduler,
|
|
113
144
|
},
|
|
114
145
|
});
|
|
115
146
|
if (!result.data?.data) {
|
|
116
|
-
this.error(t('commands.
|
|
147
|
+
this.error(t('commands.sandbox.create.error', 'Failed to create sandbox: {{message}}', {
|
|
117
148
|
message: getApiErrorMessage(result.error, result.response),
|
|
118
149
|
}));
|
|
119
150
|
}
|
|
120
151
|
let sandbox = result.data.data;
|
|
121
152
|
this.log('');
|
|
122
|
-
this.logger.info({ sandboxId: sandbox.id }, t('commands.
|
|
153
|
+
this.logger.info({ sandboxId: sandbox.id }, t('commands.sandbox.create.success', 'Sandbox created successfully'));
|
|
123
154
|
if (wait && sandbox.id) {
|
|
155
|
+
this.log(t('commands.sandbox.create.waiting', 'Waiting for sandbox to get started..'));
|
|
156
|
+
try {
|
|
157
|
+
await waitForSandbox(this.odsClient, {
|
|
158
|
+
sandboxId: sandbox.id,
|
|
159
|
+
targetState: 'started',
|
|
160
|
+
pollIntervalSeconds: pollInterval,
|
|
161
|
+
timeoutSeconds: timeout,
|
|
162
|
+
onPoll: ({ elapsedSeconds, state }) => {
|
|
163
|
+
this.logger.info({ sandboxId: sandbox.id, elapsed: elapsedSeconds, state }, `[${elapsedSeconds}s] State: ${state}`);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (error instanceof SandboxPollingTimeoutError) {
|
|
169
|
+
this.error(t('commands.sandbox.create.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
|
|
170
|
+
seconds: String(error.timeoutSeconds),
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
if (error instanceof SandboxTerminalStateError) {
|
|
174
|
+
if (error.state === 'deleted') {
|
|
175
|
+
this.error(t('commands.sandbox.create.deleted', 'Sandbox was deleted'));
|
|
176
|
+
}
|
|
177
|
+
this.error(t('commands.sandbox.create.failed', 'Sandbox creation failed'));
|
|
178
|
+
}
|
|
179
|
+
if (error instanceof SandboxPollingError) {
|
|
180
|
+
this.error(t('commands.sandbox.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
|
|
181
|
+
message: error.message,
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
const finalResult = await this.odsClient.GET('/sandboxes/{sandboxId}', {
|
|
187
|
+
params: {
|
|
188
|
+
path: { sandboxId: sandbox.id },
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
if (!finalResult.data?.data) {
|
|
192
|
+
this.error(t('commands.sandbox.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
|
|
193
|
+
message: finalResult.response?.statusText || 'Unknown error',
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
sandbox = finalResult.data.data;
|
|
124
197
|
this.log('');
|
|
125
|
-
|
|
198
|
+
this.logger.info({ sandboxId: sandbox.id }, t('commands.sandbox.create.ready', 'Sandbox is now ready'));
|
|
126
199
|
}
|
|
127
200
|
if (this.jsonEnabled()) {
|
|
128
201
|
return sandbox;
|
|
@@ -132,31 +205,38 @@ export default class OdsCreate extends OdsCommand {
|
|
|
132
205
|
}
|
|
133
206
|
/**
|
|
134
207
|
* Builds the sandbox settings object with OCAPI and WebDAV permissions.
|
|
135
|
-
* @param setPermissions - Whether to set permissions for the client ID
|
|
136
208
|
* @returns Settings object or undefined if permissions should not be set
|
|
137
209
|
*/
|
|
138
|
-
buildSettings(
|
|
139
|
-
if (!setPermissions) {
|
|
210
|
+
buildSettings(options) {
|
|
211
|
+
if (!options.setPermissions) {
|
|
140
212
|
return undefined;
|
|
141
213
|
}
|
|
142
|
-
const
|
|
143
|
-
|
|
214
|
+
const hasCustomOcapi = options.ocapiSettings !== undefined;
|
|
215
|
+
const hasCustomWebdav = options.webdavSettings !== undefined;
|
|
216
|
+
const clientId = options.permissionsClientId || this.resolvedConfig.values.clientId;
|
|
217
|
+
// If no custom settings and no client ID, we can't build defaults
|
|
218
|
+
if (!hasCustomOcapi && !hasCustomWebdav && !clientId) {
|
|
144
219
|
return undefined;
|
|
145
220
|
}
|
|
146
|
-
|
|
147
|
-
ocapi
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
221
|
+
const ocapi = hasCustomOcapi
|
|
222
|
+
? this.parseJsonFlag('ocapi-settings', options.ocapiSettings)
|
|
223
|
+
: clientId
|
|
224
|
+
? [{ client_id: clientId, resources: DEFAULT_OCAPI_RESOURCES }]
|
|
225
|
+
: [];
|
|
226
|
+
const webdav = hasCustomWebdav
|
|
227
|
+
? this.parseJsonFlag('webdav-settings', options.webdavSettings)
|
|
228
|
+
: clientId
|
|
229
|
+
? [{ client_id: clientId, permissions: DEFAULT_WEBDAV_PERMISSIONS }]
|
|
230
|
+
: [];
|
|
231
|
+
return { ocapi, webdav };
|
|
232
|
+
}
|
|
233
|
+
parseJsonFlag(flagName, value) {
|
|
234
|
+
try {
|
|
235
|
+
return JSON.parse(value);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
this.error(`Invalid JSON for --${flagName}: ${value}`);
|
|
239
|
+
}
|
|
160
240
|
}
|
|
161
241
|
printSandboxSummary(sandbox) {
|
|
162
242
|
const ui = cliui({ width: process.stdout.columns || 80 });
|
|
@@ -180,75 +260,5 @@ export default class OdsCreate extends OdsCommand {
|
|
|
180
260
|
}
|
|
181
261
|
ux.stdout(ui.toString());
|
|
182
262
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Sleep for a given number of milliseconds.
|
|
185
|
-
*/
|
|
186
|
-
async sleep(ms) {
|
|
187
|
-
await new Promise((resolve) => {
|
|
188
|
-
setTimeout(resolve, ms);
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Polls for sandbox status until it reaches a terminal state.
|
|
193
|
-
* @param sandboxId - The sandbox ID to poll
|
|
194
|
-
* @param pollIntervalSeconds - Interval between polls in seconds
|
|
195
|
-
* @param timeoutSeconds - Maximum time to wait (0 for no timeout)
|
|
196
|
-
* @returns The final sandbox state
|
|
197
|
-
*/
|
|
198
|
-
async waitForSandbox(sandboxId, pollIntervalSeconds, timeoutSeconds) {
|
|
199
|
-
const startTime = Date.now();
|
|
200
|
-
const pollIntervalMs = pollIntervalSeconds * 1000;
|
|
201
|
-
const timeoutMs = timeoutSeconds * 1000;
|
|
202
|
-
this.log(t('commands.ods.create.waiting', 'Waiting for sandbox to be ready...'));
|
|
203
|
-
// Initial delay before first poll to allow the sandbox to be registered in the API
|
|
204
|
-
await this.sleep(pollIntervalMs);
|
|
205
|
-
while (true) {
|
|
206
|
-
// Check for timeout
|
|
207
|
-
if (timeoutSeconds > 0 && Date.now() - startTime > timeoutMs) {
|
|
208
|
-
this.error(t('commands.ods.create.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
|
|
209
|
-
seconds: String(timeoutSeconds),
|
|
210
|
-
}));
|
|
211
|
-
}
|
|
212
|
-
// eslint-disable-next-line no-await-in-loop
|
|
213
|
-
const result = await this.odsClient.GET('/sandboxes/{sandboxId}', {
|
|
214
|
-
params: {
|
|
215
|
-
path: { sandboxId },
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
if (!result.data?.data) {
|
|
219
|
-
this.error(t('commands.ods.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
|
|
220
|
-
message: result.response?.statusText || 'Unknown error',
|
|
221
|
-
}));
|
|
222
|
-
}
|
|
223
|
-
const sandbox = result.data.data;
|
|
224
|
-
const currentState = sandbox.state;
|
|
225
|
-
// Log current state on each poll
|
|
226
|
-
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
227
|
-
const state = currentState || 'unknown';
|
|
228
|
-
this.logger.info({ sandboxId, elapsed, state }, `[${elapsed}s] State: ${state}`);
|
|
229
|
-
// Check for terminal states
|
|
230
|
-
if (currentState && TERMINAL_STATES.has(currentState)) {
|
|
231
|
-
switch (currentState) {
|
|
232
|
-
case 'deleted': {
|
|
233
|
-
this.error(t('commands.ods.create.deleted', 'Sandbox was deleted'));
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
case 'failed': {
|
|
237
|
-
this.error(t('commands.ods.create.failed', 'Sandbox creation failed'));
|
|
238
|
-
break;
|
|
239
|
-
}
|
|
240
|
-
case 'started': {
|
|
241
|
-
this.log('');
|
|
242
|
-
this.logger.info({ sandboxId }, t('commands.ods.create.ready', 'Sandbox is now ready'));
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
return sandbox;
|
|
247
|
-
}
|
|
248
|
-
// Wait before next poll
|
|
249
|
-
// eslint-disable-next-line no-await-in-loop
|
|
250
|
-
await this.sleep(pollIntervalMs);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
263
|
}
|
|
254
264
|
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/sandbox/create.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAC,KAAK,EAAE,EAAE,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,UAAU,EAAC,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,yBAAyB,EACzB,cAAc,GAEf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAC,CAAC,EAAE,QAAQ,EAAC,MAAM,qBAAqB,CAAC;AAQhD;;;GAGG;AAEH,MAAM,uBAAuB,GAAoD;IAC/E,EAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAC;IACpG,EAAC,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAC;IAClH,EAAC,WAAW,EAAE,oBAAoB,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAC;IACzG,EAAC,WAAW,EAAE,sBAAsB,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAC;IAC1G,EAAC,WAAW,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAC;CAC3G,CAAC;AAEF;;;GAGG;AACH,MAAM,0BAA0B,GAA0C;IACxE,EAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,YAAY,CAAC,EAAC;IAC5C,EAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,YAAY,CAAC,EAAC;IACjD,EAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,YAAY,CAAC,EAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAgC;IACzE,MAAM,CAAC,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC;IAEhC,MAAM,CAAC,WAAW,GAAG,QAAQ,CAC3B,CAAC,CAAC,qCAAqC,EAAE,gCAAgC,CAAC,EAC1E,sCAAsC,CACvC,CAAC;IAEF,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAE7B,MAAM,CAAC,QAAQ,GAAG;QAChB,kDAAkD;QAClD,2DAA2D;QAC3D,kEAAkE;QAClE,mEAAmE;QACnE,yDAAyD;QACzD,4EAA4E;QAC5E,yDAAyD;KAC1D,CAAC;IAEF,MAAM,CAAC,KAAK,GAAG;QACb,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,2BAA2B;YACxC,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;YACjB,WAAW,EAAE,wCAAwC;YACrD,OAAO,EAAE,EAAE;SACZ,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;SAClD,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC;YAC9B,WAAW,EAAE,wCAAwC;YACrD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,wEAAwE;YACrF,OAAO,EAAE,KAAK;SACf,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;YAC7B,WAAW,EAAE,+CAA+C;YAC5D,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,CAAC,MAAM,CAAC;SACpB,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,WAAW,EAAE,sEAAsE;YACnF,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,CAAC,MAAM,CAAC;SACpB,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,OAAO,CAAC;YAC/B,WAAW,EAAE,6FAA6F;YAC1G,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;SACd,CAAC;QACF,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC;YACpC,WAAW,EAAE,oFAAoF;SAClG,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC7B,WAAW,EACT,uGAAuG;SAC1G,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC9B,WAAW,EACT,0GAA0G;SAC7G,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC9B,WAAW,EAAE,kFAAkF;SAChG,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC7B,WAAW,EAAE,4EAA4E;SAC1F,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAiC,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAC3B,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACnC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACrD,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxD,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAEtD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,kCAAkC,EAAE,wCAAwC,EAAE,EAAC,KAAK,EAAC,CAAC,CAAC,CAAC;QACnG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,iCAAiC,EAAE,sBAAsB,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,6BAA6B,EAAE,oBAAoB,EAAE,EAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAC,CAAC,CAAC,CAAC;QAE9G,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;YAClC,cAAc;YACd,mBAAmB;YACnB,aAAa,EAAE,gBAAgB;YAC/B,cAAc,EAAE,iBAAiB;SAClC,CAAC,CAAC;QACH,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,iBAAiB,GAAG,mBAAmB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;YACrF,MAAM,SAAS,GAAG,gBAAgB,IAAI,iBAAiB,CAAC;YACxD,IAAI,CAAC,GAAG,CACN,CAAC,CACC,4CAA4C,EAC5C,kEAAkE,EAClE,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAkB,EAAC,CAC/D,CACF,CAAC;QACJ,CAAC;QAED,wBAAwB;QACxB,MAAM,cAAc,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChH,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5G,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE;YACrD,IAAI,EAAE;gBACJ,KAAK;gBACL,GAAG;gBACH,eAAe,EAAE,OAAO;gBACxB,aAAa;gBACb,gBAAgB,EAAE,KAAK;gBACvB,QAAQ;gBACR,cAAc;gBACd,aAAa;aACd;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CACR,CAAC,CAAC,+BAA+B,EAAE,uCAAuC,EAAE;gBAC1E,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;aAC3D,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QAE/B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAC,EAAE,CAAC,CAAC,iCAAiC,EAAE,8BAA8B,CAAC,CAAC,CAAC;QAEhH,IAAI,IAAI,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,iCAAiC,EAAE,sCAAsC,CAAC,CAAC,CAAC;YAEvF,IAAI,CAAC;gBACH,MAAM,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE;oBACnC,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,WAAW,EAAE,SAAS;oBACtB,mBAAmB,EAAE,YAAY;oBACjC,cAAc,EAAE,OAAO;oBACvB,MAAM,EAAE,CAAC,EAAC,cAAc,EAAE,KAAK,EAAC,EAAE,EAAE;wBAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAC,EACvD,IAAI,cAAc,aAAa,KAAK,EAAE,CACvC,CAAC;oBACJ,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,0BAA0B,EAAE,CAAC;oBAChD,IAAI,CAAC,KAAK,CACR,CAAC,CAAC,iCAAiC,EAAE,uDAAuD,EAAE;wBAC5F,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;qBACtC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,IAAI,KAAK,YAAY,yBAAyB,EAAE,CAAC;oBAC/C,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;wBAC9B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iCAAiC,EAAE,qBAAqB,CAAC,CAAC,CAAC;oBAC1E,CAAC;oBACD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,gCAAgC,EAAE,yBAAyB,CAAC,CAAC,CAAC;gBAC7E,CAAC;gBAED,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;oBACzC,IAAI,CAAC,KAAK,CACR,CAAC,CAAC,mCAAmC,EAAE,6CAA6C,EAAE;wBACpF,OAAO,EAAE,KAAK,CAAC,OAAO;qBACvB,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,wBAAwB,EAAE;gBACrE,MAAM,EAAE;oBACN,IAAI,EAAE,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAC;iBAC9B;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,KAAK,CACR,CAAC,CAAC,mCAAmC,EAAE,6CAA6C,EAAE;oBACpF,OAAO,EAAE,WAAW,CAAC,QAAQ,EAAE,UAAU,IAAI,eAAe;iBAC7D,CAAC,CACH,CAAC;YACJ,CAAC;YAED,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YAEhC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAC,EAAE,CAAC,CAAC,+BAA+B,EAAE,sBAAsB,CAAC,CAAC,CAAC;QACxG,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAElC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,aAAa,CAAC,OAKrB;QACC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC;QAC3D,MAAM,eAAe,GAAG,OAAO,CAAC,cAAc,KAAK,SAAS,CAAC;QAE7D,MAAM,QAAQ,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;QAEpF,kEAAkE;QAClE,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAkB,cAAc;YACzC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,aAAc,CAAC;YAC9D,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,uBAAuB,EAAC,CAAC;gBAC7D,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,MAAM,GAAmB,eAAe;YAC5C,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,OAAO,CAAC,cAAe,CAAC;YAChE,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAC,CAAC;gBAClE,CAAC,CAAC,EAAE,CAAC;QAET,OAAO,EAAC,KAAK,EAAE,MAAM,EAAC,CAAC;IACzB,CAAC;IAEO,aAAa,CAAI,QAAgB,EAAE,KAAa;QACtD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,KAAK,CAAC,sBAAsB,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,OAAqB;QAC/C,MAAM,EAAE,GAAG,KAAK,CAAC,EAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,EAAC,CAAC,CAAC;QAExD,EAAE,CAAC,GAAG,CAAC,EAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAmC;YAC7C,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAClB,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC;YACxB,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;YAC9B,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC;YACxB,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC;YACpC,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;SAC/B,CAAC;QAEF,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,EAAE,CAAC,GAAG,CAAC,EAAC,IAAI,EAAE,GAAG,KAAK,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;YACtG,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;YACtB,EAAE,CAAC,GAAG,CAAC,EAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;YAC1C,EAAE,CAAC,GAAG,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,EAAE,EAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;QAC/G,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OdsCommand } from '@salesforce/b2c-tooling-sdk/cli';
|
|
2
|
+
/**
|
|
3
|
+
* Command to delete an on-demand sandbox.
|
|
4
|
+
*/
|
|
5
|
+
export default class SandboxDelete extends OdsCommand<typeof SandboxDelete> {
|
|
6
|
+
static aliases: string[];
|
|
7
|
+
static args: {
|
|
8
|
+
sandboxId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
|
+
};
|
|
10
|
+
static description: string;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
static flags: {
|
|
13
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
wait: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'poll-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as readline from 'node:readline';
|
|
7
|
+
import { Args, Flags } from '@oclif/core';
|
|
8
|
+
import { OdsCommand } from '@salesforce/b2c-tooling-sdk/cli';
|
|
9
|
+
import { getApiErrorMessage, SandboxPollingError, SandboxPollingTimeoutError, SandboxTerminalStateError, waitForSandbox, } from '@salesforce/b2c-tooling-sdk';
|
|
10
|
+
import { t, withDocs } from '../../i18n/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Simple confirmation prompt.
|
|
13
|
+
*/
|
|
14
|
+
async function confirm(message) {
|
|
15
|
+
const rl = readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stderr,
|
|
18
|
+
});
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
rl.question(`${message} `, (answer) => {
|
|
21
|
+
rl.close();
|
|
22
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Command to delete an on-demand sandbox.
|
|
28
|
+
*/
|
|
29
|
+
export default class SandboxDelete extends OdsCommand {
|
|
30
|
+
static aliases = ['ods:delete'];
|
|
31
|
+
static args = {
|
|
32
|
+
sandboxId: Args.string({
|
|
33
|
+
description: 'Sandbox ID (UUID or realm-instance, e.g., abcd-123)',
|
|
34
|
+
required: true,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
static description = withDocs(t('commands.sandbox.delete.description', 'Delete an on-demand sandbox'), '/cli/sandbox.html#b2c-sandbox-delete');
|
|
38
|
+
static examples = [
|
|
39
|
+
'<%= config.bin %> <%= command.id %> abc12345-1234-1234-1234-abc123456789',
|
|
40
|
+
'<%= config.bin %> <%= command.id %> zzzv-123',
|
|
41
|
+
'<%= config.bin %> <%= command.id %> zzzv_123 --force',
|
|
42
|
+
];
|
|
43
|
+
static flags = {
|
|
44
|
+
force: Flags.boolean({
|
|
45
|
+
char: 'f',
|
|
46
|
+
description: 'Skip confirmation prompt',
|
|
47
|
+
default: false,
|
|
48
|
+
}),
|
|
49
|
+
wait: Flags.boolean({
|
|
50
|
+
char: 'w',
|
|
51
|
+
description: 'Wait for the sandbox to be fully deleted before returning',
|
|
52
|
+
default: false,
|
|
53
|
+
}),
|
|
54
|
+
'poll-interval': Flags.integer({
|
|
55
|
+
description: 'Polling interval in seconds when using --wait',
|
|
56
|
+
default: 10,
|
|
57
|
+
dependsOn: ['wait'],
|
|
58
|
+
}),
|
|
59
|
+
timeout: Flags.integer({
|
|
60
|
+
description: 'Maximum time to wait in seconds when using --wait (0 for no timeout)',
|
|
61
|
+
default: 600,
|
|
62
|
+
dependsOn: ['wait'],
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
async run() {
|
|
66
|
+
const sandboxId = await this.resolveSandboxId(this.args.sandboxId);
|
|
67
|
+
const wait = this.flags.wait;
|
|
68
|
+
const pollInterval = this.flags['poll-interval'];
|
|
69
|
+
const timeout = this.flags.timeout;
|
|
70
|
+
// Get sandbox details first to show in confirmation
|
|
71
|
+
const getResult = await this.odsClient.GET('/sandboxes/{sandboxId}', {
|
|
72
|
+
params: {
|
|
73
|
+
path: { sandboxId },
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (!getResult.data?.data) {
|
|
77
|
+
this.error(t('commands.sandbox.delete.notFound', 'Sandbox not found: {{sandboxId}}', { sandboxId }));
|
|
78
|
+
}
|
|
79
|
+
const sandbox = getResult.data.data;
|
|
80
|
+
const sandboxInfo = `${sandbox.realm}/${sandbox.instance || sandboxId}`;
|
|
81
|
+
// Confirm deletion unless --force is used
|
|
82
|
+
if (!this.flags.force) {
|
|
83
|
+
const confirmed = await confirm(t('commands.sandbox.delete.confirm', 'Are you sure you want to delete sandbox "{{sandboxInfo}}"? (y/n)', {
|
|
84
|
+
sandboxInfo,
|
|
85
|
+
}));
|
|
86
|
+
if (!confirmed) {
|
|
87
|
+
this.log(t('commands.sandbox.delete.cancelled', 'Deletion cancelled'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.log(t('commands.sandbox.delete.deleting', 'Deleting sandbox {{sandboxInfo}}...', { sandboxInfo }));
|
|
92
|
+
const result = await this.odsClient.DELETE('/sandboxes/{sandboxId}', {
|
|
93
|
+
params: {
|
|
94
|
+
path: { sandboxId },
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
if (result.response.status !== 202) {
|
|
98
|
+
this.error(t('commands.sandbox.delete.error', 'Failed to delete sandbox: {{message}}', {
|
|
99
|
+
message: getApiErrorMessage(result.error, result.response),
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
this.log(t('commands.sandbox.delete.success', 'Sandbox deletion initiated. The sandbox will be removed shortly.'));
|
|
103
|
+
if (wait) {
|
|
104
|
+
this.log(t('commands.sandbox.delete.waiting', 'Waiting for sandbox to reach state {{state}}...', {
|
|
105
|
+
state: 'deleted',
|
|
106
|
+
}));
|
|
107
|
+
try {
|
|
108
|
+
await waitForSandbox(this.odsClient, {
|
|
109
|
+
sandboxId,
|
|
110
|
+
targetState: 'deleted',
|
|
111
|
+
pollIntervalSeconds: pollInterval,
|
|
112
|
+
timeoutSeconds: timeout,
|
|
113
|
+
onPoll: ({ elapsedSeconds, state }) => {
|
|
114
|
+
this.logger.info({ sandboxId, elapsed: elapsedSeconds, state }, `[${elapsedSeconds}s] State: ${state}`);
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error instanceof SandboxPollingTimeoutError) {
|
|
120
|
+
this.error(t('commands.sandbox.delete.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
|
|
121
|
+
seconds: String(error.timeoutSeconds),
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
if (error instanceof SandboxTerminalStateError) {
|
|
125
|
+
this.error(t('commands.sandbox.delete.failed', 'Sandbox did not reach the expected state. Current state: {{state}}', {
|
|
126
|
+
state: error.state || 'unknown',
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
if (error instanceof SandboxPollingError) {
|
|
130
|
+
this.error(t('commands.sandbox.delete.pollError', 'Failed to fetch sandbox status: {{message}}', {
|
|
131
|
+
message: error.message,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
this.log('');
|
|
137
|
+
this.logger.info({ sandboxId }, t('commands.sandbox.delete.ready', 'Sandbox is now deleted'));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=delete.js.map
|