Version 1.0.2 mit node_modules Verzeichnis

This commit is contained in:
ISA
2024-10-02 07:58:24 +02:00
parent f353a06b1b
commit 62b6e55a0a
68228 changed files with 4548477 additions and 651 deletions

19
node_modules/mysql2/License generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) 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.

114
node_modules/mysql2/README.md generated vendored Normal file
View File

@@ -0,0 +1,114 @@
[npm-image]: https://img.shields.io/npm/v/mysql2.svg
[npm-url]: https://npmjs.com/package/mysql2
[node-version-image]: https://img.shields.io/node/v/mysql2.svg
[node-version-url]: https://nodejs.org/en/download
[downloads-image]: https://img.shields.io/npm/dm/mysql2.svg
[downloads-url]: https://npmjs.com/package/mysql2
[license-url]: https://github.com/sidorares/node-mysql2/blob/master/License
[license-image]: https://img.shields.io/npm/l/mysql2.svg?maxAge=2592000
[node-mysql]: https://github.com/mysqljs/mysql
[mysqljs]: https://github.com/mysqljs
[mysql-native]: https://github.com/sidorares/nodejs-mysql-native
[sidorares]: https://github.com/sidorares
[TooTallNate]: https://gist.github.com/TooTallNate
[starttls.js]: https://gist.github.com/TooTallNate/848444
[node-mariasql]: https://github.com/mscdex/node-mariasql
[contributors]: https://github.com/sidorares/node-mysql2/graphs/contributors
[contributing]: https://github.com/sidorares/node-mysql2/blob/master/Contributing.md
[docs-base]: https://sidorares.github.io/node-mysql2/docs
[docs-base-zh-CN]: https://sidorares.github.io/node-mysql2/zh-CN/docs
[docs-base-pt-BR]: https://sidorares.github.io/node-mysql2/pt-BR/docs
[docs-prepared-statements]: https://sidorares.github.io/node-mysql2/docs/documentation/prepared-statements
[docs-mysql-server]: https://sidorares.github.io/node-mysql2/docs/documentation/mysql-server
[docs-promise-wrapper]: https://sidorares.github.io/node-mysql2/docs/documentation/promise-wrapper
[docs-authentication-switch]: https://sidorares.github.io/node-mysql2/docs/documentation/authentication-switch
[docs-streams]: https://sidorares.github.io/node-mysql2/docs/documentation/extras
[docs-typescript-docs]: https://sidorares.github.io/node-mysql2/docs/documentation/typescript-examples
[docs-qs-pooling]: https://sidorares.github.io/node-mysql2/docs#using-connection-pools
[docs-qs-first-query]: https://sidorares.github.io/node-mysql2/docs#first-query
[docs-qs-using-prepared-statements]: https://sidorares.github.io/node-mysql2/docs#using-prepared-statements
[docs-examples]: https://sidorares.github.io/node-mysql2/docs/examples
[docs-faq]: https://sidorares.github.io/node-mysql2/docs/faq
[docs-documentation]: https://sidorares.github.io/node-mysql2/docs/documentation
[docs-contributing]: https://sidorares.github.io/node-mysql2/docs/contributing/website
[coverage]: https://img.shields.io/codecov/c/github/sidorares/node-mysql2
[coverage-url]: https://app.codecov.io/github/sidorares/node-mysql2
[ci-url]: https://github.com/sidorares/node-mysql2/actions/workflows/ci-coverage.yml?query=branch%3Amaster
[ci-image]: https://img.shields.io/github/actions/workflow/status/sidorares/node-mysql2/ci-coverage.yml?event=push&style=flat&label=CI&branch=master
# MySQL2
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![GitHub Workflow Status (with event)][ci-image]][ci-url]
[![Codecov][coverage]][coverage-url]
[![License][license-image]][license-url]
[English][docs-base] | [简体中文][docs-base-zh-CN] | [Português (BR)][docs-base-pt-BR]
> MySQL client for Node.js with focus on performance. Supports prepared statements, non-utf8 encodings, binary log protocol, compression, ssl [much more][docs-documentation].
**Table of Contents**
- [History and Why MySQL2](#history-and-why-mysql2)
- [Installation](#installation)
- [Documentation](#documentation)
- [Acknowledgements](#acknowledgements)
- [Contributing](#contributing)
## History and Why MySQL2
MySQL2 project is a continuation of [MySQL-Native][mysql-native]. Protocol parser code was rewritten from scratch and api changed to match popular [Node MySQL][node-mysql]. MySQL2 team is working together with [Node MySQL][node-mysql] team to factor out shared code and move it under [mysqljs][mysqljs] organization.
MySQL2 is mostly API compatible with [Node MySQL][node-mysql] and supports majority of features. MySQL2 also offers these additional features:
- Faster / Better Performance
- [Prepared Statements][docs-prepared-statements]
- MySQL Binary Log Protocol
- [MySQL Server][docs-mysql-server]
- Extended support for Encoding and Collation
- [Promise Wrapper][docs-promise-wrapper]
- Compression
- SSL and [Authentication Switch][docs-authentication-switch]
- [Custom Streams][docs-streams]
- [Pooling][docs-qs-pooling]
## Installation
MySQL2 is free from native bindings and can be installed on Linux, Mac OS or Windows without any issues.
```bash
npm install --save mysql2
```
If you are using TypeScript, you will need to install `@types/node`.
```bash
npm install --save-dev @types/node
```
> For TypeScript documentation and examples, see [here][docs-typescript-docs].
## Documentation
- [Quickstart][docs-base]
- [First Query][docs-qs-first-query], [Using Prepared Statements][docs-qs-using-prepared-statements], [Using Connection Pools][docs-qs-pooling] and more.
- [Documentation][docs-documentation]
- [Examples][docs-examples]
- [FAQ][docs-faq]
## Acknowledgements
- Internal protocol is written by [@sidorares][sidorares] [MySQL-Native][mysql-native].
- Constants, SQL parameters interpolation, Pooling, `ConnectionConfig` class taken from [Node MySQL][node-mysql].
- SSL upgrade code based on [@TooTallNate][TooTallNate] [code][starttls.js].
- Secure connection / compressed connection api flags compatible to [MariaSQL][node-mariasql] client.
- [Contributors][contributors].
## Contributing
Want to improve something in **MySQL2**?
Please check [Contributing.md][contributing] for detailed instruction on how to get started.
To contribute in **MySQL2 Documentation**, please visit the [Website Contributing Guidelines][docs-contributing] for detailed instruction on how to get started.

1
node_modules/mysql2/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export * from './typings/mysql/index.js';

83
node_modules/mysql2/index.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
'use strict';
const SqlString = require('sqlstring');
const Connection = require('./lib/connection.js');
const ConnectionConfig = require('./lib/connection_config.js');
const parserCache = require('./lib/parsers/parser_cache');
exports.createConnection = function(opts) {
return new Connection({ config: new ConnectionConfig(opts) });
};
exports.connect = exports.createConnection;
exports.Connection = Connection;
exports.ConnectionConfig = ConnectionConfig;
const Pool = require('./lib/pool.js');
const PoolCluster = require('./lib/pool_cluster.js');
exports.createPool = function(config) {
const PoolConfig = require('./lib/pool_config.js');
return new Pool({ config: new PoolConfig(config) });
};
exports.createPoolCluster = function(config) {
const PoolCluster = require('./lib/pool_cluster.js');
return new PoolCluster(config);
};
exports.createQuery = Connection.createQuery;
exports.Pool = Pool;
exports.PoolCluster = PoolCluster;
exports.createServer = function(handler) {
const Server = require('./lib/server.js');
const s = new Server();
if (handler) {
s.on('connection', handler);
}
return s;
};
exports.PoolConnection = require('./lib/pool_connection');
exports.authPlugins = require('./lib/auth_plugins');
exports.escape = SqlString.escape;
exports.escapeId = SqlString.escapeId;
exports.format = SqlString.format;
exports.raw = SqlString.raw;
exports.__defineGetter__(
'createConnectionPromise',
() => require('./promise.js').createConnection
);
exports.__defineGetter__(
'createPoolPromise',
() => require('./promise.js').createPool
);
exports.__defineGetter__(
'createPoolClusterPromise',
() => require('./promise.js').createPoolCluster
);
exports.__defineGetter__('Types', () => require('./lib/constants/types.js'));
exports.__defineGetter__('Charsets', () =>
require('./lib/constants/charsets.js')
);
exports.__defineGetter__('CharsetToEncoding', () =>
require('./lib/constants/charset_encodings.js')
);
exports.setMaxParserCache = function(max) {
parserCache.setMaxCache(max);
};
exports.clearParserCache = function() {
parserCache.clearCache();
};

95
node_modules/mysql2/lib/auth_41.js generated vendored Normal file
View File

@@ -0,0 +1,95 @@
'use strict';
/*
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
SERVER: public_seed=create_random_string()
send(public_seed)
CLIENT: recv(public_seed)
hash_stage1=sha1("password")
hash_stage2=sha1(hash_stage1)
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
// this three steps are done in scramble()
send(reply)
SERVER: recv(reply)
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
candidate_hash2=sha1(hash_stage1)
check(candidate_hash2==hash_stage2)
server stores sha1(sha1(password)) ( hash_stag2)
*/
const crypto = require('crypto');
function sha1(msg, msg1, msg2) {
const hash = crypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}
if (msg2) {
hash.update(msg2);
}
return hash.digest();
}
function xor(a, b) {
const result = Buffer.allocUnsafe(a.length);
for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ b[i];
}
return result;
}
exports.xor = xor;
function token(password, scramble1, scramble2) {
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha1(password);
return exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
}
exports.calculateTokenFromPasswordSha = function(
passwordSha,
scramble1,
scramble2
) {
// we use AUTH 41 here, and we need only the bytes we just need.
const authPluginData1 = scramble1.slice(0, 8);
const authPluginData2 = scramble2.slice(0, 12);
const stage2 = sha1(passwordSha);
const stage3 = sha1(authPluginData1, authPluginData2, stage2);
return xor(stage3, passwordSha);
};
exports.calculateToken = token;
exports.verifyToken = function(publicSeed1, publicSeed2, token, doubleSha) {
const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
const candidateHash2 = sha1(hashStage1);
return candidateHash2.compare(doubleSha) === 0;
};
exports.doubleSha1 = function(password) {
return sha1(sha1(password));
};
function xorRotating(a, seed) {
const result = Buffer.allocUnsafe(a.length);
const seedLen = seed.length;
for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ seed[i % seedLen];
}
return result;
}
exports.xorRotating = xorRotating;

View File

@@ -0,0 +1,106 @@
'use strict';
// https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/
const PLUGIN_NAME = 'caching_sha2_password';
const crypto = require('crypto');
const { xor, xorRotating } = require('../auth_41');
const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
const FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
const PERFORM_FULL_AUTHENTICATION_PACKET = Buffer.from([4]);
const STATE_INITIAL = 0;
const STATE_TOKEN_SENT = 1;
const STATE_WAIT_SERVER_KEY = 2;
const STATE_FINAL = -1;
function sha256(msg) {
const hash = crypto.createHash('sha256');
hash.update(msg);
return hash.digest();
}
function calculateToken(password, scramble) {
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha256(Buffer.from(password));
const stage2 = sha256(stage1);
const stage3 = sha256(Buffer.concat([stage2, scramble]));
return xor(stage1, stage3);
}
function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return crypto.publicEncrypt({
key,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
}, stage1);
}
module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;
const password = connection.config.password;
const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
return data => {
switch (state) {
case STATE_INITIAL:
scramble = data.slice(0, 20);
state = STATE_TOKEN_SENT;
return calculateToken(password, scramble);
case STATE_TOKEN_SENT:
if (FAST_AUTH_SUCCESS_PACKET.equals(data)) {
state = STATE_FINAL;
return null;
}
if (PERFORM_FULL_AUTHENTICATION_PACKET.equals(data)) {
const isSecureConnection =
typeof pluginOptions.overrideIsSecure === 'undefined'
? connection.config.ssl || connection.config.socketPath
: pluginOptions.overrideIsSecure;
if (isSecureConnection) {
state = STATE_FINAL;
return Buffer.from(`${password}\0`, 'utf8');
}
// if client provides key we can save one extra roundrip on first connection
if (pluginOptions.serverPublicKey) {
return authWithKey(pluginOptions.serverPublicKey);
}
state = STATE_WAIT_SERVER_KEY;
return REQUEST_SERVER_KEY_PACKET;
}
throw new Error(
`Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.`
);
case STATE_WAIT_SERVER_KEY:
if (pluginOptions.onServerPublicKey) {
pluginOptions.onServerPublicKey(data);
}
return authWithKey(data);
case STATE_FINAL:
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
);
}
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
);
};
};

View File

@@ -0,0 +1,18 @@
##
https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html
```js
const mysql = require('mysql');
mysql.createConnection({
authPlugins: {
caching_sha2_password: mysql.authPlugins.caching_sha2_password({
onServerPublikKey: function(key) {
console.log(key);
},
serverPublicKey: 'xxxyyy',
overrideIsSecure: true //
})
}
});
```

8
node_modules/mysql2/lib/auth_plugins/index.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
module.exports = {
caching_sha2_password: require('./caching_sha2_password'),
mysql_clear_password: require('./mysql_clear_password'),
mysql_native_password: require('./mysql_native_password'),
sha256_password: require('./sha256_password'),
};

View File

@@ -0,0 +1,17 @@
'use strict';
function bufferFromStr(str) {
return Buffer.from(`${str}\0`);
}
const create_mysql_clear_password_plugin = pluginOptions =>
function mysql_clear_password_plugin({ connection, command }) {
const password =
command.password || pluginOptions.password || connection.config.password;
return function (/* pluginData */) {
return bufferFromStr(password);
};
};
module.exports = create_mysql_clear_password_plugin;

View File

@@ -0,0 +1,32 @@
'use strict';
//const PLUGIN_NAME = 'mysql_native_password';
const auth41 = require('../auth_41.js');
module.exports = pluginOptions => ({ connection, command }) => {
const password =
command.password || pluginOptions.password || connection.config.password;
const passwordSha1 =
command.passwordSha1 ||
pluginOptions.passwordSha1 ||
connection.config.passwordSha1;
return data => {
const authPluginData1 = data.slice(0, 8);
const authPluginData2 = data.slice(8, 20);
let authToken;
if (passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
passwordSha1,
authPluginData1,
authPluginData2
);
} else {
authToken = auth41.calculateToken(
password,
authPluginData1,
authPluginData2
);
}
return authToken;
};
};

View File

@@ -0,0 +1,60 @@
'use strict';
const PLUGIN_NAME = 'sha256_password';
const crypto = require('crypto');
const { xorRotating } = require('../auth_41');
const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);
const STATE_INITIAL = 0;
const STATE_WAIT_SERVER_KEY = 1;
const STATE_FINAL = -1;
function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return crypto.publicEncrypt(key, stage1);
}
module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;
const password = connection.config.password;
const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
return data => {
switch (state) {
case STATE_INITIAL:
scramble = data.slice(0, 20);
// if client provides key we can save one extra roundrip on first connection
if (pluginOptions.serverPublicKey) {
return authWithKey(pluginOptions.serverPublicKey);
}
state = STATE_WAIT_SERVER_KEY;
return REQUEST_SERVER_KEY_PACKET;
case STATE_WAIT_SERVER_KEY:
if (pluginOptions.onServerPublicKey) {
pluginOptions.onServerPublicKey(data);
}
return authWithKey(data);
case STATE_FINAL:
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
);
}
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
);
};
};

108
node_modules/mysql2/lib/commands/auth_switch.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
// This file was modified by Oracle on July 5, 2021.
// Errors generated by asynchronous authentication plugins are now being
// handled and subsequently emitted at the command level.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const Packets = require('../packets/index.js');
const sha256_password = require('../auth_plugins/sha256_password');
const caching_sha2_password = require('../auth_plugins/caching_sha2_password.js');
const mysql_native_password = require('../auth_plugins/mysql_native_password.js');
const mysql_clear_password = require('../auth_plugins/mysql_clear_password.js');
const standardAuthPlugins = {
sha256_password: sha256_password({}),
caching_sha2_password: caching_sha2_password({}),
mysql_native_password: mysql_native_password({}),
mysql_clear_password: mysql_clear_password({})
};
function warnLegacyAuthSwitch() {
console.warn(
'WARNING! authSwitchHandler api is deprecated, please use new authPlugins api'
);
}
function authSwitchPluginError(error, command) {
// Authentication errors are fatal
error.code = 'AUTH_SWITCH_PLUGIN_ERROR';
error.fatal = true;
command.emit('error', error);
}
function authSwitchRequest(packet, connection, command) {
const { pluginName, pluginData } = Packets.AuthSwitchRequest.fromPacket(
packet
);
let authPlugin =
connection.config.authPlugins && connection.config.authPlugins[pluginName];
// legacy plugin api don't allow to override mysql_native_password
// if pluginName is mysql_native_password it's using standard auth4.1 auth
if (
connection.config.authSwitchHandler &&
pluginName !== 'mysql_native_password'
) {
const legacySwitchHandler = connection.config.authSwitchHandler;
warnLegacyAuthSwitch();
legacySwitchHandler({ pluginName, pluginData }, (err, data) => {
if (err) {
return authSwitchPluginError(err, command);
}
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
});
return;
}
if (!authPlugin) {
authPlugin = standardAuthPlugins[pluginName];
}
if (!authPlugin) {
throw new Error(
`Server requests authentication using unknown plugin ${pluginName}. See ${'TODO: add plugins doco here'} on how to configure or author authentication plugins.`
);
}
connection._authPlugin = authPlugin({ connection, command });
Promise.resolve(connection._authPlugin(pluginData)).then(data => {
if (data) {
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
}
}).catch(err => {
authSwitchPluginError(err, command);
});
}
function authSwitchRequestMoreData(packet, connection, command) {
const { data } = Packets.AuthSwitchRequestMoreData.fromPacket(packet);
if (connection.config.authSwitchHandler) {
const legacySwitchHandler = connection.config.authSwitchHandler;
warnLegacyAuthSwitch();
legacySwitchHandler({ pluginData: data }, (err, data) => {
if (err) {
return authSwitchPluginError(err, command);
}
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
});
return;
}
if (!connection._authPlugin) {
throw new Error(
'AuthPluginMoreData received but no auth plugin instance found'
);
}
Promise.resolve(connection._authPlugin(data)).then(data => {
if (data) {
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
}
}).catch(err => {
authSwitchPluginError(err, command);
});
}
module.exports = {
authSwitchRequest,
authSwitchRequestMoreData
};

109
node_modules/mysql2/lib/commands/binlog_dump.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets');
const eventParsers = [];
class BinlogEventHeader {
constructor(packet) {
this.timestamp = packet.readInt32();
this.eventType = packet.readInt8();
this.serverId = packet.readInt32();
this.eventSize = packet.readInt32();
this.logPos = packet.readInt32();
this.flags = packet.readInt16();
}
}
class BinlogDump extends Command {
constructor(opts) {
super();
// this.onResult = callback;
this.opts = opts;
}
start(packet, connection) {
const newPacket = new Packets.BinlogDump(this.opts);
connection.writePacket(newPacket.toPacket(1));
return BinlogDump.prototype.binlogData;
}
binlogData(packet) {
// ok - continue consuming events
// error - error
// eof - end of binlog
if (packet.isEOF()) {
this.emit('eof');
return null;
}
// binlog event header
packet.readInt8();
const header = new BinlogEventHeader(packet);
const EventParser = eventParsers[header.eventType];
let event;
if (EventParser) {
event = new EventParser(packet);
} else {
event = {
name: 'UNKNOWN'
};
}
event.header = header;
this.emit('event', event);
return BinlogDump.prototype.binlogData;
}
}
class RotateEvent {
constructor(packet) {
this.pposition = packet.readInt32();
// TODO: read uint64 here
packet.readInt32(); // positionDword2
this.nextBinlog = packet.readString();
this.name = 'RotateEvent';
}
}
class FormatDescriptionEvent {
constructor(packet) {
this.binlogVersion = packet.readInt16();
this.serverVersion = packet.readString(50).replace(/\u0000.*/, ''); // eslint-disable-line no-control-regex
this.createTimestamp = packet.readInt32();
this.eventHeaderLength = packet.readInt8(); // should be 19
this.eventsLength = packet.readBuffer();
this.name = 'FormatDescriptionEvent';
}
}
class QueryEvent {
constructor(packet) {
const parseStatusVars = require('../packets/binlog_query_statusvars.js');
this.slaveProxyId = packet.readInt32();
this.executionTime = packet.readInt32();
const schemaLength = packet.readInt8();
this.errorCode = packet.readInt16();
const statusVarsLength = packet.readInt16();
const statusVars = packet.readBuffer(statusVarsLength);
this.schema = packet.readString(schemaLength);
packet.readInt8(); // should be zero
this.statusVars = parseStatusVars(statusVars);
this.query = packet.readString();
this.name = 'QueryEvent';
}
}
class XidEvent {
constructor(packet) {
this.binlogVersion = packet.readInt16();
this.xid = packet.readInt64();
this.name = 'XidEvent';
}
}
eventParsers[2] = QueryEvent;
eventParsers[4] = RotateEvent;
eventParsers[15] = FormatDescriptionEvent;
eventParsers[16] = XidEvent;
module.exports = BinlogDump;

66
node_modules/mysql2/lib/commands/change_user.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
// This file was modified by Oracle on September 21, 2021.
// The changes involve saving additional authentication factor passwords
// in the command scope and enabling multi-factor authentication in the
// client-side when the server supports it.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const ClientConstants = require('../constants/client');
const ClientHandshake = require('./client_handshake.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class ChangeUser extends Command {
constructor(options, callback) {
super();
this.onResult = callback;
this.user = options.user;
this.password = options.password;
// "password1" is an alias of "password"
this.password1 = options.password;
this.password2 = options.password2;
this.password3 = options.password3;
this.database = options.database;
this.passwordSha1 = options.passwordSha1;
this.charsetNumber = options.charsetNumber;
this.currentConfig = options.currentConfig;
this.authenticationFactor = 0;
}
start(packet, connection) {
const newPacket = new Packets.ChangeUser({
flags: connection.config.clientFlags,
user: this.user,
database: this.database,
charsetNumber: this.charsetNumber,
password: this.password,
passwordSha1: this.passwordSha1,
authPluginData1: connection._handshakePacket.authPluginData1,
authPluginData2: connection._handshakePacket.authPluginData2
});
this.currentConfig.user = this.user;
this.currentConfig.password = this.password;
this.currentConfig.database = this.database;
this.currentConfig.charsetNumber = this.charsetNumber;
connection.clientEncoding = CharsetToEncoding[this.charsetNumber];
// clear prepared statements cache as all statements become invalid after changeUser
connection._statements.clear();
connection.writePacket(newPacket.toPacket());
// check if the server supports multi-factor authentication
const multiFactorAuthentication = connection.serverCapabilityFlags & ClientConstants.MULTI_FACTOR_AUTHENTICATION;
if (multiFactorAuthentication) {
// if the server supports multi-factor authentication, we enable it in
// the client
this.authenticationFactor = 1;
}
return ChangeUser.prototype.handshakeResult;
}
}
ChangeUser.prototype.handshakeResult =
ClientHandshake.prototype.handshakeResult;
ChangeUser.prototype.calculateNativePasswordAuthToken =
ClientHandshake.prototype.calculateNativePasswordAuthToken;
module.exports = ChangeUser;

239
node_modules/mysql2/lib/commands/client_handshake.js generated vendored Normal file
View File

@@ -0,0 +1,239 @@
// This file was modified by Oracle on June 17, 2021.
// Handshake errors are now maked as fatal and the corresponding events are
// emitted in the command instance itself.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// This file was modified by Oracle on September 21, 2021.
// Handshake workflow now supports additional authentication factors requested
// by the server.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const auth41 = require('../auth_41.js');
function flagNames(flags) {
const res = [];
for (const c in ClientConstants) {
if (flags & ClientConstants[c]) {
res.push(c.replace(/_/g, ' ').toLowerCase());
}
}
return res;
}
class ClientHandshake extends Command {
constructor(clientFlags) {
super();
this.handshake = null;
this.clientFlags = clientFlags;
this.authenticationFactor = 0;
}
start() {
return ClientHandshake.prototype.handshakeInit;
}
sendSSLRequest(connection) {
const sslRequest = new Packets.SSLRequest(
this.clientFlags,
connection.config.charsetNumber
);
connection.writePacket(sslRequest.toPacket());
}
sendCredentials(connection) {
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
'Sending handshake packet: flags:%d=(%s)',
this.clientFlags,
flagNames(this.clientFlags).join(', ')
);
}
this.user = connection.config.user;
this.password = connection.config.password;
// "password1" is an alias to the original "password" value
// to make it easier to integrate multi-factor authentication
this.password1 = connection.config.password;
// "password2" and "password3" are the 2nd and 3rd factor authentication
// passwords, which can be undefined depending on the authentication
// plugin being used
this.password2 = connection.config.password2;
this.password3 = connection.config.password3;
this.passwordSha1 = connection.config.passwordSha1;
this.database = connection.config.database;
this.autPluginName = this.handshake.autPluginName;
const handshakeResponse = new Packets.HandshakeResponse({
flags: this.clientFlags,
user: this.user,
database: this.database,
password: this.password,
passwordSha1: this.passwordSha1,
charsetNumber: connection.config.charsetNumber,
authPluginData1: this.handshake.authPluginData1,
authPluginData2: this.handshake.authPluginData2,
compress: connection.config.compress,
connectAttributes: connection.config.connectAttributes
});
connection.writePacket(handshakeResponse.toPacket());
}
calculateNativePasswordAuthToken(authPluginData) {
// TODO: dont split into authPluginData1 and authPluginData2, instead join when 1 & 2 received
const authPluginData1 = authPluginData.slice(0, 8);
const authPluginData2 = authPluginData.slice(8, 20);
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
authPluginData1,
authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
authPluginData1,
authPluginData2
);
}
return authToken;
}
handshakeInit(helloPacket, connection) {
this.on('error', e => {
connection._fatalError = e;
connection._protocolError = e;
});
this.handshake = Packets.Handshake.fromPacket(helloPacket);
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
'Server hello packet: capability flags:%d=(%s)',
this.handshake.capabilityFlags,
flagNames(this.handshake.capabilityFlags).join(', ')
);
}
connection.serverCapabilityFlags = this.handshake.capabilityFlags;
connection.serverEncoding = CharsetToEncoding[this.handshake.characterSet];
connection.connectionId = this.handshake.connectionId;
const serverSSLSupport =
this.handshake.capabilityFlags & ClientConstants.SSL;
// multi factor authentication is enabled with the
// "MULTI_FACTOR_AUTHENTICATION" capability and should only be used if it
// is supported by the server
const multiFactorAuthentication =
this.handshake.capabilityFlags & ClientConstants.MULTI_FACTOR_AUTHENTICATION;
this.clientFlags = this.clientFlags | multiFactorAuthentication;
// use compression only if requested by client and supported by server
connection.config.compress =
connection.config.compress &&
this.handshake.capabilityFlags & ClientConstants.COMPRESS;
this.clientFlags = this.clientFlags | connection.config.compress;
if (connection.config.ssl) {
// client requires SSL but server does not support it
if (!serverSSLSupport) {
const err = new Error('Server does not support secure connection');
err.code = 'HANDSHAKE_NO_SSL_SUPPORT';
err.fatal = true;
this.emit('error', err);
return false;
}
// send ssl upgrade request and immediately upgrade connection to secure
this.clientFlags |= ClientConstants.SSL;
this.sendSSLRequest(connection);
connection.startTLS(err => {
// after connection is secure
if (err) {
// SSL negotiation error are fatal
err.code = 'HANDSHAKE_SSL_ERROR';
err.fatal = true;
this.emit('error', err);
return;
}
// rest of communication is encrypted
this.sendCredentials(connection);
});
} else {
this.sendCredentials(connection);
}
if (multiFactorAuthentication) {
// if the server supports multi-factor authentication, we enable it in
// the client
this.authenticationFactor = 1;
}
return ClientHandshake.prototype.handshakeResult;
}
handshakeResult(packet, connection) {
const marker = packet.peekByte();
// packet can be OK_Packet, ERR_Packet, AuthSwitchRequest, AuthNextFactor
// or AuthMoreData
if (marker === 0xfe || marker === 1 || marker === 0x02) {
const authSwitch = require('./auth_switch');
try {
if (marker === 1) {
authSwitch.authSwitchRequestMoreData(packet, connection, this);
} else {
// if authenticationFactor === 0, it means the server does not support
// the multi-factor authentication capability
if (this.authenticationFactor !== 0) {
// if we are past the first authentication factor, we should use the
// corresponding password (if there is one)
connection.config.password = this[`password${this.authenticationFactor}`];
// update the current authentication factor
this.authenticationFactor += 1;
}
// if marker === 0x02, it means it is an AuthNextFactor packet,
// which is similar in structure to an AuthSwitchRequest packet,
// so, we can use it directly
authSwitch.authSwitchRequest(packet, connection, this);
}
return ClientHandshake.prototype.handshakeResult;
} catch (err) {
// Authentication errors are fatal
err.code = 'AUTH_SWITCH_PLUGIN_ERROR';
err.fatal = true;
if (this.onResult) {
this.onResult(err);
} else {
this.emit('error', err);
}
return null;
}
}
if (marker !== 0) {
const err = new Error('Unexpected packet during handshake phase');
// Unknown handshake errors are fatal
err.code = 'HANDSHAKE_UNKNOWN_ERROR';
err.fatal = true;
if (this.onResult) {
this.onResult(err);
} else {
this.emit('error', err);
}
return null;
}
// this should be called from ClientHandshake command only
// and skipped when called from ChangeUser command
if (!connection.authorized) {
connection.authorized = true;
if (connection.config.compress) {
const enableCompression = require('../compressed_protocol.js')
.enableCompression;
enableCompression(connection);
}
}
if (this.onResult) {
this.onResult(null);
}
return null;
}
}
module.exports = ClientHandshake;

18
node_modules/mysql2/lib/commands/close_statement.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets/index.js');
class CloseStatement extends Command {
constructor(id) {
super();
this.id = id;
}
start(packet, connection) {
connection.writePacket(new Packets.CloseStatement(this.id).toPacket(1));
return null;
}
}
module.exports = CloseStatement;

55
node_modules/mysql2/lib/commands/command.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict';
const EventEmitter = require('events').EventEmitter;
const Timers = require('timers');
class Command extends EventEmitter {
constructor() {
super();
this.next = null;
}
// slow. debug only
stateName() {
const state = this.next;
for (const i in this) {
if (this[i] === state && i !== 'next') {
return i;
}
}
return 'unknown name';
}
execute(packet, connection) {
if (!this.next) {
this.next = this.start;
connection._resetSequenceId();
}
if (packet && packet.isError()) {
const err = packet.asError(connection.clientEncoding);
err.sql = this.sql || this.query;
if (this.queryTimeout) {
Timers.clearTimeout(this.queryTimeout);
this.queryTimeout = null;
}
if (this.onResult) {
this.onResult(err);
this.emit('end');
} else {
this.emit('error', err);
this.emit('end');
}
return true;
}
// TODO: don't return anything from execute, it's ugly and error-prone. Listen for 'end' event in connection
this.next = this.next(packet, connection);
if (this.next) {
return false;
}
this.emit('end');
return true;
}
}
module.exports = Command;

107
node_modules/mysql2/lib/commands/execute.js generated vendored Normal file
View File

@@ -0,0 +1,107 @@
'use strict';
const Command = require('./command.js');
const Query = require('./query.js');
const Packets = require('../packets/index.js');
const getBinaryParser = require('../parsers/binary_parser.js');
class Execute extends Command {
constructor(options, callback) {
super();
this.statement = options.statement;
this.sql = options.sql;
this.values = options.values;
this.onResult = callback;
this.parameters = options.values;
this.insertId = 0;
this.timeout = options.timeout;
this.queryTimeout = null;
this._rows = [];
this._fields = [];
this._result = [];
this._fieldCount = 0;
this._rowParser = null;
this._executeOptions = options;
this._resultIndex = 0;
this._localStream = null;
this._unpipeStream = function() {};
this._streamFactory = options.infileStreamFactory;
this._connection = null;
}
buildParserFromFields(fields, connection) {
return getBinaryParser(fields, this.options, connection.config);
}
start(packet, connection) {
this._connection = connection;
this.options = Object.assign({}, connection.config, this._executeOptions);
this._setTimeout();
const executePacket = new Packets.Execute(
this.statement.id,
this.parameters,
connection.config.charsetNumber,
connection.config.timezone
);
//For reasons why this try-catch is here, please see
// https://github.com/sidorares/node-mysql2/pull/689
//For additional discussion, see
// 1. https://github.com/sidorares/node-mysql2/issues/493
// 2. https://github.com/sidorares/node-mysql2/issues/187
// 3. https://github.com/sidorares/node-mysql2/issues/480
try {
connection.writePacket(executePacket.toPacket(1));
} catch (error) {
this.onResult(error);
}
return Execute.prototype.resultsetHeader;
}
readField(packet, connection) {
let fields;
// disabling for now, but would be great to find reliable way to parse fields only once
// fields reported by prepare can be empty at all or just incorrect - see #169
//
// perfomance optimisation: if we already have this field parsed in statement header, use one from header
// const field = this.statement.columns.length == this._fieldCount ?
// this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
const field = new Packets.ColumnDefinition(
packet,
connection.clientEncoding
);
this._receivedFieldsCount++;
this._fields[this._resultIndex].push(field);
if (this._receivedFieldsCount === this._fieldCount) {
fields = this._fields[this._resultIndex];
this.emit('fields', fields, this._resultIndex);
return Execute.prototype.fieldsEOF;
}
return Execute.prototype.readField;
}
fieldsEOF(packet, connection) {
// check EOF
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet');
}
this._rowParser = new (this.buildParserFromFields(
this._fields[this._resultIndex],
connection
))();
return Execute.prototype.row;
}
}
Execute.prototype.done = Query.prototype.done;
Execute.prototype.doneInsert = Query.prototype.doneInsert;
Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
Execute.prototype._findOrCreateReadStream =
Query.prototype._findOrCreateReadStream;
Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
Execute.prototype._setTimeout = Query.prototype._setTimeout;
Execute.prototype._handleTimeoutError = Query.prototype._handleTimeoutError;
Execute.prototype.row = Query.prototype.row;
Execute.prototype.stream = Query.prototype.stream;
module.exports = Execute;

27
node_modules/mysql2/lib/commands/index.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
const ClientHandshake = require('./client_handshake.js');
const ServerHandshake = require('./server_handshake.js');
const Query = require('./query.js');
const Prepare = require('./prepare.js');
const CloseStatement = require('./close_statement.js');
const Execute = require('./execute.js');
const Ping = require('./ping.js');
const RegisterSlave = require('./register_slave.js');
const BinlogDump = require('./binlog_dump.js');
const ChangeUser = require('./change_user.js');
const Quit = require('./quit.js');
module.exports = {
ClientHandshake,
ServerHandshake,
Query,
Prepare,
CloseStatement,
Execute,
Ping,
RegisterSlave,
BinlogDump,
ChangeUser,
Quit
};

