Commit 66c04430 authored by Alexandra Rogova's avatar Alexandra Rogova

started auto bench scripts

parent cc5cce49
const puppeteer = require('puppeteer');
const getPort = require('get-port');
const Server = require('ws').Server;
const args = require("yargs")
.usage("Usage : add_rss.js -file file_path")
......@@ -12,10 +13,10 @@ var browser,
index_start,
index_total,
db_start,
db_total;
db_total,
port;
function init_server (){
var port = 9030;
var ws = new Server({port: port});
ws.on('connection', function(w){
w.on('message', function(msg){
......@@ -26,8 +27,9 @@ function init_server (){
db_start = Date.now();
} else if (msg.includes("Done")){
db_total = Date.now() - db_start;
console.log(msg + " in " + (db_total+index_total)/1000 +
"s (index : " + index_total/1000 + "s, db : " + db_total/1000 + "s)");
process.send((db_total+index_total)/1000);
// console.log(msg + " in " + (db_total+index_total)/1000 +
// "s (index : " + index_total/1000 + "s, db : " + db_total/1000 + "s)");
ws.close();
browser.close();
} else {
......@@ -43,10 +45,11 @@ function init_server (){
}
(async () => {
port = await getPort();
init_server();
browser = await puppeteer.launch();
var page = await browser.newPage();
await page.goto('https://softinst115787.host.vifib.net/public/unit_tests/add_rss.html');
await page.goto('https://softinst115787.host.vifib.net/public/unit_tests/add_rss.html?port='+port);
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.click('input#load')
......
......@@ -17,7 +17,8 @@ function init_server (){
ws.on('connection', function(w){
w.on('message', function(msg){
if (msg.includes("Done")){
var now = Date.now()
var now = Date.now();
process.send((now-start)/1000);
console.log(msg + " in " + (now-start)/1000 +"s");
ws.close();
browser.close();
......
/// <reference types="node"/>
import {Omit} from 'type-fest';
import {ListenOptions} from 'net';
declare namespace getPort {
interface Options extends Omit<ListenOptions, 'port'> {
/**
A preferred port or an iterable of preferred ports to use.
*/
readonly port?: number | Iterable<number>;
/**
The host on which port resolution should be performed. Can be either an IPv4 or IPv6 address.
*/
readonly host?: string;
}
}
declare const getPort: {
/**
Get an available TCP port number.
@returns Port number.
@example
```
import getPort = require('get-port');
(async () => {
console.log(await getPort());
//=> 51402
// Pass in a preferred port
console.log(await getPort({port: 3000}));
// Will use 3000 if available, otherwise fall back to a random port
// Pass in an array of preferred ports
console.log(await getPort({port: [3000, 3001, 3002]}));
// Will use any element in the preferred ports array if available, otherwise fall back to a random port
})();
```
*/
(options?: getPort.Options): Promise<number>;
/**
Make a range of ports `from`...`to`.
@param from - First port of the range. Must be in the range `1024`...`65535`.
@param to - Last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`.
@returns The ports in the range.
@example
```
import getPort = require('get-port');
(async () => {
console.log(await getPort({port: getPort.makeRange(3000, 3100)}));
// Will use any port from 3000 to 3100, otherwise fall back to a random port
})();
```
*/
makeRange(from: number, to: number): Iterable<number>;
};
export = getPort;
'use strict';
const net = require('net');
const getAvailablePort = options => new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
server.on('error', reject);
server.listen(options, () => {
const {port} = server.address();
server.close(() => {
resolve(port);
});
});
});
const portCheckSequence = function * (ports) {
if (ports) {
yield * ports;
}
yield 0; // Fall back to 0 if anything else failed
};
module.exports = async options => {
let ports = null;
if (options) {
ports = typeof options.port === 'number' ? [options.port] : options.port;
}
for (const port of portCheckSequence(ports)) {
try {
return await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
} catch (error) {
if (error.code !== 'EADDRINUSE') {
throw error;
}
}
}
throw new Error('No available ports found');
};
module.exports.makeRange = (from, to) => {
if (!Number.isInteger(from) || !Number.isInteger(to)) {
throw new TypeError('`from` and `to` must be integer numbers');
}
if (from < 1024 || from > 65535) {
throw new RangeError('`from` must be between 1024 and 65535');
}
if (to < 1024 || to > 65536) {
throw new RangeError('`to` must be between 1024 and 65536');
}
if (to < from) {
throw new RangeError('`to` must be greater than or equal to `from`');
}
const generator = function * (from, to) {
for (let port = from; port <= to; port++) {
yield port;
}
};
return generator(from, to);
};
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
"_from": "get-port",
"_id": "get-port@5.0.0",
"_inBundle": false,
"_integrity": "sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ==",
"_location": "/get-port",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "get-port",
"name": "get-port",
"escapedName": "get-port",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/get-port/-/get-port-5.0.0.tgz",
"_shasum": "aa22b6b86fd926dd7884de3e23332c9f70c031a6",
"_spec": "get-port",
"_where": "C:\\Users\\thequ\\Documents\\Mynij\\Mynij-unit-tests",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/get-port/issues"
},
"bundleDependencies": false,
"dependencies": {
"type-fest": "^0.3.0"
},
"deprecated": false,
"description": "Get an available port",
"devDependencies": {
"@types/node": "^11.13.0",
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
},
"engines": {
"node": ">=8"
},
"files": [
"index.js",
"index.d.ts"
],
"homepage": "https://github.com/sindresorhus/get-port#readme",
"keywords": [
"port",
"find",
"finder",
"portfinder",
"free",
"available",
"connection",
"connect",
"open",
"net",
"tcp",
"scan",
"random",
"preferred",
"chosen"
],
"license": "MIT",
"name": "get-port",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/get-port.git"
},
"scripts": {
"test": "xo && ava && tsd"
},
"version": "5.0.0"
}
# get-port [![Build Status](https://travis-ci.org/sindresorhus/get-port.svg?branch=master)](https://travis-ci.org/sindresorhus/get-port)
> Get an available [TCP port](https://en.wikipedia.org/wiki/Port_(computer_networking))
## Install
```
$ npm install get-port
```
## Usage
```js
const getPort = require('get-port');
(async () => {
console.log(await getPort());
//=> 51402
})();
```
Pass in a preferred port:
```js
(async () => {
console.log(await getPort({port: 3000}));
// Will use 3000 if available, otherwise fall back to a random port
})();
```
Pass in an array of preferred ports:
```js
(async () => {
console.log(await getPort({port: [3000, 3001, 3002]}));
// Will use any element in the preferred ports array if available, otherwise fall back to a random port
})();
```
Use the `makeRange()` helper in case you need a port in a certain range:
```js
(async () => {
console.log(await getPort({port: getPort.makeRange(3000, 3100)}));
// Will use any port from 3000 to 3100, otherwise fall back to a random port
})();
```
## API
### getPort([options])
Returns a `Promise` for a port number.
#### options
Type: `Object`
##### port
Type: `number | Iterable<number>`
A preferred port or an iterable of preferred ports to use.
##### host
Type: `string`
The host on which port resolution should be performed. Can be either an IPv4 or IPv6 address.
### getPort.makeRange(from, to)
Make a range of ports `from`...`to`.
Returns an `Iterable` for ports in the given range.
#### from
Type: `number`
First port of the range. Must be in the range `1024`...`65535`.
#### to
Type: `number`
Last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`.
## Beware
There is a very tiny chance of a race condition if another service starts using the same port number as you in between the time you get the port number and you actually start using it.
## Related
- [get-port-cli](https://github.com/sindresorhus/get-port-cli) - CLI for this module
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
......@@ -30,6 +30,12 @@ For major (breaking) changes - version 3 and 2 see end of page.
| Version | Date | Comment |
| -------------- | -------------- | -------- |
| 4.14.17 | 2019-10-22 | `graphics()` improved display detection (windows) |
| 4.14.16 | 2019-10-19 | `graphics()` improved display detection (windows) |
| 4.14.15 | 2019-10-18 | `graphics()` fallback display detection (windows) |
| 4.14.14 | 2019-10-18 | `powerShell()` fixed error handling (windows) |
| 4.14.13 | 2019-10-15 | `networkConnections()` fixed parsing (linux) |
| 4.14.12 | 2019-10-14 | `getCpu()` fixed multi socket detection (linux) |
| 4.14.11 | 2019-10-01 | type definitions fix dockerInfo |
| 4.14.10 | 2019-10-01 | type definitions fix memLayout |
| 4.14.9 | 2019-10-01 | `processLoad()` fix windows |
......
......@@ -29,7 +29,7 @@
[![Caretaker][caretaker-image]][caretaker-url]
[![MIT license][license-img]][license-url]
**2019-03-12** - 5th birthday of systeminformation. This is amazing. Started as a small projekt just for myself, it now has > 8,000 lines of code, > 200 versions published, up to 100,000 downloads per month, > 1 Mio downloads overall. Thank you to all who contributed to this project!
This is amazing. Started as a small project just for myself, it now has > 9,000 lines of code, > 250 versions published, up to 400,000 downloads per month, > 1 Mio downloads overall. Thank you to all who contributed to this project!
## New Version 4.0
......
......@@ -321,38 +321,21 @@ function getCpu() {
result.cache.l3 = util.getValue(lines, 'l3 cache');
if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1); }
const threadsPerCore = util.getValue(lines, 'thread(s) per core') || '1';
const processors = util.getValue(lines, 'socket(s)') || '1';
let threadsPerCoreInt = parseInt(threadsPerCore, 10);
let processorsInt = parseInt(processors, 10);
result.physicalCores = result.cores / threadsPerCoreInt;
result.processors = processorsInt;
// socket type
lines = [];
let lines2 = [];
exec('export LC_ALL=C; dmidecode –t 4 2>/dev/null | grep "Upgrade: Socket"; unset LC_ALL', function (error2, stdout2) {
lines = stdout2.toString().split('\n');
if (lines && lines.length) {
result.socket = util.getValue(lines, 'Upgrade').replace('Socket', '').trim();
lines2 = stdout2.toString().split('\n');
if (lines2 && lines2.length) {
result.socket = util.getValue(lines2, 'Upgrade').replace('Socket', '').trim();
}
// # processurs & # threads/core - method 1
let threadsPerCoreInt = 0;
lines = [];
exec('cat /proc/cpuinfo | grep -E "physical id|core id"', function (error2, stdout3) {
lines = stdout3.toString().split('\n');
if (lines && lines.length) {
result.processors = util.countUniqueLines(lines, 'physical id') || 1;
result.physicalCores = util.countUniqueLines(lines, 'core id') / result.processors;
if (result.physicalCores) {
threadsPerCoreInt = result.cores / result.physicalCores;
}
}
// # threads/core - method 2
if (threadsPerCoreInt === 0) {
const threadsPerCore = util.getValue(lines, 'thread(s) per core');
if (threadsPerCore) {
threadsPerCoreInt = parseInt(threadsPerCore, 10);
if (!isNaN(threadsPerCoreInt)) {
result.physicalCores = result.cores / threadsPerCoreInt;
}
}
}
resolve(result);
});
resolve(result);
});
});
}
......
......@@ -561,6 +561,7 @@ function graphics(callback) {
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorBasicDisplayParams | fl'));
workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens'));
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
workload.push(util.powerShell('gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.InstanceName}'));
Promise.all(
workload
......@@ -587,19 +588,34 @@ function graphics(callback) {
let tsections = data[4].split(/\n\s*\n/);
tsections.shift();
result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections);
// monitor ID (powershell) - model / vendor
const res = data[5].split(/\r\n/);
let isections = [];
res.forEach(element => {
const parts = element.split('|');
if (parts.length === 5) {
isections.push({
vendor: parts[0],
code: parts[1],
model: parts[2],
serial: parts[3],
instanceId: parts[4]
});
}
});
result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
if (result.controllers.length === 1 && result.displays.length === 1) {
if (result.displays.length === 1) {
if (_resolutionx) {
result.displays[0].currentResX = _resolutionx;
if (!result.displays[0].resolutionx) {
result.displays[0].resolutionx = _resolutionx;
result.displays[0].resolutionx = _resolutionx;
if (!result.displays[0].currentResX) {
result.displays[0].currentResX = _resolutionx;
}
}
if (_resolutiony) {
result.displays[0].currentResY = _resolutiony;
if (result.displays[0].resolutiony === 0) {
result.displays[0].resolutiony = _resolutiony;
result.displays[0].resolutiony = _resolutiony;
if (result.displays[0].currentResY === 0) {
result.displays[0].currentResY = _resolutiony;
}
}
if (_pixeldepth) {
......@@ -643,10 +659,10 @@ function graphics(callback) {
vram: parseInt(util.getValue(lines, 'AdapterRAM', '='), 10) / 1024 / 1024,
vramDynamic: (util.getValue(lines, 'VideoMemoryType', '=') === '2')
});
_resolutionx = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', '='));
_resolutiony = util.toInt(util.getValue(lines, 'CurrentVerticalResolution', '='));
_refreshrate = util.toInt(util.getValue(lines, 'CurrentRefreshRate', '='));
_pixeldepth = util.toInt(util.getValue(lines, 'CurrentBitsPerPixel', '='));
_resolutionx = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', '=')) || _resolutionx;
_resolutiony = util.toInt(util.getValue(lines, 'CurrentVerticalResolution', '=')) || _resolutiony;
_refreshrate = util.toInt(util.getValue(lines, 'CurrentRefreshRate', '=')) || _refreshrate;
_pixeldepth = util.toInt(util.getValue(lines, 'CurrentBitsPerPixel', '=')) || _pixeldepth;
}
}
}
......@@ -677,18 +693,21 @@ function graphics(callback) {
// return displays;
// }
function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections) {
function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
let displays = [];
let vendor = '';
let model = '';
let deviceID = '';
let resolutionx = 0;
let resolutiony = 0;
if (dsections && dsections.length) {
let linesDisplay = dsections[0].split(os.EOL);
vendor = util.getValue(linesDisplay, 'MonitorManufacturer', '=');
model = util.getValue(linesDisplay, 'Name', '=');
deviceID = util.getValue(linesDisplay, 'PNPDeviceID', '=').replace(/&amp;/g, '&').toLowerCase();
resolutionx = util.toInt(util.getValue(linesDisplay, 'ScreenWidth', '='));
resolutiony = util.toInt(util.getValue(linesDisplay, 'ScreenHeight', '='));
}
for (let i = 0; i < ssections.length; i++) {
if (ssections[i].trim() !== '') {
ssections[i] = 'BitsPerPixel ' + ssections[i];
......@@ -704,9 +723,17 @@ function graphics(callback) {
const sizey = util.getValue(linesMonitor, 'MaxVerticalImageSize');
const instanceName = util.getValue(linesMonitor, 'InstanceName').toLowerCase();
const videoOutputTechnology = util.getValue(linesConnection, 'VideoOutputTechnology');
let displayVendor = '';
let displayModel = '';
isections.forEach(element => {
if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
displayVendor = element.vendor;
displayModel = element.model;
}
});
displays.push({
vendor: instanceName.startsWith(deviceID) ? vendor : '',
model: instanceName.startsWith(deviceID) ? model : '',
vendor: instanceName.startsWith(deviceID) && displayVendor === '' ? vendor : displayVendor,
model: instanceName.startsWith(deviceID) && displayModel === '' ? model : displayModel,
main: primary.toLowerCase() === 'true',
builtin: videoOutputTechnology === '2147483648',
connection: videoOutputTechnology && videoTypes[videoOutputTechnology] ? videoTypes[videoOutputTechnology] : '',
......@@ -722,6 +749,22 @@ function graphics(callback) {
});
}
}
if (ssections.length === 0) {
displays.push({
vendor,
model,
main: true,
resolutionx,
resolutiony,
sizex: -1,
sizey: -1,
pixeldepth: -1,
currentResX: resolutionx,
currentResY: resolutiony,
positionX: 0,
positionY: 0
});
}
return displays;
}
......
......@@ -785,7 +785,7 @@ function networkConnections(callback) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
line = line.replace(/ +/g, ' ').split(' ');
if (line.length >= 6) {
if (line.length >= 7) {
let localip = line[3];
let localport = '';
let localaddress = line[3].split(':');
......
......@@ -178,7 +178,7 @@ function parseDateTime(dt) {
// Dateformat: mm/dd/yyyy
result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
} else {
// Dateformat: dd/mm/yyyy
// Dateformat: dd/mm/yyyy
result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
}
}
......@@ -321,6 +321,11 @@ function powerShell(cmd) {
stdio: 'pipe'
});
if (child && !child.pid) {
child.on('error', function () {
resolve(result);
});
}
if (child && child.pid) {
child.stdout.on('data', function (data) {
result = result + data.toString('utf8');
......@@ -454,6 +459,7 @@ function countUniqueLines(lines, startingWith) {
});
return uniqueLines.length;
}
function noop() { }
exports.toInt = toInt;
......
{
"_from": "systeminformation",
"_id": "systeminformation@4.14.11",
"_from": "systeminformation@4.14.17",
"_id": "systeminformation@4.14.17",
"_inBundle": false,
"_integrity": "sha512-KlMaQQftyGUPjKzGRrATN5mpKrpdtrVk/KPuqPeu733bUgpokIhevg5zjKOb4Gur91XKdbdQCCja/oFsg5R4Dw==",
"_integrity": "sha512-CQbT5vnkqNb3JNl41xr8sYA8AX7GoaWP55/jnmFNQY0XQmUuoFshSNUkCkxiDdEC1qu2Vg9s0jR6LLmVSmNJUw==",
"_location": "/systeminformation",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"type": "version",
"registry": true,
"raw": "systeminformation",
"raw": "systeminformation@4.14.17",
"name": "systeminformation",
"escapedName": "systeminformation",
"rawSpec": "",
"rawSpec": "4.14.17",
"saveSpec": null,
"fetchSpec": "latest"
"fetchSpec": "4.14.17"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.14.11.tgz",
"_shasum": "5c7f23d92586f2639a9d037a359890f7ab01c4ea",
"_spec": "systeminformation",
"_where": "C:\\Users\\thequ\\Documents\\Mynij",
"_resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.14.17.tgz",
"_shasum": "c7ba98a63835785c3e8df711c0e0730cc3b1b2ce",
"_spec": "systeminformation@4.14.17",
"_where": "C:\\Users\\thequ\\Documents\\Mynij\\Mynij-unit-tests",
"author": {
"name": "Sebastian Hildebrandt",
"email": "hildebrandt@plus-innovations.com",
......@@ -146,5 +146,5 @@
"watch": "tsc -w"
},
"types": "./lib/index.d.ts",
"version": "4.14.11"
"version": "4.14.17"
}
export {PackageJson} from './source/package-json';
// TODO: Add more examples
// TODO: This can just be `export type Primitive = not object` when the `not` keyword is out.
/**
Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
*/
export type Primitive =
| null
| undefined
| string
| number
| boolean
| symbol;
/**
Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
*/
export type Class<T = unknown> = new(...arguments_: any[]) => T;
/**
Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`.
*/
export type TypedArray =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| Float32Array
| Float64Array;
/**
Matches a JSON object.
*/
export type JsonObject = {[key: string]: JsonValue};
/**
Matches a JSON array.
*/
export interface JsonArray extends Array<JsonValue> {}
/**
Matches any valid JSON value.
*/
export type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
declare global {
interface SymbolConstructor {
readonly observable: symbol;
}
}
/**
Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable).
*/
export interface ObservableLike {
subscribe(observer: (value: unknown) => void): void;
[Symbol.observable](): ObservableLike;
}
/**
Create a type from an object type without certain keys.
@example
```
import {Omit} from 'type-fest';
type Foo = {
a: number;
b: string;
};
type FooWithoutA = Omit<Foo, 'a'>;
//=> {b: string};
```
I'm surprised this one is not built-in. It seems [other people agree](https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-420919470). Please 👍 [this issue on TypeScript](https://github.com/Microsoft/TypeScript/issues/30455) about making it built-in.
*/
export type Omit<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>;
/**
Merge two types into a new type. Keys of the second type overrides keys of the first type.
@example
```
import {Merge} from 'type-fest';
type Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
};
const ab: Merge<Foo, Bar> = {a: 1, b: 2};
```
*/
export type Merge<FirstType, SecondType> = Omit<FirstType, Extract<keyof FirstType, keyof SecondType>> & SecondType;
// Helper type. Not useful on its own.
type Without<FirstType, SecondType> = {[KeyType in Exclude<keyof FirstType, keyof SecondType>]?: never};
/**
Create a type that has mutually exclusive properties.
This type was inspired by [this comment](https://github.com/Microsoft/TypeScript/issues/14094#issuecomment-373782604).
This type works with a helper type, called `Without`. `Without<FirstType, SecondType>` produces a type that has only keys from `FirstType` which are not present on `SecondType` and sets the value type for these keys to `never`. This helper type is then used in `MergeExclusive` to remove keys from either `FirstType` or `SecondType`.
@example
```
import {MergeExclusive} from 'type-fest';
interface ExclusiveVariation1 {
exclusive1: boolean;
}
interface ExclusiveVariation2 {
exclusive2: string;
}
type ExclusiveOptions = MergeExclusive<ExclusiveVariation1, ExclusiveVariation2>;
let exclusiveOptions: ExclusiveOptions;
exclusiveOptions = {exclusive1: true};
//=> Works
exclusiveOptions = {exclusive2: 'hi'};
//=> Works
exclusiveOptions = {exclusive1: true, exclusive2: 'hi'};
//=> Error
```
*/
export type MergeExclusive<FirstType, SecondType> =
(FirstType | SecondType) extends object ?
(Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType) :
FirstType | SecondType;
/**
Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union.
Currently, when a union type of a primitive type is combined with literal types, TypeScript loses all information about the combined literals. Thus, when such type is used in an IDE with autocompletion, no suggestions are made for the declared literals.
This type is a workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729). It will be removed as soon as it's not needed anymore.
@example
```
import {LiteralUnion} from 'type-fest';
// Before
type Pet = 'dog' | 'cat' | string;
const pet: Pet = '';
// Start typing in your TypeScript-enabled IDE.
// You **will not** get auto-completion for `dog` and `cat` literals.
// After
type Pet2 = LiteralUnion<'dog' | 'cat', string>;
const pet: Pet2 = '';
// You **will** get auto-completion for `dog` and `cat` literals.
```
*/
export type LiteralUnion<
LiteralType extends BaseType,
BaseType extends Primitive
> = LiteralType | (BaseType & {_?: never});
/*
Create a type that requires at least one of the given properties. The remaining properties are kept as is.
@example
```
import {RequireAtLeastOne} from 'type-fest';
type Responder = {
text?: () => string;
json?: () => string;
secure?: boolean;
};
const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
json: () => '{"message": "ok"}',
secure: true
};
```
*/
export type RequireAtLeastOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
{
// For each Key in KeysType make a mapped type
[Key in KeysType]: (
// …by picking that Key's type and making it required
Required<Pick<ObjectType, Key>>
)
}[KeysType]
// …then, make intersection types by adding the remaining properties to each mapped type.
& Omit<ObjectType, KeysType>;
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
"_from": "type-fest@^0.3.0",
"_id": "type-fest@0.3.1",
"_inBundle": false,
"_integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
"_location": "/type-fest",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "type-fest@^0.3.0",
"name": "type-fest",
"escapedName": "type-fest",
"rawSpec": "^0.3.0",
"saveSpec": null,
"fetchSpec": "^0.3.0"
},
"_requiredBy": [
"/get-port"
],
"_resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
"_shasum": "63d00d204e059474fe5e1b7c011112bbd1dc29e1",
"_spec": "type-fest@^0.3.0",
"_where": "C:\\Users\\thequ\\Documents\\Mynij\\Mynij-unit-tests\\node_modules\\get-port",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/type-fest/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A collection of essential TypeScript types",
"devDependencies": {
"@sindresorhus/tsconfig": "^0.3.0",
"@typescript-eslint/eslint-plugin": "^1.5.0",
"eslint-config-xo-typescript": "^0.9.0",
"tsd": "^0.7.2",
"xo": "^0.24.0"
},
"engines": {
"node": ">=6"
},
"files": [
"index.d.ts",
"source"
],
"homepage": "https://github.com/sindresorhus/type-fest#readme",
"keywords": [
"typescript",
"ts",
"types",
"utility",
"util",
"utilities",
"omit",
"merge",
"json"
],
"license": "(MIT OR CC0-1.0)",
"name": "type-fest",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/type-fest.git"
},
"scripts": {
"test": "xo && tsd"
},
"version": "0.3.1",
"xo": {
"extends": "xo-typescript",
"extensions": [
"ts"
],
"rules": {
"import/no-unresolved": "off"
}
}
}
<div align="center">
<br>
<br>
<img src="media/logo.svg" alt="type-fest" height="300">
<br>
<br>
<b>A collection of essential TypeScript types</b>
<br>
<hr>
</div>
<br>
<br>
[![Build Status](https://travis-ci.com/sindresorhus/type-fest.svg?branch=master)](https://travis-ci.com/sindresorhus/type-fest)
[![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4)
<!-- Commented out until they actually show anything
[![npm dependents](https://badgen.net/npm/dependents/type-fest)](https://www.npmjs.com/package/type-fest?activeTab=dependents) [![npm downloads](https://badgen.net/npm/dt/type-fest)](https://www.npmjs.com/package/type-fest)
-->
Many of the types here should have been built-in. You can help by suggesting some of them to the [TypeScript project](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md).
Either add this package as a dependency or copy-paste the needed types. No credit required. 👌
PR welcome for additional commonly needed types and docs improvements. Read the [contributing guidelines](.github/contributing.md) first.
## Install
```
$ npm install type-fest
```
## Usage
```ts
import {Omit} from 'type-fest';
type Foo = {
unicorn: string;
rainbow: boolean;
};
type FooWithoutRainbow = Omit<Foo, 'rainbow'>;
//=> {unicorn: string}
```
## API
See the [types file](index.d.ts) for complete docs.
### Basic
- `Primitive` - Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
- `Class` - Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
- `TypedArray` - Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`.
- `JsonObject` - Matches a JSON object.
- `JsonArray` - Matches a JSON array.
- `JsonValue` - Matches any valid JSON value.
- `ObservableLike` - Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable).
### Utilities
- `Omit` - Create a type from an object type without certain keys.
- `Merge` - Merge two types into a new type. Keys of the second type overrides keys of the first type.
- `MergeExclusive` - Create a type that has mutually exclusive properties.
- `RequireAtLeastOne` - Create a type that requires at least one of the given properties.
- `LiteralUnion` - Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. Workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729).
### Miscellaneous
- `PackageJson` - Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-json-file).
## Declined types
*If we decline a type addition, we will make sure to document the better solution here.*
## Tips
### Built-in types
There are many advanced types most users don't know about.
- [`Partial<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1401-L1406) - Make all properties in `T` optional.
- [`Required<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1408-L1413) - Make all properties in `T` required.
- [`Readonly<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1415-L1420) - Make all properties in `T` readonly.
- [`Pick<T, K>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1422-L1427) - From `T`, pick a set of properties whose keys are in the union `K`.
- [`Record<K, T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1429-L1434) - Construct a type with a set of properties `K` of type `T`.
- [`Exclude<T, U>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1436-L1439) - Exclude from `T` those types that are assignable to `U`.
- [`Extract<T, U>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1441-L1444) - Extract from `T` those types that are assignable to `U`.
- [`NonNullable<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1446-L1449) - Exclude `null` and `undefined` from `T`.
- [`Parameters<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1451-L1454) - Obtain the parameters of a function type in a tuple.
- [`ConstructorParameters<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1456-L1459) - Obtain the parameters of a constructor function type in a tuple.
- [`ReturnType<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1461-L1464) – Obtain the return type of a function type.
- [`InstanceType<T>`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1466-L1469) – Obtain the instance type of a constructor function type.
You can find some examples in the [TypeScript docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#predefined-conditional-types).
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Jarek Radosz](https://github.com/CvX)
- [Dimitri Benin](https://github.com/BendingBender)
## License
(MIT OR CC0-1.0)
import {LiteralUnion} from '..';
declare namespace PackageJson {
/**
A person who has been involved in creating or maintaining the package.
*/
export type Person =
| string
| {
name: string;
url?: string;
email?: string;
};
export type BugsLocation =
| string
| {
/**
The URL to the package's issue tracker.
*/
url?: string;
/**
The email address to which issues should be reported.
*/
email?: string;
};
export interface DirectoryLocations {
/**
Location for executable scripts. Sugar to generate entries in the `bin` property by walking the folder.
*/
bin?: string;
/**
Location for Markdown files.
*/
doc?: string;
/**
Location for example scripts.
*/
example?: string;
/**
Location for the bulk of the library.
*/
lib?: string;
/**
Location for man pages. Sugar to generate a `man` array by walking the folder.
*/
man?: string;
/**
Location for test files.
*/
test?: string;
[directoryType: string]: unknown;
}
export type Scripts = {
/**
Run **before** the package is published (Also run on local `npm install` without any arguments).
*/
prepublish?: string;
/**
Run both **before** the package is packed and published, and on local `npm install` without any arguments. This is run **after** `prepublish`, but **before** `prepublishOnly`.
*/
prepare?: string;
/**
Run **before** the package is prepared and packed, **only** on `npm publish`.
*/
prepublishOnly?: string;
/**
Run **before** a tarball is packed (on `npm pack`, `npm publish`, and when installing git dependencies).
*/
prepack?: string;
/**
Run **after** the tarball has been generated and moved to its final destination.
*/
postpack?: string;
/**
Run **after** the package is published.
*/
publish?: string;
/**
Run **after** the package is published.
*/
postpublish?: string;
/**
Run **before** the package is installed.
*/
preinstall?: string;
/**
Run **after** the package is installed.
*/
install?: string;
/**
Run **after** the package is installed and after `install`.
*/
postinstall?: string;
/**
Run **before** the package is uninstalled and before `uninstall`.
*/
preuninstall?: string;
/**
Run **before** the package is uninstalled.
*/
uninstall?: string;
/**
Run **after** the package is uninstalled.
*/
postuninstall?: string;
/**
Run **before** bump the package version and before `version`.
*/
preversion?: string;
/**
Run **before** bump the package version.
*/
version?: string;
/**
Run **after** bump the package version.
*/
postversion?: string;
/**
Run with the `npm test` command, before `test`.
*/
pretest?: string;
/**
Run with the `npm test` command.
*/
test?: string;
/**
Run with the `npm test` command, after `test`.
*/
posttest?: string;
/**
Run with the `npm stop` command, before `stop`.
*/
prestop?: string;
/**
Run with the `npm stop` command.
*/
stop?: string;
/**
Run with the `npm stop` command, after `stop`.
*/
poststop?: string;
/**
Run with the `npm start` command, before `start`.
*/
prestart?: string;
/**
Run with the `npm start` command.
*/
start?: string;
/**
Run with the `npm start` command, after `start`.
*/
poststart?: string;
/**
Run with the `npm restart` command, before `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
prerestart?: string;
/**
Run with the `npm restart` command. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
restart?: string;
/**
Run with the `npm restart` command, after `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided.
*/
postrestart?: string;
} & {
[scriptName: string]: string;
}
/**
Dependencies of the package. The version range is a string which has one or more space-separated descriptors. Dependencies can also be identified with a tarball or Git URL.
*/
export interface Dependency {
[packageName: string]: string;
}
export interface NonStandardEntryPoints {
/**
An ECMAScript module ID that is the primary entry point to the program.
*/
module?: string;
/**
A module ID with untranspiled code that is the primary entry point to the program.
*/
esnext?:
| string
| {
main?: string;
browser?: string;
[moduleName: string]: string | undefined;
};
/**
A hint to JavaScript bundlers or component tools when packaging modules for client side use.
*/
browser?:
| string
| {
[moduleName: string]: string | false;
};
}
export interface TypeScriptConfiguration {
/**
Location of the bundled TypeScript declaration file.
*/
types?: string;
/**
Location of the bundled TypeScript declaration file. Alias of `types`.
*/
typings?: string;
}
export interface YarnConfiguration {
/**
Selective version resolutions. Allows the definition of custom package versions inside dependencies without manual edits in the `yarn.lock` file.
*/
resolutions?: Dependency;
}
export interface JSPMConfiguration {
/**
JSPM configuration.
*/
jspm?: PackageJson;
}
}
/**
Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-json-file). Also includes types for fields used by other popular projects, like TypeScript and Yarn.
*/
export type PackageJson = {
/**
The name of the package.
*/
name?: string;
/**
Package version, parseable by [`node-semver`](https://github.com/npm/node-semver).
*/
version?: string;
/**
Package description, listed in `npm search`.
*/
description?: string;
/**
Keywords associated with package, listed in `npm search`.
*/
keywords?: string[];
/**
The URL to the package's homepage.
*/
homepage?: LiteralUnion<'.', string>;
/**
The URL to the package's issue tracker and/or the email address to which issues should be reported.
*/
bugs?: PackageJson.BugsLocation;
/**
The license for the package.
*/
license?: string;
/**
The licenses for the package.
*/
licenses?: {
type?: string;
url?: string;
}[];
author?: PackageJson.Person;
/**
A list of people who contributed to the package.
*/
contributors?: PackageJson.Person[];
/**
A list of people who maintain the package.
*/
maintainers?: PackageJson.Person[];
/**
The files included in the package.
*/
files?: string[];
/**
The module ID that is the primary entry point to the program.
*/
main?: string;
/**
The executable files that should be installed into the `PATH`.
*/
bin?:
| string
| {
[binary: string]: string;
};
/**
Filenames to put in place for the `man` program to find.
*/
man?: string | string[];
/**
Indicates the structure of the package.
*/
directories?: PackageJson.DirectoryLocations;
/**
Location for the code repository.
*/
repository?:
| string
| {
type: string;
url: string;
};
/**
Script commands that are run at various times in the lifecycle of the package. The key is the lifecycle event, and the value is the command to run at that point.
*/
scripts?: PackageJson.Scripts;
/**
Is used to set configuration parameters used in package scripts that persist across upgrades.
*/
config?: {
[configKey: string]: unknown;
};
/**
The dependencies of the package.
*/
dependencies?: PackageJson.Dependency;
/**
Additional tooling dependencies that are not required for the package to work. Usually test, build, or documentation tooling.
*/
devDependencies?: PackageJson.Dependency;
/**
Dependencies that are skipped if they fail to install.
*/
optionalDependencies?: PackageJson.Dependency;
/**
Dependencies that will usually be required by the package user directly or via another dependency.
*/
peerDependencies?: PackageJson.Dependency;
/**
Package names that are bundled when the package is published.
*/
bundledDependencies?: string[];
/**
Alias of `bundledDependencies`.
*/
bundleDependencies?: string[];
/**
Engines that this package runs on.
*/
engines?: {
[EngineName in 'npm' | 'node' | string]: string;
};
/**
@deprecated
*/
engineStrict?: boolean;
/**
Operating systems the module runs on.
*/
os?: LiteralUnion<
| 'aix'
| 'darwin'
| 'freebsd'
| 'linux'
| 'openbsd'
| 'sunos'
| 'win32'
| '!aix'
| '!darwin'
| '!freebsd'
| '!linux'
| '!openbsd'
| '!sunos'
| '!win32',
string
>[];
/**
CPU architectures the module runs on.
*/
cpu?: LiteralUnion<
| 'arm'
| 'arm64'
| 'ia32'
| 'mips'
| 'mipsel'
| 'ppc'
| 'ppc64'
| 's390'
| 's390x'
| 'x32'
| 'x64'
| '!arm'
| '!arm64'
| '!ia32'
| '!mips'
| '!mipsel'
| '!ppc'
| '!ppc64'
| '!s390'
| '!s390x'
| '!x32'
| '!x64',
string
>[];
/**
If set to `true`, a warning will be shown if package is installed locally. Useful if the package is primarily a command-line application that should be installed globally.
@deprecated
*/
preferGlobal?: boolean;
/**
If set to `true`, then npm will refuse to publish it.
*/
private?: boolean;
/**
* A set of config values that will be used at publish-time. It's especially handy to set the tag, registry or access, to ensure that a given package is not tagged with 'latest', published to the global public registry or that a scoped module is private by default.
*/
publishConfig?: {
[config: string]: unknown;
};
} &
PackageJson.NonStandardEntryPoints &
PackageJson.TypeScriptConfiguration &
PackageJson.YarnConfiguration &
PackageJson.JSPMConfiguration & {
[key: string]: unknown;
};
......@@ -2,6 +2,39 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [14.2.0](https://github.com/yargs/yargs/compare/v14.1.0...v14.2.0) (2019-10-07)
### Bug Fixes
* async middleware was called twice ([#1422](https://github.com/yargs/yargs/issues/1422)) ([9a42b63](https://github.com/yargs/yargs/commit/9a42b63))
* fix promise check to accept any spec conform object ([#1424](https://github.com/yargs/yargs/issues/1424)) ([0be43d2](https://github.com/yargs/yargs/commit/0be43d2))
* groups were not being maintained for nested commands ([#1430](https://github.com/yargs/yargs/issues/1430)) ([d38650e](https://github.com/yargs/yargs/commit/d38650e))
* **docs:** broken markdown link ([#1426](https://github.com/yargs/yargs/issues/1426)) ([236e24e](https://github.com/yargs/yargs/commit/236e24e))
* support merging deeply nested configuration ([#1423](https://github.com/yargs/yargs/issues/1423)) ([bae66fe](https://github.com/yargs/yargs/commit/bae66fe))
### Features
* **deps:** introduce yargs-parser with support for unknown-options-as-args ([#1440](https://github.com/yargs/yargs/issues/1440)) ([4d21520](https://github.com/yargs/yargs/commit/4d21520))
## [14.1.0](https://github.com/yargs/yargs/compare/v14.0.0...v14.1.0) (2019-09-06)
### Bug Fixes
* **docs:** fix incorrect parserConfiguration documentation ([2a99124](https://github.com/yargs/yargs/commit/2a99124))
* detect zsh when zsh isnt run as a login prompt ([#1395](https://github.com/yargs/yargs/issues/1395)) ([8792d13](https://github.com/yargs/yargs/commit/8792d13))
* populate correct value on yargs.parsed and stop warning on access ([#1412](https://github.com/yargs/yargs/issues/1412)) ([bb0eb52](https://github.com/yargs/yargs/commit/bb0eb52))
* showCompletionScript was logging script twice ([#1388](https://github.com/yargs/yargs/issues/1388)) ([07c8537](https://github.com/yargs/yargs/commit/07c8537))
* strict() should not ignore hyphenated arguments ([#1414](https://github.com/yargs/yargs/issues/1414)) ([b774b5e](https://github.com/yargs/yargs/commit/b774b5e))
* **docs:** formalize existing callback argument to showHelp ([#1386](https://github.com/yargs/yargs/issues/1386)) ([d217764](https://github.com/yargs/yargs/commit/d217764))
### Features
* make it possible to merge configurations when extending other config. ([#1411](https://github.com/yargs/yargs/issues/1411)) ([5d7ad98](https://github.com/yargs/yargs/commit/5d7ad98))
## [14.0.0](https://github.com/yargs/yargs/compare/v13.3.0...v14.0.0) (2019-07-30)
......
......@@ -80,7 +80,8 @@ require('yargs') // eslint-disable-line
})
.option('verbose', {
alias: 'v',
default: false
type: 'boolean',
description: 'Run with verbose logging'
})
.argv
```
......@@ -95,7 +96,7 @@ yargs has type definitions at [@types/yargs][type-definitions].
npm i @types/yargs --save-dev
```
See usage examples in [docs](/docs/typescript.md)
See usage examples in [docs](/docs/typescript.md).
## Community :
......
......@@ -32,7 +32,6 @@ function singletonify (inst) {
return inst.$0
})
Argv.__defineGetter__('parsed', () => {
console.warn('In future major releases of yargs, "parsed" will be a private field. Use the return value of ".parse()" or ".argv" instead')
return inst.parsed
})
}
......
......@@ -16,7 +16,21 @@ function getPathToDefaultConfig (cwd, pathToExtend) {
return path.resolve(cwd, pathToExtend)
}
function applyExtends (config, cwd) {
function mergeDeep (config1, config2) {
const target = {}
const isObject = obj => obj && typeof obj === 'object' && !Array.isArray(obj)
Object.assign(target, config1)
for (let key of Object.keys(config2)) {
if (isObject(config2[key]) && isObject(target[key])) {
target[key] = mergeDeep(config1[key], config2[key])
} else {
target[key] = config2[key]
}
}
return target
}
function applyExtends (config, cwd, mergeExtends) {
let defaultConfig = {}
if (Object.prototype.hasOwnProperty.call(config, 'extends')) {
......@@ -42,12 +56,12 @@ function applyExtends (config, cwd) {
defaultConfig = isPath ? JSON.parse(fs.readFileSync(pathToDefault, 'utf8')) : require(config.extends)
delete config.extends
defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault))
defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault), mergeExtends)
}
previouslyVisitedConfigs = []
return Object.assign({}, defaultConfig, config)
return mergeExtends ? mergeDeep(defaultConfig, config) : Object.assign({}, defaultConfig, config)
}
module.exports = applyExtends
......@@ -174,7 +174,7 @@ module.exports = function command (yargs, usage, validation, globalMiddleware) {
let numFiles = currentContext.files.length
const parentCommands = currentContext.commands.slice()
// what does yargs look like after the buidler is run?
// what does yargs look like after the builder is run?
let innerArgv = parsed.argv
let innerYargs = null
let positionalMap = {}
......@@ -230,14 +230,22 @@ module.exports = function command (yargs, usage, validation, globalMiddleware) {
innerArgv = applyMiddleware(innerArgv, yargs, middlewares, false)
const handlerResult = isPromise(innerArgv)
? innerArgv.then(argv => commandHandler.handler(argv))
: commandHandler.handler(innerArgv)
let handlerResult
if (isPromise(innerArgv)) {
handlerResult = innerArgv.then(argv => commandHandler.handler(argv))
} else {
handlerResult = commandHandler.handler(innerArgv)
}
if (isPromise(handlerResult)) {
handlerResult.catch(error =>
yargs.getUsageInstance().fail(null, error)
)
yargs.getUsageInstance().cacheHelpMessage()
handlerResult.catch(error => {
try {
yargs.getUsageInstance().fail(null, error)
} catch (err) {
// fail's throwing would cause an unhandled rejection.
}
})
}
}
......
......@@ -8,7 +8,8 @@ module.exports = function completion (yargs, usage, command) {
completionKey: 'get-yargs-completions'
}
const zshShell = process.env.SHELL && process.env.SHELL.indexOf('zsh') !== -1
const zshShell = (process.env.SHELL && process.env.SHELL.indexOf('zsh') !== -1) ||
(process.env.ZSH_NAME && process.env.ZSH_NAME.indexOf('zsh') !== -1)
// get a list of completion commands.
// 'args' is the array of strings from the line to be completed
self.getCompletion = function getCompletion (args, done) {
......
module.exports = function isPromise (maybePromise) {
return maybePromise instanceof Promise
return !!maybePromise && !!maybePromise.then && (typeof maybePromise.then === 'function')
}
......@@ -40,8 +40,7 @@ function applyMiddleware (argv, yargs, middlewares, beforeValidation) {
const beforeValidationError = new Error('middleware cannot return a promise when applyBeforeValidation is true')
return middlewares
.reduce((accumulation, middleware) => {
if (middleware.applyBeforeValidation !== beforeValidation &&
!isPromise(accumulation)) {
if (middleware.applyBeforeValidation !== beforeValidation) {
return accumulation
}
......
......@@ -148,6 +148,7 @@ module.exports = function usage (yargs, y18n) {
const defaultGroup = 'Options:'
self.help = function help () {
if (cachedHelpMessage) return cachedHelpMessage
normalizeAliases()
// handle old demanded API
......@@ -403,6 +404,13 @@ module.exports = function usage (yargs, y18n) {
})
}
// if yargs is executing an async handler, we take a snapshot of the
// help message to display on failure:
let cachedHelpMessage
self.cacheHelpMessage = function () {
cachedHelpMessage = this.help()
}
// given a set of keys, place any keys that are
// ungrouped under the 'Options:' grouping.
function addUngroupedKeys (keys, aliases, groups) {
......
......@@ -96,7 +96,7 @@ module.exports = function validation (yargs, usage, y18n) {
if (specialKeys.indexOf(key) === -1 &&
!positionalMap.hasOwnProperty(key) &&
!yargs._getParseContext().hasOwnProperty(key) &&
!aliases.hasOwnProperty(key)
!self.isValidAndSomeAliasIsNotNew(key, aliases)
) {
unknown.push(key)
}
......@@ -120,6 +120,21 @@ module.exports = function validation (yargs, usage, y18n) {
}
}
// check for a key that is not an alias, or for which every alias is new,
// implying that it was invented by the parser, e.g., during camelization
self.isValidAndSomeAliasIsNotNew = function isValidAndSomeAliasIsNotNew (key, aliases) {
if (!aliases.hasOwnProperty(key)) {
return false
}
const newAliases = yargs.parsed.newAliases
for (let a of [key, ...aliases[key]]) {
if (!newAliases.hasOwnProperty(a) || !newAliases[key]) {
return true
}
}
return false
}
// validate arguments limited to enumerated choices
self.limitedChoices = function limitedChoices (argv) {
const options = yargs.getOptions()
......@@ -209,43 +224,36 @@ module.exports = function validation (yargs, usage, y18n) {
return implied
}
function keyExists (argv, val) {
// convert string '1' to number 1
let num = Number(val)
val = isNaN(num) ? val : num
if (typeof val === 'number') {
// check length of argv._
val = argv._.length >= val
} else if (val.match(/^--no-.+/)) {
// check if key/value doesn't exist
val = val.match(/^--no-(.+)/)[1]
val = !argv[val]
} else {
// check if key/value exists
val = argv[val]
}
return val
}
self.implications = function implications (argv) {
const implyFail = []
Object.keys(implied).forEach((key) => {
const origKey = key
;(implied[key] || []).forEach((value) => {
let num
let key = origKey
const origValue = value
key = keyExists(argv, key)
value = keyExists(argv, value)
// convert string '1' to number 1
num = Number(key)
key = isNaN(num) ? key : num
if (typeof key === 'number') {
// check length of argv._
key = argv._.length >= key
} else if (key.match(/^--no-.+/)) {
// check if key doesn't exist
key = key.match(/^--no-(.+)/)[1]
key = !argv[key]
} else {
// check if key exists
key = argv[key]
}
num = Number(value)
value = isNaN(num) ? value : num
if (typeof value === 'number') {
value = argv._.length >= value
} else if (value.match(/^--no-.+/)) {
value = value.match(/^--no-(.+)/)[1]
value = !argv[value]
} else {
value = argv[value]
}
if (key && !value) {
implyFail.push(` ${origKey} -> ${origValue}`)
}
......
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [15.0.0](https://github.com/yargs/yargs-parser/compare/v14.0.0...v15.0.0) (2019-10-07)
### Features
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality ([ef771ca](https://github.com/yargs/yargs-parser/commit/ef771ca))
### BREAKING CHANGES
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality
## [14.0.0](https://github.com/yargs/yargs-parser/compare/v13.1.1...v14.0.0) (2019-09-06)
### Bug Fixes
* boolean arrays with default values ([#185](https://github.com/yargs/yargs-parser/issues/185)) ([7d42572](https://github.com/yargs/yargs-parser/commit/7d42572))
* boolean now behaves the same as other array types ([#184](https://github.com/yargs/yargs-parser/issues/184)) ([17ca3bd](https://github.com/yargs/yargs-parser/commit/17ca3bd))
* eatNargs() for 'opt.narg === 0' and boolean typed options ([#188](https://github.com/yargs/yargs-parser/issues/188)) ([c5a1db0](https://github.com/yargs/yargs-parser/commit/c5a1db0))
* maybeCoerceNumber now takes precedence over coerce return value ([#182](https://github.com/yargs/yargs-parser/issues/182)) ([2f26436](https://github.com/yargs/yargs-parser/commit/2f26436))
* take into account aliases when appending arrays from config object ([#199](https://github.com/yargs/yargs-parser/issues/199)) ([f8a2d3f](https://github.com/yargs/yargs-parser/commit/f8a2d3f))
### Features
* add configuration option to "collect-unknown-options" ([#181](https://github.com/yargs/yargs-parser/issues/181)) ([7909cc4](https://github.com/yargs/yargs-parser/commit/7909cc4))
* maybeCoerceNumber() now takes into account arrays ([#187](https://github.com/yargs/yargs-parser/issues/187)) ([31c204b](https://github.com/yargs/yargs-parser/commit/31c204b))
### BREAKING CHANGES
* unless "parse-numbers" is set to "false", arrays of numeric strings are now parsed as numbers, rather than strings.
* we have dropped the broken "defaulted" functionality; we would like to revisit adding this in the future.
* maybeCoerceNumber now takes precedence over coerce return value (#182)
### [13.1.1](https://www.github.com/yargs/yargs-parser/compare/v13.1.0...v13.1.1) (2019-06-10)
### Bug Fixes
* convert values to strings when tokenizing ([#167](https://www.github.com/yargs/yargs-parser/issues/167)) ([57b7883](https://www.github.com/yargs/yargs-parser/commit/57b7883))
* nargs should allow duplicates when duplicate-arguments-array=false ([#164](https://www.github.com/yargs/yargs-parser/issues/164)) ([47ccb0b](https://www.github.com/yargs/yargs-parser/commit/47ccb0b))
* should populate "_" when given config with "short-option-groups" false ([#179](https://www.github.com/yargs/yargs-parser/issues/179)) ([6055974](https://www.github.com/yargs/yargs-parser/commit/6055974))
## [13.1.0](https://github.com/yargs/yargs-parser/compare/v13.0.0...v13.1.0) (2019-05-05)
### Features
* add `strip-aliased` and `strip-dashed` configuration options. ([#172](https://github.com/yargs/yargs-parser/issues/172)) ([a3936aa](https://github.com/yargs/yargs-parser/commit/a3936aa))
* support boolean which do not consume next argument. ([#171](https://github.com/yargs/yargs-parser/issues/171)) ([0ae7fcb](https://github.com/yargs/yargs-parser/commit/0ae7fcb))
<a name="13.0.0"></a>
# [13.0.0](https://github.com/yargs/yargs-parser/compare/v12.0.0...v13.0.0) (2019-02-02)
### Features
* don't coerce number from string with leading '0' or '+' ([#158](https://github.com/yargs/yargs-parser/issues/158)) ([18d0fd5](https://github.com/yargs/yargs-parser/commit/18d0fd5))
### BREAKING CHANGES
* options with leading '+' or '0' now parse as strings
<a name="12.0.0"></a>
# [12.0.0](https://github.com/yargs/yargs-parser/compare/v11.1.1...v12.0.0) (2019-01-29)
### Bug Fixes
* better handling of quoted strings ([#153](https://github.com/yargs/yargs-parser/issues/153)) ([2fb71b2](https://github.com/yargs/yargs-parser/commit/2fb71b2))
### Features
* default value is now used if no right-hand value provided for numbers/strings ([#156](https://github.com/yargs/yargs-parser/issues/156)) ([5a7c46a](https://github.com/yargs/yargs-parser/commit/5a7c46a))
### BREAKING CHANGES
* a flag with no right-hand value no longer populates defaulted options with `undefined`.
* quotes at beginning and endings of strings are not removed during parsing.
<a name="11.1.1"></a>
## [11.1.1](https://github.com/yargs/yargs-parser/compare/v11.1.0...v11.1.1) (2018-11-19)
### Bug Fixes
* ensure empty string is added into argv._ ([#140](https://github.com/yargs/yargs-parser/issues/140)) ([79cda98](https://github.com/yargs/yargs-parser/commit/79cda98))
### Reverts
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([f4a3063](https://github.com/yargs/yargs-parser/commit/f4a3063))
<a name="11.1.0"></a>
# [11.1.0](https://github.com/yargs/yargs-parser/compare/v11.0.0...v11.1.0) (2018-11-10)
### Bug Fixes
* handling of one char alias ([#139](https://github.com/yargs/yargs-parser/issues/139)) ([ee56e31](https://github.com/yargs/yargs-parser/commit/ee56e31))
### Features
* add halt-at-non-option configuration option ([#130](https://github.com/yargs/yargs-parser/issues/130)) ([a849fce](https://github.com/yargs/yargs-parser/commit/a849fce))
<a name="11.0.0"></a>
# [11.0.0](https://github.com/yargs/yargs-parser/compare/v10.1.0...v11.0.0) (2018-10-06)
### Bug Fixes
* flatten-duplicate-arrays:false for more than 2 arrays ([#128](https://github.com/yargs/yargs-parser/issues/128)) ([2bc395f](https://github.com/yargs/yargs-parser/commit/2bc395f))
* hyphenated flags combined with dot notation broke parsing ([#131](https://github.com/yargs/yargs-parser/issues/131)) ([dc788da](https://github.com/yargs/yargs-parser/commit/dc788da))
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([77ae1d4](https://github.com/yargs/yargs-parser/commit/77ae1d4))
### Chores
* update dependencies ([6dc42a1](https://github.com/yargs/yargs-parser/commit/6dc42a1))
### Features
* also add camelCase array options ([#125](https://github.com/yargs/yargs-parser/issues/125)) ([08c0117](https://github.com/yargs/yargs-parser/commit/08c0117))
* array.type can now be provided, supporting coercion ([#132](https://github.com/yargs/yargs-parser/issues/132)) ([4b8cfce](https://github.com/yargs/yargs-parser/commit/4b8cfce))
### BREAKING CHANGES
* drops Node 4 support
* the argv object is now populated differently (correctly) when hyphens and dot notation are used in conjunction.
<a name="10.1.0"></a>
# [10.1.0](https://github.com/yargs/yargs-parser/compare/v10.0.0...v10.1.0) (2018-06-29)
### Features
* add `set-placeholder-key` configuration ([#123](https://github.com/yargs/yargs-parser/issues/123)) ([19386ee](https://github.com/yargs/yargs-parser/commit/19386ee))
<a name="10.0.0"></a>
# [10.0.0](https://github.com/yargs/yargs-parser/compare/v9.0.2...v10.0.0) (2018-04-04)
### Bug Fixes
* do not set boolean flags if not defined in `argv` ([#119](https://github.com/yargs/yargs-parser/issues/119)) ([f6e6599](https://github.com/yargs/yargs-parser/commit/f6e6599))
### BREAKING CHANGES
* `boolean` flags defined without a `default` value will now behave like other option type and won't be set in the parsed results when the user doesn't set the corresponding CLI arg.
Previous behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [], flag: false }
```
New behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [] } => flag not set similarly to other option type
```
<a name="9.0.2"></a>
## [9.0.2](https://github.com/yargs/yargs-parser/compare/v9.0.1...v9.0.2) (2018-01-20)
### Bug Fixes
* nargs was still aggressively consuming too many arguments ([9b28aad](https://github.com/yargs/yargs-parser/commit/9b28aad))
<a name="9.0.1"></a>
## [9.0.1](https://github.com/yargs/yargs-parser/compare/v9.0.0...v9.0.1) (2018-01-20)
### Bug Fixes
* nargs was consuming too many arguments ([4fef206](https://github.com/yargs/yargs-parser/commit/4fef206))
<a name="9.0.0"></a>
# [9.0.0](https://github.com/yargs/yargs-parser/compare/v8.1.0...v9.0.0) (2018-01-20)
### Features
* narg arguments no longer consume flag arguments ([#114](https://github.com/yargs/yargs-parser/issues/114)) ([60bb9b3](https://github.com/yargs/yargs-parser/commit/60bb9b3))
### BREAKING CHANGES
* arguments of form --foo, -abc, will no longer be consumed by nargs
<a name="8.1.0"></a>
# [8.1.0](https://github.com/yargs/yargs-parser/compare/v8.0.0...v8.1.0) (2017-12-20)
### Bug Fixes
* allow null config values ([#108](https://github.com/yargs/yargs-parser/issues/108)) ([d8b14f9](https://github.com/yargs/yargs-parser/commit/d8b14f9))
* ensure consistent parsing of dot-notation arguments ([#102](https://github.com/yargs/yargs-parser/issues/102)) ([c9bd79c](https://github.com/yargs/yargs-parser/commit/c9bd79c))
* implement [@antoniom](https://github.com/antoniom)'s fix for camel-case expansion ([3087e1d](https://github.com/yargs/yargs-parser/commit/3087e1d))
* only run coercion functions once, despite aliases. ([#76](https://github.com/yargs/yargs-parser/issues/76)) ([#103](https://github.com/yargs/yargs-parser/issues/103)) ([507aaef](https://github.com/yargs/yargs-parser/commit/507aaef))
* scientific notation circumvented bounds check ([#110](https://github.com/yargs/yargs-parser/issues/110)) ([3571f57](https://github.com/yargs/yargs-parser/commit/3571f57))
* tokenizer should ignore spaces at the beginning of the argString ([#106](https://github.com/yargs/yargs-parser/issues/106)) ([f34ead9](https://github.com/yargs/yargs-parser/commit/f34ead9))
### Features
* make combining arrays a configurable option ([#111](https://github.com/yargs/yargs-parser/issues/111)) ([c8bf536](https://github.com/yargs/yargs-parser/commit/c8bf536))
* merge array from arguments with array from config ([#83](https://github.com/yargs/yargs-parser/issues/83)) ([806ddd6](https://github.com/yargs/yargs-parser/commit/806ddd6))
<a name="8.0.0"></a>
# [8.0.0](https://github.com/yargs/yargs-parser/compare/v7.0.0...v8.0.0) (2017-10-05)
### Bug Fixes
* Ignore multiple spaces between arguments. ([#100](https://github.com/yargs/yargs-parser/issues/100)) ([d137227](https://github.com/yargs/yargs-parser/commit/d137227))
### Features
* allow configuration of prefix for boolean negation ([#94](https://github.com/yargs/yargs-parser/issues/94)) ([00bde7d](https://github.com/yargs/yargs-parser/commit/00bde7d))
* reworking how numbers are parsed ([#104](https://github.com/yargs/yargs-parser/issues/104)) ([fba00eb](https://github.com/yargs/yargs-parser/commit/fba00eb))
### BREAKING CHANGES
* strings that fail `Number.isSafeInteger()` are no longer coerced into numbers.
<a name="7.0.0"></a>
# [7.0.0](https://github.com/yargs/yargs-parser/compare/v6.0.1...v7.0.0) (2017-05-02)
### Chores
* revert populate-- logic ([#91](https://github.com/yargs/yargs-parser/issues/91)) ([6003e6d](https://github.com/yargs/yargs-parser/commit/6003e6d))
### BREAKING CHANGES
* populate-- now defaults to false.
<a name="6.0.1"></a>
## [6.0.1](https://github.com/yargs/yargs-parser/compare/v6.0.0...v6.0.1) (2017-05-01)
### Bug Fixes
* default '--' to undefined when not provided; this is closer to the array API ([#90](https://github.com/yargs/yargs-parser/issues/90)) ([4e739cc](https://github.com/yargs/yargs-parser/commit/4e739cc))
<a name="6.0.0"></a>
# [6.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v6.0.0) (2017-05-01)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
* parsing hints should apply for dot notation keys ([#86](https://github.com/yargs/yargs-parser/issues/86)) ([3e47d62](https://github.com/yargs/yargs-parser/commit/3e47d62))
### Chores
* upgrade to newest version of camelcase ([#87](https://github.com/yargs/yargs-parser/issues/87)) ([f1903aa](https://github.com/yargs/yargs-parser/commit/f1903aa))
### Features
* add -- option which allows arguments after the -- flag to be returned separated from positional arguments ([#84](https://github.com/yargs/yargs-parser/issues/84)) ([2572ca8](https://github.com/yargs/yargs-parser/commit/2572ca8))
* when parsing stops, we now populate "--" by default ([#88](https://github.com/yargs/yargs-parser/issues/88)) ([cd666db](https://github.com/yargs/yargs-parser/commit/cd666db))
### BREAKING CHANGES
* rather than placing arguments in "_", when parsing is stopped via "--"; we now populate an array called "--" by default.
* camelcase now requires Node 4+.
* environment variables will now override config files (args, env, config-file, config-object)
<a name="5.0.0"></a>
# [5.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v5.0.0) (2017-02-18)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
### BREAKING CHANGES
* environment variables will now override config files (args, env, config-file, config-object)
<a name="4.2.1"></a>
## [4.2.1](https://github.com/yargs/yargs-parser/compare/v4.2.0...v4.2.1) (2017-01-02)
### Bug Fixes
* flatten/duplicate regression ([#75](https://github.com/yargs/yargs-parser/issues/75)) ([68d68a0](https://github.com/yargs/yargs-parser/commit/68d68a0))
<a name="4.2.0"></a>
# [4.2.0](https://github.com/yargs/yargs-parser/compare/v4.1.0...v4.2.0) (2016-12-01)
### Bug Fixes
* inner objects in configs had their keys appended to top-level key when dot-notation was disabled ([#72](https://github.com/yargs/yargs-parser/issues/72)) ([0b1b5f9](https://github.com/yargs/yargs-parser/commit/0b1b5f9))
### Features
* allow multiple arrays to be provided, rather than always combining ([#71](https://github.com/yargs/yargs-parser/issues/71)) ([0f0fb2d](https://github.com/yargs/yargs-parser/commit/0f0fb2d))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/yargs/yargs-parser/compare/v4.0.2...v4.1.0) (2016-11-07)
### Features
* apply coercions to default options ([#65](https://github.com/yargs/yargs-parser/issues/65)) ([c79052b](https://github.com/yargs/yargs-parser/commit/c79052b))
* handle dot notation boolean options ([#63](https://github.com/yargs/yargs-parser/issues/63)) ([02c3545](https://github.com/yargs/yargs-parser/commit/02c3545))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/yargs/yargs-parser/compare/v4.0.1...v4.0.2) (2016-09-30)
### Bug Fixes
* whoops, let's make the assign not change the Object key order ([29d069a](https://github.com/yargs/yargs-parser/commit/29d069a))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/yargs/yargs-parser/compare/v4.0.0...v4.0.1) (2016-09-30)
### Bug Fixes
* lodash.assign was deprecated ([#59](https://github.com/yargs/yargs-parser/issues/59)) ([5e7eb11](https://github.com/yargs/yargs-parser/commit/5e7eb11))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/yargs/yargs-parser/compare/v3.2.0...v4.0.0) (2016-09-26)
### Bug Fixes
* coerce should be applied to the final objects and arrays created ([#57](https://github.com/yargs/yargs-parser/issues/57)) ([4ca69da](https://github.com/yargs/yargs-parser/commit/4ca69da))
### BREAKING CHANGES
* coerce is no longer applied to individual arguments in an implicit array.
<a name="3.2.0"></a>
# [3.2.0](https://github.com/yargs/yargs-parser/compare/v3.1.0...v3.2.0) (2016-08-13)
### Features
* coerce full array instead of each element ([#51](https://github.com/yargs/yargs-parser/issues/51)) ([cc4dc56](https://github.com/yargs/yargs-parser/commit/cc4dc56))
<a name="3.1.0"></a>
# [3.1.0](https://github.com/yargs/yargs-parser/compare/v3.0.0...v3.1.0) (2016-08-09)
### Bug Fixes
* address pkgConf parsing bug outlined in [#37](https://github.com/yargs/yargs-parser/issues/37) ([#45](https://github.com/yargs/yargs-parser/issues/45)) ([be76ee6](https://github.com/yargs/yargs-parser/commit/be76ee6))
* better parsing of negative values ([#44](https://github.com/yargs/yargs-parser/issues/44)) ([2e43692](https://github.com/yargs/yargs-parser/commit/2e43692))
* check aliases when guessing defaults for arguments fixes [#41](https://github.com/yargs/yargs-parser/issues/41) ([#43](https://github.com/yargs/yargs-parser/issues/43)) ([f3e4616](https://github.com/yargs/yargs-parser/commit/f3e4616))
### Features
* added coerce option, for providing specialized argument parsing ([#42](https://github.com/yargs/yargs-parser/issues/42)) ([7b49cd2](https://github.com/yargs/yargs-parser/commit/7b49cd2))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/yargs/yargs-parser/compare/v2.4.1...v3.0.0) (2016-08-07)
### Bug Fixes
* parsing issue with numeric character in group of options ([#19](https://github.com/yargs/yargs-parser/issues/19)) ([f743236](https://github.com/yargs/yargs-parser/commit/f743236))
* upgraded lodash.assign ([5d7fdf4](https://github.com/yargs/yargs-parser/commit/5d7fdf4))
### BREAKING CHANGES
* subtle change to how values are parsed in a group of single-character arguments.
* _first released in 3.1.0, better handling of negative values should be considered a breaking change._
<a name="2.4.1"></a>
## [2.4.1](https://github.com/yargs/yargs-parser/compare/v2.4.0...v2.4.1) (2016-07-16)
### Bug Fixes
* **count:** do not increment a default value ([#39](https://github.com/yargs/yargs-parser/issues/39)) ([b04a189](https://github.com/yargs/yargs-parser/commit/b04a189))
<a name="2.4.0"></a>
# [2.4.0](https://github.com/yargs/yargs-parser/compare/v2.3.0...v2.4.0) (2016-04-11)
### Features
* **environment:** Support nested options in environment variables ([#26](https://github.com/yargs/yargs-parser/issues/26)) thanks [@elas7](https://github.com/elas7) \o/ ([020778b](https://github.com/yargs/yargs-parser/commit/020778b))
<a name="2.3.0"></a>
# [2.3.0](https://github.com/yargs/yargs-parser/compare/v2.2.0...v2.3.0) (2016-04-09)
### Bug Fixes
* **boolean:** fix for boolean options with non boolean defaults (#20) ([2dbe86b](https://github.com/yargs/yargs-parser/commit/2dbe86b)), closes [(#20](https://github.com/(/issues/20)
* **package:** remove tests from tarball ([0353c0d](https://github.com/yargs/yargs-parser/commit/0353c0d))
* **parsing:** handle calling short option with an empty string as the next value. ([a867165](https://github.com/yargs/yargs-parser/commit/a867165))
* boolean flag when next value contains the strings 'true' or 'false'. ([69941a6](https://github.com/yargs/yargs-parser/commit/69941a6))
* update dependencies; add standard-version bin for next release (#24) ([822d9d5](https://github.com/yargs/yargs-parser/commit/822d9d5))
### Features
* **configuration:** Allow to pass configuration objects to yargs-parser ([0780900](https://github.com/yargs/yargs-parser/commit/0780900))
* **normalize:** allow normalize to work with arrays ([e0eaa1a](https://github.com/yargs/yargs-parser/commit/e0eaa1a))
Copyright (c) 2016, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# yargs-parser
[![Build Status](https://travis-ci.org/yargs/yargs-parser.svg)](https://travis-ci.org/yargs/yargs-parser)
[![Coverage Status](https://coveralls.io/repos/yargs/yargs-parser/badge.svg?branch=)](https://coveralls.io/r/yargs/yargs-parser?branch=master)
[![NPM version](https://img.shields.io/npm/v/yargs-parser.svg)](https://www.npmjs.com/package/yargs-parser)
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
The mighty option parser used by [yargs](https://github.com/yargs/yargs).
visit the [yargs website](http://yargs.js.org/) for more examples, and thorough usage instructions.
<img width="250" src="https://raw.githubusercontent.com/yargs/yargs-parser/master/yargs-logo.png">
## Example
```sh
npm i yargs-parser --save
```
```js
var argv = require('yargs-parser')(process.argv.slice(2))
console.log(argv)
```
```sh
node example.js --foo=33 --bar hello
{ _: [], foo: 33, bar: 'hello' }
```
_or parse a string!_
```js
var argv = require('yargs-parser')('--foo=99 --bar=33')
console.log(argv)
```
```sh
{ _: [], foo: 99, bar: 33 }
```
Convert an array of mixed types before passing to `yargs-parser`:
```js
var parse = require('yargs-parser')
parse(['-f', 11, '--zoom', 55].join(' ')) // <-- array to string
parse(['-f', 11, '--zoom', 55].map(String)) // <-- array of strings
```
## API
### require('yargs-parser')(args, opts={})
Parses command line arguments returning a simple mapping of keys and values.
**expects:**
* `args`: a string or array of strings representing the options to parse.
* `opts`: provide a set of hints indicating how `args` should be parsed:
* `opts.alias`: an object representing the set of aliases for a key: `{alias: {foo: ['f']}}`.
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.<br>
Indicate that keys should be parsed as an array and coerced to booleans / numbers:<br>
`{array: [{ key: 'foo', boolean: true }, {key: 'bar', number: true}]}`.
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
* `opts.coerce`: provide a custom synchronous function that returns a coerced value from the argument provided
(or throws an error). For arrays the function is called only once for the entire array:<br>
`{coerce: {foo: function (arg) {return modifiedArg}}}`.
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
* `opts.configObjects`: configuration objects to parse, their properties will be set as arguments:<br>
`{configObjects: [{'x': 5, 'y': 33}, {'z': 44}]}`.
* `opts.configuration`: provide configuration options to the yargs-parser (see: [configuration](#configuration)).
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.
* `opts.narg`: specify that a key requires `n` arguments: `{narg: {x: 2}}`.
* `opts.normalize`: `path.normalize()` will be applied to values set to this key.
* `opts.number`: keys should be treated as numbers.
* `opts.string`: keys should be treated as strings (even if they resemble a number `-x 33`).
**returns:**
* `obj`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
### require('yargs-parser').detailed(args, opts={})
Parses a command line string, returning detailed information required by the
yargs engine.
**expects:**
* `args`: a string or array of strings representing options to parse.
* `opts`: provide a set of hints indicating how `args`, inputs are identical to `require('yargs-parser')(args, opts={})`.
**returns:**
* `argv`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* `error`: populated with an error object if an exception occurred during parsing.
* `aliases`: the inferred list of aliases built by combining lists in `opts.alias`.
* `newAliases`: any new aliases added via camel-case expansion.
* `configuration`: the configuration loaded from the `yargs` stanza in package.json.
<a name="configuration"></a>
### Configuration
The yargs-parser applies several automated transformations on the keys provided
in `args`. These features can be turned on and off using the `configuration` field
of `opts`.
```js
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
```
### short option groups
* default: `true`.
* key: `short-option-groups`.
Should a group of short-options be treated as boolean flags?
```sh
node example.js -abc
{ _: [], a: true, b: true, c: true }
```
_if disabled:_
```sh
node example.js -abc
{ _: [], abc: true }
```
### camel-case expansion
* default: `true`.
* key: `camel-case-expansion`.
Should hyphenated arguments be expanded into camel-case aliases?
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true, fooBar: true }
```
_if disabled:_
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true }
```
### dot-notation
* default: `true`
* key: `dot-notation`
Should keys that contain `.` be treated as objects?
```sh
node example.js --foo.bar
{ _: [], foo: { bar: true } }
```
_if disabled:_
```sh
node example.js --foo.bar
{ _: [], "foo.bar": true }
```
### parse numbers
* default: `true`
* key: `parse-numbers`
Should keys that look like numbers be treated as such?
```sh
node example.js --foo=99.3
{ _: [], foo: 99.3 }
```
_if disabled:_
```sh
node example.js --foo=99.3
{ _: [], foo: "99.3" }
```
### boolean negation
* default: `true`
* key: `boolean-negation`
Should variables prefixed with `--no` be treated as negations?
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if disabled:_
```sh
node example.js --no-foo
{ _: [], "no-foo": true }
```
### combine arrays
* default: `false`
* key: `combine-arrays`
Should arrays be combined when provided by both command line arguments and
a configuration file.
### duplicate arguments array
* default: `true`
* key: `duplicate-arguments-array`
Should arguments be coerced into an array when duplicated:
```sh
node example.js -x 1 -x 2
{ _: [], x: [1, 2] }
```
_if disabled:_
```sh
node example.js -x 1 -x 2
{ _: [], x: 2 }
```
### flatten duplicate arrays
* default: `true`
* key: `flatten-duplicate-arrays`
Should array arguments be coerced into a single array when duplicated:
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [1, 2, 3, 4] }
```
_if disabled:_
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [[1, 2], [3, 4]] }
```
### negation prefix
* default: `no-`
* key: `negation-prefix`
The prefix to use for negated boolean variables.
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if set to `quux`:_
```sh
node example.js --quuxfoo
{ _: [], foo: false }
```
### populate --
* default: `false`.
* key: `populate--`
Should unparsed flags be stored in `--` or `_`.
_If disabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a', 'x', 'y' ], b: true }
```
_If enabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a' ], '--': [ 'x', 'y' ], b: true }
```
### set placeholder key
* default: `false`.
* key: `set-placeholder-key`.
Should a placeholder be added for keys not set via the corresponding CLI argument?
_If disabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, c: 2 }
```
_If enabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, b: undefined, c: 2 }
```
### halt at non-option
* default: `false`.
* key: `halt-at-non-option`.
Should parsing stop at the first positional argument? This is similar to how e.g. `ssh` parses its command line.
_If disabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b' ], a: 'run', x: 'y' }
```
_If enabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b', '-x', 'y' ], a: 'run' }
```
### strip aliased
* default: `false`
* key: `strip-aliased`
Should aliases be removed before returning results?
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1, 'test-alias': 1, testAlias: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
### strip dashed
* default: `false`
* key: `strip-dashed`
Should dashed keys be removed before returning results? This option has no effect if
`camel-case-expansion` is disabled.
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], testField: 1 }
```
### unknown options as args
* default: `false`
* key: `unknown-options-as-args`
Should unknown options be treated like regular arguments? An unknown option is one that is not
configured in `opts`.
_If disabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: [], unknownOption: true, knownOption: 2, stringOption: '', unknownOption2: true }
```
_If enabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: ['--unknown-option'], knownOption: 2, stringOption: '--unknown-option2' }
```
## Special Thanks
The yargs project evolves from optimist and minimist. It owes its
existence to a lot of James Halliday's hard work. Thanks [substack](https://github.com/substack) **beep** **boop** \o/
## License
ISC
var camelCase = require('camelcase')
var decamelize = require('decamelize')
var path = require('path')
var tokenizeArgString = require('./lib/tokenize-arg-string')
var util = require('util')
function parse (args, opts) {
if (!opts) opts = {}
// allow a string argument to be passed in rather
// than an argv array.
args = tokenizeArgString(args)
// aliases might have transitive relationships, normalize this.
var aliases = combineAliases(opts.alias || {})
var configuration = Object.assign({
'short-option-groups': true,
'camel-case-expansion': true,
'dot-notation': true,
'parse-numbers': true,
'boolean-negation': true,
'negation-prefix': 'no-',
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true,
'populate--': false,
'combine-arrays': false,
'set-placeholder-key': false,
'halt-at-non-option': false,
'strip-aliased': false,
'strip-dashed': false,
'unknown-options-as-args': false
}, opts.configuration)
var defaults = opts.default || {}
var configObjects = opts.configObjects || []
var envPrefix = opts.envPrefix
var notFlagsOption = configuration['populate--']
var notFlagsArgv = notFlagsOption ? '--' : '_'
var newAliases = {}
// allow a i18n handler to be passed in, default to a fake one (util.format).
var __ = opts.__ || util.format
var error = null
var flags = {
aliases: {},
arrays: {},
bools: {},
strings: {},
numbers: {},
counts: {},
normalize: {},
configs: {},
nargs: {},
coercions: {},
keys: []
}
var negative = /^-[0-9]+(\.[0-9]+)?/
var negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)')
;[].concat(opts.array).filter(Boolean).forEach(function (opt) {
var key = opt.key || opt
// assign to flags[bools|strings|numbers]
const assignment = Object.keys(opt).map(function (key) {
return ({
boolean: 'bools',
string: 'strings',
number: 'numbers'
})[key]
}).filter(Boolean).pop()
// assign key to be coerced
if (assignment) {
flags[assignment][key] = true
}
flags.arrays[key] = true
flags.keys.push(key)
})
;[].concat(opts.boolean).filter(Boolean).forEach(function (key) {
flags.bools[key] = true
flags.keys.push(key)
})
;[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true
flags.keys.push(key)
})
;[].concat(opts.number).filter(Boolean).forEach(function (key) {
flags.numbers[key] = true
flags.keys.push(key)
})
;[].concat(opts.count).filter(Boolean).forEach(function (key) {
flags.counts[key] = true
flags.keys.push(key)
})
;[].concat(opts.normalize).filter(Boolean).forEach(function (key) {
flags.normalize[key] = true
flags.keys.push(key)
})
Object.keys(opts.narg || {}).forEach(function (k) {
flags.nargs[k] = opts.narg[k]
flags.keys.push(k)
})
Object.keys(opts.coerce || {}).forEach(function (k) {
flags.coercions[k] = opts.coerce[k]
flags.keys.push(k)
})
if (Array.isArray(opts.config) || typeof opts.config === 'string') {
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
flags.configs[key] = true
})
} else {
Object.keys(opts.config || {}).forEach(function (k) {
flags.configs[k] = opts.config[k]
})
}
// create a lookup table that takes into account all
// combinations of aliases: {f: ['foo'], foo: ['f']}
extendAliases(opts.key, aliases, opts.default, flags.arrays)
// apply default values to all aliases.
Object.keys(defaults).forEach(function (key) {
(flags.aliases[key] || []).forEach(function (alias) {
defaults[alias] = defaults[key]
})
})
var argv = { _: [] }
var notFlags = []
for (var i = 0; i < args.length; i++) {
var arg = args[i]
var broken
var key
var letters
var m
var next
var value
if (isUnknownOptionAsArg(arg)) {
argv._.push(arg)
// -- separated by =
} else if (arg.match(/^--.+=/) || (
!configuration['short-option-groups'] && arg.match(/^-.+=/)
)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
m = arg.match(/^--?([^=]+)=([\s\S]*)$/)
// nargs format = '--f=monkey washing cat'
if (checkAllAliases(m[1], flags.nargs)) {
args.splice(i + 1, 0, m[2])
i = eatNargs(i, m[1], args)
// arrays format = '--f=a b c'
} else if (checkAllAliases(m[1], flags.arrays)) {
args.splice(i + 1, 0, m[2])
i = eatArray(i, m[1], args)
} else {
setArg(m[1], m[2])
}
} else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
key = arg.match(negatedBoolean)[1]
setArg(key, checkAllAliases(key, flags.arrays) ? [false] : false)
// -- separated by space.
} else if (arg.match(/^--.+/) || (
!configuration['short-option-groups'] && arg.match(/^-[^-]+/)
)) {
key = arg.match(/^--?(.+)/)[1]
// nargs format = '--foo a b c'
// should be truthy even if: flags.nargs[key] === 0
if (checkAllAliases(key, flags.nargs) !== false) {
i = eatNargs(i, key, args)
// array format = '--foo a b c'
} else if (checkAllAliases(key, flags.arrays)) {
i = eatArray(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!next.match(/^-/) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
}
// dot-notation flag separated by '='.
} else if (arg.match(/^-.\..+=/)) {
m = arg.match(/^-([^=]+)=([\s\S]*)$/)
setArg(m[1], m[2])
// dot-notation flag separated by space.
} else if (arg.match(/^-.\..+/)) {
next = args[i + 1]
key = arg.match(/^-(.\..+)/)[1]
if (next !== undefined && !next.match(/^-/) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
} else if (arg.match(/^-[^-]+/) && !arg.match(negative)) {
letters = arg.slice(1, -1).split('')
broken = false
for (var j = 0; j < letters.length; j++) {
next = arg.slice(j + 2)
if (letters[j + 1] && letters[j + 1] === '=') {
value = arg.slice(j + 3)
key = letters[j]
// nargs format = '-f=monkey washing cat'
if (checkAllAliases(key, flags.nargs)) {
args.splice(i + 1, 0, value)
i = eatNargs(i, key, args)
// array format = '-f=a b c'
} else if (checkAllAliases(key, flags.arrays)) {
args.splice(i + 1, 0, value)
i = eatArray(i, key, args)
} else {
setArg(key, value)
}
broken = true
break
}
if (next === '-') {
setArg(letters[j], next)
continue
}
// current letter is an alphabetic character and next value is a number
if (/[A-Za-z]/.test(letters[j]) &&
/^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next)
broken = true
break
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
setArg(letters[j], next)
broken = true
break
} else {
setArg(letters[j], defaultValue(letters[j]))
}
}
key = arg.slice(-1)[0]
if (!broken && key !== '-') {
// nargs format = '-f a b c'
// should be truthy even if: flags.nargs[key] === 0
if (checkAllAliases(key, flags.nargs) !== false) {
i = eatNargs(i, key, args)
// array format = '-f a b c'
} else if (checkAllAliases(key, flags.arrays)) {
i = eatArray(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!/^(-|--)[^-]/.test(next) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
}
}
} else if (arg === '--') {
notFlags = args.slice(i + 1)
break
} else if (configuration['halt-at-non-option']) {
notFlags = args.slice(i)
break
} else {
argv._.push(maybeCoerceNumber('_', arg))
}
}
// order of precedence:
// 1. command line arg
// 2. value from env var
// 3. value from config file
// 4. value from config objects
// 5. configured default value
applyEnvVars(argv, true) // special case: check env vars that point to config file
applyEnvVars(argv, false)
setConfig(argv)
setConfigObjects()
applyDefaultsAndAliases(argv, flags.aliases, defaults)
applyCoercions(argv)
if (configuration['set-placeholder-key']) setPlaceholderKeys(argv)
// for any counts either not in args or without an explicit default, set to 0
Object.keys(flags.counts).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) setArg(key, 0)
})
// '--' defaults to undefined.
if (notFlagsOption && notFlags.length) argv[notFlagsArgv] = []
notFlags.forEach(function (key) {
argv[notFlagsArgv].push(key)
})
if (configuration['camel-case-expansion'] && configuration['strip-dashed']) {
Object.keys(argv).filter(key => key !== '--' && key.includes('-')).forEach(key => {
delete argv[key]
})
}
if (configuration['strip-aliased']) {
// XXX Switch to [].concat(...Object.values(aliases)) once node.js 6 is dropped
;[].concat(...Object.keys(aliases).map(k => aliases[k])).forEach(alias => {
if (configuration['camel-case-expansion']) {
delete argv[alias.split('.').map(prop => camelCase(prop)).join('.')]
}
delete argv[alias]
})
}
// how many arguments should we consume, based
// on the nargs option?
function eatNargs (i, key, args) {
var ii
const toEat = checkAllAliases(key, flags.nargs)
if (toEat === 0) {
setArg(key, defaultValue(key))
return i
}
// nargs will not consume flag arguments, e.g., -abc, --foo,
// and terminates when one is observed.
var available = 0
for (ii = i + 1; ii < args.length; ii++) {
if (!args[ii].match(/^-[^0-9]/) || isUnknownOptionAsArg(args[ii])) available++
else break
}
if (available < toEat) error = Error(__('Not enough arguments following: %s', key))
const consumed = Math.min(available, toEat)
for (ii = i + 1; ii < (consumed + i + 1); ii++) {
setArg(key, args[ii])
}
return (i + consumed)
}
// if an option is an array, eat all non-hyphenated arguments
// following it... YUM!
// e.g., --foo apple banana cat becomes ["apple", "banana", "cat"]
function eatArray (i, key, args) {
let argsToSet = []
let next = args[i + 1]
if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) {
argsToSet.push(true)
} else if (isUndefined(next) || (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) {
// for keys without value ==> argsToSet remains an empty []
// set user default value, if available
if (defaults.hasOwnProperty(key)) {
argsToSet.push(defaults[key])
}
} else {
for (var ii = i + 1; ii < args.length; ii++) {
next = args[ii]
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
i = ii
argsToSet.push(processValue(key, next))
}
}
setArg(key, argsToSet)
return i
}
function setArg (key, val) {
if (/-/.test(key) && configuration['camel-case-expansion']) {
var alias = key.split('.').map(function (prop) {
return camelCase(prop)
}).join('.')
addNewAlias(key, alias)
}
var value = processValue(key, val)
var splitKey = key.split('.')
setKey(argv, splitKey, value)
// handle populating aliases of the full key
if (flags.aliases[key]) {
flags.aliases[key].forEach(function (x) {
x = x.split('.')
setKey(argv, x, value)
})
}
// handle populating aliases of the first element of the dot-notation key
if (splitKey.length > 1 && configuration['dot-notation']) {
;(flags.aliases[splitKey[0]] || []).forEach(function (x) {
x = x.split('.')
// expand alias with nested objects in key
var a = [].concat(splitKey)
a.shift() // nuke the old key.
x = x.concat(a)
setKey(argv, x, value)
})
}
// Set normalize getter and setter when key is in 'normalize' but isn't an array
if (checkAllAliases(key, flags.normalize) && !checkAllAliases(key, flags.arrays)) {
var keys = [key].concat(flags.aliases[key] || [])
keys.forEach(function (key) {
argv.__defineSetter__(key, function (v) {
val = path.normalize(v)
})
argv.__defineGetter__(key, function () {
return typeof val === 'string' ? path.normalize(val) : val
})
})
}
}
function addNewAlias (key, alias) {
if (!(flags.aliases[key] && flags.aliases[key].length)) {
flags.aliases[key] = [alias]
newAliases[alias] = true
}
if (!(flags.aliases[alias] && flags.aliases[alias].length)) {
addNewAlias(alias, key)
}
}
function processValue (key, val) {
// strings may be quoted, clean this up as we assign values.
if (typeof val === 'string' &&
(val[0] === "'" || val[0] === '"') &&
val[val.length - 1] === val[0]
) {
val = val.substring(1, val.length - 1)
}
// handle parsing boolean arguments --foo=true --bar false.
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) {
if (typeof val === 'string') val = val === 'true'
}
var value = Array.isArray(val)
? val.map(function (v) { return maybeCoerceNumber(key, v) })
: maybeCoerceNumber(key, val)
// increment a count given as arg (either no value or value parsed as boolean)
if (checkAllAliases(key, flags.counts) && (isUndefined(value) || typeof value === 'boolean')) {
value = increment
}
// Set normalized value when key is in 'normalize' and in 'arrays'
if (checkAllAliases(key, flags.normalize) && checkAllAliases(key, flags.arrays)) {
if (Array.isArray(val)) value = val.map(path.normalize)
else value = path.normalize(val)
}
return value
}
function maybeCoerceNumber (key, value) {
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.bools) && !Array.isArray(value)) {
const shouldCoerceNumber = isNumber(value) && configuration['parse-numbers'] && (
Number.isSafeInteger(Math.floor(value))
)
if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) value = Number(value)
}
return value
}
// set args from config.json file, this should be
// applied last so that defaults can be applied.
function setConfig (argv) {
var configLookup = {}
// expand defaults/aliases, in-case any happen to reference
// the config.json file.
applyDefaultsAndAliases(configLookup, flags.aliases, defaults)
Object.keys(flags.configs).forEach(function (configKey) {
var configPath = argv[configKey] || configLookup[configKey]
if (configPath) {
try {
var config = null
var resolvedConfigPath = path.resolve(process.cwd(), configPath)
if (typeof flags.configs[configKey] === 'function') {
try {
config = flags.configs[configKey](resolvedConfigPath)
} catch (e) {
config = e
}
if (config instanceof Error) {
error = config
return
}
} else {
config = require(resolvedConfigPath)
}
setConfigObject(config)
} catch (ex) {
if (argv[configKey]) error = Error(__('Invalid JSON config file: %s', configPath))
}
}
})
}
// set args from config object.
// it recursively checks nested objects.
function setConfigObject (config, prev) {
Object.keys(config).forEach(function (key) {
var value = config[key]
var fullKey = prev ? prev + '.' + key : key
// if the value is an inner object and we have dot-notation
// enabled, treat inner objects in config the same as
// heavily nested dot notations (foo.bar.apple).
if (typeof value === 'object' && value !== null && !Array.isArray(value) && configuration['dot-notation']) {
// if the value is an object but not an array, check nested object
setConfigObject(value, fullKey)
} else {
// setting arguments via CLI takes precedence over
// values within the config file.
if (!hasKey(argv, fullKey.split('.')) || (checkAllAliases(fullKey, flags.arrays) && configuration['combine-arrays'])) {
setArg(fullKey, value)
}
}
})
}
// set all config objects passed in opts
function setConfigObjects () {
if (typeof configObjects === 'undefined') return
configObjects.forEach(function (configObject) {
setConfigObject(configObject)
})
}
function applyEnvVars (argv, configOnly) {
if (typeof envPrefix === 'undefined') return
var prefix = typeof envPrefix === 'string' ? envPrefix : ''
Object.keys(process.env).forEach(function (envVar) {
if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) {
// get array of nested keys and convert them to camel case
var keys = envVar.split('__').map(function (key, i) {
if (i === 0) {
key = key.substring(prefix.length)
}
return camelCase(key)
})
if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && !hasKey(argv, keys)) {
setArg(keys.join('.'), process.env[envVar])
}
}
})
}
function applyCoercions (argv) {
var coerce
var applied = {}
Object.keys(argv).forEach(function (key) {
if (!applied.hasOwnProperty(key)) { // If we haven't already coerced this option via one of its aliases
coerce = checkAllAliases(key, flags.coercions)
if (typeof coerce === 'function') {
try {
var value = maybeCoerceNumber(key, coerce(argv[key]))
;([].concat(flags.aliases[key] || [], key)).forEach(ali => {
applied[ali] = argv[ali] = value
})
} catch (err) {
error = err
}
}
}
})
}
function setPlaceholderKeys (argv) {
flags.keys.forEach((key) => {
// don't set placeholder keys for dot notation options 'foo.bar'.
if (~key.indexOf('.')) return
if (typeof argv[key] === 'undefined') argv[key] = undefined
})
return argv
}
function applyDefaultsAndAliases (obj, aliases, defaults) {
Object.keys(defaults).forEach(function (key) {
if (!hasKey(obj, key.split('.'))) {
setKey(obj, key.split('.'), defaults[key])
;(aliases[key] || []).forEach(function (x) {
if (hasKey(obj, x.split('.'))) return
setKey(obj, x.split('.'), defaults[key])
})
}
})
}
function hasKey (obj, keys) {
var o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key) {
o = (o[key] || {})
})
var key = keys[keys.length - 1]
if (typeof o !== 'object') return false
else return key in o
}
function setKey (obj, keys, value) {
var o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key, index) {
if (typeof o === 'object' && o[key] === undefined) {
o[key] = {}
}
if (typeof o[key] !== 'object' || Array.isArray(o[key])) {
// ensure that o[key] is an array, and that the last item is an empty object.
if (Array.isArray(o[key])) {
o[key].push({})
} else {
o[key] = [o[key], {}]
}
// we want to update the empty object at the end of the o[key] array, so set o to that object
o = o[key][o[key].length - 1]
} else {
o = o[key]
}
})
var key = keys[keys.length - 1]
var isTypeArray = checkAllAliases(keys.join('.'), flags.arrays)
var isValueArray = Array.isArray(value)
var duplicate = configuration['duplicate-arguments-array']
// nargs has higher priority than duplicate
if (!duplicate && checkAllAliases(key, flags.nargs)) {
duplicate = true
if ((!isUndefined(o[key]) && flags.nargs[key] === 1) || (Array.isArray(o[key]) && o[key].length === flags.nargs[key])) {
o[key] = undefined
}
}
if (value === increment) {
o[key] = increment(o[key])
} else if (Array.isArray(o[key])) {
if (duplicate && isTypeArray && isValueArray) {
o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : (Array.isArray(o[key][0]) ? o[key] : [o[key]]).concat([value])
} else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) {
o[key] = value
} else {
o[key] = o[key].concat([value])
}
} else if (o[key] === undefined && isTypeArray) {
o[key] = isValueArray ? value : [value]
} else if (duplicate && !(o[key] === undefined || checkAllAliases(key, flags.counts))) {
o[key] = [ o[key], value ]
} else {
o[key] = value
}
}
// extend the aliases list with inferred aliases.
function extendAliases (...args) {
args.forEach(function (obj) {
Object.keys(obj || {}).forEach(function (key) {
// short-circuit if we've already added a key
// to the aliases array, for example it might
// exist in both 'opts.default' and 'opts.key'.
if (flags.aliases[key]) return
flags.aliases[key] = [].concat(aliases[key] || [])
// For "--option-name", also set argv.optionName
flags.aliases[key].concat(key).forEach(function (x) {
if (/-/.test(x) && configuration['camel-case-expansion']) {
var c = camelCase(x)
if (c !== key && flags.aliases[key].indexOf(c) === -1) {
flags.aliases[key].push(c)
newAliases[c] = true
}
}
})
// For "--optionName", also set argv['option-name']
flags.aliases[key].concat(key).forEach(function (x) {
if (x.length > 1 && /[A-Z]/.test(x) && configuration['camel-case-expansion']) {
var c = decamelize(x, '-')
if (c !== key && flags.aliases[key].indexOf(c) === -1) {
flags.aliases[key].push(c)
newAliases[c] = true
}
}
})
flags.aliases[key].forEach(function (x) {
flags.aliases[x] = [key].concat(flags.aliases[key].filter(function (y) {
return x !== y
}))
})
})
})
}
// check if a flag is set for any of a key's aliases.
function checkAllAliases (key, flag) {
var isSet = false
var toCheck = [].concat(flags.aliases[key] || [], key)
toCheck.forEach(function (key) {
if (flag.hasOwnProperty(key)) isSet = flag[key]
})
return isSet
}
function hasAnyFlag (key) {
// XXX Switch to [].concat(...Object.values(flags)) once node.js 6 is dropped
var toCheck = [].concat(...Object.keys(flags).map(k => flags[k]))
return toCheck.some(function (flag) {
return flag[key]
})
}
function hasFlagsMatching (arg, ...patterns) {
var toCheck = [].concat(...patterns)
return toCheck.some(function (pattern) {
var match = arg.match(pattern)
return match && hasAnyFlag(match[1])
})
}
// based on a simplified version of the short flag group parsing logic
function hasAllShortFlags (arg) {
// if this is a negative number, or doesn't start with a single hyphen, it's not a short flag group
if (arg.match(negative) || !arg.match(/^-[^-]+/)) { return false }
var hasAllFlags = true
var letters = arg.slice(1).split('')
var next
for (var j = 0; j < letters.length; j++) {
next = arg.slice(j + 2)
if (!hasAnyFlag(letters[j])) {
hasAllFlags = false
break
}
if ((letters[j + 1] && letters[j + 1] === '=') ||
next === '-' ||
(/[A-Za-z]/.test(letters[j]) && /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) ||
(letters[j + 1] && letters[j + 1].match(/\W/))) {
break
}
}
return hasAllFlags
}
function isUnknownOptionAsArg (arg) {
return configuration['unknown-options-as-args'] && isUnknownOption(arg)
}
function isUnknownOption (arg) {
// ignore negative numbers
if (arg.match(negative)) { return false }
// if this is a short option group and all of them are configured, it isn't unknown
if (hasAllShortFlags(arg)) { return false }
// e.g. '--count=2'
const flagWithEquals = /^-+([^=]+?)=[\s\S]*$/
// e.g. '-a' or '--arg'
const normalFlag = /^-+([^=]+?)$/
// e.g. '-a-'
const flagEndingInHyphen = /^-+([^=]+?)-$/
// e.g. '-abc123'
const flagEndingInDigits = /^-+([^=]+?)\d+$/
// e.g. '-a/usr/local'
const flagEndingInNonWordCharacters = /^-+([^=]+?)\W+.*$/
// check the different types of flag styles, including negatedBoolean, a pattern defined near the start of the parse method
return !hasFlagsMatching(arg, flagWithEquals, negatedBoolean, normalFlag, flagEndingInHyphen, flagEndingInDigits, flagEndingInNonWordCharacters)
}
// make a best effor to pick a default value
// for an option based on name and type.
function defaultValue (key) {
if (!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts) &&
`${key}` in defaults) {
return defaults[key]
} else {
return defaultForType(guessType(key))
}
}
// return a default value, given the type of a flag.,
// e.g., key of type 'string' will default to '', rather than 'true'.
function defaultForType (type) {
var def = {
boolean: true,
string: '',
number: undefined,
array: []
}
return def[type]
}
// given a flag, enforce a default type.
function guessType (key) {
var type = 'boolean'
if (checkAllAliases(key, flags.strings)) type = 'string'
else if (checkAllAliases(key, flags.numbers)) type = 'number'
else if (checkAllAliases(key, flags.bools)) type = 'boolean'
else if (checkAllAliases(key, flags.arrays)) type = 'array'
return type
}
function isNumber (x) {
if (x === null || x === undefined) return false
// if loaded from config, may already be a number.
if (typeof x === 'number') return true
// hexadecimal.
if (/^0x[0-9a-f]+$/i.test(x)) return true
// don't treat 0123 as a number; as it drops the leading '0'.
if (x.length > 1 && x[0] === '0') return false
return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
}
function isUndefined (num) {
return num === undefined
}
return {
argv: argv,
error: error,
aliases: flags.aliases,
newAliases: newAliases,
configuration: configuration
}
}
// if any aliases reference each other, we should
// merge them together.
function combineAliases (aliases) {
var aliasArrays = []
var change = true
var combined = {}
// turn alias lookup hash {key: ['alias1', 'alias2']} into
// a simple array ['key', 'alias1', 'alias2']
Object.keys(aliases).forEach(function (key) {
aliasArrays.push(
[].concat(aliases[key], key)
)
})
// combine arrays until zero changes are
// made in an iteration.
while (change) {
change = false
for (var i = 0; i < aliasArrays.length; i++) {
for (var ii = i + 1; ii < aliasArrays.length; ii++) {
var intersect = aliasArrays[i].filter(function (v) {
return aliasArrays[ii].indexOf(v) !== -1
})
if (intersect.length) {
aliasArrays[i] = aliasArrays[i].concat(aliasArrays[ii])
aliasArrays.splice(ii, 1)
change = true
break
}
}
}
}
// map arrays back to the hash-lookup (de-dupe while
// we're at it).
aliasArrays.forEach(function (aliasArray) {
aliasArray = aliasArray.filter(function (v, i, self) {
return self.indexOf(v) === i
})
combined[aliasArray.pop()] = aliasArray
})
return combined
}
// this function should only be called when a count is given as an arg
// it is NOT called to set a default value
// thus we can start the count at 1 instead of 0
function increment (orig) {
return orig !== undefined ? orig + 1 : 1
}
function Parser (args, opts) {
var result = parse(args.slice(), opts)
return result.argv
}
// parse arguments and return detailed
// meta information, aliases, etc.
Parser.detailed = function (args, opts) {
return parse(args.slice(), opts)
}
module.exports = Parser
// take an un-split argv string and tokenize it.
module.exports = function (argString) {
if (Array.isArray(argString)) {
return argString.map(e => typeof e !== 'string' ? e + '' : e)
}
argString = argString.trim()
var i = 0
var prevC = null
var c = null
var opening = null
var args = []
for (var ii = 0; ii < argString.length; ii++) {
prevC = c
c = argString.charAt(ii)
// split on spaces unless we're in quotes.
if (c === ' ' && !opening) {
if (!(prevC === ' ')) {
i++
}
continue
}
// don't split the string if we're in matching
// opening or closing single and double quotes.
if (c === opening) {
opening = null
} else if ((c === "'" || c === '"') && !opening) {
opening = c
}
if (!args[i]) args[i] = ''
args[i] += c
}
return args
}
{
"_from": "yargs-parser@^15.0.0",
"_id": "yargs-parser@15.0.0",
"_inBundle": false,
"_integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
"_location": "/yargs/yargs-parser",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "yargs-parser@^15.0.0",
"name": "yargs-parser",
"escapedName": "yargs-parser",
"rawSpec": "^15.0.0",
"saveSpec": null,
"fetchSpec": "^15.0.0"
},
"_requiredBy": [
"/yargs"
],
"_resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
"_shasum": "cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08",
"_spec": "yargs-parser@^15.0.0",
"_where": "C:\\Users\\thequ\\Documents\\Mynij\\Mynij-unit-tests\\node_modules\\yargs",
"author": {
"name": "Ben Coe",
"email": "ben@npmjs.com"
},
"bugs": {
"url": "https://github.com/yargs/yargs-parser/issues"
},
"bundleDependencies": false,
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"deprecated": false,
"description": "the mighty option parser used by yargs",
"devDependencies": {
"chai": "^4.2.0",
"coveralls": "^3.0.2",
"mocha": "^5.2.0",
"nyc": "^14.1.0",
"standard": "^12.0.1",
"standard-version": "^6.0.0"
},
"engine": {
"node": ">=6"
},
"files": [
"lib",
"index.js"
],
"homepage": "https://github.com/yargs/yargs-parser#readme",
"keywords": [
"argument",
"parser",
"yargs",
"command",
"cli",
"parsing",
"option",
"args",
"argument"
],
"license": "ISC",
"main": "index.js",
"name": "yargs-parser",
"repository": {
"url": "git+ssh://git@github.com/yargs/yargs-parser.git"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"posttest": "standard",
"release": "standard-version",
"test": "nyc mocha test/*.js"
},
"version": "15.0.0"
}
{
"_from": "yargs",
"_id": "yargs@14.0.0",
"_from": "yargs@14.2.0",
"_id": "yargs@14.2.0",
"_inBundle": false,
"_integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==",
"_integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==",
"_location": "/yargs",
"_phantomChildren": {},
"_phantomChildren": {
"camelcase": "5.3.1",
"decamelize": "1.2.0"
},
"_requested": {
"type": "tag",
"type": "version",
"registry": true,
"raw": "yargs",
"raw": "yargs@14.2.0",
"name": "yargs",
"escapedName": "yargs",
"rawSpec": "",
"rawSpec": "14.2.0",
"saveSpec": null,
"fetchSpec": "latest"
"fetchSpec": "14.2.0"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz",
"_shasum": "ba4cacc802b3c0b3e36a9e791723763d57a85066",
"_spec": "yargs",
"_resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz",
"_shasum": "f116a9242c4ed8668790b40759b4906c276e76c3",
"_spec": "yargs@14.2.0",
"_where": "C:\\Users\\thequ\\Documents\\Mynij\\Mynij-unit-tests",
"bugs": {
"url": "https://github.com/yargs/yargs/issues"
......@@ -44,7 +47,7 @@
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.1"
"yargs-parser": "^15.0.0"
},
"deprecated": false,
"description": "yargs the modern, pirate-themed, successor to optimist.",
......@@ -104,5 +107,5 @@
"**/example/**"
]
},
"version": "14.0.0"
"version": "14.2.0"
}
......@@ -94,14 +94,17 @@ function Yargs (processArgs, cwd, parentRequire) {
})
})
// preserve all groups not set to local.
preservedGroups = Object.keys(groups).reduce((acc, groupName) => {
const keys = groups[groupName].filter(key => !(key in localLookup))
if (keys.length > 0) {
acc[groupName] = keys
}
return acc
}, {})
// add all groups not set to local to preserved groups
Object.assign(
preservedGroups,
Object.keys(groups).reduce((acc, groupName) => {
const keys = groups[groupName].filter(key => !(key in localLookup))
if (keys.length > 0) {
acc[groupName] = keys
}
return acc
}, {})
)
// groups can now be reset
groups = {}
......@@ -330,7 +333,7 @@ function Yargs (processArgs, cwd, parentRequire) {
argsert('[object|string] [string|function] [function]', [key, msg, parseFn], arguments.length)
// allow a config object to be provided directly.
if (typeof key === 'object') {
key = applyExtends(key, cwd)
key = applyExtends(key, cwd, self.getParserConfiguration()['deep-merge-config'])
options.configObjects = (options.configObjects || []).concat(key)
return self
}
......@@ -504,7 +507,7 @@ function Yargs (processArgs, cwd, parentRequire) {
// If an object exists in the key, add it to options.configObjects
if (obj[key] && typeof obj[key] === 'object') {
conf = applyExtends(obj[key], rootPath || cwd)
conf = applyExtends(obj[key], rootPath || cwd, self.getParserConfiguration()['deep-merge-config'])
options.configObjects = (options.configObjects || []).concat(conf)
}
......@@ -544,10 +547,12 @@ function Yargs (processArgs, cwd, parentRequire) {
argsert('[string|array] [function|boolean|object] [function]', [args, shortCircuit, _parseFn], arguments.length)
freeze()
if (typeof args === 'undefined') {
const parsed = self._parseArgs(processArgs)
const argv = self._parseArgs(processArgs)
const tmpParsed = self.parsed
unfreeze()
// TODO: remove this compatibility hack when we release yargs@15.x:
return (this.parsed = parsed)
self.parsed = tmpParsed
return argv
}
// a context object can optionally be provided, this allows
......@@ -923,8 +928,7 @@ function Yargs (processArgs, cwd, parentRequire) {
self.showCompletionScript = function ($0, cmd) {
argsert('[string] [string]', [$0, cmd], arguments.length)
$0 = $0 || self.$0
completionCommand = cmd || completionCommand || 'completion'
_logger.log(completion.generateCompletionScript($0, completionCommand))
_logger.log(completion.generateCompletionScript($0, cmd || completionCommand || 'completion'))
return self
}
......
......@@ -184,6 +184,14 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-port": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-5.0.0.tgz",
"integrity": "sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ==",
"requires": {
"type-fest": "^0.3.0"
}
},
"glob": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
......@@ -431,9 +439,9 @@
}
},
"systeminformation": {
"version": "4.14.11",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.14.11.tgz",
"integrity": "sha512-KlMaQQftyGUPjKzGRrATN5mpKrpdtrVk/KPuqPeu733bUgpokIhevg5zjKOb4Gur91XKdbdQCCja/oFsg5R4Dw=="
"version": "4.14.17",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.14.17.tgz",
"integrity": "sha512-CQbT5vnkqNb3JNl41xr8sYA8AX7GoaWP55/jnmFNQY0XQmUuoFshSNUkCkxiDdEC1qu2Vg9s0jR6LLmVSmNJUw=="
},
"tmp": {
"version": "0.1.0",
......@@ -443,6 +451,11 @@
"rimraf": "^2.6.3"
}
},
"type-fest": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
"integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ=="
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
......@@ -487,9 +500,9 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
},
"yargs": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz",
"integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==",
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz",
"integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==",
"requires": {
"cliui": "^5.0.0",
"decamelize": "^1.2.0",
......@@ -501,7 +514,18 @@
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.1"
"yargs-parser": "^15.0.0"
},
"dependencies": {
"yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"yargs-parser": {
......
100,3.61
1000,34.637
5000,174.397
10000,298.66
var childProcess = require('child_process');
const fs = require('fs');
var stream = fs.createWriteStream("./results/rss.csv", {flags:'a'});
// function runScript(scriptPath, args, callback) {
// var invoked = false,
// process = childProcess.fork(scriptPath, args);
// process.on('message', function (mes){
// console.log("Message from child : " + mes);
// });
// process.on('error', function (err) {
// if (invoked) return;
// invoked = true;
// callback(err);
// });
// process.on('exit', function (code) {
// if (invoked) return;
// invoked = true;
// var err = code === 0 ? null : new Error('exit code ' + code);
// callback(err);
// });
// }
function writeResult(items, time){
stream.write(items + "," + time + "\n");
}
function runScriptSync(list, callback) {
if (list.length === 0) return;
var invoked = false,
to_run = list.pop();
process = childProcess.fork(to_run.scriptPath, to_run.args);
process.on('message', function (mes){
console.log(to_run.amount + " : " + mes)
writeResult(to_run.amount, mes);
runScriptSync(list, callback);
});
process.on('error', function (err) {
if (invoked) return;
invoked = true;
callback(err);
});
process.on('exit', function (code) {
if (invoked) return;
invoked = true;
var err = code === 0 ? null : new Error('exit code ' + code);
callback(err);
});
}
var to_run = [{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_100000.xml"], amount : 100000},
{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_50000.xml"], amount : 50000},
{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_10000.xml"], amount : 10000},
{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_5000.xml"], amount : 5000},
{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_1000.xml"], amount : 1000},
{scriptPath : './add_rss.js', args : ['-f' ,"./test_files/RSS/rss_100.xml"], amount : 100}];
runScriptSync(to_run, function (err) {if (err) throw err;});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment