Add commands help in rondo command

This commit is contained in:
Jerko Steiner 2019-10-01 08:31:57 +07:00
parent cd569887c0
commit 5bd2121a7d
13 changed files with 77 additions and 26 deletions

View File

@ -3,6 +3,7 @@ import { arg, argparse } from '@rondo.dev/argparse'
import { Command } from './Command' import { Command } from './Command'
import * as log from './log' import * as log from './log'
import { resolve } from './resolve' import { resolve } from './resolve'
import { getHelp } from './util/getHelp'
async function run( async function run(
commandName: string, commandName: string,
@ -25,19 +26,27 @@ async function start(
exit = (code: number) => process.exit(code), exit = (code: number) => process.exit(code),
) { ) {
const commands = await resolve() const commands = await resolve()
const choices = Object.keys(commands)
.filter(c => !c.startsWith('_') && typeof commands[c] === 'function')
const desc = 'Commands:\n ' + choices
.filter(choice => typeof commands[choice] === 'function')
.map(choice => getHelp(commands[choice]))
.join('\n ')
const {parse} = argparse({ const {parse} = argparse({
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
debug: arg('boolean'), debug: arg('boolean'),
command: arg('string', { command: arg('string', {
required: true, required: true,
positional: true, positional: true,
choices: Object.keys(commands).filter(c => !c.startsWith('_')), choices,
}), }),
args: arg('string[]', { args: arg('string[]', {
n: '*', n: '*',
positional: true, positional: true,
}), }),
}) }, desc)
let args: ReturnType<typeof parse> | null = null let args: ReturnType<typeof parse> | null = null
try { try {

View File

@ -31,7 +31,7 @@ export async function add(...argv: string[]) {
description: 'Print help message', description: 'Print help message',
}), }),
// frontend: arg('boolean', {alias: 'f'}), // frontend: arg('boolean', {alias: 'f'}),
}, 'Create a new library from template') }, add.help)
const args = parse(argv) const args = parse(argv)
const destDir = path.join('./packages', args.name) const destDir = path.join('./packages', args.name)
@ -63,3 +63,5 @@ export async function add(...argv: string[]) {
pkg.dependencies[libraryName] = `file:packages/${args.name}` pkg.dependencies[libraryName] = `file:packages/${args.name}`
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, ' ')) fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, ' '))
} }
add.help = 'Create a new package from template. ' +
'Update root package.json with its definition'

View File

