diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +build diff --git a/.gitignore b/.gitignore index 3c3629e..dd87e2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +build diff --git a/.travis.yml b/.travis.yml index 21d7f7c..6535747 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,4 +3,5 @@ node_js: - '6' - '8' script: +- npm build - npm test diff --git a/README.md b/README.md index 0a26ec4..dc4b120 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Config is described with a combination of a functions: var parser = root(section({ system: section({ parallelLimit: option({ + defaultValue: 0, parseEnv: Number, parseCli: Number, validate: function() {...} diff --git a/lib/core.ts b/lib/core.ts index 34f1d0f..73bc74f 100644 --- a/lib/core.ts +++ b/lib/core.ts @@ -1,24 +1,36 @@ -const _ = require('lodash'); -const {buildLazyObject, forceParsing} = require('./lazy'); -const {MissingOptionError, UnknownKeysError} = require('./errors'); -const initLocator = require('./locator'); +import _ from 'lodash'; + +import {MissingOptionError, UnknownKeysError} from './errors'; +import {buildLazyObject, forceParsing} from './lazy'; +import initLocator from './locator'; + +import type {Rooted, Parser} from './types/common'; +import type {LazyObject} from './types/lazy'; +import type {Locator} from './types/locator'; +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 {Map} from './types/utils'; /** * Single option */ -function option({ +export function option({ defaultValue, parseCli = _.identity, parseEnv = _.identity, validate = _.noop, map: mapFunc = _.identity, isDeprecated = false -}) { +}: OptionParserConfig = {}): OptionParser { + const validateFunc: typeof validate = validate; + return (locator, parsed) => { const config = parsed.root; const currNode = locator.parent ? _.get(config, locator.parent) : config; - let value, isSetByUser = true; + let value: unknown, isSetByUser = true; if (locator.cliOption !== undefined) { value = parseCli(locator.cliOption); } else if (locator.envVar !== undefined) { @@ -38,7 +50,7 @@ function option({ console.warn(`Using "${locator.name}" option is deprecated`); } - validate(value, config, currNode, {isSetByUser}); + validateFunc(value, config, currNode, {isSetByUser}); return mapFunc(value, config, currNode, {isSetByUser}); }; @@ -48,13 +60,15 @@ function option({ * Object with fixed properties. * Any unknown property will be reported as error. */ -function section(properties) { - const expectedKeys = _.keys(properties); +export function section(properties: SectionProperties): SectionParser { + const expectedKeys = _.keys(properties) as Array; + return (locator, config) => { const unknownKeys = _.difference( _.keys(locator.option), - expectedKeys + expectedKeys as Array ); + if (unknownKeys.length > 0) { throw new UnknownKeysError( unknownKeys.map((key) => `${locator.name}.${key}`) @@ -63,6 +77,7 @@ function section(properties) { const lazyResult = buildLazyObject(expectedKeys, (key) => { const parser = properties[key]; + return () => parser(locator.nested(key), config); }); @@ -76,32 +91,34 @@ function section(properties) { * Object with user-specified keys and values, * parsed by valueParser. */ -function map(valueParser, defaultValue) { +export function map( + valueParser: Parser, + defaultValue: Map +): MapParser, Result> { return (locator, config) => { if (locator.option === undefined) { if (!defaultValue) { - return {}; + return {} as LazyObject>; } locator = locator.resetOption(defaultValue); } - const optionsToParse = Object.keys(locator.option); - const lazyResult = buildLazyObject(optionsToParse, (key) => { + const optionsToParse = Object.keys(locator.option as Map); + const lazyResult = buildLazyObject>(optionsToParse, (key) => { return () => valueParser(locator.nested(key), config); }); + _.set(config, locator.name, lazyResult); return lazyResult; }; } -function root(rootParser, {envPrefix, cliPrefix}) { +export function root(rootParser: RootParser, {envPrefix, cliPrefix}: RootPrefixes = {}): ConfigParser { return ({options, env, argv}) => { const rootLocator = initLocator({options, env, argv, envPrefix, cliPrefix}); - const parsed = {}; - rootParser(rootLocator, parsed); - return forceParsing(parsed.root); + const parsed = rootParser(rootLocator as Locator, {} as Rooted); + + return forceParsing(parsed); }; } - -module.exports = {option, section, map, root}; diff --git a/lib/errors.ts b/lib/errors.ts index 69d1daf..db41cd1 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -1,5 +1,7 @@ -class MissingOptionError extends Error { - constructor(optionName) { +export class MissingOptionError extends Error { + optionName: string; + + constructor(optionName: string) { const message = `${optionName} is required`; super(message); this.name = 'MissingOptionError'; @@ -10,8 +12,10 @@ class MissingOptionError extends Error { } } -class UnknownKeysError extends Error { - constructor(keys) { +export class UnknownKeysError extends Error { + keys: Array; + + constructor(keys: Array) { const message = `Unknown options: ${keys.join(', ')}`; super(message); this.name = 'UnknownKeysError'; @@ -21,5 +25,3 @@ class UnknownKeysError extends Error { Error.captureStackTrace(this, UnknownKeysError); } } - -module.exports = {MissingOptionError, UnknownKeysError}; diff --git a/lib/index.ts b/lib/index.ts index 76fbcbc..e1ce12a 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,2 @@ -const {root, section, map, option} = require('./core'); -const {MissingOptionError, UnknownKeysError} = require('./errors'); - -module.exports = { - root, section, map, option, - MissingOptionError, UnknownKeysError -}; +export {root, section, map, option} from './core'; +export {MissingOptionError, UnknownKeysError} from './errors'; diff --git a/lib/lazy.ts b/lib/lazy.ts index 1af3c3b..d1ee3fc 100644 --- a/lib/lazy.ts +++ b/lib/lazy.ts @@ -1,38 +1,50 @@ -const _ = require('lodash'); +import _ from 'lodash'; -const isLazy = Symbol('isLazy'); +import type {LazyObject} from './types/lazy'; -function buildLazyObject(keys, getKeyGetter) { +export const isLazy = Symbol('isLazy'); + +type SimpleOrLazyObject = T | LazyObject; + +export function buildLazyObject(keys: Array, getKeyGetter: (key: keyof T) => () => (SimpleOrLazyObject)): LazyObject { const target = { [isLazy]: true - }; + } as LazyObject; + for (const key of keys) { defineLazy(target, key, getKeyGetter(key)); } + return target; } -function forceParsing(lazyObject) { +export function forceParsing(lazyObject: LazyObject): T { return _.cloneDeep(lazyObject); } -function defineLazy(object, key, getter) { +function defineLazy(object: LazyObject, key: keyof T, getter: () => SimpleOrLazyObject): void { let defined = false; - let value; + let value: T[keyof T]; Object.defineProperty(object, key, { - get() { + get(): T[keyof T] { if (!defined) { defined = true; - value = getter(); - if (_.isObject(value) && value[isLazy]) { - value = forceParsing(value); - } + const val = getter(); + + value = isLazyObject(val) ? forceParsing(val) : val; } + return value; }, enumerable: true }); } -module.exports = {forceParsing, buildLazyObject}; +function isLazyObject(value: T): value is LazyObject { + return _.isObject(value) && hasOwnProperty(value, isLazy) && value[isLazy] === true; +} + +function hasOwnProperty(obj: T, prop: K): obj is T & Record { + return Object.prototype.hasOwnProperty.call(obj, prop); +} diff --git a/lib/locator.ts b/lib/locator.ts index 63f8207..dfcc7fb 100644 --- a/lib/locator.ts +++ b/lib/locator.ts @@ -1,6 +1,8 @@ -const _ = require('lodash'); +import _ from 'lodash'; -function parseArgv(argv, cliPrefix) { +import type {LocatorArg, Locator, Node, Prefixes} from './types/locator'; + +function parseArgv(argv: Array, cliPrefix: string): Array { return argv.reduce(function(argv, arg) { if (!arg.startsWith(cliPrefix) || !_.includes(arg, '=')) { return argv.concat(arg); @@ -11,20 +13,22 @@ function parseArgv(argv, cliPrefix) { const value = parts.slice(1).join('='); return argv.concat(option, value); - }, []); + }, [] as Array); } -module.exports = function({options, env, argv, envPrefix = '', cliPrefix = '--'}) { +export = function initLocator({options, env, argv, envPrefix = '', cliPrefix = '--'}: LocatorArg): Locator { const parsedArgv = parseArgv(argv, cliPrefix); - function getNested(option, {namePrefix, envPrefix, cliPrefix}) { - return (subKey) => { - const envName = envPrefix + _.snakeCase(subKey); - const cliFlag = cliPrefix + _.kebabCase(subKey); + function getNested(option: Options | undefined, {namePrefix, envPrefix, cliPrefix}: Prefixes) { + return (subKey: Key): Locator => { + const stringSubKey = subKey.toString(); + + const envName = envPrefix + _.snakeCase(stringSubKey); + const cliFlag = cliPrefix + _.kebabCase(stringSubKey); const argIndex = parsedArgv.lastIndexOf(cliFlag); - const subOption = _.get(option, subKey); - const newName = namePrefix ? `${namePrefix}.${subKey}` : subKey; + const subOption: Options[Key] = _.get(option, subKey); + const newName = namePrefix ? `${namePrefix}.${stringSubKey}` : stringSubKey; return mkLocator( { @@ -43,11 +47,11 @@ module.exports = function({options, env, argv, envPrefix = '', cliPrefix = '--'} }; } - function mkLocator(base, prefixes) { + function mkLocator(base: Node, prefixes: Prefixes): Locator { return _.extend(base, { nested: getNested(base.option, prefixes), - resetOption: function(newOptions) { - return _.extend({}, base, { + resetOption: function(newOptions: Options): Locator { + return _.extend({}, base as Locator, { option: newOptions, nested: getNested(newOptions, prefixes) }); diff --git a/lib/types/common.ts b/lib/types/common.ts new file mode 100644 index 0000000..1c2f130 --- /dev/null +++ b/lib/types/common.ts @@ -0,0 +1,12 @@ +import type {LazyObject} from './lazy'; +import type {MapParser} from './map'; +import type {OptionParser} from './option'; +import type {SectionParser} from './section'; + +export type ParsedConfig = {[Key in keyof Config]: LazyObject}; + +export type Parser = OptionParser | SectionParser | MapParser; + +export interface Rooted { + root: T; +} diff --git a/lib/types/lazy.ts b/lib/types/lazy.ts new file mode 100644 index 0000000..c449d5e --- /dev/null +++ b/lib/types/lazy.ts @@ -0,0 +1,5 @@ +import type {isLazy} from '../lazy'; + +export type LazyObject = T & { + [isLazy]: true; +}; diff --git a/lib/types/locator.ts b/lib/types/locator.ts new file mode 100644 index 0000000..338e5f1 --- /dev/null +++ b/lib/types/locator.ts @@ -0,0 +1,20 @@ +import type {RootPrefixes, ConfigParserArg} from './root'; + +export type LocatorArg = RootPrefixes & ConfigParserArg; + +export type Prefixes = Required & { + namePrefix: string; +}; + +export interface Node { + name: string; + parent: string | null; + option: Options; + envVar?: string; + cliOption?: string; +} + +export interface Locator extends Node { + nested(key: Key): Locator; + resetOption(newOption: Options): Locator; +} diff --git a/lib/types/map.ts b/lib/types/map.ts new file mode 100644 index 0000000..af1d0ab --- /dev/null +++ b/lib/types/map.ts @@ -0,0 +1,7 @@ +import type {Rooted} from './common'; +import type {LazyObject} from './lazy'; +import type {Locator} from './locator'; + +export interface MapParser { + (locator: Locator, config: Rooted): LazyObject; +} diff --git a/lib/types/option.ts b/lib/types/option.ts new file mode 100644 index 0000000..7c5a4e6 --- /dev/null +++ b/lib/types/option.ts @@ -0,0 +1,19 @@ +import type {Rooted} from './common'; +import type {Locator} from './locator'; + +interface MetaInfo { + isSetByUser: boolean; +} + +export interface OptionParserConfig { + defaultValue?: Value | ((config: Result, currNode: any) => Value); + parseCli?: (input?: string) => Value | undefined; + parseEnv?: (input?: string) => Value | undefined; + validate?: (value: unknown, config: Result, currNode: any, meta: MetaInfo) => asserts value is Value; + map?(value: Value, config: Result, currNode: any, meta: MetaInfo): MappedValue; + isDeprecated?: boolean; +} + +export interface OptionParser { + (locator: Locator, config: Rooted): Value; +} diff --git a/lib/types/root.ts b/lib/types/root.ts new file mode 100644 index 0000000..5a0d676 --- /dev/null +++ b/lib/types/root.ts @@ -0,0 +1,20 @@ +import type {MapParser} from './map'; +import type {SectionParser} from './section'; +import type {DeepPartial} from './utils'; + +export interface ConfigParserArg { + options: Options; + env: NodeJS.ProcessEnv; + argv: NodeJS.Process['argv']; +} + +export interface ConfigParser { + (arg: ConfigParserArg>): Config; +} + +export interface RootPrefixes { + envPrefix?: string; + cliPrefix?: string; +} + +export type RootParser = SectionParser | MapParser; diff --git a/lib/types/section.ts b/lib/types/section.ts new file mode 100644 index 0000000..5d19867 --- /dev/null +++ b/lib/types/section.ts @@ -0,0 +1,8 @@ +import type {Parser, Rooted} from './common'; +import type {LazyObject} from './lazy'; +import type {Locator} from './locator'; + +export type SectionProperties = {[Key in keyof Config]: Parser}; +export interface SectionParser { + (locator: Locator, config: Rooted): LazyObject; +} diff --git a/lib/types/utils.ts b/lib/types/utils.ts new file mode 100644 index 0000000..6da59cb --- /dev/null +++ b/lib/types/utils.ts @@ -0,0 +1,5 @@ +export type DeepPartial = { + [K in keyof T]?: T[K] extends object ? DeepPartial : T[K]; +} + +export type Map = Record; diff --git a/package-lock.json b/package-lock.json index 32e3f28..9ef080e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,24 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@tsconfig/recommended": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.1.tgz", + "integrity": "sha512-2xN+iGTbPBEzGSnVp/Hd64vKJCJWxsi9gfs88x4PPMyEjHJoA3o5BY9r5OLPHIZU2pAQxkSAsJFqn6itClP8mQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.176", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.176.tgz", + "integrity": "sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ==", + "dev": true + }, + "@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true + }, "acorn": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", @@ -16,7 +34,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -33,10 +51,10 @@ "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "json-schema-traverse": "^0.3.0", + "json-stable-stringify": "^1.0.1" } }, "ajv-keywords": { @@ -69,7 +87,7 @@ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "array-union": { @@ -78,7 +96,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -105,9 +123,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" }, "dependencies": { "chalk": { @@ -116,11 +134,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "strip-ansi": { @@ -129,7 +147,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } } } @@ -146,7 +164,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -162,7 +180,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -177,12 +195,12 @@ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { - "assertion-error": "1.0.2", - "check-error": "1.0.2", - "deep-eql": "3.0.1", - "get-func-name": "2.0.0", - "pathval": "1.1.0", - "type-detect": "4.0.3" + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" } }, "chalk": { @@ -191,9 +209,9 @@ "integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" }, "dependencies": { "ansi-styles": { @@ -202,7 +220,7 @@ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "color-convert": "1.9.0" + "color-convert": "^1.9.0" } }, "supports-color": { @@ -211,7 +229,7 @@ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -234,7 +252,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-width": { @@ -255,7 +273,7 @@ "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -282,9 +300,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "core-util-is": { @@ -299,9 +317,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "debug": { @@ -319,7 +337,7 @@ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "4.0.3" + "type-detect": "^4.0.0" } }, "deep-is": { @@ -334,13 +352,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "diff": { @@ -355,8 +373,8 @@ "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "escape-string-regexp": { @@ -371,43 +389,43 @@ "integrity": "sha1-doedJ0BoJhsZH+Dy9Wx0wvQgjos=", "dev": true, "requires": { - "ajv": "5.2.3", - "babel-code-frame": "6.26.0", - "chalk": "2.2.0", - "concat-stream": "1.6.0", - "cross-spawn": "5.1.0", - "debug": "3.1.0", - "doctrine": "2.0.0", - "eslint-scope": "3.7.1", - "espree": "3.5.1", - "esquery": "1.0.0", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.5", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "require-uncached": "1.0.3", - "semver": "5.4.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.2", - "text-table": "0.2.0" + "ajv": "^5.2.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.0.1", + "doctrine": "^2.0.0", + "eslint-scope": "^3.7.1", + "espree": "^3.5.1", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^9.17.0", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "^4.0.1", + "text-table": "~0.2.0" } }, "eslint-config-gemini-testing": { @@ -422,8 +440,8 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "espree": { @@ -432,8 +450,8 @@ "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", "dev": true, "requires": { - "acorn": "5.1.2", - "acorn-jsx": "3.0.1" + "acorn": "^5.1.1", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -448,7 +466,7 @@ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.0.0" } }, "esrecurse": { @@ -457,8 +475,8 @@ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "^4.1.0", + "object-assign": "^4.0.1" } }, "estraverse": { @@ -479,9 +497,9 @@ "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", "dev": true, "requires": { - "iconv-lite": "0.4.19", - "jschardet": "1.5.1", - "tmp": "0.0.33" + "iconv-lite": "^0.4.17", + "jschardet": "^1.4.2", + "tmp": "^0.0.33" } }, "fast-deep-equal": { @@ -493,7 +511,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "figures": { @@ -502,7 +520,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -511,8 +529,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "flat-cache": { @@ -521,10 +539,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" } }, "formatio": { @@ -533,7 +551,7 @@ "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", "dev": true, "requires": { - "samsam": "1.3.0" + "samsam": "1.x" } }, "fs.realpath": { @@ -545,7 +563,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "dev": true }, "get-func-name": { @@ -560,12 +578,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "globals": { @@ -580,12 +598,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "graceful-fs": { @@ -606,7 +624,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -636,7 +654,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "inflight": { @@ -645,8 +663,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -661,20 +679,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.2.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.0.5", - "figures": "2.0.0", - "lodash": "4.17.4", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" } }, "is-fullwidth-code-point": { @@ -695,7 +713,7 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -704,7 +722,7 @@ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-promise": { @@ -719,7 +737,7 @@ "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", "dev": true, "requires": { - "tryit": "1.0.3" + "tryit": "^1.0.1" } }, "isarray": { @@ -731,7 +749,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "js-tokens": { @@ -746,8 +764,8 @@ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jschardet": { @@ -768,7 +786,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "jsonify": { @@ -789,8 +807,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { @@ -816,8 +834,8 @@ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "mimic-fn": { @@ -832,7 +850,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -874,7 +892,7 @@ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -900,7 +918,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "nise": { @@ -909,11 +927,11 @@ "integrity": "sha512-f5DMJB0MqBaSuP2NAwPx7HyVKPdaozds0KsNe9XIP3npKWt/QUg73l5TTLRTSwfG/Y3AB0ktacuxX4QNcg6vVw==", "dev": true, "requires": { - "formatio": "1.2.0", - "just-extend": "1.1.22", - "lolex": "1.6.0", - "path-to-regexp": "1.7.0", - "text-encoding": "0.6.4" + "formatio": "^1.2.0", + "just-extend": "^1.1.22", + "lolex": "^1.6.0", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" }, "dependencies": { "lolex": { @@ -936,7 +954,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -945,7 +963,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "^1.0.0" } }, "optionator": { @@ -954,12 +972,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "os-tmpdir": { @@ -1021,7 +1039,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pluralize": { @@ -1060,13 +1078,13 @@ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "require-uncached": { @@ -1075,8 +1093,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, "resolve-from": { @@ -1091,8 +1109,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "rimraf": { @@ -1101,7 +1119,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "run-async": { @@ -1110,7 +1128,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "^2.1.0" } }, "rx-lite": { @@ -1125,7 +1143,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "4.0.8" + "rx-lite": "*" } }, "safe-buffer": { @@ -1152,7 +1170,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -1173,16 +1191,16 @@ "integrity": "sha512-4qIY0pCWCvGCJpV/1JkFu9kbsNEZ9O34cG1oru/c7OCDtrEs50Gq/VjkA2ID5ZwLyoNx1i1ws118oh/p6fVeDg==", "dev": true, "requires": { - "diff": "3.3.1", + "diff": "^3.1.0", "formatio": "1.2.0", - "lodash.get": "4.4.2", - "lolex": "2.1.3", - "native-promise-only": "0.8.1", - "nise": "1.1.1", - "path-to-regexp": "1.7.0", - "samsam": "1.3.0", + "lodash.get": "^4.4.2", + "lolex": "^2.1.3", + "native-promise-only": "^0.8.1", + "nise": "^1.1.1", + "path-to-regexp": "^1.7.0", + "samsam": "^1.1.3", "text-encoding": "0.6.4", - "type-detect": "4.0.3" + "type-detect": "^4.0.0" } }, "slice-ansi": { @@ -1191,7 +1209,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0" + "is-fullwidth-code-point": "^2.0.0" } }, "sprintf-js": { @@ -1200,23 +1218,23 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -1225,7 +1243,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" }, "dependencies": { "ansi-regex": { @@ -1254,12 +1272,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.2.3", - "ajv-keywords": "2.1.0", - "chalk": "2.2.0", - "lodash": "4.17.4", + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", "slice-ansi": "1.0.0", - "string-width": "2.1.1" + "string-width": "^2.1.1" } }, "text-encoding": { @@ -1271,7 +1289,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "through": { @@ -1286,7 +1304,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "tryit": { @@ -1301,7 +1319,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-detect": { @@ -1316,6 +1334,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1328,7 +1352,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "wordwrap": { @@ -1349,7 +1373,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "yallist": { diff --git a/package.json b/package.json index a2e0e73..31ec7d0 100644 --- a/package.json +++ b/package.json @@ -2,24 +2,31 @@ "name": "gemini-configparser", "version": "1.3.0", "description": "Config parser module for gemini", - "main": "lib/index.js", - "types": "./typings/index.d.ts", + "main": "./build/index.js", + "types": "./build/index.d.ts", "author": "Sergey Tatarintsev (https://github.com/SevInf)", "license": "MIT", "engines": { "node": ">=12" }, "devDependencies": { + "@tsconfig/recommended": "^1.0.1", + "@types/lodash": "^4.14.176", + "@types/node": "^12.20.55", "chai": "^4.1.2", "eslint": "^4.9.0", "eslint-config-gemini-testing": "^2.0.0", "mocha": "^4.0.1", - "sinon": "^4.0.1" + "sinon": "^4.0.1", + "typescript": "^4.8.3" }, "dependencies": { "lodash": "^4.17.4" }, "scripts": { + "build": "tsc --build", + "prepublishOnly": "npm run build", + "pretest": "npm run build", "test": "npm run lint && npm run test-unit", "lint": "eslint .", "test-unit": "mocha test" diff --git a/test/lazy.js b/test/lazy.js index 51f6378..69576e9 100644 --- a/test/lazy.js +++ b/test/lazy.js @@ -1,4 +1,4 @@ -const {buildLazyObject, forceParsing} = require('../lib/lazy'); +const {buildLazyObject, forceParsing} = require('../build/lazy'); describe('build lazy object', () => { it('should build an object with given keys', () => { diff --git a/test/locator.js b/test/locator.js index 8cd49d5..a979f9f 100644 --- a/test/locator.js +++ b/test/locator.js @@ -1,4 +1,4 @@ -const locator = require('../lib/locator'); +const locator = require('../build/locator'); function locatorWithOptions(options) { return locator({options, env: {}, argv: []}); diff --git a/test/map.js b/test/map.js index bc1ff75..7d3dd8c 100644 --- a/test/map.js +++ b/test/map.js @@ -1,5 +1,5 @@ -const {map} = require('../lib/core'); -const {forceParsing} = require('../lib/lazy'); +const {map} = require('../build/core'); +const {forceParsing} = require('../build/lazy'); const _ = require('lodash'); describe('map', () => { diff --git a/test/option.js b/test/option.js index e304225..c793e78 100644 --- a/test/option.js +++ b/test/option.js @@ -1,5 +1,5 @@ -const {option} = require('../lib/core'); -const {MissingOptionError} = require('../lib/errors'); +const {option} = require('../build/core'); +const {MissingOptionError} = require('../build/errors'); describe('option', () => { const LAZY_CONFIG = { diff --git a/test/section.js b/test/section.js index e20691a..4854307 100644 --- a/test/section.js +++ b/test/section.js @@ -1,5 +1,5 @@ -const {section} = require('../lib/core'); -const {forceParsing} = require('../lib/lazy'); +const {section} = require('../build/core'); +const {forceParsing} = require('../build/lazy'); function stubLocator(locatorKeys) { return Object.assign({ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..98a7554 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@tsconfig/recommended/tsconfig.json", + "include": ["lib"], + "exclude": ["build", "test"], + "compilerOptions": { + "target": "ES2019", + "outDir": "build", + "allowJs": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "declaration": true, + "sourceMap": true + } +} diff --git a/typings/index.d.ts b/typings/index.d.ts deleted file mode 100644 index 9bfe50e..0000000 --- a/typings/index.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -declare module "gemini-configparser" { - type PartialConfig = never; - type Locator = never; - type UnsanitizedRootConfig = any; - type UnsanitizedConfigNode = any; - - type Parser = (locator: Locator, config: PartialConfig) => T; - - type RootPrefixes = { - envPrefix: string; - cliPrefix: string; - }; - - type MetaInfo = { - isSetByUser: boolean; - }; - - type OptionParserConfig = { - defaultValue: T | ((config: UnsanitizedRootConfig, currNode: UnsanitizedConfigNode) => T); - parseCli?(input: string): T; - parseEnv?(input: string): T; - validate?(value: T, config: UnsanitizedRootConfig, currNode: UnsanitizedConfigNode, meta: MetaInfo): void; - }; - - type MappedOptionParserConfig = OptionParserConfig & { - map(value: S, config: UnsanitizedRootConfig, currNode: UnsanitizedConfigNode, meta: MetaInfo): T; - }; - - type SectionProperties = { [name in keyof T]: Parser }; - - export function option(description: OptionParserConfig): Parser; - export function option(description: MappedOptionParserConfig): Parser; - export function section(properties: SectionProperties): Parser; - - type RootParserArg = { - options: UnsanitizedRootConfig; - env: NodeJS.ProcessEnv; - argv: Array; - }; - type RootParser = (arg: RootParserArg) => T; - export function root(rootParser: Parser, prefixes: RootPrefixes): RootParser; - - export class MissingOptionError extends Error {} - export class UnknownKeysError extends Error {} -}