-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: rewrite package to typescript
- Loading branch information
oldskytree
committed
Feb 12, 2022
1 parent
d84e204
commit 751efda
Showing
30 changed files
with
647 additions
and
425 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
node_modules | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ node_js: | |
- '6' | ||
- '8' | ||
script: | ||
- npm build | ||
- npm test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { root, map, section, option } from './lib'; | ||
import { buildLazyObject } from './lib/lazy'; | ||
|
||
// const map1 = map(section({ | ||
// r: option({ | ||
// defaultValue: '1', | ||
// map: (v) => +v | ||
// }), | ||
// t: option({ | ||
// defaultValue: 0, | ||
// map: (v) => v.toString() | ||
// }) | ||
// }), | ||
// {'': { | ||
// r: 's', | ||
// t: 0 | ||
// }} | ||
// ); | ||
|
||
// const config = root(, {envPrefix: '', cliPrefix: ''})({ | ||
// options: {}, | ||
// env: process.env, | ||
// argv: process.argv | ||
// }); | ||
|
||
// console.log(config); | ||
|
||
const rootOption = option({ | ||
defaultValue: 'root', | ||
map: (v: string): string[] => [].concat(v) | ||
}); | ||
const tralalaOption = option({ | ||
defaultValue: 1234 | ||
}) | ||
const mainSection = section({ | ||
r: rootOption, | ||
t: tralalaOption | ||
}); | ||
const fileMap = map(mainSection, { | ||
'tralala': { | ||
r: [''], | ||
t: 0 | ||
} | ||
}); | ||
const configParser = root(fileMap, { | ||
envPrefix: '', | ||
cliPrefix: '' | ||
}); | ||
const config2 = configParser({ | ||
options: {}, | ||
env: process.env, | ||
argv: process.argv | ||
}); | ||
|
||
type A = { | ||
system: { | ||
parallelLimit: number; | ||
}; | ||
browsers: { | ||
[x: string]: { | ||
calibrate: boolean; | ||
windowSize: number; | ||
}; | ||
}; | ||
}; | ||
|
||
const parser = root(section({ | ||
system: section({ | ||
parallelLimit: option({ | ||
defaultValue: 123, | ||
parseEnv: Number, | ||
parseCli: Number, | ||
map: (value, config, node) => { | ||
return value * 2; | ||
} | ||
}) | ||
}), | ||
browsers: map(section({ | ||
calibrate: option({ | ||
defaultValue: true | ||
}), | ||
windowSize: option({ | ||
defaultValue: 1024 | ||
}) | ||
}), {'': {}}) | ||
}), { | ||
envPrefix: '', | ||
cliPrefix: '' | ||
}); | ||
|
||
const parsedConfig = parser({ | ||
options: { | ||
browsers: { | ||
'': {calibrate: false, } | ||
}, | ||
system: {parallelLimit: 1} | ||
}, | ||
env: process.env, | ||
argv: process.argv | ||
}); | ||
|
||
const a = root(section({ | ||
id: option({defaultValue: 1}) | ||
}), { envPrefix: '', cliPrefix: '' })({ options: { id: 1 }, env: process.env, argv: process.argv }); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import _ from 'lodash'; | ||
|
||
import { MissingOptionError, UnknownKeysError } from './errors'; | ||
import { buildLazyObject, forceParsing } from './lazy'; | ||
import initLocator from './locator'; | ||
|
||
import type { LazyObject } from './types/lazy'; | ||
import type { RootParsedConfig } from './types/common'; | ||
import type { MapParser } from './types/map'; | ||
import type { OptionParser, OptionParserConfig } from './types/option'; | ||
import type { RootParser, RootPrefixes, ConfigParser } from './types/root'; | ||
import type { SectionParser, SectionProperties } from './types/section'; | ||
import type { DeepPartial } from './types/utils'; | ||
import type { Locator } from './types/locator'; | ||
|
||
type Parser<T, R = any> = OptionParser<T, R> | SectionParser<T, R> | MapParser<T, R>; | ||
|
||
/** | ||
* Single option | ||
*/ | ||
export function option<T, S = T, R = any>({ | ||
defaultValue, | ||
parseCli = _.identity, | ||
parseEnv = _.identity, | ||
validate = _.noop, | ||
map: mapFunc = _.identity | ||
}: OptionParserConfig<T, S, R>): OptionParser<S, R> { | ||
const validateFunc: typeof validate = validate; | ||
|
||
return (locator, parsed) => { | ||
const config = parsed.root; | ||
const currNode = locator.parent ? _.get(parsed, locator.parent) : config; | ||
|
||
let value: unknown; | ||
if (locator.cliOption !== undefined) { | ||
value = parseCli(locator.cliOption); | ||
} else if (locator.envVar !== undefined) { | ||
value = parseEnv(locator.envVar); | ||
} else if (locator.option !== undefined) { | ||
value = locator.option; | ||
} else if (defaultValue !== undefined) { | ||
value = _.isFunction(defaultValue) | ||
? defaultValue(config, currNode) | ||
: defaultValue; | ||
} else { | ||
throw new MissingOptionError(locator.name); | ||
} | ||
|
||
validateFunc(value, config, currNode); | ||
|
||
return mapFunc(value, config, currNode); | ||
}; | ||
} | ||
|
||
/** | ||
* Object with fixed properties. | ||
* Any unknown property will be reported as error. | ||
*/ | ||
export function section<T, R = any>(properties: SectionProperties<T, R>): SectionParser<T, R> { | ||
const expectedKeys = _.keys(properties) as Array<keyof T>; | ||
|
||
return (locator, config) => { | ||
const unknownKeys = _.difference( | ||
_.keys(locator.option), | ||
expectedKeys as Array<string> | ||
); | ||
|
||
if (unknownKeys.length > 0) { | ||
throw new UnknownKeysError( | ||
unknownKeys.map((key) => `${locator.name}.${key}`) | ||
); | ||
} | ||
|
||
const lazyResult = buildLazyObject(expectedKeys, (key) => { | ||
const parser = properties[key]; | ||
|
||
return () => parser(locator.nested(key) as Locator<DeepPartial<T[keyof T]>>, config); | ||
}); | ||
|
||
_.set(config, locator.name, lazyResult); | ||
|
||
return lazyResult; | ||
}; | ||
} | ||
|
||
/** | ||
* Object with user-specified keys and values, | ||
* parsed by valueParser. | ||
*/ | ||
export function map<T extends Record<string, any>, V extends T[string] = T[string], R = any>( | ||
valueParser: Parser<V, R>, | ||
defaultValue: DeepPartial<Record<string, V>> | ||
): MapParser<Record<string, V>, R> { | ||
return (locator, config) => { | ||
if (locator.option === undefined) { | ||
if (!defaultValue) { | ||
return {} as LazyObject<T>; | ||
} | ||
locator = locator.resetOption(defaultValue); | ||
} | ||
|
||
const optionsToParse = Object.keys(locator.option as Record<string, V>); | ||
const lazyResult = buildLazyObject<Record<string, V>>(optionsToParse, (key) => { | ||
return () => valueParser(locator.nested(key) as Locator<DeepPartial<T[keyof T]>>, config); | ||
}); | ||
_.set(config, locator.name, lazyResult); | ||
|
||
return lazyResult; | ||
}; | ||
} | ||
|
||
export function root<T>(rootParser: RootParser<T>, {envPrefix, cliPrefix}: RootPrefixes): ConfigParser<T> { | ||
return ({options, env, argv}) => { | ||
const rootLocator = initLocator({options, env, argv, envPrefix, cliPrefix}); | ||
const parsed = rootParser(rootLocator, {} as RootParsedConfig<T>); | ||
|
||
return forceParsing(parsed); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { root, section, map, option } from './core'; | ||
export { MissingOptionError, UnknownKeysError } from './errors'; |
Oops, something went wrong.