@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.
Files changed (260) hide show
  1. package/README.md +70 -1
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +14 -1
  4. package/dist/commands/am/clients/create.d.ts +28 -0
  5. package/dist/commands/am/clients/create.js +158 -0
  6. package/dist/commands/am/clients/create.js.map +1 -0
  7. package/dist/commands/am/clients/delete.d.ts +13 -0
  8. package/dist/commands/am/clients/delete.js +29 -0
  9. package/dist/commands/am/clients/delete.js.map +1 -0
  10. package/dist/commands/am/clients/get.d.ts +26 -0
  11. package/dist/commands/am/clients/get.js +186 -0
  12. package/dist/commands/am/clients/get.js.map +1 -0
  13. package/dist/commands/am/clients/list.d.ts +18 -0
  14. package/dist/commands/am/clients/list.js +139 -0
  15. package/dist/commands/am/clients/list.js.map +1 -0
  16. package/dist/commands/am/clients/password.d.ts +16 -0
  17. package/dist/commands/am/clients/password.js +51 -0
  18. package/dist/commands/am/clients/password.js.map +1 -0
  19. package/dist/commands/am/clients/update.d.ts +34 -0
  20. package/dist/commands/am/clients/update.js +146 -0
  21. package/dist/commands/am/clients/update.js.map +1 -0
  22. package/dist/commands/am/orgs/get.d.ts +23 -0
  23. package/dist/commands/am/orgs/get.js +175 -0
  24. package/dist/commands/am/orgs/get.js.map +1 -0
  25. package/dist/commands/am/orgs/list.d.ts +18 -0
  26. package/dist/commands/am/orgs/list.js +149 -0
  27. package/dist/commands/am/orgs/list.js.map +1 -0
  28. package/dist/commands/am/roles/get.d.ts +15 -0
  29. package/dist/commands/am/roles/get.js +63 -0
  30. package/dist/commands/am/roles/get.js.map +1 -0
  31. package/dist/commands/am/roles/grant.d.ts +18 -0
  32. package/dist/commands/am/roles/grant.js +72 -0
  33. package/dist/commands/am/roles/grant.js.map +1 -0
  34. package/dist/commands/am/roles/list.d.ts +22 -0
  35. package/dist/commands/am/roles/list.js +142 -0
  36. package/dist/commands/am/roles/list.js.map +1 -0
  37. package/dist/commands/am/roles/revoke.d.ts +18 -0
  38. package/dist/commands/am/roles/revoke.js +72 -0
  39. package/dist/commands/am/roles/revoke.js.map +1 -0
  40. package/dist/commands/am/users/create.d.ts +17 -0
  41. package/dist/commands/am/users/create.js +67 -0
  42. package/dist/commands/am/users/create.js.map +1 -0
  43. package/dist/commands/am/users/delete.d.ts +16 -0
  44. package/dist/commands/am/users/delete.js +63 -0
  45. package/dist/commands/am/users/delete.js.map +1 -0
  46. package/dist/commands/am/users/get.d.ts +18 -0
  47. package/dist/commands/am/users/get.js +96 -0
  48. package/dist/commands/am/users/get.js.map +1 -0
  49. package/dist/commands/am/users/list.d.ts +21 -0
  50. package/dist/commands/am/users/list.js +162 -0
  51. package/dist/commands/am/users/list.js.map +1 -0
  52. package/dist/commands/am/users/reset.d.ts +13 -0
  53. package/dist/commands/am/users/reset.js +43 -0
  54. package/dist/commands/am/users/reset.js.map +1 -0
  55. package/dist/commands/am/users/update.d.ts +18 -0
  56. package/dist/commands/am/users/update.js +63 -0
  57. package/dist/commands/am/users/update.js.map +1 -0
  58. package/dist/commands/auth/token.js +1 -1
  59. package/dist/commands/auth/token.js.map +1 -1
  60. package/dist/commands/code/activate.d.ts +2 -1
  61. package/dist/commands/code/delete.d.ts +2 -1
  62. package/dist/commands/code/deploy.d.ts +2 -1
  63. package/dist/commands/code/watch.d.ts +2 -1
  64. package/dist/commands/content/export.d.ts +57 -0
  65. package/dist/commands/content/export.js +217 -0
  66. package/dist/commands/content/export.js.map +1 -0
  67. package/dist/commands/content/list.d.ts +56 -0
  68. package/dist/commands/content/list.js +133 -0
  69. package/dist/commands/content/list.js.map +1 -0
  70. package/dist/commands/docs/download.d.ts +2 -1
  71. package/dist/commands/ecdn/cache/purge.d.ts +2 -1
  72. package/dist/commands/ecdn/certificates/add.d.ts +2 -1
  73. package/dist/commands/ecdn/certificates/delete.d.ts +2 -1
  74. package/dist/commands/ecdn/certificates/list.d.ts +2 -1
  75. package/dist/commands/ecdn/certificates/update.d.ts +2 -1
  76. package/dist/commands/ecdn/certificates/validate.d.ts +2 -1
  77. package/dist/commands/ecdn/cipher-suites/get.d.ts +2 -1
  78. package/dist/commands/ecdn/cipher-suites/update.d.ts +2 -1
  79. package/dist/commands/ecdn/logpush/jobs/create.d.ts +2 -1
  80. package/dist/commands/ecdn/logpush/jobs/delete.d.ts +2 -1
  81. package/dist/commands/ecdn/logpush/jobs/get.d.ts +2 -1
  82. package/dist/commands/ecdn/logpush/jobs/list.d.ts +2 -1
  83. package/dist/commands/ecdn/logpush/jobs/update.d.ts +2 -1
  84. package/dist/commands/ecdn/logpush/ownership.d.ts +2 -1
  85. package/dist/commands/ecdn/mrt-rules/create.d.ts +2 -1
  86. package/dist/commands/ecdn/mrt-rules/delete.d.ts +2 -1
  87. package/dist/commands/ecdn/mrt-rules/get.d.ts +2 -1
  88. package/dist/commands/ecdn/mrt-rules/rules/delete.d.ts +2 -1
  89. package/dist/commands/ecdn/mrt-rules/rules/update.d.ts +2 -1
  90. package/dist/commands/ecdn/mrt-rules/update.d.ts +2 -1
  91. package/dist/commands/ecdn/mtls/create.d.ts +2 -1
  92. package/dist/commands/ecdn/mtls/delete.d.ts +2 -1
  93. package/dist/commands/ecdn/mtls/get.d.ts +2 -1
  94. package/dist/commands/ecdn/mtls/list.d.ts +2 -1
  95. package/dist/commands/ecdn/origin-headers/delete.d.ts +2 -1
  96. package/dist/commands/ecdn/origin-headers/get.d.ts +2 -1
  97. package/dist/commands/ecdn/origin-headers/set.d.ts +2 -1
  98. package/dist/commands/ecdn/page-shield/notifications/create.d.ts +2 -1
  99. package/dist/commands/ecdn/page-shield/notifications/delete.d.ts +2 -1
  100. package/dist/commands/ecdn/page-shield/notifications/list.d.ts +2 -1
  101. package/dist/commands/ecdn/page-shield/policies/create.d.ts +2 -1
  102. package/dist/commands/ecdn/page-shield/policies/delete.d.ts +2 -1
  103. package/dist/commands/ecdn/page-shield/policies/get.d.ts +2 -1
  104. package/dist/commands/ecdn/page-shield/policies/list.d.ts +2 -1
  105. package/dist/commands/ecdn/page-shield/policies/update.d.ts +2 -1
  106. package/dist/commands/ecdn/page-shield/scripts/get.d.ts +2 -1
  107. package/dist/commands/ecdn/page-shield/scripts/list.d.ts +2 -1
  108. package/dist/commands/ecdn/security/get.d.ts +2 -1
  109. package/dist/commands/ecdn/security/update.d.ts +2 -1
  110. package/dist/commands/ecdn/speed/get.d.ts +2 -1
  111. package/dist/commands/ecdn/speed/update.d.ts +2 -1
  112. package/dist/commands/ecdn/waf/groups/list.d.ts +2 -1
  113. package/dist/commands/ecdn/waf/groups/update.d.ts +2 -1
  114. package/dist/commands/ecdn/waf/managed-rules/list.d.ts +2 -1
  115. package/dist/commands/ecdn/waf/managed-rules/update.d.ts +2 -1
  116. package/dist/commands/ecdn/waf/migrate.d.ts +2 -1
  117. package/dist/commands/ecdn/waf/owasp/get.d.ts +2 -1
  118. package/dist/commands/ecdn/waf/owasp/update.d.ts +2 -1
  119. package/dist/commands/ecdn/waf/rules/get.d.ts +2 -1
  120. package/dist/commands/ecdn/waf/rules/list.d.ts +2 -1
  121. package/dist/commands/ecdn/waf/rules/update.d.ts +2 -1
  122. package/dist/commands/ecdn/waf/rulesets/list.d.ts +2 -1
  123. package/dist/commands/ecdn/waf/rulesets/update.d.ts +2 -1
  124. package/dist/commands/ecdn/zones/create.d.ts +2 -1
  125. package/dist/commands/ecdn/zones/list.d.ts +2 -1
  126. package/dist/commands/job/export.d.ts +2 -1
  127. package/dist/commands/job/import.d.ts +2 -1
  128. package/dist/commands/job/run.d.ts +2 -1
  129. package/dist/commands/job/search.d.ts +2 -1
  130. package/dist/commands/job/wait.d.ts +2 -1
  131. package/dist/commands/logs/get.d.ts +2 -1
  132. package/dist/commands/logs/list.d.ts +2 -1
  133. package/dist/commands/logs/tail.d.ts +2 -1
  134. package/dist/commands/mrt/bundle/deploy.js +24 -4
  135. package/dist/commands/mrt/bundle/deploy.js.map +1 -1
  136. package/dist/commands/mrt/tail-logs.d.ts +27 -0
  137. package/dist/commands/mrt/tail-logs.js +137 -0
  138. package/dist/commands/mrt/tail-logs.js.map +1 -0
  139. package/dist/commands/{ods → sandbox}/create.d.ts +8 -14
  140. package/dist/commands/{ods → sandbox}/create.js +112 -102
  141. package/dist/commands/sandbox/create.js.map +1 -0
  142. package/dist/commands/sandbox/delete.d.ts +19 -0
  143. package/dist/commands/sandbox/delete.js +141 -0
  144. package/dist/commands/sandbox/delete.js.map +1 -0
  145. package/dist/commands/{ods → sandbox}/get.d.ts +2 -1
  146. package/dist/commands/{ods → sandbox}/get.js +5 -4
  147. package/dist/commands/sandbox/get.js.map +1 -0
  148. package/dist/commands/{ods → sandbox}/info.d.ts +2 -1
  149. package/dist/commands/{ods → sandbox}/info.js +6 -5
  150. package/dist/commands/sandbox/info.js.map +1 -0
  151. package/dist/commands/{ods → sandbox}/list.d.ts +2 -1
  152. package/dist/commands/{ods → sandbox}/list.js +6 -5
  153. package/dist/commands/sandbox/list.js.map +1 -0
  154. package/dist/commands/{ods → sandbox}/restart.d.ts +7 -1
  155. package/dist/commands/sandbox/restart.js +107 -0
  156. package/dist/commands/sandbox/restart.js.map +1 -0
  157. package/dist/commands/{ods → sandbox}/start.d.ts +7 -1
  158. package/dist/commands/sandbox/start.js +108 -0
  159. package/dist/commands/sandbox/start.js.map +1 -0
  160. package/dist/commands/{ods → sandbox}/stop.d.ts +7 -1
  161. package/dist/commands/sandbox/stop.js +107 -0
  162. package/dist/commands/sandbox/stop.js.map +1 -0
  163. package/dist/commands/scaffold/generate.d.ts +22 -0
  164. package/dist/commands/scaffold/generate.js +74 -0
  165. package/dist/commands/scaffold/generate.js.map +1 -0
  166. package/dist/commands/scaffold/index.d.ts +24 -0
  167. package/dist/commands/scaffold/index.js +80 -0
  168. package/dist/commands/scaffold/index.js.map +1 -0
  169. package/dist/commands/scaffold/info.d.ts +24 -0
  170. package/dist/commands/scaffold/info.js +89 -0
  171. package/dist/commands/scaffold/info.js.map +1 -0
  172. package/dist/commands/scaffold/init.d.ts +29 -0
  173. package/dist/commands/scaffold/init.js +221 -0
  174. package/dist/commands/scaffold/init.js.map +1 -0
  175. package/dist/commands/scaffold/list.d.ts +38 -0
  176. package/dist/commands/scaffold/list.js +131 -0
  177. package/dist/commands/scaffold/list.js.map +1 -0
  178. package/dist/commands/scaffold/search.d.ts +32 -0
  179. package/dist/commands/scaffold/search.js +97 -0
  180. package/dist/commands/scaffold/search.js.map +1 -0
  181. package/dist/commands/scaffold/validate.d.ts +24 -0
  182. package/dist/commands/scaffold/validate.js +74 -0
  183. package/dist/commands/scaffold/validate.js.map +1 -0
  184. package/dist/commands/scapi/custom/status.d.ts +2 -1
  185. package/dist/commands/scapi/schemas/get.d.ts +2 -1
  186. package/dist/commands/scapi/schemas/list.d.ts +2 -1
  187. package/dist/commands/setup/index.d.ts +12 -0
  188. package/dist/commands/setup/index.js +34 -0
  189. package/dist/commands/setup/index.js.map +1 -0
  190. package/dist/commands/setup/{config.d.ts → inspect.d.ts} +5 -4
  191. package/dist/commands/setup/{config.js → inspect.js} +5 -3
  192. package/dist/commands/setup/inspect.js.map +1 -0
  193. package/dist/commands/setup/instance/create.d.ts +43 -0
  194. package/dist/commands/setup/instance/create.js +269 -0
  195. package/dist/commands/setup/instance/create.js.map +1 -0
  196. package/dist/commands/setup/instance/index.d.ts +9 -0
  197. package/dist/commands/setup/instance/index.js +22 -0
  198. package/dist/commands/setup/instance/index.js.map +1 -0
  199. package/dist/commands/setup/instance/list.d.ts +31 -0
  200. package/dist/commands/setup/instance/list.js +68 -0
  201. package/dist/commands/setup/instance/list.js.map +1 -0
  202. package/dist/commands/setup/instance/remove.d.ts +34 -0
  203. package/dist/commands/setup/instance/remove.js +75 -0
  204. package/dist/commands/setup/instance/remove.js.map +1 -0
  205. package/dist/commands/setup/instance/set-active.d.ts +33 -0
  206. package/dist/commands/setup/instance/set-active.js +78 -0
  207. package/dist/commands/setup/instance/set-active.js.map +1 -0
  208. package/dist/commands/slas/client/create.d.ts +2 -1
  209. package/dist/commands/slas/client/create.js +1 -0
  210. package/dist/commands/slas/client/create.js.map +1 -1
  211. package/dist/commands/slas/client/delete.d.ts +2 -1
  212. package/dist/commands/slas/client/get.d.ts +2 -1
  213. package/dist/commands/slas/client/list.d.ts +2 -1
  214. package/dist/commands/slas/client/list.js +8 -3
  215. package/dist/commands/slas/client/list.js.map +1 -1
  216. package/dist/commands/slas/client/update.d.ts +2 -1
  217. package/dist/commands/webdav/get.d.ts +2 -1
  218. package/dist/commands/webdav/rm.d.ts +2 -1
  219. package/dist/i18n/locales/en.d.ts +42 -0
  220. package/dist/i18n/locales/en.js +42 -0
  221. package/dist/i18n/locales/en.js.map +1 -1
  222. package/dist/i18n/locales/index.d.ts +42 -0
  223. package/dist/lib/scaffold/generate-helper.d.ts +47 -0
  224. package/dist/lib/scaffold/generate-helper.js +271 -0
  225. package/dist/lib/scaffold/generate-helper.js.map +1 -0
  226. package/dist/lib/scaffold/source-resolver.d.ts +25 -0
  227. package/dist/lib/scaffold/source-resolver.js +37 -0
  228. package/dist/lib/scaffold/source-resolver.js.map +1 -0
  229. package/dist/utils/am/resolve-org.d.ts +11 -0
  230. package/dist/utils/am/resolve-org.js +15 -0
  231. package/dist/utils/am/resolve-org.js.map +1 -0
  232. package/dist/utils/am/user-display.d.ts +5 -0
  233. package/dist/utils/am/user-display.js +100 -0
  234. package/dist/utils/am/user-display.js.map +1 -0
  235. package/dist/utils/ecdn/zone-command.d.ts +2 -1
  236. package/dist/utils/mrt-logs/format.d.ts +28 -0
  237. package/dist/utils/mrt-logs/format.js +90 -0
  238. package/dist/utils/mrt-logs/format.js.map +1 -0
  239. package/dist/utils/mrt-logs/index.d.ts +1 -0
  240. package/dist/utils/mrt-logs/index.js +7 -0
  241. package/dist/utils/mrt-logs/index.js.map +1 -0
  242. package/dist/utils/slas/client.d.ts +7 -0
  243. package/dist/utils/slas/client.js +26 -13
  244. package/dist/utils/slas/client.js.map +1 -1
  245. package/oclif.manifest.json +14039 -5107
  246. package/package.json +61 -19
  247. package/dist/commands/ods/create.js.map +0 -1
  248. package/dist/commands/ods/delete.d.ts +0 -15
  249. package/dist/commands/ods/delete.js +0 -86
  250. package/dist/commands/ods/delete.js.map +0 -1
  251. package/dist/commands/ods/get.js.map +0 -1
  252. package/dist/commands/ods/info.js.map +0 -1
  253. package/dist/commands/ods/list.js.map +0 -1
  254. package/dist/commands/ods/restart.js +0 -51
  255. package/dist/commands/ods/restart.js.map +0 -1
  256. package/dist/commands/ods/start.js +0 -51
  257. package/dist/commands/ods/start.js.map +0 -1
  258. package/dist/commands/ods/stop.js +0 -51
  259. package/dist/commands/ods/stop.js.map +0 -1
  260. 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 OdsCreate extends OdsCommand<typeof OdsCreate> {
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 OdsCreate extends OdsCommand {
37
- static description = withDocs(t('commands.ods.create.description', 'Create a new on-demand sandbox'), '/cli/ods.html#b2c-ods-create');
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.log(t('commands.ods.create.creating', 'Creating sandbox in realm {{realm}}...', { realm }));
98
- this.log(t('commands.ods.create.profile', 'Profile: {{profile}}', { profile }));
99
- this.log(t('commands.ods.create.ttl', 'TTL: {{ttl}} hours', { ttl: ttl === 0 ? 'infinite' : String(ttl) }));
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(setPermissions);
120
+ const settings = this.buildSettings({
121
+ setPermissions,
122
+ permissionsClientId,
123
+ ocapiSettings: ocapiSettingsRaw,
124
+ webdavSettings: webdavSettingsRaw,
125
+ });
102
126
  if (settings) {
103
- this.log(t('commands.ods.create.settingPermissions', 'Setting OCAPI and WebDAV permissions for client ID: {{clientId}}', { clientId: this.resolvedConfig.values.clientId }));
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.ods.create.error', 'Failed to create sandbox: {{message}}', {
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.ods.create.success', 'Sandbox created successfully'));
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
- sandbox = await this.waitForSandbox(sandbox.id, pollInterval, timeout);
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(setPermissions) {
139
- if (!setPermissions) {
210
+ buildSettings(options) {
211
+ if (!options.setPermissions) {
140
212
  return undefined;
141
213
  }
142
- const clientId = this.resolvedConfig.values.clientId;
143
- if (!clientId) {
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
- return {
147
- ocapi: [
148
- {
149
- client_id: clientId,
150
- resources: DEFAULT_OCAPI_RESOURCES,
151
- },
152
- ],
153
- webdav: [
154
- {
155
- client_id: clientId,
156
- permissions: DEFAULT_WEBDAV_PERMISSIONS,
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":"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"}
@@ -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