Skip to content
This repository has been archived by the owner on Oct 21, 2020. It is now read-only.

feat(cli): add --watch option to create a plugin zip automatically #70

Merged
merged 1 commit into from
Mar 18, 2018
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ $ kintone-plugin-packer [OPTIONS] PLUGIN_DIR

- `--ppk PPK_FILE`: The path of input private key file. If omitted, it is generated automatically into `<Plugin ID>.ppk` in the same directory of `PLUGIN_DIR` or `--out` if specified.
- `--out PLUGIN_FILE`: The path of generated plugin file. The default is `plugin.zip` in the same directory of `PLUGIN_DIR`.
- `--watch`: Watch PLUGIN_DIR for the changes.


## How to use with `npm run`
Expand Down
4 changes: 4 additions & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const flagSpec = {
out: {
type: 'string',
},
watch: {
type: 'boolean',
},
};

const cli = meow(
Expand All @@ -24,6 +27,7 @@ Usage
Options
--ppk PPK_FILE: Private key file. If omitted, it's generated into '<Plugin ID>.ppk' in the same directory of PLUGIN_DIR.
--out PLUGIN_FILE: The default is 'plugin.zip' in the same directory of PLUGIN_DIR.
--watch: Watch PLUGIN_DIR for the changes.
`,
{
flag: flagSpec,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
},
"dependencies": {
"@teppeis/kintone-plugin-manifest-validator": "^0.6.1",
"chokidar": "^2.0.2",
"debug": "^3.1.0",
"denodeify": "^1.2.1",
"meow": "^4.0.0",
Expand Down
109 changes: 64 additions & 45 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const path = require('path');
const fs = require('fs');
const chokidar = require('chokidar');
const denodeify = require('denodeify');

const writeFile = denodeify(fs.writeFile);
Expand All @@ -22,51 +23,69 @@ function cli(pluginDir, options) {
options = options || {};
const packerLocal = options.packerMock_ ? options.packerMock_ : packer;

// 1. check if pluginDir is a directory
if (!fs.statSync(pluginDir).isDirectory()) {
throw new Error(`${pluginDir} should be a directory.`);
}

// 2. check pluginDir/manifest.json
const manifestJsonPath = path.join(pluginDir, 'manifest.json');
if (!fs.statSync(manifestJsonPath).isFile()) {
throw new Error('Manifest file $PLUGIN_DIR/manifest.json not found.');
}

// 3. validate manifest.json
const manifest = loadJson(manifestJsonPath);
throwIfInvalidManifest(manifest, pluginDir);

let outputDir = path.dirname(path.resolve(pluginDir));
let outputFile = path.join(outputDir, 'plugin.zip');
if (options.out) {
outputFile = options.out;
outputDir = path.dirname(path.resolve(outputFile));
}
debug(`outputDir : ${outputDir}`);
debug(`outputFile : ${outputFile}`);

// 4. generate new ppk if not specified
const ppkFile = options.ppk;
let privateKey;
if (ppkFile) {
debug(`loading an existing key: ${ppkFile}`);
privateKey = fs.readFileSync(ppkFile, 'utf8');
}

// 5. package plugin.zip
return Promise.all([
mkdirp(outputDir),
createContentsZip(pluginDir, manifest).then(contentsZip =>
packerLocal(contentsZip, privateKey)
),
]).then(result => {
const output = result[1];
if (!ppkFile) {
fs.writeFileSync(path.join(outputDir, `${output.id}.ppk`), output.privateKey, 'utf8');
}
return outputPlugin(outputFile, output.plugin);
});
return Promise.resolve()
.then(() => {
// 1. check if pluginDir is a directory
if (!fs.statSync(pluginDir).isDirectory()) {
throw new Error(`${pluginDir} should be a directory.`);
}

// 2. check pluginDir/manifest.json
const manifestJsonPath = path.join(pluginDir, 'manifest.json');
if (!fs.statSync(manifestJsonPath).isFile()) {
throw new Error('Manifest file $PLUGIN_DIR/manifest.json not found.');
}

// 3. validate manifest.json
const manifest = loadJson(manifestJsonPath);
throwIfInvalidManifest(manifest, pluginDir);

let outputDir = path.dirname(path.resolve(pluginDir));
let outputFile = path.join(outputDir, 'plugin.zip');
if (options.out) {
outputFile = options.out;
outputDir = path.dirname(path.resolve(outputFile));
}
debug(`outputDir : ${outputDir}`);
debug(`outputFile : ${outputFile}`);

// 4. generate new ppk if not specified
const ppkFile = options.ppk;
let privateKey;
if (ppkFile) {
debug(`loading an existing key: ${ppkFile}`);
privateKey = fs.readFileSync(ppkFile, 'utf8');
}

// 5. package plugin.zip
return Promise.all([
mkdirp(outputDir),
createContentsZip(pluginDir, manifest).then(contentsZip =>
packerLocal(contentsZip, privateKey)
),
]).then(result => {
const output = result[1];
if (!ppkFile) {
fs.writeFileSync(path.join(outputDir, `${output.id}.ppk`), output.privateKey, 'utf8');
}

if (options.watch) {
const watcher = chokidar.watch(pluginDir);
watcher.on('change', () => {
cli(pluginDir, Object.assign({}, options, {watch: false}));
});
}
return outputPlugin(outputFile, output.plugin);
});
})
.then(outputFile => {
console.log('Succeeded:', outputFile);
return outputFile;
})
.catch(error => {
console.error('Failed:', error.message);
return Promise.reject(error);
});
}

module.exports = cli;
Expand Down
42 changes: 26 additions & 16 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,38 @@ describe('cli', () => {
});
});

it('invalid `url`', () => {
assert.throws(() => {
cli(path.join(fixturesDir, 'plugin-invalid-url'), {packerMock_: packer});
}, /Invalid manifest.json/);
it('invalid `url`', done => {
cli(path.join(fixturesDir, 'plugin-invalid-url'), {packerMock_: packer}).catch(error => {
assert(/Invalid manifest.json/.test(error.message));
done();
});
});

it('invalid `https-url`', () => {
assert.throws(() => {
cli(path.join(fixturesDir, 'plugin-invalid-https-url'), {packerMock_: packer});
}, /Invalid manifest.json/);
it('invalid `https-url`', done => {
cli(path.join(fixturesDir, 'plugin-invalid-https-url'), {packerMock_: packer}).catch(
error => {
assert(/Invalid manifest.json/.test(error.message));
done();
}
);
});

it('invalid `relative-path`', () => {
assert.throws(() => {
cli(path.join(fixturesDir, 'plugin-invalid-relative-path'), {packerMock_: packer});
}, /Invalid manifest.json/);
it('invalid `relative-path`', done => {
cli(path.join(fixturesDir, 'plugin-invalid-relative-path'), {packerMock_: packer}).catch(
error => {
assert(/Invalid manifest.json/.test(error.message));
done();
}
);
});

it('invalid `maxFileSize`', () => {
assert.throws(() => {
cli(path.join(fixturesDir, 'plugin-invalid-maxFileSize'), {packerMock_: packer});
}, /Invalid manifest.json/);
it('invalid `maxFileSize`', done => {
cli(path.join(fixturesDir, 'plugin-invalid-maxFileSize'), {packerMock_: packer}).catch(
error => {
assert(/Invalid manifest.json/.test(error.message));
done();
}
);
});
});

Expand Down