Skip to content

Commit 149df46

Browse files
author
oldskytree
committed
chore: rewrite package to typescript
1 parent d84e204 commit 149df46

29 files changed

+544
-425
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
build

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ node_js:
33
- '6'
44
- '8'
55
script:
6+
- npm build
67
- npm test

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Config is described with a combination of a functions:
88
var parser = root(section({
99
system: section({
1010
parallelLimit: option({
11+
defaultValue: 0,
1112
parseEnv: Number,
1213
parseCli: Number,
1314
validate: function() {...}

lib/core.js

Lines changed: 0 additions & 100 deletions
This file was deleted.

lib/core.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import _ from 'lodash';
2+
3+
import { MissingOptionError, UnknownKeysError } from './errors';
4+
import { buildLazyObject, forceParsing } from './lazy';
5+
import initLocator from './locator';
6+
7+
import type { LazyObject } from './types/lazy';
8+
import type { RootParsedConfig } from './types/common';
9+
import type { MapParser } from './types/map';
10+
import type { OptionParser, OptionParserConfig } from './types/option';
11+
import type { RootParser, RootPrefixes, ConfigParser } from './types/root';
12+
import type { SectionParser, SectionProperties } from './types/section';
13+
import type { DeepPartial } from './types/utils';
14+
import type { Locator } from './types/locator';
15+
16+
type Parser<T, R = any> = OptionParser<T, R> | SectionParser<T, R> | MapParser<T, R>;
17+
18+
/**
19+
* Single option
20+
*/
21+
export function option<T, S = T, R = any>({
22+
defaultValue,
23+
parseCli = _.identity,
24+
parseEnv = _.identity,
25+
validate = _.noop,
26+
map: mapFunc = _.identity
27+
}: OptionParserConfig<T, S, R>): OptionParser<S, R> {
28+
const validateFunc: typeof validate = validate;
29+
30+
return (locator, parsed) => {
31+
const config = parsed.root;
32+
const currNode = locator.parent ? _.get(parsed, locator.parent) : config;
33+
34+
let value: unknown;
35+
if (locator.cliOption !== undefined) {
36+
value = parseCli(locator.cliOption);
37+
} else if (locator.envVar !== undefined) {
38+
value = parseEnv(locator.envVar);
39+
} else if (locator.option !== undefined) {
40+
value = locator.option;
41+
} else if (defaultValue !== undefined) {
42+
value = _.isFunction(defaultValue)
43+
? defaultValue(config, currNode)
44+
: defaultValue;
45+
} else {
46+
throw new MissingOptionError(locator.name);
47+
}
48+
49+
validateFunc(value, config, currNode);
50+
51+
return mapFunc(value, config, currNode);
52+
};
53+
}
54+
55+
/**
56+
* Object with fixed properties.
57+
* Any unknown property will be reported as error.
58+
*/
59+
export function section<T, R = any>(properties: SectionProperties<T, R>): SectionParser<T, R> {
60+
const expectedKeys = _.keys(properties) as Array<keyof T>;
61+
62+
return (locator, config) => {
63+
const unknownKeys = _.difference(
64+
_.keys(locator.option),
65+
expectedKeys as Array<string>
66+
);
67+
68+
if (unknownKeys.length > 0) {
69+
throw new UnknownKeysError(
70+
unknownKeys.map((key) => `${locator.name}.${key}`)
71+
);
72+
}
73+
74+
const lazyResult = buildLazyObject(expectedKeys, (key) => {
75+
const parser = properties[key];
76+
77+
return () => parser(locator.nested(key) as Locator<DeepPartial<T[keyof T]>>, config);
78+
});
79+
80+
_.set(config, locator.name, lazyResult);
81+
82+
return lazyResult;
83+
};
84+
}
85+
86+
/**
87+
* Object with user-specified keys and values,
88+
* parsed by valueParser.
89+
*/
90+
export function map<T extends Record<string, any>, V extends T[string] = T[string], R = any>(
91+
valueParser: Parser<V, R>,
92+
defaultValue: DeepPartial<Record<string, V>>
93+
): MapParser<Record<string, V>, R> {
94+
return (locator, config) => {
95+
if (locator.option === undefined) {
96+
if (!defaultValue) {
97+
return {} as LazyObject<T>;
98+
}
99+
locator = locator.resetOption(defaultValue);
100+
}
101+
102+
const optionsToParse = Object.keys(locator.option as Record<string, V>);
103+
const lazyResult = buildLazyObject<Record<string, V>>(optionsToParse, (key) => {
104+
return () => valueParser(locator.nested(key) as Locator<DeepPartial<T[keyof T]>>, config);
105+
});
106+
_.set(config, locator.name, lazyResult);
107+
108+
return lazyResult;
109+
};
110+
}
111+
112+
export function root<T>(rootParser: RootParser<T>, {envPrefix, cliPrefix}: RootPrefixes): ConfigParser<T> {
113+
return ({options, env, argv}) => {
114+
const rootLocator = initLocator({options, env, argv, envPrefix, cliPrefix});
115+
const parsed = rootParser(rootLocator, {} as RootParsedConfig<T>);
116+
117+
return forceParsing(parsed);
118+
};
119+
}

lib/errors.js renamed to lib/errors.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
class MissingOptionError extends Error {
2-
constructor(optionName) {
1+
export class MissingOptionError extends Error {
2+
public optionName: string;
3+
4+
constructor(optionName: string) {
35
const message = `${optionName} is required`;
46
super(message);
57
this.name = 'MissingOptionError';
@@ -10,8 +12,10 @@ class MissingOptionError extends Error {
1012
}
1113
}
1214

13-
class UnknownKeysError extends Error {
14-
constructor(keys) {
15+
export class UnknownKeysError extends Error {
16+
public keys: Array<string>;
17+
18+
constructor(keys: Array<string>) {
1519
const message = `Unknown options: ${keys.join(', ')}`;
1620
super(message);
1721
this.name = 'UnknownKeysError';
@@ -21,5 +25,3 @@ class UnknownKeysError extends Error {
2125
Error.captureStackTrace(this, UnknownKeysError);
2226
}
2327
}
24-
25-
module.exports = {MissingOptionError, UnknownKeysError};

lib/index.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { root, section, map, option } from './core';
2+
export { MissingOptionError, UnknownKeysError } from './errors';

lib/lazy.js

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)