Can now send links, do some string formatting, send newlines, organised chats more. Updated the readme
This commit is contained in:
parent
245bf4e418
commit
c63a625a0a
|
@ -1 +1,3 @@
|
|||
profiles.json
|
||||
key.pub
|
||||
key
|
||||
|
|
|
@ -14,3 +14,12 @@ An open source chat client
|
|||
- atob
|
||||
- btoa
|
||||
- child_process
|
||||
- showdown
|
||||
- open
|
||||
|
||||
# Chat formatting
|
||||
- Bold: `*`
|
||||
- Italic: `_`
|
||||
- Strikethrough: `~`
|
||||
- Underline: `-`
|
||||
- Code: <code>`</code>
|
||||
|
|
11
index.html
11
index.html
|
@ -3,11 +3,20 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Chat Client</title>
|
||||
|
||||
<!-- Insert this line above script imports -->
|
||||
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
|
||||
|
||||
<script src="scripts/jquery-3.3.1.min.js"></script>
|
||||
<script src="scripts/include.js"></script>
|
||||
<script src="scripts/profiles.js"></script>
|
||||
<script src="scripts/communications.js"></script>
|
||||
<script src="scripts/scripts.js"></script>
|
||||
<script src="scripts/jquery-3.3.1.min.js"></script>
|
||||
<script src="scripts/formatting.js"></script>
|
||||
|
||||
<!-- Insert this line after script imports -->
|
||||
<script>if (window.module) module = window.module;</script>
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../mime/cli.js
|
|
@ -0,0 +1 @@
|
|||
../showdown/bin/showdown.js
|
|
@ -0,0 +1 @@
|
|||
../which/bin/which
|
|
@ -1,146 +0,0 @@
|
|||
CircularJSON
|
||||
============
|
||||
|
||||
[![donate](https://img.shields.io/badge/$-donate-ff69b4.svg?maxAge=2592000&style=flat)](https://github.com/WebReflection/donate) ![Downloads](https://img.shields.io/npm/dm/circular-json.svg) [![Build Status](https://travis-ci.org/WebReflection/circular-json.svg?branch=master)](https://travis-ci.org/WebReflection/circular-json) [![Coverage Status](https://coveralls.io/repos/github/WebReflection/circular-json/badge.svg?branch=master)](https://coveralls.io/github/WebReflection/circular-json?branch=master)
|
||||
|
||||
Serializes and deserializes otherwise valid JSON objects containing circular references into and from a specialized JSON format.
|
||||
|
||||
- - -
|
||||
|
||||
## The future of this module is called [flatted](https://github.com/WebReflection/flatted#flatted)
|
||||
|
||||
Smaller, faster, and able to produce on average a reduced output too, [flatted](https://github.com/WebReflection/flatted#flatted) is the new, bloatless, ESM and CJS compatible, circular JSON parser.
|
||||
|
||||
It has now reached V1 and it implements the exact same JSON API.
|
||||
|
||||
Please note **CircularJSON is in maintenance only** and **[flatted](https://github.com/WebReflection/flatted#flatted) is its successor**.
|
||||
|
||||
- - -
|
||||
|
||||
### A Working Solution To A Common Problem
|
||||
A usage example:
|
||||
|
||||
```JavaScript
|
||||
var object = {};
|
||||
object.arr = [
|
||||
object, object
|
||||
];
|
||||
object.arr.push(object.arr);
|
||||
object.obj = object;
|
||||
|
||||
var serialized = CircularJSON.stringify(object);
|
||||
// '{"arr":["~","~","~arr"],"obj":"~"}'
|
||||
// NOTE: CircularJSON DOES NOT parse JS
|
||||
// it handles receiver and reviver callbacks
|
||||
|
||||
var unserialized = CircularJSON.parse(serialized);
|
||||
// { arr: [ [Circular], [Circular] ],
|
||||
// obj: [Circular] }
|
||||
|
||||
unserialized.obj === unserialized;
|
||||
unserialized.arr[0] === unserialized;
|
||||
unserialized.arr.pop() === unserialized.arr;
|
||||
```
|
||||
|
||||
A quick summary:
|
||||
|
||||
* **new** in version `0.5`, you can specify a JSON parser different from JSON itself. `CircularJSON.parser = ABetterJSON;` is all you need.
|
||||
* uses `~` as a special prefix symbol to denote which parent the reference belongs to (i.e. `~root~child1~child2`)
|
||||
* reasonably fast in both serialization and deserialization
|
||||
* compact serialization for easier and slimmer transportation across environments
|
||||
* [tested and covered](test/circular-json.js) over nasty structures too
|
||||
* compatible with all JavaScript engines
|
||||
|
||||
Node Installation & Usage
|
||||
============
|
||||
|
||||
```bash
|
||||
npm install --save circular-json
|
||||
```
|
||||
|
||||
```javascript
|
||||
'use strict';
|
||||
|
||||
var
|
||||
CircularJSON = require('circular-json'),
|
||||
obj = { foo: 'bar' },
|
||||
str
|
||||
;
|
||||
|
||||
obj.self = obj;
|
||||
str = CircularJSON.stringify(obj);
|
||||
```
|
||||
|
||||
There are no dependencies.
|
||||
|
||||
Browser Installation & Usage
|
||||
================
|
||||
|
||||
* Global: <build/circular-json.js>
|
||||
* AMD: <build/circular-json.amd.js>
|
||||
* CommonJS: <build/circular-json.node.js>
|
||||
|
||||
(generated via [gitstrap](https://github.com/WebReflection/gitstrap))
|
||||
|
||||
```html
|
||||
<script src="build/circular-json.js"></script>
|
||||
```
|
||||
|
||||
```javascript
|
||||
'use strict';
|
||||
|
||||
var CircularJSON = window.CircularJSON
|
||||
, obj = { foo: 'bar' }
|
||||
, str
|
||||
;
|
||||
|
||||
obj.self = obj;
|
||||
str = CircularJSON.stringify(obj);
|
||||
```
|
||||
|
||||
NOTE: Platforms without native JSON (i.e. MSIE <= 8) requires `json3.js` or similar.
|
||||
|
||||
It is also *a bad idea* to `CircularJSON.parse(JSON.stringify(object))` because of those manipulation used in `CircularJSON.stringify()` able to make parsing safe and secure.
|
||||
|
||||
As summary: `CircularJSON.parse(CircularJSON.stringify(object))` is the way to go, same is for `JSON.parse(JSON.stringify(object))`.
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
It's the same as native JSON, except the fourth parameter `placeholder`, which circular references to be replaced with `"[Circular]"` (i.e. for logging).
|
||||
|
||||
* CircularJSON.stringify(object, replacer, spacer, placeholder)
|
||||
* CircularJSON.parse(string, reviver)
|
||||
|
||||
Bear in mind `JSON.parse(CircularJSON.stringify(object))` will work but not produce the expected output.
|
||||
|
||||
Similar Libraries
|
||||
=======
|
||||
|
||||
### Why Not the [@izs](https://twitter.com/izs) One
|
||||
The module [json-stringify-safe](https://github.com/isaacs/json-stringify-safe) seems to be for `console.log()` but it's completely pointless for `JSON.parse()`, being latter one unable to retrieve back the initial structure. Here an example:
|
||||
|
||||
```JavaScript
|
||||
// a logged object with circular references
|
||||
{
|
||||
"circularRef": "[Circular]",
|
||||
"list": [
|
||||
"[Circular]",
|
||||
"[Circular]"
|
||||
]
|
||||
}
|
||||
// what do we do with above output ?
|
||||
```
|
||||
|
||||
Just type this in your `node` console: `var o = {}; o.a = o; console.log(o);`. The output will be `{ a: [Circular] }` ... good, but that ain't really solving the problem.
|
||||
|
||||
However, if that's all you need, the function used to create that kind of output is probably faster than `CircularJSON` and surely fits in less lines of code.
|
||||
|
||||
|
||||
### Why Not {{put random name}} Solution
|
||||
So here the thing: circular references can be wrong but, if there is a need for them, any attempt to ignore them or remove them can be considered just a failure.
|
||||
|
||||
Not because the method is bad or it's not working, simply because the circular info, the one we needed and used in the first place, is lost!
|
||||
|
||||
In this case, `CircularJSON` does even more than just solve circular and recursions: it maps all same objects so that less memory is used as well on deserialization as less bandwidth too!
|
||||
It's able to redefine those references back later on so the way we store is the way we retrieve and in a reasonably performant way, also trusting the snappy and native `JSON` methods to iterate.
|
|
@ -1,2 +0,0 @@
|
|||
/*! (C) WebReflection Mit Style License */
|
||||
var CircularJSON=function(JSON,RegExp){var specialChar="~",safeSpecialChar="\\x"+("0"+specialChar.charCodeAt(0).toString(16)).slice(-2),escapedSafeSpecialChar="\\"+safeSpecialChar,specialCharRG=new RegExp(safeSpecialChar,"g"),safeSpecialCharRG=new RegExp(escapedSafeSpecialChar,"g"),safeStartWithSpecialCharRG=new RegExp("(?:^|([^\\\\]))"+escapedSafeSpecialChar),indexOf=[].indexOf||function(v){for(var i=this.length;i--&&this[i]!==v;);return i},$String=String;function generateReplacer(value,replacer,resolve){var doNotIgnore=false,inspect=!!replacer,path=[],all=[value],seen=[value],mapp=[resolve?specialChar:"[Circular]"],last=value,lvl=1,i,fn;if(inspect){fn=typeof replacer==="object"?function(key,value){return key!==""&&replacer.indexOf(key)<0?void 0:value}:replacer}return function(key,value){if(inspect)value=fn.call(this,key,value);if(doNotIgnore){if(last!==this){i=lvl-indexOf.call(all,this)-1;lvl-=i;all.splice(lvl,all.length);path.splice(lvl-1,path.length);last=this}if(typeof value==="object"&&value){if(indexOf.call(all,value)<0){all.push(last=value)}lvl=all.length;i=indexOf.call(seen,value);if(i<0){i=seen.push(value)-1;if(resolve){path.push((""+key).replace(specialCharRG,safeSpecialChar));mapp[i]=specialChar+path.join(specialChar)}else{mapp[i]=mapp[0]}}else{value=mapp[i]}}else{if(typeof value==="string"&&resolve){value=value.replace(safeSpecialChar,escapedSafeSpecialChar).replace(specialChar,safeSpecialChar)}}}else{doNotIgnore=true}return value}}function retrieveFromPath(current,keys){for(var i=0,length=keys.length;i<length;current=current[keys[i++].replace(safeSpecialCharRG,specialChar)]);return current}function generateReviver(reviver){return function(key,value){var isString=typeof value==="string";if(isString&&value.charAt(0)===specialChar){return new $String(value.slice(1))}if(key==="")value=regenerate(value,value,{});if(isString)value=value.replace(safeStartWithSpecialCharRG,"$1"+specialChar).replace(escapedSafeSpecialChar,safeSpecialChar);return reviver?reviver.call(this,key,value):value}}function regenerateArray(root,current,retrieve){for(var i=0,length=current.length;i<length;i++){current[i]=regenerate(root,current[i],retrieve)}return current}function regenerateObject(root,current,retrieve){for(var key in current){if(current.hasOwnProperty(key)){current[key]=regenerate(root,current[key],retrieve)}}return current}function regenerate(root,current,retrieve){return current instanceof Array?regenerateArray(root,current,retrieve):current instanceof $String?current.length?retrieve.hasOwnProperty(current)?retrieve[current]:retrieve[current]=retrieveFromPath(root,current.split(specialChar)):root:current instanceof Object?regenerateObject(root,current,retrieve):current}var CircularJSON={stringify:function stringify(value,replacer,space,doNotResolve){return CircularJSON.parser.stringify(value,generateReplacer(value,replacer,!doNotResolve),space)},parse:function parse(text,reviver){return CircularJSON.parser.parse(text,generateReviver(reviver))},parser:JSON};return CircularJSON}(JSON,RegExp);
|
|
@ -1,210 +0,0 @@
|
|||
/*!
|
||||
Copyright (C) 2013-2017 by Andrea Giammarchi - @WebReflection
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
var CircularJSON = (function(JSON, RegExp){
|
||||
var
|
||||
// should be a not so common char
|
||||
// possibly one JSON does not encode
|
||||
// possibly one encodeURIComponent does not encode
|
||||
// right now this char is '~' but this might change in the future
|
||||
specialChar = '~',
|
||||
safeSpecialChar = '\\x' + (
|
||||
'0' + specialChar.charCodeAt(0).toString(16)
|
||||
).slice(-2),
|
||||
escapedSafeSpecialChar = '\\' + safeSpecialChar,
|
||||
specialCharRG = new RegExp(safeSpecialChar, 'g'),
|
||||
safeSpecialCharRG = new RegExp(escapedSafeSpecialChar, 'g'),
|
||||
|
||||
safeStartWithSpecialCharRG = new RegExp('(?:^|([^\\\\]))' + escapedSafeSpecialChar),
|
||||
|
||||
indexOf = [].indexOf || function(v){
|
||||
for(var i=this.length;i--&&this[i]!==v;);
|
||||
return i;
|
||||
},
|
||||
$String = String // there's no way to drop warnings in JSHint
|
||||
// about new String ... well, I need that here!
|
||||
// faked, and happy linter!
|
||||
;
|
||||
|
||||
function generateReplacer(value, replacer, resolve) {
|
||||
var
|
||||
doNotIgnore = false,
|
||||
inspect = !!replacer,
|
||||
path = [],
|
||||
all = [value],
|
||||
seen = [value],
|
||||
mapp = [resolve ? specialChar : '[Circular]'],
|
||||
last = value,
|
||||
lvl = 1,
|
||||
i, fn
|
||||
;
|
||||
if (inspect) {
|
||||
fn = typeof replacer === 'object' ?
|
||||
function (key, value) {
|
||||
return key !== '' && replacer.indexOf(key) < 0 ? void 0 : value;
|
||||
} :
|
||||
replacer;
|
||||
}
|
||||
return function(key, value) {
|
||||
// the replacer has rights to decide
|
||||
// if a new object should be returned
|
||||
// or if there's some key to drop
|
||||
// let's call it here rather than "too late"
|
||||
if (inspect) value = fn.call(this, key, value);
|
||||
|
||||
// first pass should be ignored, since it's just the initial object
|
||||
if (doNotIgnore) {
|
||||
if (last !== this) {
|
||||
i = lvl - indexOf.call(all, this) - 1;
|
||||
lvl -= i;
|
||||
all.splice(lvl, all.length);
|
||||
path.splice(lvl - 1, path.length);
|
||||
last = this;
|
||||
}
|
||||
// console.log(lvl, key, path);
|
||||
if (typeof value === 'object' && value) {
|
||||
// if object isn't referring to parent object, add to the
|
||||
// object path stack. Otherwise it is already there.
|
||||
if (indexOf.call(all, value) < 0) {
|
||||
all.push(last = value);
|
||||
}
|
||||
lvl = all.length;
|
||||
i = indexOf.call(seen, value);
|
||||
if (i < 0) {
|
||||
i = seen.push(value) - 1;
|
||||
if (resolve) {
|
||||
// key cannot contain specialChar but could be not a string
|
||||
path.push(('' + key).replace(specialCharRG, safeSpecialChar));
|
||||
mapp[i] = specialChar + path.join(specialChar);
|
||||
} else {
|
||||
mapp[i] = mapp[0];
|
||||
}
|
||||
} else {
|
||||
value = mapp[i];
|
||||
}
|
||||
} else {
|
||||
if (typeof value === 'string' && resolve) {
|
||||
// ensure no special char involved on deserialization
|
||||
// in this case only first char is important
|
||||
// no need to replace all value (better performance)
|
||||
value = value .replace(safeSpecialChar, escapedSafeSpecialChar)
|
||||
.replace(specialChar, safeSpecialChar);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doNotIgnore = true;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
function retrieveFromPath(current, keys) {
|
||||
for(var i = 0, length = keys.length; i < length; current = current[
|
||||
// keys should be normalized back here
|
||||
keys[i++].replace(safeSpecialCharRG, specialChar)
|
||||
]);
|
||||
return current;
|
||||
}
|
||||
|
||||
function generateReviver(reviver) {
|
||||
return function(key, value) {
|
||||
var isString = typeof value === 'string';
|
||||
if (isString && value.charAt(0) === specialChar) {
|
||||
return new $String(value.slice(1));
|
||||
}
|
||||
if (key === '') value = regenerate(value, value, {});
|
||||
// again, only one needed, do not use the RegExp for this replacement
|
||||
// only keys need the RegExp
|
||||
if (isString) value = value .replace(safeStartWithSpecialCharRG, '$1' + specialChar)
|
||||
.replace(escapedSafeSpecialChar, safeSpecialChar);
|
||||
return reviver ? reviver.call(this, key, value) : value;
|
||||
};
|
||||
}
|
||||
|
||||
function regenerateArray(root, current, retrieve) {
|
||||
for (var i = 0, length = current.length; i < length; i++) {
|
||||
current[i] = regenerate(root, current[i], retrieve);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function regenerateObject(root, current, retrieve) {
|
||||
for (var key in current) {
|
||||
if (current.hasOwnProperty(key)) {
|
||||
current[key] = regenerate(root, current[key], retrieve);
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function regenerate(root, current, retrieve) {
|
||||
return current instanceof Array ?
|
||||
// fast Array reconstruction
|
||||
regenerateArray(root, current, retrieve) :
|
||||
(
|
||||
current instanceof $String ?
|
||||
(
|
||||
// root is an empty string
|
||||
current.length ?
|
||||
(
|
||||
retrieve.hasOwnProperty(current) ?
|
||||
retrieve[current] :
|
||||
retrieve[current] = retrieveFromPath(
|
||||
root, current.split(specialChar)
|
||||
)
|
||||
) :
|
||||
root
|
||||
) :
|
||||
(
|
||||
current instanceof Object ?
|
||||
// dedicated Object parser
|
||||
regenerateObject(root, current, retrieve) :
|
||||
// value as it is
|
||||
current
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
var CircularJSON = {
|
||||
stringify: function stringify(value, replacer, space, doNotResolve) {
|
||||
return CircularJSON.parser.stringify(
|
||||
value,
|
||||
generateReplacer(value, replacer, !doNotResolve),
|
||||
space
|
||||
);
|
||||
},
|
||||
parse: function parse(text, reviver) {
|
||||
return CircularJSON.parser.parse(
|
||||
text,
|
||||
generateReviver(reviver)
|
||||
);
|
||||
},
|
||||
// A parser should be an API 1:1 compatible with JSON
|
||||
// it should expose stringify and parse methods.
|
||||
// The default parser is the native JSON.
|
||||
parser: JSON
|
||||
};
|
||||
|
||||
return CircularJSON;
|
||||
|
||||
}(JSON, RegExp));
|
|
@ -1,207 +0,0 @@
|
|||
/*!
|
||||
Copyright (C) 2013-2017 by Andrea Giammarchi - @WebReflection
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
var
|
||||
// should be a not so common char
|
||||
// possibly one JSON does not encode
|
||||
// possibly one encodeURIComponent does not encode
|
||||
// right now this char is '~' but this might change in the future
|
||||
specialChar = '~',
|
||||
safeSpecialChar = '\\x' + (
|
||||
'0' + specialChar.charCodeAt(0).toString(16)
|
||||
).slice(-2),
|
||||
escapedSafeSpecialChar = '\\' + safeSpecialChar,
|
||||
specialCharRG = new RegExp(safeSpecialChar, 'g'),
|
||||
safeSpecialCharRG = new RegExp(escapedSafeSpecialChar, 'g'),
|
||||
|
||||
safeStartWithSpecialCharRG = new RegExp('(?:^|([^\\\\]))' + escapedSafeSpecialChar),
|
||||
|
||||
indexOf = [].indexOf || function(v){
|
||||
for(var i=this.length;i--&&this[i]!==v;);
|
||||
return i;
|
||||
},
|
||||
$String = String // there's no way to drop warnings in JSHint
|
||||
// about new String ... well, I need that here!
|
||||
// faked, and happy linter!
|
||||
;
|
||||
|
||||
function generateReplacer(value, replacer, resolve) {
|
||||
var
|
||||
doNotIgnore = false,
|
||||
inspect = !!replacer,
|
||||
path = [],
|
||||
all = [value],
|
||||
seen = [value],
|
||||
mapp = [resolve ? specialChar : '[Circular]'],
|
||||
last = value,
|
||||
lvl = 1,
|
||||
i, fn
|
||||
;
|
||||
if (inspect) {
|
||||
fn = typeof replacer === 'object' ?
|
||||
function (key, value) {
|
||||
return key !== '' && replacer.indexOf(key) < 0 ? void 0 : value;
|
||||
} :
|
||||
replacer;
|
||||
}
|
||||
return function(key, value) {
|
||||
// the replacer has rights to decide
|
||||
// if a new object should be returned
|
||||
// or if there's some key to drop
|
||||
// let's call it here rather than "too late"
|
||||
if (inspect) value = fn.call(this, key, value);
|
||||
|
||||
// first pass should be ignored, since it's just the initial object
|
||||
if (doNotIgnore) {
|
||||
if (last !== this) {
|
||||
i = lvl - indexOf.call(all, this) - 1;
|
||||
lvl -= i;
|
||||
all.splice(lvl, all.length);
|
||||
path.splice(lvl - 1, path.length);
|
||||
last = this;
|
||||
}
|
||||
// console.log(lvl, key, path);
|
||||
if (typeof value === 'object' && value) {
|
||||
// if object isn't referring to parent object, add to the
|
||||
// object path stack. Otherwise it is already there.
|
||||
if (indexOf.call(all, value) < 0) {
|
||||
all.push(last = value);
|
||||
}
|
||||
lvl = all.length;
|
||||
i = indexOf.call(seen, value);
|
||||
if (i < 0) {
|
||||
i = seen.push(value) - 1;
|
||||
if (resolve) {
|
||||
// key cannot contain specialChar but could be not a string
|
||||
path.push(('' + key).replace(specialCharRG, safeSpecialChar));
|
||||
mapp[i] = specialChar + path.join(specialChar);
|
||||
} else {
|
||||
mapp[i] = mapp[0];
|
||||
}
|
||||
} else {
|
||||
value = mapp[i];
|
||||
}
|
||||
} else {
|
||||
if (typeof value === 'string' && resolve) {
|
||||
// ensure no special char involved on deserialization
|
||||
// in this case only first char is important
|
||||
// no need to replace all value (better performance)
|
||||
value = value .replace(safeSpecialChar, escapedSafeSpecialChar)
|
||||
.replace(specialChar, safeSpecialChar);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doNotIgnore = true;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
function retrieveFromPath(current, keys) {
|
||||
for(var i = 0, length = keys.length; i < length; current = current[
|
||||
// keys should be normalized back here
|
||||
keys[i++].replace(safeSpecialCharRG, specialChar)
|
||||
]);
|
||||
return current;
|
||||
}
|
||||
|
||||
function generateReviver(reviver) {
|
||||
return function(key, value) {
|
||||
var isString = typeof value === 'string';
|
||||
if (isString && value.charAt(0) === specialChar) {
|
||||
return new $String(value.slice(1));
|
||||
}
|
||||
if (key === '') value = regenerate(value, value, {});
|
||||
// again, only one needed, do not use the RegExp for this replacement
|
||||
// only keys need the RegExp
|
||||
if (isString) value = value .replace(safeStartWithSpecialCharRG, '$1' + specialChar)
|
||||
.replace(escapedSafeSpecialChar, safeSpecialChar);
|
||||
return reviver ? reviver.call(this, key, value) : value;
|
||||
};
|
||||
}
|
||||
|
||||
function regenerateArray(root, current, retrieve) {
|
||||
for (var i = 0, length = current.length; i < length; i++) {
|
||||
current[i] = regenerate(root, current[i], retrieve);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function regenerateObject(root, current, retrieve) {
|
||||
for (var key in current) {
|
||||
if (current.hasOwnProperty(key)) {
|
||||
current[key] = regenerate(root, current[key], retrieve);
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function regenerate(root, current, retrieve) {
|
||||
return current instanceof Array ?
|
||||
// fast Array reconstruction
|
||||
regenerateArray(root, current, retrieve) :
|
||||
(
|
||||
current instanceof $String ?
|
||||
(
|
||||
// root is an empty string
|
||||
current.length ?
|
||||
(
|
||||
retrieve.hasOwnProperty(current) ?
|
||||
retrieve[current] :
|
||||
retrieve[current] = retrieveFromPath(
|
||||
root, current.split(specialChar)
|
||||
)
|
||||
) :
|
||||
root
|
||||
) :
|
||||
(
|
||||
current instanceof Object ?
|
||||
// dedicated Object parser
|
||||
regenerateObject(root, current, retrieve) :
|
||||
// value as it is
|
||||
current
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
var CircularJSON = {
|
||||
stringify: function stringify(value, replacer, space, doNotResolve) {
|
||||
return CircularJSON.parser.stringify(
|
||||
value,
|
||||
generateReplacer(value, replacer, !doNotResolve),
|
||||
space
|
||||
);
|
||||
},
|
||||
parse: function parse(text, reviver) {
|
||||
return CircularJSON.parser.parse(
|
||||
text,
|
||||
generateReviver(reviver)
|
||||
);
|
||||
},
|
||||
// A parser should be an API 1:1 compatible with JSON
|
||||
// it should expose stringify and parse methods.
|
||||
// The default parser is the native JSON.
|
||||
parser: JSON
|
||||
};
|
||||
|
||||
module.exports = CircularJSON;
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"circular-json",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client"
|
||||
]
|
||||
],
|
||||
"_from": "circular-json@latest",
|
||||
"_hasShrinkwrap": false,
|
||||
"_id": "circular-json@0.5.9",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/circular-json",
|
||||
"_nodeVersion": "9.11.1",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/circular-json_0.5.9_1540325095720_0.16760917845332957"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "andrea.giammarchi@gmail.com",
|
||||
"name": "webreflection"
|
||||
},
|
||||
"_npmVersion": "6.0.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "circular-json",
|
||||
"raw": "circular-json",
|
||||
"rawSpec": "",
|
||||
"scope": null,
|
||||
"spec": "latest",
|
||||
"type": "tag"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
|
||||
"_shasum": "932763ae88f4f7dead7a0d09c8a51a4743a53b1d",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "circular-json",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client",
|
||||
"author": {
|
||||
"name": "Andrea Giammarchi",
|
||||
"url": "http://webreflection.blogspot.com/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/WebReflection/circular-json/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"deprecated": "CircularJSON is in maintenance only, flatted is its successor.",
|
||||
"description": "JSON does not handle circular references. This version does",
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.13.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"tiny-cdn": "^0.7.0",
|
||||
"tressa": "^0.3.1"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"fileCount": 8,
|
||||
"integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==",
|
||||
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbz37oCRA9TVsSAnZWagAAsSYP/RjvSGPXrxP6ptjmghAa\nEN0y2yee4izsGxkqFQWBu0ENXJVGbClT1LtIu6WH2RGrJslYLWMViw/g7h6o\nDYbExQ4jGVksRKVUtWVQMlv0QsoONa6F5zXC0+JdxeblxjHf/j2sAL3OpU+j\nR/RBpr9jupANRqbkuxauz7Bz+3xFoRSm092m6nzo6Nn+iud52lpOwCf9HMzm\npTAx/OUbTJH4l8O3M769+gok7NN2l5CUqx5Xam09FygLkqSwpkuov9Ge5Aku\nx9pDcGkdKSCjb0bA7ShsQQYObXpanim3RAEeSnEYwhKaZP2QfzElvLurmcV3\nAJSCaid30hAUAZ8RqLUSuf0yURC/73hR5Kw29F6rENAxw9utW7uXNDw1qTxC\nvctbMh3yE/jmebx9VUmKyjbFYDCFk2wVPiWIwOrH7j+u3Xg4AnS9I+JcI3aD\nlt0owFEhx9oe7SR9e4WiNzgGeCKciJDV4CSe36CPeK9ENoSRhGB4el9iKLIG\n3wvPtH/Z3DV6eV0cSG50UfmZnYgMLnyXSBZyP+dhj0TQVSbHokCno1/iu619\nNtQ3JlD+v6Mj64F9bECEOPAOdvDgxqwmlhHCc4IfLLHnznX+7OrlOrdDx7uz\nIR0cLSB2l52yQ6Xlqwaz2xTF6YhSSlRezCh/wAjzQkIZyT4jdzl9GuzVeLzC\npEkP\r\n=VAF5\r\n-----END PGP SIGNATURE-----\r\n",
|
||||
"shasum": "932763ae88f4f7dead7a0d09c8a51a4743a53b1d",
|
||||
"tarball": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
|
||||
"unpackedSize": 24233
|
||||
},
|
||||
"generator": "https://github.com/WebReflection/gitstrap",
|
||||
"gitHead": "ceab9c16070d3fc63f193bc10124eccb20424990",
|
||||
"homepage": "https://github.com/WebReflection/circular-json",
|
||||
"keywords": [
|
||||
"JSON",
|
||||
"circular",
|
||||
"parse",
|
||||
"recursion",
|
||||
"recursive",
|
||||
"reference",
|
||||
"stringify"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./build/circular-json.node.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "webreflection",
|
||||
"email": "andrea.giammarchi@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "circular-json",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/WebReflection/circular-json.git"
|
||||
},
|
||||
"scripts": {
|
||||
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
||||
"test": "istanbul cover test/circular-json.js",
|
||||
"web": "$(sleep 2 && open http://0.0.0.0:7151/) & tiny-cdn run ./"
|
||||
},
|
||||
"unpkg": "build/circular-json.js",
|
||||
"version": "0.5.9"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
*/
|
|
@ -1 +0,0 @@
|
|||
/*!
|
|
@ -0,0 +1,51 @@
|
|||
# Change Log
|
||||
|
||||
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.
|
||||
|
||||
<a name="4.1.0"></a>
|
||||
# [4.1.0](https://github.com/yargs/cliui/compare/v4.0.0...v4.1.0) (2018-04-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add resetOutput method ([#57](https://github.com/yargs/cliui/issues/57)) ([7246902](https://github.com/yargs/cliui/commit/7246902))
|
||||
|
||||
|
||||
|
||||
<a name="4.0.0"></a>
|
||||
# [4.0.0](https://github.com/yargs/cliui/compare/v3.2.0...v4.0.0) (2017-12-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* downgrades strip-ansi to version 3.0.1 ([#54](https://github.com/yargs/cliui/issues/54)) ([5764c46](https://github.com/yargs/cliui/commit/5764c46))
|
||||
* set env variable FORCE_COLOR. ([#56](https://github.com/yargs/cliui/issues/56)) ([7350e36](https://github.com/yargs/cliui/commit/7350e36))
|
||||
|
||||
|
||||
### Chores
|
||||
|
||||
* drop support for node < 4 ([#53](https://github.com/yargs/cliui/issues/53)) ([b105376](https://github.com/yargs/cliui/commit/b105376))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add fallback for window width ([#45](https://github.com/yargs/cliui/issues/45)) ([d064922](https://github.com/yargs/cliui/commit/d064922))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* officially drop support for Node < 4
|
||||
|
||||
|
||||
|
||||
<a name="3.2.0"></a>
|
||||
# [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33))
|
||||
|
||||
### Features
|
||||
|
||||
* adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32))
|
|
@ -0,0 +1,14 @@
|
|||
Copyright (c) 2015, 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.
|
|
@ -0,0 +1,115 @@
|
|||
# cliui
|
||||
|
||||
[![Build Status](https://travis-ci.org/yargs/cliui.svg)](https://travis-ci.org/yargs/cliui)
|
||||
[![Coverage Status](https://coveralls.io/repos/yargs/cliui/badge.svg?branch=)](https://coveralls.io/r/yargs/cliui?branch=)
|
||||
[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui)
|
||||
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
|
||||
|
||||
easily create complex multi-column command-line-interfaces.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
var ui = require('cliui')()
|
||||
|
||||
ui.div('Usage: $0 [command] [options]')
|
||||
|
||||
ui.div({
|
||||
text: 'Options:',
|
||||
padding: [2, 0, 2, 0]
|
||||
})
|
||||
|
||||
ui.div(
|
||||
{
|
||||
text: "-f, --file",
|
||||
width: 20,
|
||||
padding: [0, 4, 0, 4]
|
||||
},
|
||||
{
|
||||
text: "the file to load." +
|
||||
chalk.green("(if this description is long it wraps).")
|
||||
,
|
||||
width: 20
|
||||
},
|
||||
{
|
||||
text: chalk.red("[required]"),
|
||||
align: 'right'
|
||||
}
|
||||
)
|
||||
|
||||
console.log(ui.toString())
|
||||
```
|
||||
|
||||
<img width="500" src="screenshot.png">
|
||||
|
||||
## Layout DSL
|
||||
|
||||
cliui exposes a simple layout DSL:
|
||||
|
||||
If you create a single `ui.row`, passing a string rather than an
|
||||
object:
|
||||
|
||||
* `\n`: characters will be interpreted as new rows.
|
||||
* `\t`: characters will be interpreted as new columns.
|
||||
* `\s`: characters will be interpreted as padding.
|
||||
|
||||
**as an example...**
|
||||
|
||||
```js
|
||||
var ui = require('./')({
|
||||
width: 60
|
||||
})
|
||||
|
||||
ui.div(
|
||||
'Usage: node ./bin/foo.js\n' +
|
||||
' <regex>\t provide a regex\n' +
|
||||
' <glob>\t provide a glob\t [required]'
|
||||
)
|
||||
|
||||
console.log(ui.toString())
|
||||
```
|
||||
|
||||
**will output:**
|
||||
|
||||
```shell
|
||||
Usage: node ./bin/foo.js
|
||||
<regex> provide a regex
|
||||
<glob> provide a glob [required]
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
```js
|
||||
cliui = require('cliui')
|
||||
```
|
||||
|
||||
### cliui({width: integer})
|
||||
|
||||
Specify the maximum width of the UI being generated.
|
||||
If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`.
|
||||
|
||||
### cliui({wrap: boolean})
|
||||
|
||||
Enable or disable the wrapping of text in a column.
|
||||
|
||||
### cliui.div(column, column, column)
|
||||
|
||||
Create a row with any number of columns, a column
|
||||
can either be a string, or an object with the following
|
||||
options:
|
||||
|
||||
* **text:** some text to place in the column.
|
||||
* **width:** the width of a column.
|
||||
* **align:** alignment, `right` or `center`.
|
||||
* **padding:** `[top, right, bottom, left]`.
|
||||
* **border:** should a border be placed around the div?
|
||||
|
||||
### cliui.span(column, column, column)
|
||||
|
||||
Similar to `div`, except the next row will be appended without
|
||||
a new line being created.
|
||||
|
||||
### cliui.resetOutput()
|
||||
|
||||
Resets the UI elements of the current cliui instance, maintaining the values
|
||||
set for `width` and `wrap`.
|
|
@ -0,0 +1,324 @@
|
|||
var stringWidth = require('string-width')
|
||||
var stripAnsi = require('strip-ansi')
|
||||
var wrap = require('wrap-ansi')
|
||||
var align = {
|
||||
right: alignRight,
|
||||
center: alignCenter
|
||||
}
|
||||
var top = 0
|
||||
var right = 1
|
||||
var bottom = 2
|
||||
var left = 3
|
||||
|
||||
function UI (opts) {
|
||||
this.width = opts.width
|
||||
this.wrap = opts.wrap
|
||||
this.rows = []
|
||||
}
|
||||
|
||||
UI.prototype.span = function () {
|
||||
var cols = this.div.apply(this, arguments)
|
||||
cols.span = true
|
||||
}
|
||||
|
||||
UI.prototype.resetOutput = function () {
|
||||
this.rows = []
|
||||
}
|
||||
|
||||
UI.prototype.div = function () {
|
||||
if (arguments.length === 0) this.div('')
|
||||
if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) {
|
||||
return this._applyLayoutDSL(arguments[0])
|
||||
}
|
||||
|
||||
var cols = []
|
||||
|
||||
for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) {
|
||||
if (typeof arg === 'string') cols.push(this._colFromString(arg))
|
||||
else cols.push(arg)
|
||||
}
|
||||
|
||||
this.rows.push(cols)
|
||||
return cols
|
||||
}
|
||||
|
||||
UI.prototype._shouldApplyLayoutDSL = function () {
|
||||
return arguments.length === 1 && typeof arguments[0] === 'string' &&
|
||||
/[\t\n]/.test(arguments[0])
|
||||
}
|
||||
|
||||
UI.prototype._applyLayoutDSL = function (str) {
|
||||
var _this = this
|
||||
var rows = str.split('\n')
|
||||
var leftColumnWidth = 0
|
||||
|
||||
// simple heuristic for layout, make sure the
|
||||
// second column lines up along the left-hand.
|
||||
// don't allow the first column to take up more
|
||||
// than 50% of the screen.
|
||||
rows.forEach(function (row) {
|
||||
var columns = row.split('\t')
|
||||
if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
|
||||
leftColumnWidth = Math.min(
|
||||
Math.floor(_this.width * 0.5),
|
||||
stringWidth(columns[0])
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// generate a table:
|
||||
// replacing ' ' with padding calculations.
|
||||
// using the algorithmically generated width.
|
||||
rows.forEach(function (row) {
|
||||
var columns = row.split('\t')
|
||||
_this.div.apply(_this, columns.map(function (r, i) {
|
||||
return {
|
||||
text: r.trim(),
|
||||
padding: _this._measurePadding(r),
|
||||
width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
return this.rows[this.rows.length - 1]
|
||||
}
|
||||
|
||||
UI.prototype._colFromString = function (str) {
|
||||
return {
|
||||
text: str,
|
||||
padding: this._measurePadding(str)
|
||||
}
|
||||
}
|
||||
|
||||
UI.prototype._measurePadding = function (str) {
|
||||
// measure padding without ansi escape codes
|
||||
var noAnsi = stripAnsi(str)
|
||||
return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
|
||||
}
|
||||
|
||||
UI.prototype.toString = function () {
|
||||
var _this = this
|
||||
var lines = []
|
||||
|
||||
_this.rows.forEach(function (row, i) {
|
||||
_this.rowToString(row, lines)
|
||||
})
|
||||
|
||||
// don't display any lines with the
|
||||
// hidden flag set.
|
||||
lines = lines.filter(function (line) {
|
||||
return !line.hidden
|
||||
})
|
||||
|
||||
return lines.map(function (line) {
|
||||
return line.text
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
UI.prototype.rowToString = function (row, lines) {
|
||||
var _this = this
|
||||
var padding
|
||||
var rrows = this._rasterize(row)
|
||||
var str = ''
|
||||
var ts
|
||||
var width
|
||||
var wrapWidth
|
||||
|
||||
rrows.forEach(function (rrow, r) {
|
||||
str = ''
|
||||
rrow.forEach(function (col, c) {
|
||||
ts = '' // temporary string used during alignment/padding.
|
||||
width = row[c].width // the width with padding.
|
||||
wrapWidth = _this._negatePadding(row[c]) // the width without padding.
|
||||
|
||||
ts += col
|
||||
|
||||
for (var i = 0; i < wrapWidth - stringWidth(col); i++) {
|
||||
ts += ' '
|
||||
}
|
||||
|
||||
// align the string within its column.
|
||||
if (row[c].align && row[c].align !== 'left' && _this.wrap) {
|
||||
ts = align[row[c].align](ts, wrapWidth)
|
||||
if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ')
|
||||
}
|
||||
|
||||
// apply border and padding to string.
|
||||
padding = row[c].padding || [0, 0, 0, 0]
|
||||
if (padding[left]) str += new Array(padding[left] + 1).join(' ')
|
||||
str += addBorder(row[c], ts, '| ')
|
||||
str += ts
|
||||
str += addBorder(row[c], ts, ' |')
|
||||
if (padding[right]) str += new Array(padding[right] + 1).join(' ')
|
||||
|
||||
// if prior row is span, try to render the
|
||||
// current row on the prior line.
|
||||
if (r === 0 && lines.length > 0) {
|
||||
str = _this._renderInline(str, lines[lines.length - 1])
|
||||
}
|
||||
})
|
||||
|
||||
// remove trailing whitespace.
|
||||
lines.push({
|
||||
text: str.replace(/ +$/, ''),
|
||||
span: row.span
|
||||
})
|
||||
})
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
function addBorder (col, ts, style) {
|
||||
if (col.border) {
|
||||
if (/[.']-+[.']/.test(ts)) return ''
|
||||
else if (ts.trim().length) return style
|
||||
else return ' '
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// if the full 'source' can render in
|
||||
// the target line, do so.
|
||||
UI.prototype._renderInline = function (source, previousLine) {
|
||||
var leadingWhitespace = source.match(/^ */)[0].length
|
||||
var target = previousLine.text
|
||||
var targetTextWidth = stringWidth(target.trimRight())
|
||||
|
||||
if (!previousLine.span) return source
|
||||
|
||||
// if we're not applying wrapping logic,
|
||||
// just always append to the span.
|
||||
if (!this.wrap) {
|
||||
previousLine.hidden = true
|
||||
return target + source
|
||||
}
|
||||
|
||||
if (leadingWhitespace < targetTextWidth) return source
|
||||
|
||||
previousLine.hidden = true
|
||||
|
||||
return target.trimRight() + new Array(leadingWhitespace - targetTextWidth + 1).join(' ') + source.trimLeft()
|
||||
}
|
||||
|
||||
UI.prototype._rasterize = function (row) {
|
||||
var _this = this
|
||||
var i
|
||||
var rrow
|
||||
var rrows = []
|
||||
var widths = this._columnWidths(row)
|
||||
var wrapped
|
||||
|
||||
// word wrap all columns, and create
|
||||
// a data-structure that is easy to rasterize.
|
||||
row.forEach(function (col, c) {
|
||||
// leave room for left and right padding.
|
||||
col.width = widths[c]
|
||||
if (_this.wrap) wrapped = wrap(col.text, _this._negatePadding(col), { hard: true }).split('\n')
|
||||
else wrapped = col.text.split('\n')
|
||||
|
||||
if (col.border) {
|
||||
wrapped.unshift('.' + new Array(_this._negatePadding(col) + 3).join('-') + '.')
|
||||
wrapped.push("'" + new Array(_this._negatePadding(col) + 3).join('-') + "'")
|
||||
}
|
||||
|
||||
// add top and bottom padding.
|
||||
if (col.padding) {
|
||||
for (i = 0; i < (col.padding[top] || 0); i++) wrapped.unshift('')
|
||||
for (i = 0; i < (col.padding[bottom] || 0); i++) wrapped.push('')
|
||||
}
|
||||
|
||||
wrapped.forEach(function (str, r) {
|
||||
if (!rrows[r]) rrows.push([])
|
||||
|
||||
rrow = rrows[r]
|
||||
|
||||
for (var i = 0; i < c; i++) {
|
||||
if (rrow[i] === undefined) rrow.push('')
|
||||
}
|
||||
rrow.push(str)
|
||||
})
|
||||
})
|
||||
|
||||
return rrows
|
||||
}
|
||||
|
||||
UI.prototype._negatePadding = function (col) {
|
||||
var wrapWidth = col.width
|
||||
if (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
|
||||
if (col.border) wrapWidth -= 4
|
||||
return wrapWidth
|
||||
}
|
||||
|
||||
UI.prototype._columnWidths = function (row) {
|
||||
var _this = this
|
||||
var widths = []
|
||||
var unset = row.length
|
||||
var unsetWidth
|
||||
var remainingWidth = this.width
|
||||
|
||||
// column widths can be set in config.
|
||||
row.forEach(function (col, i) {
|
||||
if (col.width) {
|
||||
unset--
|
||||
widths[i] = col.width
|
||||
remainingWidth -= col.width
|
||||
} else {
|
||||
widths[i] = undefined
|
||||
}
|
||||
})
|
||||
|
||||
// any unset widths should be calculated.
|
||||
if (unset) unsetWidth = Math.floor(remainingWidth / unset)
|
||||
widths.forEach(function (w, i) {
|
||||
if (!_this.wrap) widths[i] = row[i].width || stringWidth(row[i].text)
|
||||
else if (w === undefined) widths[i] = Math.max(unsetWidth, _minWidth(row[i]))
|
||||
})
|
||||
|
||||
return widths
|
||||
}
|
||||
|
||||
// calculates the minimum width of
|
||||
// a column, based on padding preferences.
|
||||
function _minWidth (col) {
|
||||
var padding = col.padding || []
|
||||
var minWidth = 1 + (padding[left] || 0) + (padding[right] || 0)
|
||||
if (col.border) minWidth += 4
|
||||
return minWidth
|
||||
}
|
||||
|
||||
function getWindowWidth () {
|
||||
if (typeof process === 'object' && process.stdout && process.stdout.columns) return process.stdout.columns
|
||||
}
|
||||
|
||||
function alignRight (str, width) {
|
||||
str = str.trim()
|
||||
var padding = ''
|
||||
var strWidth = stringWidth(str)
|
||||
|
||||
if (strWidth < width) {
|
||||
padding = new Array(width - strWidth + 1).join(' ')
|
||||
}
|
||||
|
||||
return padding + str
|
||||
}
|
||||
|
||||
function alignCenter (str, width) {
|
||||
str = str.trim()
|
||||
var padding = ''
|
||||
var strWidth = stringWidth(str.trim())
|
||||
|
||||
if (strWidth < width) {
|
||||
padding = new Array(parseInt((width - strWidth) / 2, 10) + 1).join(' ')
|
||||
}
|
||||
|
||||
return padding + str
|
||||
}
|
||||
|
||||
module.exports = function (opts) {
|
||||
opts = opts || {}
|
||||
|
||||
return new UI({
|
||||
width: (opts || {}).width || getWindowWidth() || 80,
|
||||
wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true
|
||||
})
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = () => {
|
||||
const pattern = [
|
||||
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)',
|
||||
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))'
|
||||
].join('|');
|
||||
|
||||
return new RegExp(pattern, 'g');
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
|
@ -0,0 +1,121 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"ansi-regex@^3.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui/node_modules/strip-ansi"
|
||||
]
|
||||
],
|
||||
"_from": "ansi-regex@>=3.0.0 <4.0.0",
|
||||
"_id": "ansi-regex@3.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cliui/ansi-regex",
|
||||
"_nodeVersion": "4.8.3",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/ansi-regex-3.0.0.tgz_1497985412590_0.5700640194118023"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.11",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "ansi-regex",
|
||||
"raw": "ansi-regex@^3.0.0",
|
||||
"rawSpec": "^3.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=3.0.0 <4.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/cliui/strip-ansi"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"_shasum": "ed0317c322064f79466c02966bddb605ab37d998",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "ansi-regex@^3.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui/node_modules/strip-ansi",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/chalk/ansi-regex/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Regular expression for matching ANSI escape codes",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "ed0317c322064f79466c02966bddb605ab37d998",
|
||||
"tarball": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "0a8cc19946c03c38520fe8c086b8adb66f9cce0b",
|
||||
"homepage": "https://github.com/chalk/ansi-regex#readme",
|
||||
"keywords": [
|
||||
"256",
|
||||
"ansi",
|
||||
"cli",
|
||||
"color",
|
||||
"colors",
|
||||
"colour",
|
||||
"command-line",
|
||||
"console",
|
||||
"escape",
|
||||
"find",
|
||||
"formatting",
|
||||
"match",
|
||||
"pattern",
|
||||
"re",
|
||||
"regex",
|
||||
"regexp",
|
||||
"rgb",
|
||||
"shell",
|
||||
"string",
|
||||
"styles",
|
||||
"terminal",
|
||||
"test",
|
||||
"text",
|
||||
"tty",
|
||||
"xterm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "dthree",
|
||||
"email": "threedeecee@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "qix",
|
||||
"email": "i.am.qix@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "ansi-regex",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/chalk/ansi-regex.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava",
|
||||
"view-supported": "node fixtures/view-codes.js"
|
||||
},
|
||||
"version": "3.0.0"
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)
|
||||
|
||||
> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install ansi-regex
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const ansiRegex = require('ansi-regex');
|
||||
|
||||
ansiRegex().test('\u001B[4mcake\u001B[0m');
|
||||
//=> true
|
||||
|
||||
ansiRegex().test('cake');
|
||||
//=> false
|
||||
|
||||
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
|
||||
//=> ['\u001B[4m', '\u001B[0m']
|
||||
```
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why do you test for codes not in the ECMA 48 standard?
|
||||
|
||||
Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
|
||||
|
||||
On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
|
||||
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
||||
- [Josh Junon](https://github.com/qix-)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
|
@ -0,0 +1,46 @@
|
|||
'use strict';
|
||||
/* eslint-disable yoda */
|
||||
module.exports = x => {
|
||||
if (Number.isNaN(x)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// code points are derived from:
|
||||
// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
|
||||
if (
|
||||
x >= 0x1100 && (
|
||||
x <= 0x115f || // Hangul Jamo
|
||||
x === 0x2329 || // LEFT-POINTING ANGLE BRACKET
|
||||
x === 0x232a || // RIGHT-POINTING ANGLE BRACKET
|
||||
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
|
||||
(0x2e80 <= x && x <= 0x3247 && x !== 0x303f) ||
|
||||
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
|
||||
(0x3250 <= x && x <= 0x4dbf) ||
|
||||
// CJK Unified Ideographs .. Yi Radicals
|
||||
(0x4e00 <= x && x <= 0xa4c6) ||
|
||||
// Hangul Jamo Extended-A
|
||||
(0xa960 <= x && x <= 0xa97c) ||
|
||||
// Hangul Syllables
|
||||
(0xac00 <= x && x <= 0xd7a3) ||
|
||||
// CJK Compatibility Ideographs
|
||||
(0xf900 <= x && x <= 0xfaff) ||
|
||||
// Vertical Forms
|
||||
(0xfe10 <= x && x <= 0xfe19) ||
|
||||
// CJK Compatibility Forms .. Small Form Variants
|
||||
(0xfe30 <= x && x <= 0xfe6b) ||
|
||||
// Halfwidth and Fullwidth Forms
|
||||
(0xff01 <= x && x <= 0xff60) ||
|
||||
(0xffe0 <= x && x <= 0xffe6) ||
|
||||
// Kana Supplement
|
||||
(0x1b000 <= x && x <= 0x1b001) ||
|
||||
// Enclosed Ideographic Supplement
|
||||
(0x1f200 <= x && x <= 0x1f251) ||
|
||||
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
|
||||
(0x20000 <= x && x <= 0x3fffd)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
|
@ -1,4 +1,6 @@
|
|||
Copyright (C) 2013-2017 by Andrea Giammarchi - @WebReflection
|
||||
The MIT License (MIT)
|
||||
|
||||
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
|
105
node_modules/cliui/node_modules/is-fullwidth-code-point/package.json
generated
vendored
Normal file
105
node_modules/cliui/node_modules/is-fullwidth-code-point/package.json
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"is-fullwidth-code-point@^2.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui/node_modules/string-width"
|
||||
]
|
||||
],
|
||||
"_from": "is-fullwidth-code-point@>=2.0.0 <3.0.0",
|
||||
"_id": "is-fullwidth-code-point@2.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cliui/is-fullwidth-code-point",
|
||||
"_nodeVersion": "4.5.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/is-fullwidth-code-point-2.0.0.tgz_1474526567505_0.299921662081033"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "3.10.7",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "is-fullwidth-code-point",
|
||||
"raw": "is-fullwidth-code-point@^2.0.0",
|
||||
"rawSpec": "^2.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=2.0.0 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/cliui/string-width"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"_shasum": "a3b30a5c4f199183167aaab93beefae3ddfb654f",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "is-fullwidth-code-point@^2.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui/node_modules/string-width",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/is-fullwidth-code-point/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Check if the character represented by a given Unicode code point is fullwidth",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "a3b30a5c4f199183167aaab93beefae3ddfb654f",
|
||||
"tarball": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "e94a78056056c5546f2bf4c4cf812a2163a46dae",
|
||||
"homepage": "https://github.com/sindresorhus/is-fullwidth-code-point#readme",
|
||||
"keywords": [
|
||||
"char",
|
||||
"character",
|
||||
"check",
|
||||
"code",
|
||||
"codepoint",
|
||||
"detect",
|
||||
"full",
|
||||
"full-width",
|
||||
"fullwidth",
|
||||
"is",
|
||||
"point",
|
||||
"str",
|
||||
"string",
|
||||
"unicode",
|
||||
"width"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "is-fullwidth-code-point",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/is-fullwidth-code-point.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
# is-fullwidth-code-point [![Build Status](https://travis-ci.org/sindresorhus/is-fullwidth-code-point.svg?branch=master)](https://travis-ci.org/sindresorhus/is-fullwidth-code-point)
|
||||
|
||||
> Check if the character represented by a given [Unicode code point](https://en.wikipedia.org/wiki/Code_point) is [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-fullwidth-code-point
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const isFullwidthCodePoint = require('is-fullwidth-code-point');
|
||||
|
||||
isFullwidthCodePoint('谢'.codePointAt());
|
||||
//=> true
|
||||
|
||||
isFullwidthCodePoint('a'.codePointAt());
|
||||
//=> false
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### isFullwidthCodePoint(input)
|
||||
|
||||
#### input
|
||||
|
||||
Type: `number`
|
||||
|
||||
[Code point](https://en.wikipedia.org/wiki/Code_point) of a character.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
const stripAnsi = require('strip-ansi');
|
||||
const isFullwidthCodePoint = require('is-fullwidth-code-point');
|
||||
|
||||
module.exports = str => {
|
||||
if (typeof str !== 'string' || str.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
str = stripAnsi(str);
|
||||
|
||||
let width = 0;
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const code = str.codePointAt(i);
|
||||
|
||||
// Ignore control characters
|
||||
if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore combining characters
|
||||
if (code >= 0x300 && code <= 0x36F) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Surrogates
|
||||
if (code > 0xFFFF) {
|
||||
i++;
|
||||
}
|
||||
|
||||
width += isFullwidthCodePoint(code) ? 2 : 1;
|
||||
}
|
||||
|
||||
return width;
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"string-width@^2.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs"
|
||||
],
|
||||
[
|
||||
"string-width@^2.1.1",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui"
|
||||
]
|
||||
],
|
||||
"_from": "string-width@>=2.1.1 <3.0.0",
|
||||
"_id": "string-width@2.1.1",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cliui/string-width",
|
||||
"_nodeVersion": "8.0.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/string-width-2.1.1.tgz_1500376154382_0.7171604454051703"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "5.0.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "string-width",
|
||||
"raw": "string-width@^2.1.1",
|
||||
"rawSpec": "^2.1.1",
|
||||
"scope": null,
|
||||
"spec": ">=2.1.1 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/cliui"
|
||||
],
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "string-width@^2.1.1",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/string-width/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
},
|
||||
"description": "Get the visual width of a string - the number of columns required to display it",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"shasum": "ab93f27a8dc13d28cac815c462143a6d9012ae9e",
|
||||
"tarball": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "74d8d552b465692790c41169b123409669d41079",
|
||||
"homepage": "https://github.com/sindresorhus/string-width#readme",
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"char",
|
||||
"character",
|
||||
"chinese",
|
||||
"cjk",
|
||||
"cli",
|
||||
"codes",
|
||||
"column",
|
||||
"columns",
|
||||
"command-line",
|
||||
"console",
|
||||
"escape",
|
||||
"fixed-width",
|
||||
"full",
|
||||
"full-width",
|
||||
"fullwidth",
|
||||
"japanese",
|
||||
"korean",
|
||||
"str",
|
||||
"string",
|
||||
"terminal",
|
||||
"unicode",
|
||||
"visual",
|
||||
"width"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "string-width",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/string-width.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "2.1.1"
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
# string-width [![Build Status](https://travis-ci.org/sindresorhus/string-width.svg?branch=master)](https://travis-ci.org/sindresorhus/string-width)
|
||||
|
||||
> Get the visual width of a string - the number of columns required to display it
|
||||
|
||||
Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width.
|
||||
|
||||
Useful to be able to measure the actual width of command-line output.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install string-width
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const stringWidth = require('string-width');
|
||||
|
||||
stringWidth('古');
|
||||
//=> 2
|
||||
|
||||
stringWidth('\u001b[1m古\u001b[22m');
|
||||
//=> 2
|
||||
|
||||
stringWidth('a');
|
||||
//=> 1
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [string-width-cli](https://github.com/sindresorhus/string-width-cli) - CLI for this module
|
||||
- [string-length](https://github.com/sindresorhus/string-length) - Get the real length of a string
|
||||
- [widest-line](https://github.com/sindresorhus/widest-line) - Get the visual width of the widest line in a string
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,4 @@
|
|||
'use strict';
|
||||
const ansiRegex = require('ansi-regex');
|
||||
|
||||
module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
|
@ -0,0 +1,120 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"strip-ansi@^4.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui"
|
||||
]
|
||||
],
|
||||
"_from": "strip-ansi@>=4.0.0 <5.0.0",
|
||||
"_id": "strip-ansi@4.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cliui/strip-ansi",
|
||||
"_nodeVersion": "4.8.3",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/strip-ansi-4.0.0.tgz_1497986904730_0.4528853143565357"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.11",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "strip-ansi",
|
||||
"raw": "strip-ansi@^4.0.0",
|
||||
"rawSpec": "^4.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=4.0.0 <5.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/cliui",
|
||||
"/cliui/string-width"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"_shasum": "a8479022eb1ac368a871389b635262c505ee368f",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "strip-ansi@^4.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/cliui",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/chalk/strip-ansi/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
},
|
||||
"description": "Strip ANSI escape codes",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "a8479022eb1ac368a871389b635262c505ee368f",
|
||||
"tarball": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "c299056a42b31d7a479d6a89b41318b2a2462cc7",
|
||||
"homepage": "https://github.com/chalk/strip-ansi#readme",
|
||||
"keywords": [
|
||||
"256",
|
||||
"ansi",
|
||||
"color",
|
||||
"colors",
|
||||
"colour",
|
||||
"command-line",
|
||||
"console",
|
||||
"escape",
|
||||
"formatting",
|
||||
"log",
|
||||
"logging",
|
||||
"remove",
|
||||
"rgb",
|
||||
"shell",
|
||||
"string",
|
||||
"strip",
|
||||
"styles",
|
||||
"terminal",
|
||||
"text",
|
||||
"trim",
|
||||
"tty",
|
||||
"xterm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "dthree",
|
||||
"email": "threedeecee@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "qix",
|
||||
"email": "i.am.qix@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "strip-ansi",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/chalk/strip-ansi.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "4.0.0"
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
# strip-ansi [![Build Status](https://travis-ci.org/chalk/strip-ansi.svg?branch=master)](https://travis-ci.org/chalk/strip-ansi)
|
||||
|
||||
> Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install strip-ansi
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const stripAnsi = require('strip-ansi');
|
||||
|
||||
stripAnsi('\u001B[4mUnicorn\u001B[0m');
|
||||
//=> 'Unicorn'
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [strip-ansi-cli](https://github.com/chalk/strip-ansi-cli) - CLI for this module
|
||||
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
|
||||
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
|
||||
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
|
||||
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
||||
- [Josh Junon](https://github.com/qix-)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
|
@ -0,0 +1,131 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"cliui@^4.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs"
|
||||
]
|
||||
],
|
||||
"_from": "cliui@>=4.0.0 <5.0.0",
|
||||
"_hasShrinkwrap": false,
|
||||
"_id": "cliui@4.1.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cliui",
|
||||
"_nodeVersion": "8.8.1",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/cliui_4.1.0_1524450515410_0.021997836619508382"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "ben@npmjs.com",
|
||||
"name": "bcoe"
|
||||
},
|
||||
"_npmVersion": "5.8.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "cliui",
|
||||
"raw": "cliui@^4.0.0",
|
||||
"rawSpec": "^4.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=4.0.0 <5.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/yargs"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||
"_shasum": "348422dbe82d800b3022eef4f6ac10bf2e4d1b49",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "cliui@^4.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs",
|
||||
"author": {
|
||||
"email": "ben@npmjs.com",
|
||||
"name": "Ben Coe"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/yargs/cliui/issues"
|
||||
},
|
||||
"config": {
|
||||
"blanket": {
|
||||
"data-cover-never": [
|
||||
"node_modules",
|
||||
"test"
|
||||
],
|
||||
"output-reporter": "spec",
|
||||
"pattern": [
|
||||
"index.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"string-width": "^2.1.1",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
},
|
||||
"description": "easily create complex multi-column command-line-interfaces",
|
||||
"devDependencies": {
|
||||
"chai": "^3.5.0",
|
||||
"chalk": "^1.1.2",
|
||||
"coveralls": "^2.11.8",
|
||||
"mocha": "^3.0.0",
|
||||
"nyc": "^10.0.0",
|
||||
"standard": "^8.0.0",
|
||||
"standard-version": "^3.0.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"fileCount": 5,
|
||||
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
|
||||
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa3UTUCRA9TVsSAnZWagAAQBYP/21PAh+wIPQktq2XDuQ+\ntMjuDek2ebHLK5M4RyNM6TAJioGf5uHwUmqV7rHAhm9gRJn+dIIqkIukvLZy\ntln2x5GkDmYIxOC2wsj8Lbyc0k1cxoynJt8v8F/oE6EEaa6mRHuk3SJQU5Yy\nim1ofDj95s/mWcHeyrjdcfyvKJ4e6GZwylinGspAk1hR6UO33RoiWL4c2YIY\n7jYvi4HNVwv52cqGyoI78QZ8Js90rOCyZQz8QP6tZ1NMo1SwUC3jPauspGsn\npMgHslY1s0fZWp70Ac/MziJdx2XTFzYJZKkiuyJCxsyBuX7f1kUTD/Za235A\nDlpUmgj5a9UKpVtptlJ3nMRmgqXBClnIjvmm9NG2nJ8Egt3QxFdBZaxgJNbM\nMFss+LSZNnxBvmgnAC37sMvie06xwV2UOB/+eiK1EWBdVILV7END0hyRSyuM\naFsVZpqDAaXSVS4hwUFQvPA4biDGncxwDmktuOuJHSGVbIqRJJ7EEfVVBbFl\nH2KZQ8gxFT93Gg6x3tFuXlXQdPaHKvtZTkKJCLtigINk1Rr9PlUzstLRayay\nG55YvsSlDm1P2FMYosbMUrNHe0f8SVgyLsZk/tQ40htjK7zMthyAamxq+JpT\nl63y6KDYrtAwAE41206ry1QyNvlCyp+ZHv5KSZdxcUW25ZK5kwJDCMs1Sbkw\nn7bO\r\n=CsbE\r\n-----END PGP SIGNATURE-----\r\n",
|
||||
"shasum": "348422dbe82d800b3022eef4f6ac10bf2e4d1b49",
|
||||
"tarball": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||
"unpackedSize": 14471
|
||||
},
|
||||
"engine": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "83ada4a595ad60fff4fb962a3288eccbe163bccf",
|
||||
"homepage": "https://github.com/yargs/cliui#readme",
|
||||
"keywords": [
|
||||
"cli",
|
||||
"command-line",
|
||||
"console",
|
||||
"design",
|
||||
"layout",
|
||||
"table",
|
||||
"wrap"
|
||||
],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "bcoe",
|
||||
"email": "ben@npmjs.com"
|
||||
}
|
||||
],
|
||||
"name": "cliui",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/yargs/cliui.git"
|
||||
},
|
||||
"scripts": {
|
||||
"coverage": "nyc --reporter=text-lcov mocha | coveralls",
|
||||
"pretest": "standard",
|
||||
"release": "standard-version",
|
||||
"test": "nyc mocha"
|
||||
},
|
||||
"standard": {
|
||||
"globals": [
|
||||
"it"
|
||||
],
|
||||
"ignore": [
|
||||
"**/example/**"
|
||||
]
|
||||
},
|
||||
"version": "4.1.0"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
## 5.0.0 - 2016-10-30
|
||||
|
||||
- Add support for `options.shell`
|
||||
- Improve parsing of shebangs by using [`shebang-command`](https://github.com/kevva/shebang-command) module
|
||||
- Refactor some code to make it more clear
|
||||
- Update README caveats
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 IndigoUnited
|
||||
|
||||
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.
|
|
@ -0,0 +1,85 @@
|
|||
# cross-spawn
|
||||
|
||||
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Build status][appveyor-image]][appveyor-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]
|
||||
|
||||
[npm-url]:https://npmjs.org/package/cross-spawn
|
||||
[downloads-image]:http://img.shields.io/npm/dm/cross-spawn.svg
|
||||
[npm-image]:http://img.shields.io/npm/v/cross-spawn.svg
|
||||
[travis-url]:https://travis-ci.org/IndigoUnited/node-cross-spawn
|
||||
[travis-image]:http://img.shields.io/travis/IndigoUnited/node-cross-spawn/master.svg
|
||||
[appveyor-url]:https://ci.appveyor.com/project/satazor/node-cross-spawn
|
||||
[appveyor-image]:https://img.shields.io/appveyor/ci/satazor/node-cross-spawn/master.svg
|
||||
[david-dm-url]:https://david-dm.org/IndigoUnited/node-cross-spawn
|
||||
[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-cross-spawn.svg
|
||||
[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-cross-spawn#info=devDependencies
|
||||
[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-cross-spawn.svg
|
||||
|
||||
A cross platform solution to node's spawn and spawnSync.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
`$ npm install cross-spawn`
|
||||
|
||||
If you are using `spawnSync` on node 0.10 or older, you will also need to install `spawn-sync`:
|
||||
|
||||
`$ npm install spawn-sync`
|
||||
|
||||
|
||||
## Why
|
||||
|
||||
Node has issues when using spawn on Windows:
|
||||
|
||||
- It ignores [PATHEXT](https://github.com/joyent/node/issues/2318)
|
||||
- It does not support [shebangs](http://pt.wikipedia.org/wiki/Shebang)
|
||||
- No `options.shell` support on node < v6
|
||||
- It does not allow you to run `del` or `dir`
|
||||
|
||||
All these issues are handled correctly by `cross-spawn`.
|
||||
There are some known modules, such as [win-spawn](https://github.com/ForbesLindesay/win-spawn), that try to solve this but they are either broken or provide faulty escaping of shell arguments.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Exactly the same way as node's [`spawn`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) or [`spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options), so it's a drop in replacement.
|
||||
|
||||
|
||||
```js
|
||||
var spawn = require('cross-spawn');
|
||||
|
||||
// Spawn NPM asynchronously
|
||||
var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
|
||||
|
||||
// Spawn NPM synchronously
|
||||
var results = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
|
||||
```
|
||||
|
||||
|
||||
## Caveats
|
||||
|
||||
#### `options.shell` as an alternative to `cross-spawn`
|
||||
|
||||
Starting from node v6, `spawn` has a `shell` option that allows you run commands from within a shell. This new option solves most of the problems that `cross-spawn` attempts to solve, but:
|
||||
|
||||
- It's not supported in node < v6
|
||||
- It has no support for shebangs on Windows
|
||||
- You must manually escape the command and arguments which is very error prone, specially when passing user input
|
||||
|
||||
If you are using the `shell` option to spawn a command in a cross platform way, consider using `cross-spawn` instead. You have been warned.
|
||||
|
||||
|
||||
#### Shebangs
|
||||
|
||||
While `cross-spawn` handles shebangs on Windows, its support is limited: e.g.: it doesn't handle arguments after the path, e.g.: `#!/bin/bash -e`.
|
||||
|
||||
Remember to always test your code on Windows!
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
`$ npm test`
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
|
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
|
||||
var cp = require('child_process');
|
||||
var parse = require('./lib/parse');
|
||||
var enoent = require('./lib/enoent');
|
||||
|
||||
var cpSpawnSync = cp.spawnSync;
|
||||
|
||||
function spawn(command, args, options) {
|
||||
var parsed;
|
||||
var spawned;
|
||||
|
||||
// Parse the arguments
|
||||
parsed = parse(command, args, options);
|
||||
|
||||
// Spawn the child process
|
||||
spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
||||
|
||||
// Hook into child process "exit" event to emit an error if the command
|
||||
// does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||||
enoent.hookChildProcess(spawned, parsed);
|
||||
|
||||
return spawned;
|
||||
}
|
||||
|
||||
function spawnSync(command, args, options) {
|
||||
var parsed;
|
||||
var result;
|
||||
|
||||
if (!cpSpawnSync) {
|
||||
try {
|
||||
cpSpawnSync = require('spawn-sync'); // eslint-disable-line global-require
|
||||
} catch (ex) {
|
||||
throw new Error(
|
||||
'In order to use spawnSync on node 0.10 or older, you must ' +
|
||||
'install spawn-sync:\n\n' +
|
||||
' npm install spawn-sync --save'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the arguments
|
||||
parsed = parse(command, args, options);
|
||||
|
||||
// Spawn the child process
|
||||
result = cpSpawnSync(parsed.command, parsed.args, parsed.options);
|
||||
|
||||
// Analyze if the command does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||||
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = spawn;
|
||||
module.exports.spawn = spawn;
|
||||
module.exports.sync = spawnSync;
|
||||
|
||||
module.exports._parse = parse;
|
||||
module.exports._enoent = enoent;
|
|
@ -0,0 +1,73 @@
|
|||
'use strict';
|
||||
|
||||
var isWin = process.platform === 'win32';
|
||||
var resolveCommand = require('./util/resolveCommand');
|
||||
|
||||
var isNode10 = process.version.indexOf('v0.10.') === 0;
|
||||
|
||||
function notFoundError(command, syscall) {
|
||||
var err;
|
||||
|
||||
err = new Error(syscall + ' ' + command + ' ENOENT');
|
||||
err.code = err.errno = 'ENOENT';
|
||||
err.syscall = syscall + ' ' + command;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
function hookChildProcess(cp, parsed) {
|
||||
var originalEmit;
|
||||
|
||||
if (!isWin) {
|
||||
return;
|
||||
}
|
||||
|
||||
originalEmit = cp.emit;
|
||||
cp.emit = function (name, arg1) {
|
||||
var err;
|
||||
|
||||
// If emitting "exit" event and exit code is 1, we need to check if
|
||||
// the command exists and emit an "error" instead
|
||||
// See: https://github.com/IndigoUnited/node-cross-spawn/issues/16
|
||||
if (name === 'exit') {
|
||||
err = verifyENOENT(arg1, parsed, 'spawn');
|
||||
|
||||
if (err) {
|
||||
return originalEmit.call(cp, 'error', err);
|
||||
}
|
||||
}
|
||||
|
||||
return originalEmit.apply(cp, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
function verifyENOENT(status, parsed) {
|
||||
if (isWin && status === 1 && !parsed.file) {
|
||||
return notFoundError(parsed.original, 'spawn');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function verifyENOENTSync(status, parsed) {
|
||||
if (isWin && status === 1 && !parsed.file) {
|
||||
return notFoundError(parsed.original, 'spawnSync');
|
||||
}
|
||||
|
||||
// If we are in node 10, then we are using spawn-sync; if it exited
|
||||
// with -1 it probably means that the command does not exist
|
||||
if (isNode10 && status === -1) {
|
||||
parsed.file = isWin ? parsed.file : resolveCommand(parsed.original);
|
||||
|
||||
if (!parsed.file) {
|
||||
return notFoundError(parsed.original, 'spawnSync');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports.hookChildProcess = hookChildProcess;
|
||||
module.exports.verifyENOENT = verifyENOENT;
|
||||
module.exports.verifyENOENTSync = verifyENOENTSync;
|
||||
module.exports.notFoundError = notFoundError;
|
|
@ -0,0 +1,113 @@
|
|||
'use strict';
|
||||
|
||||
var resolveCommand = require('./util/resolveCommand');
|
||||
var hasEmptyArgumentBug = require('./util/hasEmptyArgumentBug');
|
||||
var escapeArgument = require('./util/escapeArgument');
|
||||
var escapeCommand = require('./util/escapeCommand');
|
||||
var readShebang = require('./util/readShebang');
|
||||
|
||||
var isWin = process.platform === 'win32';
|
||||
var skipShellRegExp = /\.(?:com|exe)$/i;
|
||||
|
||||
// Supported in Node >= 6 and >= 4.8
|
||||
var supportsShellOption = parseInt(process.version.substr(1).split('.')[0], 10) >= 6 ||
|
||||
parseInt(process.version.substr(1).split('.')[0], 10) === 4 && parseInt(process.version.substr(1).split('.')[1], 10) >= 8;
|
||||
|
||||
function parseNonShell(parsed) {
|
||||
var shebang;
|
||||
var needsShell;
|
||||
var applyQuotes;
|
||||
|
||||
if (!isWin) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Detect & add support for shebangs
|
||||
parsed.file = resolveCommand(parsed.command);
|
||||
parsed.file = parsed.file || resolveCommand(parsed.command, true);
|
||||
shebang = parsed.file && readShebang(parsed.file);
|
||||
|
||||
if (shebang) {
|
||||
parsed.args.unshift(parsed.file);
|
||||
parsed.command = shebang;
|
||||
needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(resolveCommand(shebang) || resolveCommand(shebang, true));
|
||||
} else {
|
||||
needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(parsed.file);
|
||||
}
|
||||
|
||||
// If a shell is required, use cmd.exe and take care of escaping everything correctly
|
||||
if (needsShell) {
|
||||
// Escape command & arguments
|
||||
applyQuotes = (parsed.command !== 'echo'); // Do not quote arguments for the special "echo" command
|
||||
parsed.command = escapeCommand(parsed.command);
|
||||
parsed.args = parsed.args.map(function (arg) {
|
||||
return escapeArgument(arg, applyQuotes);
|
||||
});
|
||||
|
||||
// Make use of cmd.exe
|
||||
parsed.args = ['/d', '/s', '/c', '"' + parsed.command + (parsed.args.length ? ' ' + parsed.args.join(' ') : '') + '"'];
|
||||
parsed.command = process.env.comspec || 'cmd.exe';
|
||||
parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function parseShell(parsed) {
|
||||
var shellCommand;
|
||||
|
||||
// If node supports the shell option, there's no need to mimic its behavior
|
||||
if (supportsShellOption) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
|
||||
shellCommand = [parsed.command].concat(parsed.args).join(' ');
|
||||
|
||||
if (isWin) {
|
||||
parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe';
|
||||
parsed.args = ['/d', '/s', '/c', '"' + shellCommand + '"'];
|
||||
parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
|
||||
} else {
|
||||
if (typeof parsed.options.shell === 'string') {
|
||||
parsed.command = parsed.options.shell;
|
||||
} else if (process.platform === 'android') {
|
||||
parsed.command = '/system/bin/sh';
|
||||
} else {
|
||||
parsed.command = '/bin/sh';
|
||||
}
|
||||
|
||||
parsed.args = ['-c', shellCommand];
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
function parse(command, args, options) {
|
||||
var parsed;
|
||||
|
||||
// Normalize arguments, similar to nodejs
|
||||
if (args && !Array.isArray(args)) {
|
||||
options = args;
|
||||
args = null;
|
||||
}
|
||||
|
||||
args = args ? args.slice(0) : []; // Clone array to avoid changing the original
|
||||
options = options || {};
|
||||
|
||||
// Build our parsed object
|
||||
parsed = {
|
||||
command: command,
|
||||
args: args,
|
||||
options: options,
|
||||
file: undefined,
|
||||
original: command,
|
||||
};
|
||||
|
||||
// Delegate further parsing to shell or non-shell
|
||||
return options.shell ? parseShell(parsed) : parseNonShell(parsed);
|
||||
}
|
||||
|
||||
module.exports = parse;
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
function escapeArgument(arg, quote) {
|
||||
// Convert to string
|
||||
arg = '' + arg;
|
||||
|
||||
// If we are not going to quote the argument,
|
||||
// escape shell metacharacters, including double and single quotes:
|
||||
if (!quote) {
|
||||
arg = arg.replace(/([()%!^<>&|;,"'\s])/g, '^$1');
|
||||
} else {
|
||||
// Sequence of backslashes followed by a double quote:
|
||||
// double up all the backslashes and escape the double quote
|
||||
arg = arg.replace(/(\\*)"/g, '$1$1\\"');
|
||||
|
||||
// Sequence of backslashes followed by the end of the string
|
||||
// (which will become a double quote later):
|
||||
// double up all the backslashes
|
||||
arg = arg.replace(/(\\*)$/, '$1$1');
|
||||
|
||||
// All other backslashes occur literally
|
||||
|
||||
// Quote the whole thing:
|
||||
arg = '"' + arg + '"';
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
module.exports = escapeArgument;
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
var escapeArgument = require('./escapeArgument');
|
||||
|
||||
function escapeCommand(command) {
|
||||
// Do not escape if this command is not dangerous..
|
||||
// We do this so that commands like "echo" or "ifconfig" work
|
||||
// Quoting them, will make them unaccessible
|
||||
return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArgument(command, true);
|
||||
}
|
||||
|
||||
module.exports = escapeCommand;
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
// See: https://github.com/IndigoUnited/node-cross-spawn/pull/34#issuecomment-221623455
|
||||
function hasEmptyArgumentBug() {
|
||||
var nodeVer;
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
return false;
|
||||
}
|
||||
|
||||
nodeVer = process.version.substr(1).split('.').map(function (num) {
|
||||
return parseInt(num, 10);
|
||||
});
|
||||
|
||||
return (nodeVer[0] === 0 && nodeVer[1] < 12);
|
||||
}
|
||||
|
||||
module.exports = hasEmptyArgumentBug();
|
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var LRU = require('lru-cache');
|
||||
var shebangCommand = require('shebang-command');
|
||||
|
||||
var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec
|
||||
|
||||
function readShebang(command) {
|
||||
var buffer;
|
||||
var fd;
|
||||
var shebang;
|
||||
|
||||
// Check if it is in the cache first
|
||||
if (shebangCache.has(command)) {
|
||||
return shebangCache.get(command);
|
||||
}
|
||||
|
||||
// Read the first 150 bytes from the file
|
||||
buffer = new Buffer(150);
|
||||
|
||||
try {
|
||||
fd = fs.openSync(command, 'r');
|
||||
fs.readSync(fd, buffer, 0, 150, 0);
|
||||
fs.closeSync(fd);
|
||||
} catch (e) { /* empty */ }
|
||||
|
||||
// Attempt to extract shebang (null is returned if not a shebang)
|
||||
shebang = shebangCommand(buffer.toString());
|
||||
|
||||
// Store the shebang in the cache
|
||||
shebangCache.set(command, shebang);
|
||||
|
||||
return shebang;
|
||||
}
|
||||
|
||||
module.exports = readShebang;
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var which = require('which');
|
||||
var LRU = require('lru-cache');
|
||||
|
||||
var commandCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec
|
||||
|
||||
function resolveCommand(command, noExtension) {
|
||||
var resolved;
|
||||
|
||||
noExtension = !!noExtension;
|
||||
resolved = commandCache.get(command + '!' + noExtension);
|
||||
|
||||
// Check if its resolved in the cache
|
||||
if (commandCache.has(command)) {
|
||||
return commandCache.get(command);
|
||||
}
|
||||
|
||||
try {
|
||||
resolved = !noExtension ?
|
||||
which.sync(command) :
|
||||
which.sync(command, { pathExt: path.delimiter + (process.env.PATHEXT || '') });
|
||||
} catch (e) { /* empty */ }
|
||||
|
||||
commandCache.set(command + '!' + noExtension, resolved);
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
module.exports = resolveCommand;
|
|
@ -0,0 +1,110 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"cross-spawn@^5.0.1",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa"
|
||||
]
|
||||
],
|
||||
"_from": "cross-spawn@>=5.0.1 <6.0.0",
|
||||
"_id": "cross-spawn@5.1.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/cross-spawn",
|
||||
"_nodeVersion": "7.0.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/cross-spawn-5.1.0.tgz_1488134324770_0.025160177145153284"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "andremiguelcruz@msn.com",
|
||||
"name": "satazor"
|
||||
},
|
||||
"_npmVersion": "3.10.8",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "cross-spawn",
|
||||
"raw": "cross-spawn@^5.0.1",
|
||||
"rawSpec": "^5.0.1",
|
||||
"scope": null,
|
||||
"spec": ">=5.0.1 <6.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/execa"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
|
||||
"_shasum": "e8bd0efee58fcff6f8f94510a0a554bbfa235449",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "cross-spawn@^5.0.1",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa",
|
||||
"author": {
|
||||
"email": "hello@indigounited.com",
|
||||
"name": "IndigoUnited",
|
||||
"url": "http://indigounited.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/IndigoUnited/node-cross-spawn/issues/"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
},
|
||||
"description": "Cross platform child_process#spawn and child_process#spawnSync",
|
||||
"devDependencies": {
|
||||
"@satazor/eslint-config": "^3.0.0",
|
||||
"eslint": "^3.0.0",
|
||||
"expect.js": "^0.3.0",
|
||||
"glob": "^7.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^3.0.2",
|
||||
"once": "^1.4.0",
|
||||
"rimraf": "^2.5.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "e8bd0efee58fcff6f8f94510a0a554bbfa235449",
|
||||
"tarball": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib"
|
||||
],
|
||||
"gitHead": "1da4c09ccf658079849a3d191b16e59bc600e8b4",
|
||||
"homepage": "https://github.com/IndigoUnited/node-cross-spawn#readme",
|
||||
"keywords": [
|
||||
"cmd",
|
||||
"cross",
|
||||
"execute",
|
||||
"ext",
|
||||
"hashbang",
|
||||
"path",
|
||||
"path-ext",
|
||||
"path_ext",
|
||||
"platform",
|
||||
"shebang",
|
||||
"spawn",
|
||||
"spawnSync",
|
||||
"windows"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "satazor",
|
||||
"email": "andremiguelcruz@msn.com"
|
||||
}
|
||||
],
|
||||
"name": "cross-spawn",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/IndigoUnited/node-cross-spawn.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint '{*.js,lib/**/*.js,test/**/*.js}'",
|
||||
"test": "node test/prepare && mocha --bail test/test"
|
||||
},
|
||||
"version": "5.1.0"
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
'use strict';
|
||||
const childProcess = require('child_process');
|
||||
const util = require('util');
|
||||
const crossSpawn = require('cross-spawn');
|
||||
const stripEof = require('strip-eof');
|
||||
const npmRunPath = require('npm-run-path');
|
||||
const isStream = require('is-stream');
|
||||
const _getStream = require('get-stream');
|
||||
const pFinally = require('p-finally');
|
||||
const onExit = require('signal-exit');
|
||||
const errname = require('./lib/errname');
|
||||
const stdio = require('./lib/stdio');
|
||||
|
||||
const TEN_MEGABYTES = 1000 * 1000 * 10;
|
||||
|
||||
function handleArgs(cmd, args, opts) {
|
||||
let parsed;
|
||||
|
||||
if (opts && opts.env && opts.extendEnv !== false) {
|
||||
opts.env = Object.assign({}, process.env, opts.env);
|
||||
}
|
||||
|
||||
if (opts && opts.__winShell === true) {
|
||||
delete opts.__winShell;
|
||||
parsed = {
|
||||
command: cmd,
|
||||
args,
|
||||
options: opts,
|
||||
file: cmd,
|
||||
original: cmd
|
||||
};
|
||||
} else {
|
||||
parsed = crossSpawn._parse(cmd, args, opts);
|
||||
}
|
||||
|
||||
opts = Object.assign({
|
||||
maxBuffer: TEN_MEGABYTES,
|
||||
stripEof: true,
|
||||
preferLocal: true,
|
||||
localDir: parsed.options.cwd || process.cwd(),
|
||||
encoding: 'utf8',
|
||||
reject: true,
|
||||
cleanup: true
|
||||
}, parsed.options);
|
||||
|
||||
opts.stdio = stdio(opts);
|
||||
|
||||
if (opts.preferLocal) {
|
||||
opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir}));
|
||||
}
|
||||
|
||||
return {
|
||||
cmd: parsed.command,
|
||||
args: parsed.args,
|
||||
opts,
|
||||
parsed
|
||||
};
|
||||
}
|
||||
|
||||
function handleInput(spawned, opts) {
|
||||
const input = opts.input;
|
||||
|
||||
if (input === null || input === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isStream(input)) {
|
||||
input.pipe(spawned.stdin);
|
||||
} else {
|
||||
spawned.stdin.end(input);
|
||||
}
|
||||
}
|
||||
|
||||
function handleOutput(opts, val) {
|
||||
if (val && opts.stripEof) {
|
||||
val = stripEof(val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
function handleShell(fn, cmd, opts) {
|
||||
let file = '/bin/sh';
|
||||
let args = ['-c', cmd];
|
||||
|
||||
opts = Object.assign({}, opts);
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
opts.__winShell = true;
|
||||
file = process.env.comspec || 'cmd.exe';
|
||||
args = ['/s', '/c', `"${cmd}"`];
|
||||
opts.windowsVerbatimArguments = true;
|
||||
}
|
||||
|
||||
if (opts.shell) {
|
||||
file = opts.shell;
|
||||
delete opts.shell;
|
||||
}
|
||||
|
||||
return fn(file, args, opts);
|
||||
}
|
||||
|
||||
function getStream(process, stream, encoding, maxBuffer) {
|
||||
if (!process[stream]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let ret;
|
||||
|
||||
if (encoding) {
|
||||
ret = _getStream(process[stream], {
|
||||
encoding,
|
||||
maxBuffer
|
||||
});
|
||||
} else {
|
||||
ret = _getStream.buffer(process[stream], {maxBuffer});
|
||||
}
|
||||
|
||||
return ret.catch(err => {
|
||||
err.stream = stream;
|
||||
err.message = `${stream} ${err.message}`;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = (cmd, args, opts) => {
|
||||
let joinedCmd = cmd;
|
||||
|
||||
if (Array.isArray(args) && args.length > 0) {
|
||||
joinedCmd += ' ' + args.join(' ');
|
||||
}
|
||||
|
||||
const parsed = handleArgs(cmd, args, opts);
|
||||
const encoding = parsed.opts.encoding;
|
||||
const maxBuffer = parsed.opts.maxBuffer;
|
||||
|
||||
let spawned;
|
||||
try {
|
||||
spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
let removeExitHandler;
|
||||
if (parsed.opts.cleanup) {
|
||||
removeExitHandler = onExit(() => {
|
||||
spawned.kill();
|
||||
});
|
||||
}
|
||||
|
||||
let timeoutId = null;
|
||||
let timedOut = false;
|
||||
|
||||
const cleanupTimeout = () => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (parsed.opts.timeout > 0) {
|
||||
timeoutId = setTimeout(() => {
|
||||
timeoutId = null;
|
||||
timedOut = true;
|
||||
spawned.kill(parsed.opts.killSignal);
|
||||
}, parsed.opts.timeout);
|
||||
}
|
||||
|
||||
const processDone = new Promise(resolve => {
|
||||
spawned.on('exit', (code, signal) => {
|
||||
cleanupTimeout();
|
||||
resolve({code, signal});
|
||||
});
|
||||
|
||||
spawned.on('error', err => {
|
||||
cleanupTimeout();
|
||||
resolve({err});
|
||||
});
|
||||
|
||||
if (spawned.stdin) {
|
||||
spawned.stdin.on('error', err => {
|
||||
cleanupTimeout();
|
||||
resolve({err});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function destroy() {
|
||||
if (spawned.stdout) {
|
||||
spawned.stdout.destroy();
|
||||
}
|
||||
|
||||
if (spawned.stderr) {
|
||||
spawned.stderr.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
const promise = pFinally(Promise.all([
|
||||
processDone,
|
||||
getStream(spawned, 'stdout', encoding, maxBuffer),
|
||||
getStream(spawned, 'stderr', encoding, maxBuffer)
|
||||
]).then(arr => {
|
||||
const result = arr[0];
|
||||
const stdout = arr[1];
|
||||
const stderr = arr[2];
|
||||
|
||||
let err = result.err;
|
||||
const code = result.code;
|
||||
const signal = result.signal;
|
||||
|
||||
if (removeExitHandler) {
|
||||
removeExitHandler();
|
||||
}
|
||||
|
||||
if (err || code !== 0 || signal !== null) {
|
||||
if (!err) {
|
||||
let output = '';
|
||||
|
||||
if (Array.isArray(parsed.opts.stdio)) {
|
||||
if (parsed.opts.stdio[2] !== 'inherit') {
|
||||
output += output.length > 0 ? stderr : `\n${stderr}`;
|
||||
}
|
||||
|
||||
if (parsed.opts.stdio[1] !== 'inherit') {
|
||||
output += `\n${stdout}`;
|
||||
}
|
||||
} else if (parsed.opts.stdio !== 'inherit') {
|
||||
output = `\n${stderr}${stdout}`;
|
||||
}
|
||||
|
||||
err = new Error(`Command failed: ${joinedCmd}${output}`);
|
||||
err.code = code < 0 ? errname(code) : code;
|
||||
}
|
||||
|
||||
// TODO: missing some timeout logic for killed
|
||||
// https://github.com/nodejs/node/blob/master/lib/child_process.js#L203
|
||||
// err.killed = spawned.killed || killed;
|
||||
err.killed = err.killed || spawned.killed;
|
||||
|
||||
err.stdout = stdout;
|
||||
err.stderr = stderr;
|
||||
err.failed = true;
|
||||
err.signal = signal || null;
|
||||
err.cmd = joinedCmd;
|
||||
err.timedOut = timedOut;
|
||||
|
||||
if (!parsed.opts.reject) {
|
||||
return err;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
return {
|
||||
stdout: handleOutput(parsed.opts, stdout),
|
||||
stderr: handleOutput(parsed.opts, stderr),
|
||||
code: 0,
|
||||
failed: false,
|
||||
killed: false,
|
||||
signal: null,
|
||||
cmd: joinedCmd,
|
||||
timedOut: false
|
||||
};
|
||||
}), destroy);
|
||||
|
||||
crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed);
|
||||
|
||||
handleInput(spawned, parsed.opts);
|
||||
|
||||
spawned.then = promise.then.bind(promise);
|
||||
spawned.catch = promise.catch.bind(promise);
|
||||
|
||||
return spawned;
|
||||
};
|
||||
|
||||
module.exports.stdout = function () {
|
||||
// TODO: set `stderr: 'ignore'` when that option is implemented
|
||||
return module.exports.apply(null, arguments).then(x => x.stdout);
|
||||
};
|
||||
|
||||
module.exports.stderr = function () {
|
||||
// TODO: set `stdout: 'ignore'` when that option is implemented
|
||||
return module.exports.apply(null, arguments).then(x => x.stderr);
|
||||
};
|
||||
|
||||
module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts);
|
||||
|
||||
module.exports.sync = (cmd, args, opts) => {
|
||||
const parsed = handleArgs(cmd, args, opts);
|
||||
|
||||
if (isStream(parsed.opts.input)) {
|
||||
throw new TypeError('The `input` option cannot be a stream in sync mode');
|
||||
}
|
||||
|
||||
const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts);
|
||||
|
||||
if (result.error || result.status !== 0) {
|
||||
throw (result.error || new Error(result.stderr === '' ? result.stdout : result.stderr));
|
||||
}
|
||||
|
||||
result.stdout = handleOutput(parsed.opts, result.stdout);
|
||||
result.stderr = handleOutput(parsed.opts, result.stderr);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts);
|
||||
|
||||
module.exports.spawn = util.deprecate(module.exports, 'execa.spawn() is deprecated. Use execa() instead.');
|
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
// The Node team wants to deprecate `process.bind(...)`.
|
||||
// https://github.com/nodejs/node/pull/2768
|
||||
//
|
||||
// However, we need the 'uv' binding for errname support.
|
||||
// This is a defensive wrapper around it so `execa` will not fail entirely if it stops working someday.
|
||||
//
|
||||
// If this ever stops working. See: https://github.com/sindresorhus/execa/issues/31#issuecomment-215939939 for another possible solution.
|
||||
let uv;
|
||||
|
||||
try {
|
||||
uv = process.binding('uv');
|
||||
|
||||
if (typeof uv.errname !== 'function') {
|
||||
throw new TypeError('uv.errname is not a function');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err);
|
||||
uv = null;
|
||||
}
|
||||
|
||||
function errname(uv, code) {
|
||||
if (uv) {
|
||||
return uv.errname(code);
|
||||
}
|
||||
|
||||
if (!(code < 0)) {
|
||||
throw new Error('err >= 0');
|
||||
}
|
||||
|
||||
return `Unknown system error ${code}`;
|
||||
}
|
||||
|
||||
module.exports = code => errname(uv, code);
|
||||
|
||||
// Used for testing the fallback behavior
|
||||
module.exports.__test__ = errname;
|
|
@ -0,0 +1,41 @@
|
|||
'use strict';
|
||||
const alias = ['stdin', 'stdout', 'stderr'];
|
||||
|
||||
const hasAlias = opts => alias.some(x => Boolean(opts[x]));
|
||||
|
||||
module.exports = opts => {
|
||||
if (!opts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (opts.stdio && hasAlias(opts)) {
|
||||
throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`);
|
||||
}
|
||||
|
||||
if (typeof opts.stdio === 'string') {
|
||||
return opts.stdio;
|
||||
}
|
||||
|
||||
const stdio = opts.stdio || [];
|
||||
|
||||
if (!Array.isArray(stdio)) {
|
||||
throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
const len = Math.max(stdio.length, alias.length);
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let value = null;
|
||||
|
||||
if (stdio[i] !== undefined) {
|
||||
value = stdio[i];
|
||||
} else if (opts[alias[i]] !== undefined) {
|
||||
value = opts[alias[i]];
|
||||
}
|
||||
|
||||
result[i] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"execa@^0.7.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale"
|
||||
]
|
||||
],
|
||||
"_from": "execa@>=0.7.0 <0.8.0",
|
||||
"_id": "execa@0.7.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/execa",
|
||||
"_nodeVersion": "4.8.3",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/execa-0.7.0.tgz_1497045041009_0.3423430174589157"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.11",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "execa",
|
||||
"raw": "execa@^0.7.0",
|
||||
"rawSpec": "^0.7.0",
|
||||
"scope": null,
|
||||
"spec": ">=0.7.0 <0.8.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/os-locale"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
|
||||
"_shasum": "944becd34cc41ee32a63a9faf27ad5a65fc59777",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "execa@^0.7.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/execa/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": "^5.0.1",
|
||||
"get-stream": "^3.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
},
|
||||
"description": "A better `child_process`",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"cat-names": "^1.0.2",
|
||||
"coveralls": "^2.11.9",
|
||||
"delay": "^2.0.0",
|
||||
"is-running": "^2.0.0",
|
||||
"nyc": "^11.0.2",
|
||||
"tempfile": "^2.0.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "944becd34cc41ee32a63a9faf27ad5a65fc59777",
|
||||
"tarball": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib"
|
||||
],
|
||||
"gitHead": "b4d1c8613fd068e3c36f11e7bff672d008ac88f9",
|
||||
"homepage": "https://github.com/sindresorhus/execa#readme",
|
||||
"keywords": [
|
||||
"bin",
|
||||
"binaries",
|
||||
"binary",
|
||||
"child",
|
||||
"exec",
|
||||
"execfile",
|
||||
"execute",
|
||||
"file",
|
||||
"fork",
|
||||
"local",
|
||||
"npm",
|
||||
"path",
|
||||
"process",
|
||||
"shell",
|
||||
"spawn"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "execa",
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
"**/fixtures/**",
|
||||
"**/test.js",
|
||||
"**/test/**"
|
||||
],
|
||||
"reporter": [
|
||||
"lcov",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/execa.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava"
|
||||
},
|
||||
"version": "0.7.0"
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
# execa [![Build Status: Linux](https://travis-ci.org/sindresorhus/execa.svg?branch=master)](https://travis-ci.org/sindresorhus/execa) [![Build status: Windows](https://ci.appveyor.com/api/projects/status/x5ajamxtjtt93cqv/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/execa/branch/master) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/execa/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/execa?branch=master)
|
||||
|
||||
> A better [`child_process`](https://nodejs.org/api/child_process.html)
|
||||
|
||||
|
||||
## Why
|
||||
|
||||
- Promise interface.
|
||||
- [Strips EOF](https://github.com/sindresorhus/strip-eof) from the output so you don't have to `stdout.trim()`.
|
||||
- Supports [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) binaries cross-platform.
|
||||
- [Improved Windows support.](https://github.com/IndigoUnited/node-cross-spawn#why)
|
||||
- Higher max buffer. 10 MB instead of 200 KB.
|
||||
- [Executes locally installed binaries by name.](#preferlocal)
|
||||
- [Cleans up spawned processes when the parent process dies.](#cleanup)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save execa
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const execa = require('execa');
|
||||
|
||||
execa('echo', ['unicorns']).then(result => {
|
||||
console.log(result.stdout);
|
||||
//=> 'unicorns'
|
||||
});
|
||||
|
||||
// pipe the child process stdout to the current stdout
|
||||
execa('echo', ['unicorns']).stdout.pipe(process.stdout);
|
||||
|
||||
execa.shell('echo unicorns').then(result => {
|
||||
console.log(result.stdout);
|
||||
//=> 'unicorns'
|
||||
});
|
||||
|
||||
// example of catching an error
|
||||
execa.shell('exit 3').catch(error => {
|
||||
console.log(error);
|
||||
/*
|
||||
{
|
||||
message: 'Command failed: /bin/sh -c exit 3'
|
||||
killed: false,
|
||||
code: 3,
|
||||
signal: null,
|
||||
cmd: '/bin/sh -c exit 3',
|
||||
stdout: '',
|
||||
stderr: '',
|
||||
timedOut: false
|
||||
}
|
||||
*/
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### execa(file, [arguments], [options])
|
||||
|
||||
Execute a file.
|
||||
|
||||
Think of this as a mix of `child_process.execFile` and `child_process.spawn`.
|
||||
|
||||
Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
|
||||
|
||||
### execa.stdout(file, [arguments], [options])
|
||||
|
||||
Same as `execa()`, but returns only `stdout`.
|
||||
|
||||
### execa.stderr(file, [arguments], [options])
|
||||
|
||||
Same as `execa()`, but returns only `stderr`.
|
||||
|
||||
### execa.shell(command, [options])
|
||||
|
||||
Execute a command through the system shell. Prefer `execa()` whenever possible, as it's both faster and safer.
|
||||
|
||||
Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess).
|
||||
|
||||
The `child_process` instance is enhanced to also be promise for a result object with `stdout` and `stderr` properties.
|
||||
|
||||
### execa.sync(file, [arguments], [options])
|
||||
|
||||
Execute a file synchronously.
|
||||
|
||||
Returns the same result object as [`child_process.spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options).
|
||||
|
||||
This method throws an `Error` if the command fails.
|
||||
|
||||
### execa.shellSync(file, [options])
|
||||
|
||||
Execute a command synchronously through the system shell.
|
||||
|
||||
Returns the same result object as [`child_process.spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options).
|
||||
|
||||
### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
#### cwd
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `process.cwd()`
|
||||
|
||||
Current working directory of the child process.
|
||||
|
||||
#### env
|
||||
|
||||
Type: `Object`<br>
|
||||
Default: `process.env`
|
||||
|
||||
Environment key-value pairs. Extends automatically from `process.env`. Set `extendEnv` to `false` if you don't want this.
|
||||
|
||||
#### extendEnv
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Set to `false` if you don't want to extend the environment variables when providing the `env` property.
|
||||
|
||||
#### argv0
|
||||
|
||||
Type: `string`
|
||||
|
||||
Explicitly set the value of `argv[0]` sent to the child process. This will be set to `command` or `file` if not specified.
|
||||
|
||||
#### stdio
|
||||
|
||||
Type: `Array` `string`<br>
|
||||
Default: `pipe`
|
||||
|
||||
Child's [stdio](https://nodejs.org/api/child_process.html#child_process_options_stdio) configuration.
|
||||
|
||||
#### detached
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Prepare child to run independently of its parent process. Specific behavior [depends on the platform](https://nodejs.org/api/child_process.html#child_process_options_detached).
|
||||
|
||||
#### uid
|
||||
|
||||
Type: `number`
|
||||
|
||||
Sets the user identity of the process.
|
||||
|
||||
#### gid
|
||||
|
||||
Type: `number`
|
||||
|
||||
Sets the group identity of the process.
|
||||
|
||||
#### shell
|
||||
|
||||
Type: `boolean` `string`<br>
|
||||
Default: `false`
|
||||
|
||||
If `true`, runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.
|
||||
|
||||
#### stripEof
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
[Strip EOF](https://github.com/sindresorhus/strip-eof) (last newline) from the output.
|
||||
|
||||
#### preferLocal
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Prefer locally installed binaries when looking for a binary to execute.<br>
|
||||
If you `$ npm install foo`, you can then `execa('foo')`.
|
||||
|
||||
#### localDir
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `process.cwd()`
|
||||
|
||||
Preferred path to find locally installed binaries in (use with `preferLocal`).
|
||||
|
||||
#### input
|
||||
|
||||
Type: `string` `Buffer` `stream.Readable`
|
||||
|
||||
Write some input to the `stdin` of your binary.<br>
|
||||
Streams are not allowed when using the synchronous methods.
|
||||
|
||||
#### reject
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Setting this to `false` resolves the promise with the error instead of rejecting it.
|
||||
|
||||
#### cleanup
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Keep track of the spawned process and `kill` it when the parent process exits.
|
||||
|
||||
#### encoding
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `utf8`
|
||||
|
||||
Specify the character encoding used to decode the `stdout` and `stderr` output.
|
||||
|
||||
#### timeout
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `0`
|
||||
|
||||
If timeout is greater than `0`, the parent will send the signal identified by the `killSignal` property (the default is `SIGTERM`) if the child runs longer than timeout milliseconds.
|
||||
|
||||
#### maxBuffer
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `10000000` (10MB)
|
||||
|
||||
Largest amount of data in bytes allowed on `stdout` or `stderr`.
|
||||
|
||||
#### killSignal
|
||||
|
||||
Type: `string` `number`<br>
|
||||
Default: `SIGTERM`
|
||||
|
||||
Signal value to be used when the spawned process will be killed.
|
||||
|
||||
#### stdin
|
||||
|
||||
Type: `string` `number` `Stream` `undefined` `null`<br>
|
||||
Default: `pipe`
|
||||
|
||||
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
|
||||
|
||||
#### stdout
|
||||
|
||||
Type: `string` `number` `Stream` `undefined` `null`<br>
|
||||
Default: `pipe`
|
||||
|
||||
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
|
||||
|
||||
#### stderr
|
||||
|
||||
Type: `string` `number` `Stream` `undefined` `null`<br>
|
||||
Default: `pipe`
|
||||
|
||||
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
### Save and pipe output from a child process
|
||||
|
||||
Let's say you want to show the output of a child process in real-time while also saving it to a variable.
|
||||
|
||||
```js
|
||||
const execa = require('execa');
|
||||
const getStream = require('get-stream');
|
||||
|
||||
const stream = execa('echo', ['foo']).stdout;
|
||||
|
||||
stream.pipe(process.stdout);
|
||||
|
||||
getStream(stream).then(value => {
|
||||
console.log('child output:', value);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,6 @@
|
|||
ISC License (ISC)
|
||||
Copyright 2018 Stefan Penner
|
||||
|
||||
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.
|
|
@ -0,0 +1,4 @@
|
|||
# get-caller-file
|
||||
|
||||
[![Build Status](https://travis-ci.org/stefanpenner/get-caller-file.svg?branch=master)](https://travis-ci.org/stefanpenner/get-caller-file)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/ol2q94g1932cy14a/branch/master?svg=true)](https://ci.appveyor.com/project/embercli/get-caller-file/branch/master)
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
// Call this function in a another function to find out the file from
|
||||
// which that function was called from. (Inspects the v8 stack trace)
|
||||
//
|
||||
// Inspired by http://stackoverflow.com/questions/13227489
|
||||
|
||||
module.exports = function getCallerFile(_position) {
|
||||
var oldPrepareStackTrace = Error.prepareStackTrace;
|
||||
Error.prepareStackTrace = function(err, stack) { return stack; };
|
||||
var stack = new Error().stack;
|
||||
Error.prepareStackTrace = oldPrepareStackTrace;
|
||||
|
||||
var position = _position ? _position : 2;
|
||||
|
||||
// stack[0] holds this file
|
||||
// stack[1] holds where this function was called
|
||||
// stack[2] holds the file we're interested in
|
||||
return stack[position] ? stack[position].getFileName() : undefined;
|
||||
};
|
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"get-caller-file@^1.0.1",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs"
|
||||
]
|
||||
],
|
||||
"_from": "get-caller-file@>=1.0.1 <2.0.0",
|
||||
"_hasShrinkwrap": false,
|
||||
"_id": "get-caller-file@1.0.3",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/get-caller-file",
|
||||
"_nodeVersion": "10.6.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/get-caller-file_1.0.3_1531318482467_0.29196568362695974"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "stefan.penner@gmail.com",
|
||||
"name": "stefanpenner"
|
||||
},
|
||||
"_npmVersion": "6.1.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "get-caller-file",
|
||||
"raw": "get-caller-file@^1.0.1",
|
||||
"rawSpec": "^1.0.1",
|
||||
"scope": null,
|
||||
"spec": ">=1.0.1 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/yargs"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"_shasum": "f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "get-caller-file@^1.0.1",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs",
|
||||
"author": {
|
||||
"name": "Stefan Penner"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/stefanpenner/get-caller-file/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "[![Build Status](https://travis-ci.org/stefanpenner/get-caller-file.svg?branch=master)](https://travis-ci.org/stefanpenner/get-caller-file) [![Build status](https://ci.appveyor.com/api/projects/status/ol2q94g1932cy14a/branch/master?svg=true)](https://ci.a",
|
||||
"devDependencies": {
|
||||
"chai": "^4.1.2",
|
||||
"ensure-posix-path": "^1.0.1",
|
||||
"mocha": "^5.2.0"
|
||||
},
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"dist": {
|
||||
"fileCount": 4,
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRhDSCRA9TVsSAnZWagAABCsQAISfJUg79/mpbXNlCcnf\nx5XH8U998GO/e1jUn+D+tJw6PqhPYMRjjfcWvDApP5XijXEPN1VxedAW6cCD\nQYNFH1M+KMQ/APV6vB6w5aqcDmrkY7F8kD0KdWen/xoOs7aeBhIlgJOIJRmI\nxPvT3JQB9tKaBu5Jit/TQfRsA2YtF1WjwvoRowu8v8Lg0facAeE9Pvt++mGm\ngKl5e0jgEzHvl4RKoit5HqC6c7N8MziTsgVOoIQb+jpCggJTPzxfu6h5hJcU\nQw4pqxYdt0vWvzxiG1owgt015O14dq2F9CvInYELcCjsjKdskBEI4iiXFa4v\n2KFxKfUy8v1He51AlEhCVEzTI53rc2EUUedxgcC6x6Z0yXEwoyF+jbtugDTn\nApmL268vD5yW7bGi3hMT11QzJidNrioi4itEc4zg/BaZC/UTW1Y9HNe6fPOE\n42MDIfd95tTHJhXVPDKjo5p85aZj2cg506PiyMgb6z9ONMsDbXlp4/x1YuzE\nfWVHefdm1Nx0fIWwVapoiEa2ZGqDLpVtxPJt1tLnmutfCR+j/GlfQr+BJ1XS\nSFQEMw0DTpBZRbXrytfO6OMjwNajlHq2FH2cSgq7bHzV4RfwI900TRudwp+S\nK9H7JpbJxWMS4x41erfD65O5NM0iLITnEeN49wC+SheDhVk/bXUoIx1sPfJj\npQXC\r\n=ofq4\r\n-----END PGP SIGNATURE-----\r\n",
|
||||
"shasum": "f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a",
|
||||
"tarball": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"unpackedSize": 2479
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "8519eaca478b51b44e575617759a503dcf13a345",
|
||||
"homepage": "https://github.com/stefanpenner/get-caller-file#readme",
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "stefanpenner",
|
||||
"email": "stefan.penner@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "get-caller-file",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/stefanpenner/get-caller-file.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha test",
|
||||
"test:debug": "mocha test"
|
||||
},
|
||||
"version": "1.0.3"
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
|
||||
module.exports = opts => {
|
||||
opts = Object.assign({}, opts);
|
||||
|
||||
const array = opts.array;
|
||||
let encoding = opts.encoding;
|
||||
const buffer = encoding === 'buffer';
|
||||
let objectMode = false;
|
||||
|
||||
if (array) {
|
||||
objectMode = !(encoding || buffer);
|
||||
} else {
|
||||
encoding = encoding || 'utf8';
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
let len = 0;
|
||||
const ret = [];
|
||||
const stream = new PassThrough({objectMode});
|
||||
|
||||
if (encoding) {
|
||||
stream.setEncoding(encoding);
|
||||
}
|
||||
|
||||
stream.on('data', chunk => {
|
||||
ret.push(chunk);
|
||||
|
||||
if (objectMode) {
|
||||
len = ret.length;
|
||||
} else {
|
||||
len += chunk.length;
|
||||
}
|
||||
});
|
||||
|
||||
stream.getBufferedValue = () => {
|
||||
if (array) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return buffer ? Buffer.concat(ret, len) : ret.join('');
|
||||
};
|
||||
|
||||
stream.getBufferedLength = () => len;
|
||||
|
||||
return stream;
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
const bufferStream = require('./buffer-stream');
|
||||
|
||||
function getStream(inputStream, opts) {
|
||||
if (!inputStream) {
|
||||
return Promise.reject(new Error('Expected a stream'));
|
||||
}
|
||||
|
||||
opts = Object.assign({maxBuffer: Infinity}, opts);
|
||||
|
||||
const maxBuffer = opts.maxBuffer;
|
||||
let stream;
|
||||
let clean;
|
||||
|
||||
const p = new Promise((resolve, reject) => {
|
||||
const error = err => {
|
||||
if (err) { // null check
|
||||
err.bufferedData = stream.getBufferedValue();
|
||||
}
|
||||
|
||||
reject(err);
|
||||
};
|
||||
|
||||
stream = bufferStream(opts);
|
||||
inputStream.once('error', error);
|
||||
inputStream.pipe(stream);
|
||||
|
||||
stream.on('data', () => {
|
||||
if (stream.getBufferedLength() > maxBuffer) {
|
||||
reject(new Error('maxBuffer exceeded'));
|
||||
}
|
||||
});
|
||||
stream.once('error', error);
|
||||
stream.on('end', resolve);
|
||||
|
||||
clean = () => {
|
||||
// some streams doesn't implement the `stream.Readable` interface correctly
|
||||
if (inputStream.unpipe) {
|
||||
inputStream.unpipe(stream);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p.then(clean, clean);
|
||||
|
||||
return p.then(() => stream.getBufferedValue());
|
||||
}
|
||||
|
||||
module.exports = getStream;
|
||||
module.exports.buffer = (stream, opts) => getStream(stream, Object.assign({}, opts, {encoding: 'buffer'}));
|
||||
module.exports.array = (stream, opts) => getStream(stream, Object.assign({}, opts, {array: true}));
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"get-stream@^3.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa"
|
||||
]
|
||||
],
|
||||
"_from": "get-stream@>=3.0.0 <4.0.0",
|
||||
"_id": "get-stream@3.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/get-stream",
|
||||
"_nodeVersion": "4.6.2",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-18-east.internal.npmjs.com",
|
||||
"tmp": "tmp/get-stream-3.0.0.tgz_1479869385406_0.47692562686279416"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.11",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "get-stream",
|
||||
"raw": "get-stream@^3.0.0",
|
||||
"rawSpec": "^3.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=3.0.0 <4.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/execa"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"_shasum": "8e943d1358dc37555054ecbe2edb05aa174ede14",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "get-stream@^3.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/get-stream/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Get a stream as a string, buffer, or array",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"into-stream": "^3.0.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "8e943d1358dc37555054ecbe2edb05aa174ede14",
|
||||
"tarball": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"buffer-stream.js",
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "3023bc31dec6680dda4f935a2b320b3a4f18c815",
|
||||
"homepage": "https://github.com/sindresorhus/get-stream#readme",
|
||||
"keywords": [
|
||||
"array",
|
||||
"buffer",
|
||||
"concat",
|
||||
"consume",
|
||||
"data",
|
||||
"get",
|
||||
"obj",
|
||||
"object",
|
||||
"promise",
|
||||
"read",
|
||||
"readable",
|
||||
"readablestream",
|
||||
"str",
|
||||
"stream",
|
||||
"string",
|
||||
"text"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "jamestalmage",
|
||||
"email": "james@talmage.io"
|
||||
},
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "get-stream",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/get-stream.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "3.0.0",
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
# get-stream [![Build Status](https://travis-ci.org/sindresorhus/get-stream.svg?branch=master)](https://travis-ci.org/sindresorhus/get-stream)
|
||||
|
||||
> Get a stream as a string, buffer, or array
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save get-stream
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const getStream = require('get-stream');
|
||||
const stream = fs.createReadStream('unicorn.txt');
|
||||
|
||||
getStream(stream).then(str => {
|
||||
console.log(str);
|
||||
/*
|
||||
,,))))))));,
|
||||
__)))))))))))))),
|
||||
\|/ -\(((((''''((((((((.
|
||||
-*-==//////(('' . `)))))),
|
||||
/|\ ))| o ;-. '((((( ,(,
|
||||
( `| / ) ;))))' ,_))^;(~
|
||||
| | | ,))((((_ _____------~~~-. %,;(;(>';'~
|
||||
o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
|
||||
; ''''```` `: `:::|\,__,%% );`'; ~
|
||||
| _ ) / `:|`----' `-'
|
||||
______/\/~ | / /
|
||||
/~;;.____/;;' / ___--,-( `;;;/
|
||||
/ // _;______;'------~~~~~ /;;/\ /
|
||||
// | | / ; \;;,\
|
||||
(<_ | ; /',/-----' _>
|
||||
\_| ||_ //~;~~~~~~~~~
|
||||
`\_| (,~~
|
||||
\~\
|
||||
~~
|
||||
*/
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
The methods returns a promise that resolves when the `end` event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
|
||||
|
||||
### getStream(stream, [options])
|
||||
|
||||
Get the `stream` as a string.
|
||||
|
||||
#### options
|
||||
|
||||
##### encoding
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `utf8`
|
||||
|
||||
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
|
||||
|
||||
##### maxBuffer
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `Infinity`
|
||||
|
||||
Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected.
|
||||
|
||||
### getStream.buffer(stream, [options])
|
||||
|
||||
Get the `stream` as a buffer.
|
||||
|
||||
It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
|
||||
|
||||
### getStream.array(stream, [options])
|
||||
|
||||
Get the `stream` as an array of values.
|
||||
|
||||
It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
|
||||
|
||||
- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
|
||||
|
||||
- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
|
||||
|
||||
- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
If the input stream emits an `error` event, the promise will be rejected with the error. The buffered data will be attached to the `bufferedData` property of the error.
|
||||
|
||||
```js
|
||||
getStream(streamThatErrorsAtTheEnd('unicorn'))
|
||||
.catch(err => {
|
||||
console.log(err.bufferedData);
|
||||
//=> 'unicorn'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How is this different from [`concat-stream`](https://github.com/maxogden/concat-stream)?
|
||||
|
||||
This module accepts a stream instead of being one and returns a promise instead of using a callback. The API is simpler and it only supports returning a string, buffer, or array. It doesn't have a fragile type inference. You explicitly choose what you want. And it doesn't depend on the huge `readable-stream` package.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [get-stdin](https://github.com/sindresorhus/get-stdin) - Get stdin as a string or buffer
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
module.exports = function (obj) {
|
||||
if (typeof obj !== 'object') {
|
||||
throw new TypeError('Expected an object');
|
||||
}
|
||||
|
||||
var ret = {};
|
||||
|
||||
for (var key in obj) {
|
||||
var val = obj[key];
|
||||
ret[val] = key;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"invert-kv@^1.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/lcid"
|
||||
]
|
||||
],
|
||||
"_from": "invert-kv@>=1.0.0 <2.0.0",
|
||||
"_id": "invert-kv@1.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/invert-kv",
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "1.4.21",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "invert-kv",
|
||||
"raw": "invert-kv@^1.0.0",
|
||||
"rawSpec": "^1.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.0.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/lcid"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||
"_shasum": "104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "invert-kv@^1.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/lcid",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "http://sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/invert-kv/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Invert the key/value of an object. Example: {foo: 'bar'} → {bar: 'foo'}",
|
||||
"devDependencies": {
|
||||
"mocha": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6",
|
||||
"tarball": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "c28c3a15abcde3f67bd90f90f8ffe54a5f8cb04e",
|
||||
"homepage": "https://github.com/sindresorhus/invert-kv",
|
||||
"keywords": [
|
||||
"invert",
|
||||
"key",
|
||||
"kv",
|
||||
"obj",
|
||||
"object",
|
||||
"val",
|
||||
"value"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "invert-kv",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/invert-kv.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# invert-kv [![Build Status](https://travis-ci.org/sindresorhus/invert-kv.svg?branch=master)](https://travis-ci.org/sindresorhus/invert-kv)
|
||||
|
||||
> Invert the key/value of an object. Example: `{foo: 'bar'}` → `{bar: 'foo'}`
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
$ npm install --save invert-kv
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var invertKv = require('invert-kv');
|
||||
|
||||
invertKv({foo: 'bar', unicorn: 'rainbow'});
|
||||
//=> {bar: 'foo', rainbow: 'unicorn'}
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
var isStream = module.exports = function (stream) {
|
||||
return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function';
|
||||
};
|
||||
|
||||
isStream.writable = function (stream) {
|
||||
return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object';
|
||||
};
|
||||
|
||||
isStream.readable = function (stream) {
|
||||
return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object';
|
||||
};
|
||||
|
||||
isStream.duplex = function (stream) {
|
||||
return isStream.writable(stream) && isStream.readable(stream);
|
||||
};
|
||||
|
||||
isStream.transform = function (stream) {
|
||||
return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object';
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"is-stream@^1.1.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa"
|
||||
]
|
||||
],
|
||||
"_from": "is-stream@>=1.1.0 <2.0.0",
|
||||
"_id": "is-stream@1.1.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/is-stream",
|
||||
"_nodeVersion": "4.4.2",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/is-stream-1.1.0.tgz_1460446915184_0.806101513793692"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "is-stream",
|
||||
"raw": "is-stream@^1.1.0",
|
||||
"rawSpec": "^1.1.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/execa"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"_shasum": "12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "is-stream@^1.1.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/execa",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/is-stream/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Check if something is a Node.js stream",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"tempfile": "^1.1.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44",
|
||||
"tarball": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "e21d73f1028c189d16150cea52641059b0936310",
|
||||
"homepage": "https://github.com/sindresorhus/is-stream#readme",
|
||||
"keywords": [
|
||||
"check",
|
||||
"detect",
|
||||
"duplex",
|
||||
"is",
|
||||
"readable",
|
||||
"stream",
|
||||
"streams",
|
||||
"transform",
|
||||
"type",
|
||||
"writable"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "is-stream",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/is-stream.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "1.1.0"
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
# is-stream [![Build Status](https://travis-ci.org/sindresorhus/is-stream.svg?branch=master)](https://travis-ci.org/sindresorhus/is-stream)
|
||||
|
||||
> Check if something is a [Node.js stream](https://nodejs.org/api/stream.html)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-stream
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const isStream = require('is-stream');
|
||||
|
||||
isStream(fs.createReadStream('unicorn.png'));
|
||||
//=> true
|
||||
|
||||
isStream({});
|
||||
//=> false
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### isStream(stream)
|
||||
|
||||
#### isStream.writable(stream)
|
||||
|
||||
#### isStream.readable(stream)
|
||||
|
||||
#### isStream.duplex(stream)
|
||||
|
||||
#### isStream.transform(stream)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
|
||||
const isWsl = () => {
|
||||
if (process.platform !== 'linux') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (os.release().includes('Microsoft')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return fs.readFileSync('/proc/version', 'utf8').includes('Microsoft');
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.__IS_WSL_TEST__) {
|
||||
module.exports = isWsl;
|
||||
} else {
|
||||
module.exports = isWsl();
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"is-wsl@^1.1.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/open"
|
||||
]
|
||||
],
|
||||
"_from": "is-wsl@>=1.1.0 <2.0.0",
|
||||
"_id": "is-wsl@1.1.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/is-wsl",
|
||||
"_nodeVersion": "4.7.3",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/is-wsl-1.1.0.tgz_1492407587032_0.143065512413159"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.11",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "is-wsl",
|
||||
"raw": "is-wsl@^1.1.0",
|
||||
"rawSpec": "^1.1.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/open"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
|
||||
"_shasum": "1f16e4aa22b04d1336b66188a66af3c600c3a66d",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "is-wsl@^1.1.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/open",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/is-wsl/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Check if the process is running inside Windows Subsystem for Linux (Bash on Windows)",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"clear-require": "^2.0.0",
|
||||
"proxyquire": "^1.7.11",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "1f16e4aa22b04d1336b66188a66af3c600c3a66d",
|
||||
"tarball": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "60ea5d57a51ee596cb144ef47187c0476a5a421b",
|
||||
"homepage": "https://github.com/sindresorhus/is-wsl#readme",
|
||||
"keywords": [
|
||||
"bash",
|
||||
"check",
|
||||
"console",
|
||||
"detect",
|
||||
"is",
|
||||
"linux",
|
||||
"process",
|
||||
"subsystem",
|
||||
"terminal",
|
||||
"windows",
|
||||
"wsl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "is-wsl",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/is-wsl.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "1.1.0"
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# is-wsl [![Build Status](https://travis-ci.org/sindresorhus/is-wsl.svg?branch=master)](https://travis-ci.org/sindresorhus/is-wsl)
|
||||
|
||||
> Check if the process is running inside [Windows Subsystem for Linux](https://msdn.microsoft.com/commandline/wsl/about) (Bash on Windows)
|
||||
|
||||
Can be useful if you need to work around unimplemented or buggy features in WSL.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-wsl
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const isWsl = require('is-wsl');
|
||||
|
||||
// When running inside Windows Subsystem for Linux
|
||||
console.log(isWsl);
|
||||
//=> true
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,2 @@
|
|||
.nyc_output/
|
||||
coverage/
|
|
@ -0,0 +1,15 @@
|
|||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and 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.
|
|
@ -0,0 +1,51 @@
|
|||
# isexe
|
||||
|
||||
Minimal module to check if a file is executable, and a normal file.
|
||||
|
||||
Uses `fs.stat` and tests against the `PATHEXT` environment variable on
|
||||
Windows.
|
||||
|
||||
## USAGE
|
||||
|
||||
```javascript
|
||||
var isexe = require('isexe')
|
||||
isexe('some-file-name', function (err, isExe) {
|
||||
if (err) {
|
||||
console.error('probably file does not exist or something', err)
|
||||
} else if (isExe) {
|
||||
console.error('this thing can be run')
|
||||
} else {
|
||||
console.error('cannot be run')
|
||||
}
|
||||
})
|
||||
|
||||
// same thing but synchronous, throws errors
|
||||
var isExe = isexe.sync('some-file-name')
|
||||
|
||||
// treat errors as just "not executable"
|
||||
isexe('maybe-missing-file', { ignoreErrors: true }, callback)
|
||||
var isExe = isexe.sync('maybe-missing-file', { ignoreErrors: true })
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `isexe(path, [options], [callback])`
|
||||
|
||||
Check if the path is executable. If no callback provided, and a
|
||||
global `Promise` object is available, then a Promise will be returned.
|
||||
|
||||
Will raise whatever errors may be raised by `fs.stat`, unless
|
||||
`options.ignoreErrors` is set to true.
|
||||
|
||||
### `isexe.sync(path, [options])`
|
||||
|
||||
Same as `isexe` but returns the value and throws any errors raised.
|
||||
|
||||
### Options
|
||||
|
||||
* `ignoreErrors` Treat all errors as "no, this is not executable", but
|
||||
don't raise them.
|
||||
* `uid` Number to use as the user id
|
||||
* `gid` Number to use as the group id
|
||||
* `pathExt` List of path extensions to use instead of `PATHEXT`
|
||||
environment variable on Windows.
|
|
@ -0,0 +1,57 @@
|
|||
var fs = require('fs')
|
||||
var core
|
||||
if (process.platform === 'win32' || global.TESTING_WINDOWS) {
|
||||
core = require('./windows.js')
|
||||
} else {
|
||||
core = require('./mode.js')
|
||||
}
|
||||
|
||||
module.exports = isexe
|
||||
isexe.sync = sync
|
||||
|
||||
function isexe (path, options, cb) {
|
||||
if (typeof options === 'function') {
|
||||
cb = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
if (!cb) {
|
||||
if (typeof Promise !== 'function') {
|
||||
throw new TypeError('callback not provided')
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
isexe(path, options || {}, function (er, is) {
|
||||
if (er) {
|
||||
reject(er)
|
||||
} else {
|
||||
resolve(is)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
core(path, options || {}, function (er, is) {
|
||||
// ignore EACCES because that just means we aren't allowed to run it
|
||||
if (er) {
|
||||
if (er.code === 'EACCES' || options && options.ignoreErrors) {
|
||||
er = null
|
||||
is = false
|
||||
}
|
||||
}
|
||||
cb(er, is)
|
||||
})
|
||||
}
|
||||
|
||||
function sync (path, options) {
|
||||
// my kingdom for a filtered catch
|
||||
try {
|
||||
return core.sync(path, options || {})
|
||||
} catch (er) {
|
||||
if (options && options.ignoreErrors || er.code === 'EACCES') {
|
||||
return false
|
||||
} else {
|
||||
throw er
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
module.exports = isexe
|
||||
isexe.sync = sync
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
function isexe (path, options, cb) {
|
||||
fs.stat(path, function (er, stat) {
|
||||
cb(er, er ? false : checkStat(stat, options))
|
||||
})
|
||||
}
|
||||
|
||||
function sync (path, options) {
|
||||
return checkStat(fs.statSync(path), options)
|
||||
}
|
||||
|
||||
function checkStat (stat, options) {
|
||||
return stat.isFile() && checkMode(stat, options)
|
||||
}
|
||||
|
||||
function checkMode (stat, options) {
|
||||
var mod = stat.mode
|
||||
var uid = stat.uid
|
||||
var gid = stat.gid
|
||||
|
||||
var myUid = options.uid !== undefined ?
|
||||
options.uid : process.getuid && process.getuid()
|
||||
var myGid = options.gid !== undefined ?
|
||||
options.gid : process.getgid && process.getgid()
|
||||
|
||||
var u = parseInt('100', 8)
|
||||
var g = parseInt('010', 8)
|
||||
var o = parseInt('001', 8)
|
||||
var ug = u | g
|
||||
|
||||
var ret = (mod & o) ||
|
||||
(mod & g) && gid === myGid ||
|
||||
(mod & u) && uid === myUid ||
|
||||
(mod & ug) && myUid === 0
|
||||
|
||||
return ret
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"isexe@^2.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/which"
|
||||
]
|
||||
],
|
||||
"_from": "isexe@>=2.0.0 <3.0.0",
|
||||
"_id": "isexe@2.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/isexe",
|
||||
"_nodeVersion": "8.0.0-pre",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/isexe-2.0.0.tgz_1490230396126_0.8949183595832437"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "i@izs.me",
|
||||
"name": "isaacs"
|
||||
},
|
||||
"_npmVersion": "4.4.2",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "isexe",
|
||||
"raw": "isexe@^2.0.0",
|
||||
"rawSpec": "^2.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=2.0.0 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/which"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"_shasum": "e8fbf374dc556ff8947a10dcb0572d633f2cfa10",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "isexe@^2.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/which",
|
||||
"author": {
|
||||
"email": "i@izs.me",
|
||||
"name": "Isaac Z. Schlueter",
|
||||
"url": "http://blog.izs.me/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/isexe/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Minimal module to check if a file is executable.",
|
||||
"devDependencies": {
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "^2.5.0",
|
||||
"tap": "^10.3.0"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "e8fbf374dc556ff8947a10dcb0572d633f2cfa10",
|
||||
"tarball": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
|
||||
},
|
||||
"gitHead": "10f8be491aab2e158c7e20df64a7f90ab5b5475c",
|
||||
"homepage": "https://github.com/isaacs/isexe#readme",
|
||||
"keywords": [],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
}
|
||||
],
|
||||
"name": "isexe",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/isaacs/isexe.git"
|
||||
},
|
||||
"scripts": {
|
||||
"postpublish": "git push origin --all; git push origin --tags",
|
||||
"postversion": "npm publish",
|
||||
"preversion": "npm test",
|
||||
"test": "tap test/*.js --100"
|
||||
},
|
||||
"version": "2.0.0"
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
var t = require('tap')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var fixture = path.resolve(__dirname, 'fixtures')
|
||||
var meow = fixture + '/meow.cat'
|
||||
var mine = fixture + '/mine.cat'
|
||||
var ours = fixture + '/ours.cat'
|
||||
var fail = fixture + '/fail.false'
|
||||
var noent = fixture + '/enoent.exe'
|
||||
var mkdirp = require('mkdirp')
|
||||
var rimraf = require('rimraf')
|
||||
|
||||
var isWindows = process.platform === 'win32'
|
||||
var hasAccess = typeof fs.access === 'function'
|
||||
var winSkip = isWindows && 'windows'
|
||||
var accessSkip = !hasAccess && 'no fs.access function'
|
||||
var hasPromise = typeof Promise === 'function'
|
||||
var promiseSkip = !hasPromise && 'no global Promise'
|
||||
|
||||
function reset () {
|
||||
delete require.cache[require.resolve('../')]
|
||||
return require('../')
|
||||
}
|
||||
|
||||
t.test('setup fixtures', function (t) {
|
||||
rimraf.sync(fixture)
|
||||
mkdirp.sync(fixture)
|
||||
fs.writeFileSync(meow, '#!/usr/bin/env cat\nmeow\n')
|
||||
fs.chmodSync(meow, parseInt('0755', 8))
|
||||
fs.writeFileSync(fail, '#!/usr/bin/env false\n')
|
||||
fs.chmodSync(fail, parseInt('0644', 8))
|
||||
fs.writeFileSync(mine, '#!/usr/bin/env cat\nmine\n')
|
||||
fs.chmodSync(mine, parseInt('0744', 8))
|
||||
fs.writeFileSync(ours, '#!/usr/bin/env cat\nours\n')
|
||||
fs.chmodSync(ours, parseInt('0754', 8))
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('promise', { skip: promiseSkip }, function (t) {
|
||||
var isexe = reset()
|
||||
t.test('meow async', function (t) {
|
||||
isexe(meow).then(function (is) {
|
||||
t.ok(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
t.test('fail async', function (t) {
|
||||
isexe(fail).then(function (is) {
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
t.test('noent async', function (t) {
|
||||
isexe(noent).catch(function (er) {
|
||||
t.ok(er)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
t.test('noent ignore async', function (t) {
|
||||
isexe(noent, { ignoreErrors: true }).then(function (is) {
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('no promise', function (t) {
|
||||
global.Promise = null
|
||||
var isexe = reset()
|
||||
t.throws('try to meow a promise', function () {
|
||||
isexe(meow)
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('access', { skip: accessSkip || winSkip }, function (t) {
|
||||
runTest(t)
|
||||
})
|
||||
|
||||
t.test('mode', { skip: winSkip }, function (t) {
|
||||
delete fs.access
|
||||
delete fs.accessSync
|
||||
var isexe = reset()
|
||||
t.ok(isexe.sync(ours, { uid: 0, gid: 0 }))
|
||||
t.ok(isexe.sync(mine, { uid: 0, gid: 0 }))
|
||||
runTest(t)
|
||||
})
|
||||
|
||||
t.test('windows', function (t) {
|
||||
global.TESTING_WINDOWS = true
|
||||
var pathExt = '.EXE;.CAT;.CMD;.COM'
|
||||
t.test('pathExt option', function (t) {
|
||||
runTest(t, { pathExt: '.EXE;.CAT;.CMD;.COM' })
|
||||
})
|
||||
t.test('pathExt env', function (t) {
|
||||
process.env.PATHEXT = pathExt
|
||||
runTest(t)
|
||||
})
|
||||
t.test('no pathExt', function (t) {
|
||||
// with a pathExt of '', any filename is fine.
|
||||
// so the "fail" one would still pass.
|
||||
runTest(t, { pathExt: '', skipFail: true })
|
||||
})
|
||||
t.test('pathext with empty entry', function (t) {
|
||||
// with a pathExt of '', any filename is fine.
|
||||
// so the "fail" one would still pass.
|
||||
runTest(t, { pathExt: ';' + pathExt, skipFail: true })
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('cleanup', function (t) {
|
||||
rimraf.sync(fixture)
|
||||
t.end()
|
||||
})
|
||||
|
||||
function runTest (t, options) {
|
||||
var isexe = reset()
|
||||
|
||||
var optionsIgnore = Object.create(options || {})
|
||||
optionsIgnore.ignoreErrors = true
|
||||
|
||||
if (!options || !options.skipFail) {
|
||||
t.notOk(isexe.sync(fail, options))
|
||||
}
|
||||
t.notOk(isexe.sync(noent, optionsIgnore))
|
||||
if (!options) {
|
||||
t.ok(isexe.sync(meow))
|
||||
} else {
|
||||
t.ok(isexe.sync(meow, options))
|
||||
}
|
||||
|
||||
t.ok(isexe.sync(mine, options))
|
||||
t.ok(isexe.sync(ours, options))
|
||||
t.throws(function () {
|
||||
isexe.sync(noent, options)
|
||||
})
|
||||
|
||||
t.test('meow async', function (t) {
|
||||
if (!options) {
|
||||
isexe(meow, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.ok(is)
|
||||
t.end()
|
||||
})
|
||||
} else {
|
||||
isexe(meow, options, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.ok(is)
|
||||
t.end()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.test('mine async', function (t) {
|
||||
isexe(mine, options, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.ok(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('ours async', function (t) {
|
||||
isexe(ours, options, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.ok(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
if (!options || !options.skipFail) {
|
||||
t.test('fail async', function (t) {
|
||||
isexe(fail, options, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
t.test('noent async', function (t) {
|
||||
isexe(noent, options, function (er, is) {
|
||||
t.ok(er)
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('noent ignore async', function (t) {
|
||||
isexe(noent, optionsIgnore, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('directory is not executable', function (t) {
|
||||
isexe(__dirname, options, function (er, is) {
|
||||
if (er) {
|
||||
throw er
|
||||
}
|
||||
t.notOk(is)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
module.exports = isexe
|
||||
isexe.sync = sync
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
function checkPathExt (path, options) {
|
||||
var pathext = options.pathExt !== undefined ?
|
||||
options.pathExt : process.env.PATHEXT
|
||||
|
||||
if (!pathext) {
|
||||
return true
|
||||
}
|
||||
|
||||
pathext = pathext.split(';')
|
||||
if (pathext.indexOf('') !== -1) {
|
||||
return true
|
||||
}
|
||||
for (var i = 0; i < pathext.length; i++) {
|
||||
var p = pathext[i].toLowerCase()
|
||||
if (p && path.substr(-p.length).toLowerCase() === p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function checkStat (stat, path, options) {
|
||||
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
||||
return false
|
||||
}
|
||||
return checkPathExt(path, options)
|
||||
}
|
||||
|
||||
function isexe (path, options, cb) {
|
||||
fs.stat(path, function (er, stat) {
|
||||
cb(er, er ? false : checkStat(stat, path, options))
|
||||
})
|
||||
}
|
||||
|
||||
function sync (path, options) {
|
||||
return checkStat(fs.statSync(path), path, options)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
var invertKv = require('invert-kv');
|
||||
var all = require('./lcid.json');
|
||||
var inverted = invertKv(all);
|
||||
|
||||
exports.from = function (lcidCode) {
|
||||
if (typeof lcidCode !== 'number') {
|
||||
throw new TypeError('Expected a number');
|
||||
}
|
||||
|
||||
return inverted[lcidCode];
|
||||
};
|
||||
|
||||
exports.to = function (localeId) {
|
||||
if (typeof localeId !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
}
|
||||
|
||||
return all[localeId];
|
||||
};
|
||||
|
||||
exports.all = all;
|
|
@ -0,0 +1,203 @@
|
|||
{
|
||||
"af_ZA": 1078,
|
||||
"am_ET": 1118,
|
||||
"ar_AE": 14337,
|
||||
"ar_BH": 15361,
|
||||
"ar_DZ": 5121,
|
||||
"ar_EG": 3073,
|
||||
"ar_IQ": 2049,
|
||||
"ar_JO": 11265,
|
||||
"ar_KW": 13313,
|
||||
"ar_LB": 12289,
|
||||
"ar_LY": 4097,
|
||||
"ar_MA": 6145,
|
||||
"ar_OM": 8193,
|
||||
"ar_QA": 16385,
|
||||
"ar_SA": 1025,
|
||||
"ar_SY": 10241,
|
||||
"ar_TN": 7169,
|
||||
"ar_YE": 9217,
|
||||
"arn_CL": 1146,
|
||||
"as_IN": 1101,
|
||||
"az_AZ": 2092,
|
||||
"ba_RU": 1133,
|
||||
"be_BY": 1059,
|
||||
"bg_BG": 1026,
|
||||
"bn_IN": 1093,
|
||||
"bo_BT": 2129,
|
||||
"bo_CN": 1105,
|
||||
"br_FR": 1150,
|
||||
"bs_BA": 8218,
|
||||
"ca_ES": 1027,
|
||||
"co_FR": 1155,
|
||||
"cs_CZ": 1029,
|
||||
"cy_GB": 1106,
|
||||
"da_DK": 1030,
|
||||
"de_AT": 3079,
|
||||
"de_CH": 2055,
|
||||
"de_DE": 1031,
|
||||
"de_LI": 5127,
|
||||
"de_LU": 4103,
|
||||
"div_MV": 1125,
|
||||
"dsb_DE": 2094,
|
||||
"el_GR": 1032,
|
||||
"en_AU": 3081,
|
||||
"en_BZ": 10249,
|
||||
"en_CA": 4105,
|
||||
"en_CB": 9225,
|
||||
"en_GB": 2057,
|
||||
"en_IE": 6153,
|
||||
"en_IN": 18441,
|
||||
"en_JA": 8201,
|
||||
"en_MY": 17417,
|
||||
"en_NZ": 5129,
|
||||
"en_PH": 13321,
|
||||
"en_TT": 11273,
|
||||
"en_US": 1033,
|
||||
"en_ZA": 7177,
|
||||
"en_ZW": 12297,
|
||||
"es_AR": 11274,
|
||||
"es_BO": 16394,
|
||||
"es_CL": 13322,
|
||||
"es_CO": 9226,
|
||||
"es_CR": 5130,
|
||||
"es_DO": 7178,
|
||||
"es_EC": 12298,
|
||||
"es_ES": 3082,
|
||||
"es_GT": 4106,
|
||||
"es_HN": 18442,
|
||||
"es_MX": 2058,
|
||||
"es_NI": 19466,
|
||||
"es_PA": 6154,
|
||||
"es_PE": 10250,
|
||||
"es_PR": 20490,
|
||||
"es_PY": 15370,
|
||||
"es_SV": 17418,
|
||||
"es_UR": 14346,
|
||||
"es_US": 21514,
|
||||
"es_VE": 8202,
|
||||
"et_EE": 1061,
|
||||
"eu_ES": 1069,
|
||||
"fa_IR": 1065,
|
||||
"fi_FI": 1035,
|
||||
"fil_PH": 1124,
|
||||
"fo_FO": 1080,
|
||||
"fr_BE": 2060,
|
||||
"fr_CA": 3084,
|
||||
"fr_CH": 4108,
|
||||
"fr_FR": 1036,
|
||||
"fr_LU": 5132,
|
||||
"fr_MC": 6156,
|
||||
"fy_NL": 1122,
|
||||
"ga_IE": 2108,
|
||||
"gbz_AF": 1164,
|
||||
"gl_ES": 1110,
|
||||
"gsw_FR": 1156,
|
||||
"gu_IN": 1095,
|
||||
"ha_NG": 1128,
|
||||
"he_IL": 1037,
|
||||
"hi_IN": 1081,
|
||||
"hr_BA": 4122,
|
||||
"hr_HR": 1050,
|
||||
"hu_HU": 1038,
|
||||
"hy_AM": 1067,
|
||||
"id_ID": 1057,
|
||||
"ii_CN": 1144,
|
||||
"is_IS": 1039,
|
||||
"it_CH": 2064,
|
||||
"it_IT": 1040,
|
||||
"iu_CA": 2141,
|
||||
"ja_JP": 1041,
|
||||
"ka_GE": 1079,
|
||||
"kh_KH": 1107,
|
||||
"kk_KZ": 1087,
|
||||
"kl_GL": 1135,
|
||||
"kn_IN": 1099,
|
||||
"ko_KR": 1042,
|
||||
"kok_IN": 1111,
|
||||
"ky_KG": 1088,
|
||||
"lb_LU": 1134,
|
||||
"lo_LA": 1108,
|
||||
"lt_LT": 1063,
|
||||
"lv_LV": 1062,
|
||||
"mi_NZ": 1153,
|
||||
"mk_MK": 1071,
|
||||
"ml_IN": 1100,
|
||||
"mn_CN": 2128,
|
||||
"mn_MN": 1104,
|
||||
"moh_CA": 1148,
|
||||
"mr_IN": 1102,
|
||||
"ms_BN": 2110,
|
||||
"ms_MY": 1086,
|
||||
"mt_MT": 1082,
|
||||
"my_MM": 1109,
|
||||
"nb_NO": 1044,
|
||||
"ne_NP": 1121,
|
||||
"nl_BE": 2067,
|
||||
"nl_NL": 1043,
|
||||
"nn_NO": 2068,
|
||||
"ns_ZA": 1132,
|
||||
"oc_FR": 1154,
|
||||
"or_IN": 1096,
|
||||
"pa_IN": 1094,
|
||||
"pl_PL": 1045,
|
||||
"ps_AF": 1123,
|
||||
"pt_BR": 1046,
|
||||
"pt_PT": 2070,
|
||||
"qut_GT": 1158,
|
||||
"quz_BO": 1131,
|
||||
"quz_EC": 2155,
|
||||
"quz_PE": 3179,
|
||||
"rm_CH": 1047,
|
||||
"ro_RO": 1048,
|
||||
"ru_RU": 1049,
|
||||
"rw_RW": 1159,
|
||||
"sa_IN": 1103,
|
||||
"sah_RU": 1157,
|
||||
"se_FI": 3131,
|
||||
"se_NO": 1083,
|
||||
"se_SE": 2107,
|
||||
"si_LK": 1115,
|
||||
"sk_SK": 1051,
|
||||
"sl_SI": 1060,
|
||||
"sma_NO": 6203,
|
||||
"sma_SE": 7227,
|
||||
"smj_NO": 4155,
|
||||
"smj_SE": 5179,
|
||||
"smn_FI": 9275,
|
||||
"sms_FI": 8251,
|
||||
"sq_AL": 1052,
|
||||
"sr_BA": 7194,
|
||||
"sr_SP": 3098,
|
||||
"sv_FI": 2077,
|
||||
"sv_SE": 1053,
|
||||
"sw_KE": 1089,
|
||||
"syr_SY": 1114,
|
||||
"ta_IN": 1097,
|
||||
"te_IN": 1098,
|
||||
"tg_TJ": 1064,
|
||||
"th_TH": 1054,
|
||||
"tk_TM": 1090,
|
||||
"tmz_DZ": 2143,
|
||||
"tn_ZA": 1074,
|
||||
"tr_TR": 1055,
|
||||
"tt_RU": 1092,
|
||||
"ug_CN": 1152,
|
||||
"uk_UA": 1058,
|
||||
"ur_IN": 2080,
|
||||
"ur_PK": 1056,
|
||||
"uz_UZ": 2115,
|
||||
"vi_VN": 1066,
|
||||
"wen_DE": 1070,
|
||||
"wo_SN": 1160,
|
||||
"xh_ZA": 1076,
|
||||
"yo_NG": 1130,
|
||||
"zh_CHS": 4,
|
||||
"zh_CHT": 31748,
|
||||
"zh_CN": 2052,
|
||||
"zh_HK": 3076,
|
||||
"zh_MO": 5124,
|
||||
"zh_SG": 4100,
|
||||
"zh_TW": 1028,
|
||||
"zu_ZA": 1077
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"lcid@^1.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale"
|
||||
]
|
||||
],
|
||||
"_from": "lcid@>=1.0.0 <2.0.0",
|
||||
"_id": "lcid@1.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/lcid",
|
||||
"_nodeVersion": "0.12.0",
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.5.1",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "lcid",
|
||||
"raw": "lcid@^1.0.0",
|
||||
"rawSpec": "^1.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.0.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/os-locale"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
||||
"_shasum": "308accafa0bc483a3867b4b6f2b9506251d1b835",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "lcid@^1.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/lcid/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"invert-kv": "^1.0.0"
|
||||
},
|
||||
"description": "Mapping between standard locale identifiers and Windows locale identifiers (LCID)",
|
||||
"devDependencies": {
|
||||
"ava": "0.0.4"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "308accafa0bc483a3867b4b6f2b9506251d1b835",
|
||||
"tarball": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lcid.json"
|
||||
],
|
||||
"gitHead": "96bb3e617f77f5f8ceb78653c77de5a85abb3b1e",
|
||||
"homepage": "https://github.com/sindresorhus/lcid",
|
||||
"keywords": [
|
||||
"bcp47",
|
||||
"convert",
|
||||
"id",
|
||||
"identifier",
|
||||
"ietf",
|
||||
"json",
|
||||
"lang",
|
||||
"language",
|
||||
"lcid",
|
||||
"locale",
|
||||
"map",
|
||||
"mapping",
|
||||
"str",
|
||||
"string",
|
||||
"tag",
|
||||
"windows"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "lcid",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/lcid.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
# lcid [![Build Status](https://travis-ci.org/sindresorhus/lcid.svg?branch=master)](https://travis-ci.org/sindresorhus/lcid)
|
||||
|
||||
> Mapping between [standard locale identifiers](http://en.wikipedia.org/wiki/Locale) and [Windows locale identifiers (LCID)](http://en.wikipedia.org/wiki/Locale#Specifics_for_Microsoft_platforms)
|
||||
|
||||
Based on the [mapping](https://github.com/python/cpython/blob/be2a1a76fa43bb1ea1b3577bb5bdd506a2e90e37/Lib/locale.py#L1395-L1604) used in the Python standard library.
|
||||
|
||||
The mapping itself is just a [JSON file](lcid.json) and can be used wherever.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save lcid
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var lcid = require('lcid');
|
||||
|
||||
lcid.from(1044);
|
||||
//=> 'nb_NO'
|
||||
|
||||
lcid.to('nb_NO');
|
||||
//=> 1044
|
||||
|
||||
lcid.all;
|
||||
//=> {'af_ZA': 1078, ...}
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
const path = require('path');
|
||||
const pathExists = require('path-exists');
|
||||
const pLocate = require('p-locate');
|
||||
|
||||
module.exports = (iterable, opts) => {
|
||||
opts = Object.assign({
|
||||
cwd: process.cwd()
|
||||
}, opts);
|
||||
|
||||
return pLocate(iterable, el => pathExists(path.resolve(opts.cwd, el)), opts);
|
||||
};
|
||||
|
||||
module.exports.sync = (iterable, opts) => {
|
||||
opts = Object.assign({
|
||||
cwd: process.cwd()
|
||||
}, opts);
|
||||
|
||||
for (const el of iterable) {
|
||||
if (pathExists.sync(path.resolve(opts.cwd, el))) {
|
||||
return el;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"locate-path@^2.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs/node_modules/find-up"
|
||||
]
|
||||
],
|
||||
"_from": "locate-path@>=2.0.0 <3.0.0",
|
||||
"_id": "locate-path@2.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/locate-path",
|
||||
"_nodeVersion": "7.2.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/locate-path-2.0.0.tgz_1480310853492_0.9661909360438585"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "3.10.9",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "locate-path",
|
||||
"raw": "locate-path@^2.0.0",
|
||||
"rawSpec": "^2.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=2.0.0 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/yargs/find-up"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"_shasum": "2b568b265eec944c6d9c0de9c3dbbbca0354cd8e",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "locate-path@^2.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/yargs/node_modules/find-up",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/locate-path/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
},
|
||||
"description": "Get the first path that exists on disk of multiple paths",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "2b568b265eec944c6d9c0de9c3dbbbca0354cd8e",
|
||||
"tarball": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "a30b86df0934329c66ff6a2be395db03d65478b8",
|
||||
"homepage": "https://github.com/sindresorhus/locate-path#readme",
|
||||
"keywords": [
|
||||
"array",
|
||||
"exists",
|
||||
"file",
|
||||
"files",
|
||||
"find",
|
||||
"finder",
|
||||
"iterable",
|
||||
"iterator",
|
||||
"locate",
|
||||
"path",
|
||||
"paths",
|
||||
"search",
|
||||
"searcher"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "locate-path",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/locate-path.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
# locate-path [![Build Status](https://travis-ci.org/sindresorhus/locate-path.svg?branch=master)](https://travis-ci.org/sindresorhus/locate-path)
|
||||
|
||||
> Get the first path that exists on disk of multiple paths
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save locate-path
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Here we find the first file that exists on disk, in array order.
|
||||
|
||||
```js
|
||||
const locatePath = require('locate-path');
|
||||
|
||||
const files = [
|
||||
'unicorn.png',
|
||||
'rainbow.png', // only this one actually exists on disk
|
||||
'pony.png'
|
||||
];
|
||||
|
||||
locatePath(files).then(foundPath => {
|
||||
console.log(foundPath);
|
||||
//=> 'rainbow'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### locatePath(input, [options])
|
||||
|
||||
Returns a `Promise` for the first path that exists or `undefined` if none exists.
|
||||
|
||||
#### input
|
||||
|
||||
Type: `Iterable<string>`
|
||||
|
||||
Paths to check.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
##### concurrency
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `Infinity`<br>
|
||||
Minimum: `1`
|
||||
|
||||
Number of concurrently pending promises.
|
||||
|
||||
##### preserveOrder
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Preserve `input` order when searching.
|
||||
|
||||
Disable this to improve performance if you don't care about the order.
|
||||
|
||||
##### cwd
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `process.cwd()`
|
||||
|
||||
Current working directory.
|
||||
|
||||
### locatePath.sync(input, [options])
|
||||
|
||||
Returns the first path that exists or `undefined` if none exists.
|
||||
|
||||
#### input
|
||||
|
||||
Type: `Iterable<string>`
|
||||
|
||||
Paths to check.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
##### cwd
|
||||
|
||||
Same as above.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [path-exists](https://github.com/sindresorhus/path-exists) - Check if a path exists
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,15 @@
|
|||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and 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.
|
|
@ -0,0 +1,158 @@
|
|||
# lru cache
|
||||
|
||||
A cache object that deletes the least-recently-used items.
|
||||
|
||||
[![Build Status](https://travis-ci.org/isaacs/node-lru-cache.svg?branch=master)](https://travis-ci.org/isaacs/node-lru-cache) [![Coverage Status](https://coveralls.io/repos/isaacs/node-lru-cache/badge.svg?service=github)](https://coveralls.io/github/isaacs/node-lru-cache)
|
||||
|
||||
## Installation:
|
||||
|
||||
```javascript
|
||||
npm install lru-cache --save
|
||||
```
|
||||
|
||||
## Usage:
|
||||
|
||||
```javascript
|
||||
var LRU = require("lru-cache")
|
||||
, options = { max: 500
|
||||
, length: function (n, key) { return n * 2 + key.length }
|
||||
, dispose: function (key, n) { n.close() }
|
||||
, maxAge: 1000 * 60 * 60 }
|
||||
, cache = LRU(options)
|
||||
, otherCache = LRU(50) // sets just the max size
|
||||
|
||||
cache.set("key", "value")
|
||||
cache.get("key") // "value"
|
||||
|
||||
// non-string keys ARE fully supported
|
||||
// but note that it must be THE SAME object, not
|
||||
// just a JSON-equivalent object.
|
||||
var someObject = { a: 1 }
|
||||
cache.set(someObject, 'a value')
|
||||
// Object keys are not toString()-ed
|
||||
cache.set('[object Object]', 'a different value')
|
||||
assert.equal(cache.get(someObject), 'a value')
|
||||
// A similar object with same keys/values won't work,
|
||||
// because it's a different object identity
|
||||
assert.equal(cache.get({ a: 1 }), undefined)
|
||||
|
||||
cache.reset() // empty the cache
|
||||
```
|
||||
|
||||
If you put more stuff in it, then items will fall out.
|
||||
|
||||
If you try to put an oversized thing in it, then it'll fall out right
|
||||
away.
|
||||
|
||||
## Options
|
||||
|
||||
* `max` The maximum size of the cache, checked by applying the length
|
||||
function to all values in the cache. Not setting this is kind of
|
||||
silly, since that's the whole purpose of this lib, but it defaults
|
||||
to `Infinity`.
|
||||
* `maxAge` Maximum age in ms. Items are not pro-actively pruned out
|
||||
as they age, but if you try to get an item that is too old, it'll
|
||||
drop it and return undefined instead of giving it to you.
|
||||
* `length` Function that is used to calculate the length of stored
|
||||
items. If you're storing strings or buffers, then you probably want
|
||||
to do something like `function(n, key){return n.length}`. The default is
|
||||
`function(){return 1}`, which is fine if you want to store `max`
|
||||
like-sized things. The item is passed as the first argument, and
|
||||
the key is passed as the second argumnet.
|
||||
* `dispose` Function that is called on items when they are dropped
|
||||
from the cache. This can be handy if you want to close file
|
||||
descriptors or do other cleanup tasks when items are no longer
|
||||
accessible. Called with `key, value`. It's called *before*
|
||||
actually removing the item from the internal cache, so if you want
|
||||
to immediately put it back in, you'll have to do that in a
|
||||
`nextTick` or `setTimeout` callback or it won't do anything.
|
||||
* `stale` By default, if you set a `maxAge`, it'll only actually pull
|
||||
stale items out of the cache when you `get(key)`. (That is, it's
|
||||
not pre-emptively doing a `setTimeout` or anything.) If you set
|
||||
`stale:true`, it'll return the stale value before deleting it. If
|
||||
you don't set this, then it'll return `undefined` when you try to
|
||||
get a stale entry, as if it had already been deleted.
|
||||
* `noDisposeOnSet` By default, if you set a `dispose()` method, then
|
||||
it'll be called whenever a `set()` operation overwrites an existing
|
||||
key. If you set this option, `dispose()` will only be called when a
|
||||
key falls out of the cache, not when it is overwritten.
|
||||
|
||||
## API
|
||||
|
||||
* `set(key, value, maxAge)`
|
||||
* `get(key) => value`
|
||||
|
||||
Both of these will update the "recently used"-ness of the key.
|
||||
They do what you think. `maxAge` is optional and overrides the
|
||||
cache `maxAge` option if provided.
|
||||
|
||||
If the key is not found, `get()` will return `undefined`.
|
||||
|
||||
The key and val can be any value.
|
||||
|
||||
* `peek(key)`
|
||||
|
||||
Returns the key value (or `undefined` if not found) without
|
||||
updating the "recently used"-ness of the key.
|
||||
|
||||
(If you find yourself using this a lot, you *might* be using the
|
||||
wrong sort of data structure, but there are some use cases where
|
||||
it's handy.)
|
||||
|
||||
* `del(key)`
|
||||
|
||||
Deletes a key out of the cache.
|
||||
|
||||
* `reset()`
|
||||
|
||||
Clear the cache entirely, throwing away all values.
|
||||
|
||||
* `has(key)`
|
||||
|
||||
Check if a key is in the cache, without updating the recent-ness
|
||||
or deleting it for being stale.
|
||||
|
||||
* `forEach(function(value,key,cache), [thisp])`
|
||||
|
||||
Just like `Array.prototype.forEach`. Iterates over all the keys
|
||||
in the cache, in order of recent-ness. (Ie, more recently used
|
||||
items are iterated over first.)
|
||||
|
||||
* `rforEach(function(value,key,cache), [thisp])`
|
||||
|
||||
The same as `cache.forEach(...)` but items are iterated over in
|
||||
reverse order. (ie, less recently used items are iterated over
|
||||
first.)
|
||||
|
||||
* `keys()`
|
||||
|
||||
Return an array of the keys in the cache.
|
||||
|
||||
* `values()`
|
||||
|
||||
Return an array of the values in the cache.
|
||||
|
||||
* `length`
|
||||
|
||||
Return total length of objects in cache taking into account
|
||||
`length` options function.
|
||||
|
||||
* `itemCount`
|
||||
|
||||
Return total quantity of objects currently in cache. Note, that
|
||||
`stale` (see options) items are returned as part of this item
|
||||
count.
|
||||
|
||||
* `dump()`
|
||||
|
||||
Return an array of the cache entries ready for serialization and usage
|
||||
with 'destinationCache.load(arr)`.
|
||||
|
||||
* `load(cacheEntriesArray)`
|
||||
|
||||
Loads another cache entries array, obtained with `sourceCache.dump()`,
|
||||
into the cache. The destination cache is reset before loading new entries
|
||||
|
||||
* `prune()`
|
||||
|
||||
Manually iterates over the entire cache proactively pruning old entries
|
|
@ -0,0 +1,468 @@
|
|||
'use strict'
|
||||
|
||||
module.exports = LRUCache
|
||||
|
||||
// This will be a proper iterable 'Map' in engines that support it,
|
||||
// or a fakey-fake PseudoMap in older versions.
|
||||
var Map = require('pseudomap')
|
||||
var util = require('util')
|
||||
|
||||
// A linked list to keep track of recently-used-ness
|
||||
var Yallist = require('yallist')
|
||||
|
||||
// use symbols if possible, otherwise just _props
|
||||
var hasSymbol = typeof Symbol === 'function' && process.env._nodeLRUCacheForceNoSymbol !== '1'
|
||||
var makeSymbol
|
||||
if (hasSymbol) {
|
||||
makeSymbol = function (key) {
|
||||
return Symbol(key)
|
||||
}
|
||||
} else {
|
||||
makeSymbol = function (key) {
|
||||
return '_' + key
|
||||
}
|
||||
}
|
||||
|
||||
var MAX = makeSymbol('max')
|
||||
var LENGTH = makeSymbol('length')
|
||||
var LENGTH_CALCULATOR = makeSymbol('lengthCalculator')
|
||||
var ALLOW_STALE = makeSymbol('allowStale')
|
||||
var MAX_AGE = makeSymbol('maxAge')
|
||||
var DISPOSE = makeSymbol('dispose')
|
||||
var NO_DISPOSE_ON_SET = makeSymbol('noDisposeOnSet')
|
||||
var LRU_LIST = makeSymbol('lruList')
|
||||
var CACHE = makeSymbol('cache')
|
||||
|
||||
function naiveLength () { return 1 }
|
||||
|
||||
// lruList is a yallist where the head is the youngest
|
||||
// item, and the tail is the oldest. the list contains the Hit
|
||||
// objects as the entries.
|
||||
// Each Hit object has a reference to its Yallist.Node. This
|
||||
// never changes.
|
||||
//
|
||||
// cache is a Map (or PseudoMap) that matches the keys to
|
||||
// the Yallist.Node object.
|
||||
function LRUCache (options) {
|
||||
if (!(this instanceof LRUCache)) {
|
||||
return new LRUCache(options)
|
||||
}
|
||||
|
||||
if (typeof options === 'number') {
|
||||
options = { max: options }
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
|
||||
var max = this[MAX] = options.max
|
||||
// Kind of weird to have a default max of Infinity, but oh well.
|
||||
if (!max ||
|
||||
!(typeof max === 'number') ||
|
||||
max <= 0) {
|
||||
this[MAX] = Infinity
|
||||
}
|
||||
|
||||
var lc = options.length || naiveLength
|
||||
if (typeof lc !== 'function') {
|
||||
lc = naiveLength
|
||||
}
|
||||
this[LENGTH_CALCULATOR] = lc
|
||||
|
||||
this[ALLOW_STALE] = options.stale || false
|
||||
this[MAX_AGE] = options.maxAge || 0
|
||||
this[DISPOSE] = options.dispose
|
||||
this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false
|
||||
this.reset()
|
||||
}
|
||||
|
||||
// resize the cache when the max changes.
|
||||
Object.defineProperty(LRUCache.prototype, 'max', {
|
||||
set: function (mL) {
|
||||
if (!mL || !(typeof mL === 'number') || mL <= 0) {
|
||||
mL = Infinity
|
||||
}
|
||||
this[MAX] = mL
|
||||
trim(this)
|
||||
},
|
||||
get: function () {
|
||||
return this[MAX]
|
||||
},
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(LRUCache.prototype, 'allowStale', {
|
||||
set: function (allowStale) {
|
||||
this[ALLOW_STALE] = !!allowStale
|
||||
},
|
||||
get: function () {
|
||||
return this[ALLOW_STALE]
|
||||
},
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(LRUCache.prototype, 'maxAge', {
|
||||
set: function (mA) {
|
||||
if (!mA || !(typeof mA === 'number') || mA < 0) {
|
||||
mA = 0
|
||||
}
|
||||
this[MAX_AGE] = mA
|
||||
trim(this)
|
||||
},
|
||||
get: function () {
|
||||
return this[MAX_AGE]
|
||||
},
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
// resize the cache when the lengthCalculator changes.
|
||||
Object.defineProperty(LRUCache.prototype, 'lengthCalculator', {
|
||||
set: function (lC) {
|
||||
if (typeof lC !== 'function') {
|
||||
lC = naiveLength
|
||||
}
|
||||
if (lC !== this[LENGTH_CALCULATOR]) {
|
||||
this[LENGTH_CALCULATOR] = lC
|
||||
this[LENGTH] = 0
|
||||
this[LRU_LIST].forEach(function (hit) {
|
||||
hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key)
|
||||
this[LENGTH] += hit.length
|
||||
}, this)
|
||||
}
|
||||
trim(this)
|
||||
},
|
||||
get: function () { return this[LENGTH_CALCULATOR] },
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(LRUCache.prototype, 'length', {
|
||||
get: function () { return this[LENGTH] },
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(LRUCache.prototype, 'itemCount', {
|
||||
get: function () { return this[LRU_LIST].length },
|
||||
enumerable: true
|
||||
})
|
||||
|
||||
LRUCache.prototype.rforEach = function (fn, thisp) {
|
||||
thisp = thisp || this
|
||||
for (var walker = this[LRU_LIST].tail; walker !== null;) {
|
||||
var prev = walker.prev
|
||||
forEachStep(this, fn, walker, thisp)
|
||||
walker = prev
|
||||
}
|
||||
}
|
||||
|
||||
function forEachStep (self, fn, node, thisp) {
|
||||
var hit = node.value
|
||||
if (isStale(self, hit)) {
|
||||
del(self, node)
|
||||
if (!self[ALLOW_STALE]) {
|
||||
hit = undefined
|
||||
}
|
||||
}
|
||||
if (hit) {
|
||||
fn.call(thisp, hit.value, hit.key, self)
|
||||
}
|
||||
}
|
||||
|
||||
LRUCache.prototype.forEach = function (fn, thisp) {
|
||||
thisp = thisp || this
|
||||
for (var walker = this[LRU_LIST].head; walker !== null;) {
|
||||
var next = walker.next
|
||||
forEachStep(this, fn, walker, thisp)
|
||||
walker = next
|
||||
}
|
||||
}
|
||||
|
||||
LRUCache.prototype.keys = function () {
|
||||
return this[LRU_LIST].toArray().map(function (k) {
|
||||
return k.key
|
||||
}, this)
|
||||
}
|
||||
|
||||
LRUCache.prototype.values = function () {
|
||||
return this[LRU_LIST].toArray().map(function (k) {
|
||||
return k.value
|
||||
}, this)
|
||||
}
|
||||
|
||||
LRUCache.prototype.reset = function () {
|
||||
if (this[DISPOSE] &&
|
||||
this[LRU_LIST] &&
|
||||
this[LRU_LIST].length) {
|
||||
this[LRU_LIST].forEach(function (hit) {
|
||||
this[DISPOSE](hit.key, hit.value)
|
||||
}, this)
|
||||
}
|
||||
|
||||
this[CACHE] = new Map() // hash of items by key
|
||||
this[LRU_LIST] = new Yallist() // list of items in order of use recency
|
||||
this[LENGTH] = 0 // length of items in the list
|
||||
}
|
||||
|
||||
LRUCache.prototype.dump = function () {
|
||||
return this[LRU_LIST].map(function (hit) {
|
||||
if (!isStale(this, hit)) {
|
||||
return {
|
||||
k: hit.key,
|
||||
v: hit.value,
|
||||
e: hit.now + (hit.maxAge || 0)
|
||||
}
|
||||
}
|
||||
}, this).toArray().filter(function (h) {
|
||||
return h
|
||||
})
|
||||
}
|
||||
|
||||
LRUCache.prototype.dumpLru = function () {
|
||||
return this[LRU_LIST]
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
LRUCache.prototype.inspect = function (n, opts) {
|
||||
var str = 'LRUCache {'
|
||||
var extras = false
|
||||
|
||||
var as = this[ALLOW_STALE]
|
||||
if (as) {
|
||||
str += '\n allowStale: true'
|
||||
extras = true
|
||||
}
|
||||
|
||||
var max = this[MAX]
|
||||
if (max && max !== Infinity) {
|
||||
if (extras) {
|
||||
str += ','
|
||||
}
|
||||
str += '\n max: ' + util.inspect(max, opts)
|
||||
extras = true
|
||||
}
|
||||
|
||||
var maxAge = this[MAX_AGE]
|
||||
if (maxAge) {
|
||||
if (extras) {
|
||||
str += ','
|
||||
}
|
||||
str += '\n maxAge: ' + util.inspect(maxAge, opts)
|
||||
extras = true
|
||||
}
|
||||
|
||||
var lc = this[LENGTH_CALCULATOR]
|
||||
if (lc && lc !== naiveLength) {
|
||||
if (extras) {
|
||||
str += ','
|
||||
}
|
||||
str += '\n length: ' + util.inspect(this[LENGTH], opts)
|
||||
extras = true
|
||||
}
|
||||
|
||||
var didFirst = false
|
||||
this[LRU_LIST].forEach(function (item) {
|
||||
if (didFirst) {
|
||||
str += ',\n '
|
||||
} else {
|
||||
if (extras) {
|
||||
str += ',\n'
|
||||
}
|
||||
didFirst = true
|
||||
str += '\n '
|
||||
}
|
||||
var key = util.inspect(item.key).split('\n').join('\n ')
|
||||
var val = { value: item.value }
|
||||
if (item.maxAge !== maxAge) {
|
||||
val.maxAge = item.maxAge
|
||||
}
|
||||
if (lc !== naiveLength) {
|
||||
val.length = item.length
|
||||
}
|
||||
if (isStale(this, item)) {
|
||||
val.stale = true
|
||||
}
|
||||
|
||||
val = util.inspect(val, opts).split('\n').join('\n ')
|
||||
str += key + ' => ' + val
|
||||
})
|
||||
|
||||
if (didFirst || extras) {
|
||||
str += '\n'
|
||||
}
|
||||
str += '}'
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
LRUCache.prototype.set = function (key, value, maxAge) {
|
||||
maxAge = maxAge || this[MAX_AGE]
|
||||
|
||||
var now = maxAge ? Date.now() : 0
|
||||
var len = this[LENGTH_CALCULATOR](value, key)
|
||||
|
||||
if (this[CACHE].has(key)) {
|
||||
if (len > this[MAX]) {
|
||||
del(this, this[CACHE].get(key))
|
||||
return false
|
||||
}
|
||||
|
||||
var node = this[CACHE].get(key)
|
||||
var item = node.value
|
||||
|
||||
// dispose of the old one before overwriting
|
||||
// split out into 2 ifs for better coverage tracking
|
||||
if (this[DISPOSE]) {
|
||||
if (!this[NO_DISPOSE_ON_SET]) {
|
||||
this[DISPOSE](key, item.value)
|
||||
}
|
||||
}
|
||||
|
||||
item.now = now
|
||||
item.maxAge = maxAge
|
||||
item.value = value
|
||||
this[LENGTH] += len - item.length
|
||||
item.length = len
|
||||
this.get(key)
|
||||
trim(this)
|
||||
return true
|
||||
}
|
||||
|
||||
var hit = new Entry(key, value, len, now, maxAge)
|
||||
|
||||
// oversized objects fall out of cache automatically.
|
||||
if (hit.length > this[MAX]) {
|
||||
if (this[DISPOSE]) {
|
||||
this[DISPOSE](key, value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
this[LENGTH] += hit.length
|
||||
this[LRU_LIST].unshift(hit)
|
||||
this[CACHE].set(key, this[LRU_LIST].head)
|
||||
trim(this)
|
||||
return true
|
||||
}
|
||||
|
||||
LRUCache.prototype.has = function (key) {
|
||||
if (!this[CACHE].has(key)) return false
|
||||
var hit = this[CACHE].get(key).value
|
||||
if (isStale(this, hit)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
LRUCache.prototype.get = function (key) {
|
||||
return get(this, key, true)
|
||||
}
|
||||
|
||||
LRUCache.prototype.peek = function (key) {
|
||||
return get(this, key, false)
|
||||
}
|
||||
|
||||
LRUCache.prototype.pop = function () {
|
||||
var node = this[LRU_LIST].tail
|
||||
if (!node) return null
|
||||
del(this, node)
|
||||
return node.value
|
||||
}
|
||||
|
||||
LRUCache.prototype.del = function (key) {
|
||||
del(this, this[CACHE].get(key))
|
||||
}
|
||||
|
||||
LRUCache.prototype.load = function (arr) {
|
||||
// reset the cache
|
||||
this.reset()
|
||||
|
||||
var now = Date.now()
|
||||
// A previous serialized cache has the most recent items first
|
||||
for (var l = arr.length - 1; l >= 0; l--) {
|
||||
var hit = arr[l]
|
||||
var expiresAt = hit.e || 0
|
||||
if (expiresAt === 0) {
|
||||
// the item was created without expiration in a non aged cache
|
||||
this.set(hit.k, hit.v)
|
||||
} else {
|
||||
var maxAge = expiresAt - now
|
||||
// dont add already expired items
|
||||
if (maxAge > 0) {
|
||||
this.set(hit.k, hit.v, maxAge)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LRUCache.prototype.prune = function () {
|
||||
var self = this
|
||||
this[CACHE].forEach(function (value, key) {
|
||||
get(self, key, false)
|
||||
})
|
||||
}
|
||||
|
||||
function get (self, key, doUse) {
|
||||
var node = self[CACHE].get(key)
|
||||
if (node) {
|
||||
var hit = node.value
|
||||
if (isStale(self, hit)) {
|
||||
del(self, node)
|
||||
if (!self[ALLOW_STALE]) hit = undefined
|
||||
} else {
|
||||
if (doUse) {
|
||||
self[LRU_LIST].unshiftNode(node)
|
||||
}
|
||||
}
|
||||
if (hit) hit = hit.value
|
||||
}
|
||||
return hit
|
||||
}
|
||||
|
||||
function isStale (self, hit) {
|
||||
if (!hit || (!hit.maxAge && !self[MAX_AGE])) {
|
||||
return false
|
||||
}
|
||||
var stale = false
|
||||
var diff = Date.now() - hit.now
|
||||
if (hit.maxAge) {
|
||||
stale = diff > hit.maxAge
|
||||
} else {
|
||||
stale = self[MAX_AGE] && (diff > self[MAX_AGE])
|
||||
}
|
||||
return stale
|
||||
}
|
||||
|
||||
function trim (self) {
|
||||
if (self[LENGTH] > self[MAX]) {
|
||||
for (var walker = self[LRU_LIST].tail;
|
||||
self[LENGTH] > self[MAX] && walker !== null;) {
|
||||
// We know that we're about to delete this one, and also
|
||||
// what the next least recently used key will be, so just
|
||||
// go ahead and set it now.
|
||||
var prev = walker.prev
|
||||
del(self, walker)
|
||||
walker = prev
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function del (self, node) {
|
||||
if (node) {
|
||||
var hit = node.value
|
||||
if (self[DISPOSE]) {
|
||||
self[DISPOSE](hit.key, hit.value)
|
||||
}
|
||||
self[LENGTH] -= hit.length
|
||||
self[CACHE].delete(hit.key)
|
||||
self[LRU_LIST].removeNode(node)
|
||||
}
|
||||
}
|
||||
|
||||
// classy, since V8 prefers predictable objects.
|
||||
function Entry (key, value, length, now, maxAge) {
|
||||
this.key = key
|
||||
this.value = value
|
||||
this.length = length
|
||||
this.now = now
|
||||
this.maxAge = maxAge || 0
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
const mimicFn = require('mimic-fn');
|
||||
|
||||
const cacheStore = new WeakMap();
|
||||
|
||||
const defaultCacheKey = function (x) {
|
||||
if (arguments.length === 1 && (x === null || x === undefined || (typeof x !== 'function' && typeof x !== 'object'))) {
|
||||
return x;
|
||||
}
|
||||
|
||||
return JSON.stringify(arguments);
|
||||
};
|
||||
|
||||
module.exports = (fn, opts) => {
|
||||
opts = Object.assign({
|
||||
cacheKey: defaultCacheKey,
|
||||
cache: new Map()
|
||||
}, opts);
|
||||
|
||||
const memoized = function () {
|
||||
const cache = cacheStore.get(memoized);
|
||||
const key = opts.cacheKey.apply(null, arguments);
|
||||
|
||||
if (cache.has(key)) {
|
||||
const c = cache.get(key);
|
||||
|
||||
if (typeof opts.maxAge !== 'number' || Date.now() < c.maxAge) {
|
||||
return c.data;
|
||||
}
|
||||
}
|
||||
|
||||
const ret = fn.apply(null, arguments);
|
||||
|
||||
cache.set(key, {
|
||||
data: ret,
|
||||
maxAge: Date.now() + (opts.maxAge || 0)
|
||||
});
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
mimicFn(memoized, fn);
|
||||
|
||||
cacheStore.set(memoized, opts.cache);
|
||||
|
||||
return memoized;
|
||||
};
|
||||
|
||||
module.exports.clear = fn => {
|
||||
const cache = cacheStore.get(fn);
|
||||
|
||||
if (cache && typeof cache.clear === 'function') {
|
||||
cache.clear();
|
||||
}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
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.
|
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"mem@^1.1.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale"
|
||||
]
|
||||
],
|
||||
"_from": "mem@>=1.1.0 <2.0.0",
|
||||
"_id": "mem@1.1.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/mem",
|
||||
"_nodeVersion": "4.6.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/mem-1.1.0.tgz_1476900325889_0.8028518599458039"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "2.15.9",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "mem",
|
||||
"raw": "mem@^1.1.0",
|
||||
"rawSpec": "^1.1.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/os-locale"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
|
||||
"_shasum": "5edd52b485ca1d900fe64895505399a0dfa45f76",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "mem@^1.1.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/os-locale",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/mem/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
},
|
||||
"description": "Memoize functions - An optimization used to speed up consecutive function calls by caching the result of calls with identical input",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"delay": "^1.1.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "5edd52b485ca1d900fe64895505399a0dfa45f76",
|
||||
"tarball": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "c12270441fab7f42fe53cf97edd53c60c4a8268f",
|
||||
"homepage": "https://github.com/sindresorhus/mem#readme",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"expire",
|
||||
"function",
|
||||
"mem",
|
||||
"memoization",
|
||||
"memoize",
|
||||
"optimize",
|
||||
"performance",
|
||||
"promise",
|
||||
"ttl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "mem",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/mem.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "1.1.0",
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
# mem [![Build Status](https://travis-ci.org/sindresorhus/mem.svg?branch=master)](https://travis-ci.org/sindresorhus/mem)
|
||||
|
||||
> [Memoize](https://en.wikipedia.org/wiki/Memoization) functions - An optimization used to speed up consecutive function calls by caching the result of calls with identical input
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save mem
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const mem = require('mem');
|
||||
|
||||
let i = 0;
|
||||
const counter = () => ++i;
|
||||
const memoized = mem(counter);
|
||||
|
||||
memoized('foo');
|
||||
//=> 1
|
||||
|
||||
// cached as it's the same arguments
|
||||
memoized('foo');
|
||||
//=> 1
|
||||
|
||||
// not cached anymore as the arguments changed
|
||||
memoized('bar');
|
||||
//=> 2
|
||||
|
||||
memoized('bar');
|
||||
//=> 2
|
||||
```
|
||||
|
||||
##### Works fine with promise returning functions
|
||||
|
||||
```js
|
||||
const mem = require('mem');
|
||||
|
||||
let i = 0;
|
||||
const counter = () => Promise.resolve(++i);
|
||||
const memoized = mem(counter);
|
||||
|
||||
memoized().then(a => {
|
||||
console.log(a);
|
||||
//=> 1
|
||||
|
||||
memoized().then(b => {
|
||||
// the return value didn't increase as it's cached
|
||||
console.log(b);
|
||||
//=> 1
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```js
|
||||
const mem = require('mem');
|
||||
const got = require('got');
|
||||
const memGot = mem(got, {maxAge: 1000});
|
||||
|
||||
memGot('sindresorhus.com').then(() => {
|
||||
// this call is cached
|
||||
memGot('sindresorhus.com').then(() => {
|
||||
setTimeout(() => {
|
||||
// this call is not cached as the cache has expired
|
||||
memGot('sindresorhus.com').then(() => {});
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### mem(fn, [options])
|
||||
|
||||
#### fn
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Function to be memoized.
|
||||
|
||||
#### options
|
||||
|
||||
##### maxAge
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `Infinity`
|
||||
|
||||
Milliseconds until the cache expires.
|
||||
|
||||
##### cacheKey
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Determines the cache key for storing the result based on the function arguments. By default, if there's only one argument and it's a [primitive](https://developer.mozilla.org/en-US/docs/Glossary/Primitive), it's used directly as a key, otherwise it's all the function arguments JSON stringified as an array.
|
||||
|
||||
You could for example change it to only cache on the first argument `x => JSON.stringify(x)`.
|
||||
|
||||
##### cache
|
||||
|
||||
Type: `Object`<br>
|
||||
Default: `new Map()`
|
||||
|
||||
Use a different cache storage. Must implement the following methods: `.has(key)`, `.get(key)`, `.set(key, value)`, and optionally `.clear()`. You could for example use a `WeakMap` instead.
|
||||
|
||||
### mem.clear(fn)
|
||||
|
||||
Clear all cached data of a memoized function.
|
||||
|
||||
#### fn
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Memoized function.
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
### Cache statistics
|
||||
|
||||
If you want to know how many times your cache had a hit or a miss, you can make use of [stats-map](https://github.com/SamVerschueren/stats-map) as a replacement for the default cache.
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const mem = require('mem');
|
||||
const StatsMap = require('stats-map');
|
||||
const got = require('got');
|
||||
|
||||
const cache = new StatsMap();
|
||||
const memGot = mem(got, {cache});
|
||||
|
||||
memGot('sindresorhus.com')
|
||||
.then(() => memGot('sindresorhus.com'))
|
||||
.then(() => memGot('sindresorhus.com'));
|
||||
|
||||
console.log(cache.stats);
|
||||
//=> {hits: 2, misses: 1}
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
@ -0,0 +1,9 @@
|
|||
'use strict';
|
||||
module.exports = (to, from) => {
|
||||
// TODO: use `Reflect.ownKeys()` when targeting Node.js 6
|
||||
for (const prop of Object.getOwnPropertyNames(from).concat(Object.getOwnPropertySymbols(from))) {
|
||||
Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
|
||||
}
|
||||
|
||||
return to;
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
"mimic-fn@^1.0.0",
|
||||
"/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/mem"
|
||||
]
|
||||
],
|
||||
"_from": "mimic-fn@>=1.0.0 <2.0.0",
|
||||
"_id": "mimic-fn@1.2.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/mimic-fn",
|
||||
"_nodeVersion": "8.9.4",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "s3://npm-registry-packages",
|
||||
"tmp": "tmp/mimic-fn-1.2.0.tgz_1517542098165_0.264689544448629"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
"_npmVersion": "5.6.0",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "mimic-fn",
|
||||
"raw": "mimic-fn@^1.0.0",
|
||||
"rawSpec": "^1.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.0.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/mem"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
|
||||
"_shasum": "820c86a39334640e99516928bd03fca88057d022",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "mimic-fn@^1.0.0",
|
||||
"_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client/node_modules/mem",
|
||||
"author": {
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "Sindre Sorhus",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/mimic-fn/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Make a function mimic another one",
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
|
||||
"shasum": "820c86a39334640e99516928bd03fca88057d022",
|
||||
"tarball": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "d762fc495eef1e48718e1f39b82c39ff5e95dfe4",
|
||||
"homepage": "https://github.com/sindresorhus/mimic-fn#readme",
|
||||
"keywords": [
|
||||
"change",
|
||||
"copy",
|
||||
"fn",
|
||||
"func",
|
||||
"function",
|
||||
"imitate",
|
||||
"infer",
|
||||
"inherit",
|
||||
"mimic",
|
||||
"name",
|
||||
"properties",
|
||||
"rename",
|
||||
"set"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "mimic-fn",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sindresorhus/mimic-fn.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"version": "1.2.0"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue