Skip to content

Commit 3ab1bf1

Browse files
committed
addressed review comments
1 parent 24c29a9 commit 3ab1bf1

10 files changed

Lines changed: 474 additions & 290 deletions

File tree

packages/b2c-cli/src/commands/ods/create.ts

Lines changed: 68 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
import {Flags, ux} from '@oclif/core';
77
import cliui from 'cliui';
88
import {OdsCommand} from '@salesforce/b2c-tooling-sdk/cli';
9-
import {getApiErrorMessage, type OdsComponents} from '@salesforce/b2c-tooling-sdk';
9+
import {
10+
getApiErrorMessage,
11+
SandboxPollingError,
12+
SandboxPollingTimeoutError,
13+
SandboxTerminalStateError,
14+
waitForSandbox,
15+
type OdsComponents,
16+
} from '@salesforce/b2c-tooling-sdk';
1017
import {t, withDocs} from '../../i18n/index.js';
11-
import {waitForSandboxStateCommon} from './polling.js';
1218

1319
type SandboxModel = OdsComponents['schemas']['SandboxModel'];
1420
type SandboxResourceProfile = OdsComponents['schemas']['SandboxResourceProfile'];
@@ -153,7 +159,66 @@ export default class OdsCreate extends OdsCommand<typeof OdsCreate> {
153159

154160
if (wait && sandbox.id) {
155161
this.log(t('commands.ods.create.waiting', 'Waiting for sandbox to get started..'));
156-
sandbox = await this.waitForSandbox(sandbox.id, pollInterval, timeout);
162+
163+
try {
164+
await waitForSandbox({
165+
sandboxId: sandbox.id,
166+
targetState: 'started',
167+
pollIntervalSeconds: pollInterval,
168+
timeoutSeconds: timeout,
169+
odsClient: this.odsClient,
170+
onPoll: ({elapsedSeconds, state}) => {
171+
this.logger.info(
172+
{sandboxId: sandbox.id, elapsed: elapsedSeconds, state},
173+
`[${elapsedSeconds}s] State: ${state}`,
174+
);
175+
},
176+
});
177+
} catch (error) {
178+
if (error instanceof SandboxPollingTimeoutError) {
179+
this.error(
180+
t('commands.ods.create.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
181+
seconds: String(error.timeoutSeconds),
182+
}),
183+
);
184+
}
185+
186+
if (error instanceof SandboxTerminalStateError) {
187+
if (error.state === 'deleted') {
188+
this.error(t('commands.ods.create.deleted', 'Sandbox was deleted'));
189+
}
190+
this.error(t('commands.ods.create.failed', 'Sandbox creation failed'));
191+
}
192+
193+
if (error instanceof SandboxPollingError) {
194+
this.error(
195+
t('commands.ods.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
196+
message: error.message,
197+
}),
198+
);
199+
}
200+
201+
throw error;
202+
}
203+
204+
const finalResult = await this.odsClient.GET('/sandboxes/{sandboxId}', {
205+
params: {
206+
path: {sandboxId: sandbox.id},
207+
},
208+
});
209+
210+
if (!finalResult.data?.data) {
211+
this.error(
212+
t('commands.ods.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
213+
message: finalResult.response?.statusText || 'Unknown error',
214+
}),
215+
);
216+
}
217+
218+
sandbox = finalResult.data.data;
219+
220+
this.log('');
221+
this.logger.info({sandboxId: sandbox.id}, t('commands.ods.create.ready', 'Sandbox is now ready'));
157222
}
158223

