First commit

This commit is contained in:
Donavon McDowell 2023-12-06 16:03:35 -07:00
commit 4cde72fe1a
154 changed files with 29391 additions and 0 deletions

View File

@ -0,0 +1,2 @@
#This is the Egnyte API Key
API_KEY="9cht7d3p565qnk3nbh3xbj7e"

View File

@ -0,0 +1,107 @@
//
// Name: Egnyte - Find Dead Files
// Purpose: To find any files like PDF's or DOCX, XLSX in the folders stated below that have a size of 0KB
// TO DO: Make this get a reporting of all of the files with 0kb
// FUTURE: Make it so that the script will automatically fix the "dead" files either by looking in previous versions and restoring or by going to lbfs01 and finding the same file and uploading
// Created By: Donavon McDowell
// Date: 12/5/2023
//
var mysql = require('mysql');
require('dotenv').config();
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
const api_key = process.env.API_KEY
//Select your folders here
//const folders = ['/Shared/N-Data/14', '/Shared/N-Data/17'];
const folders = ['/Shared/IT/Egnyte/Egnyte Testing'];
const baseURL = "https://mpe.egnyte.com/pubapi/v1";
function maskMiddleCharacters(inputString) {
//Used to mask the middle characters of important items such as API Keys
// Check if the input is a string
if (typeof inputString !== 'string') {
return 'Input is not a string';
}
// Get the length of the string
const len = inputString.length;
if (len < 6) {
return inputString;
}
// Extract the first Four and last Four characters
const firstFourChars = inputString.slice(0, 3);
const lastFourChars = inputString.slice(-3);
// Create a string of stars with the same length as the middle characters
const middleStars = '*'.repeat(len - 6);
// Concatenate the first Four, middle stars, and last Four characters
const maskedString = firstFourChars + middleStars + lastFourChars;
return maskedString;
}
function encodeURI(string){
//Used to encode the URI to be compatible with Egnyte
encodedURI = encodeURIComponent(string);
encodedURI = encodedURI.replaceAll("%2F" , "/"); //Adds slashs back in
encodedURI = encodedURI.replaceAll("-" , "%2D"); //Encodes any "-" to %2D
encodedURI = encodedURI.replace("https%3A//mpe.egnyte.com/pubapi/v1", "https://mpe.egnyte.com/pubapi/v1"); //Fixes the URL so it still works
return encodedURI;
}
async function hitApi(base){
//Used to hit the api
//To Use: Pass in a string that contains the endpoint you would like to hit I.E: /fs/Shared or /events/cursor
base = encodeURI(base); //This runs the encodeURI function to encode the URL to work properly
const response = await fetch(base,
{
method: 'get',
headers: new Headers({
'Authorization': 'Bearer ' + api_key,
'Content-Type': 'application/json'
})
});
//DEBUG
//console.log(await response.json());
const returnRespone = await response.json();
return returnRespone;
}
async function fetchData() {
for(let i = 0; i < folders.length; i++) {
path = baseURL + "/fs" + folders[i]; //Set your folder path here
console.log("Location: " + path);
data = await hitApi(path);
for(let k = 0; k < data.length; i++){
currentPath = path + data.folders[k].name;
console.log(currentPath);
}
//DEBUGGING ONLY! COMMENT THE LINE UNDER THIS OUT TO STOP THE OUTPUT
console.log(data);
}
}
console.log("*****************************");
console.log("");
console.log("Egnyte - Find Dead Files 💀");
console.log("");
console.log("API KEY: " + maskMiddleCharacters(api_key));
console.log("ASSIGNED FOLDERS: " + folders);
console.log("");
console.log("*****************************");
fetchData();

View File

@ -0,0 +1,100 @@
{
"name": "Egnyte - Find Dead Files",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
"engines": {
"node": "*"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/mysql": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
"dependencies": {
"bignumber.js": "9.0.0",
"readable-stream": "2.3.7",
"safe-buffer": "5.1.2",
"sqlstring": "2.3.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
"integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
}
}
}

View File

@ -0,0 +1,266 @@
#### 9.0.0
* 27/05/2019
* For compatibility with legacy browsers, remove `Symbol` references.
#### 8.1.1
* 24/02/2019
* [BUGFIX] #222 Restore missing `var` to `export BigNumber`.
* Allow any key in BigNumber.Instance in *bignumber.d.ts*.
#### 8.1.0
* 23/02/2019
* [NEW FEATURE] #220 Create a BigNumber using `{s, e, c}`.
* [NEW FEATURE] `isBigNumber`: if `BigNumber.DEBUG` is `true`, also check that the BigNumber instance is well-formed.
* Remove `instanceof` checks; just use `_isBigNumber` to identify a BigNumber instance.
* Add `_isBigNumber` to prototype in *bignumber.mjs*.
* Add tests for BigNumber creation from object.
* Update *API.html*.
#### 8.0.2
* 13/01/2019
* #209 `toPrecision` without argument should follow `toString`.
* Improve *Use* section of *README*.
* Optimise `toString(10)`.
* Add verson number to API doc.
#### 8.0.1
* 01/11/2018
* Rest parameter must be array type in *bignumber.d.ts*.
#### 8.0.0
* 01/11/2018
* [NEW FEATURE] Add `BigNumber.sum` method.
* [NEW FEATURE]`toFormat`: add `prefix` and `suffix` options.
* [NEW FEATURE] #178 Pass custom formatting to `toFormat`.
* [BREAKING CHANGE] #184 `toFraction`: return array of BigNumbers not strings.
* [NEW FEATURE] #185 Enable overwrite of `valueOf` to prevent accidental addition to string.
* #183 Add Node.js `crypto` requirement to documentation.
* [BREAKING CHANGE] #198 Disallow signs and whitespace in custom alphabet.
* [NEW FEATURE] #188 Implement `util.inspect.custom` for Node.js REPL.
* #170 Make `isBigNumber` a type guard in *bignumber.d.ts*.
* [BREAKING CHANGE] `BigNumber.min` and `BigNumber.max`: don't accept an array.
* Update *.travis.yml*.
* Remove *bower.json*.
#### 7.2.1
* 24/05/2018
* Add `browser` field to *package.json*.
#### 7.2.0
* 22/05/2018
* #166 Correct *.mjs* file. Remove extension from `main` field in *package.json*.
#### 7.1.0
* 18/05/2018
* Add `module` field to *package.json* for *bignumber.mjs*.
#### 7.0.2
* 17/05/2018
* #165 Bugfix: upper-case letters for bases 11-36 in a custom alphabet.
* Add note to *README* regarding creating BigNumbers from Number values.
#### 7.0.1
* 26/04/2018
* #158 Fix global object variable name typo.
#### 7.0.0
* 26/04/2018
* #143 Remove global BigNumber from typings.
* #144 Enable compatibility with `Object.freeze(Object.prototype)`.
* #148 #123 #11 Only throw on a number primitive with more than 15 significant digits if `BigNumber.DEBUG` is `true`.
* Only throw on an invalid BigNumber value if `BigNumber.DEBUG` is `true`. Return BigNumber `NaN` instead.
* #154 `exponentiatedBy`: allow BigNumber exponent.
* #156 Prevent Content Security Policy *unsafe-eval* issue.
* `toFraction`: allow `Infinity` maximum denominator.
* Comment-out some excess tests to reduce test time.
* Amend indentation and other spacing.
#### 6.0.0
* 26/01/2018
* #137 Implement `APLHABET` configuration option.
* Remove `ERRORS` configuration option.
* Remove `toDigits` method; extend `precision` method accordingly.
* Remove s`round` method; extend `decimalPlaces` method accordingly.
* Remove methods: `ceil`, `floor`, and `truncated`.
* Remove method aliases: `add`, `cmp`, `isInt`, `isNeg`, `trunc`, `mul`, `neg` and `sub`.
* Rename methods: `shift` to `shiftedBy`, `another` to `clone`, `toPower` to `exponentiatedBy`, and `equals` to `isEqualTo`.
* Rename methods: add `is` prefix to `greaterThan`, `greaterThanOrEqualTo`, `lessThan` and `lessThanOrEqualTo`.
* Add methods: `multipliedBy`, `isBigNumber`, `isPositive`, `integerValue`, `maximum` and `minimum`.
* Refactor test suite.
* Add *CHANGELOG.md*.
* Rewrite *bignumber.d.ts*.
* Redo API image.
#### 5.0.0
* 27/11/2017
* #81 Don't throw on constructor call without `new`.
#### 4.1.0
* 26/09/2017
* Remove node 0.6 from *.travis.yml*.
* Add *bignumber.mjs*.
#### 4.0.4
* 03/09/2017
* Add missing aliases to *bignumber.d.ts*.
#### 4.0.3
* 30/08/2017
* Add types: *bignumber.d.ts*.
#### 4.0.2
* 03/05/2017
* #120 Workaround Safari/Webkit bug.
#### 4.0.1
* 05/04/2017
* #121 BigNumber.default to BigNumber['default'].
#### 4.0.0
* 09/01/2017
* Replace BigNumber.isBigNumber method with isBigNumber prototype property.
#### 3.1.2
* 08/01/2017
* Minor documentation edit.
#### 3.1.1
* 08/01/2017
* Uncomment `isBigNumber` tests.
* Ignore dot files.
#### 3.1.0
* 08/01/2017
* Add `isBigNumber` method.
#### 3.0.2
* 08/01/2017
* Bugfix: Possible incorrect value of `ERRORS` after a `BigNumber.another` call (due to `parseNumeric` declaration in outer scope).
#### 3.0.1
* 23/11/2016
* Apply fix for old ipads with `%` issue, see #57 and #102.
* Correct error message.
#### 3.0.0
* 09/11/2016
* Remove `require('crypto')` - leave it to the user.
* Add `BigNumber.set` as `BigNumber.config` alias.
* Default `POW_PRECISION` to `0`.
#### 2.4.0
* 14/07/2016
* #97 Add exports to support ES6 imports.
#### 2.3.0
* 07/03/2016
* #86 Add modulus parameter to `toPower`.
#### 2.2.0
* 03/03/2016
* #91 Permit larger JS integers.
#### 2.1.4
* 15/12/2015
* Correct UMD.
#### 2.1.3
* 13/12/2015
* Refactor re global object and crypto availability when bundling.
#### 2.1.2
* 10/12/2015
* Bugfix: `window.crypto` not assigned to `crypto`.
#### 2.1.1
* 09/12/2015
* Prevent code bundler from adding `crypto` shim.
#### 2.1.0
* 26/10/2015
* For `valueOf` and `toJSON`, include the minus sign with negative zero.
#### 2.0.8
* 2/10/2015
* Internal round function bugfix.
#### 2.0.6
* 31/03/2015
* Add bower.json. Tweak division after in-depth review.
#### 2.0.5
* 25/03/2015
* Amend README. Remove bitcoin address.
#### 2.0.4
* 25/03/2015
* Critical bugfix #58: division.
#### 2.0.3
* 18/02/2015
* Amend README. Add source map.
#### 2.0.2
* 18/02/2015
* Correct links.
#### 2.0.1
* 18/02/2015
* Add `max`, `min`, `precision`, `random`, `shiftedBy`, `toDigits` and `truncated` methods.
* Add the short-forms: `add`, `mul`, `sd`, `sub` and `trunc`.
* Add an `another` method to enable multiple independent constructors to be created.
* Add support for the base 2, 8 and 16 prefixes `0b`, `0o` and `0x`.
* Enable a rounding mode to be specified as a second parameter to `toExponential`, `toFixed`, `toFormat` and `toPrecision`.
* Add a `CRYPTO` configuration property so cryptographically-secure pseudo-random number generation can be specified.
* Add a `MODULO_MODE` configuration property to enable the rounding mode used by the `modulo` operation to be specified.
* Add a `POW_PRECISION` configuration property to enable the number of significant digits calculated by the power operation to be limited.
* Improve code quality.
* Improve documentation.
#### 2.0.0
* 29/12/2014
* Add `dividedToIntegerBy`, `isInteger` and `toFormat` methods.
* Remove the following short-forms: `isF`, `isZ`, `toE`, `toF`, `toFr`, `toN`, `toP`, `toS`.
* Store a BigNumber's coefficient in base 1e14, rather than base 10.
* Add fast path for integers to BigNumber constructor.
* Incorporate the library into the online documentation.
#### 1.5.0
* 13/11/2014
* Add `toJSON` and `decimalPlaces` methods.
#### 1.4.1
* 08/06/2014
* Amend README.
#### 1.4.0
* 08/05/2014
* Add `toNumber`.
#### 1.3.0
* 08/11/2013
* Ensure correct rounding of `sqrt` in all, rather than almost all, cases.
* Maximum radix to 64.
#### 1.2.1
* 17/10/2013
* Sign of zero when x < 0 and x + (-x) = 0.
#### 1.2.0
* 19/9/2013
* Throw Error objects for stack.
#### 1.1.1
* 22/8/2013
* Show original value in constructor error message.
#### 1.1.0
* 1/8/2013
* Allow numbers with trailing radix point.
#### 1.0.1
* Bugfix: error messages with incorrect method name
#### 1.0.0
* 8/11/2012
* Initial release

View File

@ -0,0 +1,23 @@
The MIT Licence.
Copyright (c) 2019 Michael Mclaughlin
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.

View File

