Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"dependencies": {
"@oclif/core": "^4",
"@salesforce/core": "^8.2.7",
"@salesforce/sf-plugins-core": "^12"
"@salesforce/sf-plugins-core": "^12",
"jszip": "^3.10.1"
},
"devDependencies": {
"@oclif/plugin-command-snapshot": "^5.2.3",
Expand Down
62 changes: 28 additions & 34 deletions src/base/zipBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,34 @@
import { existsSync } from 'node:fs';
import { SfCommand } from '@salesforce/sf-plugins-core';
import { Messages, SfError } from '@salesforce/core';
import { DatacodeBinaryExecutor, type DatacodeZipExecutionResult } from '../utils/datacodeBinaryExecutor.js';
import { checkEnvironment } from '../utils/environmentChecker.js';
import { type SharedResultProps } from './types.js';
import { zipWithSfError, type ZipResult as ZipBuilderResult } from '../utils/zipBuilder.js';

export type BaseZipFlags = {
'package-dir': string;
network?: string;
};

export type ZipResult = SharedResultProps & {
archivePath?: string;
executionResult?: DatacodeZipExecutionResult;
export type ZipResult = {
success: boolean;
codeType: 'script' | 'function';
packageDir: string;
archivePath: string;
fileCount: number;
archiveSizeBytes: number;
message: string;
};

function formatBytes(bytes: number): string {
const units = ['B', 'KB', 'MB', 'GB'];
let value = bytes;
let unit = 0;
while (value >= 1024 && unit < units.length - 1) {
value /= 1024;
unit += 1;
}
return `${value.toFixed(unit === 0 ? 0 : 2)} ${units[unit]}`;
}

// eslint-disable-next-line sf-plugin/command-summary, sf-plugin/command-example
export abstract class ZipBase extends SfCommand<ZipResult> {
public static enableJsonFlag = false;
Expand All @@ -39,7 +53,7 @@ export abstract class ZipBase extends SfCommand<ZipResult> {
const codeType = this.getCodeType();
const messages = this.getMessages();
const packageDir = flags['package-dir'];
const network = flags.network;
const network = flags.network ?? 'default';

if (!existsSync(packageDir)) {
throw new SfError(
Expand All @@ -50,45 +64,25 @@ export abstract class ZipBase extends SfCommand<ZipResult> {
}

try {
const { pythonInfo, packageInfo, binaryInfo } = await checkEnvironment(
this.spinner,
this.log.bind(this),
messages
);

this.spinner.start(messages.getMessage('info.executingZip'));
const executionResult = await DatacodeBinaryExecutor.executeBinaryZip(packageDir, network);

const result: ZipBuilderResult = await zipWithSfError(packageDir, network, this.log.bind(this));
this.spinner.stop();

if (executionResult.archivePath) {
this.log(messages.getMessage('info.archiveCreated', [executionResult.archivePath]));
}

if (executionResult.fileCount !== undefined) {
this.log(messages.getMessage('info.filesIncluded', [executionResult.fileCount.toString()]));
}

if (executionResult.archiveSize) {
this.log(messages.getMessage('info.archiveSize', [executionResult.archiveSize]));
}
this.log(messages.getMessage('info.archiveCreated', [result.archivePath]));
this.log(messages.getMessage('info.filesIncluded', [result.fileCount.toString()]));
this.log(messages.getMessage('info.archiveSize', [formatBytes(result.archiveSizeBytes)]));

return {
success: true,
pythonVersion: pythonInfo,
packageInfo,
binaryInfo,
codeType,
packageDir,
archivePath: executionResult.archivePath,
executionResult,
archivePath: result.archivePath,
fileCount: result.fileCount,
archiveSizeBytes: result.archiveSizeBytes,
message: messages.getMessage('info.zipCompleted'),
};
} catch (error) {
this.spinner.stop();

// The error will be properly handled by the Salesforce CLI framework
// as an SfError with actions, so we just throw it
throw error;
}
}
Expand Down
9 changes: 8 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export { PipChecker, type PipPackageInfo } from './utils/pipChecker.js';
export { DatacodeBinaryChecker, type DatacodeBinaryInfo } from './utils/datacodeBinaryChecker.js';
export {
DatacodeBinaryExecutor,
type DatacodeZipExecutionResult,
type DatacodeDeployExecutionResult,
type DatacodeRunExecutionResult,
} from './utils/datacodeBinaryExecutor.js';
Expand All @@ -39,3 +38,11 @@ export {
type ScanPermissions,
} from './utils/nativeScan.js';
export type { ScanResult } from './base/scanBase.js';
export {
createZip,
hasNonemptyRequirementsFile,
prepareDependencyArchive,
zip as zipPackage,
zipWithSfError,
type ZipResult as ZipBuilderResult,
} from './utils/zipBuilder.js';
45 changes: 0 additions & 45 deletions src/utils/datacodeBinaryExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ import { spawnAsync, type SpawnError } from './spawnHelper.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-data-code-extension', 'datacodeBinaryExecutor');

export type DatacodeZipExecutionResult = {
stdout: string;
stderr: string;
archivePath?: string;
fileCount?: number;
archiveSize?: string;
};

export type DatacodeDeployExecutionResult = {
stdout: string;
stderr: string;
Expand All @@ -48,43 +40,6 @@ export type DatacodeRunExecutionResult = {
};

export class DatacodeBinaryExecutor {
/**
* Executes datacustomcode zip with the specified parameters.
*
* @param packageDir The directory containing the initialized package to zip
* @param network Optional network configuration for Jupyter notebooks
* @returns Execution result with stdout, stderr, and archive information
* @throws SfError if execution fails
*/
public static async executeBinaryZip(packageDir: string, network?: string): Promise<DatacodeZipExecutionResult> {
const args = ['zip'];

if (network) {
args.push('--network', network);
}

args.push(packageDir);

try {
const { stdout, stderr } = await spawnAsync('datacustomcode', args, {
timeout: 120_000,
});

return {
stdout: stdout.trim(),
stderr: stderr.trim(),
};
} catch (error) {
const spawnError = error as SpawnError;
const binaryOutput = spawnError.stderr?.trim() ?? (error instanceof Error ? error.message : String(error));
throw new SfError(
messages.getMessage('error.zipExecutionFailed', [packageDir, binaryOutput]),
'ZipExecutionFailed',
messages.getMessages('actions.zipExecutionFailed')
);
}
}

/**
* Executes datacustomcode deploy with the specified parameters.
*
Expand Down
Loading