36
node_modules/mysql2/lib/commands/ping.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict';
const Command = require('./command');
const CommandCode = require('../constants/commands');
const Packet = require('../packets/packet');
// TODO: time statistics?
// usefull for queue size and network latency monitoring
// store created,sent,reply timestamps
class Ping extends Command {
constructor(callback) {
super();
this.onResult = callback;
}
start(packet, connection) {
const ping = new Packet(
0,
Buffer.from([1, 0, 0, 0, CommandCode.PING]),
0,
5
);
connection.writePacket(ping);
return Ping.prototype.pingResponse;
}
pingResponse() {
// TODO: check it's OK packet. error check already done in caller
if (this.onResult) {
process.nextTick(this.onResult.bind(this));
}
return null;
}
}
module.exports = Ping;

143
node_modules/mysql2/lib/commands/prepare.js generated vendored Normal file
View File

@@ -0,0 +1,143 @@
'use strict';
const Packets = require('../packets/index.js');
const Command = require('./command.js');
const CloseStatement = require('./close_statement.js');
const Execute = require('./execute.js');
class PreparedStatementInfo {
constructor(query, id, columns, parameters, connection) {
this.query = query;
this.id = id;
this.columns = columns;
this.parameters = parameters;
this.rowParser = null;
this._connection = connection;
}
close() {
return this._connection.addCommand(new CloseStatement(this.id));
}
execute(parameters, callback) {
if (typeof parameters === 'function') {
callback = parameters;
parameters = [];
}
return this._connection.addCommand(
new Execute({ statement: this, values: parameters }, callback)
);
}
}
class Prepare extends Command {
constructor(options, callback) {
super();
this.query = options.sql;
this.onResult = callback;
this.id = 0;
this.fieldCount = 0;
this.parameterCount = 0;
this.fields = [];
this.parameterDefinitions = [];
this.options = options;
}
start(packet, connection) {
const Connection = connection.constructor;
this.key = Connection.statementKey(this.options);
const statement = connection._statements.get(this.key);
if (statement) {
if (this.onResult) {
this.onResult(null, statement);
}
return null;
}
const cmdPacket = new Packets.PrepareStatement(
this.query,
connection.config.charsetNumber,
this.options.values
);
connection.writePacket(cmdPacket.toPacket(1));
return Prepare.prototype.prepareHeader;
}
prepareHeader(packet, connection) {
const header = new Packets.PreparedStatementHeader(packet);
this.id = header.id;
this.fieldCount = header.fieldCount;
this.parameterCount = header.parameterCount;
if (this.parameterCount > 0) {
return Prepare.prototype.readParameter;
} if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(connection);
}
readParameter(packet, connection) {
// there might be scenarios when mysql server reports more parameters than
// are actually present in the array of parameter definitions.
// if EOF packet is received we switch to "read fields" state if there are
// any fields reported by the server, otherwise we finish the command.
if (packet.isEOF()) {
if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(connection);
}
const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
this.parameterDefinitions.push(def);
if (this.parameterDefinitions.length === this.parameterCount) {
return Prepare.prototype.parametersEOF;
}
return this.readParameter;
}
readField(packet, connection) {
if (packet.isEOF()) {
return this.prepareDone(connection);
}
const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
this.fields.push(def);
if (this.fields.length === this.fieldCount) {
return Prepare.prototype.fieldsEOF;
}
return Prepare.prototype.readField;
}
parametersEOF(packet, connection) {
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet after parameters');
}
if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(connection);
}
fieldsEOF(packet, connection) {
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet after fields');
}
return this.prepareDone(connection);
}
prepareDone(connection) {
const statement = new PreparedStatementInfo(
this.query,
this.id,
this.fields,
this.parameterDefinitions,
connection
);
connection._statements.set(this.key, statement);
if (this.onResult) {
this.onResult(null, statement);
}
return null;
}
}
module.exports = Prepare;

323
node_modules/mysql2/lib/commands/query.js generated vendored Normal file
View File

@@ -0,0 +1,323 @@
'use strict';
const process = require('process');
const Timers = require('timers');
const Readable = require('stream').Readable;
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const getTextParser = require('../parsers/text_parser.js');
const ServerStatus = require('../constants/server_status.js');
const EmptyPacket = new Packets.Packet(0, Buffer.allocUnsafe(4), 0, 4);
// http://dev.mysql.com/doc/internals/en/com-query.html
class Query extends Command {
constructor(options, callback) {
super();
this.sql = options.sql;
this.values = options.values;
this._queryOptions = options;
this.namedPlaceholders = options.namedPlaceholders || false;
this.onResult = callback;
this.timeout = options.timeout;
this.queryTimeout = null;
this._fieldCount = 0;
this._rowParser = null;
this._fields = [];
this._rows = [];
this._receivedFieldsCount = 0;
this._resultIndex = 0;
this._localStream = null;
this._unpipeStream = function () { };
this._streamFactory = options.infileStreamFactory;
this._connection = null;
}
then() {
const err =
"You have tried to call .then(), .catch(), or invoked await on the result of query that is not a promise, which is a programming error. Try calling con.promise().query(), or require('mysql2/promise') instead of 'mysql2' for a promise-compatible version of the query interface. To learn how to use async/await or Promises check out documentation at https://sidorares.github.io/node-mysql2/docs#using-promise-wrapper, or the mysql2 documentation at https://sidorares.github.io/node-mysql2/docs/documentation/promise-wrapper";
// eslint-disable-next-line
console.log(err);
throw new Error(err);
}
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
start(_packet, connection) {
if (connection.config.debug) {
// eslint-disable-next-line
console.log(' Sending query command: %s', this.sql);
}
this._connection = connection;
this.options = Object.assign({}, connection.config, this._queryOptions);
this._setTimeout();
const cmdPacket = new Packets.Query(
this.sql,
connection.config.charsetNumber
);
connection.writePacket(cmdPacket.toPacket(1));
return Query.prototype.resultsetHeader;
}
done() {
this._unpipeStream();
// if all ready timeout, return null directly
if (this.timeout && !this.queryTimeout) {
return null;
}
// else clear timer
if (this.queryTimeout) {
Timers.clearTimeout(this.queryTimeout);
this.queryTimeout = null;
}
if (this.onResult) {
let rows, fields;
if (this._resultIndex === 0) {
rows = this._rows[0];
fields = this._fields[0];
} else {
rows = this._rows;
fields = this._fields;
}
if (fields) {
process.nextTick(() => {
this.onResult(null, rows, fields);
});
} else {
process.nextTick(() => {
this.onResult(null, rows);
});
}
}
return null;
}
doneInsert(rs) {
if (this._localStreamError) {
if (this.onResult) {
this.onResult(this._localStreamError, rs);
} else {
this.emit('error', this._localStreamError);
}
return null;
}
this._rows.push(rs);
this._fields.push(void 0);
this.emit('fields', void 0);
this.emit('result', rs);
if (rs.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
this._resultIndex++;
return this.resultsetHeader;
}
return this.done();
}
resultsetHeader(packet, connection) {
const rs = new Packets.ResultSetHeader(packet, connection);
this._fieldCount = rs.fieldCount;
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
` Resultset header received, expecting ${rs.fieldCount} column definition packets`
);
}
if (this._fieldCount === 0) {
return this.doneInsert(rs);
}
if (this._fieldCount === null) {
return this._streamLocalInfile(connection, rs.infileName);
}
this._receivedFieldsCount = 0;
this._rows.push([]);
this._fields.push([]);
return this.readField;
}
_streamLocalInfile(connection, path) {
if (this._streamFactory) {
this._localStream = this._streamFactory(path);
} else {
this._localStreamError = new Error(
`As a result of LOCAL INFILE command server wants to read ${path} file, but as of v2.0 you must provide streamFactory option returning ReadStream.`
);
connection.writePacket(EmptyPacket);
return this.infileOk;
}
const onConnectionError = () => {
this._unpipeStream();
};
const onDrain = () => {
this._localStream.resume();
};
const onPause = () => {
this._localStream.pause();
};
const onData = function (data) {
const dataWithHeader = Buffer.allocUnsafe(data.length + 4);
data.copy(dataWithHeader, 4);
connection.writePacket(
new Packets.Packet(0, dataWithHeader, 0, dataWithHeader.length)
);
};
const onEnd = () => {
connection.removeListener('error', onConnectionError);
connection.writePacket(EmptyPacket);
};
const onError = err => {
this._localStreamError = err;
connection.removeListener('error', onConnectionError);
connection.writePacket(EmptyPacket);
};
this._unpipeStream = () => {
connection.stream.removeListener('pause', onPause);
connection.stream.removeListener('drain', onDrain);
this._localStream.removeListener('data', onData);
this._localStream.removeListener('end', onEnd);
this._localStream.removeListener('error', onError);
};
connection.stream.on('pause', onPause);
connection.stream.on('drain', onDrain);
this._localStream.on('data', onData);
this._localStream.on('end', onEnd);
this._localStream.on('error', onError);
connection.once('error', onConnectionError);
return this.infileOk;
}
readField(packet, connection) {
this._receivedFieldsCount++;
// Often there is much more data in the column definition than in the row itself
// If you set manually _fields[0] to array of ColumnDefinition's (from previous call)
// you can 'cache' result of parsing. Field packets still received, but ignored in that case
// this is the reason _receivedFieldsCount exist (otherwise we could just use current length of fields array)
if (this._fields[this._resultIndex].length !== this._fieldCount) {
const field = new Packets.ColumnDefinition(
packet,
connection.clientEncoding
);
this._fields[this._resultIndex].push(field);
if (connection.config.debug) {
/* eslint-disable no-console */
console.log(' Column definition:');
console.log(` name: ${field.name}`);
console.log(` type: ${field.columnType}`);
console.log(` flags: ${field.flags}`);
/* eslint-enable no-console */
}
}
// last field received
if (this._receivedFieldsCount === this._fieldCount) {
const fields = this._fields[this._resultIndex];
this.emit('fields', fields);
this._rowParser = new (getTextParser(fields, this.options, connection.config))(fields);
return Query.prototype.fieldsEOF;
}
return Query.prototype.readField;
}
fieldsEOF(packet, connection) {
// check EOF
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet');
}
return this.row;
}
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
row(packet, _connection) {
if (packet.isEOF()) {
const status = packet.eofStatusFlags();
const moreResults = status & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
if (moreResults) {
this._resultIndex++;
return Query.prototype.resultsetHeader;
}
return this.done();
}
let row;
try {
row = this._rowParser.next(
packet,
this._fields[this._resultIndex],
this.options
);
} catch (err) {
this._localStreamError = err;
return this.doneInsert(null);
}
if (this.onResult) {
this._rows[this._resultIndex].push(row);
} else {
this.emit('result', row, this._resultIndex);
}
return Query.prototype.row;
}
infileOk(packet, connection) {
const rs = new Packets.ResultSetHeader(packet, connection);
return this.doneInsert(rs);
}
stream(options) {
options = options || {};
options.objectMode = true;
const stream = new Readable(options);
stream._read = () => {
this._connection && this._connection.resume();
};
this.on('result', (row, resultSetIndex) => {
if (!stream.push(row)) {
this._connection.pause();
}
stream.emit('result', row, resultSetIndex); // replicate old emitter
});
this.on('error', err => {
stream.emit('error', err); // Pass on any errors
});
this.on('end', () => {
stream.push(null); // pushing null, indicating EOF
});
this.on('fields', fields => {
stream.emit('fields', fields); // replicate old emitter
});
stream.on('end', () => {
stream.emit('close');
});
return stream;
}
_setTimeout() {
if (this.timeout) {
const timeoutHandler = this._handleTimeoutError.bind(this);
this.queryTimeout = Timers.setTimeout(
timeoutHandler,
this.timeout
);
}
}
_handleTimeoutError() {
if (this.queryTimeout) {
Timers.clearTimeout(this.queryTimeout);
this.queryTimeout = null;
}
const err = new Error('Query inactivity timeout');
err.errorno = 'PROTOCOL_SEQUENCE_TIMEOUT';
err.code = 'PROTOCOL_SEQUENCE_TIMEOUT';
err.syscall = 'query';
if (this.onResult) {
this.onResult(err);
} else {
this.emit('error', err);
}
}
}
Query.prototype.catch = Query.prototype.then;
module.exports = Query;

29
node_modules/mysql2/lib/commands/quit.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
'use strict';
const Command = require('./command.js');
const CommandCode = require('../constants/commands.js');
const Packet = require('../packets/packet.js');
class Quit extends Command {
constructor(callback) {
super();
this.onResult = callback;
}
start(packet, connection) {
connection._closing = true;
const quit = new Packet(
0,
Buffer.from([1, 0, 0, 0, CommandCode.QUIT]),
0,
5
);
if (this.onResult) {
this.onResult();
}
connection.writePacket(quit);
return null;
}
}
module.exports = Quit;

27
node_modules/mysql2/lib/commands/register_slave.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets');
class RegisterSlave extends Command {
constructor(opts, callback) {
super();
this.onResult = callback;
this.opts = opts;
}
start(packet, connection) {
const newPacket = new Packets.RegisterSlave(this.opts);
connection.writePacket(newPacket.toPacket(1));
return RegisterSlave.prototype.registerResponse;
}
registerResponse() {
if (this.onResult) {
process.nextTick(this.onResult.bind(this));
}
return null;
}
}
module.exports = RegisterSlave;

197
node_modules/mysql2/lib/commands/server_handshake.js generated vendored Normal file
View File

@@ -0,0 +1,197 @@
'use strict';
const CommandCode = require('../constants/commands.js');
const Errors = require('../constants/errors.js');
const Command = require('./command.js');
const Packets = require('../packets/index.js');
class ServerHandshake extends Command {
constructor(args) {
super();
this.args = args;
/*
this.protocolVersion = args.protocolVersion || 10;
this.serverVersion = args.serverVersion;
this.connectionId = args.connectionId,
this.statusFlags = args.statusFlags,
this.characterSet = args.characterSet,
this.capabilityFlags = args.capabilityFlags || 512;
*/
}
start(packet, connection) {
const serverHelloPacket = new Packets.Handshake(this.args);
this.serverHello = serverHelloPacket;
serverHelloPacket.setScrambleData(err => {
if (err) {
connection.emit('error', new Error('Error generating random bytes'));
return;
}
connection.writePacket(serverHelloPacket.toPacket(0));
});
return ServerHandshake.prototype.readClientReply;
}
readClientReply(packet, connection) {
// check auth here
const clientHelloReply = Packets.HandshakeResponse.fromPacket(packet);
// TODO check we don't have something similar already
connection.clientHelloReply = clientHelloReply;
if (this.args.authCallback) {
this.args.authCallback(
{
user: clientHelloReply.user,
database: clientHelloReply.database,
address: connection.stream.remoteAddress,
authPluginData1: this.serverHello.authPluginData1,
authPluginData2: this.serverHello.authPluginData2,
authToken: clientHelloReply.authToken
},
(err, mysqlError) => {
// if (err)
if (!mysqlError) {
connection.writeOk();
} else {
// TODO create constants / errorToCode
// 1045 = ER_ACCESS_DENIED_ERROR
connection.writeError({
message: mysqlError.message || '',
code: mysqlError.code || 1045
});
connection.close();
}
}
);
} else {
connection.writeOk();
}
return ServerHandshake.prototype.dispatchCommands;
}
_isStatement(query, name) {
const firstWord = query.split(' ')[0].toUpperCase();
return firstWord === name;
}
dispatchCommands(packet, connection) {
// command from client to server
let knownCommand = true;
const encoding = connection.clientHelloReply.encoding;
const commandCode = packet.readInt8();
switch (commandCode) {
case CommandCode.STMT_PREPARE:
if (connection.listeners('stmt_prepare').length) {
const query = packet.readString(undefined, encoding);
connection.emit('stmt_prepare', query);
} else {
connection.writeError({
code: Errors.HA_ERR_INTERNAL_ERROR,
message:
'No query handler for prepared statements.'
});
}
break;
case CommandCode.STMT_EXECUTE:
if (connection.listeners('stmt_execute').length) {
const { stmtId, flags, iterationCount, values } = Packets.Execute.fromPacket(packet, encoding);
connection.emit('stmt_execute', stmtId, flags, iterationCount, values);
} else {
connection.writeError({
code: Errors.HA_ERR_INTERNAL_ERROR,
message:
'No query handler for execute statements.'
});
}
break;
case CommandCode.QUIT:
if (connection.listeners('quit').length) {
connection.emit('quit');
} else {
connection.stream.end();
}
break;
case CommandCode.INIT_DB:
if (connection.listeners('init_db').length) {
const schemaName = packet.readString(undefined, encoding);
connection.emit('init_db', schemaName);
} else {
connection.writeOk();
}
break;
case CommandCode.QUERY:
if (connection.listeners('query').length) {
const query = packet.readString(undefined, encoding);
if (this._isStatement(query, 'PREPARE') || this._isStatement(query, 'SET')) {
connection.emit('stmt_prepare', query);
}
else if (this._isStatement(query, 'EXECUTE')) {
connection.emit('stmt_execute', null, null, null, null, query);
}
else connection.emit('query', query);
} else {
connection.writeError({
code: Errors.HA_ERR_INTERNAL_ERROR,
message: 'No query handler'
});
}
break;
case CommandCode.FIELD_LIST:
if (connection.listeners('field_list').length) {
const table = packet.readNullTerminatedString(encoding);
const fields = packet.readString(undefined, encoding);
connection.emit('field_list', table, fields);
} else {
connection.writeError({
code: Errors.ER_WARN_DEPRECATED_SYNTAX,
message:
'As of MySQL 5.7.11, COM_FIELD_LIST is deprecated and will be removed in a future version of MySQL.'
});
}
break;
case CommandCode.PING:
if (connection.listeners('ping').length) {
connection.emit('ping');
} else {
connection.writeOk();
}
break;
default:
knownCommand = false;
}
if (connection.listeners('packet').length) {
connection.emit('packet', packet.clone(), knownCommand, commandCode);
} else if (!knownCommand) {
// eslint-disable-next-line no-console
console.log('Unknown command:', commandCode);
}
return ServerHandshake.prototype.dispatchCommands;
}
}
module.exports = ServerHandshake;
// TODO: implement server-side 4.1 authentication
/*
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
SERVER: public_seed=create_random_string()
send(public_seed)
CLIENT: recv(public_seed)
hash_stage1=sha1("password")
hash_stage2=sha1(hash_stage1)
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
// this three steps are done in scramble()
send(reply)
SERVER: recv(reply)
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
candidate_hash2=sha1(hash_stage1)
check(candidate_hash2==hash_stage2)
server stores sha1(sha1(password)) ( hash_stag2)
*/

127
node_modules/mysql2/lib/compressed_protocol.js generated vendored Normal file
View File

@@ -0,0 +1,127 @@
'use strict';
// connection mixins
// implementation of http://dev.mysql.com/doc/internals/en/compression.html
const zlib = require('zlib');
const PacketParser = require('./packet_parser.js');
function handleCompressedPacket(packet) {
// eslint-disable-next-line consistent-this, no-invalid-this
const connection = this;
const deflatedLength = packet.readInt24();
const body = packet.readBuffer();
if (deflatedLength !== 0) {
connection.inflateQueue.push(task => {
zlib.inflate(body, (err, data) => {
if (err) {
connection._handleNetworkError(err);
return;
}
connection._bumpCompressedSequenceId(packet.numPackets);
connection._inflatedPacketsParser.execute(data);
task.done();
});
});
} else {
connection.inflateQueue.push(task => {
connection._bumpCompressedSequenceId(packet.numPackets);
connection._inflatedPacketsParser.execute(body);
task.done();
});
}
}
function writeCompressed(buffer) {
// http://dev.mysql.com/doc/internals/en/example-several-mysql-packets.html
// note: sending a MySQL Packet of the size 2^245 to 2^241 via compression
// leads to at least one extra compressed packet.
// (this is because "length of the packet before compression" need to fit
// into 3 byte unsigned int. "length of the packet before compression" includes
// 4 byte packet header, hence 2^245)
const MAX_COMPRESSED_LENGTH = 16777210;
let start;
if (buffer.length > MAX_COMPRESSED_LENGTH) {
for (start = 0; start < buffer.length; start += MAX_COMPRESSED_LENGTH) {
writeCompressed.call(
// eslint-disable-next-line no-invalid-this
this,
buffer.slice(start, start + MAX_COMPRESSED_LENGTH)
);
}
return;
}
// eslint-disable-next-line no-invalid-this, consistent-this
const connection = this;
let packetLen = buffer.length;
const compressHeader = Buffer.allocUnsafe(7);
// seqqueue is used here because zlib async execution is routed via thread pool
// internally and when we have multiple compressed packets arriving we need
// to assemble uncompressed result sequentially
(function(seqId) {
connection.deflateQueue.push(task => {
zlib.deflate(buffer, (err, compressed) => {
if (err) {
connection._handleFatalError(err);
return;
}
let compressedLength = compressed.length;
if (compressedLength < packetLen) {
compressHeader.writeUInt8(compressedLength & 0xff, 0);
compressHeader.writeUInt16LE(compressedLength >> 8, 1);
compressHeader.writeUInt8(seqId, 3);
compressHeader.writeUInt8(packetLen & 0xff, 4);
compressHeader.writeUInt16LE(packetLen >> 8, 5);
connection.writeUncompressed(compressHeader);
connection.writeUncompressed(compressed);
} else {
// http://dev.mysql.com/doc/internals/en/uncompressed-payload.html
// To send an uncompressed payload:
// - set length of payload before compression to 0
// - the compressed payload contains the uncompressed payload instead.
compressedLength = packetLen;
packetLen = 0;
compressHeader.writeUInt8(compressedLength & 0xff, 0);
compressHeader.writeUInt16LE(compressedLength >> 8, 1);
compressHeader.writeUInt8(seqId, 3);
compressHeader.writeUInt8(packetLen & 0xff, 4);
compressHeader.writeUInt16LE(packetLen >> 8, 5);
connection.writeUncompressed(compressHeader);
connection.writeUncompressed(buffer);
}
task.done();
});
});
})(connection.compressedSequenceId);
connection._bumpCompressedSequenceId(1);
}
function enableCompression(connection) {
connection._lastWrittenPacketId = 0;
connection._lastReceivedPacketId = 0;
connection._handleCompressedPacket = handleCompressedPacket;
connection._inflatedPacketsParser = new PacketParser(p => {
connection.handlePacket(p);
}, 4);
connection._inflatedPacketsParser._lastPacket = 0;
connection.packetParser = new PacketParser(packet => {
connection._handleCompressedPacket(packet);
}, 7);
connection.writeUncompressed = connection.write;
connection.write = writeCompressed;
const seqqueue = require('seq-queue');
connection.inflateQueue = seqqueue.createQueue();
connection.deflateQueue = seqqueue.createQueue();
}
module.exports = {
enableCompression: enableCompression
};

948
node_modules/mysql2/lib/connection.js generated vendored Normal file
View File

@@ -0,0 +1,948 @@
// This file was modified by Oracle on June 1, 2021.
// The changes involve new logic to handle an additional ERR Packet sent by
// the MySQL server when the connection is closed unexpectedly.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// This file was modified by Oracle on June 17, 2021.
// The changes involve logic to ensure the socket connection is closed when
// there is a fatal error.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// This file was modified by Oracle on September 21, 2021.
// The changes involve passing additional authentication factor passwords
// to the ChangeUser Command instance.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const Net = require('net');
const Tls = require('tls');
const Timers = require('timers');
const EventEmitter = require('events').EventEmitter;
const Readable = require('stream').Readable;
const Queue = require('denque');
const SqlString = require('sqlstring');
const LRU = require('lru-cache').default;
const PacketParser = require('./packet_parser.js');
const Packets = require('./packets/index.js');
const Commands = require('./commands/index.js');
const ConnectionConfig = require('./connection_config.js');
const CharsetToEncoding = require('./constants/charset_encodings.js');
let _connectionId = 0;
let convertNamedPlaceholders = null;
class Connection extends EventEmitter {
constructor(opts) {
super();
this.config = opts.config;
// TODO: fill defaults
// if no params, connect to /var/lib/mysql/mysql.sock ( /tmp/mysql.sock on OSX )
// if host is given, connect to host:3306
// TODO: use `/usr/local/mysql/bin/mysql_config --socket` output? as default socketPath
// if there is no host/port and no socketPath parameters?
if (!opts.config.stream) {
if (opts.config.socketPath) {
this.stream = Net.connect(opts.config.socketPath);
} else {
this.stream = Net.connect(
opts.config.port,
opts.config.host
);
// Optionally enable keep-alive on the socket.
if (this.config.enableKeepAlive) {
this.stream.on('connect', () => {
this.stream.setKeepAlive(true, this.config.keepAliveInitialDelay);
});
}
// Enable TCP_NODELAY flag. This is needed so that the network packets
// are sent immediately to the server
this.stream.setNoDelay(true);
}
// if stream is a function, treat it as "stream agent / factory"
} else if (typeof opts.config.stream === 'function') {
this.stream = opts.config.stream(opts);
} else {
this.stream = opts.config.stream;
}
this._internalId = _connectionId++;
this._commands = new Queue();
this._command = null;
this._paused = false;
this._paused_packets = new Queue();
this._statements = new LRU({
max: this.config.maxPreparedStatements,
dispose: function(statement) {
statement.close();
}
});
this.serverCapabilityFlags = 0;
this.authorized = false;
this.sequenceId = 0;
this.compressedSequenceId = 0;
this.threadId = null;
this._handshakePacket = null;
this._fatalError = null;
this._protocolError = null;
this._outOfOrderPackets = [];
this.clientEncoding = CharsetToEncoding[this.config.charsetNumber];
this.stream.on('error', this._handleNetworkError.bind(this));
// see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
this.packetParser = new PacketParser(p => {
this.handlePacket(p);
});
this.stream.on('data', data => {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this.packetParser.execute(data);
});
this.stream.on('end', () => {
// emit the end event so that the pooled connection can close the connection
this.emit('end');
});
this.stream.on('close', () => {
// we need to set this flag everywhere where we want connection to close
if (this._closing) {
return;
}
if (!this._protocolError) {
// no particular error message before disconnect
this._protocolError = new Error(
'Connection lost: The server closed the connection.'
);
this._protocolError.fatal = true;
this._protocolError.code = 'PROTOCOL_CONNECTION_LOST';
}
this._notifyError(this._protocolError);
});
let handshakeCommand;
if (!this.config.isServer) {
handshakeCommand = new Commands.ClientHandshake(this.config.clientFlags);
handshakeCommand.on('end', () => {
// this happens when handshake finishes early either because there was
// some fatal error or the server sent an error packet instead of
// an hello packet (for example, 'Too many connections' error)
if (!handshakeCommand.handshake || this._fatalError || this._protocolError) {
return;
}
this._handshakePacket = handshakeCommand.handshake;
this.threadId = handshakeCommand.handshake.connectionId;
this.emit('connect', handshakeCommand.handshake);
});
handshakeCommand.on('error', err => {
this._closing = true;
this._notifyError(err);
});
this.addCommand(handshakeCommand);
}
// in case there was no initial handshake but we need to read sting, assume it utf-8
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
// will be overwritten with actual encoding value as soon as server handshake packet is received
this.serverEncoding = 'utf8';
if (this.config.connectTimeout) {
const timeoutHandler = this._handleTimeoutError.bind(this);
this.connectTimeout = Timers.setTimeout(
timeoutHandler,
this.config.connectTimeout
);
}
}
promise(promiseImpl) {
const PromiseConnection = require('../promise').PromiseConnection;
return new PromiseConnection(this, promiseImpl);
}
_addCommandClosedState(cmd) {
const err = new Error(
"Can't add new command when connection is in closed state"
);
err.fatal = true;
if (cmd.onResult) {
cmd.onResult(err);
} else {
this.emit('error', err);
}
}
_handleFatalError(err) {
err.fatal = true;
// stop receiving packets
this.stream.removeAllListeners('data');
this.addCommand = this._addCommandClosedState;
this.write = () => {
this.emit('error', new Error("Can't write in closed state"));
};
this._notifyError(err);
this._fatalError = err;
}
_handleNetworkError(err) {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
// Do not throw an error when a connection ends with a RST,ACK packet
if (err.code === 'ECONNRESET' && this._closing) {
return;
}
this._handleFatalError(err);
}
_handleTimeoutError() {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this.stream.destroy && this.stream.destroy();
const err = new Error('connect ETIMEDOUT');
err.errorno = 'ETIMEDOUT';
err.code = 'ETIMEDOUT';
err.syscall = 'connect';
this._handleNetworkError(err);
}
// notify all commands in the queue and bubble error as connection "error"
// called on stream error or unexpected termination
_notifyError(err) {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
// prevent from emitting 'PROTOCOL_CONNECTION_LOST' after EPIPE or ECONNRESET
if (this._fatalError) {
return;
}
let command;
// if there is no active command, notify connection
// if there are commands and all of them have callbacks, pass error via callback
let bubbleErrorToConnection = !this._command;
if (this._command && this._command.onResult) {
this._command.onResult(err);
this._command = null;
// connection handshake is special because we allow it to be implicit
// if error happened during handshake, but there are others commands in queue
// then bubble error to other commands and not to connection
} else if (
!(
this._command &&
this._command.constructor === Commands.ClientHandshake &&
this._commands.length > 0
)
) {
bubbleErrorToConnection = true;
}
while ((command = this._commands.shift())) {
if (command.onResult) {
command.onResult(err);
} else {
bubbleErrorToConnection = true;
}
}
// notify connection if some comands in the queue did not have callbacks
// or if this is pool connection ( so it can be removed from pool )
if (bubbleErrorToConnection || this._pool) {
this.emit('error', err);
}
// close connection after emitting the event in case of a fatal error
if (err.fatal) {
this.close();
}
}
write(buffer) {
const result = this.stream.write(buffer, err => {
if (err) {
this._handleNetworkError(err);
}
});
if (!result) {
this.stream.emit('pause');
}
}
// http://dev.mysql.com/doc/internals/en/sequence-id.html
//
// The sequence-id is incremented with each packet and may wrap around.
// It starts at 0 and is reset to 0 when a new command
// begins in the Command Phase.
// http://dev.mysql.com/doc/internals/en/example-several-mysql-packets.html
_resetSequenceId() {
this.sequenceId = 0;
this.compressedSequenceId = 0;
}
_bumpCompressedSequenceId(numPackets) {
this.compressedSequenceId += numPackets;
this.compressedSequenceId %= 256;
}
_bumpSequenceId(numPackets) {
this.sequenceId += numPackets;
this.sequenceId %= 256;
}
writePacket(packet) {
const MAX_PACKET_LENGTH = 16777215;
const length = packet.length();
let chunk, offset, header;
if (length < MAX_PACKET_LENGTH) {
packet.writeHeader(this.sequenceId);
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${this._command._commandName}#${this._command.stateName()}(${[this.sequenceId, packet._name, packet.length()].join(',')})`
);
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${packet.buffer.toString('hex')}`
);
}
this._bumpSequenceId(1);
this.write(packet.buffer);
} else {
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== Writing large packet, raw content not written:`
);
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${this._command._commandName}#${this._command.stateName()}(${[this.sequenceId, packet._name, packet.length()].join(',')})`
);
}
for (offset = 4; offset < 4 + length; offset += MAX_PACKET_LENGTH) {
chunk = packet.buffer.slice(offset, offset + MAX_PACKET_LENGTH);
if (chunk.length === MAX_PACKET_LENGTH) {
header = Buffer.from([0xff, 0xff, 0xff, this.sequenceId]);
} else {
header = Buffer.from([
chunk.length & 0xff,
(chunk.length >> 8) & 0xff,
(chunk.length >> 16) & 0xff,
this.sequenceId
]);
}
this._bumpSequenceId(1);
this.write(header);
this.write(chunk);
}
}
}
// 0.11+ environment
startTLS(onSecure) {
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log('Upgrading connection to TLS');
}
const secureContext = Tls.createSecureContext({
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,
minVersion: this.config.ssl.minVersion,
maxVersion: this.config.ssl.maxVersion
});
const rejectUnauthorized = this.config.ssl.rejectUnauthorized;
const verifyIdentity = this.config.ssl.verifyIdentity;
const servername = this.config.host;
let secureEstablished = false;
this.stream.removeAllListeners('data');
const secureSocket = Tls.connect({
rejectUnauthorized,
requestCert: rejectUnauthorized,
checkServerIdentity: verifyIdentity
? Tls.checkServerIdentity
: function() { return undefined; },
secureContext,
isServer: false,
socket: this.stream,
servername
}, () => {
secureEstablished = true;
if (rejectUnauthorized) {
if (typeof servername === 'string' && verifyIdentity) {
const cert = secureSocket.getPeerCertificate(true);
const serverIdentityCheckError = Tls.checkServerIdentity(servername, cert);
if (serverIdentityCheckError) {
onSecure(serverIdentityCheckError);
return;
}
}
}
onSecure();
});
// error handler for secure socket
secureSocket.on('error', err => {
if (secureEstablished) {
this._handleNetworkError(err);
} else {
onSecure(err);
}
});
secureSocket.on('data', data => {
this.packetParser.execute(data);
});
this.write = buffer => secureSocket.write(buffer);
}
protocolError(message, code) {
// Starting with MySQL 8.0.24, if the client closes the connection
// unexpectedly, the server will send a last ERR Packet, which we can
// safely ignore.
// https://dev.mysql.com/worklog/task/?id=12999
if (this._closing) {
return;
}
const err = new Error(message);
err.fatal = true;
err.code = code || 'PROTOCOL_ERROR';
this.emit('error', err);
}
get fatalError() {
return this._fatalError;
}
handlePacket(packet) {
if (this._paused) {
this._paused_packets.push(packet);
return;
}
if (this.config.debug) {
if (packet) {
// eslint-disable-next-line no-console
console.log(
` raw: ${packet.buffer
.slice(packet.offset, packet.offset + packet.length())
.toString('hex')}`
);
// eslint-disable-next-line no-console
console.trace();
const commandName = this._command
? this._command._commandName
: '(no command)';
const stateName = this._command
? this._command.stateName()
: '(no command)';
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} ==> ${commandName}#${stateName}(${[packet.sequenceId, packet.type(), packet.length()].join(',')})`
);
}
}
if (!this._command) {
const marker = packet.peekByte();
// If it's an Err Packet, we should use it.
if (marker === 0xff) {
const error = Packets.Error.fromPacket(packet);
this.protocolError(error.message, error.code);
} else {
// Otherwise, it means it's some other unexpected packet.
this.protocolError(
'Unexpected packet while no commands in the queue',
'PROTOCOL_UNEXPECTED_PACKET'
);
}
this.close();
return;
}
if (packet) {
// Note: when server closes connection due to inactivity, Err packet ER_CLIENT_INTERACTION_TIMEOUT from MySQL 8.0.24, sequenceId will be 0
if (this.sequenceId !== packet.sequenceId) {
const err = new Error(
`Warning: got packets out of order. Expected ${this.sequenceId} but received ${packet.sequenceId}`
);
err.expected = this.sequenceId;
err.received = packet.sequenceId;
this.emit('warn', err); // REVIEW
// eslint-disable-next-line no-console
console.error(err.message);
}
this._bumpSequenceId(packet.numPackets);
}
try {
if (this._fatalError) {
// skip remaining packets after client is in the error state
return;
}
const done = this._command.execute(packet, this);
if (done) {
this._command = this._commands.shift();
if (this._command) {
this.sequenceId = 0;
this.compressedSequenceId = 0;
this.handlePacket();
}
}
} catch (err) {
this._handleFatalError(err);
this.stream.destroy();
}
}
addCommand(cmd) {
// this.compressedSequenceId = 0;
// this.sequenceId = 0;
if (this.config.debug) {
const commandName = cmd.constructor.name;
// eslint-disable-next-line no-console
console.log(`Add command: ${commandName}`);
cmd._commandName = commandName;
}
if (!this._command) {
this._command = cmd;
this.handlePacket();
} else {
this._commands.push(cmd);
}
return cmd;
}
format(sql, values) {
if (typeof this.config.queryFormat === 'function') {
return this.config.queryFormat.call(
this,
sql,
values,
this.config.timezone
);
}
const opts = {
sql: sql,
values: values
};
this._resolveNamedPlaceholders(opts);
return SqlString.format(
opts.sql,
opts.values,
this.config.stringifyObjects,
this.config.timezone
);
}
escape(value) {
return SqlString.escape(value, false, this.config.timezone);
}
escapeId(value) {
return SqlString.escapeId(value, false);
}
raw(sql) {
return SqlString.raw(sql);
}
_resolveNamedPlaceholders(options) {
let unnamed;
if (this.config.namedPlaceholders || options.namedPlaceholders) {
if (Array.isArray(options.values)) {
// if an array is provided as the values, assume the conversion is not necessary.
// this allows the usage of unnamed placeholders even if the namedPlaceholders flag is enabled.
return
}
if (convertNamedPlaceholders === null) {
convertNamedPlaceholders = require('named-placeholders')();
}
unnamed = convertNamedPlaceholders(options.sql, options.values);
options.sql = unnamed[0];
options.values = unnamed[1];
}
}
query(sql, values, cb) {
let cmdQuery;
if (sql.constructor === Commands.Query) {
cmdQuery = sql;
} else {
cmdQuery = Connection.createQuery(sql, values, cb, this.config);
}
this._resolveNamedPlaceholders(cmdQuery);
const rawSql = this.format(cmdQuery.sql, cmdQuery.values !== undefined ? cmdQuery.values : []);
cmdQuery.sql = rawSql;
return this.addCommand(cmdQuery);
}
pause() {
this._paused = true;
this.stream.pause();
}
resume() {
let packet;
this._paused = false;
while ((packet = this._paused_packets.shift())) {
this.handlePacket(packet);
// don't resume if packet handler paused connection
if (this._paused) {
return;
}
}
this.stream.resume();
}
// TODO: named placeholders support
prepare(options, cb) {
if (typeof options === 'string') {
options = { sql: options };
}
return this.addCommand(new Commands.Prepare(options, cb));
}
unprepare(sql) {
let options = {};
if (typeof sql === 'object') {
options = sql;
} else {
options.sql = sql;
}
const key = Connection.statementKey(options);
const stmt = this._statements.get(key);
if (stmt) {
this._statements.delete(key);
stmt.close();
}
return stmt;
}
execute(sql, values, cb) {
let options = {
infileStreamFactory: this.config.infileStreamFactory
};
if (typeof sql === 'object') {
// execute(options, cb)
options = {
...options,
...sql,
sql: sql.sql,
values: sql.values
};
if (typeof values === 'function') {
cb = values;
} else {
options.values = options.values || values;
}
} else if (typeof values === 'function') {
// execute(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// execute(sql, values, cb)
options.sql = sql;
options.values = values;
}
this._resolveNamedPlaceholders(options);
// check for values containing undefined
if (options.values) {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
options.values.forEach(val => {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
if (val === undefined) {
throw new TypeError(
'Bind parameters must not contain undefined. To pass SQL NULL specify JS null'
);
}
if (typeof val === 'function') {
throw new TypeError(
'Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first'
);
}
});
}
const executeCommand = new Commands.Execute(options, cb);
const prepareCommand = new Commands.Prepare(options, (err, stmt) => {
if (err) {
// skip execute command if prepare failed, we have main
// combined callback here
executeCommand.start = function() {
return null;
};
if (cb) {
cb(err);
} else {
executeCommand.emit('error', err);
}
executeCommand.emit('end');
return;
}
executeCommand.statement = stmt;
});
this.addCommand(prepareCommand);
this.addCommand(executeCommand);
return executeCommand;
}
changeUser(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
const charsetNumber = options.charset
? ConnectionConfig.getCharsetNumber(options.charset)
: this.config.charsetNumber;
return this.addCommand(
new Commands.ChangeUser(
{
user: options.user || this.config.user,
// for the purpose of multi-factor authentication, or not, the main
// password (used for the 1st authentication factor) can also be
// provided via the "password1" option
password: options.password || options.password1 || this.config.password || this.config.password1,
password2: options.password2 || this.config.password2,
password3: options.password3 || this.config.password3,
passwordSha1: options.passwordSha1 || this.config.passwordSha1,
database: options.database || this.config.database,
timeout: options.timeout,
charsetNumber: charsetNumber,
currentConfig: this.config
},
err => {
if (err) {
err.fatal = true;
}
if (callback) {
callback(err);
}
}
)
);
}
// transaction helpers
beginTransaction(cb) {
return this.query('START TRANSACTION', cb);
}
commit(cb) {
return this.query('COMMIT', cb);
}
rollback(cb) {
return this.query('ROLLBACK', cb);
}
ping(cb) {
return this.addCommand(new Commands.Ping(cb));
}
_registerSlave(opts, cb) {
return this.addCommand(new Commands.RegisterSlave(opts, cb));
}
_binlogDump(opts, cb) {
return this.addCommand(new Commands.BinlogDump(opts, cb));
}
// currently just alias to close
destroy() {
this.close();
}
close() {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this._closing = true;
this.stream.end();
this.addCommand = this._addCommandClosedState;
}
createBinlogStream(opts) {
// TODO: create proper stream class
// TODO: use through2
let test = 1;
const stream = new Readable({ objectMode: true });
stream._read = function() {
return {
data: test++
};
};
this._registerSlave(opts, () => {
const dumpCmd = this._binlogDump(opts);
dumpCmd.on('event', ev => {
stream.push(ev);
});
dumpCmd.on('eof', () => {
stream.push(null);
// if non-blocking, then close stream to prevent errors
if (opts.flags && opts.flags & 0x01) {
this.close();
}
});
// TODO: pipe errors as well
});
return stream;
}
connect(cb) {
if (!cb) {
return;
}
if (this._fatalError || this._protocolError) {
return cb(this._fatalError || this._protocolError);
}
if (this._handshakePacket) {
return cb(null, this);
}
let connectCalled = 0;
function callbackOnce(isErrorHandler) {
return function(param) {
if (!connectCalled) {
if (isErrorHandler) {
cb(param);
} else {
cb(null, param);
}
}
connectCalled = 1;
};
}
this.once('error', callbackOnce(true));
this.once('connect', callbackOnce(false));
}
// ===================================
// outgoing server connection methods
// ===================================
writeColumns(columns) {
this.writePacket(Packets.ResultSetHeader.toPacket(columns.length));
columns.forEach(column => {
this.writePacket(
Packets.ColumnDefinition.toPacket(column, this.serverConfig.encoding)
);
});
this.writeEof();
}
// row is array of columns, not hash
writeTextRow(column) {
this.writePacket(
Packets.TextRow.toPacket(column, this.serverConfig.encoding)
);
}
writeBinaryRow(column) {
this.writePacket(
Packets.BinaryRow.toPacket(column, this.serverConfig.encoding)
);
}
writeTextResult(rows, columns, binary=false) {
this.writeColumns(columns);
rows.forEach(row => {
const arrayRow = new Array(columns.length);
columns.forEach(column => {
arrayRow.push(row[column.name]);
});
if(binary) {
this.writeBinaryRow(arrayRow);
}
else this.writeTextRow(arrayRow);
});
this.writeEof();
}
writeEof(warnings, statusFlags) {
this.writePacket(Packets.EOF.toPacket(warnings, statusFlags));
}
writeOk(args) {
if (!args) {
args = { affectedRows: 0 };
}
this.writePacket(Packets.OK.toPacket(args, this.serverConfig.encoding));
}
writeError(args) {
// if we want to send error before initial hello was sent, use default encoding
const encoding = this.serverConfig ? this.serverConfig.encoding : 'cesu8';
this.writePacket(Packets.Error.toPacket(args, encoding));
}
serverHandshake(args) {
this.serverConfig = args;
this.serverConfig.encoding =
CharsetToEncoding[this.serverConfig.characterSet];
return this.addCommand(new Commands.ServerHandshake(args));
}
// ===============================================================
end(callback) {
if (this.config.isServer) {
this._closing = true;
const quitCmd = new EventEmitter();
setImmediate(() => {
this.stream.end();
quitCmd.emit('end');
});
return quitCmd;
}
// trigger error if more commands enqueued after end command
const quitCmd = this.addCommand(new Commands.Quit(callback));
this.addCommand = this._addCommandClosedState;
return quitCmd;
}
static createQuery(sql, values, cb, config) {
let options = {
rowsAsArray: config.rowsAsArray,
infileStreamFactory: config.infileStreamFactory
};
if (typeof sql === 'object') {
// query(options, cb)
options = {
...options,
...sql,
sql: sql.sql,
values: sql.values
};
if (typeof values === 'function') {
cb = values;
} else if (values !== undefined) {
options.values = values;
}
} else if (typeof values === 'function') {
// query(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// query(sql, values, cb)
options.sql = sql;
options.values = values;
}
return new Commands.Query(options, cb);
}
static statementKey(options) {
return (
`${typeof options.nestTables}/${options.nestTables}/${options.rowsAsArray}${options.sql}`
);
}
}
module.exports = Connection;

