Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

Commit

Permalink
perf: lazy-load deps
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed Apr 9, 2018
1 parent dd596c8 commit fbbfbf0
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"chalk": "^2.3.2"
},
"devDependencies": {
"@oclif/errors": "^1.0.3",
"@oclif/errors": "^1.0.4",
"@oclif/tslint": "^1.1.0",
"@types/chai": "^4.1.2",
"@types/mocha": "^5.0.0",
Expand Down
12 changes: 12 additions & 0 deletions src/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default () => {
const cache: {[k: string]: any} = {}
return {
add<T, K extends string, U>(this: T, name: K, fn: () => U): T & {[P in K]: U} {
Object.defineProperty(this, name, {
enumerable: true,
get: () => cache[name] || (cache[name] = fn()),
})
return this as any
},
}
}
15 changes: 11 additions & 4 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import {CLIError} from '@oclif/errors'

import {Arg} from './args'
import Deps from './deps'
import * as flags from './flags'
import {flagUsages} from './help'
import {renderList} from './list'
import * as Help from './help'
import * as List from './list'
import {ParserInput, ParserOutput} from './parse'

export {CLIError} from '@oclif/errors'

const m = Deps()
.add('help', () => require('./help') as typeof Help)
.add('list', () => require('./list') as typeof List)

export interface ICLIParseErrorOptions {
parse: {
input?: ParserInput
Expand All @@ -30,7 +37,7 @@ export class RequiredArgsError extends CLIParseError {
let message = `Missing ${args.length} required arg${args.length === 1 ? '' : 's'}`
const namedArgs = args.filter(a => a.name)
if (namedArgs.length) {
const list = renderList(namedArgs.map(a => [a.name, a.description] as [string, string]))
const list = m.list.renderList(namedArgs.map(a => [a.name, a.description] as [string, string]))
message += `:\n${list}`
}
super({parse, message})
Expand All @@ -42,7 +49,7 @@ export class RequiredFlagError extends CLIParseError {
public flags: flags.IFlag<any>[]

constructor({flags, parse}: ICLIParseErrorOptions & { flags: flags.IFlag<any>[] }) {
const usage = renderList(flagUsages(flags, {displayRequired: false}))
const usage = m.list.renderList(m.help.flagUsages(flags, {displayRequired: false}))
const message = `Missing required flag${flags.length === 1 ? '' : 's'}:\n${usage}`
super({parse, message})
this.flags = flags
Expand Down
15 changes: 8 additions & 7 deletions src/help.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import chalk from 'chalk'
import Chalk from 'chalk'

import Deps from './deps'
import {IFlag} from './flags'
import {sortBy} from './util'
import * as Util from './util'

function dim(s: string): string {
if (chalk) return chalk.dim(s)
return s
}
const m = Deps()
.add('chalk', () => require('chalk') as typeof Chalk)
.add('util', () => require('./util') as typeof Util)

export interface FlagUsageOptions { displayRequired?: boolean }
export function flagUsage(flag: IFlag<any>, options: FlagUsageOptions = {}): [string, string | undefined] {
Expand All @@ -18,13 +18,14 @@ export function flagUsage(flag: IFlag<any>, options: FlagUsageOptions = {}): [st

let description: string | undefined = flag.description || ''
if (options.displayRequired && flag.required) description = `(required) ${description}`
description = description ? dim(description) : undefined
description = description ? m.chalk.dim(description) : undefined

return [` ${label.join(',').trim()}${usage}`, description] as [string, string | undefined]
}

export function flagUsages(flags: IFlag<any>[], options: FlagUsageOptions = {}): [string, string | undefined][] {
if (!flags.length) return []
const {sortBy} = m.util
return sortBy(flags, f => [f.char ? -1 : 1, f.char, f.name])
.map(f => flagUsage(f, options))
}
8 changes: 6 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import * as args from './args'
import {OutputArgs, OutputFlags, Parser, ParserOutput as Output} from './parse'
export {args}
import * as flags from './flags'
import {validate} from './validate'
import * as Validate from './validate'
export {flags}
export {flagUsages} from './help'
import Deps from './deps'

const m = Deps()
.add('validate', () => require('./validate').validate as typeof Validate.validate)

export type Input<TFlags extends flags.Output> = {
flags?: flags.Input<TFlags>
Expand All @@ -30,7 +34,7 @@ export function parse<TFlags, TArgs extends {[name: string]: string}>(argv: stri
}
const parser = new Parser(input)
const output = parser.parse()
validate({input, output})
m.validate({input, output})
return output as any
}

Expand Down
18 changes: 11 additions & 7 deletions src/parse.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// tslint:disable interface-over-type-literal

import {CLIError} from '@oclif/errors'

import {Arg} from './args'
import Deps from './deps'
import * as Errors from './errors'
import * as Flags from './flags'
import {pickBy} from './util'
import * as Util from './util'

const m = Deps()
.add('errors', () => require('./errors') as typeof Errors)
.add('util', () => require('./util') as typeof Util)

let debug: any
try {
Expand Down Expand Up @@ -45,6 +48,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']
private readonly booleanFlags: { [k: string]: Flags.IBooleanFlag<any> }
private readonly context: any
constructor(private readonly input: T) {
const {pickBy} = m.util
this.context = input.context || {}
this.argv = input.argv.slice(0)
this._setNames()
Expand Down Expand Up @@ -95,7 +99,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']
input = arg.slice(arg[2] === '=' ? 3 : 2)
}
if (!input) {
throw new CLIError(`Flag --${name} expects a value`)
throw new m.errors.CLIError(`Flag --${name} expects a value`)
}
this.raw.push({type: 'flag', flag: flag.name, input})
} else {
Expand Down Expand Up @@ -151,7 +155,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']
const flags = {} as any
for (const token of this._flagTokens) {
const flag = this.input.flags[token.flag]
if (!flag) throw new CLIError(`Unexpected flag ${token.flag}`)
if (!flag) throw new m.errors.CLIError(`Unexpected flag ${token.flag}`)
if (flag.type === 'boolean') {
if (token.input === `--no-${flag.name}`) {
flags[token.flag] = false
Expand All @@ -162,7 +166,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']
} else {
const input = token.input
if (flag.options && !flag.options.includes(input)) {
throw new Errors.FlagInvalidOptionError(flag, input)
throw new m.errors.FlagInvalidOptionError(flag, input)
}
const value = flag.parse ? flag.parse(input, this.context) : input
if (flag.multiple) {
Expand Down Expand Up @@ -200,7 +204,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']
if (token) {
if (arg) {
if (arg.options && !arg.options.includes(token.input)) {
throw new Errors.ArgInvalidOptionError(arg, token.input)
throw new m.errors.ArgInvalidOptionError(arg, token.input)
}
args[i] = arg.parse(token.input)
} else {
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
version "1.0.0"
resolved "https://registry.yarnpkg.com/@heroku/linewrap/-/linewrap-1.0.0.tgz#a9d4e99f0a3e423a899b775f5f3d6747a1ff15c6"

"@oclif/errors@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.0.3.tgz#f23c024075855c7d116d041ee158f99bd51175af"
"@oclif/errors@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.0.4.tgz#8e34386ede530484ae3c98bc21d818c416214c66"
dependencies:
clean-stack "^1.3.0"
fs-extra "^5.0.0"
Expand Down

0 comments on commit fbbfbf0

Please sign in to comment.