mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 05:37:34 +03:00
Consistent interface and response
- Creating a better, more long-term API here - compress and extract are opposite, neat terms - Use new Promise to get rid of callback argument when using archiver to compress a folder - Add options argument, and make a couple of key details configurable - Make the response intelligable - Ensure both functions are consistent - Updated tests to match
This commit is contained in:
parent
62c2fce6cc
commit
adfb3fe499
@ -11,6 +11,17 @@ or
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
const zip = require('@tryghost/zip');
|
||||||
|
|
||||||
|
// Create a zip from a folder
|
||||||
|
|
||||||
|
let res = await zip.compress('path/to/a/folder', 'path/to/archive.zip', [options])
|
||||||
|
|
||||||
|
// Extract a zip to a folder
|
||||||
|
|
||||||
|
let res = await zip.extract('path/to/archive.zip', 'path/to/files', [options])
|
||||||
|
```
|
||||||
|
|
||||||
## Develop
|
## Develop
|
||||||
|
|
||||||
@ -34,6 +45,6 @@ Follow the instructions for the top-level repo.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Copyright & License
|
# Copyright & License
|
||||||
|
|
||||||
Copyright (c) 2020 Ghost Foundation - Released under the [MIT license](LICENSE).
|
Copyright (c) 2020 Ghost Foundation - Released under the [MIT license](LICENSE).
|
@ -1,7 +1,4 @@
|
|||||||
const extract = require('extract-zip');
|
|
||||||
const zipFolder = require('./lib/zip-folder');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extract,
|
extract: require('./lib/extract'),
|
||||||
zipFolder
|
compress: require('./lib/compress')
|
||||||
};
|
};
|
||||||
|
50
ghost/zip/lib/compress.js
Normal file
50
ghost/zip/lib/compress.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const fs = require('fs-extra');
|
||||||
|
const Promise = require('bluebird');
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
type: 'zip',
|
||||||
|
glob: '**/*',
|
||||||
|
ignore: ['node_modules/**']
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compress
|
||||||
|
*
|
||||||
|
* - Create a zip file from a folder
|
||||||
|
*
|
||||||
|
* @param {String} folderToZip - full path to the folder to be zipped
|
||||||
|
* @param {String} destination - full path to the resulting zip file
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @param {String} options.type - zip by default see archiver for other options
|
||||||
|
* @param {String} options.glob - the files to include, defaults to all files and folders
|
||||||
|
* @param {Array} options.ignore - any paths that should be ignored, sets node_modules by default
|
||||||
|
*/
|
||||||
|
module.exports = (folderToZip, destination, options = {}) => {
|
||||||
|
const opts = Object.assign({}, defaultOptions, options);
|
||||||
|
|
||||||
|
const archiver = require('archiver');
|
||||||
|
const output = fs.createWriteStream(destination);
|
||||||
|
const archive = archiver.create(opts.type, {});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// If folder to zip is a symlink, we want to get the target
|
||||||
|
// of the link and zip that instead of zipping the symlink
|
||||||
|
if (fs.lstatSync(folderToZip).isSymbolicLink()) {
|
||||||
|
folderToZip = fs.realpathSync(folderToZip);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.on('close', function () {
|
||||||
|
resolve({path: destination, size: archive.pointer()});
|
||||||
|
});
|
||||||
|
|
||||||
|
archive.on('error', function (err) {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
archive.glob(opts.glob, {
|
||||||
|
cwd: folderToZip,
|
||||||
|
ignore: opts.ignore
|
||||||
|
});
|
||||||
|
archive.pipe(output);
|
||||||
|
archive.finalize();
|
||||||
|
});
|
||||||
|
};
|
25
ghost/zip/lib/extract.js
Normal file
25
ghost/zip/lib/extract.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const defaultOptions = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract
|
||||||
|
*
|
||||||
|
* - Unzip an archive to a folder
|
||||||
|
*
|
||||||
|
* @param {String} zipToExtract - full path to zip file that should be extracted
|
||||||
|
* @param {String} destination - full path of the extraction target
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @param {Integer} options.defaultDirMode - Directory Mode (permissions), defaults to 0o755
|
||||||
|
* @param {Integer} options.defaultFileMode - File Mode (permissions), defaults to 0o644
|
||||||
|
* @param {Function} options.onEntry - if present, will be called with (entry, zipfile) for every entry in the zip
|
||||||
|
*/
|
||||||
|
module.exports = (zipToExtract, destination, options) => {
|
||||||
|
const opts = Object.assign({}, defaultOptions, options);
|
||||||
|
|
||||||
|
const extract = require('extract-zip');
|
||||||
|
|
||||||
|
opts.dir = destination;
|
||||||
|
|
||||||
|
return extract(zipToExtract, opts).then(() => {
|
||||||
|
return {path: destination};
|
||||||
|
});
|
||||||
|
};
|
@ -1,30 +0,0 @@
|
|||||||
const fs = require('fs-extra');
|
|
||||||
const Promise = require('bluebird');
|
|
||||||
|
|
||||||
const zipFolder = (folderToZip, destination, callback) => {
|
|
||||||
var archiver = require('archiver'),
|
|
||||||
output = fs.createWriteStream(destination),
|
|
||||||
archive = archiver.create('zip', {});
|
|
||||||
|
|
||||||
// If folder to zip is a symlink, we want to get the target
|
|
||||||
// of the link and zip that instead of zipping the symlink
|
|
||||||
if (fs.lstatSync(folderToZip).isSymbolicLink()) {
|
|
||||||
folderToZip = fs.realpathSync(folderToZip);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.on('close', function () {
|
|
||||||
callback(null, archive.pointer());
|
|
||||||
});
|
|
||||||
|
|
||||||
archive.on('error', function (err) {
|
|
||||||
callback(err, null);
|
|
||||||
});
|
|
||||||
archive.glob(`**/*`, {
|
|
||||||
cwd: folderToZip,
|
|
||||||
ignore: ['node_modules/**']
|
|
||||||
});
|
|
||||||
archive.pipe(output);
|
|
||||||
archive.finalize();
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Promise.promisify(zipFolder);
|
|
@ -6,9 +6,9 @@ const path = require('path');
|
|||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
// Mimic how we expect this to be required
|
// Mimic how we expect this to be required
|
||||||
const {zipFolder, extract} = require('../');
|
const {compress, extract} = require('../');
|
||||||
|
|
||||||
describe('lib/fs: read csv', function () {
|
describe('Compress and Extract should be opposite functions', function () {
|
||||||
let symlinkPath, folderToSymlink, zipDestination, unzipDestination;
|
let symlinkPath, folderToSymlink, zipDestination, unzipDestination;
|
||||||
|
|
||||||
const cleanUp = () => {
|
const cleanUp = () => {
|
||||||
@ -33,10 +33,17 @@ describe('lib/fs: read csv', function () {
|
|||||||
it('ensure symlinks work', function (done) {
|
it('ensure symlinks work', function (done) {
|
||||||
fs.symlink(folderToSymlink, symlinkPath);
|
fs.symlink(folderToSymlink, symlinkPath);
|
||||||
|
|
||||||
zipFolder(symlinkPath, zipDestination)
|
compress(symlinkPath, zipDestination)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
extract(zipDestination, {dir: unzipDestination})
|
res.should.be.an.Object().with.properties('path', 'size');
|
||||||
.then(() => {
|
res.path.should.eql(zipDestination);
|
||||||
|
res.size.should.eql(321775);
|
||||||
|
|
||||||
|
extract(zipDestination, unzipDestination)
|
||||||
|
.then((res) => {
|
||||||
|
res.should.be.an.Object().with.properties('path');
|
||||||
|
res.path.should.eql(unzipDestination);
|
||||||
|
|
||||||
fs.readdir(unzipDestination, function (err, files) {
|
fs.readdir(unzipDestination, function (err, files) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
Loading…
Reference in New Issue
Block a user