284
node_modules/mysql2/lib/connection_config.js generated vendored Normal file
View File

@@ -0,0 +1,284 @@
// This file was modified by Oracle on September 21, 2021.
// New connection options for additional authentication factors were
// introduced.
// Multi-factor authentication capability is now enabled if one of these
// options is used.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const { URL } = require('url');
const ClientConstants = require('./constants/client');
const Charsets = require('./constants/charsets');
const { version } = require('../package.json')
let SSLProfiles = null;
const validOptions = {
authPlugins: 1,
authSwitchHandler: 1,
bigNumberStrings: 1,
charset: 1,
charsetNumber: 1,
compress: 1,
connectAttributes: 1,
connectTimeout: 1,
database: 1,
dateStrings: 1,
debug: 1,
decimalNumbers: 1,
enableKeepAlive: 1,
flags: 1,
host: 1,
insecureAuth: 1,
infileStreamFactory: 1,
isServer: 1,
keepAliveInitialDelay: 1,
localAddress: 1,
maxPreparedStatements: 1,
multipleStatements: 1,
namedPlaceholders: 1,
nestTables: 1,
password: 1,
// with multi-factor authentication, the main password (used for the first
// authentication factor) can be provided via password1
password1: 1,
password2: 1,
password3: 1,
passwordSha1: 1,
pool: 1,
port: 1,
queryFormat: 1,
rowsAsArray: 1,
socketPath: 1,
ssl: 1,
stream: 1,
stringifyObjects: 1,
supportBigNumbers: 1,
timezone: 1,
trace: 1,
typeCast: 1,
uri: 1,
user: 1,
// These options are used for Pool
connectionLimit: 1,
maxIdle: 1,
idleTimeout: 1,
Promise: 1,
queueLimit: 1,
waitForConnections: 1,
jsonStrings: 1
};
class ConnectionConfig {
constructor(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
} else if (options && options.uri) {
const uriOptions = ConnectionConfig.parseUrl(options.uri);
for (const key in uriOptions) {
if (!Object.prototype.hasOwnProperty.call(uriOptions, key)) continue;
if (options[key]) continue;
options[key] = uriOptions[key];
}
}
for (const key in options) {
if (!Object.prototype.hasOwnProperty.call(options, key)) continue;
if (validOptions[key] !== 1) {
// REVIEW: Should this be emitted somehow?
// eslint-disable-next-line no-console
console.error(
`Ignoring invalid configuration option passed to Connection: ${key}. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection`
);
}
}
this.isServer = options.isServer;
this.stream = options.stream;
this.host = options.host || 'localhost';
this.port = (typeof options.port === 'string' ? parseInt(options.port, 10) : options.port)|| 3306;
this.localAddress = options.localAddress;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
// for the purpose of multi-factor authentication, or not, the main
// password (used for the 1st authentication factor) can also be
// provided via the "password1" option
this.password = options.password || options.password1 || undefined;
this.password2 = options.password2 || undefined;
this.password3 = options.password3 || undefined;
this.passwordSha1 = options.passwordSha1 || undefined;
this.database = options.database;
this.connectTimeout = isNaN(options.connectTimeout)
? 10 * 1000
: options.connectTimeout;
this.insecureAuth = options.insecureAuth || false;
this.infileStreamFactory = options.infileStreamFactory || undefined;
this.supportBigNumbers = options.supportBigNumbers || false;
this.bigNumberStrings = options.bigNumberStrings || false;
this.decimalNumbers = options.decimalNumbers || false;
this.dateStrings = options.dateStrings || false;
this.debug = options.debug;
this.trace = options.trace !== false;
this.stringifyObjects = options.stringifyObjects || false;
this.enableKeepAlive = options.enableKeepAlive !== false;
this.keepAliveInitialDelay = options.keepAliveInitialDelay;
if (
options.timezone &&
!/^(?:local|Z|[ +-]\d\d:\d\d)$/.test(options.timezone)
) {
// strictly supports timezones specified by mysqljs/mysql:
// https://github.com/mysqljs/mysql#user-content-connection-options
// eslint-disable-next-line no-console
console.error(
`Ignoring invalid timezone passed to Connection: ${options.timezone}. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection`
);
// SqlStrings falls back to UTC on invalid timezone
this.timezone = 'Z';
} else {
this.timezone = options.timezone || 'local';
}
this.queryFormat = options.queryFormat;
this.pool = options.pool || undefined;
this.ssl =
typeof options.ssl === 'string'
? ConnectionConfig.getSSLProfile(options.ssl)
: options.ssl || false;
this.multipleStatements = options.multipleStatements || false;
this.rowsAsArray = options.rowsAsArray || false;
this.namedPlaceholders = options.namedPlaceholders || false;
this.nestTables =
options.nestTables === undefined ? undefined : options.nestTables;
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.slice(1)}`;
}
if (this.ssl) {
if (typeof this.ssl !== 'object') {
throw new TypeError(
`SSL profile must be an object, instead it's a ${typeof 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.UTF8MB4_UNICODE_CI;
this.compress = options.compress || false;
this.authPlugins = options.authPlugins;
this.authSwitchHandler = options.authSwitchHandler;
this.clientFlags = ConnectionConfig.mergeFlags(
ConnectionConfig.getDefaultFlags(options),
options.flags || ''
);
// Default connection attributes
// https://dev.mysql.com/doc/refman/8.0/en/performance-schema-connection-attribute-tables.html
const defaultConnectAttributes = {
_client_name: 'Node-MySQL-2',
_client_version: version
};
this.connectAttributes = { ...defaultConnectAttributes, ...(options.connectAttributes || {})};
this.maxPreparedStatements = options.maxPreparedStatements || 16000;
this.jsonStrings = options.jsonStrings || false;
}
static mergeFlags(default_flags, user_flags) {
let flags = 0x0,
i;
if (!Array.isArray(user_flags)) {
user_flags = String(user_flags || '')
.toUpperCase()
.split(/\s*,+\s*/);
}
// add default flags unless "blacklisted"
for (i in default_flags) {
if (user_flags.indexOf(`-${default_flags[i]}`) >= 0) {
continue;
}
flags |= ClientConstants[default_flags[i]] || 0x0;
}
// add user flags unless already already added
for (i in user_flags) {
if (user_flags[i][0] === '-') {
continue;
}
if (default_flags.indexOf(user_flags[i]) >= 0) {
continue;
}
flags |= ClientConstants[user_flags[i]] || 0x0;
}
return flags;
}
static getDefaultFlags(options) {
const defaultFlags = [
'LONG_PASSWORD',
'FOUND_ROWS',
'LONG_FLAG',
'CONNECT_WITH_DB',
'ODBC',
'LOCAL_FILES',
'IGNORE_SPACE',
'PROTOCOL_41',
'IGNORE_SIGPIPE',
'TRANSACTIONS',
'RESERVED',
'SECURE_CONNECTION',
'MULTI_RESULTS',
'TRANSACTIONS',
'SESSION_TRACK',
'CONNECT_ATTRS'
];
if (options && options.multipleStatements) {
defaultFlags.push('MULTI_STATEMENTS');
}
defaultFlags.push('PLUGIN_AUTH');
defaultFlags.push('PLUGIN_AUTH_LENENC_CLIENT_DATA');
return defaultFlags;
}
static getCharsetNumber(charset) {
const num = Charsets[charset.toUpperCase()];
if (num === undefined) {
throw new TypeError(`Unknown charset '${charset}'`);
}
return num;
}
static getSSLProfile(name) {
if (!SSLProfiles) {
SSLProfiles = require('./constants/ssl_profiles.js');
}
const ssl = SSLProfiles[name];
if (ssl === undefined) {
throw new TypeError(`Unknown SSL profile '${name}'`);
}
return ssl;
}
static parseUrl(url) {
const parsedUrl = new URL(url);
const options = {
host: decodeURIComponent(parsedUrl.hostname),
port: parseInt(parsedUrl.port, 10),
database: decodeURIComponent(parsedUrl.pathname.slice(1)),
user: decodeURIComponent(parsedUrl.username),
password: decodeURIComponent(parsedUrl.password),
};
parsedUrl.searchParams.forEach((value, 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;
}
}
module.exports = ConnectionConfig;

316
node_modules/mysql2/lib/constants/charset_encodings.js generated vendored Normal file
View File

@@ -0,0 +1,316 @@
'use strict';
// see tools/generate-charset-mapping.js
// basicalliy result of "SHOW COLLATION" query
module.exports = [
'utf8',
'big5',
'latin2',
'dec8',
'cp850',
'latin1',
'hp8',
'koi8r',
'latin1',
'latin2',
'swe7',
'ascii',
'eucjp',
'sjis',
'cp1251',
'latin1',
'hebrew',
'utf8',
'tis620',
'euckr',
'latin7',
'latin2',
'koi8u',
'cp1251',
'gb2312',
'greek',
'cp1250',
'latin2',
'gbk',
'cp1257',
'latin5',
'latin1',
'armscii8',
'cesu8',
'cp1250',
'ucs2',
'cp866',
'keybcs2',
'macintosh',
'macroman',
'cp852',
'latin7',
'latin7',
'macintosh',
'cp1250',
'utf8',
'utf8',
'latin1',
'latin1',
'latin1',
'cp1251',
'cp1251',
'cp1251',
'macroman',
'utf16',
'utf16',
'utf16-le',
'cp1256',
'cp1257',
'cp1257',
'utf32',
'utf32',
'utf16-le',
'binary',
'armscii8',
'ascii',
'cp1250',
'cp1256',
'cp866',
'dec8',
'greek',
'hebrew',
'hp8',
'keybcs2',
'koi8r',
'koi8u',
'cesu8',
'latin2',
'latin5',
'latin7',
'cp850',
'cp852',
'swe7',
'cesu8',
'big5',
'euckr',
'gb2312',
'gbk',
'sjis',
'tis620',
'ucs2',
'eucjp',
'geostd8',
'geostd8',
'latin1',
'cp932',
'cp932',
'eucjpms',
'eucjpms',
'cp1250',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf8',
'utf8',
'utf8',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'ucs2',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'cesu8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'gb18030',
'gb18030',
'gb18030',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8'
];

317
node_modules/mysql2/lib/constants/charsets.js generated vendored Normal file
View File

@@ -0,0 +1,317 @@
'use strict';
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.UTF8_TOLOWER_CI = 76;
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_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_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_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_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_CI = 245;
exports.UTF8MB4_UNICODE_520_CI = 246;
exports.UTF8MB4_VIETNAMESE_CI = 247;
exports.GB18030_CHINESE_CI = 248;
exports.GB18030_BIN = 249;
exports.GB18030_UNICODE_520_CI = 250;
exports.UTF8_GENERAL50_CI = 253; // deprecated
exports.UTF8MB4_0900_AI_CI = 255;
exports.UTF8MB4_DE_PB_0900_AI_CI = 256;
exports.UTF8MB4_IS_0900_AI_CI = 257;
exports.UTF8MB4_LV_0900_AI_CI = 258;
exports.UTF8MB4_RO_0900_AI_CI = 259;
exports.UTF8MB4_SL_0900_AI_CI = 260;
exports.UTF8MB4_PL_0900_AI_CI = 261;
exports.UTF8MB4_ET_0900_AI_CI = 262;
exports.UTF8MB4_ES_0900_AI_CI = 263;
exports.UTF8MB4_SV_0900_AI_CI = 264;
exports.UTF8MB4_TR_0900_AI_CI = 265;
exports.UTF8MB4_CS_0900_AI_CI = 266;
exports.UTF8MB4_DA_0900_AI_CI = 267;
exports.UTF8MB4_LT_0900_AI_CI = 268;
exports.UTF8MB4_SK_0900_AI_CI = 269;
exports.UTF8MB4_ES_TRAD_0900_AI_CI = 270;
exports.UTF8MB4_LA_0900_AI_CI = 271;
exports.UTF8MB4_EO_0900_AI_CI = 273;
exports.UTF8MB4_HU_0900_AI_CI = 274;
exports.UTF8MB4_HR_0900_AI_CI = 275;
exports.UTF8MB4_VI_0900_AI_CI = 277;
exports.UTF8MB4_0900_AS_CS = 278;
exports.UTF8MB4_DE_PB_0900_AS_CS = 279;
exports.UTF8MB4_IS_0900_AS_CS = 280;
exports.UTF8MB4_LV_0900_AS_CS = 281;
exports.UTF8MB4_RO_0900_AS_CS = 282;
exports.UTF8MB4_SL_0900_AS_CS = 283;
exports.UTF8MB4_PL_0900_AS_CS = 284;
exports.UTF8MB4_ET_0900_AS_CS = 285;
exports.UTF8MB4_ES_0900_AS_CS = 286;
exports.UTF8MB4_SV_0900_AS_CS = 287;
exports.UTF8MB4_TR_0900_AS_CS = 288;
exports.UTF8MB4_CS_0900_AS_CS = 289;
exports.UTF8MB4_DA_0900_AS_CS = 290;
exports.UTF8MB4_LT_0900_AS_CS = 291;
exports.UTF8MB4_SK_0900_AS_CS = 292;
exports.UTF8MB4_ES_TRAD_0900_AS_CS = 293;
exports.UTF8MB4_LA_0900_AS_CS = 294;
exports.UTF8MB4_EO_0900_AS_CS = 296;
exports.UTF8MB4_HU_0900_AS_CS = 297;
exports.UTF8MB4_HR_0900_AS_CS = 298;
exports.UTF8MB4_VI_0900_AS_CS = 300;
exports.UTF8MB4_JA_0900_AS_CS = 303;
exports.UTF8MB4_JA_0900_AS_CS_KS = 304;
exports.UTF8MB4_0900_AS_CI = 305;
exports.UTF8MB4_RU_0900_AI_CI = 306;
exports.UTF8MB4_RU_0900_AS_CS = 307;
exports.UTF8MB4_ZH_0900_AS_CS = 308;
exports.UTF8MB4_0900_BIN = 309;
// short aliases
exports.BIG5 = exports.BIG5_CHINESE_CI;
exports.DEC8 = exports.DEC8_SWEDISH_CI;
exports.CP850 = exports.CP850_GENERAL_CI;
exports.HP8 = exports.HP8_ENGLISH_CI;
exports.KOI8R = exports.KOI8R_GENERAL_CI;
exports.LATIN1 = exports.LATIN1_SWEDISH_CI;
exports.LATIN2 = exports.LATIN2_GENERAL_CI;
exports.SWE7 = exports.SWE7_SWEDISH_CI;
exports.ASCII = exports.ASCII_GENERAL_CI;
exports.UJIS = exports.UJIS_JAPANESE_CI;
exports.SJIS = exports.SJIS_JAPANESE_CI;
exports.HEBREW = exports.HEBREW_GENERAL_CI;
exports.TIS620 = exports.TIS620_THAI_CI;
exports.EUCKR = exports.EUCKR_KOREAN_CI;
exports.KOI8U = exports.KOI8U_GENERAL_CI;
exports.GB2312 = exports.GB2312_CHINESE_CI;
exports.GREEK = exports.GREEK_GENERAL_CI;
exports.CP1250 = exports.CP1250_GENERAL_CI;
exports.GBK = exports.GBK_CHINESE_CI;
exports.LATIN5 = exports.LATIN5_TURKISH_CI;
exports.ARMSCII8 = exports.ARMSCII8_GENERAL_CI;
exports.UTF8 = exports.UTF8_GENERAL_CI;
exports.UCS2 = exports.UCS2_GENERAL_CI;
exports.CP866 = exports.CP866_GENERAL_CI;
exports.KEYBCS2 = exports.KEYBCS2_GENERAL_CI;
exports.MACCE = exports.MACCE_GENERAL_CI;
exports.MACROMAN = exports.MACROMAN_GENERAL_CI;
exports.CP852 = exports.CP852_GENERAL_CI;
exports.LATIN7 = exports.LATIN7_GENERAL_CI;
exports.UTF8MB4 = exports.UTF8MB4_GENERAL_CI;
exports.CP1251 = exports.CP1251_GENERAL_CI;
exports.UTF16 = exports.UTF16_GENERAL_CI;
exports.UTF16LE = exports.UTF16LE_GENERAL_CI;
exports.CP1256 = exports.CP1256_GENERAL_CI;
exports.CP1257 = exports.CP1257_GENERAL_CI;
exports.UTF32 = exports.UTF32_GENERAL_CI;
exports.CP932 = exports.CP932_JAPANESE_CI;
exports.EUCJPMS = exports.EUCJPMS_JAPANESE_CI;
exports.GB18030 = exports.GB18030_CHINESE_CI;
exports.GEOSTD8 = exports.GEOSTD8_GENERAL_CI;

39
node_modules/mysql2/lib/constants/client.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
// This file was modified by Oracle on September 21, 2021.
// New capability for multi-factor authentication based on mandatory session
// trackers, that are signaled with an extra single-byte prefix on new
// versions of the MySQL server.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.LONG_PASSWORD = 0x00000001; /* new more secure passwords */
exports.FOUND_ROWS = 0x00000002; /* found instead of affected rows */
exports.LONG_FLAG = 0x00000004; /* get all column flags */
exports.CONNECT_WITH_DB = 0x00000008; /* one can specify db on connect */
exports.NO_SCHEMA = 0x00000010; /* don't allow database.table.column */
exports.COMPRESS = 0x00000020; /* can use compression protocol */
exports.ODBC = 0x00000040; /* odbc client */
exports.LOCAL_FILES = 0x00000080; /* can use LOAD DATA LOCAL */
exports.IGNORE_SPACE = 0x00000100; /* ignore spaces before '' */
exports.PROTOCOL_41 = 0x00000200; /* new 4.1 protocol */
exports.INTERACTIVE = 0x00000400; /* this is an interactive client */
exports.SSL = 0x00000800; /* switch to ssl after handshake */
exports.IGNORE_SIGPIPE = 0x00001000; /* IGNORE sigpipes */
exports.TRANSACTIONS = 0x00002000; /* client knows about transactions */
exports.RESERVED = 0x00004000; /* old flag for 4.1 protocol */
exports.SECURE_CONNECTION = 0x00008000; /* new 4.1 authentication */
exports.MULTI_STATEMENTS = 0x00010000; /* enable/disable multi-stmt support */
exports.MULTI_RESULTS = 0x00020000; /* enable/disable multi-results */
exports.PS_MULTI_RESULTS = 0x00040000; /* multi-results in ps-protocol */
exports.PLUGIN_AUTH = 0x00080000; /* client supports plugin authentication */
exports.CONNECT_ATTRS = 0x00100000; /* permits connection attributes */
exports.PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000; /* Understands length-encoded integer for auth response data in Protocol::HandshakeResponse41. */
exports.CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000; /* Announces support for expired password extension. */
exports.SESSION_TRACK = 0x00800000; /* Can set SERVER_SESSION_STATE_CHANGED in the Status Flags and send session-state change data after a OK packet. */
exports.DEPRECATE_EOF = 0x01000000; /* Can send OK after a Text Resultset. */
exports.SSL_VERIFY_SERVER_CERT = 0x40000000;
exports.REMEMBER_OPTIONS = 0x80000000;
exports.MULTI_FACTOR_AUTHENTICATION = 0x10000000; /* multi-factor authentication */

36
node_modules/mysql2/lib/constants/commands.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict';
module.exports = {
SLEEP: 0x00, // deprecated
QUIT: 0x01,
INIT_DB: 0x02,
QUERY: 0x03,
FIELD_LIST: 0x04,
CREATE_DB: 0x05,
DROP_DB: 0x06,
REFRESH: 0x07,
SHUTDOWN: 0x08,
STATISTICS: 0x09,
PROCESS_INFO: 0x0a, // deprecated
CONNECT: 0x0b, // deprecated
PROCESS_KILL: 0x0c,
DEBUG: 0x0d,
PING: 0x0e,
TIME: 0x0f, // deprecated
DELAYED_INSERT: 0x10, // deprecated
CHANGE_USER: 0x11,
BINLOG_DUMP: 0x12,
TABLE_DUMP: 0x13,
CONNECT_OUT: 0x14,
REGISTER_SLAVE: 0x15,
STMT_PREPARE: 0x16,
STMT_EXECUTE: 0x17,
STMT_SEND_LONG_DATA: 0x18,
STMT_CLOSE: 0x19,
STMT_RESET: 0x1a,
SET_OPTION: 0x1b,
STMT_FETCH: 0x1c,
DAEMON: 0x1d, // deprecated
BINLOG_DUMP_GTID: 0x1e,
UNKNOWN: 0xff // bad!
};

8
node_modules/mysql2/lib/constants/cursor.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
module.exports = {
NO_CURSOR: 0,
READ_ONLY: 1,
FOR_UPDATE: 2,
SCROLLABLE: 3
};

49
node_modules/mysql2/lib/constants/encoding_charset.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
'use strict';
// inverse of charset_encodings
// given encoding, get matching mysql charset number
module.exports = {
big5: 1,
latin2: 2,
dec8: 3,
cp850: 4,
latin1: 5,
hp8: 6,
koi8r: 7,
swe7: 10,
ascii: 11,
eucjp: 12,
sjis: 13,
cp1251: 14,
hebrew: 16,
tis620: 18,
euckr: 19,
latin7: 20,
koi8u: 22,
gb2312: 24,
greek: 25,
cp1250: 26,
gbk: 28,
cp1257: 29,
latin5: 30,
armscii8: 32,
cesu8: 33,
ucs2: 35,
cp866: 36,
keybcs2: 37,
macintosh: 38,
macroman: 39,
cp852: 40,
utf8: 45,
utf8mb4: 45,
utf16: 54,
utf16le: 56,
cp1256: 57,
utf32: 60,
binary: 63,
geostd8: 92,
cp932: 95,
eucjpms: 97,
gb18030: 248
};

3968
node_modules/mysql2/lib/constants/errors.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

20
node_modules/mysql2/lib/constants/field_flags.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.NOT_NULL = 1; /* Field can't be NULL */
exports.PRI_KEY = 2; /* Field is part of a primary key */
exports.UNIQUE_KEY = 4; /* Field is part of a unique key */
exports.MULTIPLE_KEY = 8; /* Field is part of a key */
exports.BLOB = 16; /* Field is a blob */
exports.UNSIGNED = 32; /* Field is unsigned */
exports.ZEROFILL = 64; /* Field is zerofill */
exports.BINARY = 128; /* Field is binary */
/* The following are only sent to new clients */
exports.ENUM = 256; /* field is an enum */
exports.AUTO_INCREMENT = 512; /* field is a autoincrement field */
exports.TIMESTAMP = 1024; /* Field is a timestamp */
exports.SET = 2048; /* field is a set */
exports.NO_DEFAULT_VALUE = 4096; /* Field doesn't have default value */
exports.ON_UPDATE_NOW = 8192; /* Field is set to NOW on UPDATE */
exports.NUM = 32768; /* Field is num (for clients) */

44
node_modules/mysql2/lib/constants/server_status.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
'use strict';
// 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;
exports.SERVER_STATUS_IN_TRANS_READONLY = 0x2000; // in a read-only transaction
exports.SERVER_SESSION_STATE_CHANGED = 0x4000;

11
node_modules/mysql2/lib/constants/session_track.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
exports.SYSTEM_VARIABLES = 0;
exports.SCHEMA = 1;
exports.STATE_CHANGE = 2;
exports.STATE_GTIDS = 3;
exports.TRANSACTION_CHARACTERISTICS = 4;
exports.TRANSACTION_STATE = 5;
exports.FIRST_KEY = exports.SYSTEM_VARIABLES;
exports.LAST_KEY = exports.TRANSACTION_STATE;

11
node_modules/mysql2/lib/constants/ssl_profiles.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
const awsCaBundle = require('aws-ssl-profiles');
/**
* @deprecated
* Please, use [**aws-ssl-profiles**](https://github.com/mysqljs/aws-ssl-profiles).
*/
exports['Amazon RDS'] = {
ca: awsCaBundle.ca,
};

65
node_modules/mysql2/lib/constants/types.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
'use strict';
module.exports = {
0x00: 'DECIMAL', // aka DECIMAL
0x01: 'TINY', // aka TINYINT, 1 byte
0x02: 'SHORT', // aka SMALLINT, 2 bytes
0x03: 'LONG', // aka INT, 4 bytes
0x04: 'FLOAT', // aka FLOAT, 4-8 bytes
0x05: 'DOUBLE', // aka DOUBLE, 8 bytes
0x06: 'NULL', // NULL (used for prepared statements, I think)
0x07: 'TIMESTAMP', // aka TIMESTAMP
0x08: 'LONGLONG', // aka BIGINT, 8 bytes
0x09: 'INT24', // aka MEDIUMINT, 3 bytes
0x0a: 'DATE', // aka DATE
0x0b: 'TIME', // aka TIME
0x0c: 'DATETIME', // aka DATETIME
0x0d: 'YEAR', // aka YEAR, 1 byte (don't ask)
0x0e: 'NEWDATE', // aka ?
0x0f: 'VARCHAR', // aka VARCHAR (?)
0x10: 'BIT', // aka BIT, 1-8 byte
0xf5: 'JSON',
0xf6: 'NEWDECIMAL', // aka DECIMAL
0xf7: 'ENUM', // aka ENUM
0xf8: 'SET', // aka SET
0xf9: 'TINY_BLOB', // aka TINYBLOB, TINYTEXT
0xfa: 'MEDIUM_BLOB', // aka MEDIUMBLOB, MEDIUMTEXT
0xfb: 'LONG_BLOB', // aka LONGBLOG, LONGTEXT
0xfc: 'BLOB', // aka BLOB, TEXT
0xfd: 'VAR_STRING', // aka VARCHAR, VARBINARY
0xfe: 'STRING', // aka CHAR, BINARY
0xff: 'GEOMETRY' // aka GEOMETRY
};
// Manually extracted from mysql-5.5.23/include/mysql_com.h
// some more info here: http://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-statement-type-codes.html
module.exports.DECIMAL = 0x00; // aka DECIMAL (http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html)
module.exports.TINY = 0x01; // aka TINYINT, 1 byte
module.exports.SHORT = 0x02; // aka SMALLINT, 2 bytes
module.exports.LONG = 0x03; // aka INT, 4 bytes
module.exports.FLOAT = 0x04; // aka FLOAT, 4-8 bytes
module.exports.DOUBLE = 0x05; // aka DOUBLE, 8 bytes
module.exports.NULL = 0x06; // NULL (used for prepared statements, I think)
module.exports.TIMESTAMP = 0x07; // aka TIMESTAMP
module.exports.LONGLONG = 0x08; // aka BIGINT, 8 bytes
module.exports.INT24 = 0x09; // aka MEDIUMINT, 3 bytes
module.exports.DATE = 0x0a; // aka DATE
module.exports.TIME = 0x0b; // aka TIME
module.exports.DATETIME = 0x0c; // aka DATETIME
module.exports.YEAR = 0x0d; // aka YEAR, 1 byte (don't ask)
module.exports.NEWDATE = 0x0e; // aka ?
module.exports.VARCHAR = 0x0f; // aka VARCHAR (?)
module.exports.BIT = 0x10; // aka BIT, 1-8 byte
module.exports.VECTOR = 0xf2;
module.exports.JSON = 0xf5;
module.exports.NEWDECIMAL = 0xf6; // aka DECIMAL
module.exports.ENUM = 0xf7; // aka ENUM
module.exports.SET = 0xf8; // aka SET
module.exports.TINY_BLOB = 0xf9; // aka TINYBLOB, TINYTEXT
module.exports.MEDIUM_BLOB = 0xfa; // aka MEDIUMBLOB, MEDIUMTEXT
module.exports.LONG_BLOB = 0xfb; // aka LONGBLOG, LONGTEXT
module.exports.BLOB = 0xfc; // aka BLOB, TEXT
module.exports.VAR_STRING = 0xfd; // aka VARCHAR, VARBINARY
module.exports.STRING = 0xfe; // aka CHAR, BINARY
module.exports.GEOMETRY = 0xff; // aka GEOMETRY

87
node_modules/mysql2/lib/helpers.js generated vendored Normal file
View File

@@ -0,0 +1,87 @@
'use strict';
/*
this seems to be not only shorter, but faster than
string.replace(/\\/g, '\\\\').
replace(/\u0008/g, '\\b').
replace(/\t/g, '\\t').
replace(/\n/g, '\\n').
replace(/\f/g, '\\f').
replace(/\r/g, '\\r').
replace(/'/g, '\\\'').
replace(/"/g, '\\"');
or string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
see http://jsperf.com/string-escape-regexp-vs-json-stringify
*/
function srcEscape(str) {
return JSON.stringify({
[str]: 1,
}).slice(1, -3);
}
exports.srcEscape = srcEscape;
let highlightFn;
let cardinalRecommended = false;
try {
// the purpose of this is to prevent projects using Webpack from displaying a warning during runtime if cardinal is not a dependency
const REQUIRE_TERMINATOR = '';
highlightFn = require(`cardinal${REQUIRE_TERMINATOR}`).highlight;
} catch (err) {
highlightFn = (text) => {
if (!cardinalRecommended) {
// eslint-disable-next-line no-console
console.log('For nicer debug output consider install cardinal@^2.0.0');
cardinalRecommended = true;
}
return text;
};
}
/**
* Prints debug message with code frame, will try to use `cardinal` if available.
*/
function printDebugWithCode(msg, code) {
// eslint-disable-next-line no-console
console.log(`\n\n${msg}:\n`);
// eslint-disable-next-line no-console
console.log(`${highlightFn(code)}\n`);
}
exports.printDebugWithCode = printDebugWithCode;
/**
* checks whether the `type` is in the `list`
*/
function typeMatch(type, list, Types) {
if (Array.isArray(list)) {
return list.some((t) => type === Types[t]);
}
return !!list;
}
exports.typeMatch = typeMatch;
const privateObjectProps = new Set([
'__defineGetter__',
'__defineSetter__',
'__lookupGetter__',
'__lookupSetter__',
'__proto__',
]);
exports.privateObjectProps = privateObjectProps;
const fieldEscape = (field) => {
if (privateObjectProps.has(field)) {
throw new Error(
`The field name (${field}) can't be the same as an object's private property.`,
);
}
return srcEscape(field);
};
exports.fieldEscape = fieldEscape;

195
node_modules/mysql2/lib/packet_parser.js generated vendored Normal file
View File

@@ -0,0 +1,195 @@
'use strict';
const Packet = require('./packets/packet.js');
const MAX_PACKET_LENGTH = 16777215;
function readPacketLength(b, off) {
const b0 = b[off];
const b1 = b[off + 1];
const b2 = b[off + 2];
if (b1 + b2 === 0) {
return b0;
}
return b0 + (b1 << 8) + (b2 << 16);
}
class PacketParser {
constructor(onPacket, packetHeaderLength) {
// 4 for normal packets, 7 for comprssed protocol packets
if (typeof packetHeaderLength === 'undefined') {
packetHeaderLength = 4;
}
// array of last payload chunks
// only used when current payload is not complete
this.buffer = [];
// total length of chunks on buffer
this.bufferLength = 0;
this.packetHeaderLength = packetHeaderLength;
// incomplete header state: number of header bytes received
this.headerLen = 0;
// expected payload length
this.length = 0;
this.largePacketParts = [];
this.firstPacketSequenceId = 0;
this.onPacket = onPacket;
this.execute = PacketParser.prototype.executeStart;
this._flushLargePacket =
packetHeaderLength === 7
? this._flushLargePacket7
: this._flushLargePacket4;
}
_flushLargePacket4() {
const numPackets = this.largePacketParts.length;
this.largePacketParts.unshift(Buffer.from([0, 0, 0, 0])); // insert header
const body = Buffer.concat(this.largePacketParts);
const packet = new Packet(this.firstPacketSequenceId, body, 0, body.length);
this.largePacketParts.length = 0;
packet.numPackets = numPackets;
this.onPacket(packet);
}
_flushLargePacket7() {
const numPackets = this.largePacketParts.length;
this.largePacketParts.unshift(Buffer.from([0, 0, 0, 0, 0, 0, 0])); // insert header
const body = Buffer.concat(this.largePacketParts);
this.largePacketParts.length = 0;
const packet = new Packet(this.firstPacketSequenceId, body, 0, body.length);
packet.numPackets = numPackets;
this.onPacket(packet);
}
executeStart(chunk) {
let start = 0;
const end = chunk.length;
while (end - start >= 3) {
this.length = readPacketLength(chunk, start);
if (end - start >= this.length + this.packetHeaderLength) {
// at least one full packet
const sequenceId = chunk[start + 3];
if (
this.length < MAX_PACKET_LENGTH &&
this.largePacketParts.length === 0
) {
this.onPacket(
new Packet(
sequenceId,
chunk,
start,
start + this.packetHeaderLength + this.length
)
);
} else {
// first large packet - remember it's id
if (this.largePacketParts.length === 0) {
this.firstPacketSequenceId = sequenceId;
}
this.largePacketParts.push(
chunk.slice(
start + this.packetHeaderLength,
start + this.packetHeaderLength + this.length
)
);
if (this.length < MAX_PACKET_LENGTH) {
this._flushLargePacket();
}
}
start += this.packetHeaderLength + this.length;
} else {
// payload is incomplete
this.buffer = [chunk.slice(start + 3, end)];
this.bufferLength = end - start - 3;
this.execute = PacketParser.prototype.executePayload;
return;
}
}
if (end - start > 0) {
// there is start of length header, but it's not full 3 bytes
this.headerLen = end - start; // 1 or 2 bytes
this.length = chunk[start];
if (this.headerLen === 2) {
this.length = chunk[start] + (chunk[start + 1] << 8);
this.execute = PacketParser.prototype.executeHeader3;
} else {
this.execute = PacketParser.prototype.executeHeader2;
}
}
}
executePayload(chunk) {
let start = 0;
const end = chunk.length;
const remainingPayload =
this.length - this.bufferLength + this.packetHeaderLength - 3;
if (end - start >= remainingPayload) {
// last chunk for payload
const payload = Buffer.allocUnsafe(this.length + this.packetHeaderLength);
let offset = 3;
for (let i = 0; i < this.buffer.length; ++i) {
this.buffer[i].copy(payload, offset);
offset += this.buffer[i].length;
}
chunk.copy(payload, offset, start, start + remainingPayload);
const sequenceId = payload[3];
if (
this.length < MAX_PACKET_LENGTH &&
this.largePacketParts.length === 0
) {
this.onPacket(
new Packet(
sequenceId,
payload,
0,
this.length + this.packetHeaderLength
)
);
} else {
// first large packet - remember it's id
if (this.largePacketParts.length === 0) {
this.firstPacketSequenceId = sequenceId;
}
this.largePacketParts.push(
payload.slice(
this.packetHeaderLength,
this.packetHeaderLength + this.length
)
);
if (this.length < MAX_PACKET_LENGTH) {
this._flushLargePacket();
}
}
this.buffer = [];
this.bufferLength = 0;
this.execute = PacketParser.prototype.executeStart;
start += remainingPayload;
if (end - start > 0) {
return this.execute(chunk.slice(start, end));
}
} else {
this.buffer.push(chunk);
this.bufferLength += chunk.length;
}
return null;
}
executeHeader2(chunk) {
this.length += chunk[0] << 8;
if (chunk.length > 1) {
this.length += chunk[1] << 16;
this.execute = PacketParser.prototype.executePayload;
return this.executePayload(chunk.slice(2));
}
this.execute = PacketParser.prototype.executeHeader3;
return null;
}
executeHeader3(chunk) {
this.length += chunk[0] << 16;
this.execute = PacketParser.prototype.executePayload;
return this.executePayload(chunk.slice(1));
}
}
module.exports = PacketParser;

35
node_modules/mysql2/lib/packets/auth_next_factor.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
// Copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const Packet = require('../packets/packet');
class AuthNextFactor {
constructor(opts) {
this.pluginName = opts.pluginName;
this.pluginData = opts.pluginData;
}
toPacket(encoding) {
const length = 6 + this.pluginName.length + this.pluginData.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0x02);
packet.writeNullTerminatedString(this.pluginName, encoding);
packet.writeBuffer(this.pluginData);
return packet;
}
static fromPacket(packet, encoding) {
packet.readInt8(); // marker
const name = packet.readNullTerminatedString(encoding);
const data = packet.readBuffer();
return new AuthNextFactor({
pluginName: name,
pluginData: data
});
}
}
module.exports = AuthNextFactor;

38
node_modules/mysql2/lib/packets/auth_switch_request.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchRequest {
constructor(opts) {
this.pluginName = opts.pluginName;
this.pluginData = opts.pluginData;
}
toPacket() {
const length = 6 + this.pluginName.length + this.pluginData.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0xfe);
// TODO: use server encoding
packet.writeNullTerminatedString(this.pluginName, 'cesu8');
packet.writeBuffer(this.pluginData);
return packet;
}
static fromPacket(packet) {
packet.readInt8(); // marker
// assert marker == 0xfe?
// TODO: use server encoding
const name = packet.readNullTerminatedString('cesu8');
const data = packet.readBuffer();
return new AuthSwitchRequest({
pluginName: name,
pluginData: data
});
}
}
module.exports = AuthSwitchRequest;

View File

@@ -0,0 +1,33 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchRequestMoreData {
constructor(data) {
this.data = data;
}
toPacket() {
const length = 5 + this.data.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0x01);
packet.writeBuffer(this.data);
return packet;
}
static fromPacket(packet) {
packet.readInt8(); // marker
const data = packet.readBuffer();
return new AuthSwitchRequestMoreData(data);
}
static verifyMarker(packet) {
return packet.peekByte() === 0x01;
}
}
module.exports = AuthSwitchRequestMoreData;

View File

@@ -0,0 +1,30 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchResponse {
constructor(data) {
if (!Buffer.isBuffer(data)) {
data = Buffer.from(data);
}
this.data = data;
}
toPacket() {
const length = 4 + this.data.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeBuffer(this.data);
return packet;
}
static fromPacket(packet) {
const data = packet.readBuffer();
return new AuthSwitchResponse(data);
}
}
module.exports = AuthSwitchResponse;

95
node_modules/mysql2/lib/packets/binary_row.js generated vendored Normal file
View File

@@ -0,0 +1,95 @@
'use strict';
const Types = require('../constants/types');
const Packet = require('../packets/packet');
const binaryReader = new Array(256);
class BinaryRow {
constructor(columns) {
this.columns = columns || [];
}
static toPacket(columns, encoding) {
// throw new Error('Not implemented');
const sequenceId = 0; // TODO remove, this is calculated now in connecton
let length = 0;
columns.forEach(val => {
if (val === null || typeof val === 'undefined') {
++length;
return;
}
length += Packet.lengthCodedStringLength(val.toString(10), encoding);
});
length = length + 2;
const buffer = Buffer.allocUnsafe(length + 4);
const packet = new Packet(sequenceId, buffer, 0, length + 4);
packet.offset = 4;
packet.writeInt8(0);
let bitmap = 0;
let bitValue = 1;
columns.forEach(parameter => {
if (parameter.type === Types.NULL) {
bitmap += bitValue;
}
bitValue *= 2;
if (bitValue === 256) {
packet.writeInt8(bitmap);
bitmap = 0;
bitValue = 1;
}
});
if (bitValue !== 1) {
packet.writeInt8(bitmap);
}
columns.forEach(val => {
if (val === null) {
packet.writeNull();
return;
}
if (typeof val === 'undefined') {
packet.writeInt8(0);
return;
}
packet.writeLengthCodedString(val.toString(10), encoding);
});
return packet;
}
// TODO: complete list of types...
static fromPacket(fields, packet) {
const columns = new Array(fields.length);
packet.readInt8(); // TODO check it's 0
const nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
// TODO: read and interpret null bitmap
packet.skip(nullBitmapLength);
for (let i = 0; i < columns.length; ++i) {
columns[i] = binaryReader[fields[i].columnType].apply(packet);
}
return new BinaryRow(columns);
}
}
// TODO: replace with constants.MYSQL_TYPE_*
binaryReader[Types.DECIMAL] = Packet.prototype.readLengthCodedString;
binaryReader[1] = Packet.prototype.readInt8; // tiny
binaryReader[2] = Packet.prototype.readInt16; // short
binaryReader[3] = Packet.prototype.readInt32; // long
binaryReader[4] = Packet.prototype.readFloat; // float
binaryReader[5] = Packet.prototype.readDouble; // double
binaryReader[6] = Packet.prototype.assertInvalid; // null, should be skipped vie null bitmap
binaryReader[7] = Packet.prototype.readTimestamp; // timestamp, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIMESTAMP
binaryReader[8] = Packet.prototype.readInt64; // long long
binaryReader[9] = Packet.prototype.readInt32; // int24
binaryReader[10] = Packet.prototype.readTimestamp; // date
binaryReader[11] = Packet.prototype.readTime; // time, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIME
binaryReader[12] = Packet.prototype.readDateTime; // datetime, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_DATETIME
binaryReader[13] = Packet.prototype.readInt16; // year
binaryReader[Types.VAR_STRING] = Packet.prototype.readLengthCodedString; // var string
module.exports = BinaryRow;

33
node_modules/mysql2/lib/packets/binlog_dump.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/com-binlog-dump.html#packet-COM_BINLOG_DUMP
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
// TODO: add flag to constants
// 0x01 - BINLOG_DUMP_NON_BLOCK
// send EOF instead of blocking
class BinlogDump {
constructor(opts) {
this.binlogPos = opts.binlogPos || 0;
this.serverId = opts.serverId || 0;
this.flags = opts.flags || 0;
this.filename = opts.filename || '';
}
toPacket() {
const length = 15 + Buffer.byteLength(this.filename, 'utf8'); // TODO: should be ascii?
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.BINLOG_DUMP);
packet.writeInt32(this.binlogPos);
packet.writeInt16(this.flags);
packet.writeInt32(this.serverId);
packet.writeString(this.filename);
return packet;
}
}
module.exports = BinlogDump;

View File

@@ -0,0 +1,115 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/query-event.html
const keys = {
FLAGS2: 0,
SQL_MODE: 1,
CATALOG: 2,
AUTO_INCREMENT: 3,
CHARSET: 4,
TIME_ZONE: 5,
CATALOG_NZ: 6,
LC_TIME_NAMES: 7,
CHARSET_DATABASE: 8,
TABLE_MAP_FOR_UPDATE: 9,
MASTER_DATA_WRITTEN: 10,
INVOKERS: 11,
UPDATED_DB_NAMES: 12,
MICROSECONDS: 3
};
module.exports = function parseStatusVars(buffer) {
const result = {};
let offset = 0;
let key, length, prevOffset;
while (offset < buffer.length) {
key = buffer[offset++];
switch (key) {
case keys.FLAGS2:
result.flags = buffer.readUInt32LE(offset);
offset += 4;
break;
case keys.SQL_MODE:
// value is 8 bytes, but all dcumented flags are in first 4 bytes
result.sqlMode = buffer.readUInt32LE(offset);
offset += 8;
break;
case keys.CATALOG:
length = buffer[offset++];
result.catalog = buffer.toString('utf8', offset, offset + length);
offset += length + 1; // null byte after string
break;
case keys.CHARSET:
result.clientCharset = buffer.readUInt16LE(offset);
result.connectionCollation = buffer.readUInt16LE(offset + 2);
result.serverCharset = buffer.readUInt16LE(offset + 4);
offset += 6;
break;
case keys.TIME_ZONE:
length = buffer[offset++];
result.timeZone = buffer.toString('utf8', offset, offset + length);
offset += length; // no null byte
break;
case keys.CATALOG_NZ:
length = buffer[offset++];
result.catalogNz = buffer.toString('utf8', offset, offset + length);
offset += length; // no null byte
break;
case keys.LC_TIME_NAMES:
result.lcTimeNames = buffer.readUInt16LE(offset);
offset += 2;
break;
case keys.CHARSET_DATABASE:
result.schemaCharset = buffer.readUInt16LE(offset);
offset += 2;
break;
case keys.TABLE_MAP_FOR_UPDATE:
result.mapForUpdate1 = buffer.readUInt32LE(offset);
result.mapForUpdate2 = buffer.readUInt32LE(offset + 4);
offset += 8;
break;
case keys.MASTER_DATA_WRITTEN:
result.masterDataWritten = buffer.readUInt32LE(offset);
offset += 4;
break;
case keys.INVOKERS:
length = buffer[offset++];
result.invokerUsername = buffer.toString(
'utf8',
offset,
offset + length
);
offset += length;
length = buffer[offset++];
result.invokerHostname = buffer.toString(
'utf8',
offset,
offset + length
);
offset += length;
break;
case keys.UPDATED_DB_NAMES:
length = buffer[offset++];
// length - number of null-terminated strings
result.updatedDBs = []; // we'll store them as array here
for (; length; --length) {
prevOffset = offset;
// fast forward to null terminating byte
while (buffer[offset++] && offset < buffer.length) {
// empty body, everything inside while condition
}
result.updatedDBs.push(
buffer.toString('utf8', prevOffset, offset - 1)
);
}
break;
case keys.MICROSECONDS:
result.microseconds =
// REVIEW: INVALID UNKNOWN VARIABLE!
buffer.readInt16LE(offset) + (buffer[offset + 2] << 16);
offset += 3;
}
}
return result;
};

97
node_modules/mysql2/lib/packets/change_user.js generated vendored Normal file
View File

@@ -0,0 +1,97 @@
'use strict';
const CommandCode = require('../constants/commands.js');
const ClientConstants = require('../constants/client.js');
const Packet = require('../packets/packet.js');
const auth41 = require('../auth_41.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
// https://dev.mysql.com/doc/internals/en/com-change-user.html#packet-COM_CHANGE_USER
class ChangeUser {
constructor(opts) {
this.flags = opts.flags;
this.user = opts.user || '';
this.database = opts.database || '';
this.password = opts.password || '';
this.passwordSha1 = opts.passwordSha1;
this.authPluginData1 = opts.authPluginData1;
this.authPluginData2 = opts.authPluginData2;
this.connectAttributes = opts.connectAttrinutes || {};
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
this.authPluginData1,
this.authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
this.authPluginData1,
this.authPluginData2
);
}
this.authToken = authToken;
this.charsetNumber = opts.charsetNumber;
}
// TODO
// ChangeUser.fromPacket = function(packet)
// };
serializeToBuffer(buffer) {
const isSet = flag => this.flags & ClientConstants[flag];
const packet = new Packet(0, buffer, 0, buffer.length);
packet.offset = 4;
const encoding = CharsetToEncoding[this.charsetNumber];
packet.writeInt8(CommandCode.CHANGE_USER);
packet.writeNullTerminatedString(this.user, encoding);
if (isSet('SECURE_CONNECTION')) {
packet.writeInt8(this.authToken.length);
packet.writeBuffer(this.authToken);
} else {
packet.writeBuffer(this.authToken);
packet.writeInt8(0);
}
packet.writeNullTerminatedString(this.database, encoding);
packet.writeInt16(this.charsetNumber);
if (isSet('PLUGIN_AUTH')) {
// TODO: read this from parameters
packet.writeNullTerminatedString('mysql_native_password', 'latin1');
}
if (isSet('CONNECT_ATTRS')) {
const connectAttributes = this.connectAttributes;
const attrNames = Object.keys(connectAttributes);
let keysLength = 0;
for (let k = 0; k < attrNames.length; ++k) {
keysLength += Packet.lengthCodedStringLength(attrNames[k], encoding);
keysLength += Packet.lengthCodedStringLength(
connectAttributes[attrNames[k]],
encoding
);
}
packet.writeLengthCodedNumber(keysLength);
for (let k = 0; k < attrNames.length; ++k) {
packet.writeLengthCodedString(attrNames[k], encoding);
packet.writeLengthCodedString(
connectAttributes[attrNames[k]],
encoding
);
}
}
return packet;
}
toPacket() {
if (typeof this.user !== 'string') {
throw new Error('"user" connection config property must be a string');
}
if (typeof this.database !== 'string') {
throw new Error('"database" connection config property must be a string');
}
// dry run: calculate resulting packet length
const p = this.serializeToBuffer(Packet.MockBuffer());
return this.serializeToBuffer(Buffer.allocUnsafe(p.offset));
}
}
module.exports = ChangeUser;

21
node_modules/mysql2/lib/packets/close_statement.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
'use strict';
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
class CloseStatement {
constructor(id) {
this.id = id;
}
// note: no response sent back
toPacket() {
const packet = new Packet(0, Buffer.allocUnsafe(9), 0, 9);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_CLOSE);
packet.writeInt32(this.id);
return packet;
}
}
module.exports = CloseStatement;

290
node_modules/mysql2/lib/packets/column_definition.js generated vendored Normal file
View File

@@ -0,0 +1,290 @@
'use strict';
const Packet = require('../packets/packet');
const StringParser = require('../parsers/string');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const fields = ['catalog', 'schema', 'table', 'orgTable', 'name', 'orgName'];
// creating JS string is relatively expensive (compared to
// reading few bytes from buffer) because all string properties
// except for name are unlikely to be used we postpone
// string conversion until property access
//
// TODO: watch for integration benchmarks (one with real network buffer)
// there could be bad side effect as keeping reference to a buffer makes it
// sit in the memory longer (usually until final .query() callback)
// Latest v8 perform much better in regard to bufferer -> string conversion,
// at some point of time this optimisation might become unnecessary
// see https://github.com/sidorares/node-mysql2/pull/137
//
class ColumnDefinition {
constructor(packet, clientEncoding) {
this._buf = packet.buffer;
this._clientEncoding = clientEncoding;
this._catalogLength = packet.readLengthCodedNumber();
this._catalogStart = packet.offset;
packet.offset += this._catalogLength;
this._schemaLength = packet.readLengthCodedNumber();
this._schemaStart = packet.offset;
packet.offset += this._schemaLength;
this._tableLength = packet.readLengthCodedNumber();
this._tableStart = packet.offset;
packet.offset += this._tableLength;
this._orgTableLength = packet.readLengthCodedNumber();
this._orgTableStart = packet.offset;
packet.offset += this._orgTableLength;
// name is always used, don't make it lazy
const _nameLength = packet.readLengthCodedNumber();
const _nameStart = packet.offset;
packet.offset += _nameLength;
this._orgNameLength = packet.readLengthCodedNumber();
this._orgNameStart = packet.offset;
packet.offset += this._orgNameLength;
packet.skip(1); // length of the following fields (always 0x0c)
this.characterSet = packet.readInt16();
this.encoding = CharsetToEncoding[this.characterSet];
this.name = StringParser.decode(
this._buf,
this.encoding === 'binary' ? this._clientEncoding : this.encoding,
_nameStart,
_nameStart + _nameLength
);
this.columnLength = packet.readInt32();
this.columnType = packet.readInt8();
this.type = this.columnType;
this.flags = packet.readInt16();
this.decimals = packet.readInt8();
}
inspect() {
return {
catalog: this.catalog,
schema: this.schema,
name: this.name,
orgName: this.orgName,
table: this.table,
orgTable: this.orgTable,
characterSet: this.characterSet,
encoding: this.encoding,
columnLength: this.columnLength,
type: this.columnType,
flags: this.flags,
decimals: this.decimals
};
}
[Symbol.for('nodejs.util.inspect.custom')](depth, inspectOptions, inspect) {
const Types = require('../constants/types.js');
const typeNames = [];
for (const t in Types) {
typeNames[Types[t]] = t;
}
const fiedFlags = require('../constants/field_flags.js');
const flagNames = [];
// TODO: respect inspectOptions.showHidden
//const inspectFlags = inspectOptions.showHidden ? this.flags : this.flags & ~fiedFlags.PRI_KEY;
const inspectFlags = this.flags;
for (const f in fiedFlags) {
if (inspectFlags & fiedFlags[f]) {
if (f === 'PRI_KEY') {
flagNames.push('PRIMARY KEY');
} else if (f === 'NOT_NULL') {
flagNames.push('NOT NULL');
} else if (f === 'BINARY') {
// ignore flag for now
} else if (f === 'MULTIPLE_KEY') {
// not sure if that should be part of inspection.
// in the schema usually this is part of index definition
// example: UNIQUE KEY `my_uniq_id` (`id_box_elements`,`id_router`)
// note that only first column has MULTIPLE_KEY flag set in this case
// so there is no good way of knowing that this is part of index just
// by looking at indifidual field flags
} else if (f === 'NO_DEFAULT_VALUE') {
// almost the same as NOT_NULL?
} else if (f === 'BLOB') {
// included in the type
} else if (f === 'UNSIGNED') {
// this should be first after type
} else if (f === 'TIMESTAMP') {
// timestamp flag is redundant for inspection - already included in type
} else if (f === 'ON_UPDATE_NOW') {
flagNames.push('ON UPDATE CURRENT_TIMESTAMP');
} else {
flagNames.push(f);
}
}
}
if (depth > 1) {
return inspect({
...this.inspect(),
typeName: typeNames[this.columnType],
flags: flagNames,
});
}
const isUnsigned = this.flags & fiedFlags.UNSIGNED;
let typeName = typeNames[this.columnType];
if (typeName === 'BLOB') {
// TODO: check for non-utf8mb4 encoding
if (this.columnLength === 4294967295) {
typeName = 'LONGTEXT';
} else if (this.columnLength === 67108860) {
typeName = 'MEDIUMTEXT';
} else if (this.columnLength === 262140) {
typeName = 'TEXT';
} else if (this.columnLength === 1020) { // 255*4
typeName = 'TINYTEXT';
} else {
typeName = `BLOB(${this.columnLength})`;
}
} else if (typeName === 'VAR_STRING') {
// TODO: check for non-utf8mb4 encoding
typeName = `VARCHAR(${Math.ceil(this.columnLength/4)})`;
} else if (typeName === 'TINY') {
if (
(this.columnLength === 3 && isUnsigned) ||
(this.columnLength === 4 && !isUnsigned) ) {
typeName = 'TINYINT';
} else {
typeName = `TINYINT(${this.columnLength})`;
}
} else if (typeName === 'LONGLONG') {
if (this.columnLength === 20) {
typeName = 'BIGINT';
} else {
typeName = `BIGINT(${this.columnLength})`;
}
} else if (typeName === 'SHORT') {
if (isUnsigned && this.columnLength === 5) {
typeName = 'SMALLINT';
} else if (!isUnsigned && this.columnLength === 6) {
typeName = 'SMALLINT';
} else {
typeName = `SMALLINT(${this.columnLength})`;
}
} else if (typeName === 'LONG') {
if (isUnsigned && this.columnLength === 10) {
typeName = 'INT';
} else if (!isUnsigned && this.columnLength === 11) {
typeName = 'INT';
} else {
typeName = `INT(${this.columnLength})`;
}
} else if (typeName === 'INT24') {
if (isUnsigned && this.columnLength === 8) {
typeName = 'MEDIUMINT';
} else if (!isUnsigned && this.columnLength === 9) {
typeName = 'MEDIUMINT';
} else {
typeName = `MEDIUMINT(${this.columnLength})`;
}
} else if (typeName === 'DOUBLE') {
// DOUBLE without modifiers is reported as DOUBLE(22, 31)
if (this.columnLength === 22 && this.decimals === 31) {
typeName = 'DOUBLE';
} else {
typeName = `DOUBLE(${this.columnLength},${this.decimals})`;
}
} else if (typeName === 'FLOAT') {
// FLOAT without modifiers is reported as FLOAT(12, 31)
if (this.columnLength === 12 && this.decimals === 31) {
typeName = 'FLOAT';
} else {
typeName = `FLOAT(${this.columnLength},${this.decimals})`;
}
} else if (typeName === 'NEWDECIMAL') {
if (this.columnLength === 11 && this.decimals === 0) {
typeName = 'DECIMAL';
} else if (this.decimals === 0) {
// not sure why, but DECIMAL(13) is reported as DECIMAL(14, 0)
// and DECIMAL(13, 9) is reported as NEWDECIMAL(15, 9)
if (isUnsigned) {
typeName = `DECIMAL(${this.columnLength})`;
} else {
typeName = `DECIMAL(${this.columnLength - 1})`;
}
} else {
typeName = `DECIMAL(${this.columnLength - 2},${this.decimals})`;
}
} else {
typeName = `${typeNames[this.columnType]}(${this.columnLength})`;
}
if (isUnsigned) {
typeName += ' UNSIGNED';
}
// TODO respect colors option
return `\`${this.name}\` ${[typeName, ...flagNames].join(' ')}`;
}
static toPacket(column, sequenceId) {
let length = 17; // = 4 padding + 1 + 12 for the rest
fields.forEach(field => {
length += Packet.lengthCodedStringLength(
column[field],
CharsetToEncoding[column.characterSet]
);
});
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(sequenceId, buffer, 0, length);
function writeField(name) {
packet.writeLengthCodedString(
column[name],
CharsetToEncoding[column.characterSet]
);
}
packet.offset = 4;
fields.forEach(writeField);
packet.writeInt8(0x0c);
packet.writeInt16(column.characterSet);
packet.writeInt32(column.columnLength);
packet.writeInt8(column.columnType);
packet.writeInt16(column.flags);
packet.writeInt8(column.decimals);
packet.writeInt16(0); // filler
return packet;
}
// node-mysql compatibility: alias "db" to "schema"
get db() {
return this.schema;
}
}
const addString = function(name) {
Object.defineProperty(ColumnDefinition.prototype, name, {
get: function() {
const start = this[`_${name}Start`];
const end = start + this[`_${name}Length`];
const val = StringParser.decode(
this._buf,
this.encoding === 'binary' ? this._clientEncoding : this.encoding,
start,
end
);
Object.defineProperty(this, name, {
value: val,
writable: false,
configurable: false,
enumerable: false
});
return val;
}
});
};
addString('catalog');
addString('schema');
addString('table');
addString('orgTable');
addString('orgName');
module.exports = ColumnDefinition;

212
node_modules/mysql2/lib/packets/execute.js generated vendored Normal file
View File

@@ -0,0 +1,212 @@
'use strict';
const CursorType = require('../constants/cursor');
const CommandCodes = require('../constants/commands');
const Types = require('../constants/types');
const Packet = require('../packets/packet');
const CharsetToEncoding = require('../constants/charset_encodings.js');
function isJSON(value) {
return (
Array.isArray(value) ||
value.constructor === Object ||
(typeof value.toJSON === 'function' && !Buffer.isBuffer(value))
);
}
/**
* Converts a value to an object describing type, String/Buffer representation and length
* @param {*} value
*/
function toParameter(value, encoding, timezone) {
let type = Types.VAR_STRING;
let length;
let writer = function(value) {
// eslint-disable-next-line no-invalid-this
return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
};
if (value !== null) {
switch (typeof value) {
case 'undefined':
throw new TypeError('Bind parameters must not contain undefined');
case 'number':
type = Types.DOUBLE;
length = 8;
writer = Packet.prototype.writeDouble;
break;
case 'boolean':
value = value | 0;
type = Types.TINY;
length = 1;
writer = Packet.prototype.writeInt8;
break;
case 'object':
if (Object.prototype.toString.call(value) === '[object Date]') {
type = Types.DATETIME;
length = 12;
writer = function(value) {
// eslint-disable-next-line no-invalid-this
return Packet.prototype.writeDate.call(this, value, timezone);
};
} else if (isJSON(value)) {
value = JSON.stringify(value);
type = Types.JSON;
} else if (Buffer.isBuffer(value)) {
length = Packet.lengthCodedNumberLength(value.length) + value.length;
writer = Packet.prototype.writeLengthCodedBuffer;
}
break;
default:
value = value.toString();
}
} else {
value = '';
type = Types.NULL;
}
if (!length) {
length = Packet.lengthCodedStringLength(value, encoding);
}
return { value, type, length, writer };
}
class Execute {
constructor(id, parameters, charsetNumber, timezone) {
this.id = id;
this.parameters = parameters;
this.encoding = CharsetToEncoding[charsetNumber];
this.timezone = timezone;
}
static fromPacket(packet, encoding) {
const stmtId = packet.readInt32();
const flags = packet.readInt8();
const iterationCount = packet.readInt32();
let i = packet.offset;
while (i < packet.end - 1) {
if((packet.buffer[i+1] === Types.VAR_STRING
|| packet.buffer[i+1] === Types.NULL
|| packet.buffer[i+1] === Types.DOUBLE
|| packet.buffer[i+1] === Types.TINY
|| packet.buffer[i+1] === Types.DATETIME
|| packet.buffer[i+1] === Types.JSON) && packet.buffer[i] === 1 && packet.buffer[i+2] === 0) {
break;
}
else {
packet.readInt8()
}
i++;
}
const types = [];
for(let i = packet.offset + 1; i < packet.end - 1; i++) {
if((packet.buffer[i] === Types.VAR_STRING
|| packet.buffer[i] === Types.NULL
|| packet.buffer[i] === Types.DOUBLE
|| packet.buffer[i] === Types.TINY
|| packet.buffer[i] === Types.DATETIME
|| packet.buffer[i] === Types.JSON) && packet.buffer[i + 1] === 0) {
types.push(packet.buffer[i]);
packet.skip(2);
}
}
packet.skip(1);
const values = [];
for(let i = 0; i < types.length; i++) {
if(types[i] === Types.VAR_STRING) {
values.push(packet.readLengthCodedString(encoding))
}
else if(types[i] === Types.DOUBLE) {
values.push(packet.readDouble())
}
else if(types[i] === Types.TINY) {
values.push(packet.readInt8())
}
else if(types[i] === Types.DATETIME) {
values.push(packet.readDateTime())
}
else if(types[i] === Types.JSON) {
values.push(JSON.parse(packet.readLengthCodedString(encoding)))
}
if(types[i] === Types.NULL) {
values.push(null)
}
}
return { stmtId, flags, iterationCount, values };
}
toPacket() {
// TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
// and copy + reallocate if not enough
// 0 + 4 - length, seqId
// 4 + 1 - COM_EXECUTE
// 5 + 4 - stmtId
// 9 + 1 - flags
// 10 + 4 - iteration-count (always 1)
let length = 14;
let parameters;
if (this.parameters && this.parameters.length > 0) {
length += Math.floor((this.parameters.length + 7) / 8);
length += 1; // new-params-bound-flag
length += 2 * this.parameters.length; // type byte for each parameter if new-params-bound-flag is set
parameters = this.parameters.map(value =>
toParameter(value, this.encoding, this.timezone)
);
length += parameters.reduce(
(accumulator, parameter) => accumulator + parameter.length,
0
);
}
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_EXECUTE);
packet.writeInt32(this.id);
packet.writeInt8(CursorType.NO_CURSOR); // flags
packet.writeInt32(1); // iteration-count, always 1
if (parameters) {
let bitmap = 0;
let bitValue = 1;
parameters.forEach(parameter => {
if (parameter.type === Types.NULL) {
bitmap += bitValue;
}
bitValue *= 2;
if (bitValue === 256) {
packet.writeInt8(bitmap);
bitmap = 0;
bitValue = 1;
}
});
if (bitValue !== 1) {
packet.writeInt8(bitmap);
}
// TODO: explain meaning of the flag
// afaik, if set n*2 bytes with type of parameter are sent before parameters
// if not, previous execution types are used (TODO prooflink)
packet.writeInt8(1); // new-params-bound-flag
// Write parameter types
parameters.forEach(parameter => {
packet.writeInt8(parameter.type); // field type
packet.writeInt8(0); // parameter flag
});
// Write parameter values
parameters.forEach(parameter => {
if (parameter.type !== Types.NULL) {
parameter.writer.call(packet, parameter.value);
}
});
}
return packet;
}
}
module.exports = Execute;

112
node_modules/mysql2/lib/packets/handshake.js generated vendored Normal file
View File

@@ -0,0 +1,112 @@
'use strict';
const Packet = require('../packets/packet');
const ClientConstants = require('../constants/client.js');
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
class Handshake {
constructor(args) {
this.protocolVersion = args.protocolVersion;
this.serverVersion = args.serverVersion;
this.capabilityFlags = args.capabilityFlags;
this.connectionId = args.connectionId;
this.authPluginData1 = args.authPluginData1;
this.authPluginData2 = args.authPluginData2;
this.characterSet = args.characterSet;
this.statusFlags = args.statusFlags;
this.autPluginName = args.autPluginName;
}
setScrambleData(cb) {
require('crypto').randomBytes(20, (err, data) => {
if (err) {
cb(err);
return;
}
this.authPluginData1 = data.slice(0, 8);
this.authPluginData2 = data.slice(8, 20);
cb();
});
}
toPacket(sequenceId) {
const length = 68 + Buffer.byteLength(this.serverVersion, 'utf8');
const buffer = Buffer.alloc(length + 4, 0); // zero fill, 10 bytes filler later needs to contain zeros
const packet = new Packet(sequenceId, buffer, 0, length + 4);
packet.offset = 4;
packet.writeInt8(this.protocolVersion);
packet.writeString(this.serverVersion, 'cesu8');
packet.writeInt8(0);
packet.writeInt32(this.connectionId);
packet.writeBuffer(this.authPluginData1);
packet.writeInt8(0);
const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
capabilityFlagsBuffer.writeUInt32LE(this.capabilityFlags, 0);
packet.writeBuffer(capabilityFlagsBuffer.slice(0, 2));
packet.writeInt8(this.characterSet);
packet.writeInt16(this.statusFlags);
packet.writeBuffer(capabilityFlagsBuffer.slice(2, 4));
packet.writeInt8(21); // authPluginDataLength
packet.skip(10);
packet.writeBuffer(this.authPluginData2);
packet.writeInt8(0);
packet.writeString('mysql_native_password', 'latin1');
packet.writeInt8(0);
return packet;
}
static fromPacket(packet) {
const args = {};
args.protocolVersion = packet.readInt8();
args.serverVersion = packet.readNullTerminatedString('cesu8');
args.connectionId = packet.readInt32();
args.authPluginData1 = packet.readBuffer(8);
packet.skip(1);
const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
capabilityFlagsBuffer[0] = packet.readInt8();
capabilityFlagsBuffer[1] = packet.readInt8();
if (packet.haveMoreData()) {
args.characterSet = packet.readInt8();
args.statusFlags = packet.readInt16();
// upper 2 bytes
capabilityFlagsBuffer[2] = packet.readInt8();
capabilityFlagsBuffer[3] = packet.readInt8();
args.capabilityFlags = capabilityFlagsBuffer.readUInt32LE(0);
if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
args.authPluginDataLength = packet.readInt8();
} else {
args.authPluginDataLength = 0;
packet.skip(1);
}
packet.skip(10);
} else {
args.capabilityFlags = capabilityFlagsBuffer.readUInt16LE(0);
}
const isSecureConnection =
args.capabilityFlags & ClientConstants.SECURE_CONNECTION;
if (isSecureConnection) {
const authPluginDataLength = args.authPluginDataLength;
if (authPluginDataLength === 0) {
// for Secure Password Authentication
args.authPluginDataLength = 20;
args.authPluginData2 = packet.readBuffer(12);
packet.skip(1);
} else {
// length > 0
// for Custom Auth Plugin (PLUGIN_AUTH)
const len = Math.max(13, authPluginDataLength - 8);
args.authPluginData2 = packet.readBuffer(len);
}
}
if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
args.autPluginName = packet.readNullTerminatedString('ascii');
}
return new Handshake(args);
}
}
module.exports = Handshake;

145
node_modules/mysql2/lib/packets/handshake_response.js generated vendored Normal file
View File

@@ -0,0 +1,145 @@
'use strict';
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const Packet = require('../packets/packet.js');
const auth41 = require('../auth_41.js');
class HandshakeResponse {
constructor(handshake) {
this.user = handshake.user || '';
this.database = handshake.database || '';
this.password = handshake.password || '';
this.passwordSha1 = handshake.passwordSha1;
this.authPluginData1 = handshake.authPluginData1;
this.authPluginData2 = handshake.authPluginData2;
this.compress = handshake.compress;
this.clientFlags = handshake.flags;
// TODO: pre-4.1 auth support
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
this.authPluginData1,
this.authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
this.authPluginData1,
this.authPluginData2
);
}
this.authToken = authToken;
this.charsetNumber = handshake.charsetNumber;
this.encoding = CharsetToEncoding[handshake.charsetNumber];
this.connectAttributes = handshake.connectAttributes;
}
serializeResponse(buffer) {
const isSet = flag => this.clientFlags & ClientConstants[flag];
const packet = new Packet(0, buffer, 0, buffer.length);
packet.offset = 4;
packet.writeInt32(this.clientFlags);
packet.writeInt32(0); // max packet size. todo: move to config
packet.writeInt8(this.charsetNumber);
packet.skip(23);
const encoding = this.encoding;
packet.writeNullTerminatedString(this.user, encoding);
let k;
if (isSet('PLUGIN_AUTH_LENENC_CLIENT_DATA')) {
packet.writeLengthCodedNumber(this.authToken.length);
packet.writeBuffer(this.authToken);
} else if (isSet('SECURE_CONNECTION')) {
packet.writeInt8(this.authToken.length);
packet.writeBuffer(this.authToken);
} else {
packet.writeBuffer(this.authToken);
packet.writeInt8(0);
}
if (isSet('CONNECT_WITH_DB')) {
packet.writeNullTerminatedString(this.database, encoding);
}
if (isSet('PLUGIN_AUTH')) {
// TODO: pass from config
packet.writeNullTerminatedString('mysql_native_password', 'latin1');
}
if (isSet('CONNECT_ATTRS')) {
const connectAttributes = this.connectAttributes || {};
const attrNames = Object.keys(connectAttributes);
let keysLength = 0;
for (k = 0; k < attrNames.length; ++k) {
keysLength += Packet.lengthCodedStringLength(attrNames[k], encoding);
keysLength += Packet.lengthCodedStringLength(
connectAttributes[attrNames[k]],
encoding
);
}
packet.writeLengthCodedNumber(keysLength);
for (k = 0; k < attrNames.length; ++k) {
packet.writeLengthCodedString(attrNames[k], encoding);
packet.writeLengthCodedString(
connectAttributes[attrNames[k]],
encoding
);
}
}
return packet;
}
toPacket() {
if (typeof this.user !== 'string') {
throw new Error('"user" connection config property must be a string');
}
if (typeof this.database !== 'string') {
throw new Error('"database" connection config property must be a string');
}
// dry run: calculate resulting packet length
const p = this.serializeResponse(Packet.MockBuffer());
return this.serializeResponse(Buffer.alloc(p.offset));
}
static fromPacket(packet) {
const args = {};
args.clientFlags = packet.readInt32();
function isSet(flag) {
return args.clientFlags & ClientConstants[flag];
}
args.maxPacketSize = packet.readInt32();
args.charsetNumber = packet.readInt8();
const encoding = CharsetToEncoding[args.charsetNumber];
args.encoding = encoding;
packet.skip(23);
args.user = packet.readNullTerminatedString(encoding);
let authTokenLength;
if (isSet('PLUGIN_AUTH_LENENC_CLIENT_DATA')) {
authTokenLength = packet.readLengthCodedNumber(encoding);
args.authToken = packet.readBuffer(authTokenLength);
} else if (isSet('SECURE_CONNECTION')) {
authTokenLength = packet.readInt8();
args.authToken = packet.readBuffer(authTokenLength);
} else {
args.authToken = packet.readNullTerminatedString(encoding);
}
if (isSet('CONNECT_WITH_DB')) {
args.database = packet.readNullTerminatedString(encoding);
}
if (isSet('PLUGIN_AUTH')) {
args.authPluginName = packet.readNullTerminatedString(encoding);
}
if (isSet('CONNECT_ATTRS')) {
const keysLength = packet.readLengthCodedNumber(encoding);
const keysEnd = packet.offset + keysLength;
const attrs = {};
while (packet.offset < keysEnd) {
attrs[
packet.readLengthCodedString(encoding)
] = packet.readLengthCodedString(encoding);
}
args.connectAttributes = attrs;
}
return args;
}
}
module.exports = HandshakeResponse;

152
node_modules/mysql2/lib/packets/index.js generated vendored Normal file
View File

@@ -0,0 +1,152 @@
// This file was modified by Oracle on June 1, 2021.
// A utility method was introduced to generate an Error instance from a
// binary server packet.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// This file was modified by Oracle on September 21, 2021.
// The new AuthNextFactor packet is now available.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const process = require('process');
const AuthNextFactor = require('./auth_next_factor');
const AuthSwitchRequest = require('./auth_switch_request');
const AuthSwitchRequestMoreData = require('./auth_switch_request_more_data');
const AuthSwitchResponse = require('./auth_switch_response');
const BinaryRow = require('./binary_row');
const BinlogDump = require('./binlog_dump');
const ChangeUser = require('./change_user');
const CloseStatement = require('./close_statement');
const ColumnDefinition = require('./column_definition');
const Execute = require('./execute');
const Handshake = require('./handshake');
const HandshakeResponse = require('./handshake_response');
const PrepareStatement = require('./prepare_statement');
const PreparedStatementHeader = require('./prepared_statement_header');
const Query = require('./query');
const RegisterSlave = require('./register_slave');
const ResultSetHeader = require('./resultset_header');
const SSLRequest = require('./ssl_request');
const TextRow = require('./text_row');
const ctorMap = {
AuthNextFactor,
AuthSwitchRequest,
AuthSwitchRequestMoreData,
AuthSwitchResponse,
BinaryRow,
BinlogDump,
ChangeUser,
CloseStatement,
ColumnDefinition,
Execute,
Handshake,
HandshakeResponse,
PrepareStatement,
PreparedStatementHeader,
Query,
RegisterSlave,
ResultSetHeader,
SSLRequest,
TextRow
};
Object.entries(ctorMap).forEach(([name, ctor]) => {
module.exports[name] = ctor;
// monkey-patch it to include name if debug is on
if (process.env.NODE_DEBUG) {
if (ctor.prototype.toPacket) {
const old = ctor.prototype.toPacket;
ctor.prototype.toPacket = function() {
const p = old.call(this);
p._name = name;
return p;
};
}
}
});
// simple packets:
const Packet = require('./packet');
exports.Packet = Packet;
class OK {
static toPacket(args, encoding) {
args = args || {};
const affectedRows = args.affectedRows || 0;
const insertId = args.insertId || 0;
const serverStatus = args.serverStatus || 0;
const warningCount = args.warningCount || 0;
const message = args.message || '';
let length = 9 + Packet.lengthCodedNumberLength(affectedRows);
length += Packet.lengthCodedNumberLength(insertId);
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0);
packet.writeLengthCodedNumber(affectedRows);
packet.writeLengthCodedNumber(insertId);
packet.writeInt16(serverStatus);
packet.writeInt16(warningCount);
packet.writeString(message, encoding);
packet._name = 'OK';
return packet;
}
}
exports.OK = OK;
// warnings, statusFlags
class EOF {
static toPacket(warnings, statusFlags) {
if (typeof warnings === 'undefined') {
warnings = 0;
}
if (typeof statusFlags === 'undefined') {
statusFlags = 0;
}
const packet = new Packet(0, Buffer.allocUnsafe(9), 0, 9);
packet.offset = 4;
packet.writeInt8(0xfe);
packet.writeInt16(warnings);
packet.writeInt16(statusFlags);
packet._name = 'EOF';
return packet;
}
}
exports.EOF = EOF;
class Error {
static toPacket(args, encoding) {
const length = 13 + Buffer.byteLength(args.message, 'utf8');
const packet = new Packet(0, Buffer.allocUnsafe(length), 0, length);
packet.offset = 4;
packet.writeInt8(0xff);
packet.writeInt16(args.code);
// TODO: sql state parameter
packet.writeString('#_____', encoding);
packet.writeString(args.message, encoding);
packet._name = 'Error';
return packet;
}
static fromPacket(packet) {
packet.readInt8(); // marker
const code = packet.readInt16();
packet.readString(1, 'ascii'); // sql state marker
// The SQL state of the ERR_Packet which is always 5 bytes long.
// https://dev.mysql.com/doc/dev/mysql-server/8.0.11/page_protocol_basic_dt_strings.html#sect_protocol_basic_dt_string_fix
packet.readString(5, 'ascii'); // sql state (ignore for now)
const message = packet.readNullTerminatedString('utf8');
const error = new Error();
error.message = message;
error.code = code;
return error;
}
}
exports.Error = Error;

929
node_modules/mysql2/lib/packets/packet.js generated vendored Normal file
View File

@@ -0,0 +1,929 @@
// This file was modified by Oracle on June 1, 2021.
// A comment describing some changes in the strict default SQL mode regarding
// non-standard dates was introduced.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
'use strict';
const ErrorCodeToName = require('../constants/errors.js');
const NativeBuffer = require('buffer').Buffer;
const Long = require('long');
const StringParser = require('../parsers/string.js');
const INVALID_DATE = new Date(NaN);
// this is nearly duplicate of previous function so generated code is not slower
// due to "if (dateStrings)" branching
const pad = '000000000000';
function leftPad(num, value) {
const s = value.toString();
// if we don't need to pad
if (s.length >= num) {
return s;
}
return (pad + s).slice(-num);
}
// The whole reason parse* function below exist
// is because String creation is relatively expensive (at least with V8), and if we have
// a buffer with "12345" content ideally we would like to bypass intermediate
// "12345" string creation and directly build 12345 number out of
// <Buffer 31 32 33 34 35> data.
// In my benchmarks the difference is ~25M 8-digit numbers per second vs
// 4.5 M using Number(packet.readLengthCodedString())
// not used when size is close to max precision as series of *10 accumulate error
// and approximate result mihgt be diffreent from (approximate as well) Number(bigNumStringValue))
// In the futire node version if speed difference is smaller parse* functions might be removed
// don't consider them as Packet public API
const minus = '-'.charCodeAt(0);
const plus = '+'.charCodeAt(0);
// TODO: handle E notation
const dot = '.'.charCodeAt(0);
const exponent = 'e'.charCodeAt(0);
const exponentCapital = 'E'.charCodeAt(0);
class Packet {
constructor(id, buffer, start, end) {
// hot path, enable checks when testing only
// if (!Buffer.isBuffer(buffer) || typeof start == 'undefined' || typeof end == 'undefined')
// throw new Error('invalid packet');
this.sequenceId = id;
this.numPackets = 1;
this.buffer = buffer;
this.start = start;
this.offset = start + 4;
this.end = end;
}
// ==============================
// readers
// ==============================
reset() {
this.offset = this.start + 4;
}
length() {
return this.end - this.start;
}
slice() {
return this.buffer.slice(this.start, this.end);
}
dump() {
// eslint-disable-next-line no-console
console.log(
[this.buffer.asciiSlice(this.start, this.end)],
this.buffer.slice(this.start, this.end),
this.length(),
this.sequenceId
);
}
haveMoreData() {
return this.end > this.offset;
}
skip(num) {
this.offset += num;
}
readInt8() {
return this.buffer[this.offset++];
}
readInt16() {
this.offset += 2;
return this.buffer.readUInt16LE(this.offset - 2);
}
readInt24() {
return this.readInt16() + (this.readInt8() << 16);
}
readInt32() {
this.offset += 4;
return this.buffer.readUInt32LE(this.offset - 4);
}
readSInt8() {
return this.buffer.readInt8(this.offset++);
}
readSInt16() {
this.offset += 2;
return this.buffer.readInt16LE(this.offset - 2);
}
readSInt32() {
this.offset += 4;
return this.buffer.readInt32LE(this.offset - 4);
}
readInt64JSNumber() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const l = new Long(word0, word1, true);
return l.toNumber();
}
readSInt64JSNumber() {
const word0 = this.readInt32();
const word1 = this.readInt32();
if (!(word1 & 0x80000000)) {
return word0 + 0x100000000 * word1;
}
const l = new Long(word0, word1, false);
return l.toNumber();
}
readInt64String() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const res = new Long(word0, word1, true);
return res.toString();
}
readSInt64String() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const res = new Long(word0, word1, false);
return res.toString();
}
readInt64() {
const word0 = this.readInt32();
const word1 = this.readInt32();
let res = new Long(word0, word1, true);
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return res;
}
readSInt64() {
const word0 = this.readInt32();
const word1 = this.readInt32();
let res = new Long(word0, word1, false);
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return res;
}
isEOF() {
return this.buffer[this.offset] === 0xfe && this.length() < 13;
}
eofStatusFlags() {
return this.buffer.readInt16LE(this.offset + 3);
}
eofWarningCount() {
return this.buffer.readInt16LE(this.offset + 1);
}
readLengthCodedNumber(bigNumberStrings, signed) {
const byte1 = this.buffer[this.offset++];
if (byte1 < 251) {
return byte1;
}
return this.readLengthCodedNumberExt(byte1, bigNumberStrings, signed);
}
readLengthCodedNumberSigned(bigNumberStrings) {
return this.readLengthCodedNumber(bigNumberStrings, true);
}
readLengthCodedNumberExt(tag, bigNumberStrings, signed) {
let word0, word1;
let res;
if (tag === 0xfb) {
return null;
}
if (tag === 0xfc) {
return this.readInt8() + (this.readInt8() << 8);
}
if (tag === 0xfd) {
return this.readInt8() + (this.readInt8() << 8) + (this.readInt8() << 16);
}
if (tag === 0xfe) {
// TODO: check version
// Up to MySQL 3.22, 0xfe was followed by a 4-byte integer.
word0 = this.readInt32();
word1 = this.readInt32();
if (word1 === 0) {
return word0; // don't convert to float if possible
}
if (word1 < 2097152) {
// max exact float point int, 2^52 / 2^32
return word1 * 0x100000000 + word0;
}
res = new Long(word0, word1, !signed); // Long need unsigned
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return bigNumberStrings ? resString : res;
}
// eslint-disable-next-line no-console
console.trace();
throw new Error(`Should not reach here: ${tag}`);
}
readFloat() {
const res = this.buffer.readFloatLE(this.offset);
this.offset += 4;
return res;
}
readDouble() {
const res = this.buffer.readDoubleLE(this.offset);
this.offset += 8;
return res;
}
readBuffer(len) {
if (typeof len === 'undefined') {
len = this.end - this.offset;
}
this.offset += len;
return this.buffer.slice(this.offset - len, this.offset);
}
// DATE, DATETIME and TIMESTAMP
readDateTime(timezone) {
if (!timezone || timezone === 'Z' || timezone === 'local') {
const length = this.readInt8();
if (length === 0xfb) {
return null;
}
let y = 0;
let m = 0;
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
if (length > 3) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();
}
if (length > 6) {
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
}
if (length > 10) {
ms = this.readInt32() / 1000;
}
// NO_ZERO_DATE mode and NO_ZERO_IN_DATE mode are part of the strict
// default SQL mode used by MySQL 8.0. This means that non-standard
// dates like '0000-00-00' become NULL. For older versions and other
// possible MySQL flavours we still need to account for the
// non-standard behaviour.
if (y + m + d + H + M + S + ms === 0) {
return INVALID_DATE;
}
if (timezone === 'Z') {
return new Date(Date.UTC(y, m - 1, d, H, M, S, ms));
}
return new Date(y, m - 1, d, H, M, S, ms);
}
let str = this.readDateTimeString(6, 'T');
if (str.length === 10) {
str += 'T00:00:00';
}
return new Date(str + timezone);
}
readDateTimeString(decimals, timeSep) {
const length = this.readInt8();
let y = 0;
let m = 0;
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
let str;
if (length > 3) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();
str = [leftPad(4, y), leftPad(2, m), leftPad(2, d)].join('-');
}
if (length > 6) {
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
str += `${timeSep || ' '}${[
leftPad(2, H),
leftPad(2, M),
leftPad(2, S)
].join(':')}`;
}
if (length > 10) {
ms = this.readInt32();
str += '.';
if (decimals) {
ms = leftPad(6, ms);
if (ms.length > decimals) {
ms = ms.substring(0, decimals); // rounding is done at the MySQL side, only 0 are here
}
}
str += ms;
}
return str;
}
// TIME - value as a string, Can be negative
readTimeString(convertTtoMs) {
const length = this.readInt8();
if (length === 0) {
return '00:00:00';
}
const sign = this.readInt8() ? -1 : 1; // 'isNegative' flag byte
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
if (length > 6) {
d = this.readInt32();
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
}
if (length > 10) {
ms = this.readInt32();
}
if (convertTtoMs) {
H += d * 24;
M += H * 60;
S += M * 60;
ms += S * 1000;
ms *= sign;
return ms;
}
// Format follows mySQL TIME format ([-][h]hh:mm:ss[.u[u[u[u[u[u]]]]]])
// For positive times below 24 hours, this makes it equal to ISO 8601 times
return (
(sign === -1 ? '-' : '') +
[leftPad(2, d * 24 + H), leftPad(2, M), leftPad(2, S)].join(':') +
(ms ? `.${ms}`.replace(/0+$/, '') : '')
);
}
readLengthCodedString(encoding) {
const len = this.readLengthCodedNumber();
// TODO: check manually first byte here to avoid polymorphic return type?
if (len === null) {
return null;
}
this.offset += len;
// TODO: Use characterSetCode to get proper encoding
// https://github.com/sidorares/node-mysql2/pull/374
return StringParser.decode(
this.buffer,
encoding,
this.offset - len,
this.offset
);
}
readLengthCodedBuffer() {
const len = this.readLengthCodedNumber();
if (len === null) {
return null;
}
return this.readBuffer(len);
}
readNullTerminatedString(encoding) {
const start = this.offset;
let end = this.offset;
while (this.buffer[end]) {
end = end + 1; // TODO: handle OOB check
}
this.offset = end + 1;
return StringParser.decode(this.buffer, encoding, start, end);
}
// TODO reuse?
readString(len, encoding) {
if (typeof len === 'string' && typeof encoding === 'undefined') {
encoding = len;
len = undefined;
}
if (typeof len === 'undefined') {
len = this.end - this.offset;
}
this.offset += len;
return StringParser.decode(
this.buffer,
encoding,
this.offset - len,
this.offset
);
}
parseInt(len, supportBigNumbers) {
if (len === null) {
return null;
}
if (len >= 14 && !supportBigNumbers) {
const s = this.buffer.toString('ascii', this.offset, this.offset + len);
this.offset += len;
return Number(s);
}
let result = 0;
const start = this.offset;
const end = this.offset + len;
let sign = 1;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
sign = -1;
}
// max precise int is 9007199254740992
let str;
const numDigits = end - this.offset;
if (supportBigNumbers) {
if (numDigits >= 15) {
str = this.readString(end - this.offset, 'binary');
result = parseInt(str, 10);
if (result.toString() === str) {
return sign * result;
}
return sign === -1 ? `-${str}` : str;
}
if (numDigits > 16) {
str = this.readString(end - this.offset);
return sign === -1 ? `-${str}` : str;
}
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
}
const num = result * sign;
if (!supportBigNumbers) {
return num;
}
str = this.buffer.toString('ascii', start, end);
if (num.toString() === str) {
return num;
}
return str;
}
// note that if value of inputNumberAsString is bigger than MAX_SAFE_INTEGER
// ( or smaller than MIN_SAFE_INTEGER ) the parseIntNoBigCheck result might be
// different from what you would get from Number(inputNumberAsString)
// String(parseIntNoBigCheck) <> String(Number(inputNumberAsString)) <> inputNumberAsString
parseIntNoBigCheck(len) {
if (len === null) {
return null;
}
let result = 0;
const end = this.offset + len;
let sign = 1;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
sign = -1;
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
}
return result * sign;
}
// copy-paste from https://github.com/mysqljs/mysql/blob/master/lib/protocol/Parser.js
parseGeometryValue() {
const buffer = this.readLengthCodedBuffer();
let offset = 4;
if (buffer === null || !buffer.length) {
return null;
}
function parseGeometry() {
let x, y, i, j, numPoints, line;
let result = null;
const byteOrder = buffer.readUInt8(offset);
offset += 1;
const wkbType = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
switch (wkbType) {
case 1: // WKBPoint
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
y = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
result = { x: x, y: y };
break;
case 2: // WKBLineString
numPoints = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = numPoints; i > 0; i--) {
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
y = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
result.push({ x: x, y: y });
}
break;
case 3: // WKBPolygon
// eslint-disable-next-line no-case-declarations
const numRings = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = numRings; i > 0; i--) {
numPoints = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
line = [];
for (j = numPoints; j > 0; j--) {
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
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
// eslint-disable-next-line no-case-declarations
const num = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = num; i > 0; i--) {
result.push(parseGeometry());
}
break;
}
return result;
}
return parseGeometry();
}
parseVector() {
const bufLen = this.readLengthCodedNumber();
const vectorEnd = this.offset + bufLen;
const result = [];
while (this.offset < vectorEnd && this.offset < this.end) {
result.push(this.readFloat());
}
return result;
}
parseDate(timezone) {
const strLen = this.readLengthCodedNumber();
if (strLen === null) {
return null;
}
if (strLen !== 10) {
// we expect only YYYY-MM-DD here.
// if for some reason it's not the case return invalid date
return new Date(NaN);
}
const y = this.parseInt(4);
this.offset++; // -
const m = this.parseInt(2);
this.offset++; // -
const d = this.parseInt(2);
if (!timezone || timezone === 'local') {
return new Date(y, m - 1, d);
}
if (timezone === 'Z') {
return new Date(Date.UTC(y, m - 1, d));
}
return new Date(
`${leftPad(4, y)}-${leftPad(2, m)}-${leftPad(2, d)}T00:00:00${timezone}`
);
}
parseDateTime(timezone) {
const str = this.readLengthCodedString('binary');
if (str === null) {
return null;
}
if (!timezone || timezone === 'local') {
return new Date(str);
}
return new Date(`${str}${timezone}`);
}
parseFloat(len) {
if (len === null) {
return null;
}
let result = 0;
const end = this.offset + len;
let factor = 1;
let pastDot = false;
let charCode = 0;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
factor = -1;
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
charCode = this.buffer[this.offset];
if (charCode === dot) {
pastDot = true;
this.offset++;
} else if (charCode === exponent || charCode === exponentCapital) {
this.offset++;
const exponentValue = this.parseInt(end - this.offset);
return (result / factor) * Math.pow(10, exponentValue);
} else {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
if (pastDot) {
factor = factor * 10;
}
}
}
return result / factor;
}
parseLengthCodedIntNoBigCheck() {
return this.parseIntNoBigCheck(this.readLengthCodedNumber());
}
parseLengthCodedInt(supportBigNumbers) {
return this.parseInt(this.readLengthCodedNumber(), supportBigNumbers);
}
parseLengthCodedIntString() {
return this.readLengthCodedString('binary');
}
parseLengthCodedFloat() {
return this.parseFloat(this.readLengthCodedNumber());
}
peekByte() {
return this.buffer[this.offset];
}
// OxFE is often used as "Alt" flag - not ok, not error.
// For example, it's first byte of AuthSwitchRequest
isAlt() {
return this.peekByte() === 0xfe;
}
isError() {
return this.peekByte() === 0xff;
}
asError(encoding) {
this.reset();
this.readInt8(); // fieldCount
const errorCode = this.readInt16();
let sqlState = '';
if (this.buffer[this.offset] === 0x23) {
this.skip(1);
sqlState = this.readBuffer(5).toString();
}
const message = this.readString(undefined, encoding);
const err = new Error(message);
err.code = ErrorCodeToName[errorCode];
err.errno = errorCode;
err.sqlState = sqlState;
err.sqlMessage = message;
return err;
}
writeInt32(n) {
this.buffer.writeUInt32LE(n, this.offset);
this.offset += 4;
}
writeInt24(n) {
this.writeInt8(n & 0xff);
this.writeInt16(n >> 8);
}
writeInt16(n) {
this.buffer.writeUInt16LE(n, this.offset);
this.offset += 2;
}
writeInt8(n) {
this.buffer.writeUInt8(n, this.offset);
this.offset++;
}
writeDouble(n) {
this.buffer.writeDoubleLE(n, this.offset);
this.offset += 8;
}
writeBuffer(b) {
b.copy(this.buffer, this.offset);
this.offset += b.length;
}
writeNull() {
this.buffer[this.offset] = 0xfb;
this.offset++;
}
// TODO: refactor following three?
writeNullTerminatedString(s, encoding) {
const buf = StringParser.encode(s, encoding);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
this.writeInt8(0);
}
writeString(s, encoding) {
if (s === null) {
this.writeInt8(0xfb);
return;
}
if (s.length === 0) {
return;
}
// const bytes = Buffer.byteLength(s, 'utf8');
// this.buffer.write(s, this.offset, bytes, 'utf8');
// this.offset += bytes;
const buf = StringParser.encode(s, encoding);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
}
writeLengthCodedString(s, encoding) {
const buf = StringParser.encode(s, encoding);
this.writeLengthCodedNumber(buf.length);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
}
writeLengthCodedBuffer(b) {
this.writeLengthCodedNumber(b.length);
b.copy(this.buffer, this.offset);
this.offset += b.length;
}
writeLengthCodedNumber(n) {
if (n < 0xfb) {
return this.writeInt8(n);
}
if (n < 0xffff) {
this.writeInt8(0xfc);
return this.writeInt16(n);
}
if (n < 0xffffff) {
this.writeInt8(0xfd);
return this.writeInt24(n);
}
if (n === null) {
return this.writeInt8(0xfb);
}
// TODO: check that n is out of int precision
this.writeInt8(0xfe);
this.buffer.writeUInt32LE(n, this.offset);
this.offset += 4;
this.buffer.writeUInt32LE(n >> 32, this.offset);
this.offset += 4;
return this.offset;
}
writeDate(d, timezone) {
this.buffer.writeUInt8(11, this.offset);
if (!timezone || timezone === 'local') {
this.buffer.writeUInt16LE(d.getFullYear(), this.offset + 1);
this.buffer.writeUInt8(d.getMonth() + 1, this.offset + 3);
this.buffer.writeUInt8(d.getDate(), this.offset + 4);
this.buffer.writeUInt8(d.getHours(), this.offset + 5);
this.buffer.writeUInt8(d.getMinutes(), this.offset + 6);
this.buffer.writeUInt8(d.getSeconds(), this.offset + 7);
this.buffer.writeUInt32LE(d.getMilliseconds() * 1000, this.offset + 8);
} else {
if (timezone !== 'Z') {
const offset =
(timezone[0] === '-' ? -1 : 1) *
(parseInt(timezone.substring(1, 3), 10) * 60 +
parseInt(timezone.substring(4), 10));
if (offset !== 0) {
d = new Date(d.getTime() + 60000 * offset);
}
}
this.buffer.writeUInt16LE(d.getUTCFullYear(), this.offset + 1);
this.buffer.writeUInt8(d.getUTCMonth() + 1, this.offset + 3);
this.buffer.writeUInt8(d.getUTCDate(), this.offset + 4);
this.buffer.writeUInt8(d.getUTCHours(), this.offset + 5);
this.buffer.writeUInt8(d.getUTCMinutes(), this.offset + 6);
this.buffer.writeUInt8(d.getUTCSeconds(), this.offset + 7);
this.buffer.writeUInt32LE(d.getUTCMilliseconds() * 1000, this.offset + 8);
}
this.offset += 12;
}
writeHeader(sequenceId) {
const offset = this.offset;
this.offset = 0;
this.writeInt24(this.buffer.length - 4);
this.writeInt8(sequenceId);
this.offset = offset;
}
clone() {
return new Packet(this.sequenceId, this.buffer, this.start, this.end);
}
type() {
if (this.isEOF()) {
return 'EOF';
}
if (this.isError()) {
return 'Error';
}
if (this.buffer[this.offset] === 0) {
return 'maybeOK'; // could be other packet types as well
}
return '';
}
static lengthCodedNumberLength(n) {
if (n < 0xfb) {
return 1;
}
if (n < 0xffff) {
return 3;
}
if (n < 0xffffff) {
return 5;
}
return 9;
}
static lengthCodedStringLength(str, encoding) {
const buf = StringParser.encode(str, encoding);
const slen = buf.length;
return Packet.lengthCodedNumberLength(slen) + slen;
}
static MockBuffer() {
const noop = function () {};
const res = Buffer.alloc(0);
for (const op in NativeBuffer.prototype) {
if (typeof res[op] === 'function') {
res[op] = noop;
}
}
return res;
}
}
module.exports = Packet;

27
node_modules/mysql2/lib/packets/prepare_statement.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
const StringParser = require('../parsers/string.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class PrepareStatement {
constructor(sql, charsetNumber) {
this.query = sql;
this.charsetNumber = charsetNumber;
this.encoding = CharsetToEncoding[charsetNumber];
}
toPacket() {
const buf = StringParser.encode(this.query, this.encoding);
const length = 5 + buf.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_PREPARE);
packet.writeBuffer(buf);
return packet;
}
}
module.exports = PrepareStatement;

View File

@@ -0,0 +1,16 @@
'use strict';
class PreparedStatementHeader {
constructor(packet) {
packet.skip(1); // should be 0
this.id = packet.readInt32();
this.fieldCount = packet.readInt16();
this.parameterCount = packet.readInt16();
packet.skip(1); // should be 0
this.warningCount = packet.readInt16();
}
}
// TODO: toPacket
module.exports = PreparedStatementHeader;

27
node_modules/mysql2/lib/packets/query.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
const Packet = require('../packets/packet.js');
const CommandCode = require('../constants/commands.js');
const StringParser = require('../parsers/string.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class Query {
constructor(sql, charsetNumber) {
this.query = sql;
this.charsetNumber = charsetNumber;
this.encoding = CharsetToEncoding[charsetNumber];
}
toPacket() {
const buf = StringParser.encode(this.query, this.encoding);
const length = 5 + buf.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCode.QUERY);
packet.writeBuffer(buf);
return packet;
}
}
module.exports = Query;

46
node_modules/mysql2/lib/packets/register_slave.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/com-register-slave.html
// note that documentation is incorrect, for example command code is actually 0x15 but documented as 0x14
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
class RegisterSlave {
constructor(opts) {
this.serverId = opts.serverId || 0;
this.slaveHostname = opts.slaveHostname || '';
this.slaveUser = opts.slaveUser || '';
this.slavePassword = opts.slavePassword || '';
this.slavePort = opts.slavePort || 0;
this.replicationRank = opts.replicationRank || 0;
this.masterId = opts.masterId || 0;
}
toPacket() {
const length =
15 + // TODO: should be ascii?
Buffer.byteLength(this.slaveHostname, 'utf8') +
Buffer.byteLength(this.slaveUser, 'utf8') +
Buffer.byteLength(this.slavePassword, 'utf8') +
3 +
4;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.REGISTER_SLAVE);
packet.writeInt32(this.serverId);
packet.writeInt8(Buffer.byteLength(this.slaveHostname, 'utf8'));
packet.writeString(this.slaveHostname);
packet.writeInt8(Buffer.byteLength(this.slaveUser, 'utf8'));
packet.writeString(this.slaveUser);
packet.writeInt8(Buffer.byteLength(this.slavePassword, 'utf8'));
packet.writeString(this.slavePassword);
packet.writeInt16(this.slavePort);
packet.writeInt32(this.replicationRank);
packet.writeInt32(this.masterId);
return packet;
}
}
module.exports = RegisterSlave;

119
node_modules/mysql2/lib/packets/resultset_header.js generated vendored Normal file
View File

@@ -0,0 +1,119 @@
'use strict';
// TODO: rename to OK packet
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
const Packet = require('./packet.js');
const ClientConstants = require('../constants/client.js');
const ServerSatusFlags = require('../constants/server_status.js');
const EncodingToCharset = require('../constants/encoding_charset.js');
const sessionInfoTypes = require('../constants/session_track.js');
class ResultSetHeader {
constructor(packet, connection) {
const bigNumberStrings = connection.config.bigNumberStrings;
const encoding = connection.serverEncoding;
const flags = connection._handshakePacket.capabilityFlags;
const isSet = function(flag) {
return flags & ClientConstants[flag];
};
if (packet.buffer[packet.offset] !== 0) {
this.fieldCount = packet.readLengthCodedNumber();
if (this.fieldCount === null) {
this.infileName = packet.readString(undefined, encoding);
}
return;
}
this.fieldCount = packet.readInt8(); // skip OK byte
this.affectedRows = packet.readLengthCodedNumber(bigNumberStrings);
this.insertId = packet.readLengthCodedNumberSigned(bigNumberStrings);
this.info = '';
if (isSet('PROTOCOL_41')) {
this.serverStatus = packet.readInt16();
this.warningStatus = packet.readInt16();
} else if (isSet('TRANSACTIONS')) {
this.serverStatus = packet.readInt16();
}
let stateChanges = null;
if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
this.info = packet.readLengthCodedString(encoding);
if (this.serverStatus && ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
// session change info record - see
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
let len =
packet.offset < packet.end ? packet.readLengthCodedNumber() : 0;
const end = packet.offset + len;
let type, key, stateEnd;
if (len > 0) {
stateChanges = {
systemVariables: {},
schema: null,
gtids: [],
trackStateChange: null
};
}
while (packet.offset < end) {
type = packet.readInt8();
len = packet.readLengthCodedNumber();
stateEnd = packet.offset + len;
if (type === sessionInfoTypes.SYSTEM_VARIABLES) {
key = packet.readLengthCodedString(encoding);
const val = packet.readLengthCodedString(encoding);
stateChanges.systemVariables[key] = val;
if (key === 'character_set_client') {
const charsetNumber = EncodingToCharset[val];
connection.config.charsetNumber = charsetNumber;
}
} else if (type === sessionInfoTypes.SCHEMA) {
key = packet.readLengthCodedString(encoding);
stateChanges.schema = key;
} else if (type === sessionInfoTypes.STATE_CHANGE) {
stateChanges.trackStateChange = packet.readLengthCodedString(
encoding
);
} else if (type === sessionInfoTypes.STATE_GTIDS) {
// TODO: find if the first length coded string means anything. Usually comes as empty
// eslint-disable-next-line no-unused-vars
const _unknownString = packet.readLengthCodedString(encoding);
const gtid = packet.readLengthCodedString(encoding);
stateChanges.gtids = gtid.split(',');
} else {
// unsupported session track type. For now just ignore
}
packet.offset = stateEnd;
}
}
} else {
this.info = packet.readString(undefined, encoding);
}
if (stateChanges) {
this.stateChanges = stateChanges;
}
const m = this.info.match(/\schanged:\s*(\d+)/i);
if (m !== null) {
this.changedRows = parseInt(m[1], 10);
} else {
this.changedRows = 0;
}
}
// TODO: should be consistent instance member, but it's just easier here to have just function
static toPacket(fieldCount, insertId) {
let length = 4 + Packet.lengthCodedNumberLength(fieldCount);
if (typeof insertId !== 'undefined') {
length += Packet.lengthCodedNumberLength(insertId);
}
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeLengthCodedNumber(fieldCount);
if (typeof insertId !== 'undefined') {
packet.writeLengthCodedNumber(insertId);
}
return packet;
}
}
module.exports = ResultSetHeader;

25
node_modules/mysql2/lib/packets/ssl_request.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
'use strict';
const ClientConstants = require('../constants/client');
const Packet = require('../packets/packet');
class SSLRequest {
constructor(flags, charset) {
this.clientFlags = flags | ClientConstants.SSL;
this.charset = charset;
}
toPacket() {
const length = 36;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
buffer.fill(0);
packet.offset = 4;
packet.writeInt32(this.clientFlags);
packet.writeInt32(0); // max packet size. todo: move to config
packet.writeInt8(this.charset);
return packet;
}
}
module.exports = SSLRequest;

47
node_modules/mysql2/lib/packets/text_row.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
'use strict';
const Packet = require('../packets/packet');
class TextRow {
constructor(columns) {
this.columns = columns || [];
}
static fromPacket(packet) {
// packet.reset(); // set offset to starting point?
const columns = [];
while (packet.haveMoreData()) {
columns.push(packet.readLengthCodedString());
}
return new TextRow(columns);
}
static toPacket(columns, encoding) {
const sequenceId = 0; // TODO remove, this is calculated now in connecton
let length = 0;
columns.forEach(val => {
if (val === null || typeof val === 'undefined') {
++length;
return;
}
length += Packet.lengthCodedStringLength(val.toString(10), encoding);
});
const buffer = Buffer.allocUnsafe(length + 4);
const packet = new Packet(sequenceId, buffer, 0, length + 4);
packet.offset = 4;
columns.forEach(val => {
if (val === null) {
packet.writeNull();
return;
}
if (typeof val === 'undefined') {
packet.writeInt8(0);
return;
}
packet.writeLengthCodedString(val.toString(10), encoding);
});
return packet;
}
}
module.exports = TextRow;

229
node_modules/mysql2/lib/parsers/binary_parser.js generated vendored Normal file
View File

@@ -0,0 +1,229 @@
'use strict';
const FieldFlags = require('../constants/field_flags.js');
const Charsets = require('../constants/charsets.js');
const Types = require('../constants/types.js');
const helpers = require('../helpers');
const genFunc = require('generate-function');
const parserCache = require('./parser_cache.js');
const typeNames = [];
for (const t in Types) {
typeNames[Types[t]] = t;
}
function readCodeFor(field, config, options, fieldNum) {
const supportBigNumbers = Boolean(
options.supportBigNumbers || config.supportBigNumbers,
);
const bigNumberStrings = Boolean(
options.bigNumberStrings || config.bigNumberStrings,
);
const timezone = options.timezone || config.timezone;
const dateStrings = options.dateStrings || config.dateStrings;
const unsigned = field.flags & FieldFlags.UNSIGNED;
switch (field.columnType) {
case Types.TINY:
return unsigned ? 'packet.readInt8();' : 'packet.readSInt8();';
case Types.SHORT:
return unsigned ? 'packet.readInt16();' : 'packet.readSInt16();';
case Types.LONG:
case Types.INT24: // in binary protocol int24 is encoded in 4 bytes int32
return unsigned ? 'packet.readInt32();' : 'packet.readSInt32();';
case Types.YEAR:
return 'packet.readInt16()';
case Types.FLOAT:
return 'packet.readFloat();';
case Types.DOUBLE:
return 'packet.readDouble();';
case Types.NULL:
return 'null;';
case Types.DATE:
case Types.DATETIME:
case Types.TIMESTAMP:
case Types.NEWDATE:
if (helpers.typeMatch(field.columnType, dateStrings, Types)) {
return `packet.readDateTimeString(${parseInt(field.decimals, 10)});`;
}
return `packet.readDateTime(${helpers.srcEscape(timezone)});`;
case Types.TIME:
return 'packet.readTimeString()';
case Types.DECIMAL:
case Types.NEWDECIMAL:
if (config.decimalNumbers) {
return 'packet.parseLengthCodedFloat();';
}
return 'packet.readLengthCodedString("ascii");';
case Types.GEOMETRY:
return 'packet.parseGeometryValue();';
case Types.VECTOR:
return 'packet.parseVector()';
case Types.JSON:
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/409
return config.jsonStrings ? 'packet.readLengthCodedString("utf8")' : 'JSON.parse(packet.readLengthCodedString("utf8"));';
case Types.LONGLONG:
if (!supportBigNumbers) {
return unsigned
? 'packet.readInt64JSNumber();'
: 'packet.readSInt64JSNumber();';
}
if (bigNumberStrings) {
return unsigned
? 'packet.readInt64String();'
: 'packet.readSInt64String();';
}
return unsigned ? 'packet.readInt64();' : 'packet.readSInt64();';
default:
if (field.characterSet === Charsets.BINARY) {
return 'packet.readLengthCodedBuffer();';
}
return `packet.readLengthCodedString(fields[${fieldNum}].encoding)`;
}
}
function compile(fields, options, config) {
const parserFn = genFunc();
const nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
function wrap(field, packet) {
return {
type: typeNames[field.columnType],
length: field.columnLength,
db: field.schema,
table: field.table,
name: field.name,
string: function (encoding = field.encoding) {
if (field.columnType === Types.JSON && encoding === field.encoding) {
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/1661
console.warn(
`typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\``,
);
}
if (
[Types.DATETIME, Types.NEWDATE, Types.TIMESTAMP, Types.DATE].includes(
field.columnType,
)
) {
return packet.readDateTimeString(parseInt(field.decimals, 10));
}
if (field.columnType === Types.TINY) {
const unsigned = field.flags & FieldFlags.UNSIGNED;
return String(unsigned ? packet.readInt8() : packet.readSInt8());
}
if (field.columnType === Types.TIME) {
return packet.readTimeString();
}
return packet.readLengthCodedString(encoding);
},
buffer: function () {
return packet.readLengthCodedBuffer();
},
geometry: function () {
return packet.parseGeometryValue();
},
};
}
parserFn('(function(){');
parserFn('return class BinaryRow {');
parserFn('constructor() {');
parserFn('}');
parserFn('next(packet, fields, options) {');
if (options.rowsAsArray) {
parserFn(`const result = new Array(${fields.length});`);
} else {
parserFn('const result = {};');
}
// Global typeCast
if (
typeof config.typeCast === 'function' &&
typeof options.typeCast !== 'function'
) {
options.typeCast = config.typeCast;
}
parserFn('packet.readInt8();'); // status byte
for (let i = 0; i < nullBitmapLength; ++i) {
parserFn(`const nullBitmaskByte${i} = packet.readInt8();`);
}
let lvalue = '';
let currentFieldNullBit = 4;
let nullByteIndex = 0;
let fieldName = '';
let tableName = '';
for (let i = 0; i < fields.length; i++) {
fieldName = helpers.fieldEscape(fields[i].name);
// parserFn(`// ${fieldName}: ${typeNames[fields[i].columnType]}`);
if (typeof options.nestTables === 'string') {
lvalue = `result[${helpers.fieldEscape(fields[i].table + options.nestTables + fields[i].name)}]`;
} else if (options.nestTables === true) {
tableName = helpers.fieldEscape(fields[i].table);
parserFn(`if (!result[${tableName}]) result[${tableName}] = {};`);
lvalue = `result[${tableName}][${fieldName}]`;
} else if (options.rowsAsArray) {
lvalue = `result[${i.toString(10)}]`;
} else {
lvalue = `result[${fieldName}]`;
}
parserFn(`if (nullBitmaskByte${nullByteIndex} & ${currentFieldNullBit}) `);
parserFn(`${lvalue} = null;`);
parserFn('else {');
if (options.typeCast === false) {
parserFn(`${lvalue} = packet.readLengthCodedBuffer();`);
} else {
const fieldWrapperVar = `fieldWrapper${i}`;
parserFn(`const ${fieldWrapperVar} = wrap(fields[${i}], packet);`);
const readCode = readCodeFor(fields[i], config, options, i);
if (typeof options.typeCast === 'function') {
parserFn(
`${lvalue} = options.typeCast(${fieldWrapperVar}, function() { return ${readCode} });`,
);
} else {
parserFn(`${lvalue} = ${readCode};`);
}
}
parserFn('}');
currentFieldNullBit *= 2;
if (currentFieldNullBit === 0x100) {
currentFieldNullBit = 1;
nullByteIndex++;
}
}
parserFn('return result;');
parserFn('}');
parserFn('};')('})()');
if (config.debug) {
helpers.printDebugWithCode(
'Compiled binary protocol row parser',
parserFn.toString(),
);
}
return parserFn.toFunction({ wrap });
}
function getBinaryParser(fields, options, config) {
return parserCache.getParser('binary', fields, options, config, compile);
}
module.exports = getBinaryParser;

66
node_modules/mysql2/lib/parsers/parser_cache.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
'use strict';
const LRU = require('lru-cache').default;
let parserCache = new LRU({
max: 15000,
});
function keyFromFields(type, fields, options, config) {
const res = [
type,
typeof options.nestTables,
options.nestTables,
Boolean(options.rowsAsArray),
Boolean(options.supportBigNumbers || config.supportBigNumbers),
Boolean(options.bigNumberStrings || config.bigNumberStrings),
typeof options.typeCast,
options.timezone || config.timezone,
Boolean(options.decimalNumbers),
options.dateStrings,
];
for (let i = 0; i < fields.length; ++i) {
const field = fields[i];
res.push([
field.name,
field.columnType,
field.length,
field.schema,
field.table,
field.flags,
field.characterSet,
]);
}
return JSON.stringify(res, null, 0);
}
function getParser(type, fields, options, config, compiler) {
const key = keyFromFields(type, fields, options, config);
let parser = parserCache.get(key);
if (parser) {
return parser;
}
parser = compiler(fields, options, config);
parserCache.set(key, parser);
return parser;
}
function setMaxCache(max) {
parserCache = new LRU({ max });
}
function clearCache() {
parserCache.clear();
}
module.exports = {
getParser: getParser,
setMaxCache: setMaxCache,
clearCache: clearCache,
_keyFromFields: keyFromFields,
};

50
node_modules/mysql2/lib/parsers/string.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
'use strict';
const Iconv = require('iconv-lite');
const LRU = require('lru-cache').default;
const decoderCache = new LRU({
max: 500,
});
exports.decode = function (buffer, encoding, start, end, options) {
if (Buffer.isEncoding(encoding)) {
return buffer.toString(encoding, start, end);
}
// Optimize for common case: encoding="short_string", options=undefined.
let decoder;
if (!options) {
decoder = decoderCache.get(encoding);
if (!decoder) {
decoder = Iconv.getDecoder(encoding);
decoderCache.set(encoding, decoder);
}
} else {
const decoderArgs = { encoding, options };
const decoderKey = JSON.stringify(decoderArgs);
decoder = decoderCache.get(decoderKey);
if (!decoder) {
decoder = Iconv.getDecoder(decoderArgs.encoding, decoderArgs.options);
decoderCache.set(decoderKey, decoder);
}
}
const res = decoder.write(buffer.slice(start, end));
const trail = decoder.end();
return trail ? res + trail : res;
};
exports.encode = function (string, encoding, options) {
if (Buffer.isEncoding(encoding)) {
return Buffer.from(string, encoding);
}
const encoder = Iconv.getEncoder(encoding, options || {});
const res = encoder.write(string);
const trail = encoder.end();
return trail && trail.length > 0 ? Buffer.concat([res, trail]) : res;
};

212
node_modules/mysql2/lib/parsers/text_parser.js generated vendored Normal file
View File

@@ -0,0 +1,212 @@
'use strict';
const Types = require('../constants/types.js');
const Charsets = require('../constants/charsets.js');
const helpers = require('../helpers');
const genFunc = require('generate-function');
const parserCache = require('./parser_cache.js');
const typeNames = [];
for (const t in Types) {
typeNames[Types[t]] = t;
}
function readCodeFor(type, charset, encodingExpr, config, options) {
const supportBigNumbers = Boolean(
options.supportBigNumbers || config.supportBigNumbers,
);
const bigNumberStrings = Boolean(
options.bigNumberStrings || config.bigNumberStrings,
);
const timezone = options.timezone || config.timezone;
const dateStrings = options.dateStrings || config.dateStrings;
switch (type) {
case Types.TINY:
case Types.SHORT:
case Types.LONG:
case Types.INT24:
case Types.YEAR:
return 'packet.parseLengthCodedIntNoBigCheck()';
case Types.LONGLONG:
if (supportBigNumbers && bigNumberStrings) {
return 'packet.parseLengthCodedIntString()';
}
return `packet.parseLengthCodedInt(${supportBigNumbers})`;
case Types.FLOAT:
case Types.DOUBLE:
return 'packet.parseLengthCodedFloat()';
case Types.NULL:
return 'packet.readLengthCodedNumber()';
case Types.DECIMAL:
case Types.NEWDECIMAL:
if (config.decimalNumbers) {
return 'packet.parseLengthCodedFloat()';
}
return 'packet.readLengthCodedString("ascii")';
case Types.DATE:
if (helpers.typeMatch(type, dateStrings, Types)) {
return 'packet.readLengthCodedString("ascii")';
}
return `packet.parseDate(${helpers.srcEscape(timezone)})`;
case Types.DATETIME:
case Types.TIMESTAMP:
if (helpers.typeMatch(type, dateStrings, Types)) {
return 'packet.readLengthCodedString("ascii")';
}
return `packet.parseDateTime(${helpers.srcEscape(timezone)})`;
case Types.TIME:
return 'packet.readLengthCodedString("ascii")';
case Types.GEOMETRY:
return 'packet.parseGeometryValue()';
case Types.VECTOR:
return 'packet.parseVector()';
case Types.JSON:
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/409
return config.jsonStrings ? 'packet.readLengthCodedString("utf8")' : 'JSON.parse(packet.readLengthCodedString("utf8"))';
default:
if (charset === Charsets.BINARY) {
return 'packet.readLengthCodedBuffer()';
}
return `packet.readLengthCodedString(${encodingExpr})`;
}
}
function compile(fields, options, config) {
// use global typeCast if current query doesn't specify one
if (
typeof config.typeCast === 'function' &&
typeof options.typeCast !== 'function'
) {
options.typeCast = config.typeCast;
}
function wrap(field, _this) {
return {
type: typeNames[field.columnType],
length: field.columnLength,
db: field.schema,
table: field.table,
name: field.name,
string: function (encoding = field.encoding) {
if (field.columnType === Types.JSON && encoding === field.encoding) {
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/1661
console.warn(
`typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\``,
);
}
return _this.packet.readLengthCodedString(encoding);
},
buffer: function () {
return _this.packet.readLengthCodedBuffer();
},
geometry: function () {
return _this.packet.parseGeometryValue();
},
};
}
const parserFn = genFunc();
parserFn('(function () {')('return class TextRow {');
// constructor method
parserFn('constructor(fields) {');
// node-mysql typeCast compatibility wrapper
// see https://github.com/mysqljs/mysql/blob/96fdd0566b654436624e2375c7b6604b1f50f825/lib/protocol/packets/Field.js
if (typeof options.typeCast === 'function') {
parserFn('const _this = this;');
parserFn('for(let i=0; i<fields.length; ++i) {');
parserFn('this[`wrap${i}`] = wrap(fields[i], _this);');
parserFn('}');
}
parserFn('}');
// next method
parserFn('next(packet, fields, options) {');
parserFn('this.packet = packet;');
if (options.rowsAsArray) {
parserFn(`const result = new Array(${fields.length});`);
} else {
parserFn('const result = {};');
}
const resultTables = {};
let resultTablesArray = [];
if (options.nestTables === true) {
for (let i = 0; i < fields.length; i++) {
resultTables[fields[i].table] = 1;
}
resultTablesArray = Object.keys(resultTables);
for (let i = 0; i < resultTablesArray.length; i++) {
parserFn(`result[${helpers.fieldEscape(resultTablesArray[i])}] = {};`);
}
}
let lvalue = '';
let fieldName = '';
let tableName = '';
for (let i = 0; i < fields.length; i++) {
fieldName = helpers.fieldEscape(fields[i].name);
// parserFn(`// ${fieldName}: ${typeNames[fields[i].columnType]}`);
if (typeof options.nestTables === 'string') {
lvalue = `result[${helpers.fieldEscape(fields[i].table + options.nestTables + fields[i].name)}]`;
} else if (options.nestTables === true) {
tableName = helpers.fieldEscape(fields[i].table);
parserFn(`if (!result[${tableName}]) result[${tableName}] = {};`);
lvalue = `result[${tableName}][${fieldName}]`;
} else if (options.rowsAsArray) {
lvalue = `result[${i.toString(10)}]`;
} else {
lvalue = `result[${fieldName}]`;
}
if (options.typeCast === false) {
parserFn(`${lvalue} = packet.readLengthCodedBuffer();`);
} else {
const encodingExpr = `fields[${i}].encoding`;
const readCode = readCodeFor(
fields[i].columnType,
fields[i].characterSet,
encodingExpr,
config,
options,
);
if (typeof options.typeCast === 'function') {
parserFn(
`${lvalue} = options.typeCast(this.wrap${i}, function() { return ${readCode} });`,
);
} else {
parserFn(`${lvalue} = ${readCode};`);
}
}
}
parserFn('return result;');
parserFn('}');
parserFn('};')('})()');
if (config.debug) {
helpers.printDebugWithCode(
'Compiled text protocol row parser',
parserFn.toString(),
);
}
if (typeof options.typeCast === 'function') {
return parserFn.toFunction({ wrap });
}
return parserFn.toFunction();
}
function getTextParser(fields, options, config) {
return parserCache.getParser('text', fields, options, config, compile);
}
module.exports = getTextParser;

237
node_modules/mysql2/lib/pool.js generated vendored Normal file
View File

@@ -0,0 +1,237 @@
'use strict';
const process = require('process');
const mysql = require('../index.js');
const EventEmitter = require('events').EventEmitter;
const PoolConnection = require('./pool_connection.js');
const Queue = require('denque');
const Connection = require('./connection.js');
function spliceConnection(queue, connection) {
const len = queue.length;
for (let i = 0; i < len; i++) {
if (queue.get(i) === connection) {
queue.removeOne(i);
break;
}
}
}
class Pool extends EventEmitter {
constructor(options) {
super();
this.config = options.config;
this.config.connectionConfig.pool = this;
this._allConnections = new Queue();
this._freeConnections = new Queue();
this._connectionQueue = new Queue();
this._closed = false;
if (this.config.maxIdle < this.config.connectionLimit) {
// create idle connection timeout automatically release job
this._removeIdleTimeoutConnections();
}
}
promise(promiseImpl) {
const PromisePool = require('../promise').PromisePool;
return new PromisePool(this, promiseImpl);
}
getConnection(cb) {
if (this._closed) {
return process.nextTick(() => cb(new Error('Pool is closed.')));
}
let connection;
if (this._freeConnections.length > 0) {
connection = this._freeConnections.pop();
this.emit('acquire', connection);
return process.nextTick(() => cb(null, connection));
}
if (
this.config.connectionLimit === 0 ||
this._allConnections.length < this.config.connectionLimit
) {
connection = new PoolConnection(this, {
config: this.config.connectionConfig
});
this._allConnections.push(connection);
return connection.connect(err => {
if (this._closed) {
return cb(new Error('Pool is closed.'));
}
if (err) {
return cb(err);
}
this.emit('connection', connection);
this.emit('acquire', connection);
return cb(null, connection);
});
}
if (!this.config.waitForConnections) {
return process.nextTick(() => cb(new Error('No connections available.')));
}
if (
this.config.queueLimit &&
this._connectionQueue.length >= this.config.queueLimit
) {
return cb(new Error('Queue limit reached.'));
}
this.emit('enqueue');
return this._connectionQueue.push(cb);
}
releaseConnection(connection) {
let cb;
if (!connection._pool) {
// The connection has been removed from the pool and is no longer good.
if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(this.getConnection.bind(this, cb));
}
} else if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(cb.bind(null, null, connection));
} else {
this._freeConnections.push(connection);
this.emit('release', connection);
}
}
end(cb) {
this._closed = true;
clearTimeout(this._removeIdleTimeoutConnectionsTimer);
if (typeof cb !== 'function') {
cb = function(err) {
if (err) {
throw err;
}
};
}
let calledBack = false;
let closedConnections = 0;
let connection;
const endCB = function(err) {
if (calledBack) {
return;
}
if (err || ++closedConnections >= this._allConnections.length) {
calledBack = true;
cb(err);
return;
}
}.bind(this);
if (this._allConnections.length === 0) {
endCB();
return;
}
for (let i = 0; i < this._allConnections.length; i++) {
connection = this._allConnections.get(i);
connection._realEnd(endCB);
}
}
query(sql, values, cb) {
const cmdQuery = Connection.createQuery(
sql,
values,
cb,
this.config.connectionConfig
);
if (typeof cmdQuery.namedPlaceholders === 'undefined') {
cmdQuery.namedPlaceholders = this.config.connectionConfig.namedPlaceholders;
}
this.getConnection((err, conn) => {
if (err) {
if (typeof cmdQuery.onResult === 'function') {
cmdQuery.onResult(err);
} else {
cmdQuery.emit('error', err);
}
return;
}
try {
conn.query(cmdQuery).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
throw e;
}
});
return cmdQuery;
}
execute(sql, values, cb) {
// TODO construct execute command first here and pass it to connection.execute
// so that polymorphic arguments logic is there in one place
if (typeof values === 'function') {
cb = values;
values = [];
}
this.getConnection((err, conn) => {
if (err) {
return cb(err);
}
try {
conn.execute(sql, values, cb).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
return cb(e);
}
});
}
_removeConnection(connection) {
// Remove connection from all connections
spliceConnection(this._allConnections, connection);
// Remove connection from free connections
spliceConnection(this._freeConnections, connection);
this.releaseConnection(connection);
}
_removeIdleTimeoutConnections() {
if (this._removeIdleTimeoutConnectionsTimer) {
clearTimeout(this._removeIdleTimeoutConnectionsTimer);
}
this._removeIdleTimeoutConnectionsTimer = setTimeout(() => {
try {
while (
this._freeConnections.length > this.config.maxIdle &&
Date.now() - this._freeConnections.get(0).lastActiveTime >
this.config.idleTimeout
) {
this._freeConnections.get(0).destroy();
}
} finally {
this._removeIdleTimeoutConnections();
}
}, 1000);
}
format(sql, values) {
return mysql.format(
sql,
values,
this.config.connectionConfig.stringifyObjects,
this.config.connectionConfig.timezone
);
}
escape(value) {
return mysql.escape(
value,
this.config.connectionConfig.stringifyObjects,
this.config.connectionConfig.timezone
);
}
escapeId(value) {
return mysql.escapeId(value, false);
}
}
module.exports = Pool;

283
node_modules/mysql2/lib/pool_cluster.js generated vendored Normal file
View File

@@ -0,0 +1,283 @@
'use strict';
const process = require('process');
const Pool = require('./pool.js');
const PoolConfig = require('./pool_config.js');
const Connection = require('./connection.js');
const EventEmitter = require('events').EventEmitter;
/**
* Selector
*/
const makeSelector = {
RR() {
let index = 0;
return clusterIds => clusterIds[index++ % clusterIds.length];
},
RANDOM() {
return clusterIds =>
clusterIds[Math.floor(Math.random() * clusterIds.length)];
},
ORDER() {
return clusterIds => clusterIds[0];
}
};
class PoolNamespace {
constructor(cluster, pattern, selector) {
this._cluster = cluster;
this._pattern = pattern;
this._selector = makeSelector[selector]();
}
getConnection(cb) {
const clusterNode = this._getClusterNode();
if (clusterNode === null) {
return cb(new Error('Pool does Not exists.'));
}
return this._cluster._getConnection(clusterNode, (err, connection) => {
if (err) {
return cb(err);
}
if (connection === 'retry') {
return this.getConnection(cb);
}
return cb(null, connection);
});
}
/**
* pool cluster query
* @param {*} sql
* @param {*} values
* @param {*} cb
* @returns query
*/
query(sql, values, cb) {
const query = Connection.createQuery(sql, values, cb, {});
this.getConnection((err, conn) => {
if (err) {
if (typeof query.onResult === 'function') {
query.onResult(err);
} else {
query.emit('error', err);
}
return;
}
try {
conn.query(query).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
throw e;
}
});
return query;
}
/**
* pool cluster execute
* @param {*} sql
* @param {*} values
* @param {*} cb
*/
execute(sql, values, cb) {
if (typeof values === 'function') {
cb = values;
values = [];
}
this.getConnection((err, conn) => {
if (err) {
return cb(err);
}
try {
conn.execute(sql, values, cb).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
throw e;
}
});
}
_getClusterNode() {
const foundNodeIds = this._cluster._findNodeIds(this._pattern);
if (foundNodeIds.length === 0) {
return null;
}
const nodeId =
foundNodeIds.length === 1
? foundNodeIds[0]
: this._selector(foundNodeIds);
return this._cluster._getNode(nodeId);
}
}
class PoolCluster extends EventEmitter {
constructor(config) {
super();
config = config || {};
this._canRetry =
typeof config.canRetry === 'undefined' ? true : config.canRetry;
this._removeNodeErrorCount = config.removeNodeErrorCount || 5;
this._defaultSelector = config.defaultSelector || 'RR';
this._closed = false;
this._lastId = 0;
this._nodes = {};
this._serviceableNodeIds = [];
this._namespaces = {};
this._findCaches = {};
}
of(pattern, selector) {
pattern = pattern || '*';
selector = selector || this._defaultSelector;
selector = selector.toUpperCase();
if (!makeSelector[selector] === 'undefined') {
selector = this._defaultSelector;
}
const key = pattern + selector;
if (typeof this._namespaces[key] === 'undefined') {
this._namespaces[key] = new PoolNamespace(this, pattern, selector);
}
return this._namespaces[key];
}
add(id, config) {
if (typeof id === 'object') {
config = id;
id = `CLUSTER::${++this._lastId}`;
}
if (typeof this._nodes[id] === 'undefined') {
this._nodes[id] = {
id: id,
errorCount: 0,
pool: new Pool({ config: new PoolConfig(config) })
};
this._serviceableNodeIds.push(id);
this._clearFindCaches();
}
}
getConnection(pattern, selector, cb) {
let 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);
}
end(callback) {
const cb =
callback !== undefined
? callback
: err => {
if (err) {
throw err;
}
};
if (this._closed) {
process.nextTick(cb);
return;
}
this._closed = true;
let calledBack = false;
let waitingClose = 0;
const onEnd = err => {
if (!calledBack && (err || --waitingClose <= 0)) {
calledBack = true;
return cb(err);
}
};
for (const id in this._nodes) {
waitingClose++;
this._nodes[id].pool.end(onEnd);
}
if (waitingClose === 0) {
process.nextTick(onEnd);
}
}
_findNodeIds(pattern) {
if (typeof this._findCaches[pattern] !== 'undefined') {
return this._findCaches[pattern];
}
let foundNodeIds;
if (pattern === '*') {
// all
foundNodeIds = this._serviceableNodeIds;
} else if (this._serviceableNodeIds.indexOf(pattern) !== -1) {
// one
foundNodeIds = [pattern];
} else {
// wild matching
const keyword = pattern.substring(pattern.length - 1, 0);
foundNodeIds = this._serviceableNodeIds.filter(id =>
id.startsWith(keyword)
);
}
this._findCaches[pattern] = foundNodeIds;
return foundNodeIds;
}
_getNode(id) {
return this._nodes[id] || null;
}
_increaseErrorCount(node) {
if (++node.errorCount >= this._removeNodeErrorCount) {
const index = this._serviceableNodeIds.indexOf(node.id);
if (index !== -1) {
this._serviceableNodeIds.splice(index, 1);
delete this._nodes[node.id];
this._clearFindCaches();
node.pool.end();
this.emit('remove', node.id);
}
}
}
_decreaseErrorCount(node) {
if (node.errorCount > 0) {
--node.errorCount;
}
}
_getConnection(node, cb) {
node.pool.getConnection((err, connection) => {
if (err) {
this._increaseErrorCount(node);
if (this._canRetry) {
// REVIEW: this seems wrong?
this.emit('warn', err);
// eslint-disable-next-line no-console
console.warn(`[Error] PoolCluster : ${err}`);
return cb(null, 'retry');
}
return cb(err);
}
this._decreaseErrorCount(node);
connection._clusterId = node.id;
return cb(null, connection);
});
}
_clearFindCaches() {
this._findCaches = {};
}
}
module.exports = PoolCluster;

30
node_modules/mysql2/lib/pool_config.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
'use strict';
const ConnectionConfig = require('./connection_config.js');
class PoolConfig {
constructor(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.connectionConfig = new ConnectionConfig(options);
this.waitForConnections =
options.waitForConnections === undefined
? true
: Boolean(options.waitForConnections);
this.connectionLimit = isNaN(options.connectionLimit)
? 10
: Number(options.connectionLimit);
this.maxIdle = isNaN(options.maxIdle)
? this.connectionLimit
: Number(options.maxIdle);
this.idleTimeout = isNaN(options.idleTimeout)
? 60000
: Number(options.idleTimeout);
this.queueLimit = isNaN(options.queueLimit)
? 0
: Number(options.queueLimit);
}
}
module.exports = PoolConfig;

