Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sywac

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sywac - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

26

api.js
'use strict'
const SOURCE_DEFAULT = require('./types/type').SOURCE_DEFAULT
class Api {

@@ -508,3 +510,11 @@ static get DEFAULT_COMMAND_INDICATOR () {

let context = this.initContext(false).slurpArgs(args)
// init unknownType in context only for the top-level (all levels share/overwrite the same argv._)
if (this.unknownType) {
this.unknownType.setValue(context, this.unknownType.defaultVal)
this.unknownType.applySource(context, SOURCE_DEFAULT)
}
if (this._showHelpByDefault && !context.details.args.length) context.deferHelp() // preemptively request help
return this.parseFromContext(context).then(whenDone => {

@@ -522,8 +532,2 @@ if (context.helpRequested && !context.output) {

}).then(whenDone => {
try {
this.types.forEach(type => type.reset())
if (this.unknownType) this.unknownType.reset()
} catch (err) {
context.unexpectedError(err)
}
return context.toResult()

@@ -566,7 +570,7 @@ })

// first add unknownType to context.argv (because it's needed to determine shouldCoerceAndCheck)
if (this.unknownType) context.populateArgv([this.unknownType.toResult(true)])
if (this.unknownType) context.populateArgv([this.unknownType.toResult(context, true)])
// next determine shouldCoerceAndCheck
const shouldCoerceAndCheck = this.shouldCoerceAndCheck(context, hasCommands, hasDefaultCommand)
// then populate argv with other types, letting them know if it makes sense to apply coercion
context.populateArgv(this.types.map(type => type.toResult(shouldCoerceAndCheck)))
context.populateArgv(this.types.map(type => type.toResult(context, shouldCoerceAndCheck)))

@@ -593,3 +597,7 @@ // TODO before postParse, determine if any are promptable (and need prompting) and prompt each in series

applyTypes (context) {
context.pushLevel(this.name, this.types.map(type => type.toObject()))
context.pushLevel(this.name, this.types.map(type => {
type.setValue(context, type.defaultVal)
type.applySource(context, SOURCE_DEFAULT)
return type.toObject()
}))
return context

@@ -596,0 +604,0 @@ }

@@ -19,2 +19,5 @@ 'use strict'

this.slurped = []
// values by type, keyed by type.id
this.values = new Map()
this.sources = new Map()
// results of parsing and validation

@@ -39,4 +42,4 @@ this.code = 0

slurpArgs (args) {
if (typeof args === 'string') args = this.utils.stringToArgs(args)
if (!args) args = process.argv.slice(2)
if (typeof args === 'string') args = this.utils.stringToArgs(args)
if (!Array.isArray(args)) args = [].concat(args)

@@ -210,2 +213,31 @@ // TODO read from stdin with no args? based on config?

// weird method names make for easier code searching
assignValue (id, value) {
this.values.set(id, value)
}
lookupValue (id) {
return this.values.get(id)
}
employSource (id, source, position, raw) {
let obj = this.lookupSource(id)
if (!obj) {
obj = { source: undefined, position: [], raw: [] }
this.sources.set(id, obj)
}
if (typeof source === 'string') obj.source = source
if (typeof position === 'number') obj.position.push(position)
if (typeof raw === 'string') obj.raw.push(raw)
}
lookupSource (id) {
return this.sources.get(id)
}
lookupSourceValue (id) {
const obj = this.lookupSource(id)
return obj && obj.source
}
populateArgv (typeResults) {

@@ -212,0 +244,0 @@ let detailIndex

@@ -149,3 +149,3 @@ // copyright license from https://github.com/chalk/ansi-regex/blob/master/license

props.defaultValue = value.slice(firstEqual + 1)
if (props.variadic) props.defaultValue = [props.defaultValue] // TODO TypeArray with defaultValue has problems!
if (props.variadic) props.defaultValue = [props.defaultValue]
value = value.slice(0, firstEqual)

@@ -152,0 +152,0 @@ }

{
"name": "sywac",
"version": "0.2.0",
"version": "0.3.0",
"description": "So you want a CLI...",

@@ -13,3 +13,3 @@ "main": "index.js",

"pretest": "standard",
"test": "tap --cov test/lib/*.js"
"test": "tap --cov test/*.js test/lib/*.js"
},

@@ -16,0 +16,0 @@ "engines": {

'use strict'
const SOURCE_DEFAULT = require('./type').SOURCE_DEFAULT
const TypeWrapper = require('./wrapper')

@@ -11,3 +12,3 @@

constructor (opts) {
super(Object.assign({ defaultValue: [], delim: ',', cumulative: true }, opts || {}))
super(Object.assign({ delim: ',', cumulative: true }, opts || {}))
}

@@ -44,2 +45,7 @@

get defaultVal () {
const dv = super.defaultVal
return dv ? [].concat(dv) : [] // DO NOT LET getValue AND defaultVal REFERENCE THE SAME ARRAY OBJECT!
}
get datatype () {

@@ -56,39 +62,45 @@ let subtype = this.elementType.datatype

isApplicable (currentValue, previousValue, slurpedArg) {
isApplicable (context, currentValue, previousValue, slurpedArg) {
// remove last element if previous value was not explicit
if (this._value && this._value.length && typeof previousValue !== 'string') {
this._value = this._value.slice(0, -1)
}
this.elementType.isApplicable(currentValue, previousValue, slurpedArg)
let v = context.lookupValue(this.id)
if (v && v.length && typeof previousValue !== 'string') v.pop()
this.elementType.isApplicable(context, currentValue, previousValue, slurpedArg)
return true // TODO this is greedy (`--key=one two` includes `one` and `two`), make this configurable
}
observeAlias (alias) {
if (!this._cumulative) this._value = []
this.elementType.observeAlias(alias)
observeAlias (context, alias) {
if (!this._cumulative) context.assignValue(this.id, [])
this.elementType.observeAlias(context, alias)
}
setValue (value) {
// console.log('array.js > setValue:', value, 'for', this.helpFlags)
setValue (context, value) {
// if current source is 'default', then we're now setting a non-default value
// so append to a fresh array instead of the default one
// note that this assumes setValue is called before applySource in api.applyTypes
if (context.lookupSourceValue(this.id) === SOURCE_DEFAULT) context.assignValue(this.id, [])
if (Array.isArray(value)) {
this._value = (this._value || []).concat(value)
let v = context.lookupValue(this.id)
context.assignValue(this.id, (v || []).concat(value))
return
}
if (value && this.delim && typeof value === 'string') {
value.split(this.delim).forEach(v => this.addValue(v))
value.split(this.delim).forEach(v => this.addValue(context, v))
return
}
this.addValue(value)
this.addValue(context, value)
}
addValue (value) {
this.elementType.setValue(value)
if (!this._value) this._value = []
// if (!this._value || !Array.isArray(this._value)) this._value = []
let elementValue = this.elementType.value
if (Array.isArray(elementValue) && this._value.length && this._value[this._value.length - 1] === elementValue) {
addValue (context, value) {
this.elementType.setValue(context, value)
let v = context.lookupValue(this.id)
if (!v) {
v = []
context.assignValue(this.id, v)
}
let elementValue = this.elementType.getValue(context)
if (Array.isArray(elementValue) && v.length && v[v.length - 1] === elementValue) {
return // we already have elementValue, it's just been modified
}
// console.log('array.js > this._value:', this._value)
this._value.push(elementValue)
v.push(elementValue)
}

@@ -106,16 +118,11 @@

buildInvalidMessage (msgAndArgs) {
super.buildInvalidMessage(msgAndArgs)
buildInvalidMessage (context, msgAndArgs) {
super.buildInvalidMessage(context, msgAndArgs)
const sub = {}
this.elementType.buildInvalidMessage(sub)
this.elementType.buildInvalidMessage(context, sub)
if (sub.msg) msgAndArgs.msg = sub.msg
if (sub.args.length > msgAndArgs.args.length) msgAndArgs.args = msgAndArgs.args.concat(sub.args.slice(msgAndArgs.args.length))
}
reset () {
super.reset()
this._value = this._value.slice() // DO NOT LET _value AND _defaultVal REFERENCE THE SAME ARRAY OBJECT!
}
}
module.exports = TypeArray

@@ -18,8 +18,8 @@ 'use strict'

isApplicable (currentValue, previousValue, slurpedArg) {
isApplicable (context, currentValue, previousValue, slurpedArg) {
return typeof currentValue === 'boolean' || currentValue === 'true' || currentValue === 'false'
}
setValue (value) {
this._value = typeof value === 'boolean' ? value : value === 'true'
setValue (context, value) {
context.assignValue(this.id, typeof value === 'boolean' ? value : value === 'true')
}

@@ -26,0 +26,0 @@ }

@@ -11,2 +11,7 @@ 'use strict'

constructor (opts) {
// default value is for benefit of context.details.types
super(Object.assign({ defaultValue: false }, opts))
}
configure (opts, override) {

@@ -91,7 +96,7 @@ opts = opts || {}

matchedArg.parsed[0].claimed = true
this.applySource(Type.SOURCE_POSITIONAL, matchedArg.index, matchedArg.raw)
this.applySource(context, Type.SOURCE_POSITIONAL, matchedArg.index, matchedArg.raw)
}
}
this.setValue(true) // set this value to true for context.details
context.populateArgv([this.toResult()]) // apply value to context.details
this.setValue(context, true) // set this value to true for context.details
context.populateArgv([this.toResult(context)]) // apply value to context.details

@@ -98,0 +103,0 @@ // add positionals from preconfigured opts

@@ -50,4 +50,4 @@ 'use strict'

buildInvalidMessage (msgAndArgs) {
super.buildInvalidMessage(msgAndArgs)
buildInvalidMessage (context, msgAndArgs) {
super.buildInvalidMessage(context, msgAndArgs)
if (this.choices.length) {

@@ -54,0 +54,0 @@ msgAndArgs.msg += ' Choices are: %s'

@@ -41,8 +41,8 @@ 'use strict'

validateParsed (context) {
if (this.value) this.requestHelp(context) // must call this before postParse in case of commands
if (this.getValue(context)) this.requestHelp(context) // must call this before postParse in case of commands
return this.resolve()
}
implicitCommandFound (source, position, raw, context) {
super.implicitCommandFound(source, position, raw, context)
implicitCommandFound (context, source, position, raw) {
super.implicitCommandFound(context, source, position, raw)
this.requestHelp(context) // must call this before postParse in case of commands

@@ -49,0 +49,0 @@ }

@@ -33,5 +33,5 @@ 'use strict'

implicitCommandFound (source, position, raw, context) {
this.setValue(true)
this.applySource(source, position, raw)
implicitCommandFound (context, source, position, raw) {
this.setValue(context, true)
this.applySource(context, source, position, raw)
}

@@ -38,0 +38,0 @@ }

@@ -18,9 +18,10 @@ 'use strict'

get value () {
if (typeof this._value === 'undefined' || this._value === null) return this._value
return TypeNumber.isNumber(this._value) ? Number(this._value) : NaN
getValue (context) {
const v = context.lookupValue(this.id)
if (typeof v === 'undefined' || v === null) return v
return TypeNumber.isNumber(v) ? Number(v) : NaN
}
setValue (value) {
this._value = typeof value === 'boolean' ? NaN : value
setValue (context, value) {
context.assignValue(this.id, typeof value === 'boolean' ? NaN : value)
}

@@ -33,4 +34,4 @@

buildInvalidMessage (msgAndArgs) {
super.buildInvalidMessage(msgAndArgs)
buildInvalidMessage (context, msgAndArgs) {
super.buildInvalidMessage(context, msgAndArgs)
msgAndArgs.msg += ' Please specify a number.'

@@ -37,0 +38,0 @@ }

@@ -111,4 +111,4 @@ 'use strict'

get value () {
let value = super.value
getValue (context) {
let value = super.getValue(context)
if (value && this._normalize) value = this.pathLib.normalize(value)

@@ -115,0 +115,0 @@ if (value && this._asObject) value = this.pathLib.parse(value)

@@ -66,9 +66,9 @@ 'use strict'

// called by unknownType
setValue (value) {
this.elementType.setValue(value)
setValue (context, value) {
this.elementType.setValue(context, value)
}
// called by unknownType
applySource (source, position, raw) {
this.elementType.applySource(source, position, raw)
applySource (context, source, position, raw) {
this.elementType.applySource(context, source, position, raw)
}

@@ -80,12 +80,7 @@

reset () {
super.reset()
this.elementType.reset()
toResult (context, shouldCoerce) {
return this.elementType.toResult(context, shouldCoerce)
}
toResult (shouldCoerce) {
return this.elementType.toResult(shouldCoerce)
}
}
module.exports = TypePositional

@@ -10,6 +10,2 @@ 'use strict'

// constructor (opts) {
// super(opts)
// }
get datatype () {

@@ -19,10 +15,10 @@ return 'string'

get value () {
if (typeof this._value === 'undefined' || this._value === null) return this._value
return String(this._value)
getValue (context) {
const v = context.lookupValue(this.id)
if (typeof v === 'undefined' || v === null) return v
return String(v)
}
setValue (value) {
// console.log('string.js > setValue:', value)
this._value = typeof value === 'boolean' ? '' : value
setValue (context, value) {
context.assignValue(this.id, typeof value === 'boolean' ? '' : value)
}

@@ -29,0 +25,0 @@ }

@@ -19,4 +19,2 @@ 'use strict'

this.configure(opts, true)
// prepare for parsing
this.reset()
}

@@ -42,2 +40,8 @@

// returns a string uniquely identifying this type across all levels
// used for mapping values and sources in context
get id () {
return `${this.parent}|${this.datatype}|${this.aliases.join(',')}`
}
withParent (apiName) {

@@ -53,5 +57,4 @@ this._parent = apiName

get datatype () {
// subtypes should override this so as not to rely on this._value
// because it's used for help text hints, when value is not set
return Array.isArray(this._value) ? 'array' : typeof this._value
// subtypes should override this!
return 'value'
}

@@ -230,3 +233,2 @@

let lastKeyMatchesAlias = false
let anyKeyMatchedAlias = false
let previousUsedValue

@@ -238,6 +240,6 @@ // iterate over each slurped arg and determine if its key-value pairs are relevant to this type/option

// does value1 apply to key? how about value2?
if (lastKeyMatchesAlias && arg.parsed.length === 1 && !arg.parsed[0].key && this.isApplicable(arg.parsed[0].value, previousUsedValue, arg)) {
if (lastKeyMatchesAlias && arg.parsed.length === 1 && !arg.parsed[0].key && this.isApplicable(context, arg.parsed[0].value, previousUsedValue, arg)) {
previousUsedValue = arg.parsed[0].value
this.setValue(previousUsedValue)
this.applySource(Type.SOURCE_FLAG, arg.index, arg.raw)
this.setValue(context, previousUsedValue)
this.applySource(context, Type.SOURCE_FLAG, arg.index, arg.raw)
arg.parsed[0].claimed = true

@@ -252,7 +254,6 @@ return

if (matchedAlias) {
anyKeyMatchedAlias = true
this.observeAlias(matchedAlias)
this.observeAlias(context, matchedAlias)
previousUsedValue = kv.value
this.setValue(previousUsedValue)
this.applySource(Type.SOURCE_FLAG, arg.index, arg.raw)
this.setValue(context, previousUsedValue)
this.applySource(context, Type.SOURCE_FLAG, arg.index, arg.raw)
kv.claimed = true

@@ -263,7 +264,2 @@ }

if (!anyKeyMatchedAlias) {
this.setValue(this.defaultVal)
this._source = Type.SOURCE_DEFAULT
}
return validate ? this.validateParsed(context) : this.resolve()

@@ -277,5 +273,5 @@ }

promises.push(new Promise(resolve => {
if (this.isRequired && this.source === Type.SOURCE_DEFAULT) {
if (this.isRequired && context.lookupSourceValue(this.id) === Type.SOURCE_DEFAULT) {
const msgAndArgs = { msg: '', args: [] }
this.buildRequiredMessage(msgAndArgs)
this.buildRequiredMessage(context, msgAndArgs)
if (msgAndArgs.msg) context.cliMessage.apply(context, [msgAndArgs.msg].concat(msgAndArgs.args || []))

@@ -287,7 +283,7 @@ }

promises.push(new Promise(resolve => {
if (this.isStrict && (this.source !== Type.SOURCE_DEFAULT || this.shouldValidateDefaultValue)) {
return Promise.resolve(this.validateValue(this.value, context)).then(isValid => {
if (this.isStrict && (context.lookupSourceValue(this.id) !== Type.SOURCE_DEFAULT || this.shouldValidateDefaultValue)) {
return Promise.resolve(this.validateValue(this.getValue(context), context)).then(isValid => {
if (!isValid) {
const msgAndArgs = { msg: '', args: [] }
this.buildInvalidMessage(msgAndArgs)
this.buildInvalidMessage(context, msgAndArgs)
if (msgAndArgs.msg) context.cliMessage.apply(context, [msgAndArgs.msg].concat(msgAndArgs.args || []))

@@ -304,3 +300,3 @@ }

buildRequiredMessage (msgAndArgs) {
buildRequiredMessage (context, msgAndArgs) {
msgAndArgs.msg = 'Missing required argument: %s'

@@ -310,5 +306,5 @@ msgAndArgs.args = [this.aliases.join(' or ')]

buildInvalidMessage (msgAndArgs) {
buildInvalidMessage (context, msgAndArgs) {
msgAndArgs.msg = 'Value "%s" is invalid for argument %s.'
msgAndArgs.args = [this.value, this.aliases.join(' or ')]
msgAndArgs.args = [this.getValue(context), this.aliases.join(' or ')]
}

@@ -322,9 +318,14 @@

applySource (source, position, raw) {
this._source = source
this._addPosition(position)
this._addRaw(raw)
applySource (context, source, position, raw) {
context.employSource(this.id, source, position, raw)
// source precedence, most to least direct (for future reference):
// 1. prompt (interactive mode only)
// 2. arg
// 3. stdin
// 4. env
// 5. configfile
// 6. default
}
isApplicable (currentValue, previousValue, slurpedArg) {
isApplicable (context, currentValue, previousValue, slurpedArg) {
// assumes (1) this type should hold a single value

@@ -336,11 +337,10 @@ // and (2) a non-string previous value was not explicit

observeAlias (alias) {}
observeAlias (context, alias) {}
setValue (value) {
this._value = value
setValue (context, value) {
context.assignValue(this.id, value)
}
// == after parsing ==
get value () {
return this._value
getValue (context) {
return context.lookupValue(this.id)
}

@@ -353,36 +353,2 @@

get source () {
return this._source
}
_addPosition (p) {
this._position = (this._position || []).concat(p)
}
get position () {
return this._position
}
_addRaw (r) {
this._raw = (this._raw || []).concat(r)
}
get raw () {
return this._raw
}
reset () {
this._value = this._defaultVal
this._source = Type.SOURCE_DEFAULT
// source precedence, most to least direct (for future reference):
// 1. prompt (interactive mode only)
// 2. arg
// 3. stdin
// 4. env
// 5. configfile
// 6. default
this._position = []
this._raw = []
}
toObject () {

@@ -400,11 +366,7 @@ return {

isHidden: this.isHidden
// populated via parse
// value: this.value,
// source: this.source,
// position: this.position,
// raw: this.raw
}
}
toResult (shouldCoerce) {
toResult (context, shouldCoerce) {
const obj = context.lookupSource(this.id)
return {

@@ -421,6 +383,6 @@ // populated via config

// populated via parse
value: shouldCoerce ? this.coerceHandler(this.value) : this.value,
source: this.source,
position: this.position,
raw: this.raw
value: shouldCoerce ? this.coerceHandler(this.getValue(context)) : this.getValue(context),
source: obj && obj.source,
position: obj && obj.position,
raw: obj && obj.raw
}

@@ -427,0 +389,0 @@ }

@@ -20,3 +20,3 @@ 'use strict'

get datatype () {
return 'array'
return 'array:string'
}

@@ -82,20 +82,16 @@

// console.log(`unparsed before positionals`, unparsed)
if (unparsed.length && this.positionals && this.positionals.length) {
unparsed = this._populatePositionals(unparsed)
// this.positionals.forEach(p => p.validateParsed(context))
unparsed = this._populatePositionals(unparsed, context)
}
// console.log(`unparsed after positionals`, unparsed)
this._value = unparsed.map(arg => {
this._addPosition(arg.index)
this._addRaw(arg.raw)
const v = unparsed.map(arg => {
this.applySource(context, null, arg.index, arg.raw)
return arg.raw
}).concat(context.details.args.slice(context.args.length).map((arg, index) => {
this._addPosition(context.args.length + index)
this._addRaw(arg)
this.applySource(context, null, context.args.length + index, arg)
return arg
}))
context.assignValue(this.id, v)
if (this._value.length > 0) this._source = Type.SOURCE_POSITIONAL
if (v.length > 0) this.applySource(context, Type.SOURCE_POSITIONAL)

@@ -114,3 +110,3 @@ if (this.positionals && this.positionals.length) {

context.slurped[first.index].parsed[0].claimed = true
this.implicit[matched].implicitCommandFound(Type.SOURCE_POSITIONAL, first.index, first.raw, context)
this.implicit[matched].implicitCommandFound(context, Type.SOURCE_POSITIONAL, first.index, first.raw)
return unparsed.slice(1)

@@ -139,3 +135,3 @@ }

_populatePositionals (unparsed) {
_populatePositionals (unparsed, context) {
// filter out positionals already populated via flags

@@ -160,4 +156,4 @@ // (can populate via flags or positional args, but not both at same time)

// assign value and decrement numArgsLeft
current.setValue(arg.raw)
current.applySource(Type.SOURCE_POSITIONAL, arg.index, arg.raw)
current.setValue(context, arg.raw)
current.applySource(context, Type.SOURCE_POSITIONAL, arg.index, arg.raw)
numArgsLeft--

@@ -164,0 +160,0 @@

@@ -41,8 +41,8 @@ 'use strict'

validateParsed (context) {
if (this.value) this.requestVersion(context) // must call this before postParse in case of commands
if (this.getValue(context)) this.requestVersion(context) // must call this before postParse in case of commands
return this.resolve()
}
implicitCommandFound (source, position, raw, context) {
super.implicitCommandFound(source, position, raw, context)
implicitCommandFound (context, source, position, raw) {
super.implicitCommandFound(context, source, position, raw)
this.requestVersion(context) // must call this before postParse in case of commands

@@ -49,0 +49,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc