Skip to content

Commit

Permalink
feat: replace archiver with jszip (#489)
Browse files Browse the repository at this point in the history
* feat: replace archiver with jszip

* feat: replace archiver with jszip

---------

Co-authored-by: mshanemc <[email protected]>
  • Loading branch information
shetzel and mshanemc committed Jun 6, 2023
1 parent abe29b6 commit f37c74e
Show file tree
Hide file tree
Showing 4 changed files with 809 additions and 760 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"@salesforce/kit": "^3.0.2",
"@salesforce/ts-types": "^2.0.2",
"@types/shelljs": "^0.8.12",
"archiver": "^5.2.0",
"debug": "^4.3.1",
"jszip": "^3.10.1",
"shelljs": "^0.8.4",
"strip-ansi": "6.0.1",
"ts-retry-promise": "^0.7.0"
Expand All @@ -59,7 +59,6 @@
"@salesforce/dev-scripts": "^5.4.2",
"@salesforce/prettier-config": "^0.0.3",
"@salesforce/ts-sinon": "^1.4.8",
"@types/archiver": "^5.3.2",
"@types/debug": "^4.1.8",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.9",
Expand Down
52 changes: 27 additions & 25 deletions src/zip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
import * as fs from 'fs';
import * as path from 'path';
import { create as createArchive } from 'archiver';
import * as JSZip from 'jszip';
import Debug from 'debug';

export interface ZipDirConfig {
Expand Down Expand Up @@ -36,34 +36,36 @@ export interface ZipDirConfig {
export const zipDir = async (config: ZipDirConfig): Promise<string> => {
const debug = Debug('testkit:zipDir');
const { sourceDir, destDir, name } = config;
const zip = createArchive('zip', { zlib: { level: 3 } });
const zipFilePath = path.join(destDir, name);
const output = fs.createWriteStream(zipFilePath);
const zip = new JSZip();
debug(`Zipping contents of ${sourceDir} to ${zipFilePath}`);

return new Promise((resolve, reject) => {
output.on('close', () => {
debug(`Zip ${zipFilePath} is closed`);
resolve(zipFilePath);
});
output.on('end', () => {
debug(`Zip data has drained for ${zipFilePath}`);
resolve(zipFilePath);
});
zip.on('warning', (err) => {
if (err.code === 'ENOENT') {
debug(`Zip warning for ${zipFilePath}\n${err.message}`);
const zipDirRecursive = (dir: string): void => {
const dirents = fs.readdirSync(dir, { withFileTypes: true });
for (const dirent of dirents) {
const fullPath = path.resolve(dir, dirent.name);
if (dirent.isDirectory()) {
zipDirRecursive(fullPath);
} else {
reject(err);
const relPath = path.relative(sourceDir, fullPath);
// Ensure only posix paths are added to zip files
const relPosixPath = relPath.replace(/\\/g, '/');
zip.file(relPosixPath, fs.createReadStream(fullPath));
}
});
zip.on('error', (err) => {
reject(err);
});
zip.pipe(output);
zip.directory(sourceDir, false);
zip.finalize().catch((err: unknown) => {
debug(`Zip finalize error with: ${(err as Error).message}`);
});
}
};

zipDirRecursive(sourceDir);

const zipBuf = await zip.generateAsync({
type: 'nodebuffer',
compression: 'DEFLATE',
compressionOptions: { level: 3 },
});

fs.writeFileSync(zipFilePath, zipBuf);

debug('Zip file written');

return zipFilePath;
};
74 changes: 35 additions & 39 deletions test/unit/zip.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,48 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import * as fs from 'fs';
import { join as pathJoin } from 'path';
import { EventEmitter } from 'events';
import { assert, expect } from 'chai';
import { stubMethod } from '@salesforce/ts-sinon';
import * as sinon from 'sinon';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { expect } from 'chai';
import * as JSZip from 'jszip';
import { zipDir } from '../../src/zip';

describe('zipDir', () => {
const sandbox = sinon.createSandbox();

class WriteStreamMock extends EventEmitter {
public write = sandbox.stub().returns(true);
public end = sandbox.stub().callsFake(() => {
this.emit('end');
});
}

afterEach(() => {
sandbox.restore();
});

it('should zip a directory', async () => {
stubMethod(sandbox, fs, 'createWriteStream').returns(new WriteStreamMock());
const zipName = 'zipTest1.zip';
const zipPath = await zipDir({
sourceDir: pathJoin(process.cwd(), 'test', 'unit'),
destDir: process.cwd(),
name: zipName,
});
expect(zipPath).to.equal(pathJoin(process.cwd(), zipName));
});

it('should fail on error', async () => {
stubMethod(sandbox, fs, 'createWriteStream').returns(new WriteStreamMock());
const zipName = 'zipTest2.zip';

const rootDir = join(tmpdir(), 'testkitZipTest');
if (fs.existsSync(rootDir)) {
fs.rmSync(rootDir, { recursive: true, force: true });
}
const sourceDir = join(rootDir, 'sourceDir');
const nestedDir = join(sourceDir, 'nestedDir');
const filePath1 = join(sourceDir, 'file1.txt');
const filePath2 = join(nestedDir, 'file2.txt');
let zipPath = '';
try {
await zipDir({
sourceDir: '',
destDir: process.cwd(),
fs.mkdirSync(nestedDir, { recursive: true });
fs.writeFileSync(filePath1, 'file 1 content');
fs.writeFileSync(filePath2, 'file 2 content');
const zipName = 'myZip.zip';
const expectedZipPath = join(rootDir, zipName);

zipPath = await zipDir({
sourceDir,
destDir: rootDir,
name: zipName,
});
assert(false, 'Expected zipDir() to throw an error');
} catch (e) {
const errMsg = 'diretory dirpath argument must be a non-empty string value';
expect(e).to.have.property('message', errMsg);

expect(fs.existsSync(expectedZipPath)).to.equal(true);
expect(fs.statSync(expectedZipPath).size).to.be.greaterThan(0);
expect(zipPath).to.equal(expectedZipPath);

// read the zip to ensure it has the expected files
const jsZip = new JSZip();
const zip = await jsZip.loadAsync(fs.readFileSync(zipPath));
expect(zip.files).to.haveOwnProperty('file1.txt');
expect(zip.files).to.haveOwnProperty('nestedDir/');
expect(zip.files).to.haveOwnProperty('nestedDir/file2.txt');
} finally {
fs.rmSync(rootDir, { recursive: true, force: true });
}
});
});
Loading

0 comments on commit f37c74e

Please sign in to comment.