@ -23,12 +23,13 @@ export async function build(...argv: string[]) {
description: 'Watch for changes', description: 'Watch for changes',
}), }),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, build.help)
const args = parse(argv) const args = parse(argv)
const path = args.esm ? join(args.project, 'tsconfig.esm.json') : args.project const path = args.esm ? join(args.project, 'tsconfig.esm.json') : args.project
const watchArgs = args.watch ? ['--watch', '--preserveWatchOutput'] : [] const watchArgs = args.watch ? ['--watch', '--preserveWatchOutput'] : []
await run(tsc, ['--build', path, ...watchArgs]) await run(tsc, ['--build', path, ...watchArgs])
} }
build.help = 'Build or watch TypeScript project'
export async function test(...argv: string[]) { export async function test(...argv: string[]) {
const {args} = argparse({ const {args} = argparse({
@ -37,10 +38,11 @@ export async function test(...argv: string[]) {
positional: true, positional: true,
}), }),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, test.help)
.parse(argv) .parse(argv)
await run('jest', args) await run('jest', args)
} }
test.help = 'Run jest tests'
export async function exec(...argv: string[]) { export async function exec(...argv: string[]) {
const {parse} = argparse({ const {parse} = argparse({
@ -53,7 +55,7 @@ export async function exec(...argv: string[]) {
positional: true, positional: true,
}), }),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, exec.help)
const args = parse(argv) const args = parse(argv)
const {file} = args const {file} = args
const command = file.endsWith('.ts') ? 'ts-node' : 'node' const command = file.endsWith('.ts') ? 'ts-node' : 'node'
@ -65,13 +67,14 @@ export async function exec(...argv: string[]) {
] : [] ] : []
await run(command, [...nodeArgs, file, ...args.args]) await run(command, [...nodeArgs, file, ...args.args])
} }
exec.help = 'Execute a js or ts file using node or ts-node'
export async function createMigration(...argv: string[]) { export async function createMigration(...argv: string[]) {
const args = argparse({ const args = argparse({
name: arg('string', {required: true, positional: true}), name: arg('string', {required: true, positional: true}),
project: arg('string', {alias: 'p', default: '.'}), project: arg('string', {alias: 'p', default: '.'}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, createMigration.help)
.parse(argv) .parse(argv)
const {name, project} = args const {name, project} = args
@ -84,6 +87,7 @@ export async function createMigration(...argv: string[]) {
} }
await run('ts-node', [typeorm, 'migration:generate', '--name', name], project) await run('ts-node', [typeorm, 'migration:generate', '--name', name], project)
} }
createMigration.help = 'Generate a new TypeORM migration'
function findTsConfig(file: string): string { function findTsConfig(file: string): string {
let lastPath = '' let lastPath = ''
@ -110,6 +114,7 @@ async function browserify(path = '.', ...extraArgs: string[]) {
...extraArgs, ...extraArgs,
]) ])
} }
browserify.help = 'Build a client-side bundle using browserify'
async function uglify(path = '.') { async function uglify(path = '.') {
await run('uglifyjs', [ await run('uglifyjs', [
@ -121,18 +126,20 @@ async function uglify(path = '.') {
join(path, 'build', 'client.prod.js'), join(path, 'build', 'client.prod.js'),
]) ])
} }
uglify.help = 'Uglify bundle'
export async function js(...argv: string[]) { export async function js(...argv: string[]) {
const args = argparse({ const args = argparse({
path: arg('string', {positional: true, default: '.'}), path: arg('string', {positional: true, default: '.'}),
watch: arg('boolean', {alias: 'w'}), watch: arg('boolean', {alias: 'w'}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, js.help)
.parse(argv) .parse(argv)
const {path, watch} = args const {path, watch} = args
return watch ? watchJs(path) : buildJs(path) return watch ? watchJs(path) : buildJs(path)
} }
js.help = 'Build or watch client-side js files'
async function buildJs(path: string) { async function buildJs(path: string) {
await build(...['-p', path, '--esm']) await build(...['-p', path, '--esm'])
@ -158,7 +165,7 @@ export async function css(...argv: string[]) {
path: arg('string', {positional: true, default: '.'}), path: arg('string', {positional: true, default: '.'}),
watch: arg('boolean', {alias: 'w'}), watch: arg('boolean', {alias: 'w'}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, css.help)
.parse(argv) .parse(argv)
const {path, watch} = args const {path, watch} = args
@ -173,6 +180,7 @@ export async function css(...argv: string[]) {
join(path, 'scss'), join(path, 'scss'),
]) ])
} }
css.help = 'Build or watch sass files'
async function watchCss(path = '.') { async function watchCss(path = '.') {
await run('node-sass', [ await run('node-sass', [
@ -212,3 +220,4 @@ export async function frontend(...argv: string[]) {
] ]
await Promise.all(promises) await Promise.all(promises)
} }
frontend.help = 'Build all frontend files'

View File

@ -15,7 +15,7 @@ export async function clean(...argv: string[]) {
positional: true, positional: true,
}), }),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, clean.help)
const args = parse(argv) const args = parse(argv)
@ -30,3 +30,4 @@ export async function clean(...argv: string[]) {
await rimrafAsync(path) await rimrafAsync(path)
} }
} }
clean.help = 'Remove *.tsbuildinfo, lib/ and esm/ folders'

View File

@ -9,7 +9,7 @@ export async function exportDir(...argv: string[]) {
dir: arg('string', {default: 'src/migrations'}), dir: arg('string', {default: 'src/migrations'}),
out: arg('string', {default: 'src/migrations/index.ts'}), out: arg('string', {default: 'src/migrations/index.ts'}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}) }, exportDir.help)
.parse(argv) .parse(argv)
const dir = join(args.project, args.dir) const dir = join(args.project, args.dir)
@ -26,3 +26,5 @@ export async function exportDir(...argv: string[]) {
info('Writing to %s', out) info('Writing to %s', out)
fs.writeFileSync(join(dir, 'index.ts'), index) fs.writeFileSync(join(dir, 'index.ts'), index)
} }
exportDir.help = 'Create index.ts and generate import statements for files ' +
'in the same directory'

View File

