268 lines
5.4 KiB
JavaScript
Executable file
268 lines
5.4 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
'use strict';
|
|
|
|
const assert = require('bsert');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
const util = require('util');
|
|
const cp = require('child_process');
|
|
const exec = util.promisify(cp.exec);
|
|
const fs = require('bfile');
|
|
const Config = require('bcfg');
|
|
|
|
const ROOT = path.dirname(__dirname);
|
|
const NAME = 'hs-client';
|
|
const HSD_PKG = require(path.join(ROOT, 'package.json'));
|
|
|
|
const REMOTE = 'git@github.com:handshake-org/hs-client.git';
|
|
|
|
const INIT_HS_CLIENT_PKG = {
|
|
name: 'hs-client',
|
|
description: 'HSD node and wallet client',
|
|
keywords: [
|
|
'http',
|
|
'request',
|
|
'socket.io',
|
|
'websockets'
|
|
],
|
|
main: './lib/client/index.js',
|
|
bin: {
|
|
'hsd-cli': './bin/hsd-cli',
|
|
'hsd-rpc': './bin/hsd-rpc',
|
|
'hsw-cli': './bin/hsw-cli',
|
|
'hsw-rpc': './bin/hsw-rpc'
|
|
},
|
|
engines: {
|
|
node: '>=8.0.0'
|
|
}
|
|
};
|
|
|
|
const INHERIT_PROPERTIES = [
|
|
'version',
|
|
'license',
|
|
'repository',
|
|
'homepage',
|
|
'bugs',
|
|
'author'
|
|
];
|
|
|
|
const DEPENDENCIES = [
|
|
'bcfg',
|
|
'bcurl',
|
|
'bsert'
|
|
];
|
|
|
|
const COPY_FILES = [
|
|
'.npmignore',
|
|
'.gitignore',
|
|
'bin/hsd-cli',
|
|
'bin/hsw-cli',
|
|
'bin/hsd-rpc',
|
|
'bin/hsw-rpc',
|
|
'lib/client/index.js',
|
|
'lib/client/wallet.js',
|
|
'lib/client/node.js',
|
|
'LICENSE',
|
|
'SECURITY.md'
|
|
];
|
|
|
|
const README = `
|
|
hs-client
|
|
=========
|
|
|
|
Autogenerated from https://github.com/handshake-org/hsd.
|
|
|
|
REST and RPC client for handshake.
|
|
|
|
## Usage
|
|
|
|
\`\`\` js
|
|
const {NodeClient, WalletClient} = require('hs-client');
|
|
\`\`\`
|
|
`;
|
|
|
|
const HELP = `Usage: gen-hsclient [DIRECTORY] [OPTIONS]...
|
|
Generate hs-client package in DIRECTORY.
|
|
|
|
OPTIONS:
|
|
--no-git - Don't setup git.
|
|
--verbose - Verbose output.
|
|
--no-steps - Don't print next steps.
|
|
`;
|
|
|
|
async function ensureDir(dir) {
|
|
dir = path.resolve(dir);
|
|
|
|
if (dir.startsWith(ROOT))
|
|
throw new Error(`${NAME} needs to be outside of the hsd. ${dir}`);
|
|
|
|
if (await fs.exists(dir)) {
|
|
throw new Error(
|
|
`Directory ${dir} already exists.`
|
|
+ ' Please remove to proceed or choose different directory.'
|
|
);
|
|
}
|
|
|
|
await fs.mkdir(dir);
|
|
return dir;
|
|
}
|
|
|
|
async function setupPackageContent(dir) {
|
|
for (const file of COPY_FILES) {
|
|
const src = path.join(ROOT, file);
|
|
const dst = path.join(dir, file);
|
|
const dstDir = path.dirname(dst);
|
|
|
|
if (!await fs.exists(dstDir))
|
|
await fs.mkdirp(dstDir);
|
|
|
|
await fs.copy(src, dst);
|
|
}
|
|
|
|
const hsClientPkg = {
|
|
...INIT_HS_CLIENT_PKG
|
|
};
|
|
|
|
for (const name of INHERIT_PROPERTIES) {
|
|
assert(HSD_PKG[name]);
|
|
hsClientPkg[name] = HSD_PKG[name];
|
|
}
|
|
|
|
hsClientPkg.dependencies = {};
|
|
for (const dep of DEPENDENCIES) {
|
|
assert(HSD_PKG.dependencies[dep], `Dependency "${dep}" not found for hsd.`);
|
|
hsClientPkg.dependencies[dep] = HSD_PKG.dependencies[dep];
|
|
}
|
|
|
|
await fs.writeJSON(path.join(dir, 'package.json'), hsClientPkg);
|
|
await fs.writeFile(path.join(dir, 'README.md'), README);
|
|
|
|
return hsClientPkg;
|
|
}
|
|
|
|
async function setupGit(dir, log) {
|
|
const commands = [
|
|
'git init -b master',
|
|
`git remote add origin ${REMOTE}`,
|
|
'git fetch -q origin master',
|
|
'git pull -q origin master',
|
|
'git rm -r .'
|
|
];
|
|
|
|
log('Setting up git: ', dir);
|
|
|
|
for (const cmd of [...commands]) {
|
|
log(` > ${cmd} in ${dir}.`);
|
|
log(await execCmd(cmd, dir, 20000));
|
|
commands.shift();
|
|
}
|
|
}
|
|
|
|
async function finalGit(dir, version, log) {
|
|
const commands = [
|
|
'git add .',
|
|
`git commit --gpg-sign -m "v${version}"`,
|
|
`git tag --sign v${version} -m "v${version}"`
|
|
];
|
|
|
|
const manualCommands = [
|
|
'git push origin master',
|
|
`git push origin v${version}`
|
|
];
|
|
|
|
for (const cmd of [...commands]) {
|
|
log(` > ${cmd} in ${dir}.`);
|
|
|
|
try {
|
|
log(await execCmd(cmd, dir));
|
|
} catch (e) {
|
|
console.log(`Failed to execute: ${cmd}.`);
|
|
console.log(e.message);
|
|
console.log('You need to proceed manually.');
|
|
break;
|
|
}
|
|
|
|
commands.shift();
|
|
}
|
|
|
|
return [...commands, ...manualCommands];
|
|
}
|
|
|
|
(async () => {
|
|
const config = new Config('hsd', {
|
|
alias: {
|
|
'v': 'verbose'
|
|
}
|
|
});
|
|
|
|
config.load({
|
|
argv: true,
|
|
env: true
|
|
});
|
|
|
|
if (config.bool('help')) {
|
|
console.log(HELP);
|
|
process.exit(0);
|
|
}
|
|
|
|
const dir = config.str(0, tmpdir());
|
|
const verbose = config.bool('verbose', false);
|
|
const noGit = config.bool('no-git', false);
|
|
const noSteps = config.bool('no-steps', false);
|
|
|
|
const log = verbose ? console.log : () => {};
|
|
|
|
const pkgDir = await ensureDir(dir);
|
|
|
|
if (!noSteps && !noGit)
|
|
await setupGit(pkgDir, log);
|
|
|
|
log(`Copying files to ${pkgDir}...`);
|
|
const pkg = await setupPackageContent(pkgDir);
|
|
|
|
if (noSteps)
|
|
return;
|
|
|
|
let gitNext;
|
|
|
|
if (!noGit)
|
|
gitNext = await finalGit(pkgDir, pkg.version, log);
|
|
|
|
console.log(`Generated ${pkgDir}.`);
|
|
console.log('Next steps:');
|
|
console.log(` $ cd ${pkgDir}`);
|
|
|
|
if (!noGit) {
|
|
assert(gitNext);
|
|
console.log('Git Next:');
|
|
for (const cmd of gitNext)
|
|
console.log(` $ ${cmd}`);
|
|
}
|
|
|
|
console.log('NPM Next:');
|
|
console.log(' $ npm publish --dry-run # check if everything is ok');
|
|
console.log(' $ npm publish');
|
|
})().catch((err) => {
|
|
console.log('Try passing --help for help.');
|
|
console.error(err.stack);
|
|
process.exit(1);
|
|
});
|
|
|
|
function tmpdir() {
|
|
return path.join(os.tmpdir(), NAME + '-' + Date.now());
|
|
}
|
|
|
|
async function execCmd(cmd, cwd, timeout = 2000) {
|
|
assert(cwd, 'CWD is required.');
|
|
|
|
const {stdout, stderr} = await exec(cmd, {
|
|
cwd,
|
|
timeout
|
|
});
|
|
|
|
if (stderr.length !== 0)
|
|
throw new Error(stderr);
|
|
|
|
return stdout;
|
|
}
|