hsd
Version:
Cryptocurrency bike-shed
269 lines (213 loc) • 5.51 kB
JavaScript
;
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;
}