69
node_modules/mysql2/lib/pool_connection.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
'use strict';
const Connection = require('../index.js').Connection;
class PoolConnection extends Connection {
constructor(pool, options) {
super(options);
this._pool = pool;
// The last active time of this connection
this.lastActiveTime = Date.now();
// 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.
// REVIEW: Moved to `once`
this.once('end', () => {
this._removeFromPool();
});
this.once('error', () => {
this._removeFromPool();
});
}
release() {
if (!this._pool || this._pool._closed) {
return;
}
// update last active time
this.lastActiveTime = Date.now();
this._pool.releaseConnection(this);
}
promise(promiseImpl) {
const PromisePoolConnection = require('../promise').PromisePoolConnection;
return new PromisePoolConnection(this, promiseImpl);
}
end() {
const err = new Error(
'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.emit('warn', err);
// eslint-disable-next-line no-console
console.warn(err.message);
this.release();
}
destroy() {
this._removeFromPool();
super.destroy();
}
_removeFromPool() {
if (!this._pool || this._pool._closed) {
return;
}
const pool = this._pool;
this._pool = null;
pool._removeConnection(this);
}
}
PoolConnection.statementKey = Connection.statementKey;
module.exports = PoolConnection;
// TODO: Remove this when we are removing PoolConnection#end
PoolConnection.prototype._realEnd = Connection.prototype.end;

38
node_modules/mysql2/lib/results_stream.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict';
const Readable = require('stream').Readable;
// copy-paste from https://github.com/mysqljs/mysql/blob/master/lib/protocol/sequences/Query.js
module.exports = function(command, connectionStream) {
command.stream = function(options) {
let stream;
options = options || {};
options.objectMode = true;
(stream = new Readable(options)),
(stream._read = function() {
connectionStream.resume();
});
this.on('result', (row, i) => {
if (!stream.push(row)) {
connectionStream.pause();
}
stream.emit('result', row, i); // replicate old emitter
});
this.on('error', err => {
stream.emit('error', err); // Pass on any errors
});
this.on('end', () => {
stream.push(null); // pushing null, indicating EOF
});
this.on('fields', (fields, i) => {
stream.emit('fields', fields, i); // replicate old emitter
});
return stream;
};
};

37
node_modules/mysql2/lib/server.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
'use strict';
const net = require('net');
const EventEmitter = require('events').EventEmitter;
const Connection = require('./connection');
const ConnectionConfig = require('./connection_config');
// TODO: inherit Server from net.Server
class Server extends EventEmitter {
constructor() {
super();
this.connections = [];
this._server = net.createServer(this._handleConnection.bind(this));
}
_handleConnection(socket) {
const connectionConfig = new ConnectionConfig({
stream: socket,
isServer: true
});
const connection = new Connection({ config: connectionConfig });
this.emit('connection', connection);
}
listen(port) {
this._port = port;
this._server.listen.apply(this._server, arguments);
return this;
}
close(cb) {
this._server.close(cb);
}
}
module.exports = Server;

15
node_modules/mysql2/node_modules/lru-cache/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) 2010-2023 Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

1180
node_modules/mysql2/node_modules/lru-cache/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
import LRUCache from './index.js';
declare const _default: typeof LRUCache & {
default: typeof LRUCache;
LRUCache: typeof LRUCache;
};
export = _default;
//# sourceMappingURL=index-cjs.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index-cjs.d.ts","sourceRoot":"","sources":["../../src/index-cjs.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,YAAY,CAAA;;;;;AAEjC,kBAAiE"}

View File

@@ -0,0 +1,7 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const index_js_1 = __importDefault(require("./index.js"));
module.exports = Object.assign(index_js_1.default, { default: index_js_1.default, LRUCache: index_js_1.default });
//# sourceMappingURL=index-cjs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index-cjs.js","sourceRoot":"","sources":["../../src/index-cjs.ts"],"names":[],"mappings":";;;;AAAA,0DAAiC;AAEjC,iBAAS,MAAM,CAAC,MAAM,CAAC,kBAAQ,EAAE,EAAE,OAAO,EAAE,kBAAQ,EAAE,QAAQ,EAAR,kBAAQ,EAAE,CAAC,CAAA","sourcesContent":["import LRUCache from './index.js'\n\nexport = Object.assign(LRUCache, { default: LRUCache, LRUCache })\n"]}

View File

@@ -0,0 +1,807 @@
/**
* @module LRUCache
*/
declare const TYPE: unique symbol;
type Index = number & {
[TYPE]: 'LRUCache Index';
};
type UintArray = Uint8Array | Uint16Array | Uint32Array;
type NumberArray = UintArray | number[];
declare class ZeroArray extends Array<number> {
constructor(size: number);
}
type StackLike = Stack | Index[];
declare class Stack {
#private;
heap: NumberArray;
length: number;
static create(max: number): StackLike;
constructor(max: number, HeapCls: {
new (n: number): NumberArray;
});
push(n: Index): void;
pop(): Index;
}
/**
* Promise representing an in-progress {@link LRUCache#fetch} call
*/
export type BackgroundFetch<V> = Promise<V | undefined | void> & {
__returned: BackgroundFetch<V> | undefined;
__abortController: AbortController;
__staleWhileFetching: V | undefined;
};
export declare namespace LRUCache {
/**
* An integer greater than 0, reflecting the calculated size of items
*/
type Size = number;
/**
* Integer greater than 0, representing some number of milliseconds, or the
* time at which a TTL started counting from.
*/
type Milliseconds = number;
/**
* An integer greater than 0, reflecting a number of items
*/
type Count = number;
/**
* The reason why an item was removed from the cache, passed
* to the {@link Disposer} methods.
*/
type DisposeReason = 'evict' | 'set' | 'delete';
/**
* A method called upon item removal, passed as the
* {@link OptionsBase.dispose} and/or
* {@link OptionsBase.disposeAfter} options.
*/
type Disposer<K, V> = (value: V, key: K, reason: DisposeReason) => void;
/**
* A function that returns the effective calculated size
* of an entry in the cache.
*/
type SizeCalculator<K, V> = (value: V, key: K) => Size;
/**
* Options provided to the
* {@link OptionsBase.fetchMethod} function.
*/
interface FetcherOptions<K, V, FC = unknown> {
signal: AbortSignal;
options: FetcherFetchOptions<K, V, FC>;
/**
* Object provided in the {@link FetchOptions.context} option to
* {@link LRUCache#fetch}
*/
context: FC;
}
/**
* Status object that may be passed to {@link LRUCache#fetch},
* {@link LRUCache#get}, {@link LRUCache#set}, and {@link LRUCache#has}.
*/
interface Status<V> {
/**
* The status of a set() operation.
*
* - add: the item was not found in the cache, and was added
* - update: the item was in the cache, with the same value provided
* - replace: the item was in the cache, and replaced
* - miss: the item was not added to the cache for some reason
*/
set?: 'add' | 'update' | 'replace' | 'miss';
/**
* the ttl stored for the item, or undefined if ttls are not used.
*/
ttl?: Milliseconds;
/**
* the start time for the item, or undefined if ttls are not used.
*/
start?: Milliseconds;
/**
* The timestamp used for TTL calculation
*/
now?: Milliseconds;
/**
* the remaining ttl for the item, or undefined if ttls are not used.
*/
remainingTTL?: Milliseconds;
/**
* The calculated size for the item, if sizes are used.
*/
entrySize?: Size;
/**
* The total calculated size of the cache, if sizes are used.
*/
totalCalculatedSize?: Size;
/**
* A flag indicating that the item was not stored, due to exceeding the
* {@link OptionsBase.maxEntrySize}
*/
maxEntrySizeExceeded?: true;
/**
* The old value, specified in the case of `set:'update'` or
* `set:'replace'`
*/
oldValue?: V;
/**
* The results of a {@link LRUCache#has} operation
*
* - hit: the item was found in the cache
* - stale: the item was found in the cache, but is stale
* - miss: the item was not found in the cache
*/
has?: 'hit' | 'stale' | 'miss';
/**
* The status of a {@link LRUCache#fetch} operation.
* Note that this can change as the underlying fetch() moves through
* various states.
*
* - inflight: there is another fetch() for this key which is in process
* - get: there is no fetchMethod, so {@link LRUCache#get} was called.
* - miss: the item is not in cache, and will be fetched.
* - hit: the item is in the cache, and was resolved immediately.
* - stale: the item is in the cache, but stale.
* - refresh: the item is in the cache, and not stale, but
* {@link FetchOptions.forceRefresh} was specified.
*/
fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh';
/**
* The {@link OptionsBase.fetchMethod} was called
*/
fetchDispatched?: true;
/**
* The cached value was updated after a successful call to
* {@link OptionsBase.fetchMethod}
*/
fetchUpdated?: true;
/**
* The reason for a fetch() rejection. Either the error raised by the
* {@link OptionsBase.fetchMethod}, or the reason for an
* AbortSignal.
*/
fetchError?: Error;
/**
* The fetch received an abort signal
*/
fetchAborted?: true;
/**
* The abort signal received was ignored, and the fetch was allowed to
* continue.
*/
fetchAbortIgnored?: true;
/**
* The fetchMethod promise resolved successfully
*/
fetchResolved?: true;
/**
* The fetchMethod promise was rejected
*/
fetchRejected?: true;
/**
* The status of a {@link LRUCache#get} operation.
*
* - fetching: The item is currently being fetched. If a previous value
* is present and allowed, that will be returned.
* - stale: The item is in the cache, and is stale.
* - hit: the item is in the cache
* - miss: the item is not in the cache
*/
get?: 'stale' | 'hit' | 'miss';
/**
* A fetch or get operation returned a stale value.
*/
returnedStale?: true;
}
/**
* options which override the options set in the LRUCache constructor
* when calling {@link LRUCache#fetch}.
*
* This is the union of {@link GetOptions} and {@link SetOptions}, plus
* {@link OptionsBase.noDeleteOnFetchRejection},
* {@link OptionsBase.allowStaleOnFetchRejection},
* {@link FetchOptions.forceRefresh}, and
* {@link OptionsBase.context}
*
* Any of these may be modified in the {@link OptionsBase.fetchMethod}
* function, but the {@link GetOptions} fields will of course have no
* effect, as the {@link LRUCache#get} call already happened by the time
* the fetchMethod is called.
*/
interface FetcherFetchOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
status?: Status<V>;
size?: Size;
}
/**
* Options that may be passed to the {@link LRUCache#fetch} method.
*/
interface FetchOptions<K, V, FC> extends FetcherFetchOptions<K, V, FC> {
/**
* Set to true to force a re-load of the existing data, even if it
* is not yet stale.
*/
forceRefresh?: boolean;
/**
* Context provided to the {@link OptionsBase.fetchMethod} as
* the {@link FetcherOptions.context} param.
*
* If the FC type is specified as unknown (the default),
* undefined or void, then this is optional. Otherwise, it will
* be required.
*/
context?: FC;
signal?: AbortSignal;
status?: Status<V>;
}
/**
* Options provided to {@link LRUCache#fetch} when the FC type is something
* other than `unknown`, `undefined`, or `void`
*/
interface FetchOptionsWithContext<K, V, FC> extends FetchOptions<K, V, FC> {
context: FC;
}
/**
* Options provided to {@link LRUCache#fetch} when the FC type is
* `undefined` or `void`
*/
interface FetchOptionsNoContext<K, V, FC> extends FetchOptions<K, V, FC> {
context?: undefined;
}
/**
* Options that may be passed to the {@link LRUCache#has} method.
*/
interface HasOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {
status?: Status<V>;
}
/**
* Options that may be passed to the {@link LRUCache#get} method.
*/
interface GetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'> {
status?: Status<V>;
}
/**
* Options that may be passed to the {@link LRUCache#peek} method.
*/
interface PeekOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {
}
/**
* Options that may be passed to the {@link LRUCache#set} method.
*/
interface SetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'> {
/**
* If size tracking is enabled, then setting an explicit size
* in the {@link LRUCache#set} call will prevent calling the
* {@link OptionsBase.sizeCalculation} function.
*/
size?: Size;
/**
* If TTL tracking is enabled, then setting an explicit start
* time in the {@link LRUCache#set} call will override the
* default time from `performance.now()` or `Date.now()`.
*
* Note that it must be a valid value for whichever time-tracking
* method is in use.
*/
start?: Milliseconds;
status?: Status<V>;
}
/**
* The type signature for the {@link OptionsBase.fetchMethod} option.
*/
type Fetcher<K, V, FC = unknown> = (key: K, staleValue: V | undefined, options: FetcherOptions<K, V, FC>) => Promise<V | void | undefined> | V | void | undefined;
/**
* Options which may be passed to the {@link LRUCache} constructor.
*
* Most of these may be overridden in the various options that use
* them.
*
* Despite all being technically optional, the constructor requires that
* a cache is at minimum limited by one or more of {@link OptionsBase.max},
* {@link OptionsBase.ttl}, or {@link OptionsBase.maxSize}.
*
* If {@link OptionsBase.ttl} is used alone, then it is strongly advised
* (and in fact required by the type definitions here) that the cache
* also set {@link OptionsBase.ttlAutopurge}, to prevent potentially
* unbounded storage.
*/
interface OptionsBase<K, V, FC> {
/**
* The maximum number of items to store in the cache before evicting
* old entries. This is read-only on the {@link LRUCache} instance,
* and may not be overridden.
*
* If set, then storage space will be pre-allocated at construction
* time, and the cache will perform significantly faster.
*
* Note that significantly fewer items may be stored, if
* {@link OptionsBase.maxSize} and/or {@link OptionsBase.ttl} are also
* set.
*/
max?: Count;
/**
* Max time in milliseconds for items to live in cache before they are
* considered stale. Note that stale items are NOT preemptively removed
* by default, and MAY live in the cache long after they have expired.
*
* Also, as this cache is optimized for LRU/MRU operations, some of
* the staleness/TTL checks will reduce performance, as they will incur
* overhead by deleting items.
*
* Must be an integer number of ms. If set to 0, this indicates "no TTL"
*
* @default 0
*/
ttl?: Milliseconds;
/**
* Minimum amount of time in ms in which to check for staleness.
* Defaults to 1, which means that the current time is checked
* at most once per millisecond.
*
* Set to 0 to check the current time every time staleness is tested.
* (This reduces performance, and is theoretically unnecessary.)
*
* Setting this to a higher value will improve performance somewhat
* while using ttl tracking, albeit at the expense of keeping stale
* items around a bit longer than their TTLs would indicate.
*
* @default 1
*/
ttlResolution?: Milliseconds;
/**
* Preemptively remove stale items from the cache.
* Note that this may significantly degrade performance,
* especially if the cache is storing a large number of items.
* It is almost always best to just leave the stale items in
* the cache, and let them fall out as new items are added.
*
* Note that this means that {@link OptionsBase.allowStale} is a bit
* pointless, as stale items will be deleted almost as soon as they
* expire.
*
* @default false
*/
ttlAutopurge?: boolean;
/**
* Update the age of items on {@link LRUCache#get}, renewing their TTL
*
* Has no effect if {@link OptionsBase.ttl} is not set.
*
* @default false
*/
updateAgeOnGet?: boolean;
/**
* Update the age of items on {@link LRUCache#has}, renewing their TTL
*
* Has no effect if {@link OptionsBase.ttl} is not set.
*
* @default false
*/
updateAgeOnHas?: boolean;
/**
* Allow {@link LRUCache#get} and {@link LRUCache#fetch} calls to return
* stale data, if available.
*/
allowStale?: boolean;
/**
* Function that is called on items when they are dropped from the cache.
* This can be handy if you want to close file descriptors or do other
* cleanup tasks when items are no longer accessible. Called with `key,
* value`. It's called before actually removing the item from the
* internal cache, so it is *NOT* safe to re-add them.
*
* Use {@link OptionsBase.disposeAfter} if you wish to dispose items after
* they have been full removed, when it is safe to add them back to the
* cache.
*/
dispose?: Disposer<K, V>;
/**
* The same as {@link OptionsBase.dispose}, but called *after* the entry
* is completely removed and the cache is once again in a clean state.
* It is safe to add an item right back into the cache at this point.
* However, note that it is *very* easy to inadvertently create infinite
* recursion this way.
*/
disposeAfter?: Disposer<K, V>;
/**
* Set to true to suppress calling the
* {@link OptionsBase.dispose} function if the entry key is
* still accessible within the cache.
* This may be overridden by passing an options object to
* {@link LRUCache#set}.
*/
noDisposeOnSet?: boolean;
/**
* Boolean flag to tell the cache to not update the TTL when
* setting a new value for an existing key (ie, when updating a value
* rather than inserting a new value). Note that the TTL value is
* _always_ set (if provided) when adding a new entry into the cache.
*
* Has no effect if a {@link OptionsBase.ttl} is not set.
*/
noUpdateTTL?: boolean;
/**
* If you wish to track item size, you must provide a maxSize
* note that we still will only keep up to max *actual items*,
* if max is set, so size tracking may cause fewer than max items
* to be stored. At the extreme, a single item of maxSize size
* will cause everything else in the cache to be dropped when it
* is added. Use with caution!
*
* Note also that size tracking can negatively impact performance,
* though for most cases, only minimally.
*/
maxSize?: Size;
/**
* The maximum allowed size for any single item in the cache.
*
* If a larger item is passed to {@link LRUCache#set} or returned by a
* {@link OptionsBase.fetchMethod}, then it will not be stored in the
* cache.
*/
maxEntrySize?: Size;
/**
* A function that returns a number indicating the item's size.
*
* If not provided, and {@link OptionsBase.maxSize} or
* {@link OptionsBase.maxEntrySize} are set, then all
* {@link LRUCache#set} calls **must** provide an explicit
* {@link SetOptions.size} or sizeCalculation param.
*/
sizeCalculation?: SizeCalculator<K, V>;
/**
* Method that provides the implementation for {@link LRUCache#fetch}
*/
fetchMethod?: Fetcher<K, V, FC>;
/**
* Set to true to suppress the deletion of stale data when a
* {@link OptionsBase.fetchMethod} returns a rejected promise.
*/
noDeleteOnFetchRejection?: boolean;
/**
* Do not delete stale items when they are retrieved with
* {@link LRUCache#get}.
*
* Note that the `get` return value will still be `undefined`
* unless {@link OptionsBase.allowStale} is true.
*/
noDeleteOnStaleGet?: boolean;
/**
* Set to true to allow returning stale data when a
* {@link OptionsBase.fetchMethod} throws an error or returns a rejected
* promise.
*
* This differs from using {@link OptionsBase.allowStale} in that stale
* data will ONLY be returned in the case that the
* {@link LRUCache#fetch} fails, not any other times.
*/
allowStaleOnFetchRejection?: boolean;
/**
* Set to true to return a stale value from the cache when the
* `AbortSignal` passed to the {@link OptionsBase.fetchMethod} dispatches an `'abort'`
* event, whether user-triggered, or due to internal cache behavior.
*
* Unless {@link OptionsBase.ignoreFetchAbort} is also set, the underlying
* {@link OptionsBase.fetchMethod} will still be considered canceled, and its return
* value will be ignored and not cached.
*/
allowStaleOnFetchAbort?: boolean;
/**
* Set to true to ignore the `abort` event emitted by the `AbortSignal`
* object passed to {@link OptionsBase.fetchMethod}, and still cache the
* resulting resolution value, as long as it is not `undefined`.
*
* When used on its own, this means aborted {@link LRUCache#fetch} calls are not
* immediately resolved or rejected when they are aborted, and instead
* take the full time to await.
*
* When used with {@link OptionsBase.allowStaleOnFetchAbort}, aborted
* {@link LRUCache#fetch} calls will resolve immediately to their stale
* cached value or `undefined`, and will continue to process and eventually
* update the cache when they resolve, as long as the resulting value is
* not `undefined`, thus supporting a "return stale on timeout while
* refreshing" mechanism by passing `AbortSignal.timeout(n)` as the signal.
*
* **Note**: regardless of this setting, an `abort` event _is still
* emitted on the `AbortSignal` object_, so may result in invalid results
* when passed to other underlying APIs that use AbortSignals.
*
* This may be overridden in the {@link OptionsBase.fetchMethod} or the
* call to {@link LRUCache#fetch}.
*/
ignoreFetchAbort?: boolean;
}
interface OptionsMaxLimit<K, V, FC> extends OptionsBase<K, V, FC> {
max: Count;
}
interface OptionsTTLLimit<K, V, FC> extends OptionsBase<K, V, FC> {
ttl: Milliseconds;
ttlAutopurge: boolean;
}
interface OptionsSizeLimit<K, V, FC> extends OptionsBase<K, V, FC> {
maxSize: Size;
}
/**
* The valid safe options for the {@link LRUCache} constructor
*/
type Options<K, V, FC> = OptionsMaxLimit<K, V, FC> | OptionsSizeLimit<K, V, FC> | OptionsTTLLimit<K, V, FC>;
/**
* Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump}
*/
interface Entry<V> {
value: V;
ttl?: Milliseconds;
size?: Size;
start?: Milliseconds;
}
}
/**
* Default export, the thing you're using this module to get.
*
* All properties from the options object (with the exception of
* {@link OptionsBase.max} and {@link OptionsBase.maxSize}) are added as
* normal public members. (`max` and `maxBase` are read-only getters.)
* Changing any of these will alter the defaults for subsequent method calls,
* but is otherwise safe.
*/
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> {
#private;
/**
* {@link LRUCache.OptionsBase.ttl}
*/
ttl: LRUCache.Milliseconds;
/**
* {@link LRUCache.OptionsBase.ttlResolution}
*/
ttlResolution: LRUCache.Milliseconds;
/**
* {@link LRUCache.OptionsBase.ttlAutopurge}
*/
ttlAutopurge: boolean;
/**
* {@link LRUCache.OptionsBase.updateAgeOnGet}
*/
updateAgeOnGet: boolean;
/**
* {@link LRUCache.OptionsBase.updateAgeOnHas}
*/
updateAgeOnHas: boolean;
/**
* {@link LRUCache.OptionsBase.allowStale}
*/
allowStale: boolean;
/**
* {@link LRUCache.OptionsBase.noDisposeOnSet}
*/
noDisposeOnSet: boolean;
/**
* {@link LRUCache.OptionsBase.noUpdateTTL}
*/
noUpdateTTL: boolean;
/**
* {@link LRUCache.OptionsBase.maxEntrySize}
*/
maxEntrySize: LRUCache.Size;
/**
* {@link LRUCache.OptionsBase.sizeCalculation}
*/
sizeCalculation?: LRUCache.SizeCalculator<K, V>;
/**
* {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
*/
noDeleteOnFetchRejection: boolean;
/**
* {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
*/
noDeleteOnStaleGet: boolean;
/**
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
*/
allowStaleOnFetchAbort: boolean;
/**
* {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
*/
allowStaleOnFetchRejection: boolean;
/**
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
*/
ignoreFetchAbort: boolean;
/**
* Do not call this method unless you need to inspect the
* inner workings of the cache. If anything returned by this
* object is modified in any way, strange breakage may occur.
*
* These fields are private for a reason!
*
* @internal
*/
static unsafeExposeInternals<K extends {}, V extends {}, FC extends unknown = unknown>(c: LRUCache<K, V, FC>): {
starts: ZeroArray | undefined;
ttls: ZeroArray | undefined;
sizes: ZeroArray | undefined;
keyMap: Map<K, number>;
keyList: (K | undefined)[];
valList: (V | BackgroundFetch<V> | undefined)[];
next: NumberArray;
prev: NumberArray;
readonly head: Index;
readonly tail: Index;
free: StackLike;
isBackgroundFetch: (p: any) => boolean;
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: any) => BackgroundFetch<V>;
moveToTail: (index: number) => void;
indexes: (options?: {
allowStale: boolean;
}) => Generator<Index, void, unknown>;
rindexes: (options?: {
allowStale: boolean;
}) => Generator<Index, void, unknown>;
isStale: (index: number | undefined) => boolean;
};
/**
* {@link LRUCache.OptionsBase.max} (read-only)
*/
get max(): LRUCache.Count;
/**
* {@link LRUCache.OptionsBase.maxSize} (read-only)
*/
get maxSize(): LRUCache.Count;
/**
* The total computed size of items in the cache (read-only)
*/
get calculatedSize(): LRUCache.Size;
/**
* The number of items stored in the cache (read-only)
*/
get size(): LRUCache.Count;
/**
* {@link LRUCache.OptionsBase.fetchMethod} (read-only)
*/
get fetchMethod(): LRUCache.Fetcher<K, V, FC> | undefined;
/**
* {@link LRUCache.OptionsBase.dispose} (read-only)
*/
get dispose(): LRUCache.Disposer<K, V> | undefined;
/**
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
*/
get disposeAfter(): LRUCache.Disposer<K, V> | undefined;
constructor(options: LRUCache.Options<K, V, FC> | LRUCache<K, V, FC>);
/**
* Return the remaining TTL time for a given entry key
*/
getRemainingTTL(key: K): number;
/**
* Return a generator yielding `[key, value]` pairs,
* in order from most recently used to least recently used.
*/
entries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Inverse order version of {@link LRUCache.entries}
*
* Return a generator yielding `[key, value]` pairs,
* in order from least recently used to most recently used.
*/
rentries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Return a generator yielding the keys in the cache,
* in order from most recently used to least recently used.
*/
keys(): Generator<K, void, unknown>;
/**
* Inverse order version of {@link LRUCache.keys}
*
* Return a generator yielding the keys in the cache,
* in order from least recently used to most recently used.
*/
rkeys(): Generator<K, void, unknown>;
/**
* Return a generator yielding the values in the cache,
* in order from most recently used to least recently used.
*/
values(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
/**
* Inverse order version of {@link LRUCache.values}
*
* Return a generator yielding the values in the cache,
* in order from least recently used to most recently used.
*/
rvalues(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
/**
* Iterating over the cache itself yields the same results as
* {@link LRUCache.entries}
*/
[Symbol.iterator](): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Find a value for which the supplied fn method returns a truthy value,
* similar to Array.find(). fn is called as fn(value, key, cache).
*/
find(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => boolean, getOptions?: LRUCache.GetOptions<K, V, FC>): V | undefined;
/**
* Call the supplied function on each item in the cache, in order from
* most recently used to least recently used. fn is called as
* fn(value, key, cache). Does not update age or recenty of use.
* Does not iterate over stale values.
*/
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
/**
* The same as {@link LRUCache.forEach} but items are iterated over in
* reverse order. (ie, less recently used items are iterated over first.)
*/
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
/**
* Delete any stale entries. Returns true if anything was removed,
* false otherwise.
*/
purgeStale(): boolean;
/**
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
* passed to cache.load()
*/
dump(): [K, LRUCache.Entry<V>][];
/**
* Reset the cache and load in the items in entries in the order listed.
* Note that the shape of the resulting cache may be different if the
* same options are not used in both caches.
*/
load(arr: [K, LRUCache.Entry<V>][]): void;
/**
* Add a value to the cache.
*/
set(k: K, v: V | BackgroundFetch<V>, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
/**
* Evict the least recently used item, returning its value or
* `undefined` if cache is empty.
*/
pop(): V | undefined;
/**
* Check if a key is in the cache, without updating the recency of use.
* Will return false if the item is stale, even though it is technically
* in the cache.
*
* Will not update item age unless
* {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
*/
has(k: K, hasOptions?: LRUCache.HasOptions<K, V, FC>): boolean;
/**
* Like {@link LRUCache#get} but doesn't update recency or delete stale
* items.
*
* Returns `undefined` if the item is stale, unless
* {@link LRUCache.OptionsBase.allowStale} is set.
*/
peek(k: K, peekOptions?: LRUCache.PeekOptions<K, V, FC>): V | undefined;
/**
* Make an asynchronous cached fetch using the
* {@link LRUCache.OptionsBase.fetchMethod} function.
*
* If multiple fetches for the same key are issued, then they will all be
* coalesced into a single call to fetchMethod.
*
* Note that this means that handling options such as
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort},
* {@link LRUCache.FetchOptions.signal},
* and {@link LRUCache.OptionsBase.allowStaleOnFetchRejection} will be
* determined by the FIRST fetch() call for a given key.
*
* This is a known (fixable) shortcoming which will be addresed on when
* someone complains about it, as the fix would involve added complexity and
* may not be worth the costs for this edge case.
*/
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<void | V>;
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<void | V>;
/**
* Return a value from the cache. Will update the recency of the cache
* entry found.
*
* If the key is not found, get() will return `undefined`.
*/
get(k: K, getOptions?: LRUCache.GetOptions<K, V, FC>): V | undefined;
/**
* Deletes a key out of the cache.
* Returns true if the key was deleted, false otherwise.
*/
delete(k: K): boolean;
/**
* Clear the cache entirely, throwing away all values.
*/
clear(): void;
}
export default LRUCache;
//# sourceMappingURL=index.d.ts.map

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 one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View File

@@ -0,0 +1,807 @@
/**
* @module LRUCache
*/
declare const TYPE: unique symbol;
type Index = number & {
[TYPE]: 'LRUCache Index';
};
type UintArray = Uint8Array | Uint16Array | Uint32Array;
type NumberArray = UintArray | number[];
declare class ZeroArray extends Array<number> {
constructor(size: number);
}
type StackLike = Stack | Index[];
declare class Stack {
#private;
heap: NumberArray;
length: number;
static create(max: number): StackLike;
constructor(max: number, HeapCls: {
new (n: number): NumberArray;
});
push(n: Index): void;
pop(): Index;
}
/**
* Promise representing an in-progress {@link LRUCache#fetch} call
*/
export type BackgroundFetch<V> = Promise<V | undefined | void> & {
__returned: BackgroundFetch<V> | undefined;
__abortController: AbortController;
__staleWhileFetching: V | undefined;
};
export declare namespace LRUCache {
/**
* An integer greater than 0, reflecting the calculated size of items
*/
type Size = number;
/**
* Integer greater than 0, representing some number of milliseconds, or the
* time at which a TTL started counting from.
*/
type Milliseconds = number;
/**
* An integer greater than 0, reflecting a number of items
*/
type Count = number;
/**
* The reason why an item was removed from the cache, passed
* to the {@link Disposer} methods.
*/
type DisposeReason = 'evict' | 'set' | 'delete';
/**
* A method called upon item removal, passed as the
* {@link OptionsBase.dispose} and/or
* {@link OptionsBase.disposeAfter} options.
*/
type Disposer<K, V> = (value: V, key: K, reason: DisposeReason) => void;
/**
* A function that returns the effective calculated size
* of an entry in the cache.
*/
type SizeCalculator<K, V> = (value: V, key: K) => Size;
/**
* Options provided to the
* {@link OptionsBase.fetchMethod} function.
*/
interface FetcherOptions<K, V, FC = unknown> {
signal: AbortSignal;
options: FetcherFetchOptions<K, V, FC>;
/**
* Object provided in the {@link FetchOptions.context} option to
* {@link LRUCache#fetch}
*/
context: FC;
}
/**
* Status object that may be passed to {@link LRUCache#fetch},
* {@link LRUCache#get}, {@link LRUCache#set}, and {@link LRUCache#has}.
*/
interface Status<V> {
/**
* The status of a set() operation.
*
* - add: the item was not found in the cache, and was added
* - update: the item was in the cache, with the same value provided
* - replace: the item was in the cache, and replaced
* - miss: the item was not added to the cache for some reason
*/
set?: 'add' | 'update' | 'replace' | 'miss';
/**
* the ttl stored for the item, or undefined if ttls are not used.
*/
ttl?: Milliseconds;
/**
* the start time for the item, or undefined if ttls are not used.
*/
start?: Milliseconds;
/**
* The timestamp used for TTL calculation
*/
now?: Milliseconds;
/**
* the remaining ttl for the item, or undefined if ttls are not used.
*/
remainingTTL?: Milliseconds;
/**
* The calculated size for the item, if sizes are used.
*/
entrySize?: Size;
/**
* The total calculated size of the cache, if sizes are used.
*/
totalCalculatedSize?: Size;
/**
* A flag indicating that the item was not stored, due to exceeding the
* {@link OptionsBase.maxEntrySize}
*/
maxEntrySizeExceeded?: true;
/**
* The old value, specified in the case of `set:'update'` or
* `set:'replace'`
*/
oldValue?: V;
/**
* The results of a {@link LRUCache#has} operation
*
* - hit: the item was found in the cache
* - stale: the item was found in the cache, but is stale
* - miss: the item was not found in the cache
*/
has?: 'hit' | 'stale' | 'miss';
/**
* The status of a {@link LRUCache#fetch} operation.
* Note that this can change as the underlying fetch() moves through
* various states.
*
* - inflight: there is another fetch() for this key which is in process
* - get: there is no fetchMethod, so {@link LRUCache#get} was called.
* - miss: the item is not in cache, and will be fetched.
* - hit: the item is in the cache, and was resolved immediately.
* - stale: the item is in the cache, but stale.
* - refresh: the item is in the cache, and not stale, but
* {@link FetchOptions.forceRefresh} was specified.
*/
fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh';
/**
* The {@link OptionsBase.fetchMethod} was called
*/
fetchDispatched?: true;
/**
* The cached value was updated after a successful call to
* {@link OptionsBase.fetchMethod}
*/
fetchUpdated?: true;
/**
* The reason for a fetch() rejection. Either the error raised by the
* {@link OptionsBase.fetchMethod}, or the reason for an
* AbortSignal.
*/
fetchError?: Error;
/**
* The fetch received an abort signal
*/
fetchAborted?: true;
/**
* The abort signal received was ignored, and the fetch was allowed to
* continue.
*/
fetchAbortIgnored?: true;
/**
* The fetchMethod promise resolved successfully
*/
fetchResolved?: true;
/**
* The fetchMethod promise was rejected
*/
fetchRejected?: true;
/**
* The status of a {@link LRUCache#get} operation.
*
* - fetching: The item is currently being fetched. If a previous value
* is present and allowed, that will be returned.
* - stale: The item is in the cache, and is stale.
* - hit: the item is in the cache
* - miss: the item is not in the cache
*/
get?: 'stale' | 'hit' | 'miss';
/**
* A fetch or get operation returned a stale value.
*/
returnedStale?: true;
}
/**
* options which override the options set in the LRUCache constructor
* when calling {@link LRUCache#fetch}.
*
* This is the union of {@link GetOptions} and {@link SetOptions}, plus
* {@link OptionsBase.noDeleteOnFetchRejection},
* {@link OptionsBase.allowStaleOnFetchRejection},
* {@link FetchOptions.forceRefresh}, and
* {@link OptionsBase.context}
*
* Any of these may be modified in the {@link OptionsBase.fetchMethod}
* function, but the {@link GetOptions} fields will of course have no
* effect, as the {@link LRUCache#get} call already happened by the time
* the fetchMethod is called.
*/
interface FetcherFetchOptions<K, V, FC = unknown> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet' | 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL' | 'noDeleteOnFetchRejection' | 'allowStaleOnFetchRejection' | 'ignoreFetchAbort' | 'allowStaleOnFetchAbort'> {
status?: Status<V>;
size?: Size;
}
/**
* Options that may be passed to the {@link LRUCache#fetch} method.
*/
interface FetchOptions<K, V, FC> extends FetcherFetchOptions<K, V, FC> {
/**
* Set to true to force a re-load of the existing data, even if it
* is not yet stale.
*/
forceRefresh?: boolean;
/**
* Context provided to the {@link OptionsBase.fetchMethod} as
* the {@link FetcherOptions.context} param.
*
* If the FC type is specified as unknown (the default),
* undefined or void, then this is optional. Otherwise, it will
* be required.
*/
context?: FC;
signal?: AbortSignal;
status?: Status<V>;
}
/**
* Options provided to {@link LRUCache#fetch} when the FC type is something
* other than `unknown`, `undefined`, or `void`
*/
interface FetchOptionsWithContext<K, V, FC> extends FetchOptions<K, V, FC> {
context: FC;
}
/**
* Options provided to {@link LRUCache#fetch} when the FC type is
* `undefined` or `void`
*/
interface FetchOptionsNoContext<K, V, FC> extends FetchOptions<K, V, FC> {
context?: undefined;
}
/**
* Options that may be passed to the {@link LRUCache#has} method.
*/
interface HasOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {
status?: Status<V>;
}
/**
* Options that may be passed to the {@link LRUCache#get} method.
*/
interface GetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'> {
status?: Status<V>;
}
/**
* Options that may be passed to the {@link LRUCache#peek} method.
*/
interface PeekOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {
}
/**
* Options that may be passed to the {@link LRUCache#set} method.
*/
interface SetOptions<K, V, FC> extends Pick<OptionsBase<K, V, FC>, 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'> {
/**
* If size tracking is enabled, then setting an explicit size
* in the {@link LRUCache#set} call will prevent calling the
* {@link OptionsBase.sizeCalculation} function.
*/
size?: Size;
/**
* If TTL tracking is enabled, then setting an explicit start
* time in the {@link LRUCache#set} call will override the
* default time from `performance.now()` or `Date.now()`.
*
* Note that it must be a valid value for whichever time-tracking
* method is in use.
*/
start?: Milliseconds;
status?: Status<V>;
}
/**
* The type signature for the {@link OptionsBase.fetchMethod} option.
*/
type Fetcher<K, V, FC = unknown> = (key: K, staleValue: V | undefined, options: FetcherOptions<K, V, FC>) => Promise<V | void | undefined> | V | void | undefined;
/**
* Options which may be passed to the {@link LRUCache} constructor.
*
* Most of these may be overridden in the various options that use
* them.
*
* Despite all being technically optional, the constructor requires that
* a cache is at minimum limited by one or more of {@link OptionsBase.max},
* {@link OptionsBase.ttl}, or {@link OptionsBase.maxSize}.
*
* If {@link OptionsBase.ttl} is used alone, then it is strongly advised
* (and in fact required by the type definitions here) that the cache
* also set {@link OptionsBase.ttlAutopurge}, to prevent potentially
* unbounded storage.
*/
interface OptionsBase<K, V, FC> {
/**
* The maximum number of items to store in the cache before evicting
* old entries. This is read-only on the {@link LRUCache} instance,
* and may not be overridden.
*
* If set, then storage space will be pre-allocated at construction
* time, and the cache will perform significantly faster.
*
* Note that significantly fewer items may be stored, if
* {@link OptionsBase.maxSize} and/or {@link OptionsBase.ttl} are also
* set.
*/
max?: Count;
/**
* Max time in milliseconds for items to live in cache before they are
* considered stale. Note that stale items are NOT preemptively removed
* by default, and MAY live in the cache long after they have expired.
*
* Also, as this cache is optimized for LRU/MRU operations, some of
* the staleness/TTL checks will reduce performance, as they will incur
* overhead by deleting items.
*
* Must be an integer number of ms. If set to 0, this indicates "no TTL"
*
* @default 0
*/
ttl?: Milliseconds;
/**
* Minimum amount of time in ms in which to check for staleness.
* Defaults to 1, which means that the current time is checked
* at most once per millisecond.
*
* Set to 0 to check the current time every time staleness is tested.
* (This reduces performance, and is theoretically unnecessary.)
*
* Setting this to a higher value will improve performance somewhat
* while using ttl tracking, albeit at the expense of keeping stale
* items around a bit longer than their TTLs would indicate.
*
* @default 1
*/
ttlResolution?: Milliseconds;
/**
* Preemptively remove stale items from the cache.
* Note that this may significantly degrade performance,
* especially if the cache is storing a large number of items.
* It is almost always best to just leave the stale items in
* the cache, and let them fall out as new items are added.
*
* Note that this means that {@link OptionsBase.allowStale} is a bit
* pointless, as stale items will be deleted almost as soon as they
* expire.
*
* @default false
*/
ttlAutopurge?: boolean;
/**
* Update the age of items on {@link LRUCache#get}, renewing their TTL
*
* Has no effect if {@link OptionsBase.ttl} is not set.
*
* @default false
*/
updateAgeOnGet?: boolean;
/**
* Update the age of items on {@link LRUCache#has}, renewing their TTL
*
* Has no effect if {@link OptionsBase.ttl} is not set.
*
* @default false
*/
updateAgeOnHas?: boolean;
/**
* Allow {@link LRUCache#get} and {@link LRUCache#fetch} calls to return
* stale data, if available.
*/
allowStale?: boolean;
/**
* Function that is called on items when they are dropped from the cache.
* This can be handy if you want to close file descriptors or do other
* cleanup tasks when items are no longer accessible. Called with `key,
* value`. It's called before actually removing the item from the
* internal cache, so it is *NOT* safe to re-add them.
*
* Use {@link OptionsBase.disposeAfter} if you wish to dispose items after
* they have been full removed, when it is safe to add them back to the
* cache.
*/
dispose?: Disposer<K, V>;
/**
* The same as {@link OptionsBase.dispose}, but called *after* the entry
* is completely removed and the cache is once again in a clean state.
* It is safe to add an item right back into the cache at this point.
* However, note that it is *very* easy to inadvertently create infinite
* recursion this way.
*/
disposeAfter?: Disposer<K, V>;
/**
* Set to true to suppress calling the
* {@link OptionsBase.dispose} function if the entry key is
* still accessible within the cache.
* This may be overridden by passing an options object to
* {@link LRUCache#set}.
*/
noDisposeOnSet?: boolean;
/**
* Boolean flag to tell the cache to not update the TTL when
* setting a new value for an existing key (ie, when updating a value
* rather than inserting a new value). Note that the TTL value is
* _always_ set (if provided) when adding a new entry into the cache.
*
* Has no effect if a {@link OptionsBase.ttl} is not set.
*/
noUpdateTTL?: boolean;
/**
* If you wish to track item size, you must provide a maxSize
* note that we still will only keep up to max *actual items*,
* if max is set, so size tracking may cause fewer than max items
* to be stored. At the extreme, a single item of maxSize size
* will cause everything else in the cache to be dropped when it
* is added. Use with caution!
*
* Note also that size tracking can negatively impact performance,
* though for most cases, only minimally.
*/
maxSize?: Size;
/**
* The maximum allowed size for any single item in the cache.
*
* If a larger item is passed to {@link LRUCache#set} or returned by a
* {@link OptionsBase.fetchMethod}, then it will not be stored in the
* cache.
*/
maxEntrySize?: Size;
/**
* A function that returns a number indicating the item's size.
*
* If not provided, and {@link OptionsBase.maxSize} or
* {@link OptionsBase.maxEntrySize} are set, then all
* {@link LRUCache#set} calls **must** provide an explicit
* {@link SetOptions.size} or sizeCalculation param.
*/
sizeCalculation?: SizeCalculator<K, V>;
/**
* Method that provides the implementation for {@link LRUCache#fetch}
*/
fetchMethod?: Fetcher<K, V, FC>;
/**
* Set to true to suppress the deletion of stale data when a
* {@link OptionsBase.fetchMethod} returns a rejected promise.
*/
noDeleteOnFetchRejection?: boolean;
/**
* Do not delete stale items when they are retrieved with
* {@link LRUCache#get}.
*
* Note that the `get` return value will still be `undefined`
* unless {@link OptionsBase.allowStale} is true.
*/
noDeleteOnStaleGet?: boolean;
/**
* Set to true to allow returning stale data when a
* {@link OptionsBase.fetchMethod} throws an error or returns a rejected
* promise.
*
* This differs from using {@link OptionsBase.allowStale} in that stale
* data will ONLY be returned in the case that the
* {@link LRUCache#fetch} fails, not any other times.
*/
allowStaleOnFetchRejection?: boolean;
/**
* Set to true to return a stale value from the cache when the
* `AbortSignal` passed to the {@link OptionsBase.fetchMethod} dispatches an `'abort'`
* event, whether user-triggered, or due to internal cache behavior.
*
* Unless {@link OptionsBase.ignoreFetchAbort} is also set, the underlying
* {@link OptionsBase.fetchMethod} will still be considered canceled, and its return
* value will be ignored and not cached.
*/
allowStaleOnFetchAbort?: boolean;
/**
* Set to true to ignore the `abort` event emitted by the `AbortSignal`
* object passed to {@link OptionsBase.fetchMethod}, and still cache the
* resulting resolution value, as long as it is not `undefined`.
*
* When used on its own, this means aborted {@link LRUCache#fetch} calls are not
* immediately resolved or rejected when they are aborted, and instead
* take the full time to await.
*
* When used with {@link OptionsBase.allowStaleOnFetchAbort}, aborted
* {@link LRUCache#fetch} calls will resolve immediately to their stale
* cached value or `undefined`, and will continue to process and eventually
* update the cache when they resolve, as long as the resulting value is
* not `undefined`, thus supporting a "return stale on timeout while
* refreshing" mechanism by passing `AbortSignal.timeout(n)` as the signal.
*
* **Note**: regardless of this setting, an `abort` event _is still
* emitted on the `AbortSignal` object_, so may result in invalid results
* when passed to other underlying APIs that use AbortSignals.
*
* This may be overridden in the {@link OptionsBase.fetchMethod} or the
* call to {@link LRUCache#fetch}.
*/
ignoreFetchAbort?: boolean;
}
interface OptionsMaxLimit<K, V, FC> extends OptionsBase<K, V, FC> {
max: Count;
}
interface OptionsTTLLimit<K, V, FC> extends OptionsBase<K, V, FC> {
ttl: Milliseconds;
ttlAutopurge: boolean;
}
interface OptionsSizeLimit<K, V, FC> extends OptionsBase<K, V, FC> {
maxSize: Size;
}
/**
* The valid safe options for the {@link LRUCache} constructor
*/
type Options<K, V, FC> = OptionsMaxLimit<K, V, FC> | OptionsSizeLimit<K, V, FC> | OptionsTTLLimit<K, V, FC>;
/**
* Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump}
*/
interface Entry<V> {
value: V;
ttl?: Milliseconds;
size?: Size;
start?: Milliseconds;
}
}
/**
* Default export, the thing you're using this module to get.
*
* All properties from the options object (with the exception of
* {@link OptionsBase.max} and {@link OptionsBase.maxSize}) are added as
* normal public members. (`max` and `maxBase` are read-only getters.)
* Changing any of these will alter the defaults for subsequent method calls,
* but is otherwise safe.
*/
export declare class LRUCache<K extends {}, V extends {}, FC = unknown> {
#private;
/**
* {@link LRUCache.OptionsBase.ttl}
*/
ttl: LRUCache.Milliseconds;
/**
* {@link LRUCache.OptionsBase.ttlResolution}
*/
ttlResolution: LRUCache.Milliseconds;
/**
* {@link LRUCache.OptionsBase.ttlAutopurge}
*/
ttlAutopurge: boolean;
/**
* {@link LRUCache.OptionsBase.updateAgeOnGet}
*/
updateAgeOnGet: boolean;
/**
* {@link LRUCache.OptionsBase.updateAgeOnHas}
*/
updateAgeOnHas: boolean;
/**
* {@link LRUCache.OptionsBase.allowStale}
*/
allowStale: boolean;
/**
* {@link LRUCache.OptionsBase.noDisposeOnSet}
*/
noDisposeOnSet: boolean;
/**
* {@link LRUCache.OptionsBase.noUpdateTTL}
*/
noUpdateTTL: boolean;
/**
* {@link LRUCache.OptionsBase.maxEntrySize}
*/
maxEntrySize: LRUCache.Size;
/**
* {@link LRUCache.OptionsBase.sizeCalculation}
*/
sizeCalculation?: LRUCache.SizeCalculator<K, V>;
/**
* {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
*/
noDeleteOnFetchRejection: boolean;
/**
* {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
*/
noDeleteOnStaleGet: boolean;
/**
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
*/
allowStaleOnFetchAbort: boolean;
/**
* {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
*/
allowStaleOnFetchRejection: boolean;
/**
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
*/
ignoreFetchAbort: boolean;
/**
* Do not call this method unless you need to inspect the
* inner workings of the cache. If anything returned by this
* object is modified in any way, strange breakage may occur.
*
* These fields are private for a reason!
*
* @internal
*/
static unsafeExposeInternals<K extends {}, V extends {}, FC extends unknown = unknown>(c: LRUCache<K, V, FC>): {
starts: ZeroArray | undefined;
ttls: ZeroArray | undefined;
sizes: ZeroArray | undefined;
keyMap: Map<K, number>;
keyList: (K | undefined)[];
valList: (V | BackgroundFetch<V> | undefined)[];
next: NumberArray;
prev: NumberArray;
readonly head: Index;
readonly tail: Index;
free: StackLike;
isBackgroundFetch: (p: any) => boolean;
backgroundFetch: (k: K, index: number | undefined, options: LRUCache.FetchOptions<K, V, FC>, context: any) => BackgroundFetch<V>;
moveToTail: (index: number) => void;
indexes: (options?: {
allowStale: boolean;
}) => Generator<Index, void, unknown>;
rindexes: (options?: {
allowStale: boolean;
}) => Generator<Index, void, unknown>;
isStale: (index: number | undefined) => boolean;
};
/**
* {@link LRUCache.OptionsBase.max} (read-only)
*/
get max(): LRUCache.Count;
/**
* {@link LRUCache.OptionsBase.maxSize} (read-only)
*/
get maxSize(): LRUCache.Count;
/**
* The total computed size of items in the cache (read-only)
*/
get calculatedSize(): LRUCache.Size;
/**
* The number of items stored in the cache (read-only)
*/
get size(): LRUCache.Count;
/**
* {@link LRUCache.OptionsBase.fetchMethod} (read-only)
*/
get fetchMethod(): LRUCache.Fetcher<K, V, FC> | undefined;
/**
* {@link LRUCache.OptionsBase.dispose} (read-only)
*/
get dispose(): LRUCache.Disposer<K, V> | undefined;
/**
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
*/
get disposeAfter(): LRUCache.Disposer<K, V> | undefined;
constructor(options: LRUCache.Options<K, V, FC> | LRUCache<K, V, FC>);
/**
* Return the remaining TTL time for a given entry key
*/
getRemainingTTL(key: K): number;
/**
* Return a generator yielding `[key, value]` pairs,
* in order from most recently used to least recently used.
*/
entries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Inverse order version of {@link LRUCache.entries}
*
* Return a generator yielding `[key, value]` pairs,
* in order from least recently used to most recently used.
*/
rentries(): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Return a generator yielding the keys in the cache,
* in order from most recently used to least recently used.
*/
keys(): Generator<K, void, unknown>;
/**
* Inverse order version of {@link LRUCache.keys}
*
* Return a generator yielding the keys in the cache,
* in order from least recently used to most recently used.
*/
rkeys(): Generator<K, void, unknown>;
/**
* Return a generator yielding the values in the cache,
* in order from most recently used to least recently used.
*/
values(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
/**
* Inverse order version of {@link LRUCache.values}
*
* Return a generator yielding the values in the cache,
* in order from least recently used to most recently used.
*/
rvalues(): Generator<V | BackgroundFetch<V> | undefined, void, unknown>;
/**
* Iterating over the cache itself yields the same results as
* {@link LRUCache.entries}
*/
[Symbol.iterator](): Generator<(K | V | BackgroundFetch<V> | undefined)[], void, unknown>;
/**
* Find a value for which the supplied fn method returns a truthy value,
* similar to Array.find(). fn is called as fn(value, key, cache).
*/
find(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => boolean, getOptions?: LRUCache.GetOptions<K, V, FC>): V | undefined;
/**
* Call the supplied function on each item in the cache, in order from
* most recently used to least recently used. fn is called as
* fn(value, key, cache). Does not update age or recenty of use.
* Does not iterate over stale values.
*/
forEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
/**
* The same as {@link LRUCache.forEach} but items are iterated over in
* reverse order. (ie, less recently used items are iterated over first.)
*/
rforEach(fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any, thisp?: any): void;
/**
* Delete any stale entries. Returns true if anything was removed,
* false otherwise.
*/
purgeStale(): boolean;
/**
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
* passed to cache.load()
*/
dump(): [K, LRUCache.Entry<V>][];
/**
* Reset the cache and load in the items in entries in the order listed.
* Note that the shape of the resulting cache may be different if the
* same options are not used in both caches.
*/
load(arr: [K, LRUCache.Entry<V>][]): void;
/**
* Add a value to the cache.
*/
set(k: K, v: V | BackgroundFetch<V>, setOptions?: LRUCache.SetOptions<K, V, FC>): this;
/**
* Evict the least recently used item, returning its value or
* `undefined` if cache is empty.
*/
pop(): V | undefined;
/**
* Check if a key is in the cache, without updating the recency of use.
* Will return false if the item is stale, even though it is technically
* in the cache.
*
* Will not update item age unless
* {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
*/
has(k: K, hasOptions?: LRUCache.HasOptions<K, V, FC>): boolean;
/**
* Like {@link LRUCache#get} but doesn't update recency or delete stale
* items.
*
* Returns `undefined` if the item is stale, unless
* {@link LRUCache.OptionsBase.allowStale} is set.
*/
peek(k: K, peekOptions?: LRUCache.PeekOptions<K, V, FC>): V | undefined;
/**
* Make an asynchronous cached fetch using the
* {@link LRUCache.OptionsBase.fetchMethod} function.
*
* If multiple fetches for the same key are issued, then they will all be
* coalesced into a single call to fetchMethod.
*
* Note that this means that handling options such as
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort},
* {@link LRUCache.FetchOptions.signal},
* and {@link LRUCache.OptionsBase.allowStaleOnFetchRejection} will be
* determined by the FIRST fetch() call for a given key.
*
* This is a known (fixable) shortcoming which will be addresed on when
* someone complains about it, as the fix would involve added complexity and
* may not be worth the costs for this edge case.
*/
fetch(k: K, fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : LRUCache.FetchOptionsWithContext<K, V, FC>): Promise<void | V>;
fetch(k: unknown extends FC ? K : FC extends undefined | void ? K : never, fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC> : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V, FC> : never): Promise<void | V>;
/**
* Return a value from the cache. Will update the recency of the cache
* entry found.
*
* If the key is not found, get() will return `undefined`.
*/
get(k: K, getOptions?: LRUCache.GetOptions<K, V, FC>): V | undefined;
/**
* Deletes a key out of the cache.
* Returns true if the key was deleted, false otherwise.
*/
delete(k: K): boolean;
/**
* Clear the cache entirely, throwing away all values.
*/
clear(): void;
}
export default LRUCache;
//# sourceMappingURL=index.d.ts.map

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 one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
{
"type": "module"
}

110
node_modules/mysql2/node_modules/lru-cache/package.json generated vendored Normal file
View File

@@ -0,0 +1,110 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
"version": "8.0.5",
"author": "Isaac Z. Schlueter <i@izs.me>",
"keywords": [
"mru",
"lru",
"cache"
],
"sideEffects": false,
"scripts": {
"build": "npm run prepare",
"preprepare": "rm -rf dist",
"prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json",
"postprepare": "bash fixup.sh",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "c8 tap",
"snap": "c8 tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"format": "prettier --write .",
"typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts",
"benchmark-results-typedoc": "bash scripts/benchmark-results-typedoc.sh",
"prebenchmark": "npm run prepare",
"benchmark": "make -C benchmark",
"preprofile": "npm run prepare",
"profile": "make -C benchmark profile"
},
"main": "./dist/cjs/index-cjs.js",
"module": "./dist/mjs/index.js",
"types": "./dist/mjs/index.d.ts",
"exports": {
"./min": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.min.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.min.js"
}
},
".": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index-cjs.js"
}
}
},
"repository": "git://github.com/isaacs/node-lru-cache.git",
"devDependencies": {
"@size-limit/preset-small-lib": "^7.0.8",
"@types/node": "^17.0.31",
"@types/tap": "^15.0.6",
"benchmark": "^2.1.4",
"c8": "^7.11.2",
"clock-mock": "^1.0.6",
"esbuild": "^0.17.11",
"eslint-config-prettier": "^8.5.0",
"marked": "^4.2.12",
"mkdirp": "^2.1.5",
"prettier": "^2.6.2",
"size-limit": "^7.0.8",
"tap": "^16.3.4",
"ts-node": "^10.7.0",
"tslib": "^2.4.0",
"typedoc": "^0.23.24",
"typescript": "^4.6.4"
},
"license": "ISC",
"files": [
"dist"
],
"engines": {
"node": ">=16.14"
},
"prettier": {
"semi": false,
"printWidth": 70,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"tap": {
"coverage": false,
"node-arg": [
"--expose-gc",
"--no-warnings",
"--loader",
"ts-node/esm"
],
"ts": false
},
"size-limit": [
{
"path": "./dist/mjs/index.js"
}
]
}