159224
if (this.jsonEnabled()) {
@@ -223,73 +288,4 @@ export default class OdsCreate extends OdsCommand<typeof OdsCreate> {
223288

224289
ux.stdout(ui.toString());
225290
}
226-
227-
/**
228-
* Sleep for a given number of milliseconds.
229-
*/
230-
private async sleep(ms: number): Promise<void> {
231-
await new Promise((resolve) => {
232-
setTimeout(resolve, ms);
233-
});
234-
}
235-
236-
/**
237-
* Polls for sandbox status until it reaches a terminal state.
238-
* @param sandboxId - The sandbox ID to poll
239-
* @param pollIntervalSeconds - Interval between polls in seconds
240-
* @param timeoutSeconds - Maximum time to wait (0 for no timeout)
241-
* @returns The final sandbox state
242-
*/
243-
private async waitForSandbox(
244-
sandboxId: string,
245-
pollIntervalSeconds: number,
246-
timeoutSeconds: number,
247-
): Promise<SandboxModel> {
248-
await waitForSandboxStateCommon({
249-
sandboxId,
250-
targetState: 'started',
251-
pollIntervalSeconds,
252-
timeoutSeconds,
253-
odsClient: this.odsClient,
254-
logger: this.logger,
255-
sleep: (ms) => this.sleep(ms),
256-
onPollError: (message) =>
257-
this.error(
258-
t('commands.ods.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
259-
message,
260-
}),
261-
),
262-
onTimeout: (seconds) =>
263-
this.error(
264-
t('commands.ods.create.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
265-
seconds: String(seconds),
266-
}),
267-
),
268-
onFailure: (state) => {
269-
if (state === 'deleted') {
270-
this.error(t('commands.ods.create.deleted', 'Sandbox was deleted'));
271-
}
272-
this.error(t('commands.ods.create.failed', 'Sandbox creation failed'));
273-
},
274-
});
275-
276-
const finalResult = await this.odsClient.GET('/sandboxes/{sandboxId}', {
277-
params: {
278-
path: {sandboxId},
279-
},
280-
});
281-
282-
if (!finalResult.data?.data) {
283-
this.error(
284-
t('commands.ods.create.pollError', 'Failed to fetch sandbox status: {{message}}', {
285-
message: finalResult.response?.statusText || 'Unknown error',
286-
}),
287-
);
288-
}
289-
290-
this.log('');
291-
this.logger.info({sandboxId}, t('commands.ods.create.ready', 'Sandbox is now ready'));
292-
293-
return finalResult.data.data;
294-
}
295291
}

packages/b2c-cli/src/commands/ods/delete.ts

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
import * as readline from 'node:readline';
77
import {Args, Flags} from '@oclif/core';
88
import {OdsCommand} from '@salesforce/b2c-tooling-sdk/cli';
9-
import {getApiErrorMessage} from '@salesforce/b2c-tooling-sdk';
9+
import {
10+
getApiErrorMessage,
11+
SandboxPollingError,
12+
SandboxPollingTimeoutError,
13+
SandboxTerminalStateError,
14+
waitForSandbox,
15+
type SandboxState,
16+
} from '@salesforce/b2c-tooling-sdk';
1017
import {t, withDocs} from '../../i18n/index.js';
11-
import {waitForSandboxStateCommon, type SandboxState} from './polling.js';
1218

1319
/**
1420
* Simple confirmation prompt.
@@ -131,32 +137,44 @@ export default class OdsDelete extends OdsCommand<typeof OdsDelete> {
131137
}),
132138
);
133139

134-
await waitForSandboxStateCommon({
135-
sandboxId,
136-
targetState: 'deleted',
137-
pollIntervalSeconds: pollInterval,
138-
timeoutSeconds: timeout,
139-
odsClient: this.odsClient,
140-
logger: this.logger,
141-
onPollError: (message) =>
142-
this.error(
143-
t('commands.ods.delete.pollError', 'Failed to fetch sandbox status: {{message}}', {
144-
message,
145-
}),
146-
),
147-
onTimeout: (seconds) =>
140+
try {
141+
await waitForSandbox({
142+
sandboxId,
143+
targetState: 'deleted',
144+
pollIntervalSeconds: pollInterval,
145+
timeoutSeconds: timeout,
146+
odsClient: this.odsClient,
147+
onPoll: ({elapsedSeconds, state}) => {
148+
this.logger.info({sandboxId, elapsed: elapsedSeconds, state}, `[${elapsedSeconds}s] State: ${state}`);
149+
},
150+
});
151+
} catch (error) {
152+
if (error instanceof SandboxPollingTimeoutError) {
148153
this.error(
149154
t('commands.ods.delete.timeout', 'Timeout waiting for sandbox after {{seconds}} seconds', {
150-
seconds: String(seconds),
155+
seconds: String(error.timeoutSeconds),
151156
}),
152-
),
153-
onFailure: (state) =>
157+
);
158+
}
159+
160+
if (error instanceof SandboxTerminalStateError) {
154161
this.error(
155162
t('commands.ods.delete.failed', 'Sandbox did not reach the expected state. Current state: {{state}}', {
156-
state: state || 'unknown',
163+
state: error.state || 'unknown',
164+
}),
165+
);
166+
}
167+
168+
if (error instanceof SandboxPollingError) {
169+
this.error(
170+
t('commands.ods.delete.pollError', 'Failed to fetch sandbox status: {{message}}', {
171+
message: error.message,
157172
}),
158-
),
159-
});
173+
);
174+
}
175+
176+
throw error;
177+
}
160178

161179
this.log('');
162180
this.logger.info({sandboxId}, t('commands.ods.delete.ready', 'Sandbox is now deleted'));

packages/b2c-cli/src/commands/ods/polling.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)