Spaces:
Running
Running
import arrayify from '../node_modules/array-back/index.mjs' | |
import t from '../node_modules/typical/index.mjs' | |
import Definition from './option-definition.mjs' | |
const _value = new WeakMap() | |
/** | |
* Encapsulates behaviour (defined by an OptionDefinition) when setting values | |
*/ | |
class Option { | |
constructor (definition) { | |
this.definition = new Definition(definition) | |
this.state = null /* set or default */ | |
this.resetToDefault() | |
} | |
get () { | |
return _value.get(this) | |
} | |
set (val) { | |
this._set(val, 'set') | |
} | |
_set (val, state) { | |
const def = this.definition | |
if (def.isMultiple()) { | |
/* don't add null or undefined to a multiple */ | |
if (val !== null && val !== undefined) { | |
const arr = this.get() | |
if (this.state === 'default') arr.length = 0 | |
arr.push(def.type(val)) | |
this.state = state | |
} | |
} else { | |
/* throw if already set on a singlar defaultOption */ | |
if (!def.isMultiple() && this.state === 'set') { | |
const err = new Error(`Singular option already set [${this.definition.name}=${this.get()}]`) | |
err.name = 'ALREADY_SET' | |
err.value = val | |
err.optionName = def.name | |
throw err | |
} else if (val === null || val === undefined) { | |
_value.set(this, val) | |
// /* required to make 'partial: defaultOption with value equal to defaultValue 2' pass */ | |
// if (!(def.defaultOption && !def.isMultiple())) { | |
// this.state = state | |
// } | |
} else { | |
_value.set(this, def.type(val)) | |
this.state = state | |
} | |
} | |
} | |
resetToDefault () { | |
if (t.isDefined(this.definition.defaultValue)) { | |
if (this.definition.isMultiple()) { | |
_value.set(this, arrayify(this.definition.defaultValue).slice()) | |
} else { | |
_value.set(this, this.definition.defaultValue) | |
} | |
} else { | |
if (this.definition.isMultiple()) { | |
_value.set(this, []) | |
} else { | |
_value.set(this, null) | |
} | |
} | |
this.state = 'default' | |
} | |
static create (definition) { | |
definition = new Definition(definition) | |
if (definition.isBoolean()) { | |
return FlagOption.create(definition) | |
} else { | |
return new this(definition) | |
} | |
} | |
} | |
class FlagOption extends Option { | |
set (val) { | |
super.set(true) | |
} | |
static create (def) { | |
return new this(def) | |
} | |
} | |
export default Option | |