Skip to content

Commit 461f935

Browse files
sf-haulakhclaude
andcommitted
fix: resolve lint errors for import ordering and method complexity
Move node:fs/path/os imports before third-party imports, extract normalizeDefinitionFile, cleanupTempFile, and handleResult into private methods to reduce run() complexity, and capture file content inside test stubs before temp file cleanup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1cd5ee4 commit 461f935

2 files changed

Lines changed: 71 additions & 69 deletions

File tree

src/commands/package/bundle/version/create.ts

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17+
import fs from 'node:fs';
18+
import os from 'node:os';
19+
import path from 'node:path';
1720
import { Flags, loglevel, orgApiVersionFlagWithDeprecations, SfCommand } from '@salesforce/sf-plugins-core';
1821
import {
1922
BundleVersionCreateOptions,
@@ -24,9 +27,6 @@ import {
2427
import { Messages, Lifecycle } from '@salesforce/core';
2528
import { camelCaseToTitleCase, Duration } from '@salesforce/kit';
2629
import { requiredHubFlag } from '../../../../utils/hubFlag.js';
27-
import fs from 'node:fs';
28-
import path from 'node:path';
29-
import os from 'node:os';
3030

3131
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
3232
// TODO: Update messages
@@ -148,31 +148,7 @@ export class PackageBundlesCreate extends SfCommand<BundleSObjects.PackageBundle
148148
}
149149

150150
// Read and normalize the definition file to handle 15-char package version IDs
151-
let definitionFilePath = flags['definition-file'];
152-
let tempFilePath: string | undefined;
153-
154-
try {
155-
// Read the definition file
156-
const definitionContent = await fs.promises.readFile(definitionFilePath, 'utf8');
157-
const definitionJson = JSON.parse(definitionContent) as unknown;
158-
159-
// Normalize any 15-character package version IDs to 18-character format
160-
const normalizedJson = normalizePackageVersionIds(definitionJson);
161-
162-
// Check if any normalization occurred by comparing stringified versions
163-
if (JSON.stringify(definitionJson) !== JSON.stringify(normalizedJson)) {
164-
// Create a temporary file with normalized content
165-
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'sf-bundle-'));
166-
tempFilePath = path.join(tempDir, 'normalized-definition.json');
167-
await fs.promises.writeFile(tempFilePath, JSON.stringify(normalizedJson, null, 2), 'utf8');
168-
definitionFilePath = tempFilePath;
169-
this.debug(`Normalized package version IDs in definition file. Using temporary file: ${tempFilePath}`);
170-
}
171-
} catch (error) {
172-
// If reading/parsing fails, let the packaging library handle the error
173-
// This preserves the original error messages for invalid JSON, missing files, etc.
174-
this.debug(`Could not normalize definition file: ${error instanceof Error ? error.message : String(error)}`);
175-
}
151+
const { definitionFilePath, tempFilePath } = await this.normalizeDefinitionFile(flags['definition-file']);
176152

177153
const options: BundleVersionCreateOptions = {
178154
connection: flags['target-dev-hub'].getConnection(flags['api-version']),
@@ -228,29 +204,57 @@ export class PackageBundlesCreate extends SfCommand<BundleSObjects.PackageBundle
228204
}
229205
throw error;
230206
} finally {
231-
// Clean up temporary file if it was created
232-
if (tempFilePath) {
233-
try {
234-
const tempDir = path.dirname(tempFilePath);
235-
await fs.promises.rm(tempDir, { recursive: true, force: true });
236-
this.debug(`Cleaned up temporary definition file: ${tempFilePath}`);
237-
} catch (cleanupError) {
238-
// Log but don't fail if cleanup fails
239-
this.debug(
240-
`Failed to clean up temporary file: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`
241-
);
242-
}
243-
}
207+
await this.cleanupTempFile(tempFilePath);
244208
}
245209

246-
// Stop spinner only if it was started - stop it cleanly without a message
247210
if (isSpinnerRunning) {
248211
this.spinner.stop();
249212
}
250213