@ -40,12 +40,12 @@ export function imports(...argv: string[]): string[] {
readDirectory: ts.sys.readDirectory, readDirectory: ts.sys.readDirectory,
useCaseSensitiveFileNames: true, useCaseSensitiveFileNames: true,
} }
const configFile = ts.readConfigFile(configPath, ts.sys.readFile); const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
const parsedCommandLine = ts.parseJsonConfigFileContent( const parsedCommandLine = ts.parseJsonConfigFileContent(
configFile.config, configFile.config,
parseConfigHost, parseConfigHost,
projectDir, projectDir,
); )
const program = ts.createProgram( const program = ts.createProgram(
parsedCommandLine.fileNames, parsedCommandLine.fileNames,
@ -116,3 +116,6 @@ export function imports(...argv: string[]): string[] {
return [] return []
} }
imports.help = 'Find used module in a package, use root package.json to ' +
'find dependency versions and update local package.json. Useful when using ' +
'hoisting in lerna'

View File

@ -62,7 +62,7 @@ export function intergen(...argv: string[]): string {
debug: arg('boolean'), debug: arg('boolean'),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
output: arg('string', {alias: 'o', default: '-'}), output: arg('string', {alias: 'o', default: '-'}),
}).parse(argv) }, intergen.help).parse(argv)
function debug(m: string, ...meta: Array<unknown>) { function debug(m: string, ...meta: Array<unknown>) {
if (args.debug) { if (args.debug) {
@ -379,3 +379,4 @@ export function intergen(...argv: string[]): string {
} }
return value return value
} }
intergen.help = 'Generate TypeScript interfaces from all found classes'

View File

@ -15,7 +15,7 @@ export async function syncEsmConfig(...argv: string[]) {
const args = argparse({ const args = argparse({
packages: arg('string', {default: 'packages/', positional: true}), packages: arg('string', {default: 'packages/', positional: true}),
help: arg('boolean', {alias: 'h'}), help: arg('boolean', {alias: 'h'}),
}, `Synchronizes ${TSCONFIG_ESM_FILENAME} files with ${TSCONFIG_FILENAME}`) }, syncEsmConfig.help)
.parse(argv) .parse(argv)
const pkgDir = args.packages const pkgDir = args.packages
@ -53,3 +53,5 @@ export async function syncEsmConfig(...argv: string[]) {
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, ' ')) fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, ' '))
}) })
} }
syncEsmConfig.help =
`Synchronizes ${TSCONFIG_ESM_FILENAME} files with ${TSCONFIG_FILENAME}`

View File

@ -1,13 +1,14 @@
import * as fs from 'fs' import { arg, argparse } from '@rondo.dev/argparse'
import _unpack from 'browser-unpack' import _unpack from 'browser-unpack'
import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import { argparse, arg } from '@rondo.dev/argparse' import { padLeft } from '../util'
export async function unpack(...argv: string[]) { export async function unpack(...argv: string[]) {
const args = argparse({ const args = argparse({
filename: arg('string', {positional: true, required: true}), filename: arg('string', {positional: true, required: true}),
help: arg('boolean'), help: arg('boolean'),
}).parse(argv) }, unpack.help).parse(argv)
const file = fs.readFileSync(args.filename, 'utf8') const file = fs.readFileSync(args.filename, 'utf8')
const result = _unpack(file) const result = _unpack(file)
@ -38,13 +39,6 @@ export async function unpack(...argv: string[]) {
return text return text
} }
function padLeft(text: string, size: number) {
while (text.length < size) {
text = ' ' + text
}
return text
}
sizes sizes
.forEach(item => { .forEach(item => {
console.log( console.log(
@ -58,12 +52,13 @@ export async function unpack(...argv: string[]) {
padLeft((totalSize / 1024).toFixed(3) + ' kb', maxSizeLength), padLeft((totalSize / 1024).toFixed(3) + ' kb', maxSizeLength),
) )
} }
unpack.help = 'Show name and size of each module in browserify bundle'
export async function unpackInverseDeps(...argv: string[]) { export async function unpackInverseDeps(...argv: string[]) {
const args = argparse({ const args = argparse({
filename: arg('string', {positional: true, required: true}), filename: arg('string', {positional: true, required: true}),
help: arg('boolean'), help: arg('boolean'),
}).parse(argv) }, unpackInverseDeps.help).parse(argv)
const file = fs.readFileSync(args.filename, 'utf8') const file = fs.readFileSync(args.filename, 'utf8')
const result = _unpack(file) const result = _unpack(file)
@ -90,3 +85,5 @@ export async function unpackInverseDeps(...argv: string[]) {
console.log('') console.log('')
}) })
} }
unpackInverseDeps.help =
'List inversed dependencies in a browserify bundle'

View File

@ -85,3 +85,4 @@ export async function update(...argv: string[]) {
info('Done! Do not forget to run npm install!') info('Done! Do not forget to run npm install!')
} }
} }
update.help = 'Update all dependencies to the latest versions'

View File

@ -0,0 +1,10 @@
import { padRight } from './pad'
export function getHelp(fn: (...args: string[]) => unknown): string {
const name = fn.name
const fn2 = fn as {help?: string}
if (typeof fn2.help === 'string') {
return padRight(name, 17) + ' ' + fn2.help
}
return name
}

View File

@ -0,0 +1 @@
export * from './pad'

View File

@ -0,0 +1,13 @@
export function padLeft(text: string, size: number) {
while (text.length < size) {
text = ' ' + text
}
return text
}
export function padRight(text: string, size: number) {
while (text.length < size) {
text = text + ' '
}
return text
}