Skip to content
Merged
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
9 changes: 5 additions & 4 deletions src/client/metadataApiDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export class MetadataApiDeploy extends MetadataTransfer<
let zipMessage = `Deployment zip file size = ${this.zipSize} Bytes`;
if (zipFileCount) {
this.zipFileCount = zipFileCount;
zipMessage += ` containing ${zipFileCount} files`;
zipMessage += ` containing ${zipFileCount} entries`;
}
this.logger.debug(zipMessage);
await LifecycleInstance.emit('apiVersionDeploy', { webService, manifestVersion, apiVersion });
Expand Down Expand Up @@ -367,7 +367,7 @@ export class MetadataApiDeploy extends MetadataTransfer<

if (zipFileCount && zipFileCount > fileCountThreshold) {
await Lifecycle.getInstance().emitWarning(
`Deployment zip file count is approaching the Metadata API limit (10,000). Warning threshold is ${thresholdPercentage}% and count ${zipFileCount} > ${fileCountThreshold}`
`Deployment zip entry count (files + folders) is approaching the Metadata API limit (10,000). Warning threshold is ${thresholdPercentage}% and count ${zipFileCount} > ${fileCountThreshold}`
);
}
}
Expand All @@ -382,7 +382,6 @@ export class MetadataApiDeploy extends MetadataTransfer<
}

const zip = JSZip();
let zipFileCount = 0;

const zipDirRecursive = (dir: string): void => {
const dirents = fs.readdirSync(dir, { withFileTypes: true });
Expand All @@ -396,13 +395,15 @@ export class MetadataApiDeploy extends MetadataTransfer<
// Ensure only posix paths are added to zip files
const relPosixPath = relPath.replace(/\\/g, '/');
zip.file(relPosixPath, fs.createReadStream(fullPath));
zipFileCount++;
}
}
};
this.logger.debug(`Zipping directory for metadata deploy: ${mdapiPath}`);
zipDirRecursive(mdapiPath);

// Count all entries (files + auto-created directories) to match the server's limit check
const zipFileCount = Object.keys(zip.files).length;

return {
zipBuffer: await zip.generateAsync({
type: 'nodebuffer',
Expand Down
2 changes: 1 addition & 1 deletion src/convert/metadataConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const getResult =
if ('addToZip' in writer) {
const buffer = writer.buffer;
if (!packagePath) {
return { packagePath, zipBuffer: buffer, zipFileCount: writer.fileCount };
return { packagePath, zipBuffer: buffer, zipFileCount: writer.entryCount };
} else if (buffer) {
await promises.writeFile(packagePath, buffer);
return { packagePath };
Expand Down
11 changes: 11 additions & 0 deletions src/convert/streams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export class ZipWriter extends ComponentWriter {
public fileCount: number = 0;
private zip = JSZip();
private zipBuffer?: Buffer;
private dirEntries = new Set<string>();

public constructor(rootDestination?: SourcePath) {
super(rootDestination);
Expand All @@ -240,6 +241,11 @@ export class ZipWriter extends ComponentWriter {
return this.zipBuffer;
}

/** Total zip entries (files + auto-created directory entries). Matches the server's count. */
public get entryCount(): number {
return this.fileCount + this.dirEntries.size;
}

public async _write(chunk: WriterFormat, encoding: string, callback: (err?: Error) => void): Promise<void> {
let err: Error | undefined;
try {
Expand Down Expand Up @@ -281,6 +287,11 @@ export class ZipWriter extends ComponentWriter {
const posixPath = path.replace(/\\/g, '/');
this.zip.file(posixPath, contents);
this.fileCount++;
// Track parent directory entries that JSZip auto-creates (createFolders defaults to true)
const parts = posixPath.split('/');
for (let i = 1; i < parts.length; i++) {
this.dirEntries.add(parts.slice(0, i).join('/') + '/');
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/client/metadataApiDeploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ describe('MetadataApiDeploy', () => {
await MetadataApiDeploy.prototype.warnIfDeployThresholdExceeded.call(mdapThis, 31_200_000, 8001);
expect(emitWarningStub.calledOnce, 'emitWarning for fileSize should have been called').to.be.true;
const warningMsg =
'Deployment zip file count is approaching the Metadata API limit (10,000). Warning threshold is 80%';
'Deployment zip entry count (files + folders) is approaching the Metadata API limit (10,000). Warning threshold is 80%';
expect(emitWarningStub.firstCall.args[0]).to.include(warningMsg);
expect(loggerDebugSpy.called).to.be.false;
});
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('MetadataApiDeploy', () => {
const fileSizeWarningMsg =
'Deployment zip file size is approaching the Metadata API limit (~39MB). Warning threshold is 75%';
const fileCountWarningMsg =
'Deployment zip file count is approaching the Metadata API limit (10,000). Warning threshold is 75%';
'Deployment zip entry count (files + folders) is approaching the Metadata API limit (10,000). Warning threshold is 75%';
expect(emitWarningStub.firstCall.args[0]).to.include(fileSizeWarningMsg);
expect(emitWarningStub.secondCall.args[0]).to.include(fileCountWarningMsg);
expect(loggerDebugSpy.calledOnce).to.be.true;
Expand Down
11 changes: 11 additions & 0 deletions test/convert/streams.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,17 @@ describe('Streams', () => {
expect(writer.fileCount).to.equal(3);
});

it('should count files and directory entries in entryCount', () => {
writer = new streams.ZipWriter();
env.stub(JSZip.prototype, 'file');
writer.addToZip(Buffer.from('a'), 'pkg/classes/Foo.cls');
writer.addToZip(Buffer.from('b'), 'pkg/classes/Foo.cls-meta.xml');
writer.addToZip(Buffer.from('c'), 'pkg/lwc/bar/bar.js');
expect(writer.fileCount).to.equal(3);
// dirs: pkg/, pkg/classes/, pkg/lwc/, pkg/lwc/bar/
expect(writer.entryCount).to.equal(7);
});

it('should generateAsync zip when stream is finished', async () => {
const generateAsyncStub = env.stub(JSZip.prototype, 'generateAsync').resolves();
const expectedArgs = {
Expand Down
Loading