214+
this.handleResult(result);
215+
return result;
216+
}
217+
218+
private async normalizeDefinitionFile(
219+
definitionFilePath: string
220+
): Promise<{ definitionFilePath: string; tempFilePath?: string }> {
221+
try {
222+
const definitionContent = await fs.promises.readFile(definitionFilePath, 'utf8');
223+
const definitionJson = JSON.parse(definitionContent) as unknown;
224+
const normalizedJson = normalizePackageVersionIds(definitionJson);
225+
226+
if (JSON.stringify(definitionJson) !== JSON.stringify(normalizedJson)) {
227+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'sf-bundle-'));
228+
const tempFilePath = path.join(tempDir, 'normalized-definition.json');
229+
await fs.promises.writeFile(tempFilePath, JSON.stringify(normalizedJson, null, 2), 'utf8');
230+
this.debug(`Normalized package version IDs in definition file. Using temporary file: ${tempFilePath}`);
231+
return { definitionFilePath: tempFilePath, tempFilePath };
232+
}
233+
} catch (error) {
234+
this.debug(`Could not normalize definition file: ${error instanceof Error ? error.message : String(error)}`);
235+
}
236+
return { definitionFilePath };
237+
}
238+
239+
private async cleanupTempFile(tempFilePath: string | undefined): Promise<void> {
240+
if (tempFilePath) {
241+
try {
242+
const tempDir = path.dirname(tempFilePath);
243+
await fs.promises.rm(tempDir, { recursive: true, force: true });
244+
this.debug(`Cleaned up temporary definition file: ${tempFilePath}`);
245+
} catch (cleanupError) {
246+
this.debug(
247+
`Failed to clean up temporary file: ${
248+
cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
249+
}`
250+
);
251+
}
252+
}
253+
}
254+
255+
private handleResult(result: BundleSObjects.PackageBundleVersionCreateRequestResult): void {
251256
switch (result.RequestStatus) {
252257
case BundleSObjects.PkgBundleVersionCreateReqStatus.error: {
253-
// Collect all error messages from both Error array and ValidationError
254258
const errorMessages: string[] = [];
255259

256260
if (result.Error && result.Error.length > 0) {
@@ -267,14 +271,12 @@ export class PackageBundlesCreate extends SfCommand<BundleSObjects.PackageBundle
267271
throw messages.createError('multipleErrors', [errorText]);
268272
}
269273
case BundleSObjects.PkgBundleVersionCreateReqStatus.success: {
270-
// Show the PackageBundleVersionId (1Q8) if available, otherwise show the request ID
271274
const displayId = result.PackageBundleVersionId || result.Id;
272275
this.log(`Successfully created bundle version with ID ${displayId}`);
273276
break;
274277
}
275278
default:
276279
this.log(messages.getMessage('InProgress', [camelCaseToTitleCase(result.RequestStatus as string), result.Id]));
277280
}
278-
return result;
279281
}
280282
}

test/commands/bundle/packageBundleVersionCreate.test.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
import fs from 'node:fs';
17+
import os from 'node:os';
18+
import path from 'node:path';
1619
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
1720
import { Config } from '@oclif/core';
1821
import { assert, expect } from 'chai';
1922
import { PackageBundleVersion, BundleSObjects } from '@salesforce/packaging';
2023
import sinon from 'sinon';
2124
import { SfCommand } from '@salesforce/sf-plugins-core';
2225
import { PackageBundlesCreate } from '../../../src/commands/package/bundle/version/create.js';
23-
import fs from 'node:fs';
24-
import path from 'node:path';
25-
import os from 'node:os';
2626

2727
const pkgBundleVersionCreateErrorResult: BundleSObjects.PackageBundleVersionCreateRequestResult = {
2828
Id: '08c3i000000fylXXXX',
@@ -243,8 +243,14 @@ describe('package:bundle:version:create - tests', () => {
243243
});
244244

245245
it('should normalize 15-character package version IDs to 18-character format', async () => {
246-
createStub = $$.SANDBOX.stub(PackageBundleVersion, 'create');
247-
createStub.resolves(pkgBundleVersionCreateSuccessResult);
246+
// Capture the file content inside the stub, before the command cleans up temp files
247+
let capturedContent: string | undefined;
248+
createStub = $$.SANDBOX.stub(PackageBundleVersion, 'create').callsFake(
249+
async (opts: { BundleVersionComponentsPath: string }) => {
250+
capturedContent = await fs.promises.readFile(opts.BundleVersionComponentsPath, 'utf8');
251+
return pkgBundleVersionCreateSuccessResult;
252+
}
253+
);
248254

249255
// Create a temporary definition file with 15-char IDs
250256
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'test-bundle-'));
@@ -265,16 +271,9 @@ describe('package:bundle:version:create - tests', () => {
265271
stubSpinner(cmd);
266272
await cmd.run();
267273

268-
// Verify that PackageBundleVersion.create was called
269274
expect(createStub.callCount).to.equal(1);
270-
271-
// Get the options passed to create
272-
const createOptions = createStub.firstCall.args[0] as { BundleVersionComponentsPath: string };
273-
const usedDefinitionPath = createOptions.BundleVersionComponentsPath;
274-
275-
// Read the file that was passed to the create method
276-
const usedContent = await fs.promises.readFile(usedDefinitionPath, 'utf8');
277-
const usedJson = JSON.parse(usedContent) as typeof definitionContent;
275+
assert(capturedContent, 'Expected file content to be captured');
276+
const usedJson = JSON.parse(capturedContent) as typeof definitionContent;
278277

279278
// Verify that the 15-char ID was converted to 18-char
280279
expect(usedJson.components[0].packageVersion).to.equal('04t5f000000WM9yAAG');
@@ -287,8 +286,14 @@ describe('package:bundle:version:create - tests', () => {
287286
});
288287

289288
it('should handle nested packageVersion fields in definition file', async () => {
290-
createStub = $$.SANDBOX.stub(PackageBundleVersion, 'create');
291-
createStub.resolves(pkgBundleVersionCreateSuccessResult);
289+
// Capture the file content inside the stub, before the command cleans up temp files
290+
let capturedContent: string | undefined;
291+
createStub = $$.SANDBOX.stub(PackageBundleVersion, 'create').callsFake(
292+
async (opts: { BundleVersionComponentsPath: string }) => {
293+
capturedContent = await fs.promises.readFile(opts.BundleVersionComponentsPath, 'utf8');
294+
return pkgBundleVersionCreateSuccessResult;
295+
}
296+
);
292297

293298
// Create a temporary definition file with nested structure
294299
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'test-bundle-'));
@@ -311,17 +316,12 @@ describe('package:bundle:version:create - tests', () => {
311316
stubSpinner(cmd);
312317
await cmd.run();
313318

314-
// Get the options passed to create
315-
const createOptions = createStub.firstCall.args[0] as { BundleVersionComponentsPath: string };
316-
const usedDefinitionPath = createOptions.BundleVersionComponentsPath;
317-
318-
// Read the file that was passed to the create method
319-
const usedContent = await fs.promises.readFile(usedDefinitionPath, 'utf8');
320-
const usedJson = JSON.parse(usedContent) as typeof definitionContent;
319+
assert(capturedContent, 'Expected file content to be captured');
320+
const usedJson = JSON.parse(capturedContent) as typeof definitionContent;
321321

322322
// Verify that both 15-char IDs were converted
323323
expect(usedJson.bundle.components[0].packageVersion).to.equal('04t5f000000WM9yAAG');
324-
expect(usedJson.bundle.components[1].nested.packageVersion).to.equal('04t5f000000WM9zAAG');
324+
expect(usedJson.bundle.components[1].nested!.packageVersion).to.equal('04t5f000000WM9zAAG');
325325
} finally {
326326
// Clean up
327327
await fs.promises.rm(tempDir, { recursive: true, force: true });

0 commit comments

Comments
 (0)