53
node_modules/mysql2/node_modules/sqlstring/HISTORY.md generated vendored Normal file
View File

@@ -0,0 +1,53 @@
2.3.3 / 2022-03-06
==================
* Fix escaping `Date` objects from foreign isolates
2.3.2 / 2020-04-15
==================
* perf: remove outdated array pattern
2.3.1 / 2018-02-24
==================
* Fix incorrectly replacing non-placeholders in SQL
2.3.0 / 2017-10-01
==================
* Add `.toSqlString()` escape overriding
* Add `raw` method to wrap raw strings for escape overriding
* Small performance improvement on `escapeId`
2.2.0 / 2016-11-01
==================
* Escape invalid `Date` objects as `NULL`
2.1.0 / 2016-09-26
==================
* Accept numbers and other value types in `escapeId`
* Run `buffer.toString()` through escaping
2.0.1 / 2016-06-06
==================
* Fix npm package to include missing `lib/` directory
2.0.0 / 2016-06-06
==================
* Bring repository up-to-date with `mysql` module changes
* Support Node.js 0.6.x
1.0.0 / 2014-11-09
==================
* Support Node.js 0.8.x
0.0.1 / 2014-02-25
==================
* Initial release

19
node_modules/mysql2/node_modules/sqlstring/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.

205
node_modules/mysql2/node_modules/sqlstring/README.md generated vendored Normal file
View File

@@ -0,0 +1,205 @@
# sqlstring
[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-image]][node-url]
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
[![Coverage Status][coveralls-image]][coveralls-url]
Simple SQL escape and format for MySQL
## Install
```sh
$ npm install sqlstring
```
## Usage
```js
var SqlString = require('sqlstring');
```
### Escaping query values
**Caution** These methods of escaping values only works when the
[NO_BACKSLASH_ESCAPES](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_backslash_escapes)
SQL mode is disabled (which is the default state for MySQL servers).
In order to avoid SQL Injection attacks, you should always escape any user
provided data before using it inside a SQL query. You can do so using the
`SqlString.escape()` method:
```js
var userId = 'some user provided value';
var sql = 'SELECT * FROM users WHERE id = ' + SqlString.escape(userId);
console.log(sql); // SELECT * FROM users WHERE id = 'some user provided value'
```
Alternatively, you can use `?` characters as placeholders for values you would
like to have escaped like this:
```js
var userId = 1;
var sql = SqlString.format('SELECT * FROM users WHERE id = ?', [userId]);
console.log(sql); // SELECT * FROM users WHERE id = 1
```
Multiple placeholders are mapped to values in the same order as passed. For example,
in the following query `foo` equals `a`, `bar` equals `b`, `baz` equals `c`, and
`id` will be `userId`:
```js
var userId = 1;
var sql = SqlString.format('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?',
['a', 'b', 'c', userId]);
console.log(sql); // UPDATE users SET foo = 'a', bar = 'b', baz = 'c' WHERE id = 1
```
This looks similar to prepared statements in MySQL, however it really just uses
the same `SqlString.escape()` method internally.
**Caution** This also differs from prepared statements in that all `?` are
replaced, even those contained in comments and strings.
Different value types are escaped differently, here is how:
* Numbers are left untouched
* Booleans are converted to `true` / `false`
* Date objects are converted to `'YYYY-mm-dd HH:ii:ss'` strings
* Buffers are converted to hex strings, e.g. `X'0fa5'`
* Strings are safely escaped
* Arrays are turned into list, e.g. `['a', 'b']` turns into `'a', 'b'`
* Nested arrays are turned into grouped lists (for bulk inserts), e.g. `[['a',
'b'], ['c', 'd']]` turns into `('a', 'b'), ('c', 'd')`
* Objects that have a `toSqlString` method will have `.toSqlString()` called
and the returned value is used as the raw SQL.
* Objects are turned into `key = 'val'` pairs for each enumerable property on
the object. If the property's value is a function, it is skipped; if the
property's value is an object, toString() is called on it and the returned
value is used.
* `undefined` / `null` are converted to `NULL`
* `NaN` / `Infinity` are left as-is. MySQL does not support these, and trying
to insert them as values will trigger MySQL errors until they implement
support.
You may have noticed that this escaping allows you to do neat things like this:
```js
var post = {id: 1, title: 'Hello MySQL'};
var sql = SqlString.format('INSERT INTO posts SET ?', post);
console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
```
And the `toSqlString` method allows you to form complex queries with functions:
```js
var CURRENT_TIMESTAMP = { toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } };
var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42
```
To generate objects with a `toSqlString` method, the `SqlString.raw()` method can
be used. This creates an object that will be left un-touched when using in a `?`
placeholder, useful for using functions as dynamic values:
**Caution** The string provided to `SqlString.raw()` will skip all escaping
functions when used, so be careful when passing in unvalidated input.
```js
var CURRENT_TIMESTAMP = SqlString.raw('CURRENT_TIMESTAMP()');
var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42
```
If you feel the need to escape queries by yourself, you can also use the escaping
function directly:
```js
var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape('Hello MySQL');
console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL'
```
### Escaping query identifiers
If you can't trust an SQL identifier (database / table / column name) because it is
provided by a user, you should escape it with `SqlString.escapeId(identifier)` like this:
```js
var sorter = 'date';
var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter);
console.log(sql); // SELECT * FROM posts ORDER BY `date`
```
It also supports adding qualified identifiers. It will escape both parts.
```js
var sorter = 'date';
var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId('posts.' + sorter);
console.log(sql); // SELECT * FROM posts ORDER BY `posts`.`date`
```
If you do not want to treat `.` as qualified identifiers, you can set the second
argument to `true` in order to keep the string as a literal identifier:
```js
var sorter = 'date.2';
var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter, true);
console.log(sql); // SELECT * FROM posts ORDER BY `date.2`
```
Alternatively, you can use `??` characters as placeholders for identifiers you would
like to have escaped like this:
```js
var userId = 1;
var columns = ['username', 'email'];
var sql = SqlString.format('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId]);
console.log(sql); // SELECT `username`, `email` FROM `users` WHERE id = 1
```
**Please note that this last character sequence is experimental and syntax might change**
When you pass an Object to `.escape()` or `.format()`, `.escapeId()` is used to avoid SQL injection in object keys.
### Formatting queries
You can use `SqlString.format` to prepare a query with multiple insertion points,
utilizing the proper escaping for ids and values. A simple example of this follows:
```js
var userId = 1;
var inserts = ['users', 'id', userId];
var sql = SqlString.format('SELECT * FROM ?? WHERE ?? = ?', inserts);
console.log(sql); // SELECT * FROM `users` WHERE `id` = 1
```
Following this you then have a valid, escaped query that you can then send to the database safely.
This is useful if you are looking to prepare the query before actually sending it to the database.
You also have the option (but are not required) to pass in `stringifyObject` and `timeZone`,
allowing you provide a custom means of turning objects into strings, as well as a
location-specific/timezone-aware `Date`.
This can be further combined with the `SqlString.raw()` helper to generate SQL
that includes MySQL functions as dynamic vales:
```js
var userId = 1;
var data = { email: 'foobar@example.com', modified: SqlString.raw('NOW()') };
var sql = SqlString.format('UPDATE ?? SET ? WHERE `id` = ?', ['users', data, userId]);
console.log(sql); // UPDATE `users` SET `email` = 'foobar@example.com', `modified` = NOW() WHERE `id` = 1
```
## License
[MIT](LICENSE)
[npm-version-image]: https://img.shields.io/npm/v/sqlstring.svg
[npm-downloads-image]: https://img.shields.io/npm/dm/sqlstring.svg
[npm-url]: https://npmjs.org/package/sqlstring
[coveralls-image]: https://img.shields.io/coveralls/mysqljs/sqlstring/master.svg
[coveralls-url]: https://coveralls.io/r/mysqljs/sqlstring?branch=master
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/mysqljs/sqlstring/ci/master?label=build
[github-actions-ci-url]: https://github.com/mysqljs/sqlstring/actions/workflows/ci.yml
[node-image]: https://img.shields.io/node/v/sqlstring.svg
[node-url]: https://nodejs.org/en/download

1
node_modules/mysql2/node_modules/sqlstring/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/SqlString');

View File

@@ -0,0 +1,237 @@
var SqlString = exports;
var ID_GLOBAL_REGEXP = /`/g;
var QUAL_GLOBAL_REGEXP = /\./g;
var CHARS_GLOBAL_REGEXP = /[\0\b\t\n\r\x1a\"\'\\]/g; // eslint-disable-line no-control-regex
var CHARS_ESCAPE_MAP = {
'\0' : '\\0',
'\b' : '\\b',
'\t' : '\\t',
'\n' : '\\n',
'\r' : '\\r',
'\x1a' : '\\Z',
'"' : '\\"',
'\'' : '\\\'',
'\\' : '\\\\'
};
SqlString.escapeId = function escapeId(val, forbidQualified) {
if (Array.isArray(val)) {
var sql = '';
for (var i = 0; i < val.length; i++) {
sql += (i === 0 ? '' : ', ') + SqlString.escapeId(val[i], forbidQualified);
}
return sql;
} else if (forbidQualified) {
return '`' + String(val).replace(ID_GLOBAL_REGEXP, '``') + '`';
} else {
return '`' + String(val).replace(ID_GLOBAL_REGEXP, '``').replace(QUAL_GLOBAL_REGEXP, '`.`') + '`';
}
};
SqlString.escape = function escape(val, stringifyObjects, timeZone) {
if (val === undefined || val === null) {
return 'NULL';
}
switch (typeof val) {
case 'boolean': return (val) ? 'true' : 'false';
case 'number': return val + '';
case 'object':
if (Object.prototype.toString.call(val) === '[object Date]') {
return SqlString.dateToString(val, timeZone || 'local');
} else if (Array.isArray(val)) {
return SqlString.arrayToList(val, timeZone);
} else if (Buffer.isBuffer(val)) {
return SqlString.bufferToString(val);
} else if (typeof val.toSqlString === 'function') {
return String(val.toSqlString());
} else if (stringifyObjects) {
return escapeString(val.toString());
} else {
return SqlString.objectToValues(val, timeZone);
}
default: return escapeString(val);
}
};
SqlString.arrayToList = function arrayToList(array, timeZone) {
var sql = '';
for (var i = 0; i < array.length; i++) {
var val = array[i];
if (Array.isArray(val)) {
sql += (i === 0 ? '' : ', ') + '(' + SqlString.arrayToList(val, timeZone) + ')';
} else {
sql += (i === 0 ? '' : ', ') + SqlString.escape(val, true, timeZone);
}
}
return sql;
};
SqlString.format = function format(sql, values, stringifyObjects, timeZone) {
if (values == null) {
return sql;
}
if (!Array.isArray(values)) {
values = [values];
}
var chunkIndex = 0;
var placeholdersRegex = /\?+/g;
var result = '';
var valuesIndex = 0;
var match;
while (valuesIndex < values.length && (match = placeholdersRegex.exec(sql))) {
var len = match[0].length;
if (len > 2) {
continue;
}
var value = len === 2
? SqlString.escapeId(values[valuesIndex])
: SqlString.escape(values[valuesIndex], stringifyObjects, timeZone);
result += sql.slice(chunkIndex, match.index) + value;
chunkIndex = placeholdersRegex.lastIndex;
valuesIndex++;
}
if (chunkIndex === 0) {
// Nothing was replaced
return sql;
}
if (chunkIndex < sql.length) {
return result + sql.slice(chunkIndex);
}
return result;
};
SqlString.dateToString = function dateToString(date, timeZone) {
var dt = new Date(date);
if (isNaN(dt.getTime())) {
return 'NULL';
}
var year;
var month;
var day;
var hour;
var minute;
var second;
var millisecond;
if (timeZone === 'local') {
year = dt.getFullYear();
month = dt.getMonth() + 1;
day = dt.getDate();
hour = dt.getHours();
minute = dt.getMinutes();
second = dt.getSeconds();
millisecond = dt.getMilliseconds();
} else {
var tz = convertTimezone(timeZone);
if (tz !== false && tz !== 0) {
dt.setTime(dt.getTime() + (tz * 60000));
}
year = dt.getUTCFullYear();
month = dt.getUTCMonth() + 1;
day = dt.getUTCDate();
hour = dt.getUTCHours();
minute = dt.getUTCMinutes();
second = dt.getUTCSeconds();
millisecond = dt.getUTCMilliseconds();
}
// YYYY-MM-DD HH:mm:ss.mmm
var str = zeroPad(year, 4) + '-' + zeroPad(month, 2) + '-' + zeroPad(day, 2) + ' ' +
zeroPad(hour, 2) + ':' + zeroPad(minute, 2) + ':' + zeroPad(second, 2) + '.' +
zeroPad(millisecond, 3);
return escapeString(str);
};
SqlString.bufferToString = function bufferToString(buffer) {
return 'X' + escapeString(buffer.toString('hex'));
};
SqlString.objectToValues = function objectToValues(object, timeZone) {
var sql = '';
for (var key in object) {
var val = object[key];
if (typeof val === 'function') {
continue;
}
sql += (sql.length === 0 ? '' : ', ') + SqlString.escapeId(key) + ' = ' + SqlString.escape(val, true, timeZone);
}
return sql;
};
SqlString.raw = function raw(sql) {
if (typeof sql !== 'string') {
throw new TypeError('argument sql must be a string');
}
return {
toSqlString: function toSqlString() { return sql; }
};
};
function escapeString(val) {
var chunkIndex = CHARS_GLOBAL_REGEXP.lastIndex = 0;
var escapedVal = '';
var match;
while ((match = CHARS_GLOBAL_REGEXP.exec(val))) {
escapedVal += val.slice(chunkIndex, match.index) + CHARS_ESCAPE_MAP[match[0]];
chunkIndex = CHARS_GLOBAL_REGEXP.lastIndex;
}
if (chunkIndex === 0) {
// Nothing was escaped
return "'" + val + "'";
}
if (chunkIndex < val.length) {
return "'" + escapedVal + val.slice(chunkIndex) + "'";
}
return "'" + escapedVal + "'";
}
function zeroPad(number, length) {
number = number.toString();
while (number.length < length) {
number = '0' + number;
}
return number;
}
function convertTimezone(tz) {
if (tz === 'Z') {
return 0;
}
var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/);
if (m) {
return (m[1] === '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60;
}
return false;
}

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