@ -0,0 +1,268 @@
![bignumber.js](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/bignumberjs.png)
A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.
[![Build Status](https://travis-ci.org/MikeMcl/bignumber.js.svg)](https://travis-ci.org/MikeMcl/bignumber.js)
<br />
## Features
- Integers and decimals
- Simple API but full-featured
- Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal
- 8 KB minified and gzipped
- Replicates the `toExponential`, `toFixed`, `toPrecision` and `toString` methods of JavaScript's Number type
- Includes a `toFraction` and a correctly-rounded `squareRoot` method
- Supports cryptographically-secure pseudo-random number generation
- No dependencies
- Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only
- Comprehensive [documentation](http://mikemcl.github.io/bignumber.js/) and test set
![API](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/API.png)
If a smaller and simpler library is required see [big.js](https://github.com/MikeMcl/big.js/).
It's less than half the size but only works with decimal numbers and only has half the methods.
It also does not allow `NaN` or `Infinity`, or have the configuration options of this library.
See also [decimal.js](https://github.com/MikeMcl/decimal.js/), which among other things adds support for non-integer powers, and performs all operations to a specified number of significant digits.
## Load
The library is the single JavaScript file *bignumber.js* (or minified, *bignumber.min.js*).
Browser:
```html
<script src='path/to/bignumber.js'></script>
```
[Node.js](http://nodejs.org):
```bash
$ npm install bignumber.js
```
```javascript
const BigNumber = require('bignumber.js');
```
ES6 module:
```javascript
import BigNumber from "./bignumber.mjs"
```
AMD loader libraries such as [requireJS](http://requirejs.org/):
```javascript
require(['bignumber'], function(BigNumber) {
// Use BigNumber here in local scope. No global BigNumber.
});
```
## Use
The library exports a single constructor function, [`BigNumber`](http://mikemcl.github.io/bignumber.js/#bignumber), which accepts a value of type Number, String or BigNumber,
```javascript
let x = new BigNumber(123.4567);
let y = BigNumber('123456.7e-3');
let z = new BigNumber(x);
x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z); // true
```
To get the string value of a BigNumber use [`toString()`](http://mikemcl.github.io/bignumber.js/#toS) or [`toFixed()`](http://mikemcl.github.io/bignumber.js/#toFix). Using `toFixed()` prevents exponential notation being returned, no matter how large or small the value.
```javascript
let x = new BigNumber('1111222233334444555566');
x.toString(); // "1.111222233334444555566e+21"
x.toFixed(); // "1111222233334444555566"
```
If the limited precision of Number values is not well understood, it is recommended to create BigNumbers from String values rather than Number values to avoid a potential loss of precision.
*In all further examples below, `let`, semicolons and `toString` calls are not shown. If a commented-out value is in quotes it means `toString` has been called on the preceding expression.*
```javascript
// Precision loss from using numeric literals with more than 15 significant digits.
new BigNumber(1.0000000000000001) // '1'
new BigNumber(88259496234518.57) // '88259496234518.56'
new BigNumber(99999999999999999999) // '100000000000000000000'
// Precision loss from using numeric literals outside the range of Number values.
new BigNumber(2e+308) // 'Infinity'
new BigNumber(1e-324) // '0'
// Precision loss from the unexpected result of arithmetic with Number values.
new BigNumber(0.7 + 0.1) // '0.7999999999999999'
```
When creating a BigNumber from a Number, note that a BigNumber is created from a Number's decimal `toString()` value not from its underlying binary value. If the latter is required, then pass the Number's `toString(2)` value and specify base 2.
```javascript
new BigNumber(Number.MAX_VALUE.toString(2), 2)
```
BigNumbers can be created from values in bases from 2 to 36. See [`ALPHABET`](http://mikemcl.github.io/bignumber.js/#alphabet) to extend this range.
```javascript
a = new BigNumber(1011, 2) // "11"
b = new BigNumber('zz.9', 36) // "1295.25"
c = a.plus(b) // "1306.25"
```
Performance is better if base 10 is NOT specified for decimal values. Only specify base 10 when it is desired that the number of decimal places of the input value be limited to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.
A BigNumber is immutable in the sense that it is not changed by its methods.
```javascript
0.3 - 0.1 // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1) // "0.2"
x // "0.3"
```
The methods that return a BigNumber can be chained.
```javascript
x.dividedBy(y).plus(z).times(9)
x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').integerValue()
```
Some of the longer method names have a shorter alias.
```javascript
x.squareRoot().dividedBy(y).exponentiatedBy(3).isEqualTo(x.sqrt().div(y).pow(3)) // true
x.modulo(y).multipliedBy(z).eq(x.mod(y).times(z)) // true
```
As with JavaScript's Number type, there are [`toExponential`](http://mikemcl.github.io/bignumber.js/#toE), [`toFixed`](http://mikemcl.github.io/bignumber.js/#toFix) and [`toPrecision`](http://mikemcl.github.io/bignumber.js/#toP) methods.
```javascript
x = new BigNumber(255.5)
x.toExponential(5) // "2.55500e+2"
x.toFixed(5) // "255.50000"
x.toPrecision(5) // "255.50"
x.toNumber() // 255.5
```
A base can be specified for [`toString`](http://mikemcl.github.io/bignumber.js/#toS). Performance is better if base 10 is NOT specified, i.e. use `toString()` not `toString(10)`. Only specify base 10 when it is desired that the number of decimal places be limited to the current [`DECIMAL_PLACES`](http://mikemcl.github.io/bignumber.js/#decimal-places) setting.
```javascript
x.toString(16) // "ff.8"
```
There is a [`toFormat`](http://mikemcl.github.io/bignumber.js/#toFor) method which may be useful for internationalisation.
```javascript
y = new BigNumber('1234567.898765')
y.toFormat(2) // "1,234,567.90"
```
The maximum number of decimal places of the result of an operation involving division (i.e. a division, square root, base conversion or negative power operation) is set using the `set` or `config` method of the `BigNumber` constructor.
The other arithmetic operations always give the exact result.
```javascript
BigNumber.set({ DECIMAL_PLACES: 10, ROUNDING_MODE: 4 })
x = new BigNumber(2)
y = new BigNumber(3)
z = x.dividedBy(y) // "0.6666666667"
z.squareRoot() // "0.8164965809"
z.exponentiatedBy(-3) // "3.3749999995"
z.toString(2) // "0.1010101011"
z.multipliedBy(z) // "0.44444444448888888889"
z.multipliedBy(z).decimalPlaces(10) // "0.4444444445"
```
There is a [`toFraction`](http://mikemcl.github.io/bignumber.js/#toFr) method with an optional *maximum denominator* argument
```javascript
y = new BigNumber(355)
pi = y.dividedBy(113) // "3.1415929204"
pi.toFraction() // [ "7853982301", "2500000000" ]
pi.toFraction(1000) // [ "355", "113" ]
```
and [`isNaN`](http://mikemcl.github.io/bignumber.js/#isNaN) and [`isFinite`](http://mikemcl.github.io/bignumber.js/#isF) methods, as `NaN` and `Infinity` are valid `BigNumber` values.
```javascript
x = new BigNumber(NaN) // "NaN"
y = new BigNumber(Infinity) // "Infinity"
x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true
```
The value of a BigNumber is stored in a decimal floating point format in terms of a coefficient, exponent and sign.
```javascript
x = new BigNumber(-123.456);
x.c // [ 123, 45600000000000 ] coefficient (i.e. significand)
x.e // 2 exponent
x.s // -1 sign
```
For advanced usage, multiple BigNumber constructors can be created, each with their own independent configuration.
```javascript
// Set DECIMAL_PLACES for the original BigNumber constructor
BigNumber.set({ DECIMAL_PLACES: 10 })
// Create another BigNumber constructor, optionally passing in a configuration object
BN = BigNumber.clone({ DECIMAL_PLACES: 5 })
x = new BigNumber(1)
y = new BN(1)
x.div(3) // '0.3333333333'
y.div(3) // '0.33333'
```
For further information see the [API](http://mikemcl.github.io/bignumber.js/) reference in the *doc* directory.
## Test
The *test/modules* directory contains the test scripts for each method.
The tests can be run with Node.js or a browser. For Node.js use
$ npm test
or
$ node test/test
To test a single method, use, for example
$ node test/methods/toFraction
For the browser, open *test/test.html*.
## Build
For Node, if [uglify-js](https://github.com/mishoo/UglifyJS2) is installed
npm install uglify-js -g
then
npm run build
will create *bignumber.min.js*.
A source map will also be created in the root directory.
## Feedback
Open an issue, or email
Michael
<a href="mailto:M8ch88l@gmail.com">M8ch88l@gmail.com</a>
## Licence
The MIT Licence.
See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/master/LICENCE).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
{
"name": "bignumber.js",
"description": "A library for arbitrary-precision decimal and non-decimal arithmetic",
"version": "9.0.0",
"keywords": [
"arbitrary",
"precision",
"arithmetic",
"big",
"number",
"decimal",
"float",
"biginteger",
"bigdecimal",
"bignumber",
"bigint",
"bignum"
],
"repository": {
"type": "git",
"url": "https://github.com/MikeMcl/bignumber.js.git"
},
"main": "bignumber",
"module": "bignumber.mjs",
"browser": "bignumber.js",
"types": "bignumber.d.ts",
"author": {
"name": "Michael Mclaughlin",
"email": "M8ch88l@gmail.com"
},
"engines": {
"node": "*"
},
"license": "MIT",
"scripts": {
"test": "node test/test",
"build": "uglifyjs bignumber.js --source-map -c -m -o bignumber.min.js"
},
"dependencies": {}
}

View File

@ -0,0 +1,19 @@
Copyright Node.js contributors. All rights reserved.
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.

View File

@ -0,0 +1,3 @@
# core-util-is
The `util.is*` functions introduced in Node v0.12.

View File

@ -0,0 +1,107 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(arg) {
if (Array.isArray) {
return Array.isArray(arg);
}
return objectToString(arg) === '[object Array]';
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return (objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('buffer').Buffer.isBuffer;
function objectToString(o) {
return Object.prototype.toString.call(o);
}

View File

@ -0,0 +1,38 @@
{
"name": "core-util-is",
"version": "1.0.3",
"description": "The `util.is*` functions introduced in Node v0.12.",
"main": "lib/util.js",
"files": [
"lib"
],
"repository": {
"type": "git",
"url": "git://github.com/isaacs/core-util-is"
},
"keywords": [
"util",
"isBuffer",
"isArray",
"isNumber",
"isString",
"isRegExp",
"isThis",
"isThat",
"polyfill"
],
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/isaacs/core-util-is/issues"
},
"scripts": {
"test": "tap test.js",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"devDependencies": {
"tap": "^15.0.9"
}
}

View File

@ -0,0 +1,431 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.3.1...master)
## [16.3.1](https://github.com/motdotla/dotenv/compare/v16.3.0...v16.3.1) (2023-06-17)
### Added
- Add missing type definitions for `processEnv` and `DOTENV_KEY` options. [#756](https://github.com/motdotla/dotenv/pull/756)
## [16.3.0](https://github.com/motdotla/dotenv/compare/v16.2.0...v16.3.0) (2023-06-16)
### Added
- Optionally pass `DOTENV_KEY` to options rather than relying on `process.env.DOTENV_KEY`. Defaults to `process.env.DOTENV_KEY` [#754](https://github.com/motdotla/dotenv/pull/754)
## [16.2.0](https://github.com/motdotla/dotenv/compare/v16.1.4...v16.2.0) (2023-06-15)
### Added
- Optionally write to your own target object rather than `process.env`. Defaults to `process.env`. [#753](https://github.com/motdotla/dotenv/pull/753)
- Add import type URL to types file [#751](https://github.com/motdotla/dotenv/pull/751)
## [16.1.4](https://github.com/motdotla/dotenv/compare/v16.1.3...v16.1.4) (2023-06-04)
### Added
- Added `.github/` to `.npmignore` [#747](https://github.com/motdotla/dotenv/pull/747)
## [16.1.3](https://github.com/motdotla/dotenv/compare/v16.1.2...v16.1.3) (2023-05-31)
### Removed
- Removed `browser` keys for `path`, `os`, and `crypto` in package.json. These were set to false incorrectly as of 16.1. Instead, if using dotenv on the front-end make sure to include polyfills for `path`, `os`, and `crypto`. [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) provides these.
## [16.1.2](https://github.com/motdotla/dotenv/compare/v16.1.1...v16.1.2) (2023-05-31)
### Changed
- Exposed private function `_configDotenv` as `configDotenv`. [#744](https://github.com/motdotla/dotenv/pull/744)
## [16.1.1](https://github.com/motdotla/dotenv/compare/v16.1.0...v16.1.1) (2023-05-30)
### Added
- Added type definition for `decrypt` function
### Changed
- Fixed `{crypto: false}` in `packageJson.browser`
## [16.1.0](https://github.com/motdotla/dotenv/compare/v16.0.3...v16.1.0) (2023-05-30)
### Added
- Add `populate` convenience method [#733](https://github.com/motdotla/dotenv/pull/733)
- Accept URL as path option [#720](https://github.com/motdotla/dotenv/pull/720)
- Add dotenv to `npm fund` command
- Spanish language README [#698](https://github.com/motdotla/dotenv/pull/698)
- Add `.env.vault` support. 🎉 ([#730](https://github.com/motdotla/dotenv/pull/730))
`.env.vault` extends the `.env` file format standard with a localized encrypted vault file. Package it securely with your production code deploys. It's cloud agnostic so that you can deploy your secrets anywhere  without [risky third-party integrations](https://techcrunch.com/2023/01/05/circleci-breach/). [read more](https://github.com/motdotla/dotenv#-deploying)
### Changed
- Fixed "cannot resolve 'fs'" error on tools like Replit [#693](https://github.com/motdotla/dotenv/pull/693)
## [16.0.3](https://github.com/motdotla/dotenv/compare/v16.0.2...v16.0.3) (2022-09-29)
### Changed
- Added library version to debug logs ([#682](https://github.com/motdotla/dotenv/pull/682))
## [16.0.2](https://github.com/motdotla/dotenv/compare/v16.0.1...v16.0.2) (2022-08-30)
### Added
- Export `env-options.js` and `cli-options.js` in package.json for use with downstream [dotenv-expand](https://github.com/motdotla/dotenv-expand) module
## [16.0.1](https://github.com/motdotla/dotenv/compare/v16.0.0...v16.0.1) (2022-05-10)
### Changed
- Minor README clarifications
- Development ONLY: updated devDependencies as recommended for development only security risks ([#658](https://github.com/motdotla/dotenv/pull/658))
## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02)
### Added
- _Breaking:_ Backtick support 🎉 ([#615](https://github.com/motdotla/dotenv/pull/615))
If you had values containing the backtick character, please quote those values with either single or double quotes.
## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02)
### Changed
- Properly parse empty single or double quoted values 🐞 ([#614](https://github.com/motdotla/dotenv/pull/614))
## [15.0.0](https://github.com/motdotla/dotenv/compare/v14.3.2...v15.0.0) (2022-01-31)
`v15.0.0` is a major new release with some important breaking changes.
### Added
- _Breaking:_ Multiline parsing support (just works. no need for the flag.)
### Changed
- _Breaking:_ `#` marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your `.env` files to wrap in quotes any values containing `#`. For example: `SECRET_HASH="something-with-a-#-hash"`).
..Understandably, (as some teams have noted) this is tedious to do across the entire team. To make it less tedious, we recommend using [dotenv cli](https://github.com/dotenv-org/cli) going forward. It's an optional plugin that will keep your `.env` files in sync between machines, environments, or team members.
### Removed
- _Breaking:_ Remove multiline option (just works out of the box now. no need for the flag.)
## [14.3.2](https://github.com/motdotla/dotenv/compare/v14.3.1...v14.3.2) (2022-01-25)
### Changed
- Preserve backwards compatibility on values containing `#` 🐞 ([#603](https://github.com/motdotla/dotenv/pull/603))
## [14.3.1](https://github.com/motdotla/dotenv/compare/v14.3.0...v14.3.1) (2022-01-25)
### Changed
- Preserve backwards compatibility on exports by re-introducing the prior in-place exports 🐞 ([#606](https://github.com/motdotla/dotenv/pull/606))
## [14.3.0](https://github.com/motdotla/dotenv/compare/v14.2.0...v14.3.0) (2022-01-24)
### Added
- Add `multiline` option 🎉 ([#486](https://github.com/motdotla/dotenv/pull/486))
## [14.2.0](https://github.com/motdotla/dotenv/compare/v14.1.1...v14.2.0) (2022-01-17)
### Added
- Add `dotenv_config_override` cli option
- Add `DOTENV_CONFIG_OVERRIDE` command line env option
## [14.1.1](https://github.com/motdotla/dotenv/compare/v14.1.0...v14.1.1) (2022-01-17)
### Added
- Add React gotcha to FAQ on README
## [14.1.0](https://github.com/motdotla/dotenv/compare/v14.0.1...v14.1.0) (2022-01-17)
### Added
- Add `override` option 🎉 ([#595](https://github.com/motdotla/dotenv/pull/595))
## [14.0.1](https://github.com/motdotla/dotenv/compare/v14.0.0...v14.0.1) (2022-01-16)
### Added
- Log error on failure to load `.env` file ([#594](https://github.com/motdotla/dotenv/pull/594))
## [14.0.0](https://github.com/motdotla/dotenv/compare/v13.0.1...v14.0.0) (2022-01-16)
### Added
- _Breaking:_ Support inline comments for the parser 🎉 ([#568](https://github.com/motdotla/dotenv/pull/568))
## [13.0.1](https://github.com/motdotla/dotenv/compare/v13.0.0...v13.0.1) (2022-01-16)
### Changed
* Hide comments and newlines from debug output ([#404](https://github.com/motdotla/dotenv/pull/404))
## [13.0.0](https://github.com/motdotla/dotenv/compare/v12.0.4...v13.0.0) (2022-01-16)
### Added
* _Breaking:_ Add type file for `config.js` ([#539](https://github.com/motdotla/dotenv/pull/539))
## [12.0.4](https://github.com/motdotla/dotenv/compare/v12.0.3...v12.0.4) (2022-01-16)
### Changed
* README updates
* Minor order adjustment to package json format
## [12.0.3](https://github.com/motdotla/dotenv/compare/v12.0.2...v12.0.3) (2022-01-15)
### Changed
* Simplified jsdoc for consistency across editors
## [12.0.2](https://github.com/motdotla/dotenv/compare/v12.0.1...v12.0.2) (2022-01-15)
### Changed
* Improve embedded jsdoc type documentation
## [12.0.1](https://github.com/motdotla/dotenv/compare/v12.0.0...v12.0.1) (2022-01-15)
### Changed
* README updates and clarifications
## [12.0.0](https://github.com/motdotla/dotenv/compare/v11.0.0...v12.0.0) (2022-01-15)
### Removed
- _Breaking:_ drop support for Flow static type checker ([#584](https://github.com/motdotla/dotenv/pull/584))
### Changed
- Move types/index.d.ts to lib/main.d.ts ([#585](https://github.com/motdotla/dotenv/pull/585))
- Typescript cleanup ([#587](https://github.com/motdotla/dotenv/pull/587))
- Explicit typescript inclusion in package.json ([#566](https://github.com/motdotla/dotenv/pull/566))
## [11.0.0](https://github.com/motdotla/dotenv/compare/v10.0.0...v11.0.0) (2022-01-11)
### Changed
- _Breaking:_ drop support for Node v10 ([#558](https://github.com/motdotla/dotenv/pull/558))
- Patch debug option ([#550](https://github.com/motdotla/dotenv/pull/550))
## [10.0.0](https://github.com/motdotla/dotenv/compare/v9.0.2...v10.0.0) (2021-05-20)
### Added
- Add generic support to parse function
- Allow for import "dotenv/config.js"
- Add support to resolve home directory in path via ~
## [9.0.2](https://github.com/motdotla/dotenv/compare/v9.0.1...v9.0.2) (2021-05-10)
### Changed
- Support windows newlines with debug mode
## [9.0.1](https://github.com/motdotla/dotenv/compare/v9.0.0...v9.0.1) (2021-05-08)
### Changed
- Updates to README
## [9.0.0](https://github.com/motdotla/dotenv/compare/v8.6.0...v9.0.0) (2021-05-05)
### Changed
- _Breaking:_ drop support for Node v8
## [8.6.0](https://github.com/motdotla/dotenv/compare/v8.5.1...v8.6.0) (2021-05-05)
### Added
- define package.json in exports
## [8.5.1](https://github.com/motdotla/dotenv/compare/v8.5.0...v8.5.1) (2021-05-05)
### Changed
- updated dev dependencies via npm audit
## [8.5.0](https://github.com/motdotla/dotenv/compare/v8.4.0...v8.5.0) (2021-05-05)
### Added
- allow for `import "dotenv/config"`
## [8.4.0](https://github.com/motdotla/dotenv/compare/v8.3.0...v8.4.0) (2021-05-05)
### Changed
- point to exact types file to work with VS Code
## [8.3.0](https://github.com/motdotla/dotenv/compare/v8.2.0...v8.3.0) (2021-05-05)
### Changed
- _Breaking:_ drop support for Node v8 (mistake to be released as minor bump. later bumped to 9.0.0. see above.)
## [8.2.0](https://github.com/motdotla/dotenv/compare/v8.1.0...v8.2.0) (2019-10-16)
### Added
- TypeScript types
## [8.1.0](https://github.com/motdotla/dotenv/compare/v8.0.0...v8.1.0) (2019-08-18)
### Changed
- _Breaking:_ drop support for Node v6 ([#392](https://github.com/motdotla/dotenv/issues/392))
# [8.0.0](https://github.com/motdotla/dotenv/compare/v7.0.0...v8.0.0) (2019-05-02)
### Changed
- _Breaking:_ drop support for Node v6 ([#302](https://github.com/motdotla/dotenv/issues/392))
## [7.0.0] - 2019-03-12
### Fixed
- Fix removing unbalanced quotes ([#376](https://github.com/motdotla/dotenv/pull/376))
### Removed
- Removed `load` alias for `config` for consistency throughout code and documentation.
## [6.2.0] - 2018-12-03
### Added
- Support preload configuration via environment variables ([#351](https://github.com/motdotla/dotenv/issues/351))
## [6.1.0] - 2018-10-08
### Added
- `debug` option for `config` and `parse` methods will turn on logging
## [6.0.0] - 2018-06-02
### Changed
- _Breaking:_ drop support for Node v4 ([#304](https://github.com/motdotla/dotenv/pull/304))
## [5.0.0] - 2018-01-29
### Added
- Testing against Node v8 and v9
- Documentation on trim behavior of values
- Documentation on how to use with `import`
### Changed
- _Breaking_: default `path` is now `path.resolve(process.cwd(), '.env')`
- _Breaking_: does not write over keys already in `process.env` if the key has a falsy value
- using `const` and `let` instead of `var`
### Removed
- Testing against Node v7
## [4.0.0] - 2016-12-23
### Changed
- Return Object with parsed content or error instead of false ([#165](https://github.com/motdotla/dotenv/pull/165)).
### Removed
- `verbose` option removed in favor of returning result.
## [3.0.0] - 2016-12-20
### Added
- `verbose` option will log any error messages. Off by default.
- parses email addresses correctly
- allow importing config method directly in ES6
### Changed
- Suppress error messages by default ([#154](https://github.com/motdotla/dotenv/pull/154))
- Ignoring more files for NPM to make package download smaller
### Fixed
- False positive test due to case-sensitive variable ([#124](https://github.com/motdotla/dotenv/pull/124))
### Removed
- `silent` option removed in favor of `verbose`
## [2.0.0] - 2016-01-20
### Added
- CHANGELOG to ["make it easier for users and contributors to see precisely what notable changes have been made between each release"](http://keepachangelog.com/). Linked to from README
- LICENSE to be more explicit about what was defined in `package.json`. Linked to from README
- Testing nodejs v4 on travis-ci
- added examples of how to use dotenv in different ways
- return parsed object on success rather than boolean true
### Changed
- README has shorter description not referencing ruby gem since we don't have or want feature parity
### Removed
- Variable expansion and escaping so environment variables are encouraged to be fully orthogonal
## [1.2.0] - 2015-06-20
### Added
- Preload hook to require dotenv without including it in your code
### Changed
- clarified license to be "BSD-2-Clause" in `package.json`
### Fixed
- retain spaces in string vars
## [1.1.0] - 2015-03-31
### Added
- Silent option to silence `console.log` when `.env` missing
## [1.0.0] - 2015-03-13
### Removed
- support for multiple `.env` files. should always use one `.env` file for the current environment
[7.0.0]: https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0
[6.2.0]: https://github.com/motdotla/dotenv/compare/v6.1.0...v6.2.0
[6.1.0]: https://github.com/motdotla/dotenv/compare/v6.0.0...v6.1.0
[6.0.0]: https://github.com/motdotla/dotenv/compare/v5.0.0...v6.0.0
[5.0.0]: https://github.com/motdotla/dotenv/compare/v4.0.0...v5.0.0
[4.0.0]: https://github.com/motdotla/dotenv/compare/v3.0.0...v4.0.0
[3.0.0]: https://github.com/motdotla/dotenv/compare/v2.0.0...v3.0.0
[2.0.0]: https://github.com/motdotla/dotenv/compare/v1.2.0...v2.0.0
[1.2.0]: https://github.com/motdotla/dotenv/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/motdotla/dotenv/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/motdotla/dotenv/compare/v0.4.0...v1.0.0

23
Egnyte - Find Dead Files/node_modules/dotenv/LICENSE generated vendored Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2015, Scott Motte
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,442 @@
<div align="center">
<p>
<sup>
<a href="https://github.com/sponsors/motdotla">Dotenv es apoyado por la comunidad.</a>
</sup>
</p>
<sup>Gracias espaciales a:</sup>
<br>
<br>
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=dotenv_p_20220831">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/v1661980709/warp_hi8oqj.png" width="230" alt="Warp">
</div>
<b>Warp es una rápida e impresionante terminal basada en Rust, reinventado para funcionar como una aplicación moderna.</b>
<div>
<sup>Haga más en la CLI con edición de texto real, resultado básado en bloques, y busqueda de comandos de IA.</sup>
</div>
</a>
<br>
<a href="https://retool.com/?utm_source=sponsor&utm_campaign=dotenv">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/c_scale,w_300/v1664466968/logo-full-black_vidfqf.png" width="270" alt="Retool">
</div>
<b>Retool ayuda a los desarrolladores a crear software interno personalizado, como aplicaciones CRUD y paneles de administración, realmente rápido.</b>
<div>
<sup>Construya Interfaces de Usuario de forma visual con componentes flexibles, conéctese a cualquier fuente de datos, y escriba lógica de negocio en JavaScript.</sup>
</div>
</a>
<br>
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=dotenv&utm_source=github">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/c_scale,w_400/v1665605496/68747470733a2f2f73696e647265736f726875732e636f6d2f6173736574732f7468616e6b732f776f726b6f732d6c6f676f2d77686974652d62672e737667_zdmsbu.svg" width="270" alt="WorkOS">
</div>
<b>Su Apliación, Lista para la Empresa.</b>
<div>
<sup>Agrega Inicio de Sesión Único, Autenticación Multi-Factor, y mucho más, en minutos en lugar de meses.</sup>
</div>
</a>
<hr>
<br>
<br>
<br>
<br>
</div>
# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv)
<img src="https://raw.githubusercontent.com/motdotla/dotenv/master/dotenv.svg" alt="dotenv" align="right" width="200" />
Dotenv es un módulo de dependencia cero que carga las variables de entorno desde un archivo `.env` en [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). El almacenamiento de la configuración del entorno separado del código está basado en la metodología [The Twelve-Factor App](http://12factor.net/config).
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE)
## Instalación
```bash
# instalación local (recomendado)
npm install dotenv --save
```
O installación con yarn? `yarn add dotenv`
## Uso
Cree un archivo `.env` en la raíz de su proyecto:
```dosini
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
```
Tan prónto como sea posible en su aplicación, importe y configure dotenv:
```javascript
require('dotenv').config()
console.log(process.env) // elimine esto después que haya confirmado que esta funcionando
```
.. o usa ES6?
```javascript
import * as dotenv from 'dotenv' // vea en https://github.com/motdotla/dotenv#como-uso-dotenv-con-import
// REVISAR LINK DE REFERENCIA DE IMPORTACIÓN
dotenv.config()
import express from 'express'
```
Eso es todo. `process.env` ahora tiene las claves y los valores que definiste en tu archivo `.env`:
```javascript
require('dotenv').config()
...
s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {})
```
### Valores multilínea
Si necesita variables de varias líneas, por ejemplo, claves privadas, ahora se admiten en la versión (`>= v15.0.0`) con saltos de línea:
```dosini
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"
```
Alternativamente, puede usar comillas dobles y usar el carácter `\n`:
```dosini
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"
```
### Comentarios
Los comentarios pueden ser agregados en tu archivo o en la misma línea:
```dosini
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"
```
Los comentarios comienzan donde existe un `#`, entonces, si su valor contiene un `#`, enciérrelo entre comillas. Este es un cambio importante desde la versión `>= v15.0.0` en adelante.
### Análisis
El motor que analiza el contenido de su archivo que contiene variables de entorno está disponible para su uso. Este Acepta una Cadena o un Búfer y devolverá un Objeto con las claves y los valores analizados.
```javascript
const dotenv = require('dotenv')
const buf = Buffer.from('BASICO=basico')
const config = dotenv.parse(buf) // devolverá un objeto
console.log(typeof config, config) // objeto { BASICO : 'basico' }
```
### Precarga
Puede usar el `--require` (`-r`) [opción de línea de comando](https://nodejs.org/api/cli.html#-r---require-module) para precargar dotenv. Al hacer esto, no necesita requerir ni cargar dotnev en el código de su aplicación.
```bash
$ node -r dotenv/config tu_script.js
```
Las opciones de configuración a continuación se admiten como argumentos de línea de comandos en el formato `dotenv_config_<option>=value`
```bash
$ node -r dotenv/config tu_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true
```
Además, puede usar variables de entorno para establecer opciones de configuración. Los argumentos de línea de comandos precederán a estos.
```bash
$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config tu_script.js
```
```bash
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config tu_script.js dotenv_config_path=/custom/path/to/.env
```
### Expansión Variable
Necesitaras agregar el valor de otro variable en una de sus variables? Usa [dotenv-expand](https://github.com/motdotla/dotenv-expand).
### Sincronizando
Necesitas mentener sincronizados los archivos `.env` entre maquinas, entornos, o miembros del equipo? Usa
[dotenv-vault](https://github.com/dotenv-org/dotenv-vault).
## Ejemplos
Vea [ejemplos](https://github.com/dotenv-org/examples) sobre el uso de dotenv con varios frameworks, lenguajes y configuraciones.
* [nodejs](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs)
* [nodejs (depurar en)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-debug)
* [nodejs (anular en)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-override)
* [esm](https://github.com/dotenv-org/examples/tree/master/dotenv-esm)
* [esm (precarga)](https://github.com/dotenv-org/examples/tree/master/dotenv-esm-preload)
* [typescript](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript)
* [typescript parse](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-parse)
* [typescript config](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-config)
* [webpack](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack)
* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack2)
* [react](https://github.com/dotenv-org/examples/tree/master/dotenv-react)
* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/dotenv-react-typescript)
* [express](https://github.com/dotenv-org/examples/tree/master/dotenv-express)
* [nestjs](https://github.com/dotenv-org/examples/tree/master/dotenv-nestjs)
## Documentación
Dotenv expone dos funciones:
* `configuración`
* `analizar`
### Configuración
`Configuración` leerá su archivo `.env`, analizará el contenido, lo asignará a [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env),
y devolverá un Objeto con una clave `parsed` que contiene el contenido cargado o una clave `error` si falla.
```js
const result = dotenv.config()
if (result.error) {
throw result.error
}
console.log(result.parsed)
```
Adicionalmente, puede pasar opciones a `configuracion`.
#### Opciones
##### Ruta
Por defecto: `path.resolve(process.cwd(), '.env')`
Especifique una ruta personalizada si el archivo que contiene las variables de entorno se encuentra localizado en otro lugar.
```js
require('dotenv').config({ path: '/personalizado/ruta/a/.env' })
```
##### Codificación
Por defecto: `utf8`
Especifique la codificación del archivo que contiene las variables de entorno.
```js
require('dotenv').config({ encoding: 'latin1' })
```
##### Depurar
Por defecto: `false`
Active el registro de ayuda para depurar por qué ciertas claves o valores no se inician como lo esperabas.
```js
require('dotenv').config({ debug: process.env.DEBUG })
```
##### Anular
Por defecto: `false`
Anule cualquier variable de entorno que ya se haya configurada en su maquina con los valores de su archivo .env.
```js
require('dotenv').config({ override: true })
```
### Analizar
El motor que analiza el contenido del archivo que contiene las variables de entorno está disponible para su uso. Acepta una Cadena o un Búfer y retornará un objecto con los valores analizados.
```js
const dotenv = require('dotenv')
const buf = Buffer.from('BASICO=basico')
const config = dotenv.parse(buf) // devolverá un objeto
console.log(typeof config, config) // objeto { BASICO : 'basico' }
```
#### Opciones
##### Depurar
Por defecto: `false`
Active el registro de ayuda para depurar por qué ciertas claves o valores no se inician como lo esperabas.
```js
const dotenv = require('dotenv')
const buf = Buffer.from('hola mundo')
const opt = { debug: true }
const config = dotenv.parse(buf, opt)
// espere por un mensaje de depuración porque el búfer no esta listo KEY=VAL
```
## FAQ
### ¿Por qué el archivo `.env` no carga mis variables de entorno correctamente?
Lo más probable es que su archivo `.env` no esté en el lugar correcto. [Vea este stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables).
Active el modo de depuración y vuelva a intentarlo...
```js
require('dotenv').config({ debug: true })
```
Recibirá un error apropiado en su consola.
### ¿Debo confirmar mi archivo `.env`?
No. Recomendamos **enfáticamente** no enviar su archivo `.env` a la versión de control. Solo debe incluir los valores especificos del entorno, como la base de datos, contraseñas o claves API.
### ¿Debería tener multiples archivos `.env`?
No. Recomendamos **enfáticamente** no tener un archivo `.env` "principal" y un archivo `.env` de "entorno" como `.env.test`. Su configuración debe variar entre implementaciones y no debe compartir valores entre entornos.
> En una Aplicación de Doce Factores, las variables de entorno son controles diferenciados, cada uno totalmente independiente a otras variables de entorno. Nunca se agrupan como "entornos", sino que se gestionan de manera independiente para cada despliegue. Este es un modelo que se escala sin problemas a medida que la aplicación se expande de forma natural en más despliegues a lo largo de su vida.
>
> [La Apliación de los Doce Factores](https://12factor.net/es/)
### ¿Qué reglas sigue el motor de análisis?
El motor de análisis actualmente admite las siguientes reglas:
- `BASICO=basico` se convierte en `{BASICO: 'basico'}`
- las líneas vacías se saltan
- las líneas que comienzan con `#` se tratan como comentarios
- `#` marca el comienzo de un comentario (a menos que el valor esté entre comillas)
- valores vacíos se convierten en cadenas vacías (`VACIO=` se convierte en `{VACIO: ''}`)
- las comillas internas se mantienen (piensa en JSON) (`JSON={"foo": "bar"}` se convierte en `{JSON:"{\"foo\": \"bar\"}"`)
- los espacios en blanco se eliminan de ambos extremos de los valores no citanos (aprende más en [`trim`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO= algo ` se convierte en `{FOO: 'algo'}`)
- los valores entre comillas simples y dobles se escapan (`CITA_SIMPLE='citado'` se convierte en `{CITA_SIMPLE: "citado"}`)
- los valores entre comillas simples y dobles mantienen los espacios en blanco en ambos extremos (`FOO=" algo "` se convierte en `{FOO: ' algo '}`)
- los valores entre comillas dobles expanden nuevas líneas (`MULTILINEA="nueva\nlínea"` se convierte en
```
{MULTILINEA: 'nueva
línea'}
```
- se admite la comilla simple invertida (`` SIGNO_ACENTO=`Esto tiene comillas 'simples' y "dobles" en su interior.` ``)
### ¿Qué sucede con las variables de entorno que ya estaban configuradas?
Por defecto, nunca modificaremos ninguna variable de entorno que ya haya sido establecida. En particular, si hay una variable en su archivo `.env` que colisiona con una que ya existe en su entorno, entonces esa variable se omitirá.
Si por el contrario, quieres anular `process.env` utiliza la opción `override`.
```javascript
require('dotenv').config({ override: true })
```
### ¿Por qué mis variables de entorno no aparecen para React?
Su código React se ejecuta en Webpack, donde el módulo `fs` o incluso el propio `process` global no son accesibles fuera-de-la-caja. El módulo `process.env` sólo puede ser inyectado a través de la configuración de Webpack.
Si estás usando [`react-scripts`](https://www.npmjs.com/package/react-scripts), el cual se distribuye a través de [`create-react-app`](https://create-react-app.dev/), tiene dotenv incorporado pero con una singularidad. Escriba sus variables de entorno con `REACT_APP_`. Vea [este stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) para más detalles.
Si estás utilizando otros frameworks (por ejemplo, Next.js, Gatsby...), debes consultar su documentación para saber cómo injectar variables de entorno en el cliente.
### ¿Puedo personalizar/escribir plugins para dotenv?
Sí! `dotenv.config()` devuelve un objeto que representa el archivo `.env` analizado. Esto te da todo lo que necesitas para poder establecer valores en `process.env`. Por ejemplo:
```js
const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const miEnv = dotenv.config()
variableExpansion(miEnv)
```
### Cómo uso dotnev con `import`?
Simplemente..
```javascript
// index.mjs (ESM)
import * as dotenv from 'dotenv' // vea https://github.com/motdotla/dotenv#como-uso-dotenv-con-import
dotenv.config()
import express from 'express'
```
Un poco de historia...
> Cuando se ejecuta un módulo que contiene una sentencia `import`, los módulos que importa serán cargados primero, y luego se ejecuta cada bloque del módulo en un recorrido en profundidad del gráfico de dependencias, evitando los ciclos al saltarse todo lo que ya se ha ejecutado.
>
> [ES6 en Profundidad: Módulos](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/)
¿Qué significa esto en lenguaje sencillo? Significa que se podrías pensar que lo siguiente funcionaría pero no lo hará.
```js
// notificarError.mjs
import { Cliente } from 'mejor-servicio-para-notificar-error'
export default new Client(process.env.CLAVE_API)
// index.mjs
import dotenv from 'dotenv'
dotenv.config()
import notificarError from './notificarError.mjs'
notificarError.report(new Error('ejemplo documentado'))
```
`process.env.CLAVE_API` será vacio.
En su lugar, el código anterior debe ser escrito como...
```js
// notificarError.mjs
import { Cliente } from 'mejor-servicio-para-notificar-errores'
export default new Client(process.env.CLAVE_API)
// index.mjs
import * as dotenv from 'dotenv'
dotenv.config()
import notificarError from './notificarError.mjs'
notificarError.report(new Error('ejemplo documentado'))
```
¿Esto tiene algo de sentido? Esto es poco poco intuitivo, pero es como funciona la importación de módulos en ES6. Aquí hay un ejemplo [ejemplo práctico de esta trampa](https://github.com/dotenv-org/examples/tree/master/dotenv-es6-import-pitfall).
Existen dos arternativas a este planteamiento:
1. Precarga dotenv: `node --require dotenv/config index.js` (_Nota: no es necesario usar `import` dotenv con este método_)
2. Cree un archivo separado que ejecutará `config` primero como se describe en [este comentario #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822)
### ¿Qué pasa con la expansión de variable?
Prueba [dotenv-expand](https://github.com/motdotla/dotenv-expand)
### ¿Qué pasa con la sincronización y la seguridad de los archivos .env?
Vea [dotenv-vault](https://github.com/dotenv-org/dotenv-vault)
## Guía de contribución
Vea [CONTRIBUTING.md](CONTRIBUTING.md)
## REGISTRO DE CAMBIOS
Vea [CHANGELOG.md](CHANGELOG.md)
## ¿Quiénes utilizan dotenv?
[Estos módulos npm dependen de él.](https://www.npmjs.com/browse/depended/dotenv)
Los proyectos que lo amplían suelen utilizar la [palabra clave "dotenv" en npm](https://www.npmjs.com/search?q=keywords:dotenv).

633
Egnyte - Find Dead Files/node_modules/dotenv/README.md generated vendored Normal file
View File

@ -0,0 +1,633 @@
<div align="center">
<p>
<sup>
<a href="https://github.com/sponsors/motdotla">Dotenv is supported by the community.</a>
</sup>
</p>
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=dotenv_p_20220831">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/v1661980709/warp_hi8oqj.png" width="230" alt="Warp">
</div>
<b>Warp is a blazingly fast, Rust-based terminal reimagined to work like a modern app.</b>
<div>
<sup>Get more done in the CLI with real text editing, block-based output, and AI command search.</sup>
</div>
</a>
<br>
<a href="https://retool.com/?utm_source=sponsor&utm_campaign=dotenv">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/c_scale,w_300/v1664466968/logo-full-black_vidfqf.png" width="270" alt="Retool">
</div>
<b>Retool helps developers build custom internal software, like CRUD apps and admin panels, really fast.</b>
<div>
<sup>Build UIs visually with flexible components, connect to any data source, and write business logic in JavaScript.</sup>
</div>
</a>
<br>
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=dotenv&utm_source=github">
<div>
<img src="https://res.cloudinary.com/dotenv-org/image/upload/c_scale,w_400/v1665605496/68747470733a2f2f73696e647265736f726875732e636f6d2f6173736574732f7468616e6b732f776f726b6f732d6c6f676f2d77686974652d62672e737667_zdmsbu.svg" width="270" alt="WorkOS">
</div>
<b>Your App, Enterprise Ready.</b>
<div>
<sup>Add Single Sign-On, Multi-Factor Auth, and more, in minutes instead of months.</sup>
</div>
</a>
<hr>
</div>
# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv)
<img src="https://raw.githubusercontent.com/motdotla/dotenv/master/dotenv.svg" alt="dotenv" align="right" width="200" />
Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](http://12factor.net/config) methodology.
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE)
[![dotenv-vault](https://badge.dotenv.org/works-with.svg?r=1)](https://www.dotenv.org/r/github.com/dotenv-org/dotenv-vault?r=1)
* [🌱 Install](#-install)
* [🏗️ Usage (.env)](#%EF%B8%8F-usage)
* [🚀 Deploying (.env.vault) 🆕](#-deploying)
* [🌴 Multiple Environments 🆕](#-manage-multiple-environments)
* [📚 Examples](#-examples)
* [📖 Docs](#-documentation)
* [❓ FAQ](#-faq)
* [⏱️ Changelog](./CHANGELOG.md)
## 🌱 Install
```bash
# install locally (recommended)
npm install dotenv --save
```
Or installing with yarn? `yarn add dotenv`
## 🏗️ Usage
<a href="https://www.youtube.com/watch?v=YtkZR0NFd1g">
<div align="right">
<img src="https://img.youtube.com/vi/YtkZR0NFd1g/hqdefault.jpg" alt="how to use dotenv video tutorial" align="right" width="330" />
<img src="https://simpleicons.vercel.app/youtube/ff0000" alt="youtube/@dotenvorg" align="right" width="24" />
</div>
</a>
Create a `.env` file in the root of your project:
```dosini
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
```
As early as possible in your application, import and configure dotenv:
```javascript
require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working
```
.. [or using ES6?](#how-do-i-use-dotenv-with-import)
```javascript
import 'dotenv/config'
```
That's it. `process.env` now has the keys and values you defined in your `.env` file:
```javascript
require('dotenv').config()
...
s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {})
```
### Multiline values
If you need multiline variables, for example private keys, those are now supported (`>= v15.0.0`) with line breaks:
```dosini
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"
```
Alternatively, you can double quote strings and use the `\n` character:
```dosini
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"
```
### Comments
Comments may be added to your file on their own line or inline:
```dosini
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"
```
Comments begin where a `#` exists, so if your value contains a `#` please wrap it in quotes. This is a breaking change from `>= v15.0.0` and on.
### Parsing
The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values.
```javascript
const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // will return an object
console.log(typeof config, config) // object { BASIC : 'basic' }
```
### Preload
You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code.
```bash
$ node -r dotenv/config your_script.js
```
The configuration options below are supported as command line arguments in the format `dotenv_config_<option>=value`
```bash
$ node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true
```
Additionally, you can use environment variables to set configuration options. Command line arguments will precede these.
```bash
$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config your_script.js
```
```bash
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env
```
### Variable Expansion
You need to add the value of another variable in one of your variables? Use [dotenv-expand](https://github.com/motdotla/dotenv-expand).
### Syncing
You need to keep `.env` files in sync between machines, environments, or team members? Use [dotenv-vault](https://github.com/dotenv-org/dotenv-vault).
### Deploying
You need to deploy your secrets in a cloud-agnostic manner? Use a `.env.vault` file.
### Multiple Environments
You need to manage your secrets across different environments and apply them as needed? Use a `.env.vault` file with a `DOTENV_KEY`.
## 🚀 Deploying
*Note: Requires dotenv >= 16.1.0*
Encrypt your `.env.vault` file.
```bash
$ npx dotenv-vault build
```
Fetch your production `DOTENV_KEY`.
```bash
$ npx dotenv-vault keys production
```
Set `DOTENV_KEY` on your server.
```bash
# heroku example
heroku config:set DOTENV_KEY=dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production
```
That's it! On deploy, your `.env.vault` file will be decrypted and its secrets injected as environment variables just in time.
* A note from [Mot](https://github.com/motdotla): Until recently, we did not have an opinion on how and where to store your secrets in production. We now strongly recommend generating a `.env.vault` file. It's the best way to prevent your secrets from being scattered across multiple servers and cloud providers protecting you from breaches like the [CircleCI breach](https://techcrunch.com/2023/01/05/circleci-breach/). Also it unlocks interoperability WITHOUT native third-party integrations. Third-party integrations are [increasingly risky](https://coderpad.io/blog/development/heroku-github-breach/) to our industry. They may be the 'du jour' of today, but we imagine a better future.*
<a href="https://github.com/dotenv-org/dotenv-vault#dotenv-vault-">Learn more at dotenv-vault: Deploying</a>
## 🌴 Manage Multiple Environments
Edit your production environment variables.
```bash
$ npx dotenv-vault open production
```
Regenerate your `.env.vault` file.
```bash
$ npx dotenv-vault build
```
* 🔐 Vault Managed vs 💻 Locally Managed: The above example, for brevity's sake, used the 🔐 Vault Managed solution to manage your `.env.vault` file. You can instead use the 💻 Locally Managed solution. [Read more here](https://github.com/dotenv-org/dotenv-vault#how-do-i-use--locally-managed-dotenv-vault). Our vision is that other platforms and orchestration tools adopt the `.env.vault` standard as they did the `.env` standard. We don't expect to be the only ones providing tooling to manage and generate `.env.vault` files.*
<a href="https://github.com/dotenv-org/dotenv-vault#-manage-multiple-environments">Learn more at dotenv-vault: Manage Multiple Environments</a>
## 📚 Examples
See [examples](https://github.com/dotenv-org/examples) of using dotenv with various frameworks, languages, and configurations.
* [nodejs](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs)
* [nodejs (debug on)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-debug)
* [nodejs (override on)](https://github.com/dotenv-org/examples/tree/master/dotenv-nodejs-override)
* [nodejs (processEnv override)](https://github.com/dotenv-org/examples/tree/master/dotenv-custom-target)
* [nodejs (DOTENV_KEY override)](https://github.com/dotenv-org/examples/tree/master/dotenv-vault-custom-target)
* [esm](https://github.com/dotenv-org/examples/tree/master/dotenv-esm)
* [esm (preload)](https://github.com/dotenv-org/examples/tree/master/dotenv-esm-preload)
* [typescript](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript)
* [typescript parse](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-parse)
* [typescript config](https://github.com/dotenv-org/examples/tree/master/dotenv-typescript-config)
* [webpack](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack)
* [webpack (plugin)](https://github.com/dotenv-org/examples/tree/master/dotenv-webpack2)
* [react](https://github.com/dotenv-org/examples/tree/master/dotenv-react)
* [react (typescript)](https://github.com/dotenv-org/examples/tree/master/dotenv-react-typescript)
* [express](https://github.com/dotenv-org/examples/tree/master/dotenv-express)
* [nestjs](https://github.com/dotenv-org/examples/tree/master/dotenv-nestjs)
* [fastify](https://github.com/dotenv-org/examples/tree/master/dotenv-fastify)
## 📖 Documentation
Dotenv exposes four functions:
* `config`
* `parse`
* `populate`
* `decrypt`
### Config
`config` will read your `.env` file, parse the contents, assign it to
[`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env),
and return an Object with a `parsed` key containing the loaded content or an `error` key if it failed.
```js
const result = dotenv.config()
if (result.error) {
throw result.error
}
console.log(result.parsed)
```
You can additionally, pass options to `config`.
#### Options
##### path
Default: `path.resolve(process.cwd(), '.env')`
Specify a custom path if your file containing environment variables is located elsewhere.
```js
require('dotenv').config({ path: '/custom/path/to/.env' })
```
##### encoding
Default: `utf8`
Specify the encoding of your file containing environment variables.
```js
require('dotenv').config({ encoding: 'latin1' })
```
##### debug
Default: `false`
Turn on logging to help debug why certain keys or values are not being set as you expect.
```js
require('dotenv').config({ debug: process.env.DEBUG })
```
##### override
Default: `false`
Override any environment variables that have already been set on your machine with values from your .env file.
```js
require('dotenv').config({ override: true })
```
##### processEnv
Default: `process.env`
Specify an object to write your secrets to. Defaults to `process.env` environment variables.
```js
const myObject = {}
require('dotenv').config({ processEnv: myObject })
console.log(myObject) // values from .env or .env.vault live here now.
console.log(process.env) // this was not changed or written to
```
##### DOTENV_KEY
Default: `process.env.DOTENV_KEY`
Pass the `DOTENV_KEY` directly to config options. Defaults to looking for `process.env.DOTENV_KEY` environment variable. Note this only applies to decrypting `.env.vault` files. If passed as null or undefined, or not passed at all, dotenv falls back to its traditional job of parsing a `.env` file.
```js
require('dotenv').config({ DOTENV_KEY: 'dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production' })
```
### Parse
The engine which parses the contents of your file containing environment
variables is available to use. It accepts a String or Buffer and will return
an Object with the parsed keys and values.
```js
const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // will return an object
console.log(typeof config, config) // object { BASIC : 'basic' }
```
#### Options
##### debug
Default: `false`
Turn on logging to help debug why certain keys or values are not being set as you expect.
```js
const dotenv = require('dotenv')
const buf = Buffer.from('hello world')
const opt = { debug: true }
const config = dotenv.parse(buf, opt)
// expect a debug message because the buffer is not in KEY=VAL form
```
### Populate
The engine which populates the contents of your .env file to `process.env` is available for use. It accepts a target, a source, and options. This is useful for power users who want to supply their own objects.
For example, customizing the source:
```js
const dotenv = require('dotenv')
const parsed = { HELLO: 'world' }
dotenv.populate(process.env, parsed)
console.log(process.env.HELLO) // world
```
For example, customizing the source AND target:
```js
const dotenv = require('dotenv')
const parsed = { HELLO: 'universe' }
const target = { HELLO: 'world' } // empty object
dotenv.populate(target, parsed, { override: true, debug: true })
console.log(target) // { HELLO: 'universe' }
```
#### options
##### Debug
Default: `false`
Turn on logging to help debug why certain keys or values are not being populated as you expect.
##### override
Default: `false`
Override any environment variables that have already been set.
### Decrypt
The engine which decrypts the ciphertext contents of your .env.vault file is available for use. It accepts a ciphertext and a decryption key. It uses AES-256-GCM encryption.
For example, decrypting a simple ciphertext:
```js
const dotenv = require('dotenv')
const ciphertext = 's7NYXa809k/bVSPwIAmJhPJmEGTtU0hG58hOZy7I0ix6y5HP8LsHBsZCYC/gw5DDFy5DgOcyd18R'
const decryptionKey = 'ddcaa26504cd70a6fef9801901c3981538563a1767c297cb8416e8a38c62fe00'
const decrypted = dotenv.decrypt(ciphertext, decryptionKey)
console.log(decrypted) // # development@v6\nALPHA="zeta"
```
## ❓ FAQ
### Why is the `.env` file not loading my environment variables successfully?
Most likely your `.env` file is not in the correct place. [See this stack overflow](https://stackoverflow.com/questions/42335016/dotenv-file-is-not-loading-environment-variables).
Turn on debug mode and try again..
```js
require('dotenv').config({ debug: true })
```
You will receive a helpful error outputted to your console.
### Should I commit my `.env` file?
No. We **strongly** recommend against committing your `.env` file to version
control. It should only include environment-specific values such as database
passwords or API keys. Your production database should have a different
password than your development database.
### Should I have multiple `.env` files?
No. We **strongly** recommend against having a "main" `.env` file and an "environment" `.env` file like `.env.test`. Your config should vary between deploys, and you should not be sharing values between environments.
> In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.
>
> [The Twelve-Factor App](http://12factor.net/config)
### What rules does the parsing engine follow?
The parsing engine currently supports the following rules:
- `BASIC=basic` becomes `{BASIC: 'basic'}`
- empty lines are skipped
- lines beginning with `#` are treated as comments
- `#` marks the beginning of a comment (unless when the value is wrapped in quotes)
- empty values become empty strings (`EMPTY=` becomes `{EMPTY: ''}`)
- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes `{JSON:"{\"foo\": \"bar\"}"`)
- whitespace is removed from both ends of unquoted values (see more on [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)) (`FOO= some value ` becomes `{FOO: 'some value'}`)
- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes `{SINGLE_QUOTE: "quoted"}`)
- single and double quoted values maintain whitespace from both ends (`FOO=" some value "` becomes `{FOO: ' some value '}`)
- double quoted values expand new lines (`MULTILINE="new\nline"` becomes
```
{MULTILINE: 'new
line'}
```
- backticks are supported (`` BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.` ``)
### What happens to environment variables that were already set?
By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your `.env` file which collides with one that already exists in your environment, then that variable will be skipped.
If instead, you want to override `process.env` use the `override` option.
```javascript
require('dotenv').config({ override: true })
```
### How come my environment variables are not showing up for React?
Your React code is run in Webpack, where the `fs` module or even the `process` global itself are not accessible out-of-the-box. `process.env` can only be injected through Webpack configuration.
If you are using [`react-scripts`](https://www.npmjs.com/package/react-scripts), which is distributed through [`create-react-app`](https://create-react-app.dev/), it has dotenv built in but with a quirk. Preface your environment variables with `REACT_APP_`. See [this stack overflow](https://stackoverflow.com/questions/42182577/is-it-possible-to-use-dotenv-in-a-react-project) for more details.
If you are using other frameworks (e.g. Next.js, Gatsby...), you need to consult their documentation for how to inject environment variables into the client.
### Can I customize/write plugins for dotenv?
Yes! `dotenv.config()` returns an object representing the parsed `.env` file. This gives you everything you need to continue setting values on `process.env`. For example:
```js
const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const myEnv = dotenv.config()
variableExpansion(myEnv)
```
### How do I use dotenv with `import`?
Simply..
```javascript
// index.mjs (ESM)
import 'dotenv/config' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
import express from 'express'
```
A little background..
> When you run a module containing an `import` declaration, the modules it imports are loaded first, then each module body is executed in a depth-first traversal of the dependency graph, avoiding cycles by skipping anything already executed.
>
> [ES6 In Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/)
What does this mean in plain language? It means you would think the following would work but it won't.
`errorReporter.mjs`:
```js
import { Client } from 'best-error-reporting-service'
export default new Client(process.env.API_KEY)
```
`index.mjs`:
```js
// Note: this is INCORRECT and will not work
import * as dotenv from 'dotenv'
dotenv.config()
import errorReporter from './errorReporter.mjs'
errorReporter.report(new Error('documented example'))
```
`process.env.API_KEY` will be blank.
Instead, `index.mjs` should be written as..
```js
import 'dotenv/config'
import errorReporter from './errorReporter.mjs'
errorReporter.report(new Error('documented example'))
```
Does that make sense? It's a bit unintuitive, but it is how importing of ES6 modules work. Here is a [working example of this pitfall](https://github.com/dotenv-org/examples/tree/master/dotenv-es6-import-pitfall).
There are two alternatives to this approach:
1. Preload dotenv: `node --require dotenv/config index.js` (_Note: you do not need to `import` dotenv with this approach_)
2. Create a separate file that will execute `config` first as outlined in [this comment on #133](https://github.com/motdotla/dotenv/issues/133#issuecomment-255298822)
### Why am I getting the error `Module not found: Error: Can't resolve 'crypto|os|path'`?
You are using dotenv on the front-end and have not included a polyfill. Webpack < 5 used to include these for you. Do the following:
```bash
npm install node-polyfill-webpack-plugin
```
Configure your `webpack.config.js` to something like the following.
```js
require('dotenv').config()
const path = require('path');
const webpack = require('webpack')
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new NodePolyfillPlugin(),
new webpack.DefinePlugin({
'process.env': {
HELLO: JSON.stringify(process.env.HELLO)
}
}),
]
};
```
Alternatively, just use [dotenv-webpack](https://github.com/mrsteele/dotenv-webpack) which does this and more behind the scenes for you.
### What about variable expansion?
Try [dotenv-expand](https://github.com/motdotla/dotenv-expand)
### What about syncing and securing .env files?
Use [dotenv-vault](https://github.com/dotenv-org/dotenv-vault)
### What is a `.env.vault` file?
A `.env.vault` file is an encrypted version of your development (and ci, staging, production, etc) environment variables. It is paired with a `DOTENV_KEY` to deploy your secrets more securely than scattering them across multiple platforms and tools. Use [dotenv-vault](https://github.com/dotenv-org/dotenv-vault) to manage and generate them.
## Contributing Guide
See [CONTRIBUTING.md](CONTRIBUTING.md)
## CHANGELOG
See [CHANGELOG.md](CHANGELOG.md)
## Who's using dotenv?
[These npm modules depend on it.](https://www.npmjs.com/browse/depended/dotenv)
Projects that expand it often use the [keyword "dotenv" on npm](https://www.npmjs.com/search?q=keywords:dotenv).

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,9 @@
(function () {
require('./lib/main').config(
Object.assign(
{},
require('./lib/env-options'),
require('./lib/cli-options')(process.argv)
)
)
})()

View File

@ -0,0 +1,11 @@
const re = /^dotenv_config_(encoding|path|debug|override|DOTENV_KEY)=(.+)$/
module.exports = function optionMatcher (args) {
return args.reduce(function (acc, cur) {
const matches = cur.match(re)
if (matches) {
acc[matches[1]] = matches[2]
}
return acc
}, {})
}

View File

@ -0,0 +1,24 @@
// ../config.js accepts options via environment variables
const options = {}
if (process.env.DOTENV_CONFIG_ENCODING != null) {
options.encoding = process.env.DOTENV_CONFIG_ENCODING
}
if (process.env.DOTENV_CONFIG_PATH != null) {
options.path = process.env.DOTENV_CONFIG_PATH
}
if (process.env.DOTENV_CONFIG_DEBUG != null) {
options.debug = process.env.DOTENV_CONFIG_DEBUG
}
if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
options.override = process.env.DOTENV_CONFIG_OVERRIDE
}
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY
}
module.exports = options

View File

@ -0,0 +1,156 @@
// TypeScript Version: 3.0
/// <reference types="node" />
import type { URL } from 'node:url';
export interface DotenvParseOutput {
[name: string]: string;
}
/**
* Parses a string or buffer in the .env file format into an object.
*
* See https://docs.dotenv.org
*
* @param src - contents to be parsed. example: `'DB_HOST=localhost'`
* @param options - additional options. example: `{ debug: true }`
* @returns an object with keys and values based on `src`. example: `{ DB_HOST : 'localhost' }`
*/
export function parse<T extends DotenvParseOutput = DotenvParseOutput>(
src: string | Buffer
): T;
export interface DotenvConfigOptions {
/**
* Default: `path.resolve(process.cwd(), '.env')`
*
* Specify a custom path if your file containing environment variables is located elsewhere.
*
* example: `require('dotenv').config({ path: '/custom/path/to/.env' })`
*/
path?: string | URL;
/**
* Default: `utf8`
*
* Specify the encoding of your file containing environment variables.
*
* example: `require('dotenv').config({ encoding: 'latin1' })`
*/
encoding?: string;
/**
* Default: `false`
*
* Turn on logging to help debug why certain keys or values are not being set as you expect.
*
* example: `require('dotenv').config({ debug: process.env.DEBUG })`
*/
debug?: boolean;
/**
* Default: `false`
*
* Override any environment variables that have already been set on your machine with values from your .env file.
*
* example: `require('dotenv').config({ override: true })`
*/
override?: boolean;
/**
* Default: `process.env`
*
* Specify an object to write your secrets to. Defaults to process.env environment variables.
*
* example: `const processEnv = {}; require('dotenv').config({ processEnv: processEnv })`
*/
processEnv?: DotenvPopulateInput;
/**
* Default: `undefined`
*
* Pass the DOTENV_KEY directly to config options. Defaults to looking for process.env.DOTENV_KEY environment variable. Note this only applies to decrypting .env.vault files. If passed as null or undefined, or not passed at all, dotenv falls back to its traditional job of parsing a .env file.
*
* example: `require('dotenv').config({ DOTENV_KEY: 'dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production' })`
*/
DOTENV_KEY?: string;
}
export interface DotenvConfigOutput {
error?: Error;
parsed?: DotenvParseOutput;
}
export interface DotenvPopulateOptions {
/**
* Default: `false`
*
* Turn on logging to help debug why certain keys or values are not being set as you expect.
*
* example: `require('dotenv').config({ debug: process.env.DEBUG })`
*/
debug?: boolean;
/**
* Default: `false`
*
* Override any environment variables that have already been set on your machine with values from your .env file.
*
* example: `require('dotenv').config({ override: true })`
*/
override?: boolean;
}
export interface DotenvPopulateOutput {
error?: Error;
}
export interface DotenvPopulateInput {
[name: string]: string;
}
/**
* Loads `.env` file contents into process.env by default. If `DOTENV_KEY` is present, it smartly attempts to load encrypted `.env.vault` file contents into process.env.
*
* See https://docs.dotenv.org
*
* @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', debug: true, override: false }`
* @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
*
*/
export function config(options?: DotenvConfigOptions): DotenvConfigOutput;
/**
* Loads `.env` file contents into process.env.
*
* See https://docs.dotenv.org
*
* @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', debug: true, override: false }`
* @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
*
*/
export function configDotenv(options?: DotenvConfigOptions): DotenvConfigOutput;
/**
* Loads `source` json contents into `target` like process.env.
*
* See https://docs.dotenv.org
*
* @param processEnv - the target JSON object. in most cases use process.env but you can also pass your own JSON object
* @param parsed - the source JSON object
* @param options - additional options. example: `{ debug: true, override: false }`
* @returns {void}
*
*/
export function populate(processEnv: DotenvPopulateInput, parsed: DotenvPopulateInput, options?: DotenvConfigOptions): DotenvPopulateOutput;
/**
* Decrypt ciphertext
*
* See https://docs.dotenv.org
*
* @param encrypted - the encrypted ciphertext string
* @param keyStr - the decryption key string
* @returns {string}
*
*/
export function decrypt(encrypted: string, keyStr: string): string;

View File

@ -0,0 +1,314 @@
const fs = require('fs')
const path = require('path')
const os = require('os')
const crypto = require('crypto')
const packageJson = require('../package.json')
const version = packageJson.version
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
// Parse src into an Object
function parse (src) {
const obj = {}
// Convert buffer to string
let lines = src.toString()
// Convert line breaks to same format
lines = lines.replace(/\r\n?/mg, '\n')
let match
while ((match = LINE.exec(lines)) != null) {
const key = match[1]
// Default undefined or null to empty string
let value = (match[2] || '')
// Remove whitespace
value = value.trim()
// Check if double quoted
const maybeQuote = value[0]
// Remove surrounding quotes
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
// Expand newlines if double quoted
if (maybeQuote === '"') {
value = value.replace(/\\n/g, '\n')
value = value.replace(/\\r/g, '\r')
}
// Add to object
obj[key] = value
}
return obj
}
function _parseVault (options) {
const vaultPath = _vaultPath(options)
// Parse .env.vault
const result = DotenvModule.configDotenv({ path: vaultPath })
if (!result.parsed) {
throw new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)
}
// handle scenario for comma separated keys - for use with key rotation
// example: DOTENV_KEY="dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenv.org/vault/.env.vault?environment=prod"
const keys = _dotenvKey(options).split(',')
const length = keys.length
let decrypted
for (let i = 0; i < length; i++) {
try {
// Get full key
const key = keys[i].trim()
// Get instructions for decrypt
const attrs = _instructions(result, key)
// Decrypt
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)
break
} catch (error) {
// last key
if (i + 1 >= length) {
throw error
}
// try next key
}
}
// Parse decrypted .env string
return DotenvModule.parse(decrypted)
}
function _log (message) {
console.log(`[dotenv@${version}][INFO] ${message}`)
}
function _warn (message) {
console.log(`[dotenv@${version}][WARN] ${message}`)
}
function _debug (message) {
console.log(`[dotenv@${version}][DEBUG] ${message}`)
}
function _dotenvKey (options) {
// prioritize developer directly setting options.DOTENV_KEY
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
return options.DOTENV_KEY
}
// secondary infra already contains a DOTENV_KEY environment variable
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
return process.env.DOTENV_KEY
}
// fallback to empty string
return ''
}
function _instructions (result, dotenvKey) {
// Parse DOTENV_KEY. Format is a URI
let uri
try {
uri = new URL(dotenvKey)
} catch (error) {
if (error.code === 'ERR_INVALID_URL') {
throw new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development')
}
throw error
}
// Get decrypt key
const key = uri.password
if (!key) {
throw new Error('INVALID_DOTENV_KEY: Missing key part')
}
// Get environment
const environment = uri.searchParams.get('environment')
if (!environment) {
throw new Error('INVALID_DOTENV_KEY: Missing environment part')
}
// Get ciphertext payload
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`
const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION
if (!ciphertext) {
throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)
}
return { ciphertext, key }
}
function _vaultPath (options) {
let dotenvPath = path.resolve(process.cwd(), '.env')
if (options && options.path && options.path.length > 0) {
dotenvPath = options.path
}
// Locate .env.vault
return dotenvPath.endsWith('.vault') ? dotenvPath : `${dotenvPath}.vault`
}
function _resolveHome (envPath) {
return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
}
function _configVault (options) {
_log('Loading env from encrypted .env.vault')
const parsed = DotenvModule._parseVault(options)
let processEnv = process.env
if (options && options.processEnv != null) {
processEnv = options.processEnv
}
DotenvModule.populate(processEnv, parsed, options)
return { parsed }
}
function configDotenv (options) {
let dotenvPath = path.resolve(process.cwd(), '.env')
let encoding = 'utf8'
const debug = Boolean(options && options.debug)
if (options) {
if (options.path != null) {
dotenvPath = _resolveHome(options.path)
}
if (options.encoding != null) {
encoding = options.encoding
}
}
try {
// Specifying an encoding returns a string instead of a buffer
const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))
let processEnv = process.env
if (options && options.processEnv != null) {
processEnv = options.processEnv
}
DotenvModule.populate(processEnv, parsed, options)
return { parsed }
} catch (e) {
if (debug) {
_debug(`Failed to load ${dotenvPath} ${e.message}`)
}
return { error: e }
}
}
// Populates process.env from .env file
function config (options) {
const vaultPath = _vaultPath(options)
// fallback to original dotenv if DOTENV_KEY is not set
if (_dotenvKey(options).length === 0) {
return DotenvModule.configDotenv(options)
}
// dotenvKey exists but .env.vault file does not exist
if (!fs.existsSync(vaultPath)) {
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)
return DotenvModule.configDotenv(options)
}
return DotenvModule._configVault(options)
}
function decrypt (encrypted, keyStr) {
const key = Buffer.from(keyStr.slice(-64), 'hex')
let ciphertext = Buffer.from(encrypted, 'base64')
const nonce = ciphertext.slice(0, 12)
const authTag = ciphertext.slice(-16)
ciphertext = ciphertext.slice(12, -16)
try {
const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)
aesgcm.setAuthTag(authTag)
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`
} catch (error) {
const isRange = error instanceof RangeError
const invalidKeyLength = error.message === 'Invalid key length'
const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'
if (isRange || invalidKeyLength) {
const msg = 'INVALID_DOTENV_KEY: It must be 64 characters long (or more)'
throw new Error(msg)
} else if (decryptionFailed) {
const msg = 'DECRYPTION_FAILED: Please check your DOTENV_KEY'
throw new Error(msg)
} else {
console.error('Error: ', error.code)
console.error('Error: ', error.message)
throw error
}
}
}
// Populate process.env with parsed values
function populate (processEnv, parsed, options = {}) {
const debug = Boolean(options && options.debug)
const override = Boolean(options && options.override)
if (typeof parsed !== 'object') {
throw new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')
}
// Set process.env
for (const key of Object.keys(parsed)) {
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
if (override === true) {
processEnv[key] = parsed[key]
}
if (debug) {
if (override === true) {
_debug(`"${key}" is already defined and WAS overwritten`)
} else {
_debug(`"${key}" is already defined and was NOT overwritten`)
}
}
} else {
processEnv[key] = parsed[key]
}
}
}
const DotenvModule = {
configDotenv,
_configVault,
_parseVault,
config,
decrypt,
parse,
populate
}
module.exports.configDotenv = DotenvModule.configDotenv
module.exports._configVault = DotenvModule._configVault
module.exports._parseVault = DotenvModule._parseVault
module.exports.config = DotenvModule.config
module.exports.decrypt = DotenvModule.decrypt
module.exports.parse = DotenvModule.parse
module.exports.populate = DotenvModule.populate
module.exports = DotenvModule

View File

@ -0,0 +1,64 @@
{
"name": "dotenv",
"version": "16.3.1",
"description": "Loads environment variables from .env file",
"main": "lib/main.js",
"types": "lib/main.d.ts",
"exports": {
".": {
"types": "./lib/main.d.ts",
"require": "./lib/main.js",
"default": "./lib/main.js"
},
"./config": "./config.js",
"./config.js": "./config.js",
"./lib/env-options": "./lib/env-options.js",
"./lib/env-options.js": "./lib/env-options.js",
"./lib/cli-options": "./lib/cli-options.js",
"./lib/cli-options.js": "./lib/cli-options.js",
"./package.json": "./package.json"
},
"scripts": {
"dts-check": "tsc --project tests/types/tsconfig.json",
"lint": "standard",
"lint-readme": "standard-markdown",
"pretest": "npm run lint && npm run dts-check",
"test": "tap tests/*.js --100 -Rspec",
"prerelease": "npm test",
"release": "standard-version"
},
"repository": {
"type": "git",
"url": "git://github.com/motdotla/dotenv.git"
},
"funding": "https://github.com/motdotla/dotenv?sponsor=1",
"keywords": [
"dotenv",
"env",
".env",
"environment",
"variables",
"config",
"settings"
],
"readmeFilename": "README.md",
"license": "BSD-2-Clause",
"devDependencies": {
"@definitelytyped/dtslint": "^0.0.133",
"@types/node": "^18.11.3",
"decache": "^4.6.1",
"sinon": "^14.0.1",
"standard": "^17.0.0",
"standard-markdown": "^7.1.0",
"standard-version": "^9.5.0",
"tap": "^16.3.0",
"tar": "^6.1.11",
"typescript": "^4.8.4"
},
"engines": {
"node": ">=12"
},
"browser": {
"fs": false
}
}

16
Egnyte - Find Dead Files/node_modules/inherits/LICENSE generated vendored Normal file
View File

@ -0,0 +1,16 @@
The ISC License
Copyright (c) Isaac Z. Schlueter
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.

View File

@ -0,0 +1,42 @@
Browser-friendly inheritance fully compatible with standard node.js
[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
This package exports standard `inherits` from node.js `util` module in
node environment, but also provides alternative browser-friendly
implementation through [browser
field](https://gist.github.com/shtylman/4339901). Alternative
implementation is a literal copy of standard one located in standalone
module to avoid requiring of `util`. It also has a shim for old
browsers with no `Object.create` support.
While keeping you sure you are using standard `inherits`
implementation in node.js environment, it allows bundlers such as
[browserify](https://github.com/substack/node-browserify) to not
include full `util` package to your client code if all you need is
just `inherits` function. It worth, because browser shim for `util`
package is large and `inherits` is often the single function you need
from it.
It's recommended to use this package instead of
`require('util').inherits` for any code that has chances to be used
not only in node.js but in browser too.
## usage
```js
var inherits = require('inherits');
// then use exactly as the standard one
```
## note on version ~1.0
Version ~1.0 had completely different motivation and is not compatible
neither with 2.0 nor with standard node.js `inherits`.
If you are using version ~1.0 and planning to switch to ~2.0, be
careful:
* new version uses `super_` instead of `super` for referencing
superclass
* new version overwrites current prototype while old one preserves any
existing fields on it

View File

@ -0,0 +1,9 @@
try {
var util = require('util');
/* istanbul ignore next */
if (typeof util.inherits !== 'function') throw '';
module.exports = util.inherits;
} catch (e) {
/* istanbul ignore next */
module.exports = require('./inherits_browser.js');
}

View File

@ -0,0 +1,27 @@
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
if (superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
})
}
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
if (superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
}

View File

@ -0,0 +1,29 @@
{
"name": "inherits",
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
"version": "2.0.4",
"keywords": [
"inheritance",
"class",
"klass",
"oop",
"object-oriented",
"inherits",
"browser",
"browserify"
],
"main": "./inherits.js",
"browser": "./inherits_browser.js",
"repository": "git://github.com/isaacs/inherits",
"license": "ISC",
"scripts": {
"test": "tap"
},
"devDependencies": {
"tap": "^14.2.4"
},
"files": [
"inherits.js",
"inherits_browser.js"
]
}

View File

@ -0,0 +1 @@
node_modules

View File

@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.8"
- "0.10"

View File

@ -0,0 +1,6 @@
test:
@node_modules/.bin/tape test.js
.PHONY: test

View File

@ -0,0 +1,60 @@
# isarray
`Array#isArray` for older browsers.
[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray)
[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray)
[![browser support](https://ci.testling.com/juliangruber/isarray.png)
](https://ci.testling.com/juliangruber/isarray)
## Usage
```js
var isArray = require('isarray');
console.log(isArray([])); // => true
console.log(isArray({})); // => false
```
## Installation
With [npm](http://npmjs.org) do
```bash
$ npm install isarray
```
Then bundle for the browser with
[browserify](https://github.com/substack/browserify).
With [component](http://component.io) do
```bash
$ component install juliangruber/isarray
```
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
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.

View File

@ -0,0 +1,19 @@
{
"name" : "isarray",
"description" : "Array#isArray for older browsers",
"version" : "0.0.1",
"repository" : "juliangruber/isarray",
"homepage": "https://github.com/juliangruber/isarray",
"main" : "index.js",
"scripts" : [
"index.js"
],
"dependencies" : {},
"keywords": ["browser","isarray","array"],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT"
}

View File

@ -0,0 +1,5 @@
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};

View File

@ -0,0 +1,45 @@
{
"name": "isarray",
"description": "Array#isArray for older browsers",
"version": "1.0.0",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/isarray.git"
},
"homepage": "https://github.com/juliangruber/isarray",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"tape": "~2.13.4"
},
"keywords": [
"browser",
"isarray",
"array"
],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test.js",
"browsers": [
"ie/8..latest",
"firefox/17..latest",
"firefox/nightly",
"chrome/22..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"scripts": {
"test": "tape test.js"
}
}

20
Egnyte - Find Dead Files/node_modules/isarray/test.js generated vendored Normal file
View File

@ -0,0 +1,20 @@
var isArray = require('./');
var test = require('tape');
test('is array', function(t){
t.ok(isArray([]));
t.notOk(isArray({}));
t.notOk(isArray(null));
t.notOk(isArray(false));
var obj = {};
obj[0] = true;
t.notOk(isArray(obj));
var arr = [];
arr.foo = 'bar';
t.ok(isArray(arr));
t.end();
});

569
Egnyte - Find Dead Files/node_modules/mysql/Changes.md generated vendored Normal file
View File

@ -0,0 +1,569 @@
# Changes
This file is a manually maintained list of changes for each release. Feel free
to add your changes here when sending pull requests. Also send corrections if
you spot any mistakes.
## v2.18.1 (2020-01-23)
* Fix Amazon RDS profile for yaSSL MySQL servers with 2019 CA #2292
## v2.18.0 (2020-01-21)
* Add `localInfile` option to control `LOAD DATA LOCAL INFILE`
* Add new Amazon RDS Root 2019 CA to Amazon RDS SSL profile #2280
* Add new error codes up to MySQL 5.7.29
* Fix early detection of bad callback to `connection.query`
* Support Node.js 12.x #2211
* Support Node.js 13.x
* Support non-enumerable properties in object argument to `connection.query` #2253
* Update `bignumber.js` to 9.0.0
* Update `readable-stream` to 2.3.7
## v2.17.1 (2019-04-18)
* Update `bignumber.js` to 7.2.1 #2206
- Fix npm deprecation warning
## v2.17.0 (2019-04-17)
* Add reverse type lookup for small performance gain #2170
* Fix `connection.threadId` missing on handshake failure
* Fix duplicate packet name in debug output
* Fix no password support for old password protocol
* Remove special case for handshake in determine packet code
* Small performance improvement starting command sequence
* Support auth switch in change user flow #1776
* Support Node.js 11.x
* Update `bignumber.js` to 6.0.0
## v2.16.0 (2018-07-17)
* Add Amazon RDS GovCloud SSL certificates #1876
* Add new error codes up to MySQL 5.7.21
* Include connection ID in debug output
* Support Node.js 9.x
* Support Node.js 10.x #2003 #2024 #2026 #2034
* Update Amazon RDS SSL certificates
* Update `bignumber.js` to 4.1.0
* Update `readable-stream` to 2.3.6
* Update `sqlstring` to 2.3.1
- Fix incorrectly replacing non-placeholders in SQL
## v2.15.0 (2017-10-05)
* Add new Amazon RDS ca-central-1 certificate CA to Amazon RDS SSL profile #1809
* Add new error codes up to MySQL 5.7.19
* Add `mysql.raw()` to generate pre-escaped values #877 #1821
* Fix "changedRows" to work on non-English servers #1819
* Fix error when server sends RST on `QUIT` #1811
* Fix typo in insecure auth error message
* Support `mysql_native_password` auth switch request for Azure #1396 #1729 #1730
* Update `sqlstring` to 2.3.0
- Add `.toSqlString()` escape overriding
- Small performance improvement on `escapeId`
* Update `bignumber.js` to 4.0.4
## v2.14.1 (2017-08-01)
* Fix holding first closure for lifetime of connection #1785
## v2.14.0 (2017-07-25)
* Add new Amazon RDS ap-south-1 certificate CA to Amazon RDS SSL profile #1780
* Add new Amazon RDS eu-west-2 certificate CA to Amazon RDS SSL profile #1770
* Add `sql` property to query `Error` objects #1462 #1628 #1629
* Add `sqlMessage` property to `Error` objects #1714
* Fix the MySQL 5.7.17 error codes
* Support Node.js 8.x
* Update `bignumber.js` to 4.0.2
* Update `readable-stream` to 2.3.3
* Use `safe-buffer` for improved Buffer API
## v2.13.0 (2017-01-24)
* Accept regular expression as pool cluster pattern #1572
* Accept wildcard anywhere in pool cluster pattern #1570
* Add `acquire` and `release` events to `Pool` for tracking #1366 #1449 #1528 #1625
* Add new error codes up to MySQL 5.7.17
* Fix edge cases when determing Query result packets #1547
* Fix memory leak when using long-running domains #1619 #1620
* Remove unnecessary buffer copies when receiving large packets
* Update `bignumber.js` to 3.1.2
* Use a simple buffer list to improve performance #566 #1590
## v2.12.0 (2016-11-02)
* Accept array of type names to `dateStrings` option #605 #1481
* Add `query` method to `PoolNamespace` #1256 #1505 #1506
- Used as `cluster.of(...).query(...)`
* Add new error codes up to MySQL 5.7.16
* Fix edge cases writing certain length coded values
* Fix typo in `HANDSHAKE_NO_SSL_SUPPORT` error message #1534
* Support Node.js 7.x
* Update `bignumber.js` to 2.4.0
* Update `sqlstring` to 2.2.0
- Accept numbers and other value types in `escapeId`
- Escape invalid `Date` objects as `NULL`
- Run `buffer.toString()` through escaping
## v2.11.1 (2016-06-07)
* Fix writing truncated packets starting with large string/buffer #1438
## v2.11.0 (2016-06-06)
* Add `POOL_CLOSED` code to "Pool is closed." error
* Add `POOL_CONNLIMIT` code to "No connections available." error #1332
* Bind underlying connections in pool to same domain as pool #1242
* Bind underlying socket to same domain as connection #1243
* Fix allocation errors receiving many result rows #918 #1265 #1324 #1415
* Fix edge cases constructing long stack traces #1387
* Fix handshake inactivity timeout on Node.js v4.2.0 #1223 #1236 #1239 #1240 #1241 #1252
* Fix Query stream to emit close after ending #1349 #1350
* Fix type cast for BIGINT columns when number is negative #1376
* Performance improvements for array/object escaping in SqlString #1331
* Performance improvements for formatting in SqlString #1431
* Performance improvements for string escaping in SqlString #1390
* Performance improvements for writing packets to network
* Support Node.js 6.x
* Update `bignumber.js` to 2.3.0
* Update `readable-stream` to 1.1.14
* Use the `sqlstring` module for SQL escaping and formatting
## v2.10.2 (2016-01-12)
* Fix exception/hang from certain SSL connection errors #1153
* Update `bignumber.js` to 2.1.4
## v2.10.1 (2016-01-11)
* Add new Amazon RDS ap-northeast-2 certificate CA to Amazon RDS SSL profile #1329
## v2.10.0 (2015-12-15)
* Add new error codes up to MySQL 5.7.9 #1294
* Add new JSON type constant #1295
* Add types for fractional seconds support
* Fix `connection.destroy()` on pool connection creating sequences #1291
* Fix error code 139 `HA_ERR_TO_BIG_ROW` to be `HA_ERR_TOO_BIG_ROW`
* Fix error when call site error is missing stack #1179
* Fix reading password from MySQL URL that has bare colon #1278
* Handle MySQL servers not closing TCP connection after QUIT -> OK exchange #1277
* Minor SqlString Date to string performance improvement #1233
* Support Node.js 4.x
* Support Node.js 5.x
* Update `bignumber.js` to 2.1.2
## v2.9.0 (2015-08-19)
* Accept the `ciphers` property in connection `ssl` option #1185
* Fix bad timezone conversion from `Date` to string for certain times #1045 #1155
## v2.8.0 (2015-07-13)
* Add `connect` event to `Connection` #1129
* Default `timeout` for `connection.end` to 30 seconds #1057
* Fix a sync callback when sequence enqueue fails #1147
* Provide static require analysis
* Re-use connection from pool after `conn.changeUser` is used #837 #1088
## v2.7.0 (2015-05-27)
* Destroy/end connections removed from the pool on error
* Delay implied connect until after `.query` argument validation
* Do not remove connections with non-fatal errors from the pool
* Error early if `callback` argument to `.query` is not a function #1060
* Lazy-load modules from many entry point; reduced memory use
## v2.6.2 (2015-04-14)
* Fix `Connection.createQuery` for no SQL #1058
* Update `bignumber.js` to 2.0.7
## v2.6.1 (2015-03-26)
* Update `bignumber.js` to 2.0.5 #1037 #1038
## v2.6.0 (2015-03-24)
* Add `poolCluster.remove` to remove pools from the cluster #1006 #1007
* Add optional callback to `poolCluster.end`
* Add `restoreNodeTimeout` option to `PoolCluster` #880 #906
* Fix LOAD DATA INFILE handling in multiple statements #1036
* Fix `poolCluster.add` to throw if `PoolCluster` has been closed
* Fix `poolCluster.add` to throw if `id` already defined
* Fix un-catchable error from `PoolCluster` when MySQL server offline #1033
* Improve speed formatting SQL #1019
* Support io.js
## v2.5.5 (2015-02-23)
* Store SSL presets in JS instead of JSON #959
* Support Node.js 0.12
* Update Amazon RDS SSL certificates #1001
## v2.5.4 (2014-12-16)
* Fix error if falsy error thrown in callback handler #960
* Fix various error code strings #954
## v2.5.3 (2014-11-06)
* Fix `pool.query` streaming interface not emitting connection errors #941
## v2.5.2 (2014-10-10)
* Fix receiving large text fields #922
## v2.5.1 (2014-09-22)
* Fix `pool.end` race conditions #915
* Fix `pool.getConnection` race conditions
## v2.5.0 (2014-09-07)
* Add code `POOL_ENQUEUELIMIT` to error reaching `queueLimit`
* Add `enqueue` event to pool #716
* Add `enqueue` event to protocol and connection #381
* Blacklist unsupported connection flags #881
* Make only column names enumerable in `RowDataPacket` #549 #895
* Support Node.js 0.6 #718
## v2.4.3 (2014-08-25)
* Fix `pool.query` to use `typeCast` configuration
## v2.4.2 (2014-08-03)
* Fix incorrect sequence packet errors to be catchable #867
* Fix stray protocol packet errors to be catchable #867
* Fix timing of fatal protocol errors bubbling to user #879
## v2.4.1 (2014-07-17)
* Fix `pool.query` not invoking callback on connection error #872
## v2.4.0 (2014-07-13)
* Add code `POOL_NOEXIST` in PoolCluster error #846
* Add `acquireTimeout` pool option to specify a timeout for acquiring a connection #821 #854
* Add `connection.escapeId`
* Add `pool.escapeId`
* Add `timeout` option to all sequences #855 #863
* Default `connectTimeout` to 10 seconds
* Fix domain binding with `conn.connect`
* Fix `packet.default` to actually be a string
* Fix `PARSER_*` errors to be catchable
* Fix `PROTOCOL_PACKETS_OUT_OF_ORDER` error to be catchable #844
* Include packets that failed parsing under `debug`
* Return `Query` object from `pool.query` like `conn.query` #830
* Use `EventEmitter.listenerCount` when possible for faster counting
## v2.3.2 (2014-05-29)
* Fix pool leaking connections after `conn.changeUser` #833
## v2.3.1 (2014-05-26)
* Add database errors to error constants
* Add global errors to error constants
* Throw when calling `conn.release` multiple times #824 #827
* Update known error codes
## v2.3.0 (2014-05-16)
* Accept MySQL charset (like `UTF8` or `UTF8MB4`) in `charset` option #808
* Accept pool options in connection string to `mysql.createPool` #811
* Clone connection config for new pool connections
* Default `connectTimeout` to 2 minutes
* Reject unauthorized SSL connections (use `ssl.rejectUnauthorized` to override) #816
* Return last error when PoolCluster exhausts connection retries #818
* Remove connection from pool after `conn.changeUser` is released #806
* Throw on unknown SSL profile name #817
* User newer TLS functions when available #809
## v2.2.0 (2014-04-27)
* Use indexOf instead of for loops removing conn from pool #611
* Make callback to `pool.query` optional like `conn.query` #585
* Prevent enqueuing sequences after fatal error #400
* Fix geometry parser for empty fields #742
* Accept lower-case charset option
* Throw on unknown charset option #789
* Update known charsets
* Remove console.warn from PoolCluster #744
* Fix `pool.end` to handle queued connections #797
* Fix `pool.releaseConnection` to keep connection queue flowing #797
* Fix SSL handshake error to be catchable #800
* Add `connection.threadId` to get MySQL connection ID #602
* Ensure `pool.getConnection` retrieves good connections #434 #557 #778
* Fix pool cluster wildcard matching #627
* Pass query values through to `SqlString.format` #590
## v2.1.1 (2014-03-13)
* fix authentication w/password failure for node.js 0.10.5 #746 #752
* fix authentication w/password TypeError exception for node.js 0.10.0-0.10.4 #747
* fix specifying `values` in `conn.query({...}).on(...)` pattern #755
* fix long stack trace to include the `pool.query(...)` call #715
## v2.1.0 (2014-02-20)
* crypto.createHash fix for node.js < 11 #735
* Add `connectTimeout` option to specify a timeout for establishing a connection #726
* SSL support #481
## v2.0.1
* internal parser speed improvement #702
* domains support
* 'trace' connection option to control if long stack traces are generated #713 #710 #439
## v2.0.0 (2014-01-09)
* stream improvements:
- node 0.8 support #692
- Emit 'close' events from query streams #688
* encoding fix in streaming LOAD DATA LOCAL INFILE #670
* Doc improvements
## v2.0.0-rc2 (2013-12-07)
* Streaming LOAD DATA LOCAL INFILE #668
* Doc improvements
## v2.0.0-rc1 (2013-11-30)
* Transaction support
* Expose SqlString.format as mysql.format()
* Many bug fixes
* Better support for dates in local time zone
* Doc improvements
## v2.0.0-alpha9 (2013-08-27)
* Add query to pool to execute queries directly using the pool
* Add `sqlState` property to `Error` objects #556
* Pool option to set queue limit
* Pool sends 'connection' event when it opens a new connection
* Added stringifyObjects option to treat input as strings rather than objects (#501)
* Support for poolClusters
* Datetime improvements
* Bug fixes
## v2.0.0-alpha8 (2013-04-30)
* Switch to old mode for Streams 2 (Node.js v 0.10.x)
* Add stream method to Query Wraps events from the query object into a node v0.10.x Readable stream
* DECIMAL should also be treated as big number
* Removed slow unnecessary stack access
* Added charsets
* Added bigNumberStrings option for forcing BIGINT columns as strings
* Changes date parsing to return String if not a valid JS Date
* Adds support for ?? escape sequence to escape identifiers
* Changes Auth.token() to force password to be in binary, not utf8 (#378)
* Restrict debugging by packet types
* Add 'multipleStatements' option tracking to ConnectionConfig. Fixes GH-408
* Changes Pool to handle 'error' events and dispose connection
* Allows db.query({ sql: "..." }, [ val1, ... ], cb); (#390)
* Improved documentation
* Bug fixes
## v2.0.0-alpha7 (2013-02-03)
* Add connection pooling (#351)
## v2.0.0-alpha6 (2013-01-31)
* Add supportBigNumbers option (#381, #382)
* Accept prebuilt Query object in connection.query
* Bug fixes
## v2.0.0-alpha5 (2012-12-03)
* Add mysql.escapeId to escape identifiers (closes #342)
* Allow custom escaping mode (config.queryFormat)
* Convert DATE columns to configured timezone instead of UTC (#332)
* Convert LONGLONG and NEWDECIMAL to numbers (#333)
* Fix Connection.escape() (fixes #330)
* Changed Readme ambiguity about custom type cast fallback
* Change typeCast to receive Connection instead of Connection.config.timezone
* Fix drain event having useless err parameter
* Add Connection.statistics() back from v0.9
* Add Connection.ping() back from v0.9
## v2.0.0-alpha4 (2012-10-03)
* Fix some OOB errors on resume()
* Fix quick pause() / resume() usage
* Properly parse host denied / similar errors
* Add Connection.ChangeUser functionality
* Make sure changeUser errors are fatal
* Enable formatting nested arrays for bulk inserts
* Add Connection.escape functionality
* Renamed 'close' to 'end' event
* Return parsed object instead of Buffer for GEOMETRY types
* Allow nestTables inline (using a string instead of a boolean)
* Check for ZEROFILL_FLAG and format number accordingly
* Add timezone support (default: local)
* Add custom typeCast functionality
* Export mysql column types
* Add connection flags functionality (#237)
* Exports drain event when queue finishes processing (#272, #271, #306)
## v2.0.0-alpha3 (2012-06-12)
* Implement support for `LOAD DATA LOCAL INFILE` queries (#182).
* Support OLD\_PASSWORD() accounts like 0.9.x did. You should still upgrade any
user accounts in your your MySQL user table that has short (16 byte) Password
values. Connecting to those accounts is not secure. (#204)
* Ignore function values when escaping objects, allows to use RowDataPacket
objects as query arguments. (Alex Gorbatchev, #213)
* Handle initial error packets from server such as `ER_HOST_NOT_PRIVILEGED`.
* Treat `utf8\_bin` as a String, not Buffer. (#214)
* Handle empty strings in first row column value. (#222)
* Honor Connection#nestTables setting for queries. (#221)
* Remove `CLIENT_INTERACTIVE` flag from config. Improves #225.
* Improve docs for connections settings.
* Implement url string support for Connection configs.
## v2.0.0-alpha2 (2012-05-31)
* Specify escaping before for NaN / Infinity (they are as unquoted constants).
* Support for unix domain socket connections (use: {socketPath: '...'}).
* Fix type casting for NULL values for Date/Number fields
* Add `fields` argument to `query()` as well as `'fields'` event. This is
similar to what was available in 0.9.x.
* Support connecting to the sphinx searchd daemon as well as MariaDB (#199).
* Implement long stack trace support, will be removed / disabled if the node
core ever supports it natively.
* Implement `nestTables` option for queries, allows fetching JOIN result sets
with overlapping column names.
* Fix ? placeholder mechanism for values containing '?' characters (#205).
* Detect when `connect()` is called more than once on a connection and provide
the user with a good error message for it (#204).
* Switch to `UTF8_GENERAL_CI` (previously `UTF8_UNICODE_CI`) as the default
charset for all connections to avoid strange MySQL performance issues (#200),
and also make the charset user configurable.
* Fix BLOB type casting for `TINY_BLOB`, `MEDIUM_BLOB` and `LONG_BLOB`.
* Add support for sending and receiving large (> 16 MB) packets.
## v2.0.0-alpha (2012-05-15)
This release is a rewrite. You should carefully test your application after
upgrading to avoid problems. This release features many improvements, most
importantly:
* ~5x faster than v0.9.x for parsing query results
* Support for pause() / resume() (for streaming rows)
* Support for multiple statement queries
* Support for stored procedures
* Support for transactions
* Support for binary columns (as blobs)
* Consistent & well documented error handling
* A new Connection class that has well defined semantics (unlike the old Client class).
* Convenient escaping of objects / arrays that allows for simpler query construction
* A significantly simpler code base
* Many bug fixes & other small improvements (Closed 62 out of 66 GitHub issues)
Below are a few notes on the upgrade process itself:
The first thing you will run into is that the old `Client` class is gone and
has been replaced with a less ambitious `Connection` class. So instead of
`mysql.createClient()`, you now have to:
```js
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
});
connection.query('SELECT 1', function(err, rows) {
if (err) throw err;
console.log('Query result: ', rows);
});
connection.end();
```
The new `Connection` class does not try to handle re-connects, please study the
`Server disconnects` section in the new Readme.
Other than that, the interface has stayed very similar. Here are a few things
to check out so:
* BIGINT's are now cast into strings
* Binary data is now cast to buffers
* The `'row'` event on the `Query` object is now called `'result'` and will
also be emitted for queries that produce an OK/Error response.
* Error handling is consistently defined now, check the Readme
* Escaping has become more powerful which may break your code if you are
currently using objects to fill query placeholders.
* Connections can now be established explicitly again, so you may wish to do so
if you want to handle connection errors specifically.
That should be most of it, if you run into anything else, please send a patch
or open an issue to improve this document.
## v0.9.6 (2012-03-12)
* Escape array values so they produce sql arrays (Roger Castells, Colin Smith)
* docs: mention mysql transaction stop gap solution (Blake Miner)
* docs: Mention affectedRows in FAQ (Michael Baldwin)
## v0.9.5 (2011-11-26)
* Fix #142 Driver stalls upon reconnect attempt that's immediately closed
* Add travis build
* Switch to urun as a test runner
* Switch to utest for unit tests
* Remove fast-or-slow dependency for tests
* Split integration tests into individual files again
## v0.9.4 (2011-08-31)
* Expose package.json as `mysql.PACKAGE` (#104)
## v0.9.3 (2011-08-22)
* Set default `client.user` to root
* Fix #91: Client#format should not mutate params array
* Fix #94: TypeError in client.js
* Parse decimals as string (vadimg)
## v0.9.2 (2011-08-07)
* The underlaying socket connection is now managed implicitly rather than explicitly.
* Check the [upgrading guide][] for a full list of changes.
## v0.9.1 (2011-02-20)
* Fix issue #49 / `client.escape()` throwing exceptions on objects. (Nick Payne)
* Drop < v0.4.x compatibility. From now on you need node v0.4.x to use this module.
## Older releases
These releases were done before maintaining this file:
* [v0.9.0](https://github.com/mysqljs/mysql/compare/v0.8.0...v0.9.0)
(2011-01-04)
* [v0.8.0](https://github.com/mysqljs/mysql/compare/v0.7.0...v0.8.0)
(2010-10-30)
* [v0.7.0](https://github.com/mysqljs/mysql/compare/v0.6.0...v0.7.0)
(2010-10-14)
* [v0.6.0](https://github.com/mysqljs/mysql/compare/v0.5.0...v0.6.0)
(2010-09-28)
* [v0.5.0](https://github.com/mysqljs/mysql/compare/v0.4.0...v0.5.0)
(2010-09-17)
* [v0.4.0](https://github.com/mysqljs/mysql/compare/v0.3.0...v0.4.0)
(2010-09-02)
* [v0.3.0](https://github.com/mysqljs/mysql/compare/v0.2.0...v0.3.0)
(2010-08-25)
* [v0.2.0](https://github.com/mysqljs/mysql/compare/v0.1.0...v0.2.0)
(2010-08-22)
* [v0.1.0](https://github.com/mysqljs/mysql/commits/v0.1.0)
(2010-08-22)

19
Egnyte - Find Dead Files/node_modules/mysql/License generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
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.

1548
Egnyte - Find Dead Files/node_modules/mysql/Readme.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

161
Egnyte - Find Dead Files/node_modules/mysql/index.js generated vendored Normal file
View File

@ -0,0 +1,161 @@
var Classes = Object.create(null);
/**
* Create a new Connection instance.
* @param {object|string} config Configuration or connection string for new MySQL connection
* @return {Connection} A new MySQL connection
* @public
*/
exports.createConnection = function createConnection(config) {
var Connection = loadClass('Connection');
var ConnectionConfig = loadClass('ConnectionConfig');
return new Connection({config: new ConnectionConfig(config)});
};
/**
* Create a new Pool instance.
* @param {object|string} config Configuration or connection string for new MySQL connections
* @return {Pool} A new MySQL pool
* @public
*/
exports.createPool = function createPool(config) {
var Pool = loadClass('Pool');
var PoolConfig = loadClass('PoolConfig');
return new Pool({config: new PoolConfig(config)});
};
/**
* Create a new PoolCluster instance.
* @param {object} [config] Configuration for pool cluster
* @return {PoolCluster} New MySQL pool cluster
* @public
*/
exports.createPoolCluster = function createPoolCluster(config) {
var PoolCluster = loadClass('PoolCluster');
return new PoolCluster(config);
};
/**
* Create a new Query instance.
* @param {string} sql The SQL for the query
* @param {array} [values] Any values to insert into placeholders in sql
* @param {function} [callback] The callback to use when query is complete
* @return {Query} New query object
* @public
*/
exports.createQuery = function createQuery(sql, values, callback) {
var Connection = loadClass('Connection');
return Connection.createQuery(sql, values, callback);
};
/**
* Escape a value for SQL.
* @param {*} value The value to escape
* @param {boolean} [stringifyObjects=false] Setting if objects should be stringified
* @param {string} [timeZone=local] Setting for time zone to use for Date conversion
* @return {string} Escaped string value
* @public
*/
exports.escape = function escape(value, stringifyObjects, timeZone) {
var SqlString = loadClass('SqlString');
return SqlString.escape(value, stringifyObjects, timeZone);
};
/**
* Escape an identifier for SQL.
* @param {*} value The value to escape
* @param {boolean} [forbidQualified=false] Setting to treat '.' as part of identifier
* @return {string} Escaped string value
* @public
*/
exports.escapeId = function escapeId(value, forbidQualified) {
var SqlString = loadClass('SqlString');
return SqlString.escapeId(value, forbidQualified);
};
/**
* Format SQL and replacement values into a SQL string.
* @param {string} sql The SQL for the query
* @param {array} [values] Any values to insert into placeholders in sql
* @param {boolean} [stringifyObjects=false] Setting if objects should be stringified
* @param {string} [timeZone=local] Setting for time zone to use for Date conversion
* @return {string} Formatted SQL string
* @public
*/
exports.format = function format(sql, values, stringifyObjects, timeZone) {
var SqlString = loadClass('SqlString');
return SqlString.format(sql, values, stringifyObjects, timeZone);
};
/**
* Wrap raw SQL strings from escape overriding.
* @param {string} sql The raw SQL
* @return {object} Wrapped object
* @public
*/
exports.raw = function raw(sql) {
var SqlString = loadClass('SqlString');
return SqlString.raw(sql);
};
/**
* The type constants.
* @public
*/
Object.defineProperty(exports, 'Types', {
get: loadClass.bind(null, 'Types')
});
/**
* Load the given class.
* @param {string} className Name of class to default
* @return {function|object} Class constructor or exports
* @private
*/
function loadClass(className) {
var Class = Classes[className];
if (Class !== undefined) {
return Class;
}
// This uses a switch for static require analysis
switch (className) {
case 'Connection':
Class = require('./lib/Connection');
break;
case 'ConnectionConfig':
Class = require('./lib/ConnectionConfig');
break;
case 'Pool':
Class = require('./lib/Pool');
break;
case 'PoolCluster':
Class = require('./lib/PoolCluster');
break;
case 'PoolConfig':
Class = require('./lib/PoolConfig');
break;
case 'SqlString':
Class = require('./lib/protocol/SqlString');
break;
case 'Types':
Class = require('./lib/protocol/constants/types');
break;
default:
throw new Error('Cannot find class \'' + className + '\'');
}
// Store to prevent invoking require()
Classes[className] = Class;
return Class;
}

View File

@ -0,0 +1,529 @@
var Crypto = require('crypto');
var Events = require('events');
var Net = require('net');
var tls = require('tls');
var ConnectionConfig = require('./ConnectionConfig');
var Protocol = require('./protocol/Protocol');
var SqlString = require('./protocol/SqlString');
var Query = require('./protocol/sequences/Query');
var Util = require('util');
module.exports = Connection;
Util.inherits(Connection, Events.EventEmitter);
function Connection(options) {
Events.EventEmitter.call(this);
this.config = options.config;
this._socket = options.socket;
this._protocol = new Protocol({config: this.config, connection: this});
this._connectCalled = false;
this.state = 'disconnected';
this.threadId = null;
}
Connection.createQuery = function createQuery(sql, values, callback) {
if (sql instanceof Query) {
return sql;
}
var cb = callback;
var options = {};
if (typeof sql === 'function') {
cb = sql;
} else if (typeof sql === 'object') {
options = Object.create(sql);
if (typeof values === 'function') {
cb = values;
} else if (values !== undefined) {
Object.defineProperty(options, 'values', { value: values });
}
} else {
options.sql = sql;
if (typeof values === 'function') {
cb = values;
} else if (values !== undefined) {
options.values = values;
}
}
if (cb !== undefined) {
cb = wrapCallbackInDomain(null, cb);
if (cb === undefined) {
throw new TypeError('argument callback must be a function when provided');
}
}
return new Query(options, cb);
};
Connection.prototype.connect = function connect(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
if (!this._connectCalled) {
this._connectCalled = true;
// Connect either via a UNIX domain socket or a TCP socket.
this._socket = (this.config.socketPath)
? Net.createConnection(this.config.socketPath)
: Net.createConnection(this.config.port, this.config.host);
// Connect socket to connection domain
if (Events.usingDomains) {
this._socket.domain = this.domain;
}
var connection = this;
this._protocol.on('data', function(data) {
connection._socket.write(data);
});
this._socket.on('data', wrapToDomain(connection, function (data) {
connection._protocol.write(data);
}));
this._protocol.on('end', function() {
connection._socket.end();
});
this._socket.on('end', wrapToDomain(connection, function () {
connection._protocol.end();
}));
this._socket.on('error', this._handleNetworkError.bind(this));
this._socket.on('connect', this._handleProtocolConnect.bind(this));
this._protocol.on('handshake', this._handleProtocolHandshake.bind(this));
this._protocol.on('initialize', this._handleProtocolInitialize.bind(this));
this._protocol.on('unhandledError', this._handleProtocolError.bind(this));
this._protocol.on('drain', this._handleProtocolDrain.bind(this));
this._protocol.on('end', this._handleProtocolEnd.bind(this));
this._protocol.on('enqueue', this._handleProtocolEnqueue.bind(this));
if (this.config.connectTimeout) {
var handleConnectTimeout = this._handleConnectTimeout.bind(this);
this._socket.setTimeout(this.config.connectTimeout, handleConnectTimeout);
this._socket.once('connect', function() {
this.setTimeout(0, handleConnectTimeout);
});
}
}
this._protocol.handshake(options, wrapCallbackInDomain(this, callback));
};
Connection.prototype.changeUser = function changeUser(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
this._implyConnect();
var charsetNumber = (options.charset)
? ConnectionConfig.getCharsetNumber(options.charset)
: this.config.charsetNumber;
return this._protocol.changeUser({
user : options.user || this.config.user,
password : options.password || this.config.password,
database : options.database || this.config.database,
timeout : options.timeout,
charsetNumber : charsetNumber,
currentConfig : this.config
}, wrapCallbackInDomain(this, callback));
};
Connection.prototype.beginTransaction = function beginTransaction(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
options.sql = 'START TRANSACTION';
options.values = null;
return this.query(options, callback);
};
Connection.prototype.commit = function commit(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
options.sql = 'COMMIT';
options.values = null;
return this.query(options, callback);
};
Connection.prototype.rollback = function rollback(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
options.sql = 'ROLLBACK';
options.values = null;
return this.query(options, callback);
};
Connection.prototype.query = function query(sql, values, cb) {
var query = Connection.createQuery(sql, values, cb);
query._connection = this;
if (!(typeof sql === 'object' && 'typeCast' in sql)) {
query.typeCast = this.config.typeCast;
}
if (query.sql) {
query.sql = this.format(query.sql, query.values);
}
if (query._callback) {
query._callback = wrapCallbackInDomain(this, query._callback);
}
this._implyConnect();
return this._protocol._enqueue(query);
};
Connection.prototype.ping = function ping(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
this._implyConnect();
this._protocol.ping(options, wrapCallbackInDomain(this, callback));
};
Connection.prototype.statistics = function statistics(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
this._implyConnect();
this._protocol.stats(options, wrapCallbackInDomain(this, callback));
};
Connection.prototype.end = function end(options, callback) {
var cb = callback;
var opts = options;
if (!callback && typeof options === 'function') {
cb = options;
opts = null;
}
// create custom options reference
opts = Object.create(opts || null);
if (opts.timeout === undefined) {
// default timeout of 30 seconds
opts.timeout = 30000;
}
this._implyConnect();
this._protocol.quit(opts, wrapCallbackInDomain(this, cb));
};
Connection.prototype.destroy = function() {
this.state = 'disconnected';
this._implyConnect();
this._socket.destroy();
this._protocol.destroy();
};
Connection.prototype.pause = function() {
this._socket.pause();
this._protocol.pause();
};
Connection.prototype.resume = function() {
this._socket.resume();
this._protocol.resume();
};
Connection.prototype.escape = function(value) {
return SqlString.escape(value, false, this.config.timezone);
};
Connection.prototype.escapeId = function escapeId(value) {
return SqlString.escapeId(value, false);
};
Connection.prototype.format = function(sql, values) {
if (typeof this.config.queryFormat === 'function') {
return this.config.queryFormat.call(this, sql, values, this.config.timezone);
}
return SqlString.format(sql, values, this.config.stringifyObjects, this.config.timezone);
};
if (tls.TLSSocket) {
// 0.11+ environment
Connection.prototype._startTLS = function _startTLS(onSecure) {
var connection = this;
createSecureContext(this.config, function (err, secureContext) {
if (err) {
onSecure(err);
return;
}
// "unpipe"
connection._socket.removeAllListeners('data');
connection._protocol.removeAllListeners('data');
// socket <-> encrypted
var rejectUnauthorized = connection.config.ssl.rejectUnauthorized;
var secureEstablished = false;
var secureSocket = new tls.TLSSocket(connection._socket, {
rejectUnauthorized : rejectUnauthorized,
requestCert : true,
secureContext : secureContext,
isServer : false
});
// error handler for secure socket
secureSocket.on('_tlsError', function(err) {
if (secureEstablished) {
connection._handleNetworkError(err);
} else {
onSecure(err);
}
});
// cleartext <-> protocol
secureSocket.pipe(connection._protocol);
connection._protocol.on('data', function(data) {
secureSocket.write(data);
});
secureSocket.on('secure', function() {
secureEstablished = true;
onSecure(rejectUnauthorized ? this.ssl.verifyError() : null);
});
// start TLS communications
secureSocket._start();
});
};
} else {
// pre-0.11 environment
Connection.prototype._startTLS = function _startTLS(onSecure) {
// before TLS:
// _socket <-> _protocol
// after:
// _socket <-> securePair.encrypted <-> securePair.cleartext <-> _protocol
var connection = this;
var credentials = Crypto.createCredentials({
ca : this.config.ssl.ca,
cert : this.config.ssl.cert,
ciphers : this.config.ssl.ciphers,
key : this.config.ssl.key,
passphrase : this.config.ssl.passphrase
});
var rejectUnauthorized = this.config.ssl.rejectUnauthorized;
var secureEstablished = false;
var securePair = tls.createSecurePair(credentials, false, true, rejectUnauthorized);
// error handler for secure pair
securePair.on('error', function(err) {
if (secureEstablished) {
connection._handleNetworkError(err);
} else {
onSecure(err);
}
});
// "unpipe"
this._socket.removeAllListeners('data');
this._protocol.removeAllListeners('data');
// socket <-> encrypted
securePair.encrypted.pipe(this._socket);
this._socket.on('data', function(data) {
securePair.encrypted.write(data);
});
// cleartext <-> protocol
securePair.cleartext.pipe(this._protocol);
this._protocol.on('data', function(data) {
securePair.cleartext.write(data);
});
// secure established
securePair.on('secure', function() {
secureEstablished = true;
if (!rejectUnauthorized) {
onSecure();
return;
}
var verifyError = this.ssl.verifyError();
var err = verifyError;
// node.js 0.6 support
if (typeof err === 'string') {
err = new Error(verifyError);
err.code = verifyError;
}
onSecure(err);
});
// node.js 0.8 bug
securePair._cycle = securePair.cycle;
securePair.cycle = function cycle() {
if (this.ssl && this.ssl.error) {
this.error();
}
return this._cycle.apply(this, arguments);
};
};
}
Connection.prototype._handleConnectTimeout = function() {
if (this._socket) {
this._socket.setTimeout(0);
this._socket.destroy();
}
var err = new Error('connect ETIMEDOUT');
err.errorno = 'ETIMEDOUT';
err.code = 'ETIMEDOUT';
err.syscall = 'connect';
this._handleNetworkError(err);
};
Connection.prototype._handleNetworkError = function(err) {
this._protocol.handleNetworkError(err);
};
Connection.prototype._handleProtocolError = function(err) {
this.state = 'protocol_error';
this.emit('error', err);
};
Connection.prototype._handleProtocolDrain = function() {
this.emit('drain');
};
Connection.prototype._handleProtocolConnect = function() {
this.state = 'connected';
this.emit('connect');
};
Connection.prototype._handleProtocolHandshake = function _handleProtocolHandshake() {
this.state = 'authenticated';
};
Connection.prototype._handleProtocolInitialize = function _handleProtocolInitialize(packet) {
this.threadId = packet.threadId;
};
Connection.prototype._handleProtocolEnd = function(err) {
this.state = 'disconnected';
this.emit('end', err);
};
Connection.prototype._handleProtocolEnqueue = function _handleProtocolEnqueue(sequence) {
this.emit('enqueue', sequence);
};
Connection.prototype._implyConnect = function() {
if (!this._connectCalled) {
this.connect();
}
};
function createSecureContext (config, cb) {
var context = null;
var error = null;
try {
context = tls.createSecureContext({
ca : config.ssl.ca,
cert : config.ssl.cert,
ciphers : config.ssl.ciphers,
key : config.ssl.key,
passphrase : config.ssl.passphrase
});
} catch (err) {
error = err;
}
cb(error, context);
}
function unwrapFromDomain(fn) {
return function () {
var domains = [];
var ret;
while (process.domain) {
domains.shift(process.domain);
process.domain.exit();
}
try {
ret = fn.apply(this, arguments);
} finally {
for (var i = 0; i < domains.length; i++) {
domains[i].enter();
}
}
return ret;
};
}
function wrapCallbackInDomain(ee, fn) {
if (typeof fn !== 'function') {
return undefined;
}
if (fn.domain) {
return fn;
}
var domain = process.domain;
if (domain) {
return domain.bind(fn);
} else if (ee) {
return unwrapFromDomain(wrapToDomain(ee, fn));
} else {
return fn;
}
}
function wrapToDomain(ee, fn) {
return function () {
if (Events.usingDomains && ee.domain) {
ee.domain.enter();
fn.apply(this, arguments);
ee.domain.exit();
} else {
fn.apply(this, arguments);
}
};
}

View File

@ -0,0 +1,209 @@
var urlParse = require('url').parse;
var ClientConstants = require('./protocol/constants/client');
var Charsets = require('./protocol/constants/charsets');
var SSLProfiles = null;
module.exports = ConnectionConfig;
function ConnectionConfig(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.host = options.host || 'localhost';
this.port = options.port || 3306;
this.localAddress = options.localAddress;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
this.password = options.password || undefined;
this.database = options.database;
this.connectTimeout = (options.connectTimeout === undefined)
? (10 * 1000)
: options.connectTimeout;
this.insecureAuth = options.insecureAuth || false;
this.supportBigNumbers = options.supportBigNumbers || false;
this.bigNumberStrings = options.bigNumberStrings || false;
this.dateStrings = options.dateStrings || false;
this.debug = options.debug;
this.trace = options.trace !== false;
this.stringifyObjects = options.stringifyObjects || false;
this.timezone = options.timezone || 'local';
this.flags = options.flags || '';
this.queryFormat = options.queryFormat;
this.pool = options.pool || undefined;
this.ssl = (typeof options.ssl === 'string')
? ConnectionConfig.getSSLProfile(options.ssl)
: (options.ssl || false);
this.localInfile = (options.localInfile === undefined)
? true
: options.localInfile;
this.multipleStatements = options.multipleStatements || false;
this.typeCast = (options.typeCast === undefined)
? true
: options.typeCast;
if (this.timezone[0] === ' ') {
// "+" is a url encoded char for space so it
// gets translated to space when giving a
// connection string..
this.timezone = '+' + this.timezone.substr(1);
}
if (this.ssl) {
// Default rejectUnauthorized to true
this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
}
this.maxPacketSize = 0;
this.charsetNumber = (options.charset)
? ConnectionConfig.getCharsetNumber(options.charset)
: options.charsetNumber || Charsets.UTF8_GENERAL_CI;
// Set the client flags
var defaultFlags = ConnectionConfig.getDefaultFlags(options);
this.clientFlags = ConnectionConfig.mergeFlags(defaultFlags, options.flags);
}
ConnectionConfig.mergeFlags = function mergeFlags(defaultFlags, userFlags) {
var allFlags = ConnectionConfig.parseFlagList(defaultFlags);
var newFlags = ConnectionConfig.parseFlagList(userFlags);
// Merge the new flags
for (var flag in newFlags) {
if (allFlags[flag] !== false) {
allFlags[flag] = newFlags[flag];
}
}
// Build flags
var flags = 0x0;
for (var flag in allFlags) {
if (allFlags[flag]) {
// TODO: Throw here on some future release
flags |= ClientConstants['CLIENT_' + flag] || 0x0;
}
}
return flags;
};
ConnectionConfig.getCharsetNumber = function getCharsetNumber(charset) {
var num = Charsets[charset.toUpperCase()];
if (num === undefined) {
throw new TypeError('Unknown charset \'' + charset + '\'');
}
return num;
};
ConnectionConfig.getDefaultFlags = function getDefaultFlags(options) {
var defaultFlags = [
'-COMPRESS', // Compression protocol *NOT* supported
'-CONNECT_ATTRS', // Does *NOT* send connection attributes in Protocol::HandshakeResponse41
'+CONNECT_WITH_DB', // One can specify db on connect in Handshake Response Packet
'+FOUND_ROWS', // Send found rows instead of affected rows
'+IGNORE_SIGPIPE', // Don't issue SIGPIPE if network failures
'+IGNORE_SPACE', // Let the parser ignore spaces before '('
'+LOCAL_FILES', // Can use LOAD DATA LOCAL
'+LONG_FLAG', // Longer flags in Protocol::ColumnDefinition320
'+LONG_PASSWORD', // Use the improved version of Old Password Authentication
'+MULTI_RESULTS', // Can handle multiple resultsets for COM_QUERY
'+ODBC', // Special handling of ODBC behaviour
'-PLUGIN_AUTH', // Does *NOT* support auth plugins
'+PROTOCOL_41', // Uses the 4.1 protocol
'+PS_MULTI_RESULTS', // Can handle multiple resultsets for COM_STMT_EXECUTE
'+RESERVED', // Unused
'+SECURE_CONNECTION', // Supports Authentication::Native41
'+TRANSACTIONS' // Expects status flags
];
if (options && options.localInfile !== undefined && !options.localInfile) {
// Disable LOCAL modifier for LOAD DATA INFILE
defaultFlags.push('-LOCAL_FILES');
}
if (options && options.multipleStatements) {
// May send multiple statements per COM_QUERY and COM_STMT_PREPARE
defaultFlags.push('+MULTI_STATEMENTS');
}
return defaultFlags;
};
ConnectionConfig.getSSLProfile = function getSSLProfile(name) {
if (!SSLProfiles) {
SSLProfiles = require('./protocol/constants/ssl_profiles');
}
var ssl = SSLProfiles[name];
if (ssl === undefined) {
throw new TypeError('Unknown SSL profile \'' + name + '\'');
}
return ssl;
};
ConnectionConfig.parseFlagList = function parseFlagList(flagList) {
var allFlags = Object.create(null);
if (!flagList) {
return allFlags;
}
var flags = !Array.isArray(flagList)
? String(flagList || '').toUpperCase().split(/\s*,+\s*/)
: flagList;
for (var i = 0; i < flags.length; i++) {
var flag = flags[i];
var offset = 1;
var state = flag[0];
if (state === undefined) {
// TODO: throw here on some future release
continue;
}
if (state !== '-' && state !== '+') {
offset = 0;
state = '+';
}
allFlags[flag.substr(offset)] = state === '+';
}
return allFlags;
};
ConnectionConfig.parseUrl = function(url) {
url = urlParse(url, true);
var options = {
host : url.hostname,
port : url.port,
database : url.pathname.substr(1)
};
if (url.auth) {
var auth = url.auth.split(':');
options.user = auth.shift();
options.password = auth.join(':');
}
if (url.query) {
for (var key in url.query) {
var value = url.query[key];
try {
// Try to parse this as a JSON expression first
options[key] = JSON.parse(value);
} catch (err) {
// Otherwise assume it is a plain string
options[key] = value;
}
}
}
return options;
};

294
Egnyte - Find Dead Files/node_modules/mysql/lib/Pool.js generated vendored Normal file
View File

@ -0,0 +1,294 @@
var mysql = require('../');
var Connection = require('./Connection');
var EventEmitter = require('events').EventEmitter;
var Util = require('util');
var PoolConnection = require('./PoolConnection');
module.exports = Pool;
Util.inherits(Pool, EventEmitter);
function Pool(options) {
EventEmitter.call(this);
this.config = options.config;
this.config.connectionConfig.pool = this;
this._acquiringConnections = [];
this._allConnections = [];
this._freeConnections = [];
this._connectionQueue = [];
this._closed = false;
}
Pool.prototype.getConnection = function (cb) {
if (this._closed) {
var err = new Error('Pool is closed.');
err.code = 'POOL_CLOSED';
process.nextTick(function () {
cb(err);
});
return;
}
var connection;
var pool = this;
if (this._freeConnections.length > 0) {
connection = this._freeConnections.shift();
this.acquireConnection(connection, cb);
return;
}
if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) {
connection = new PoolConnection(this, { config: this.config.newConnectionConfig() });
this._acquiringConnections.push(connection);
this._allConnections.push(connection);
connection.connect({timeout: this.config.acquireTimeout}, function onConnect(err) {
spliceConnection(pool._acquiringConnections, connection);
if (pool._closed) {
err = new Error('Pool is closed.');
err.code = 'POOL_CLOSED';
}
if (err) {
pool._purgeConnection(connection);
cb(err);
return;
}
pool.emit('connection', connection);
pool.emit('acquire', connection);
cb(null, connection);
});
return;
}
if (!this.config.waitForConnections) {
process.nextTick(function(){
var err = new Error('No connections available.');
err.code = 'POOL_CONNLIMIT';
cb(err);
});
return;
}
this._enqueueCallback(cb);
};
Pool.prototype.acquireConnection = function acquireConnection(connection, cb) {
if (connection._pool !== this) {
throw new Error('Connection acquired from wrong pool.');
}
var changeUser = this._needsChangeUser(connection);
var pool = this;
this._acquiringConnections.push(connection);
function onOperationComplete(err) {
spliceConnection(pool._acquiringConnections, connection);
if (pool._closed) {
err = new Error('Pool is closed.');
err.code = 'POOL_CLOSED';
}
if (err) {
pool._connectionQueue.unshift(cb);
pool._purgeConnection(connection);
return;
}
if (changeUser) {
pool.emit('connection', connection);
}
pool.emit('acquire', connection);
cb(null, connection);
}
if (changeUser) {
// restore user back to pool configuration
connection.config = this.config.newConnectionConfig();
connection.changeUser({timeout: this.config.acquireTimeout}, onOperationComplete);
} else {
// ping connection
connection.ping({timeout: this.config.acquireTimeout}, onOperationComplete);
}
};
Pool.prototype.releaseConnection = function releaseConnection(connection) {
if (this._acquiringConnections.indexOf(connection) !== -1) {
// connection is being acquired
return;
}
if (connection._pool) {
if (connection._pool !== this) {
throw new Error('Connection released to wrong pool');
}
if (this._freeConnections.indexOf(connection) !== -1) {
// connection already in free connection pool
// this won't catch all double-release cases
throw new Error('Connection already released');
} else {
// add connection to end of free queue
this._freeConnections.push(connection);
this.emit('release', connection);
}
}
if (this._closed) {
// empty the connection queue
this._connectionQueue.splice(0).forEach(function (cb) {
var err = new Error('Pool is closed.');
err.code = 'POOL_CLOSED';
process.nextTick(function () {
cb(err);
});
});
} else if (this._connectionQueue.length) {
// get connection with next waiting callback
this.getConnection(this._connectionQueue.shift());
}
};
Pool.prototype.end = function (cb) {
this._closed = true;
if (typeof cb !== 'function') {
cb = function (err) {
if (err) throw err;
};
}
var calledBack = false;
var waitingClose = 0;
function onEnd(err) {
if (!calledBack && (err || --waitingClose <= 0)) {
calledBack = true;
cb(err);
}
}
while (this._allConnections.length !== 0) {
waitingClose++;
this._purgeConnection(this._allConnections[0], onEnd);
}
if (waitingClose === 0) {
process.nextTick(onEnd);
}
};
Pool.prototype.query = function (sql, values, cb) {
var query = Connection.createQuery(sql, values, cb);
if (!(typeof sql === 'object' && 'typeCast' in sql)) {
query.typeCast = this.config.connectionConfig.typeCast;
}
if (this.config.connectionConfig.trace) {
// Long stack trace support
query._callSite = new Error();
}
this.getConnection(function (err, conn) {
if (err) {
query.on('error', function () {});
query.end(err);
return;
}
// Release connection based off event
query.once('end', function() {
conn.release();
});
conn.query(query);
});
return query;
};
Pool.prototype._enqueueCallback = function _enqueueCallback(callback) {
if (this.config.queueLimit && this._connectionQueue.length >= this.config.queueLimit) {
process.nextTick(function () {
var err = new Error('Queue limit reached.');
err.code = 'POOL_ENQUEUELIMIT';
callback(err);
});
return;
}
// Bind to domain, as dequeue will likely occur in a different domain
var cb = process.domain
? process.domain.bind(callback)
: callback;
this._connectionQueue.push(cb);
this.emit('enqueue');
};
Pool.prototype._needsChangeUser = function _needsChangeUser(connection) {
var connConfig = connection.config;
var poolConfig = this.config.connectionConfig;
// check if changeUser values are different
return connConfig.user !== poolConfig.user
|| connConfig.database !== poolConfig.database
|| connConfig.password !== poolConfig.password
|| connConfig.charsetNumber !== poolConfig.charsetNumber;
};
Pool.prototype._purgeConnection = function _purgeConnection(connection, callback) {
var cb = callback || function () {};
if (connection.state === 'disconnected') {
connection.destroy();
}
this._removeConnection(connection);
if (connection.state !== 'disconnected' && !connection._protocol._quitSequence) {
connection._realEnd(cb);
return;
}
process.nextTick(cb);
};
Pool.prototype._removeConnection = function(connection) {
connection._pool = null;
// Remove connection from all connections
spliceConnection(this._allConnections, connection);
// Remove connection from free connections
spliceConnection(this._freeConnections, connection);
this.releaseConnection(connection);
};
Pool.prototype.escape = function(value) {
return mysql.escape(value, this.config.connectionConfig.stringifyObjects, this.config.connectionConfig.timezone);
};
Pool.prototype.escapeId = function escapeId(value) {
return mysql.escapeId(value, false);
};
function spliceConnection(array, connection) {
var index;
if ((index = array.indexOf(connection)) !== -1) {
// Remove connection from all connections
array.splice(index, 1);
}
}

View File

@ -0,0 +1,288 @@
var Pool = require('./Pool');
var PoolConfig = require('./PoolConfig');
var PoolNamespace = require('./PoolNamespace');
var PoolSelector = require('./PoolSelector');
var Util = require('util');
var EventEmitter = require('events').EventEmitter;
module.exports = PoolCluster;
/**
* PoolCluster
* @constructor
* @param {object} [config] The pool cluster configuration
* @public
*/
function PoolCluster(config) {
EventEmitter.call(this);
config = config || {};
this._canRetry = typeof config.canRetry === 'undefined' ? true : config.canRetry;
this._defaultSelector = config.defaultSelector || 'RR';
this._removeNodeErrorCount = config.removeNodeErrorCount || 5;
this._restoreNodeTimeout = config.restoreNodeTimeout || 0;
this._closed = false;
this._findCaches = Object.create(null);
this._lastId = 0;
this._namespaces = Object.create(null);
this._nodes = Object.create(null);
}
Util.inherits(PoolCluster, EventEmitter);
PoolCluster.prototype.add = function add(id, config) {
if (this._closed) {
throw new Error('PoolCluster is closed.');
}
var nodeId = typeof id === 'object'
? 'CLUSTER::' + (++this._lastId)
: String(id);
if (this._nodes[nodeId] !== undefined) {
throw new Error('Node ID "' + nodeId + '" is already defined in PoolCluster.');
}
var poolConfig = typeof id !== 'object'
? new PoolConfig(config)
: new PoolConfig(id);
this._nodes[nodeId] = {
id : nodeId,
errorCount : 0,
pool : new Pool({config: poolConfig}),
_offlineUntil : 0
};
this._clearFindCaches();
};
PoolCluster.prototype.end = function end(callback) {
var cb = callback !== undefined
? callback
: _cb;
if (typeof cb !== 'function') {
throw TypeError('callback argument must be a function');
}
if (this._closed) {
process.nextTick(cb);
return;
}
this._closed = true;
var calledBack = false;
var nodeIds = Object.keys(this._nodes);
var waitingClose = 0;
function onEnd(err) {
if (!calledBack && (err || --waitingClose <= 0)) {
calledBack = true;
cb(err);
}
}
for (var i = 0; i < nodeIds.length; i++) {
var nodeId = nodeIds[i];
var node = this._nodes[nodeId];
waitingClose++;
node.pool.end(onEnd);
}
if (waitingClose === 0) {
process.nextTick(onEnd);
}
};
PoolCluster.prototype.of = function(pattern, selector) {
pattern = pattern || '*';
selector = selector || this._defaultSelector;
selector = selector.toUpperCase();
if (typeof PoolSelector[selector] === 'undefined') {
selector = this._defaultSelector;
}
var key = pattern + selector;
if (typeof this._namespaces[key] === 'undefined') {
this._namespaces[key] = new PoolNamespace(this, pattern, selector);
}
return this._namespaces[key];
};
PoolCluster.prototype.remove = function remove(pattern) {
var foundNodeIds = this._findNodeIds(pattern, true);
for (var i = 0; i < foundNodeIds.length; i++) {
var node = this._getNode(foundNodeIds[i]);
if (node) {
this._removeNode(node);
}
}
};
PoolCluster.prototype.getConnection = function(pattern, selector, cb) {
var namespace;
if (typeof pattern === 'function') {
cb = pattern;
namespace = this.of();
} else {
if (typeof selector === 'function') {
cb = selector;
selector = this._defaultSelector;
}
namespace = this.of(pattern, selector);
}
namespace.getConnection(cb);
};
PoolCluster.prototype._clearFindCaches = function _clearFindCaches() {
this._findCaches = Object.create(null);
};
PoolCluster.prototype._decreaseErrorCount = function _decreaseErrorCount(node) {
var errorCount = node.errorCount;
if (errorCount > this._removeNodeErrorCount) {
errorCount = this._removeNodeErrorCount;
}
if (errorCount < 1) {
errorCount = 1;
}
node.errorCount = errorCount - 1;
if (node._offlineUntil) {
node._offlineUntil = 0;
this.emit('online', node.id);
}
};
PoolCluster.prototype._findNodeIds = function _findNodeIds(pattern, includeOffline) {
var currentTime = 0;
var foundNodeIds = this._findCaches[pattern];
if (foundNodeIds === undefined) {
var expression = patternRegExp(pattern);
var nodeIds = Object.keys(this._nodes);
foundNodeIds = nodeIds.filter(function (id) {
return id.match(expression);
});
this._findCaches[pattern] = foundNodeIds;
}
if (includeOffline) {
return foundNodeIds;
}
return foundNodeIds.filter(function (nodeId) {
var node = this._getNode(nodeId);
if (!node._offlineUntil) {
return true;
}
if (!currentTime) {
currentTime = getMonotonicMilliseconds();
}
return node._offlineUntil <= currentTime;
}, this);
};
PoolCluster.prototype._getNode = function _getNode(id) {
return this._nodes[id] || null;
};
PoolCluster.prototype._increaseErrorCount = function _increaseErrorCount(node) {
var errorCount = ++node.errorCount;
if (this._removeNodeErrorCount > errorCount) {
return;
}
if (this._restoreNodeTimeout > 0) {
node._offlineUntil = getMonotonicMilliseconds() + this._restoreNodeTimeout;
this.emit('offline', node.id);
return;
}
this._removeNode(node);
this.emit('remove', node.id);
};
PoolCluster.prototype._getConnection = function(node, cb) {
var self = this;
node.pool.getConnection(function (err, connection) {
if (err) {
self._increaseErrorCount(node);
cb(err);
return;
} else {
self._decreaseErrorCount(node);
}
connection._clusterId = node.id;
cb(null, connection);
});
};
PoolCluster.prototype._removeNode = function _removeNode(node) {
delete this._nodes[node.id];
this._clearFindCaches();
node.pool.end(_noop);
};
function getMonotonicMilliseconds() {
var ms;
if (typeof process.hrtime === 'function') {
ms = process.hrtime();
ms = ms[0] * 1e3 + ms[1] * 1e-6;
} else {
ms = process.uptime() * 1000;
}
return Math.floor(ms);
}
function isRegExp(val) {
return typeof val === 'object'
&& Object.prototype.toString.call(val) === '[object RegExp]';
}
function patternRegExp(pattern) {
if (isRegExp(pattern)) {
return pattern;
}
var source = pattern
.replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1')
.replace(/\*/g, '.*');
return new RegExp('^' + source + '$');
}
function _cb(err) {
if (err) {
throw err;
}
}
function _noop() {}

View File

@ -0,0 +1,32 @@
var ConnectionConfig = require('./ConnectionConfig');
module.exports = PoolConfig;
function PoolConfig(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.acquireTimeout = (options.acquireTimeout === undefined)
? 10 * 1000
: Number(options.acquireTimeout);
this.connectionConfig = new ConnectionConfig(options);
this.waitForConnections = (options.waitForConnections === undefined)
? true
: Boolean(options.waitForConnections);
this.connectionLimit = (options.connectionLimit === undefined)
? 10
: Number(options.connectionLimit);
this.queueLimit = (options.queueLimit === undefined)
? 0
: Number(options.queueLimit);
}
PoolConfig.prototype.newConnectionConfig = function newConnectionConfig() {
var connectionConfig = new ConnectionConfig(this.connectionConfig);
connectionConfig.clientFlags = this.connectionConfig.clientFlags;
connectionConfig.maxPacketSize = this.connectionConfig.maxPacketSize;
return connectionConfig;
};

View File

@ -0,0 +1,65 @@
var inherits = require('util').inherits;
var Connection = require('./Connection');
var Events = require('events');
module.exports = PoolConnection;
inherits(PoolConnection, Connection);
function PoolConnection(pool, options) {
Connection.call(this, options);
this._pool = pool;
// Bind connection to pool domain
if (Events.usingDomains) {
this.domain = pool.domain;
}
// When a fatal error occurs the connection's protocol ends, which will cause
// the connection to end as well, thus we only need to watch for the end event
// and we will be notified of disconnects.
this.on('end', this._removeFromPool);
this.on('error', function (err) {
if (err.fatal) {
this._removeFromPool();
}
});
}
PoolConnection.prototype.release = function release() {
var pool = this._pool;
if (!pool || pool._closed) {
return undefined;
}
return pool.releaseConnection(this);
};
// TODO: Remove this when we are removing PoolConnection#end
PoolConnection.prototype._realEnd = Connection.prototype.end;
PoolConnection.prototype.end = function () {
console.warn(
'Calling conn.end() to release a pooled connection is ' +
'deprecated. In next version calling conn.end() will be ' +
'restored to default conn.end() behavior. Use ' +
'conn.release() instead.'
);
this.release();
};
PoolConnection.prototype.destroy = function () {
Connection.prototype.destroy.apply(this, arguments);
this._removeFromPool(this);
};
PoolConnection.prototype._removeFromPool = function _removeFromPool() {
if (!this._pool || this._pool._closed) {
return;
}
var pool = this._pool;
this._pool = null;
pool._purgeConnection(this);
};

View File

@ -0,0 +1,136 @@
var Connection = require('./Connection');
var PoolSelector = require('./PoolSelector');
module.exports = PoolNamespace;
/**
* PoolNamespace
* @constructor
* @param {PoolCluster} cluster The parent cluster for the namespace
* @param {string} pattern The selection pattern to use
* @param {string} selector The selector name to use
* @public
*/
function PoolNamespace(cluster, pattern, selector) {
this._cluster = cluster;
this._pattern = pattern;
this._selector = new PoolSelector[selector]();
}
PoolNamespace.prototype.getConnection = function(cb) {
var clusterNode = this._getClusterNode();
var cluster = this._cluster;
var namespace = this;
if (clusterNode === null) {
var err = null;
if (this._cluster._findNodeIds(this._pattern, true).length !== 0) {
err = new Error('Pool does not have online node.');
err.code = 'POOL_NONEONLINE';
} else {
err = new Error('Pool does not exist.');
err.code = 'POOL_NOEXIST';
}
cb(err);
return;
}
cluster._getConnection(clusterNode, function(err, connection) {
var retry = err && cluster._canRetry
&& cluster._findNodeIds(namespace._pattern).length !== 0;
if (retry) {
namespace.getConnection(cb);
return;
}
if (err) {
cb(err);
return;
}
cb(null, connection);
});
};
PoolNamespace.prototype.query = function (sql, values, cb) {
var cluster = this._cluster;
var clusterNode = this._getClusterNode();
var query = Connection.createQuery(sql, values, cb);
var namespace = this;
if (clusterNode === null) {
var err = null;
if (this._cluster._findNodeIds(this._pattern, true).length !== 0) {
err = new Error('Pool does not have online node.');
err.code = 'POOL_NONEONLINE';
} else {
err = new Error('Pool does not exist.');
err.code = 'POOL_NOEXIST';
}
process.nextTick(function () {
query.on('error', function () {});
query.end(err);
});
return query;
}
if (!(typeof sql === 'object' && 'typeCast' in sql)) {
query.typeCast = clusterNode.pool.config.connectionConfig.typeCast;
}
if (clusterNode.pool.config.connectionConfig.trace) {
// Long stack trace support
query._callSite = new Error();
}
cluster._getConnection(clusterNode, function (err, conn) {
var retry = err && cluster._canRetry
&& cluster._findNodeIds(namespace._pattern).length !== 0;
if (retry) {
namespace.query(query);
return;
}
if (err) {
query.on('error', function () {});
query.end(err);
return;
}
// Release connection based off event
query.once('end', function() {
conn.release();
});
conn.query(query);
});
return query;
};
PoolNamespace.prototype._getClusterNode = function _getClusterNode() {
var foundNodeIds = this._cluster._findNodeIds(this._pattern);
var nodeId;
switch (foundNodeIds.length) {
case 0:
nodeId = null;
break;
case 1:
nodeId = foundNodeIds[0];
break;
default:
nodeId = this._selector(foundNodeIds);
break;
}
return nodeId !== null
? this._cluster._getNode(nodeId)
: null;
};

View File

@ -0,0 +1,31 @@
/**
* PoolSelector
*/
var PoolSelector = module.exports = {};
PoolSelector.RR = function PoolSelectorRoundRobin() {
var index = 0;
return function(clusterIds) {
if (index >= clusterIds.length) {
index = 0;
}
var clusterId = clusterIds[index++];
return clusterId;
};
};
PoolSelector.RANDOM = function PoolSelectorRandom() {
return function(clusterIds) {
return clusterIds[Math.floor(Math.random() * clusterIds.length)];
};
};
PoolSelector.ORDER = function PoolSelectorOrder() {
return function(clusterIds) {
return clusterIds[0];
};
};

View File

@ -0,0 +1,168 @@
var Buffer = require('safe-buffer').Buffer;
var Crypto = require('crypto');
var Auth = exports;
function auth(name, data, options) {
options = options || {};
switch (name) {
case 'mysql_native_password':
return Auth.token(options.password, data.slice(0, 20));
default:
return undefined;
}
}
Auth.auth = auth;
function sha1(msg) {
var hash = Crypto.createHash('sha1');
hash.update(msg, 'binary');
return hash.digest('binary');
}
Auth.sha1 = sha1;
function xor(a, b) {
a = Buffer.from(a, 'binary');
b = Buffer.from(b, 'binary');
var result = Buffer.allocUnsafe(a.length);
for (var i = 0; i < a.length; i++) {
result[i] = (a[i] ^ b[i]);
}
return result;
}
Auth.xor = xor;
Auth.token = function(password, scramble) {
if (!password) {
return Buffer.alloc(0);
}
// password must be in binary format, not utf8
var stage1 = sha1((Buffer.from(password, 'utf8')).toString('binary'));
var stage2 = sha1(stage1);
var stage3 = sha1(scramble.toString('binary') + stage2);
return xor(stage3, stage1);
};
// This is a port of sql/password.c:hash_password which needs to be used for
// pre-4.1 passwords.
Auth.hashPassword = function(password) {
var nr = [0x5030, 0x5735];
var add = 7;
var nr2 = [0x1234, 0x5671];
var result = Buffer.alloc(8);
if (typeof password === 'string'){
password = Buffer.from(password);
}
for (var i = 0; i < password.length; i++) {
var c = password[i];
if (c === 32 || c === 9) {
// skip space in password
continue;
}
// nr^= (((nr & 63)+add)*c)+ (nr << 8);
// nr = xor(nr, add(mul(add(and(nr, 63), add), c), shl(nr, 8)))
nr = this.xor32(nr, this.add32(this.mul32(this.add32(this.and32(nr, [0, 63]), [0, add]), [0, c]), this.shl32(nr, 8)));
// nr2+=(nr2 << 8) ^ nr;
// nr2 = add(nr2, xor(shl(nr2, 8), nr))
nr2 = this.add32(nr2, this.xor32(this.shl32(nr2, 8), nr));
// add+=tmp;
add += c;
}
this.int31Write(result, nr, 0);
this.int31Write(result, nr2, 4);
return result;
};
Auth.randomInit = function(seed1, seed2) {
return {
max_value : 0x3FFFFFFF,
max_value_dbl : 0x3FFFFFFF,
seed1 : seed1 % 0x3FFFFFFF,
seed2 : seed2 % 0x3FFFFFFF
};
};
Auth.myRnd = function(r){
r.seed1 = (r.seed1 * 3 + r.seed2) % r.max_value;
r.seed2 = (r.seed1 + r.seed2 + 33) % r.max_value;
return r.seed1 / r.max_value_dbl;
};
Auth.scramble323 = function(message, password) {
if (!password) {
return Buffer.alloc(0);
}
var to = Buffer.allocUnsafe(8);
var hashPass = this.hashPassword(password);
var hashMessage = this.hashPassword(message.slice(0, 8));
var seed1 = this.int32Read(hashPass, 0) ^ this.int32Read(hashMessage, 0);
var seed2 = this.int32Read(hashPass, 4) ^ this.int32Read(hashMessage, 4);
var r = this.randomInit(seed1, seed2);
for (var i = 0; i < 8; i++){
to[i] = Math.floor(this.myRnd(r) * 31) + 64;
}
var extra = (Math.floor(this.myRnd(r) * 31));
for (var i = 0; i < 8; i++){
to[i] ^= extra;
}
return to;
};
Auth.xor32 = function(a, b){
return [a[0] ^ b[0], a[1] ^ b[1]];
};
Auth.add32 = function(a, b){
var w1 = a[1] + b[1];
var w2 = a[0] + b[0] + ((w1 & 0xFFFF0000) >> 16);
return [w2 & 0xFFFF, w1 & 0xFFFF];
};
Auth.mul32 = function(a, b){
// based on this example of multiplying 32b ints using 16b
// http://www.dsprelated.com/showmessage/89790/1.php
var w1 = a[1] * b[1];
var w2 = (((a[1] * b[1]) >> 16) & 0xFFFF) + ((a[0] * b[1]) & 0xFFFF) + (a[1] * b[0] & 0xFFFF);
return [w2 & 0xFFFF, w1 & 0xFFFF];
};
Auth.and32 = function(a, b){
return [a[0] & b[0], a[1] & b[1]];
};
Auth.shl32 = function(a, b){
// assume b is 16 or less
var w1 = a[1] << b;
var w2 = (a[0] << b) | ((w1 & 0xFFFF0000) >> 16);
return [w2 & 0xFFFF, w1 & 0xFFFF];
};
Auth.int31Write = function(buffer, number, offset) {
buffer[offset] = (number[0] >> 8) & 0x7F;
buffer[offset + 1] = (number[0]) & 0xFF;
buffer[offset + 2] = (number[1] >> 8) & 0xFF;
buffer[offset + 3] = (number[1]) & 0xFF;
};
Auth.int32Read = function(buffer, offset){
return (buffer[offset] << 24)
+ (buffer[offset + 1] << 16)
+ (buffer[offset + 2] << 8)
+ (buffer[offset + 3]);
};

View File

@ -0,0 +1,25 @@
module.exports = BufferList;
function BufferList() {
this.bufs = [];
this.size = 0;
}
BufferList.prototype.shift = function shift() {
var buf = this.bufs.shift();
if (buf) {
this.size -= buf.length;
}
return buf;
};
BufferList.prototype.push = function push(buf) {
if (!buf || !buf.length) {
return;
}
this.bufs.push(buf);
this.size += buf.length;
};

View File

@ -0,0 +1,5 @@
module.exports = PacketHeader;
function PacketHeader(length, number) {
this.length = length;
this.number = number;
}

View File

@ -0,0 +1,211 @@
var BIT_16 = Math.pow(2, 16);
var BIT_24 = Math.pow(2, 24);
var BUFFER_ALLOC_SIZE = Math.pow(2, 8);
// The maximum precision JS Numbers can hold precisely
// Don't panic: Good enough to represent byte values up to 8192 TB
var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);
var MAX_PACKET_LENGTH = Math.pow(2, 24) - 1;
var Buffer = require('safe-buffer').Buffer;
module.exports = PacketWriter;
function PacketWriter() {
this._buffer = null;
this._offset = 0;
}
PacketWriter.prototype.toBuffer = function toBuffer(parser) {
if (!this._buffer) {
this._buffer = Buffer.alloc(0);
this._offset = 0;
}
var buffer = this._buffer;
var length = this._offset;
var packets = Math.floor(length / MAX_PACKET_LENGTH) + 1;
this._buffer = Buffer.allocUnsafe(length + packets * 4);
this._offset = 0;
for (var packet = 0; packet < packets; packet++) {
var isLast = (packet + 1 === packets);
var packetLength = (isLast)
? length % MAX_PACKET_LENGTH
: MAX_PACKET_LENGTH;
var packetNumber = parser.incrementPacketNumber();
this.writeUnsignedNumber(3, packetLength);
this.writeUnsignedNumber(1, packetNumber);
var start = packet * MAX_PACKET_LENGTH;
var end = start + packetLength;
this.writeBuffer(buffer.slice(start, end));
}
return this._buffer;
};
PacketWriter.prototype.writeUnsignedNumber = function(bytes, value) {
this._allocate(bytes);
for (var i = 0; i < bytes; i++) {
this._buffer[this._offset++] = (value >> (i * 8)) & 0xff;
}
};
PacketWriter.prototype.writeFiller = function(bytes) {
this._allocate(bytes);
for (var i = 0; i < bytes; i++) {
this._buffer[this._offset++] = 0x00;
}
};
PacketWriter.prototype.writeNullTerminatedString = function(value, encoding) {
// Typecast undefined into '' and numbers into strings
value = value || '';
value = value + '';
var bytes = Buffer.byteLength(value, encoding || 'utf-8') + 1;
this._allocate(bytes);
this._buffer.write(value, this._offset, encoding);
this._buffer[this._offset + bytes - 1] = 0x00;
this._offset += bytes;
};
PacketWriter.prototype.writeString = function(value) {
// Typecast undefined into '' and numbers into strings
value = value || '';
value = value + '';
var bytes = Buffer.byteLength(value, 'utf-8');
this._allocate(bytes);
this._buffer.write(value, this._offset, 'utf-8');
this._offset += bytes;
};
PacketWriter.prototype.writeBuffer = function(value) {
var bytes = value.length;
this._allocate(bytes);
value.copy(this._buffer, this._offset);
this._offset += bytes;
};
PacketWriter.prototype.writeLengthCodedNumber = function(value) {
if (value === null) {
this._allocate(1);
this._buffer[this._offset++] = 251;
return;
}
if (value <= 250) {
this._allocate(1);
this._buffer[this._offset++] = value;
return;
}
if (value > IEEE_754_BINARY_64_PRECISION) {
throw new Error(
'writeLengthCodedNumber: JS precision range exceeded, your ' +
'number is > 53 bit: "' + value + '"'
);
}
if (value < BIT_16) {
this._allocate(3);
this._buffer[this._offset++] = 252;
} else if (value < BIT_24) {
this._allocate(4);
this._buffer[this._offset++] = 253;
} else {
this._allocate(9);
this._buffer[this._offset++] = 254;
}
// 16 Bit
this._buffer[this._offset++] = value & 0xff;
this._buffer[this._offset++] = (value >> 8) & 0xff;
if (value < BIT_16) {
return;
}
// 24 Bit
this._buffer[this._offset++] = (value >> 16) & 0xff;
if (value < BIT_24) {
return;
}
this._buffer[this._offset++] = (value >> 24) & 0xff;
// Hack: Get the most significant 32 bit (JS bitwise operators are 32 bit)
value = value.toString(2);
value = value.substr(0, value.length - 32);
value = parseInt(value, 2);
this._buffer[this._offset++] = value & 0xff;
this._buffer[this._offset++] = (value >> 8) & 0xff;
this._buffer[this._offset++] = (value >> 16) & 0xff;
// Set last byte to 0, as we can only support 53 bits in JS (see above)
this._buffer[this._offset++] = 0;
};
PacketWriter.prototype.writeLengthCodedBuffer = function(value) {
var bytes = value.length;
this.writeLengthCodedNumber(bytes);
this.writeBuffer(value);
};
PacketWriter.prototype.writeNullTerminatedBuffer = function(value) {
this.writeBuffer(value);
this.writeFiller(1); // 0x00 terminator
};
PacketWriter.prototype.writeLengthCodedString = function(value) {
if (value === null) {
this.writeLengthCodedNumber(null);
return;
}
value = (value === undefined)
? ''
: String(value);
var bytes = Buffer.byteLength(value, 'utf-8');
this.writeLengthCodedNumber(bytes);
if (!bytes) {
return;
}
this._allocate(bytes);
this._buffer.write(value, this._offset, 'utf-8');
this._offset += bytes;
};
PacketWriter.prototype._allocate = function _allocate(bytes) {
if (!this._buffer) {
this._buffer = Buffer.alloc(Math.max(BUFFER_ALLOC_SIZE, bytes));
this._offset = 0;
return;
}
var bytesRemaining = this._buffer.length - this._offset;
if (bytesRemaining >= bytes) {
return;
}
var newSize = this._buffer.length + Math.max(BUFFER_ALLOC_SIZE, bytes);
var oldBuffer = this._buffer;
this._buffer = Buffer.alloc(newSize);
oldBuffer.copy(this._buffer);
};

View File

@ -0,0 +1,491 @@
var PacketHeader = require('./PacketHeader');
var BigNumber = require('bignumber.js');
var Buffer = require('safe-buffer').Buffer;
var BufferList = require('./BufferList');
var MAX_PACKET_LENGTH = Math.pow(2, 24) - 1;
var MUL_32BIT = Math.pow(2, 32);
var PACKET_HEADER_LENGTH = 4;
module.exports = Parser;
function Parser(options) {
options = options || {};
this._supportBigNumbers = options.config && options.config.supportBigNumbers;
this._buffer = Buffer.alloc(0);
this._nextBuffers = new BufferList();
this._longPacketBuffers = new BufferList();
this._offset = 0;
this._packetEnd = null;
this._packetHeader = null;
this._packetOffset = null;
this._onError = options.onError || function(err) { throw err; };
this._onPacket = options.onPacket || function() {};
this._nextPacketNumber = 0;
this._encoding = 'utf-8';
this._paused = false;
}
Parser.prototype.write = function write(chunk) {
this._nextBuffers.push(chunk);
while (!this._paused) {
var packetHeader = this._tryReadPacketHeader();
if (!packetHeader) {
break;
}
if (!this._combineNextBuffers(packetHeader.length)) {
break;
}
this._parsePacket(packetHeader);
}
};
Parser.prototype.append = function append(chunk) {
if (!chunk || chunk.length === 0) {
return;
}
// Calculate slice ranges
var sliceEnd = this._buffer.length;
var sliceStart = this._packetOffset === null
? this._offset
: this._packetOffset;
var sliceLength = sliceEnd - sliceStart;
// Get chunk data
var buffer = null;
var chunks = !(chunk instanceof Array || Array.isArray(chunk)) ? [chunk] : chunk;
var length = 0;
var offset = 0;
for (var i = 0; i < chunks.length; i++) {
length += chunks[i].length;
}
if (sliceLength !== 0) {
// Create a new Buffer
buffer = Buffer.allocUnsafe(sliceLength + length);
offset = 0;
// Copy data slice
offset += this._buffer.copy(buffer, 0, sliceStart, sliceEnd);
// Copy chunks
for (var i = 0; i < chunks.length; i++) {
offset += chunks[i].copy(buffer, offset);
}
} else if (chunks.length > 1) {
// Create a new Buffer
buffer = Buffer.allocUnsafe(length);
offset = 0;
// Copy chunks
for (var i = 0; i < chunks.length; i++) {
offset += chunks[i].copy(buffer, offset);
}
} else {
// Buffer is the only chunk
buffer = chunks[0];
}
// Adjust data-tracking pointers
this._buffer = buffer;
this._offset = this._offset - sliceStart;
this._packetEnd = this._packetEnd !== null
? this._packetEnd - sliceStart
: null;
this._packetOffset = this._packetOffset !== null
? this._packetOffset - sliceStart
: null;
};
Parser.prototype.pause = function() {
this._paused = true;
};
Parser.prototype.resume = function() {
this._paused = false;
// nextTick() to avoid entering write() multiple times within the same stack
// which would cause problems as write manipulates the state of the object.
process.nextTick(this.write.bind(this));
};
Parser.prototype.peak = function peak(offset) {
return this._buffer[this._offset + (offset >>> 0)];
};
Parser.prototype.parseUnsignedNumber = function parseUnsignedNumber(bytes) {
if (bytes === 1) {
return this._buffer[this._offset++];
}
var buffer = this._buffer;
var offset = this._offset + bytes - 1;
var value = 0;
if (bytes > 4) {
var err = new Error('parseUnsignedNumber: Supports only up to 4 bytes');
err.offset = (this._offset - this._packetOffset - 1);
err.code = 'PARSER_UNSIGNED_TOO_LONG';
throw err;
}
while (offset >= this._offset) {
value = ((value << 8) | buffer[offset]) >>> 0;
offset--;
}
this._offset += bytes;
return value;
};
Parser.prototype.parseLengthCodedString = function() {
var length = this.parseLengthCodedNumber();
if (length === null) {
return null;
}
return this.parseString(length);
};
Parser.prototype.parseLengthCodedBuffer = function() {
var length = this.parseLengthCodedNumber();
if (length === null) {
return null;
}
return this.parseBuffer(length);
};
Parser.prototype.parseLengthCodedNumber = function parseLengthCodedNumber() {
if (this._offset >= this._buffer.length) {
var err = new Error('Parser: read past end');
err.offset = (this._offset - this._packetOffset);
err.code = 'PARSER_READ_PAST_END';
throw err;
}
var bits = this._buffer[this._offset++];
if (bits <= 250) {
return bits;
}
switch (bits) {
case 251:
return null;
case 252:
return this.parseUnsignedNumber(2);
case 253:
return this.parseUnsignedNumber(3);
case 254:
break;
default:
var err = new Error('Unexpected first byte' + (bits ? ': 0x' + bits.toString(16) : ''));
err.offset = (this._offset - this._packetOffset - 1);
err.code = 'PARSER_BAD_LENGTH_BYTE';
throw err;
}
var low = this.parseUnsignedNumber(4);
var high = this.parseUnsignedNumber(4);
var value;
if (high >>> 21) {
value = BigNumber(MUL_32BIT).times(high).plus(low).toString();
if (this._supportBigNumbers) {
return value;
}
var err = new Error(
'parseLengthCodedNumber: JS precision range exceeded, ' +
'number is >= 53 bit: "' + value + '"'
);
err.offset = (this._offset - this._packetOffset - 8);
err.code = 'PARSER_JS_PRECISION_RANGE_EXCEEDED';
throw err;
}
value = low + (MUL_32BIT * high);
return value;
};
Parser.prototype.parseFiller = function(length) {
return this.parseBuffer(length);
};
Parser.prototype.parseNullTerminatedBuffer = function() {
var end = this._nullByteOffset();
var value = this._buffer.slice(this._offset, end);
this._offset = end + 1;
return value;
};
Parser.prototype.parseNullTerminatedString = function() {
var end = this._nullByteOffset();
var value = this._buffer.toString(this._encoding, this._offset, end);
this._offset = end + 1;
return value;
};
Parser.prototype._nullByteOffset = function() {
var offset = this._offset;
while (this._buffer[offset] !== 0x00) {
offset++;
if (offset >= this._buffer.length) {
var err = new Error('Offset of null terminated string not found.');
err.offset = (this._offset - this._packetOffset);
err.code = 'PARSER_MISSING_NULL_BYTE';
throw err;
}
}
return offset;
};
Parser.prototype.parsePacketTerminatedBuffer = function parsePacketTerminatedBuffer() {
var length = this._packetEnd - this._offset;
return this.parseBuffer(length);
};
Parser.prototype.parsePacketTerminatedString = function() {
var length = this._packetEnd - this._offset;
return this.parseString(length);
};
Parser.prototype.parseBuffer = function(length) {
var response = Buffer.alloc(length);
this._buffer.copy(response, 0, this._offset, this._offset + length);
this._offset += length;
return response;
};
Parser.prototype.parseString = function(length) {
var offset = this._offset;
var end = offset + length;
var value = this._buffer.toString(this._encoding, offset, end);
this._offset = end;
return value;
};
Parser.prototype.parseGeometryValue = function() {
var buffer = this.parseLengthCodedBuffer();
var offset = 4;
if (buffer === null || !buffer.length) {
return null;
}
function parseGeometry() {
var result = null;
var byteOrder = buffer.readUInt8(offset); offset += 1;
var wkbType = byteOrder ? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
switch (wkbType) {
case 1: // WKBPoint
var x = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
result = {x: x, y: y};
break;
case 2: // WKBLineString
var numPoints = byteOrder ? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
result = [];
for (var i = numPoints; i > 0; i--) {
var x = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
result.push({x: x, y: y});
}
break;
case 3: // WKBPolygon
var numRings = byteOrder ? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
result = [];
for (var i = numRings; i > 0; i--) {
var numPoints = byteOrder ? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
var line = [];
for (var j = numPoints; j > 0; j--) {
var x = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder ? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
line.push({x: x, y: y});
}
result.push(line);
}
break;
case 4: // WKBMultiPoint
case 5: // WKBMultiLineString
case 6: // WKBMultiPolygon
case 7: // WKBGeometryCollection
var num = byteOrder ? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
var result = [];
for (var i = num; i > 0; i--) {
result.push(parseGeometry());
}
break;
}
return result;
}
return parseGeometry();
};
Parser.prototype.reachedPacketEnd = function() {
return this._offset === this._packetEnd;
};
Parser.prototype.incrementPacketNumber = function() {
var currentPacketNumber = this._nextPacketNumber;
this._nextPacketNumber = (this._nextPacketNumber + 1) % 256;
return currentPacketNumber;
};
Parser.prototype.resetPacketNumber = function() {
this._nextPacketNumber = 0;
};
Parser.prototype.packetLength = function packetLength() {
if (!this._packetHeader) {
return null;
}
return this._packetHeader.length + this._longPacketBuffers.size;
};
Parser.prototype._combineNextBuffers = function _combineNextBuffers(bytes) {
var length = this._buffer.length - this._offset;
if (length >= bytes) {
return true;
}
if ((length + this._nextBuffers.size) < bytes) {
return false;
}
var buffers = [];
var bytesNeeded = bytes - length;
while (bytesNeeded > 0) {
var buffer = this._nextBuffers.shift();
buffers.push(buffer);
bytesNeeded -= buffer.length;
}
this.append(buffers);
return true;
};
Parser.prototype._combineLongPacketBuffers = function _combineLongPacketBuffers() {
if (!this._longPacketBuffers.size) {
return;
}
// Calculate bytes
var remainingBytes = this._buffer.length - this._offset;
var trailingPacketBytes = this._buffer.length - this._packetEnd;
// Create buffer
var buf = null;
var buffer = Buffer.allocUnsafe(remainingBytes + this._longPacketBuffers.size);
var offset = 0;
// Copy long buffers
while ((buf = this._longPacketBuffers.shift())) {
offset += buf.copy(buffer, offset);
}
// Copy remaining bytes
this._buffer.copy(buffer, offset, this._offset);
this._buffer = buffer;
this._offset = 0;
this._packetEnd = this._buffer.length - trailingPacketBytes;
this._packetOffset = 0;
};
Parser.prototype._parsePacket = function _parsePacket(packetHeader) {
this._packetEnd = this._offset + packetHeader.length;
this._packetOffset = this._offset;
if (packetHeader.length === MAX_PACKET_LENGTH) {
this._longPacketBuffers.push(this._buffer.slice(this._packetOffset, this._packetEnd));
this._advanceToNextPacket();
return;
}
this._combineLongPacketBuffers();
var hadException = true;
try {
this._onPacket(packetHeader);
hadException = false;
} catch (err) {
if (!err || typeof err.code !== 'string' || err.code.substr(0, 7) !== 'PARSER_') {
throw err; // Rethrow non-MySQL errors
}
// Pass down parser errors
this._onError(err);
hadException = false;
} finally {
this._advanceToNextPacket();
// If there was an exception, the parser while loop will be broken out
// of after the finally block. So schedule a blank write to re-enter it
// to continue parsing any bytes that may already have been received.
if (hadException) {
process.nextTick(this.write.bind(this));
}
}
};
Parser.prototype._tryReadPacketHeader = function _tryReadPacketHeader() {
if (this._packetHeader) {
return this._packetHeader;
}
if (!this._combineNextBuffers(PACKET_HEADER_LENGTH)) {
return null;
}
this._packetHeader = new PacketHeader(
this.parseUnsignedNumber(3),
this.parseUnsignedNumber(1)
);
if (this._packetHeader.number !== this._nextPacketNumber) {
var err = new Error(
'Packets out of order. Got: ' + this._packetHeader.number + ' ' +
'Expected: ' + this._nextPacketNumber
);
err.code = 'PROTOCOL_PACKETS_OUT_OF_ORDER';
err.fatal = true;
this._onError(err);
}
this.incrementPacketNumber();
return this._packetHeader;
};
Parser.prototype._advanceToNextPacket = function() {
this._offset = this._packetEnd;
this._packetHeader = null;
this._packetEnd = null;
this._packetOffset = null;
};

View File

@ -0,0 +1,463 @@
var Parser = require('./Parser');
var Sequences = require('./sequences');
var Packets = require('./packets');
var Stream = require('stream').Stream;
var Util = require('util');
var PacketWriter = require('./PacketWriter');
module.exports = Protocol;
Util.inherits(Protocol, Stream);
function Protocol(options) {
Stream.call(this);
options = options || {};
this.readable = true;
this.writable = true;
this._config = options.config || {};
this._connection = options.connection;
this._callback = null;
this._fatalError = null;
this._quitSequence = null;
this._handshake = false;
this._handshaked = false;
this._ended = false;
this._destroyed = false;
this._queue = [];
this._handshakeInitializationPacket = null;
this._parser = new Parser({
onError : this.handleParserError.bind(this),
onPacket : this._parsePacket.bind(this),
config : this._config
});
}
Protocol.prototype.write = function(buffer) {
this._parser.write(buffer);
return true;
};
Protocol.prototype.handshake = function handshake(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
options.config = this._config;
var sequence = this._enqueue(new Sequences.Handshake(options, callback));
this._handshake = true;
return sequence;
};
Protocol.prototype.query = function query(options, callback) {
return this._enqueue(new Sequences.Query(options, callback));
};
Protocol.prototype.changeUser = function changeUser(options, callback) {
return this._enqueue(new Sequences.ChangeUser(options, callback));
};
Protocol.prototype.ping = function ping(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
return this._enqueue(new Sequences.Ping(options, callback));
};
Protocol.prototype.stats = function stats(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
return this._enqueue(new Sequences.Statistics(options, callback));
};
Protocol.prototype.quit = function quit(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
var self = this;
var sequence = this._enqueue(new Sequences.Quit(options, callback));
sequence.on('end', function () {
self.end();
});
return this._quitSequence = sequence;
};
Protocol.prototype.end = function() {
if (this._ended) {
return;
}
this._ended = true;
if (this._quitSequence && (this._quitSequence._ended || this._queue[0] === this._quitSequence)) {
this._quitSequence.end();
this.emit('end');
return;
}
var err = new Error('Connection lost: The server closed the connection.');
err.fatal = true;
err.code = 'PROTOCOL_CONNECTION_LOST';
this._delegateError(err);
};
Protocol.prototype.pause = function() {
this._parser.pause();
// Since there is a file stream in query, we must transmit pause/resume event to current sequence.
var seq = this._queue[0];
if (seq && seq.emit) {
seq.emit('pause');
}
};
Protocol.prototype.resume = function() {
this._parser.resume();
// Since there is a file stream in query, we must transmit pause/resume event to current sequence.
var seq = this._queue[0];
if (seq && seq.emit) {
seq.emit('resume');
}
};
Protocol.prototype._enqueue = function(sequence) {
if (!this._validateEnqueue(sequence)) {
return sequence;
}
if (this._config.trace) {
// Long stack trace support
sequence._callSite = sequence._callSite || new Error();
}
this._queue.push(sequence);
this.emit('enqueue', sequence);
var self = this;
sequence
.on('error', function(err) {
self._delegateError(err, sequence);
})
.on('packet', function(packet) {
sequence._timer.active();
self._emitPacket(packet);
})
.on('timeout', function() {
var err = new Error(sequence.constructor.name + ' inactivity timeout');
err.code = 'PROTOCOL_SEQUENCE_TIMEOUT';
err.fatal = true;
err.timeout = sequence._timeout;
self._delegateError(err, sequence);
});
if (sequence.constructor === Sequences.Handshake) {
sequence.on('start-tls', function () {
sequence._timer.active();
self._connection._startTLS(function(err) {
if (err) {
// SSL negotiation error are fatal
err.code = 'HANDSHAKE_SSL_ERROR';
err.fatal = true;
sequence.end(err);
return;
}
sequence._timer.active();
sequence._tlsUpgradeCompleteHandler();
});
});
sequence.on('end', function () {
self._handshaked = true;
if (!self._fatalError) {
self.emit('handshake', self._handshakeInitializationPacket);
}
});
}
sequence.on('end', function () {
self._dequeue(sequence);
});
if (this._queue.length === 1) {
this._parser.resetPacketNumber();
this._startSequence(sequence);
}
return sequence;
};
Protocol.prototype._validateEnqueue = function _validateEnqueue(sequence) {
var err;
var prefix = 'Cannot enqueue ' + sequence.constructor.name;
if (this._fatalError) {
err = new Error(prefix + ' after fatal error.');
err.code = 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR';
} else if (this._quitSequence) {
err = new Error(prefix + ' after invoking quit.');
err.code = 'PROTOCOL_ENQUEUE_AFTER_QUIT';
} else if (this._destroyed) {
err = new Error(prefix + ' after being destroyed.');
err.code = 'PROTOCOL_ENQUEUE_AFTER_DESTROY';
} else if ((this._handshake || this._handshaked) && sequence.constructor === Sequences.Handshake) {
err = new Error(prefix + ' after already enqueuing a Handshake.');
err.code = 'PROTOCOL_ENQUEUE_HANDSHAKE_TWICE';
} else {
return true;
}
var self = this;
err.fatal = false;
// add error handler
sequence.on('error', function (err) {
self._delegateError(err, sequence);
});
process.nextTick(function () {
sequence.end(err);
});
return false;
};
Protocol.prototype._parsePacket = function() {
var sequence = this._queue[0];
if (!sequence) {
var err = new Error('Received packet with no active sequence.');
err.code = 'PROTOCOL_STRAY_PACKET';
err.fatal = true;
this._delegateError(err);
return;
}
var Packet = this._determinePacket(sequence);
var packet = new Packet({protocol41: this._config.protocol41});
var packetName = Packet.name;
// Special case: Faster dispatch, and parsing done inside sequence
if (Packet === Packets.RowDataPacket) {
sequence.RowDataPacket(packet, this._parser, this._connection);
if (this._config.debug) {
this._debugPacket(true, packet);
}
return;
}
if (this._config.debug) {
this._parsePacketDebug(packet);
} else {
packet.parse(this._parser);
}
if (Packet === Packets.HandshakeInitializationPacket) {
this._handshakeInitializationPacket = packet;
this.emit('initialize', packet);
}
sequence._timer.active();
if (!sequence[packetName]) {
var err = new Error('Received packet in the wrong sequence.');
err.code = 'PROTOCOL_INCORRECT_PACKET_SEQUENCE';
err.fatal = true;
this._delegateError(err);
return;
}
sequence[packetName](packet);
};
Protocol.prototype._parsePacketDebug = function _parsePacketDebug(packet) {
try {
packet.parse(this._parser);
} finally {
this._debugPacket(true, packet);
}
};
Protocol.prototype._emitPacket = function(packet) {
var packetWriter = new PacketWriter();
packet.write(packetWriter);
this.emit('data', packetWriter.toBuffer(this._parser));
if (this._config.debug) {
this._debugPacket(false, packet);
}
};
Protocol.prototype._determinePacket = function(sequence) {
var firstByte = this._parser.peak();
if (sequence.determinePacket) {
var Packet = sequence.determinePacket(firstByte, this._parser);
if (Packet) {
return Packet;
}
}
switch (firstByte) {
case 0x00: return Packets.OkPacket;
case 0xfe: return Packets.EofPacket;
case 0xff: return Packets.ErrorPacket;
}
throw new Error('Could not determine packet, firstByte = ' + firstByte);
};
Protocol.prototype._dequeue = function(sequence) {
sequence._timer.stop();
// No point in advancing the queue, we are dead
if (this._fatalError) {
return;
}
this._queue.shift();
var sequence = this._queue[0];
if (!sequence) {
this.emit('drain');
return;
}
this._parser.resetPacketNumber();
this._startSequence(sequence);
};
Protocol.prototype._startSequence = function(sequence) {
if (sequence._timeout > 0 && isFinite(sequence._timeout)) {
sequence._timer.start(sequence._timeout);
}
if (sequence.constructor === Sequences.ChangeUser) {
sequence.start(this._handshakeInitializationPacket);
} else {
sequence.start();
}
};
Protocol.prototype.handleNetworkError = function(err) {
err.fatal = true;
var sequence = this._queue[0];
if (sequence) {
sequence.end(err);
} else {
this._delegateError(err);
}
};
Protocol.prototype.handleParserError = function handleParserError(err) {
var sequence = this._queue[0];
if (sequence) {
sequence.end(err);
} else {
this._delegateError(err);
}
};
Protocol.prototype._delegateError = function(err, sequence) {
// Stop delegating errors after the first fatal error
if (this._fatalError) {
return;
}
if (err.fatal) {
this._fatalError = err;
}
if (this._shouldErrorBubbleUp(err, sequence)) {
// Can't use regular 'error' event here as that always destroys the pipe
// between socket and protocol which is not what we want (unless the
// exception was fatal).
this.emit('unhandledError', err);
} else if (err.fatal) {
// Send fatal error to all sequences in the queue
var queue = this._queue;
process.nextTick(function () {
queue.forEach(function (sequence) {
sequence.end(err);
});
queue.length = 0;
});
}
// Make sure the stream we are piping to is getting closed
if (err.fatal) {
this.emit('end', err);
}
};
Protocol.prototype._shouldErrorBubbleUp = function(err, sequence) {
if (sequence) {
if (sequence.hasErrorHandler()) {
return false;
} else if (!err.fatal) {
return true;
}
}
return (err.fatal && !this._hasPendingErrorHandlers());
};
Protocol.prototype._hasPendingErrorHandlers = function() {
return this._queue.some(function(sequence) {
return sequence.hasErrorHandler();
});
};
Protocol.prototype.destroy = function() {
this._destroyed = true;
this._parser.pause();
if (this._connection.state !== 'disconnected') {
if (!this._ended) {
this.end();
}
}
};
Protocol.prototype._debugPacket = function(incoming, packet) {
var connection = this._connection;
var direction = incoming
? '<--'
: '-->';
var packetName = packet.constructor.name;
var threadId = connection && connection.threadId !== null
? ' (' + connection.threadId + ')'
: '';
// check for debug packet restriction
if (Array.isArray(this._config.debug) && this._config.debug.indexOf(packetName) === -1) {
return;
}
var packetPayload = Util.inspect(packet).replace(/^[^{]+/, '');
console.log('%s%s %s %s\n', direction, threadId, packetName, packetPayload);
};

View File

@ -0,0 +1,7 @@
module.exports = ResultSet;
function ResultSet(resultSetHeaderPacket) {
this.resultSetHeaderPacket = resultSetHeaderPacket;
this.fieldPackets = [];
this.eofPackets = [];
this.rows = [];
}

View File

@ -0,0 +1 @@
module.exports = require('sqlstring');

View File

@ -0,0 +1,33 @@
var Timers = require('timers');
module.exports = Timer;
function Timer(object) {
this._object = object;
this._timeout = null;
}
Timer.prototype.active = function active() {
if (this._timeout) {
if (this._timeout.refresh) {
this._timeout.refresh();
} else {
Timers.active(this._timeout);
}
}
};
Timer.prototype.start = function start(msecs) {
this.stop();
this._timeout = Timers.setTimeout(this._onTimeout.bind(this), msecs);
};
Timer.prototype.stop = function stop() {
if (this._timeout) {
Timers.clearTimeout(this._timeout);
this._timeout = null;
}
};
Timer.prototype._onTimeout = function _onTimeout() {
return this._object._onTimeout();
};

View File

@ -0,0 +1,262 @@
exports.BIG5_CHINESE_CI = 1;
exports.LATIN2_CZECH_CS = 2;
exports.DEC8_SWEDISH_CI = 3;
exports.CP850_GENERAL_CI = 4;
exports.LATIN1_GERMAN1_CI = 5;
exports.HP8_ENGLISH_CI = 6;
exports.KOI8R_GENERAL_CI = 7;
exports.LATIN1_SWEDISH_CI = 8;
exports.LATIN2_GENERAL_CI = 9;
exports.SWE7_SWEDISH_CI = 10;
exports.ASCII_GENERAL_CI = 11;
exports.UJIS_JAPANESE_CI = 12;
exports.SJIS_JAPANESE_CI = 13;
exports.CP1251_BULGARIAN_CI = 14;
exports.LATIN1_DANISH_CI = 15;
exports.HEBREW_GENERAL_CI = 16;
exports.TIS620_THAI_CI = 18;
exports.EUCKR_KOREAN_CI = 19;
exports.LATIN7_ESTONIAN_CS = 20;
exports.LATIN2_HUNGARIAN_CI = 21;
exports.KOI8U_GENERAL_CI = 22;
exports.CP1251_UKRAINIAN_CI = 23;
exports.GB2312_CHINESE_CI = 24;
exports.GREEK_GENERAL_CI = 25;
exports.CP1250_GENERAL_CI = 26;
exports.LATIN2_CROATIAN_CI = 27;
exports.GBK_CHINESE_CI = 28;
exports.CP1257_LITHUANIAN_CI = 29;
exports.LATIN5_TURKISH_CI = 30;
exports.LATIN1_GERMAN2_CI = 31;
exports.ARMSCII8_GENERAL_CI = 32;
exports.UTF8_GENERAL_CI = 33;
exports.CP1250_CZECH_CS = 34;
exports.UCS2_GENERAL_CI = 35;
exports.CP866_GENERAL_CI = 36;
exports.KEYBCS2_GENERAL_CI = 37;
exports.MACCE_GENERAL_CI = 38;
exports.MACROMAN_GENERAL_CI = 39;
exports.CP852_GENERAL_CI = 40;
exports.LATIN7_GENERAL_CI = 41;
exports.LATIN7_GENERAL_CS = 42;
exports.MACCE_BIN = 43;
exports.CP1250_CROATIAN_CI = 44;
exports.UTF8MB4_GENERAL_CI = 45;
exports.UTF8MB4_BIN = 46;
exports.LATIN1_BIN = 47;
exports.LATIN1_GENERAL_CI = 48;
exports.LATIN1_GENERAL_CS = 49;
exports.CP1251_BIN = 50;
exports.CP1251_GENERAL_CI = 51;
exports.CP1251_GENERAL_CS = 52;
exports.MACROMAN_BIN = 53;
exports.UTF16_GENERAL_CI = 54;
exports.UTF16_BIN = 55;
exports.UTF16LE_GENERAL_CI = 56;
exports.CP1256_GENERAL_CI = 57;
exports.CP1257_BIN = 58;
exports.CP1257_GENERAL_CI = 59;
exports.UTF32_GENERAL_CI = 60;
exports.UTF32_BIN = 61;
exports.UTF16LE_BIN = 62;
exports.BINARY = 63;
exports.ARMSCII8_BIN = 64;
exports.ASCII_BIN = 65;
exports.CP1250_BIN = 66;
exports.CP1256_BIN = 67;
exports.CP866_BIN = 68;
exports.DEC8_BIN = 69;
exports.GREEK_BIN = 70;
exports.HEBREW_BIN = 71;
exports.HP8_BIN = 72;
exports.KEYBCS2_BIN = 73;
exports.KOI8R_BIN = 74;
exports.KOI8U_BIN = 75;
exports.LATIN2_BIN = 77;
exports.LATIN5_BIN = 78;
exports.LATIN7_BIN = 79;
exports.CP850_BIN = 80;
exports.CP852_BIN = 81;
exports.SWE7_BIN = 82;
exports.UTF8_BIN = 83;
exports.BIG5_BIN = 84;
exports.EUCKR_BIN = 85;
exports.GB2312_BIN = 86;
exports.GBK_BIN = 87;
exports.SJIS_BIN = 88;
exports.TIS620_BIN = 89;
exports.UCS2_BIN = 90;
exports.UJIS_BIN = 91;
exports.GEOSTD8_GENERAL_CI = 92;
exports.GEOSTD8_BIN = 93;
exports.LATIN1_SPANISH_CI = 94;
exports.CP932_JAPANESE_CI = 95;
exports.CP932_BIN = 96;
exports.EUCJPMS_JAPANESE_CI = 97;
exports.EUCJPMS_BIN = 98;
exports.CP1250_POLISH_CI = 99;
exports.UTF16_UNICODE_CI = 101;
exports.UTF16_ICELANDIC_CI = 102;
exports.UTF16_LATVIAN_CI = 103;
exports.UTF16_ROMANIAN_CI = 104;
exports.UTF16_SLOVENIAN_CI = 105;
exports.UTF16_POLISH_CI = 106;
exports.UTF16_ESTONIAN_CI = 107;
exports.UTF16_SPANISH_CI = 108;
exports.UTF16_SWEDISH_CI = 109;
exports.UTF16_TURKISH_CI = 110;
exports.UTF16_CZECH_CI = 111;
exports.UTF16_DANISH_CI = 112;
exports.UTF16_LITHUANIAN_CI = 113;
exports.UTF16_SLOVAK_CI = 114;
exports.UTF16_SPANISH2_CI = 115;
exports.UTF16_ROMAN_CI = 116;
exports.UTF16_PERSIAN_CI = 117;
exports.UTF16_ESPERANTO_CI = 118;
exports.UTF16_HUNGARIAN_CI = 119;
exports.UTF16_SINHALA_CI = 120;
exports.UTF16_GERMAN2_CI = 121;
exports.UTF16_CROATIAN_MYSQL561_CI = 122;
exports.UTF16_UNICODE_520_CI = 123;
exports.UTF16_VIETNAMESE_CI = 124;
exports.UCS2_UNICODE_CI = 128;
exports.UCS2_ICELANDIC_CI = 129;
exports.UCS2_LATVIAN_CI = 130;
exports.UCS2_ROMANIAN_CI = 131;
exports.UCS2_SLOVENIAN_CI = 132;
exports.UCS2_POLISH_CI = 133;
exports.UCS2_ESTONIAN_CI = 134;
exports.UCS2_SPANISH_CI = 135;
exports.UCS2_SWEDISH_CI = 136;
exports.UCS2_TURKISH_CI = 137;
exports.UCS2_CZECH_CI = 138;
exports.UCS2_DANISH_CI = 139;
exports.UCS2_LITHUANIAN_CI = 140;
exports.UCS2_SLOVAK_CI = 141;
exports.UCS2_SPANISH2_CI = 142;
exports.UCS2_ROMAN_CI = 143;
exports.UCS2_PERSIAN_CI = 144;
exports.UCS2_ESPERANTO_CI = 145;
exports.UCS2_HUNGARIAN_CI = 146;
exports.UCS2_SINHALA_CI = 147;
exports.UCS2_GERMAN2_CI = 148;
exports.UCS2_CROATIAN_MYSQL561_CI = 149;
exports.UCS2_UNICODE_520_CI = 150;
exports.UCS2_VIETNAMESE_CI = 151;
exports.UCS2_GENERAL_MYSQL500_CI = 159;
exports.UTF32_UNICODE_CI = 160;
exports.UTF32_ICELANDIC_CI = 161;
exports.UTF32_LATVIAN_CI = 162;
exports.UTF32_ROMANIAN_CI = 163;
exports.UTF32_SLOVENIAN_CI = 164;
exports.UTF32_POLISH_CI = 165;
exports.UTF32_ESTONIAN_CI = 166;
exports.UTF32_SPANISH_CI = 167;
exports.UTF32_SWEDISH_CI = 168;
exports.UTF32_TURKISH_CI = 169;
exports.UTF32_CZECH_CI = 170;
exports.UTF32_DANISH_CI = 171;
exports.UTF32_LITHUANIAN_CI = 172;
exports.UTF32_SLOVAK_CI = 173;
exports.UTF32_SPANISH2_CI = 174;
exports.UTF32_ROMAN_CI = 175;
exports.UTF32_PERSIAN_CI = 176;
exports.UTF32_ESPERANTO_CI = 177;
exports.UTF32_HUNGARIAN_CI = 178;
exports.UTF32_SINHALA_CI = 179;
exports.UTF32_GERMAN2_CI = 180;
exports.UTF32_CROATIAN_MYSQL561_CI = 181;
exports.UTF32_UNICODE_520_CI = 182;
exports.UTF32_VIETNAMESE_CI = 183;
exports.UTF8_UNICODE_CI = 192;
exports.UTF8_ICELANDIC_CI = 193;
exports.UTF8_LATVIAN_CI = 194;
exports.UTF8_ROMANIAN_CI = 195;
exports.UTF8_SLOVENIAN_CI = 196;
exports.UTF8_POLISH_CI = 197;
exports.UTF8_ESTONIAN_CI = 198;
exports.UTF8_SPANISH_CI = 199;
exports.UTF8_SWEDISH_CI = 200;
exports.UTF8_TURKISH_CI = 201;
exports.UTF8_CZECH_CI = 202;
exports.UTF8_DANISH_CI = 203;
exports.UTF8_LITHUANIAN_CI = 204;
exports.UTF8_SLOVAK_CI = 205;
exports.UTF8_SPANISH2_CI = 206;
exports.UTF8_ROMAN_CI = 207;
exports.UTF8_PERSIAN_CI = 208;
exports.UTF8_ESPERANTO_CI = 209;
exports.UTF8_HUNGARIAN_CI = 210;
exports.UTF8_SINHALA_CI = 211;
exports.UTF8_GERMAN2_CI = 212;
exports.UTF8_CROATIAN_MYSQL561_CI = 213;
exports.UTF8_UNICODE_520_CI = 214;
exports.UTF8_VIETNAMESE_CI = 215;
exports.UTF8_GENERAL_MYSQL500_CI = 223;
exports.UTF8MB4_UNICODE_CI = 224;
exports.UTF8MB4_ICELANDIC_CI = 225;
exports.UTF8MB4_LATVIAN_CI = 226;
exports.UTF8MB4_ROMANIAN_CI = 227;
exports.UTF8MB4_SLOVENIAN_CI = 228;
exports.UTF8MB4_POLISH_CI = 229;
exports.UTF8MB4_ESTONIAN_CI = 230;
exports.UTF8MB4_SPANISH_CI = 231;
exports.UTF8MB4_SWEDISH_CI = 232;
exports.UTF8MB4_TURKISH_CI = 233;
exports.UTF8MB4_CZECH_CI = 234;
exports.UTF8MB4_DANISH_CI = 235;
exports.UTF8MB4_LITHUANIAN_CI = 236;
exports.UTF8MB4_SLOVAK_CI = 237;
exports.UTF8MB4_SPANISH2_CI = 238;
exports.UTF8MB4_ROMAN_CI = 239;
exports.UTF8MB4_PERSIAN_CI = 240;
exports.UTF8MB4_ESPERANTO_CI = 241;
exports.UTF8MB4_HUNGARIAN_CI = 242;
exports.UTF8MB4_SINHALA_CI = 243;
exports.UTF8MB4_GERMAN2_CI = 244;
exports.UTF8MB4_CROATIAN_MYSQL561_CI = 245;
exports.UTF8MB4_UNICODE_520_CI = 246;
exports.UTF8MB4_VIETNAMESE_CI = 247;
exports.UTF8_GENERAL50_CI = 253;
// short aliases
exports.ARMSCII8 = exports.ARMSCII8_GENERAL_CI;
exports.ASCII = exports.ASCII_GENERAL_CI;
exports.BIG5 = exports.BIG5_CHINESE_CI;
exports.BINARY = exports.BINARY;
exports.CP1250 = exports.CP1250_GENERAL_CI;
exports.CP1251 = exports.CP1251_GENERAL_CI;
exports.CP1256 = exports.CP1256_GENERAL_CI;
exports.CP1257 = exports.CP1257_GENERAL_CI;
exports.CP866 = exports.CP866_GENERAL_CI;
exports.CP850 = exports.CP850_GENERAL_CI;
exports.CP852 = exports.CP852_GENERAL_CI;
exports.CP932 = exports.CP932_JAPANESE_CI;
exports.DEC8 = exports.DEC8_SWEDISH_CI;
exports.EUCJPMS = exports.EUCJPMS_JAPANESE_CI;
exports.EUCKR = exports.EUCKR_KOREAN_CI;
exports.GB2312 = exports.GB2312_CHINESE_CI;
exports.GBK = exports.GBK_CHINESE_CI;
exports.GEOSTD8 = exports.GEOSTD8_GENERAL_CI;
exports.GREEK = exports.GREEK_GENERAL_CI;
exports.HEBREW = exports.HEBREW_GENERAL_CI;
exports.HP8 = exports.HP8_ENGLISH_CI;
exports.KEYBCS2 = exports.KEYBCS2_GENERAL_CI;
exports.KOI8R = exports.KOI8R_GENERAL_CI;
exports.KOI8U = exports.KOI8U_GENERAL_CI;
exports.LATIN1 = exports.LATIN1_SWEDISH_CI;
exports.LATIN2 = exports.LATIN2_GENERAL_CI;
exports.LATIN5 = exports.LATIN5_TURKISH_CI;
exports.LATIN7 = exports.LATIN7_GENERAL_CI;
exports.MACCE = exports.MACCE_GENERAL_CI;
exports.MACROMAN = exports.MACROMAN_GENERAL_CI;
exports.SJIS = exports.SJIS_JAPANESE_CI;
exports.SWE7 = exports.SWE7_SWEDISH_CI;
exports.TIS620 = exports.TIS620_THAI_CI;
exports.UCS2 = exports.UCS2_GENERAL_CI;
exports.UJIS = exports.UJIS_JAPANESE_CI;
exports.UTF16 = exports.UTF16_GENERAL_CI;
exports.UTF16LE = exports.UTF16LE_GENERAL_CI;
exports.UTF8 = exports.UTF8_GENERAL_CI;
exports.UTF8MB4 = exports.UTF8MB4_GENERAL_CI;
exports.UTF32 = exports.UTF32_GENERAL_CI;

View File

@ -0,0 +1,26 @@
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.CLIENT_LONG_PASSWORD = 1; /* new more secure passwords */
exports.CLIENT_FOUND_ROWS = 2; /* Found instead of affected rows */
exports.CLIENT_LONG_FLAG = 4; /* Get all column flags */
exports.CLIENT_CONNECT_WITH_DB = 8; /* One can specify db on connect */
exports.CLIENT_NO_SCHEMA = 16; /* Don't allow database.table.column */
exports.CLIENT_COMPRESS = 32; /* Can use compression protocol */
exports.CLIENT_ODBC = 64; /* Odbc client */
exports.CLIENT_LOCAL_FILES = 128; /* Can use LOAD DATA LOCAL */
exports.CLIENT_IGNORE_SPACE = 256; /* Ignore spaces before '(' */
exports.CLIENT_PROTOCOL_41 = 512; /* New 4.1 protocol */
exports.CLIENT_INTERACTIVE = 1024; /* This is an interactive client */
exports.CLIENT_SSL = 2048; /* Switch to SSL after handshake */
exports.CLIENT_IGNORE_SIGPIPE = 4096; /* IGNORE sigpipes */
exports.CLIENT_TRANSACTIONS = 8192; /* Client knows about transactions */
exports.CLIENT_RESERVED = 16384; /* Old flag for 4.1 protocol */
exports.CLIENT_SECURE_CONNECTION = 32768; /* New 4.1 authentication */
exports.CLIENT_MULTI_STATEMENTS = 65536; /* Enable/disable multi-stmt support */
exports.CLIENT_MULTI_RESULTS = 131072; /* Enable/disable multi-results */
exports.CLIENT_PS_MULTI_RESULTS = 262144; /* Multi-results in PS-protocol */
exports.CLIENT_PLUGIN_AUTH = 524288; /* Client supports plugin authentication */
exports.CLIENT_SSL_VERIFY_SERVER_CERT = 1073741824;
exports.CLIENT_REMEMBER_OPTIONS = 2147483648;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.NOT_NULL_FLAG = 1; /* Field can't be NULL */
exports.PRI_KEY_FLAG = 2; /* Field is part of a primary key */
exports.UNIQUE_KEY_FLAG = 4; /* Field is part of a unique key */
exports.MULTIPLE_KEY_FLAG = 8; /* Field is part of a key */
exports.BLOB_FLAG = 16; /* Field is a blob */
exports.UNSIGNED_FLAG = 32; /* Field is unsigned */
exports.ZEROFILL_FLAG = 64; /* Field is zerofill */
exports.BINARY_FLAG = 128; /* Field is binary */
/* The following are only sent to new clients */
exports.ENUM_FLAG = 256; /* field is an enum */
exports.AUTO_INCREMENT_FLAG = 512; /* field is a autoincrement field */
exports.TIMESTAMP_FLAG = 1024; /* Field is a timestamp */
exports.SET_FLAG = 2048; /* field is a set */
exports.NO_DEFAULT_VALUE_FLAG = 4096; /* Field doesn't have default value */
exports.ON_UPDATE_NOW_FLAG = 8192; /* Field is set to NOW on UPDATE */
exports.NUM_FLAG = 32768; /* Field is num (for clients) */

View File

@ -0,0 +1,39 @@
// Manually extracted from mysql-5.5.23/include/mysql_com.h
/**
Is raised when a multi-statement transaction
has been started, either explicitly, by means
of BEGIN or COMMIT AND CHAIN, or
implicitly, by the first transactional
statement, when autocommit=off.
*/
exports.SERVER_STATUS_IN_TRANS = 1;
exports.SERVER_STATUS_AUTOCOMMIT = 2; /* Server in auto_commit mode */
exports.SERVER_MORE_RESULTS_EXISTS = 8; /* Multi query - next query exists */
exports.SERVER_QUERY_NO_GOOD_INDEX_USED = 16;
exports.SERVER_QUERY_NO_INDEX_USED = 32;
/**
The server was able to fulfill the clients request and opened a
read-only non-scrollable cursor for a query. This flag comes
in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
*/
exports.SERVER_STATUS_CURSOR_EXISTS = 64;
/**
This flag is sent when a read-only cursor is exhausted, in reply to
COM_STMT_FETCH command.
*/
exports.SERVER_STATUS_LAST_ROW_SENT = 128;
exports.SERVER_STATUS_DB_DROPPED = 256; /* A database was dropped */
exports.SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512;
/**
Sent to the client if after a prepared statement reprepare
we discovered that the new statement returns a different
number of result set columns.
*/
exports.SERVER_STATUS_METADATA_CHANGED = 1024;
exports.SERVER_QUERY_WAS_SLOW = 2048;
/**
To mark ResultSet containing output parameter values.
*/
exports.SERVER_PS_OUT_PARAMS = 4096;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
/**
* MySQL type constants
*
* Extracted from version 5.7.29
*
* !! Generated by generate-type-constants.js, do not modify by hand !!
*/
exports.DECIMAL = 0;
exports.TINY = 1;
exports.SHORT = 2;
exports.LONG = 3;
exports.FLOAT = 4;
exports.DOUBLE = 5;
exports.NULL = 6;
exports.TIMESTAMP = 7;
exports.LONGLONG = 8;
exports.INT24 = 9;
exports.DATE = 10;
exports.TIME = 11;
exports.DATETIME = 12;
exports.YEAR = 13;
exports.NEWDATE = 14;
exports.VARCHAR = 15;
exports.BIT = 16;
exports.TIMESTAMP2 = 17;
exports.DATETIME2 = 18;
exports.TIME2 = 19;
exports.JSON = 245;
exports.NEWDECIMAL = 246;
exports.ENUM = 247;
exports.SET = 248;
exports.TINY_BLOB = 249;
exports.MEDIUM_BLOB = 250;
exports.LONG_BLOB = 251;
exports.BLOB = 252;
exports.VAR_STRING = 253;
exports.STRING = 254;
exports.GEOMETRY = 255;
// Lookup-by-number table
exports[0] = 'DECIMAL';
exports[1] = 'TINY';
exports[2] = 'SHORT';
exports[3] = 'LONG';
exports[4] = 'FLOAT';
exports[5] = 'DOUBLE';
exports[6] = 'NULL';
exports[7] = 'TIMESTAMP';
exports[8] = 'LONGLONG';
exports[9] = 'INT24';
exports[10] = 'DATE';
exports[11] = 'TIME';
exports[12] = 'DATETIME';
exports[13] = 'YEAR';
exports[14] = 'NEWDATE';
exports[15] = 'VARCHAR';
exports[16] = 'BIT';
exports[17] = 'TIMESTAMP2';
exports[18] = 'DATETIME2';
exports[19] = 'TIME2';
exports[245] = 'JSON';
exports[246] = 'NEWDECIMAL';
exports[247] = 'ENUM';
exports[248] = 'SET';
exports[249] = 'TINY_BLOB';
exports[250] = 'MEDIUM_BLOB';
exports[251] = 'LONG_BLOB';
exports[252] = 'BLOB';
exports[253] = 'VAR_STRING';
exports[254] = 'STRING';
exports[255] = 'GEOMETRY';

View File

@ -0,0 +1,20 @@
module.exports = AuthSwitchRequestPacket;
function AuthSwitchRequestPacket(options) {
options = options || {};
this.status = 0xfe;
this.authMethodName = options.authMethodName;
this.authMethodData = options.authMethodData;
}
AuthSwitchRequestPacket.prototype.parse = function parse(parser) {
this.status = parser.parseUnsignedNumber(1);
this.authMethodName = parser.parseNullTerminatedString();
this.authMethodData = parser.parsePacketTerminatedBuffer();
};
AuthSwitchRequestPacket.prototype.write = function write(writer) {
writer.writeUnsignedNumber(1, this.status);
writer.writeNullTerminatedString(this.authMethodName);
writer.writeBuffer(this.authMethodData);
};

View File

@ -0,0 +1,14 @@
module.exports = AuthSwitchResponsePacket;
function AuthSwitchResponsePacket(options) {
options = options || {};
this.data = options.data;
}
AuthSwitchResponsePacket.prototype.parse = function parse(parser) {
this.data = parser.parsePacketTerminatedBuffer();
};
AuthSwitchResponsePacket.prototype.write = function write(writer) {
writer.writeBuffer(this.data);
};

View File

@ -0,0 +1,54 @@
var Buffer = require('safe-buffer').Buffer;
module.exports = ClientAuthenticationPacket;
function ClientAuthenticationPacket(options) {
options = options || {};
this.clientFlags = options.clientFlags;
this.maxPacketSize = options.maxPacketSize;
this.charsetNumber = options.charsetNumber;
this.filler = undefined;
this.user = options.user;
this.scrambleBuff = options.scrambleBuff;
this.database = options.database;
this.protocol41 = options.protocol41;
}
ClientAuthenticationPacket.prototype.parse = function(parser) {
if (this.protocol41) {
this.clientFlags = parser.parseUnsignedNumber(4);
this.maxPacketSize = parser.parseUnsignedNumber(4);
this.charsetNumber = parser.parseUnsignedNumber(1);
this.filler = parser.parseFiller(23);
this.user = parser.parseNullTerminatedString();
this.scrambleBuff = parser.parseLengthCodedBuffer();
this.database = parser.parseNullTerminatedString();
} else {
this.clientFlags = parser.parseUnsignedNumber(2);
this.maxPacketSize = parser.parseUnsignedNumber(3);
this.user = parser.parseNullTerminatedString();
this.scrambleBuff = parser.parseBuffer(8);
this.database = parser.parseLengthCodedBuffer();
}
};
ClientAuthenticationPacket.prototype.write = function(writer) {
if (this.protocol41) {
writer.writeUnsignedNumber(4, this.clientFlags);
writer.writeUnsignedNumber(4, this.maxPacketSize);
writer.writeUnsignedNumber(1, this.charsetNumber);
writer.writeFiller(23);
writer.writeNullTerminatedString(this.user);
writer.writeLengthCodedBuffer(this.scrambleBuff);
writer.writeNullTerminatedString(this.database);
} else {
writer.writeUnsignedNumber(2, this.clientFlags);
writer.writeUnsignedNumber(3, this.maxPacketSize);
writer.writeNullTerminatedString(this.user);
writer.writeBuffer(this.scrambleBuff);
if (this.database && this.database.length) {
writer.writeFiller(1);
writer.writeBuffer(Buffer.from(this.database));
}
}
};

View File

@ -0,0 +1,26 @@
module.exports = ComChangeUserPacket;
function ComChangeUserPacket(options) {
options = options || {};
this.command = 0x11;
this.user = options.user;
this.scrambleBuff = options.scrambleBuff;
this.database = options.database;
this.charsetNumber = options.charsetNumber;
}
ComChangeUserPacket.prototype.parse = function(parser) {
this.command = parser.parseUnsignedNumber(1);
this.user = parser.parseNullTerminatedString();
this.scrambleBuff = parser.parseLengthCodedBuffer();
this.database = parser.parseNullTerminatedString();
this.charsetNumber = parser.parseUnsignedNumber(1);
};
ComChangeUserPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.command);
writer.writeNullTerminatedString(this.user);
writer.writeLengthCodedBuffer(this.scrambleBuff);
writer.writeNullTerminatedString(this.database);
writer.writeUnsignedNumber(2, this.charsetNumber);
};

View File

@ -0,0 +1,12 @@
module.exports = ComPingPacket;
function ComPingPacket() {
this.command = 0x0e;
}
ComPingPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.command);
};
ComPingPacket.prototype.parse = function(parser) {
this.command = parser.parseUnsignedNumber(1);
};

View File

@ -0,0 +1,15 @@
module.exports = ComQueryPacket;
function ComQueryPacket(sql) {
this.command = 0x03;
this.sql = sql;
}
ComQueryPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.command);
writer.writeString(this.sql);
};
ComQueryPacket.prototype.parse = function(parser) {
this.command = parser.parseUnsignedNumber(1);
this.sql = parser.parsePacketTerminatedString();
};

View File

@ -0,0 +1,12 @@
module.exports = ComQuitPacket;
function ComQuitPacket() {
this.command = 0x01;
}
ComQuitPacket.prototype.parse = function parse(parser) {
this.command = parser.parseUnsignedNumber(1);
};
ComQuitPacket.prototype.write = function write(writer) {
writer.writeUnsignedNumber(1, this.command);
};

View File

@ -0,0 +1,12 @@
module.exports = ComStatisticsPacket;
function ComStatisticsPacket() {
this.command = 0x09;
}
ComStatisticsPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.command);
};
ComStatisticsPacket.prototype.parse = function(parser) {
this.command = parser.parseUnsignedNumber(1);
};

View File

@ -0,0 +1,9 @@
module.exports = EmptyPacket;
function EmptyPacket() {
}
EmptyPacket.prototype.parse = function parse() {
};
EmptyPacket.prototype.write = function write() {
};

View File

@ -0,0 +1,25 @@
module.exports = EofPacket;
function EofPacket(options) {
options = options || {};
this.fieldCount = undefined;
this.warningCount = options.warningCount;
this.serverStatus = options.serverStatus;
this.protocol41 = options.protocol41;
}
EofPacket.prototype.parse = function(parser) {
this.fieldCount = parser.parseUnsignedNumber(1);
if (this.protocol41) {
this.warningCount = parser.parseUnsignedNumber(2);
this.serverStatus = parser.parseUnsignedNumber(2);
}
};
EofPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, 0xfe);
if (this.protocol41) {
writer.writeUnsignedNumber(2, this.warningCount);
writer.writeUnsignedNumber(2, this.serverStatus);
}
};

View File

@ -0,0 +1,35 @@
module.exports = ErrorPacket;
function ErrorPacket(options) {
options = options || {};
this.fieldCount = options.fieldCount;
this.errno = options.errno;
this.sqlStateMarker = options.sqlStateMarker;
this.sqlState = options.sqlState;
this.message = options.message;
}
ErrorPacket.prototype.parse = function(parser) {
this.fieldCount = parser.parseUnsignedNumber(1);
this.errno = parser.parseUnsignedNumber(2);
// sqlStateMarker ('#' = 0x23) indicates error packet format
if (parser.peak() === 0x23) {
this.sqlStateMarker = parser.parseString(1);
this.sqlState = parser.parseString(5);
}
this.message = parser.parsePacketTerminatedString();
};
ErrorPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, 0xff);
writer.writeUnsignedNumber(2, this.errno);
if (this.sqlStateMarker) {
writer.writeString(this.sqlStateMarker);
writer.writeString(this.sqlState);
}
writer.writeString(this.message);
};

View File

@ -0,0 +1,26 @@
var Types = require('../constants/types');
module.exports = Field;
function Field(options) {
options = options || {};
this.parser = options.parser;
this.packet = options.packet;
this.db = options.packet.db;
this.table = options.packet.table;
this.name = options.packet.name;
this.type = Types[options.packet.type];
this.length = options.packet.length;
}
Field.prototype.string = function () {
return this.parser.parseLengthCodedString();
};
Field.prototype.buffer = function () {
return this.parser.parseLengthCodedBuffer();
};
Field.prototype.geometry = function () {
return this.parser.parseGeometryValue();
};

View File

@ -0,0 +1,93 @@
module.exports = FieldPacket;
function FieldPacket(options) {
options = options || {};
this.catalog = options.catalog;
this.db = options.db;
this.table = options.table;
this.orgTable = options.orgTable;
this.name = options.name;
this.orgName = options.orgName;
this.charsetNr = options.charsetNr;
this.length = options.length;
this.type = options.type;
this.flags = options.flags;
this.decimals = options.decimals;
this.default = options.default;
this.zeroFill = options.zeroFill;
this.protocol41 = options.protocol41;
}
FieldPacket.prototype.parse = function(parser) {
if (this.protocol41) {
this.catalog = parser.parseLengthCodedString();
this.db = parser.parseLengthCodedString();
this.table = parser.parseLengthCodedString();
this.orgTable = parser.parseLengthCodedString();
this.name = parser.parseLengthCodedString();
this.orgName = parser.parseLengthCodedString();
if (parser.parseLengthCodedNumber() !== 0x0c) {
var err = new TypeError('Received invalid field length');
err.code = 'PARSER_INVALID_FIELD_LENGTH';
throw err;
}
this.charsetNr = parser.parseUnsignedNumber(2);
this.length = parser.parseUnsignedNumber(4);
this.type = parser.parseUnsignedNumber(1);
this.flags = parser.parseUnsignedNumber(2);
this.decimals = parser.parseUnsignedNumber(1);
var filler = parser.parseBuffer(2);
if (filler[0] !== 0x0 || filler[1] !== 0x0) {
var err = new TypeError('Received invalid filler');
err.code = 'PARSER_INVALID_FILLER';
throw err;
}
// parsed flags
this.zeroFill = (this.flags & 0x0040 ? true : false);
if (parser.reachedPacketEnd()) {
return;
}
this.default = parser.parseLengthCodedString();
} else {
this.table = parser.parseLengthCodedString();
this.name = parser.parseLengthCodedString();
this.length = parser.parseUnsignedNumber(parser.parseUnsignedNumber(1));
this.type = parser.parseUnsignedNumber(parser.parseUnsignedNumber(1));
}
};
FieldPacket.prototype.write = function(writer) {
if (this.protocol41) {
writer.writeLengthCodedString(this.catalog);
writer.writeLengthCodedString(this.db);
writer.writeLengthCodedString(this.table);
writer.writeLengthCodedString(this.orgTable);
writer.writeLengthCodedString(this.name);
writer.writeLengthCodedString(this.orgName);
writer.writeLengthCodedNumber(0x0c);
writer.writeUnsignedNumber(2, this.charsetNr || 0);
writer.writeUnsignedNumber(4, this.length || 0);
writer.writeUnsignedNumber(1, this.type || 0);
writer.writeUnsignedNumber(2, this.flags || 0);
writer.writeUnsignedNumber(1, this.decimals || 0);
writer.writeFiller(2);
if (this.default !== undefined) {
writer.writeLengthCodedString(this.default);
}
} else {
writer.writeLengthCodedString(this.table);
writer.writeLengthCodedString(this.name);
writer.writeUnsignedNumber(1, 0x01);
writer.writeUnsignedNumber(1, this.length);
writer.writeUnsignedNumber(1, 0x01);
writer.writeUnsignedNumber(1, this.type);
}
};

View File

@ -0,0 +1,103 @@
var Buffer = require('safe-buffer').Buffer;
var Client = require('../constants/client');
module.exports = HandshakeInitializationPacket;
function HandshakeInitializationPacket(options) {
options = options || {};
this.protocolVersion = options.protocolVersion;
this.serverVersion = options.serverVersion;
this.threadId = options.threadId;
this.scrambleBuff1 = options.scrambleBuff1;
this.filler1 = options.filler1;
this.serverCapabilities1 = options.serverCapabilities1;
this.serverLanguage = options.serverLanguage;
this.serverStatus = options.serverStatus;
this.serverCapabilities2 = options.serverCapabilities2;
this.scrambleLength = options.scrambleLength;
this.filler2 = options.filler2;
this.scrambleBuff2 = options.scrambleBuff2;
this.filler3 = options.filler3;
this.pluginData = options.pluginData;
this.protocol41 = options.protocol41;
if (this.protocol41) {
// force set the bit in serverCapabilities1
this.serverCapabilities1 |= Client.CLIENT_PROTOCOL_41;
}
}
HandshakeInitializationPacket.prototype.parse = function(parser) {
this.protocolVersion = parser.parseUnsignedNumber(1);
this.serverVersion = parser.parseNullTerminatedString();
this.threadId = parser.parseUnsignedNumber(4);
this.scrambleBuff1 = parser.parseBuffer(8);
this.filler1 = parser.parseFiller(1);
this.serverCapabilities1 = parser.parseUnsignedNumber(2);
this.serverLanguage = parser.parseUnsignedNumber(1);
this.serverStatus = parser.parseUnsignedNumber(2);
this.protocol41 = (this.serverCapabilities1 & (1 << 9)) > 0;
if (this.protocol41) {
this.serverCapabilities2 = parser.parseUnsignedNumber(2);
this.scrambleLength = parser.parseUnsignedNumber(1);
this.filler2 = parser.parseFiller(10);
// scrambleBuff2 should be 0x00 terminated, but sphinx does not do this
// so we assume scrambleBuff2 to be 12 byte and treat the next byte as a
// filler byte.
this.scrambleBuff2 = parser.parseBuffer(12);
this.filler3 = parser.parseFiller(1);
} else {
this.filler2 = parser.parseFiller(13);
}
if (parser.reachedPacketEnd()) {
return;
}
// According to the docs this should be 0x00 terminated, but MariaDB does
// not do this, so we assume this string to be packet terminated.
this.pluginData = parser.parsePacketTerminatedString();
// However, if there is a trailing '\0', strip it
var lastChar = this.pluginData.length - 1;
if (this.pluginData[lastChar] === '\0') {
this.pluginData = this.pluginData.substr(0, lastChar);
}
};
HandshakeInitializationPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.protocolVersion);
writer.writeNullTerminatedString(this.serverVersion);
writer.writeUnsignedNumber(4, this.threadId);
writer.writeBuffer(this.scrambleBuff1);
writer.writeFiller(1);
writer.writeUnsignedNumber(2, this.serverCapabilities1);
writer.writeUnsignedNumber(1, this.serverLanguage);
writer.writeUnsignedNumber(2, this.serverStatus);
if (this.protocol41) {
writer.writeUnsignedNumber(2, this.serverCapabilities2);
writer.writeUnsignedNumber(1, this.scrambleLength);
writer.writeFiller(10);
}
writer.writeNullTerminatedBuffer(this.scrambleBuff2);
if (this.pluginData !== undefined) {
writer.writeNullTerminatedString(this.pluginData);
}
};
HandshakeInitializationPacket.prototype.scrambleBuff = function() {
var buffer = null;
if (typeof this.scrambleBuff2 === 'undefined') {
buffer = Buffer.from(this.scrambleBuff1);
} else {
buffer = Buffer.allocUnsafe(this.scrambleBuff1.length + this.scrambleBuff2.length);
this.scrambleBuff1.copy(buffer, 0);
this.scrambleBuff2.copy(buffer, this.scrambleBuff1.length);
}
return buffer;
};

View File

@ -0,0 +1,15 @@
module.exports = LocalDataFilePacket;
/**
* Create a new LocalDataFilePacket
* @constructor
* @param {Buffer} data The data contents of the packet
* @public
*/
function LocalDataFilePacket(data) {
this.data = data;
}
LocalDataFilePacket.prototype.write = function(writer) {
writer.writeBuffer(this.data);
};

View File

@ -0,0 +1,21 @@
module.exports = LocalInfileRequestPacket;
function LocalInfileRequestPacket(options) {
options = options || {};
this.filename = options.filename;
}
LocalInfileRequestPacket.prototype.parse = function parse(parser) {
if (parser.parseLengthCodedNumber() !== null) {
var err = new TypeError('Received invalid field length');
err.code = 'PARSER_INVALID_FIELD_LENGTH';
throw err;
}
this.filename = parser.parsePacketTerminatedString();
};
LocalInfileRequestPacket.prototype.write = function write(writer) {
writer.writeLengthCodedNumber(null);
writer.writeString(this.filename);
};

View File

@ -0,0 +1,44 @@
// Language-neutral expression to match ER_UPDATE_INFO
var ER_UPDATE_INFO_REGEXP = /^[^:0-9]+: [0-9]+[^:0-9]+: ([0-9]+)[^:0-9]+: [0-9]+[^:0-9]*$/;
module.exports = OkPacket;
function OkPacket(options) {
options = options || {};
this.fieldCount = undefined;
this.affectedRows = undefined;
this.insertId = undefined;
this.serverStatus = undefined;
this.warningCount = undefined;
this.message = undefined;
this.protocol41 = options.protocol41;
}
OkPacket.prototype.parse = function(parser) {
this.fieldCount = parser.parseUnsignedNumber(1);
this.affectedRows = parser.parseLengthCodedNumber();
this.insertId = parser.parseLengthCodedNumber();
if (this.protocol41) {
this.serverStatus = parser.parseUnsignedNumber(2);
this.warningCount = parser.parseUnsignedNumber(2);
}
this.message = parser.parsePacketTerminatedString();
this.changedRows = 0;
var m = ER_UPDATE_INFO_REGEXP.exec(this.message);
if (m !== null) {
this.changedRows = parseInt(m[1], 10);
}
};
OkPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, 0x00);
writer.writeLengthCodedNumber(this.affectedRows || 0);
writer.writeLengthCodedNumber(this.insertId || 0);
if (this.protocol41) {
writer.writeUnsignedNumber(2, this.serverStatus || 0);
writer.writeUnsignedNumber(2, this.warningCount || 0);
}
writer.writeString(this.message);
};

View File

@ -0,0 +1,14 @@
module.exports = OldPasswordPacket;
function OldPasswordPacket(options) {
options = options || {};
this.scrambleBuff = options.scrambleBuff;
}
OldPasswordPacket.prototype.parse = function(parser) {
this.scrambleBuff = parser.parsePacketTerminatedBuffer();
};
OldPasswordPacket.prototype.write = function(writer) {
writer.writeBuffer(this.scrambleBuff);
};

View File

@ -0,0 +1,14 @@
module.exports = ResultSetHeaderPacket;
function ResultSetHeaderPacket(options) {
options = options || {};
this.fieldCount = options.fieldCount;
}
ResultSetHeaderPacket.prototype.parse = function(parser) {
this.fieldCount = parser.parseLengthCodedNumber();
};
ResultSetHeaderPacket.prototype.write = function(writer) {
writer.writeLengthCodedNumber(this.fieldCount);
};

View File

@ -0,0 +1,130 @@
var Types = require('../constants/types');
var Charsets = require('../constants/charsets');
var Field = require('./Field');
var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);
module.exports = RowDataPacket;
function RowDataPacket() {
}
Object.defineProperty(RowDataPacket.prototype, 'parse', {
configurable : true,
enumerable : false,
value : parse
});
Object.defineProperty(RowDataPacket.prototype, '_typeCast', {
configurable : true,
enumerable : false,
value : typeCast
});
function parse(parser, fieldPackets, typeCast, nestTables, connection) {
var self = this;
var next = function () {
return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings);
};
for (var i = 0; i < fieldPackets.length; i++) {
var fieldPacket = fieldPackets[i];
var value;
if (typeof typeCast === 'function') {
value = typeCast.apply(connection, [ new Field({ packet: fieldPacket, parser: parser }), next ]);
} else {
value = (typeCast)
? this._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings)
: ( (fieldPacket.charsetNr === Charsets.BINARY)
? parser.parseLengthCodedBuffer()
: parser.parseLengthCodedString() );
}
if (typeof nestTables === 'string' && nestTables.length) {
this[fieldPacket.table + nestTables + fieldPacket.name] = value;
} else if (nestTables) {
this[fieldPacket.table] = this[fieldPacket.table] || {};
this[fieldPacket.table][fieldPacket.name] = value;
} else {
this[fieldPacket.name] = value;
}
}
}
function typeCast(field, parser, timeZone, supportBigNumbers, bigNumberStrings, dateStrings) {
var numberString;
switch (field.type) {
case Types.TIMESTAMP:
case Types.TIMESTAMP2:
case Types.DATE:
case Types.DATETIME:
case Types.DATETIME2:
case Types.NEWDATE:
var dateString = parser.parseLengthCodedString();
if (typeMatch(field.type, dateStrings)) {
return dateString;
}
if (dateString === null) {
return null;
}
var originalString = dateString;
if (field.type === Types.DATE) {
dateString += ' 00:00:00';
}
if (timeZone !== 'local') {
dateString += ' ' + timeZone;
}
var dt = new Date(dateString);
if (isNaN(dt.getTime())) {
return originalString;
}
return dt;
case Types.TINY:
case Types.SHORT:
case Types.LONG:
case Types.INT24:
case Types.YEAR:
case Types.FLOAT:
case Types.DOUBLE:
numberString = parser.parseLengthCodedString();
return (numberString === null || (field.zeroFill && numberString[0] === '0'))
? numberString : Number(numberString);
case Types.NEWDECIMAL:
case Types.LONGLONG:
numberString = parser.parseLengthCodedString();
return (numberString === null || (field.zeroFill && numberString[0] === '0'))
? numberString
: ((supportBigNumbers && (bigNumberStrings || (Number(numberString) >= IEEE_754_BINARY_64_PRECISION) || Number(numberString) <= -IEEE_754_BINARY_64_PRECISION))
? numberString
: Number(numberString));
case Types.BIT:
return parser.parseLengthCodedBuffer();
case Types.STRING:
case Types.VAR_STRING:
case Types.TINY_BLOB:
case Types.MEDIUM_BLOB:
case Types.LONG_BLOB:
case Types.BLOB:
return (field.charsetNr === Charsets.BINARY)
? parser.parseLengthCodedBuffer()
: parser.parseLengthCodedString();
case Types.GEOMETRY:
return parser.parseGeometryValue();
default:
return parser.parseLengthCodedString();
}
}
function typeMatch(type, list) {
if (Array.isArray(list)) {
return list.indexOf(Types[type]) !== -1;
} else {
return Boolean(list);
}
}

View File

@ -0,0 +1,27 @@
// http://dev.mysql.com/doc/internals/en/ssl.html
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
var ClientConstants = require('../constants/client');
module.exports = SSLRequestPacket;
function SSLRequestPacket(options) {
options = options || {};
this.clientFlags = options.clientFlags | ClientConstants.CLIENT_SSL;
this.maxPacketSize = options.maxPacketSize;
this.charsetNumber = options.charsetNumber;
}
SSLRequestPacket.prototype.parse = function(parser) {
// TODO: check SSLRequest packet v41 vs pre v41
this.clientFlags = parser.parseUnsignedNumber(4);
this.maxPacketSize = parser.parseUnsignedNumber(4);
this.charsetNumber = parser.parseUnsignedNumber(1);
};
SSLRequestPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(4, this.clientFlags);
writer.writeUnsignedNumber(4, this.maxPacketSize);
writer.writeUnsignedNumber(1, this.charsetNumber);
writer.writeFiller(23);
};

View File

@ -0,0 +1,20 @@
module.exports = StatisticsPacket;
function StatisticsPacket() {
this.message = undefined;
}
StatisticsPacket.prototype.parse = function(parser) {
this.message = parser.parsePacketTerminatedString();
var items = this.message.split(/\s\s/);
for (var i = 0; i < items.length; i++) {
var m = items[i].match(/^(.+)\:\s+(.+)$/);
if (m !== null) {
this[m[1].toLowerCase().replace(/\s/g, '_')] = Number(m[2]);
}
}
};
StatisticsPacket.prototype.write = function(writer) {
writer.writeString(this.message);
};

View File

@ -0,0 +1,14 @@
module.exports = UseOldPasswordPacket;
function UseOldPasswordPacket(options) {
options = options || {};
this.firstByte = options.firstByte || 0xfe;
}
UseOldPasswordPacket.prototype.parse = function(parser) {
this.firstByte = parser.parseUnsignedNumber(1);
};
UseOldPasswordPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, this.firstByte);
};

View File

@ -0,0 +1,23 @@
exports.AuthSwitchRequestPacket = require('./AuthSwitchRequestPacket');
exports.AuthSwitchResponsePacket = require('./AuthSwitchResponsePacket');
exports.ClientAuthenticationPacket = require('./ClientAuthenticationPacket');
exports.ComChangeUserPacket = require('./ComChangeUserPacket');
exports.ComPingPacket = require('./ComPingPacket');
exports.ComQueryPacket = require('./ComQueryPacket');
exports.ComQuitPacket = require('./ComQuitPacket');
exports.ComStatisticsPacket = require('./ComStatisticsPacket');
exports.EmptyPacket = require('./EmptyPacket');
exports.EofPacket = require('./EofPacket');
exports.ErrorPacket = require('./ErrorPacket');
exports.Field = require('./Field');
exports.FieldPacket = require('./FieldPacket');
exports.HandshakeInitializationPacket = require('./HandshakeInitializationPacket');
exports.LocalDataFilePacket = require('./LocalDataFilePacket');
exports.LocalInfileRequestPacket = require('./LocalInfileRequestPacket');
exports.OkPacket = require('./OkPacket');
exports.OldPasswordPacket = require('./OldPasswordPacket');
exports.ResultSetHeaderPacket = require('./ResultSetHeaderPacket');
exports.RowDataPacket = require('./RowDataPacket');
exports.SSLRequestPacket = require('./SSLRequestPacket');
exports.StatisticsPacket = require('./StatisticsPacket');
exports.UseOldPasswordPacket = require('./UseOldPasswordPacket');

View File

@ -0,0 +1,67 @@
var Sequence = require('./Sequence');
var Util = require('util');
var Packets = require('../packets');
var Auth = require('../Auth');
module.exports = ChangeUser;
Util.inherits(ChangeUser, Sequence);
function ChangeUser(options, callback) {
Sequence.call(this, options, callback);
this._user = options.user;
this._password = options.password;
this._database = options.database;
this._charsetNumber = options.charsetNumber;
this._currentConfig = options.currentConfig;
}
ChangeUser.prototype.determinePacket = function determinePacket(firstByte) {
switch (firstByte) {
case 0xfe: return Packets.AuthSwitchRequestPacket;
case 0xff: return Packets.ErrorPacket;
default: return undefined;
}
};
ChangeUser.prototype.start = function(handshakeInitializationPacket) {
var scrambleBuff = handshakeInitializationPacket.scrambleBuff();
scrambleBuff = Auth.token(this._password, scrambleBuff);
var packet = new Packets.ComChangeUserPacket({
user : this._user,
scrambleBuff : scrambleBuff,
database : this._database,
charsetNumber : this._charsetNumber
});
this._currentConfig.user = this._user;
this._currentConfig.password = this._password;
this._currentConfig.database = this._database;
this._currentConfig.charsetNumber = this._charsetNumber;
this.emit('packet', packet);
};
ChangeUser.prototype['AuthSwitchRequestPacket'] = function (packet) {
var name = packet.authMethodName;
var data = Auth.auth(name, packet.authMethodData, {
password: this._password
});
if (data !== undefined) {
this.emit('packet', new Packets.AuthSwitchResponsePacket({
data: data
}));
} else {
var err = new Error('MySQL is requesting the ' + name + ' authentication method, which is not supported.');
err.code = 'UNSUPPORTED_AUTH_METHOD';
err.fatal = true;
this.end(err);
}
};
ChangeUser.prototype['ErrorPacket'] = function(packet) {
var err = this._packetToError(packet);
err.fatal = true;
this.end(err);
};

View File

@ -0,0 +1,126 @@
var Sequence = require('./Sequence');
var Util = require('util');
var Packets = require('../packets');
var Auth = require('../Auth');
var ClientConstants = require('../constants/client');
module.exports = Handshake;
Util.inherits(Handshake, Sequence);
function Handshake(options, callback) {
Sequence.call(this, options, callback);
options = options || {};
this._config = options.config;
this._handshakeInitializationPacket = null;
}
Handshake.prototype.determinePacket = function determinePacket(firstByte, parser) {
if (firstByte === 0xff) {
return Packets.ErrorPacket;
}
if (!this._handshakeInitializationPacket) {
return Packets.HandshakeInitializationPacket;
}
if (firstByte === 0xfe) {
return (parser.packetLength() === 1)
? Packets.UseOldPasswordPacket
: Packets.AuthSwitchRequestPacket;
}
return undefined;
};
Handshake.prototype['AuthSwitchRequestPacket'] = function (packet) {
var name = packet.authMethodName;
var data = Auth.auth(name, packet.authMethodData, {
password: this._config.password
});
if (data !== undefined) {
this.emit('packet', new Packets.AuthSwitchResponsePacket({
data: data
}));
} else {
var err = new Error('MySQL is requesting the ' + name + ' authentication method, which is not supported.');
err.code = 'UNSUPPORTED_AUTH_METHOD';
err.fatal = true;
this.end(err);
}
};
Handshake.prototype['HandshakeInitializationPacket'] = function(packet) {
this._handshakeInitializationPacket = packet;
this._config.protocol41 = packet.protocol41;
var serverSSLSupport = packet.serverCapabilities1 & ClientConstants.CLIENT_SSL;
if (this._config.ssl) {
if (!serverSSLSupport) {
var err = new Error('Server does not support secure connection');
err.code = 'HANDSHAKE_NO_SSL_SUPPORT';
err.fatal = true;
this.end(err);
return;
}
this._config.clientFlags |= ClientConstants.CLIENT_SSL;
this.emit('packet', new Packets.SSLRequestPacket({
clientFlags : this._config.clientFlags,
maxPacketSize : this._config.maxPacketSize,
charsetNumber : this._config.charsetNumber
}));
this.emit('start-tls');
} else {
this._sendCredentials();
}
};
Handshake.prototype._tlsUpgradeCompleteHandler = function() {
this._sendCredentials();
};
Handshake.prototype._sendCredentials = function() {
var packet = this._handshakeInitializationPacket;
this.emit('packet', new Packets.ClientAuthenticationPacket({
clientFlags : this._config.clientFlags,
maxPacketSize : this._config.maxPacketSize,
charsetNumber : this._config.charsetNumber,
user : this._config.user,
database : this._config.database,
protocol41 : packet.protocol41,
scrambleBuff : (packet.protocol41)
? Auth.token(this._config.password, packet.scrambleBuff())
: Auth.scramble323(packet.scrambleBuff(), this._config.password)
}));
};
Handshake.prototype['UseOldPasswordPacket'] = function() {
if (!this._config.insecureAuth) {
var err = new Error(
'MySQL server is requesting the old and insecure pre-4.1 auth mechanism. ' +
'Upgrade the user password or use the {insecureAuth: true} option.'
);
err.code = 'HANDSHAKE_INSECURE_AUTH';
err.fatal = true;
this.end(err);
return;
}
this.emit('packet', new Packets.OldPasswordPacket({
scrambleBuff: Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._config.password)
}));
};
Handshake.prototype['ErrorPacket'] = function(packet) {
var err = this._packetToError(packet, true);
err.fatal = true;
this.end(err);
};

View File

@ -0,0 +1,19 @@
var Sequence = require('./Sequence');
var Util = require('util');
var Packets = require('../packets');
module.exports = Ping;
Util.inherits(Ping, Sequence);
function Ping(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
Sequence.call(this, options, callback);
}
Ping.prototype.start = function() {
this.emit('packet', new Packets.ComPingPacket());
};

View File

@ -0,0 +1,228 @@
var ClientConstants = require('../constants/client');
var fs = require('fs');
var Packets = require('../packets');
var ResultSet = require('../ResultSet');
var Sequence = require('./Sequence');
var ServerStatus = require('../constants/server_status');
var Readable = require('readable-stream');
var Util = require('util');
module.exports = Query;
Util.inherits(Query, Sequence);
function Query(options, callback) {
Sequence.call(this, options, callback);
this.sql = options.sql;
this.values = options.values;
this.typeCast = (options.typeCast === undefined)
? true
: options.typeCast;
this.nestTables = options.nestTables || false;
this._resultSet = null;
this._results = [];
this._fields = [];
this._index = 0;
this._loadError = null;
}
Query.prototype.start = function() {
this.emit('packet', new Packets.ComQueryPacket(this.sql));
};
Query.prototype.determinePacket = function determinePacket(byte, parser) {
var resultSet = this._resultSet;
if (!resultSet) {
switch (byte) {
case 0x00: return Packets.OkPacket;
case 0xfb: return Packets.LocalInfileRequestPacket;
case 0xff: return Packets.ErrorPacket;
default: return Packets.ResultSetHeaderPacket;
}
}
if (resultSet.eofPackets.length === 0) {
return (resultSet.fieldPackets.length < resultSet.resultSetHeaderPacket.fieldCount)
? Packets.FieldPacket
: Packets.EofPacket;
}
if (byte === 0xff) {
return Packets.ErrorPacket;
}
if (byte === 0xfe && parser.packetLength() < 9) {
return Packets.EofPacket;
}
return Packets.RowDataPacket;
};
Query.prototype['OkPacket'] = function(packet) {
// try...finally for exception safety
try {
if (!this._callback) {
this.emit('result', packet, this._index);
} else {
this._results.push(packet);
this._fields.push(undefined);
}
} finally {
this._index++;
this._resultSet = null;
this._handleFinalResultPacket(packet);
}
};
Query.prototype['ErrorPacket'] = function(packet) {
var err = this._packetToError(packet);
var results = (this._results.length > 0)
? this._results
: undefined;
var fields = (this._fields.length > 0)
? this._fields
: undefined;
err.index = this._index;
err.sql = this.sql;
this.end(err, results, fields);
};
Query.prototype['LocalInfileRequestPacket'] = function(packet) {
if (this._connection.config.clientFlags & ClientConstants.CLIENT_LOCAL_FILES) {
this._sendLocalDataFile(packet.filename);
} else {
this._loadError = new Error('Load local files command is disabled');
this._loadError.code = 'LOCAL_FILES_DISABLED';
this._loadError.fatal = false;
this.emit('packet', new Packets.EmptyPacket());
}
};
Query.prototype['ResultSetHeaderPacket'] = function(packet) {
this._resultSet = new ResultSet(packet);
};
Query.prototype['FieldPacket'] = function(packet) {
this._resultSet.fieldPackets.push(packet);
};
Query.prototype['EofPacket'] = function(packet) {
this._resultSet.eofPackets.push(packet);
if (this._resultSet.eofPackets.length === 1 && !this._callback) {
this.emit('fields', this._resultSet.fieldPackets, this._index);
}
if (this._resultSet.eofPackets.length !== 2) {
return;
}
if (this._callback) {
this._results.push(this._resultSet.rows);
this._fields.push(this._resultSet.fieldPackets);
}
this._index++;
this._resultSet = null;
this._handleFinalResultPacket(packet);
};
Query.prototype._handleFinalResultPacket = function(packet) {
if (packet.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
return;
}
var results = (this._results.length > 1)
? this._results
: this._results[0];
var fields = (this._fields.length > 1)
? this._fields
: this._fields[0];
this.end(this._loadError, results, fields);
};
Query.prototype['RowDataPacket'] = function(packet, parser, connection) {
packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, connection);
if (this._callback) {
this._resultSet.rows.push(packet);
} else {
this.emit('result', packet, this._index);
}
};
Query.prototype._sendLocalDataFile = function(path) {
var self = this;
var localStream = fs.createReadStream(path, {
flag : 'r',
encoding : null,
autoClose : true
});
this.on('pause', function () {
localStream.pause();
});
this.on('resume', function () {
localStream.resume();
});
localStream.on('data', function (data) {
self.emit('packet', new Packets.LocalDataFilePacket(data));
});
localStream.on('error', function (err) {
self._loadError = err;
localStream.emit('end');
});
localStream.on('end', function () {
self.emit('packet', new Packets.EmptyPacket());
});
};
Query.prototype.stream = function(options) {
var self = this;
options = options || {};
options.objectMode = true;
var stream = new Readable(options);
stream._read = function() {
self._connection && self._connection.resume();
};
stream.once('end', function() {
process.nextTick(function () {
stream.emit('close');
});
});
this.on('result', function(row, i) {
if (!stream.push(row)) self._connection.pause();
stream.emit('result', row, i); // replicate old emitter
});
this.on('error', function(err) {
stream.emit('error', err); // Pass on any errors
});
this.on('end', function() {
stream.push(null); // pushing null, indicating EOF
});
this.on('fields', function(fields, i) {
stream.emit('fields', fields, i); // replicate old emitter
});
return stream;
};

View File

@ -0,0 +1,40 @@
var Sequence = require('./Sequence');
var Util = require('util');
var Packets = require('../packets');
module.exports = Quit;
Util.inherits(Quit, Sequence);
function Quit(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
Sequence.call(this, options, callback);
this._started = false;
}
Quit.prototype.end = function end(err) {
if (this._ended) {
return;
}
if (!this._started) {
Sequence.prototype.end.call(this, err);
return;
}
if (err && err.code === 'ECONNRESET' && err.syscall === 'read') {
// Ignore read errors after packet sent
Sequence.prototype.end.call(this);
return;
}
Sequence.prototype.end.call(this, err);
};
Quit.prototype.start = function() {
this._started = true;
this.emit('packet', new Packets.ComQuitPacket());
};

View File

@ -0,0 +1,125 @@
var Util = require('util');
var EventEmitter = require('events').EventEmitter;
var Packets = require('../packets');
var ErrorConstants = require('../constants/errors');
var Timer = require('../Timer');
// istanbul ignore next: Node.js < 0.10 not covered
var listenerCount = EventEmitter.listenerCount
|| function(emitter, type){ return emitter.listeners(type).length; };
var LONG_STACK_DELIMITER = '\n --------------------\n';
module.exports = Sequence;
Util.inherits(Sequence, EventEmitter);
function Sequence(options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
EventEmitter.call(this);
options = options || {};
this._callback = callback;
this._callSite = null;
this._ended = false;
this._timeout = options.timeout;
this._timer = new Timer(this);
}
Sequence.determinePacket = function(byte) {
switch (byte) {
case 0x00: return Packets.OkPacket;
case 0xfe: return Packets.EofPacket;
case 0xff: return Packets.ErrorPacket;
default: return undefined;
}
};
Sequence.prototype.hasErrorHandler = function() {
return Boolean(this._callback) || listenerCount(this, 'error') > 1;
};
Sequence.prototype._packetToError = function(packet) {
var code = ErrorConstants[packet.errno] || 'UNKNOWN_CODE_PLEASE_REPORT';
var err = new Error(code + ': ' + packet.message);
err.code = code;
err.errno = packet.errno;
err.sqlMessage = packet.message;
err.sqlState = packet.sqlState;
return err;
};
Sequence.prototype.end = function(err) {
if (this._ended) {
return;
}
this._ended = true;
if (err) {
this._addLongStackTrace(err);
}
// Without this we are leaking memory. This problem was introduced in
// 8189925374e7ce3819bbe88b64c7b15abac96b16. I suspect that the error object
// causes a cyclic reference that the GC does not detect properly, but I was
// unable to produce a standalone version of this leak. This would be a great
// challenge for somebody interested in difficult problems : )!
this._callSite = null;
// try...finally for exception safety
try {
if (err) {
this.emit('error', err);
}
} finally {
try {
if (this._callback) {
this._callback.apply(this, arguments);
}
} finally {
this.emit('end');
}
}
};
Sequence.prototype['OkPacket'] = function(packet) {
this.end(null, packet);
};
Sequence.prototype['ErrorPacket'] = function(packet) {
this.end(this._packetToError(packet));
};
// Implemented by child classes
Sequence.prototype.start = function() {};
Sequence.prototype._addLongStackTrace = function _addLongStackTrace(err) {
var callSiteStack = this._callSite && this._callSite.stack;
if (!callSiteStack || typeof callSiteStack !== 'string') {
// No recorded call site
return;
}
if (err.stack.indexOf(LONG_STACK_DELIMITER) !== -1) {
// Error stack already looks long
return;
}
var index = callSiteStack.indexOf('\n');
if (index !== -1) {
// Append recorded call site
err.stack += LONG_STACK_DELIMITER + callSiteStack.substr(index + 1);
}
};
Sequence.prototype._onTimeout = function _onTimeout() {
this.emit('timeout');
};

View File

@ -0,0 +1,30 @@
var Sequence = require('./Sequence');
var Util = require('util');
var Packets = require('../packets');
module.exports = Statistics;
Util.inherits(Statistics, Sequence);
function Statistics(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
Sequence.call(this, options, callback);
}
Statistics.prototype.start = function() {
this.emit('packet', new Packets.ComStatisticsPacket());
};
Statistics.prototype['StatisticsPacket'] = function (packet) {
this.end(null, packet);
};
Statistics.prototype.determinePacket = function determinePacket(firstByte) {
if (firstByte === 0x55) {
return Packets.StatisticsPacket;
}
return undefined;
};

Some files were not shown because too many files have changed in this diff Show More