@depup/mysql2 3.19.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/License +19 -0
  2. package/README.md +114 -0
  3. package/index.d.ts +1 -0
  4. package/index.js +77 -0
  5. package/lib/auth_41.js +95 -0
  6. package/lib/auth_plugins/caching_sha2_password.js +114 -0
  7. package/lib/auth_plugins/caching_sha2_password.md +18 -0
  8. package/lib/auth_plugins/index.js +8 -0
  9. package/lib/auth_plugins/mysql_clear_password.js +17 -0
  10. package/lib/auth_plugins/mysql_native_password.js +34 -0
  11. package/lib/auth_plugins/sha256_password.js +68 -0
  12. package/lib/base/connection.js +988 -0
  13. package/lib/base/pool.js +282 -0
  14. package/lib/base/pool_connection.js +77 -0
  15. package/lib/commands/auth_switch.js +129 -0
  16. package/lib/commands/binlog_dump.js +109 -0
  17. package/lib/commands/change_user.js +68 -0
  18. package/lib/commands/client_handshake.js +383 -0
  19. package/lib/commands/close_statement.js +18 -0
  20. package/lib/commands/command.js +54 -0
  21. package/lib/commands/execute.js +112 -0
  22. package/lib/commands/index.js +27 -0
  23. package/lib/commands/ping.js +36 -0
  24. package/lib/commands/prepare.js +143 -0
  25. package/lib/commands/query.js +361 -0
  26. package/lib/commands/quit.js +29 -0
  27. package/lib/commands/register_slave.js +27 -0
  28. package/lib/commands/server_handshake.js +202 -0
  29. package/lib/compressed_protocol.js +153 -0
  30. package/lib/connection.js +12 -0
  31. package/lib/connection_config.js +293 -0
  32. package/lib/constants/charset_encodings.js +317 -0
  33. package/lib/constants/charsets.js +317 -0
  34. package/lib/constants/client.js +38 -0
  35. package/lib/constants/commands.js +36 -0
  36. package/lib/constants/cursor.js +8 -0
  37. package/lib/constants/encoding_charset.js +50 -0
  38. package/lib/constants/errors.js +3973 -0
  39. package/lib/constants/field_flags.js +20 -0
  40. package/lib/constants/server_status.js +44 -0
  41. package/lib/constants/session_track.js +11 -0
  42. package/lib/constants/ssl_profiles.js +11 -0
  43. package/lib/constants/types.js +64 -0
  44. package/lib/create_connection.js +10 -0
  45. package/lib/create_pool.js +10 -0
  46. package/lib/create_pool_cluster.js +9 -0
  47. package/lib/helpers.js +83 -0
  48. package/lib/packet_parser.js +195 -0
  49. package/lib/packets/auth_next_factor.js +35 -0
  50. package/lib/packets/auth_switch_request.js +38 -0
  51. package/lib/packets/auth_switch_request_more_data.js +33 -0
  52. package/lib/packets/auth_switch_response.js +30 -0
  53. package/lib/packets/binary_row.js +95 -0
  54. package/lib/packets/binlog_dump.js +33 -0
  55. package/lib/packets/binlog_query_statusvars.js +115 -0
  56. package/lib/packets/change_user.js +97 -0
  57. package/lib/packets/close_statement.js +21 -0
  58. package/lib/packets/column_definition.js +291 -0
  59. package/lib/packets/execute.js +214 -0
  60. package/lib/packets/handshake.js +112 -0
  61. package/lib/packets/handshake_response.js +173 -0
  62. package/lib/packets/index.js +152 -0
  63. package/lib/packets/packet.js +946 -0
  64. package/lib/packets/prepare_statement.js +27 -0
  65. package/lib/packets/prepared_statement_header.js +16 -0
  66. package/lib/packets/query.js +27 -0
  67. package/lib/packets/register_slave.js +46 -0
  68. package/lib/packets/resultset_header.js +124 -0
  69. package/lib/packets/ssl_request.js +25 -0
  70. package/lib/packets/text_row.js +47 -0
  71. package/lib/parsers/binary_parser.js +235 -0
  72. package/lib/parsers/parser_cache.js +68 -0
  73. package/lib/parsers/static_binary_parser.js +213 -0
  74. package/lib/parsers/static_text_parser.js +152 -0
  75. package/lib/parsers/string.js +50 -0
  76. package/lib/parsers/text_parser.js +214 -0
  77. package/lib/pool.js +12 -0
  78. package/lib/pool_cluster.js +375 -0
  79. package/lib/pool_config.js +30 -0
  80. package/lib/pool_connection.js +12 -0
  81. package/lib/promise/connection.js +228 -0
  82. package/lib/promise/inherit_events.js +27 -0
  83. package/lib/promise/make_done_cb.js +19 -0
  84. package/lib/promise/pool.js +118 -0
  85. package/lib/promise/pool_cluster.js +54 -0
  86. package/lib/promise/pool_connection.js +23 -0
  87. package/lib/promise/prepared_statement_info.js +32 -0
  88. package/lib/results_stream.js +38 -0
  89. package/lib/server.js +37 -0
  90. package/package.json +96 -0
  91. package/promise.d.ts +139 -0
  92. package/promise.js +208 -0
  93. package/typings/mysql/LICENSE.txt +15 -0
  94. package/typings/mysql/index.d.ts +84 -0
  95. package/typings/mysql/info.txt +1 -0
  96. package/typings/mysql/lib/Auth.d.ts +30 -0
  97. package/typings/mysql/lib/Connection.d.ts +442 -0
  98. package/typings/mysql/lib/Pool.d.ts +71 -0
  99. package/typings/mysql/lib/PoolCluster.d.ts +92 -0
  100. package/typings/mysql/lib/PoolConnection.d.ts +11 -0
  101. package/typings/mysql/lib/Server.d.ts +11 -0
  102. package/typings/mysql/lib/constants/CharsetToEncoding.d.ts +8 -0
  103. package/typings/mysql/lib/constants/Charsets.d.ts +326 -0
  104. package/typings/mysql/lib/constants/Types.d.ts +70 -0
  105. package/typings/mysql/lib/constants/index.d.ts +5 -0
  106. package/typings/mysql/lib/parsers/ParserCache.d.ts +4 -0
  107. package/typings/mysql/lib/parsers/index.d.ts +18 -0
  108. package/typings/mysql/lib/parsers/typeCast.d.ts +54 -0
  109. package/typings/mysql/lib/protocol/packets/Field.d.ts +10 -0
  110. package/typings/mysql/lib/protocol/packets/FieldPacket.d.ts +27 -0
  111. package/typings/mysql/lib/protocol/packets/OkPacket.d.ts +23 -0
  112. package/typings/mysql/lib/protocol/packets/ProcedurePacket.d.ts +13 -0
  113. package/typings/mysql/lib/protocol/packets/ResultSetHeader.d.ts +18 -0
  114. package/typings/mysql/lib/protocol/packets/RowDataPacket.d.ts +9 -0
  115. package/typings/mysql/lib/protocol/packets/index.d.ts +28 -0
  116. package/typings/mysql/lib/protocol/packets/params/ErrorPacketParams.d.ts +6 -0
  117. package/typings/mysql/lib/protocol/packets/params/OkPacketParams.d.ts +9 -0
  118. package/typings/mysql/lib/protocol/sequences/ExecutableBase.d.ts +41 -0
  119. package/typings/mysql/lib/protocol/sequences/Prepare.d.ts +65 -0
  120. package/typings/mysql/lib/protocol/sequences/Query.d.ts +228 -0
  121. package/typings/mysql/lib/protocol/sequences/QueryableBase.d.ts +41 -0
  122. package/typings/mysql/lib/protocol/sequences/Sequence.d.ts +5 -0
  123. package/typings/mysql/lib/protocol/sequences/promise/ExecutableBase.d.ts +17 -0
  124. package/typings/mysql/lib/protocol/sequences/promise/QueryableBase.d.ts +18 -0
@@ -0,0 +1,202 @@
1
+ 'use strict';
2
+
3
+ const CommandCode = require('../constants/commands.js');
4
+ const Errors = require('../constants/errors.js');
5
+
6
+ const Command = require('./command.js');
7
+ const Packets = require('../packets/index.js');
8
+
9
+ class ServerHandshake extends Command {
10
+ constructor(args) {
11
+ super();
12
+ this.args = args;
13
+ /*
14
+ this.protocolVersion = args.protocolVersion || 10;
15
+ this.serverVersion = args.serverVersion;
16
+ this.connectionId = args.connectionId,
17
+ this.statusFlags = args.statusFlags,
18
+ this.characterSet = args.characterSet,
19
+ this.capabilityFlags = args.capabilityFlags || 512;
20
+ */
21
+ }
22
+
23
+ start(packet, connection) {
24
+ const serverHelloPacket = new Packets.Handshake(this.args);
25
+ this.serverHello = serverHelloPacket;
26
+ serverHelloPacket.setScrambleData((err) => {
27
+ if (err) {
28
+ connection.emit('error', new Error('Error generating random bytes'));
29
+ return;
30
+ }
31
+ connection.writePacket(serverHelloPacket.toPacket(0));
32
+ });
33
+ return ServerHandshake.prototype.readClientReply;
34
+ }
35
+
36
+ readClientReply(packet, connection) {
37
+ // check auth here
38
+ const clientHelloReply = Packets.HandshakeResponse.fromPacket(packet);
39
+ // TODO check we don't have something similar already
40
+ connection.clientHelloReply = clientHelloReply;
41
+ if (this.args.authCallback) {
42
+ this.args.authCallback(
43
+ {
44
+ user: clientHelloReply.user,
45
+ database: clientHelloReply.database,
46
+ address: connection.stream.remoteAddress,
47
+ authPluginData1: this.serverHello.authPluginData1,
48
+ authPluginData2: this.serverHello.authPluginData2,
49
+ authToken: clientHelloReply.authToken,
50
+ },
51
+ (err, mysqlError) => {
52
+ // if (err)
53
+ if (!mysqlError) {
54
+ connection.writeOk();
55
+ } else {
56
+ // TODO create constants / errorToCode
57
+ // 1045 = ER_ACCESS_DENIED_ERROR
58
+ connection.writeError({
59
+ message: mysqlError.message || '',
60
+ code: mysqlError.code || 1045,
61
+ });
62
+ connection.close();
63
+ }
64
+ }
65
+ );
66
+ } else {
67
+ connection.writeOk();
68
+ }
69
+ return ServerHandshake.prototype.dispatchCommands;
70
+ }
71
+
72
+ _isStatement(query, name) {
73
+ const firstWord = query.split(' ')[0].toUpperCase();
74
+ return firstWord === name;
75
+ }
76
+
77
+ dispatchCommands(packet, connection) {
78
+ // command from client to server
79
+ let knownCommand = true;
80
+ const encoding = connection.clientHelloReply.encoding;
81
+ const commandCode = packet.readInt8();
82
+ switch (commandCode) {
83
+ case CommandCode.STMT_PREPARE:
84
+ if (connection.listeners('stmt_prepare').length) {
85
+ const query = packet.readString(undefined, encoding);
86
+ connection.emit('stmt_prepare', query);
87
+ } else {
88
+ connection.writeError({
89
+ code: Errors.HA_ERR_INTERNAL_ERROR,
90
+ message: 'No query handler for prepared statements.',
91
+ });
92
+ }
93
+ break;
94
+ case CommandCode.STMT_EXECUTE:
95
+ if (connection.listeners('stmt_execute').length) {
96
+ const { stmtId, flags, iterationCount, values } =
97
+ Packets.Execute.fromPacket(packet, encoding);
98
+ connection.emit(
99
+ 'stmt_execute',
100
+ stmtId,
101
+ flags,
102
+ iterationCount,
103
+ values
104
+ );
105
+ } else {
106
+ connection.writeError({
107
+ code: Errors.HA_ERR_INTERNAL_ERROR,
108
+ message: 'No query handler for execute statements.',
109
+ });
110
+ }
111
+ break;
112
+ case CommandCode.QUIT:
113
+ if (connection.listeners('quit').length) {
114
+ connection.emit('quit');
115
+ } else {
116
+ connection.stream.end();
117
+ }
118
+ break;
119
+ case CommandCode.INIT_DB:
120
+ if (connection.listeners('init_db').length) {
121
+ const schemaName = packet.readString(undefined, encoding);
122
+ connection.emit('init_db', schemaName);
123
+ } else {
124
+ connection.writeOk();
125
+ }
126
+ break;
127
+ case CommandCode.QUERY:
128
+ if (connection.listeners('query').length) {
129
+ const query = packet.readString(undefined, encoding);
130
+ if (
131
+ this._isStatement(query, 'PREPARE') ||
132
+ this._isStatement(query, 'SET')
133
+ ) {
134
+ connection.emit('stmt_prepare', query);
135
+ } else if (this._isStatement(query, 'EXECUTE')) {
136
+ connection.emit('stmt_execute', null, null, null, null, query);
137
+ } else connection.emit('query', query);
138
+ } else {
139
+ connection.writeError({
140
+ code: Errors.HA_ERR_INTERNAL_ERROR,
141
+ message: 'No query handler',
142
+ });
143
+ }
144
+ break;
145
+ case CommandCode.FIELD_LIST:
146
+ if (connection.listeners('field_list').length) {
147
+ const table = packet.readNullTerminatedString(encoding);
148
+ const fields = packet.readString(undefined, encoding);
149
+ connection.emit('field_list', table, fields);
150
+ } else {
151
+ connection.writeError({
152
+ code: Errors.ER_WARN_DEPRECATED_SYNTAX,
153
+ message:
154
+ 'As of MySQL 5.7.11, COM_FIELD_LIST is deprecated and will be removed in a future version of MySQL.',
155
+ });
156
+ }
157
+ break;
158
+ case CommandCode.PING:
159
+ if (connection.listeners('ping').length) {
160
+ connection.emit('ping');
161
+ } else {
162
+ connection.writeOk();
163
+ }
164
+ break;
165
+ default:
166
+ knownCommand = false;
167
+ }
168
+ if (connection.listeners('packet').length) {
169
+ connection.emit('packet', packet.clone(), knownCommand, commandCode);
170
+ } else if (!knownCommand) {
171
+ console.log('Unknown command:', commandCode);
172
+ }
173
+ return ServerHandshake.prototype.dispatchCommands;
174
+ }
175
+ }
176
+
177
+ module.exports = ServerHandshake;
178
+
179
+ // TODO: implement server-side 4.1 authentication
180
+ /*
181
+ 4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
182
+
183
+ SERVER: public_seed=create_random_string()
184
+ send(public_seed)
185
+
186
+ CLIENT: recv(public_seed)
187
+ hash_stage1=sha1("password")
188
+ hash_stage2=sha1(hash_stage1)
189
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
190
+
191
+ // this three steps are done in scramble()
192
+
193
+ send(reply)
194
+
195
+
196
+ SERVER: recv(reply)
197
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
198
+ candidate_hash2=sha1(hash_stage1)
199
+ check(candidate_hash2==hash_stage2)
200
+
201
+ server stores sha1(sha1(password)) ( hash_stag2)
202
+ */
@@ -0,0 +1,153 @@
1
+ 'use strict';
2
+
3
+ // connection mixins
4
+ // implementation of http://dev.mysql.com/doc/internals/en/compression.html
5
+
6
+ const zlib = require('zlib');
7
+ const PacketParser = require('./packet_parser.js');
8
+
9
+ class Queue {
10
+ constructor() {
11
+ this._queue = [];
12
+ this._running = false;
13
+ }
14
+
15
+ push(fn) {
16
+ this._queue.push(fn);
17
+ if (!this._running) {
18
+ this._running = true;
19
+ process.nextTick(() => this._next());
20
+ }
21
+ }
22
+
23
+ _next() {
24
+ const task = this._queue.shift();
25
+ if (!task) {
26
+ this._running = false;
27
+ return;
28
+ }
29
+ task({
30
+ done: () => process.nextTick(() => this._next()),
31
+ });
32
+ }
33
+ }
34
+
35
+ function handleCompressedPacket(packet) {
36
+ // eslint-disable-next-line consistent-this, no-invalid-this
37
+ const connection = this;
38
+ const deflatedLength = packet.readInt24();
39
+ const body = packet.readBuffer();
40
+
41
+ if (deflatedLength !== 0) {
42
+ connection.inflateQueue.push((task) => {
43
+ zlib.inflate(body, (err, data) => {
44
+ if (err) {
45
+ connection._handleNetworkError(err);
46
+ return;
47
+ }
48
+ connection._bumpCompressedSequenceId(packet.numPackets);
49
+ connection._inflatedPacketsParser.execute(data);
50
+ task.done();
51
+ });
52
+ });
53
+ } else {
54
+ connection.inflateQueue.push((task) => {
55
+ connection._bumpCompressedSequenceId(packet.numPackets);
56
+ connection._inflatedPacketsParser.execute(body);
57
+ task.done();
58
+ });
59
+ }
60
+ }
61
+
62
+ function writeCompressed(buffer) {
63
+ // http://dev.mysql.com/doc/internals/en/example-several-mysql-packets.html
64
+ // note: sending a MySQL Packet of the size 2^24−5 to 2^24−1 via compression
65
+ // leads to at least one extra compressed packet.
66
+ // (this is because "length of the packet before compression" need to fit
67
+ // into 3 byte unsigned int. "length of the packet before compression" includes
68
+ // 4 byte packet header, hence 2^24−5)
69
+ const MAX_COMPRESSED_LENGTH = 16777210;
70
+ let start;
71
+ if (buffer.length > MAX_COMPRESSED_LENGTH) {
72
+ for (start = 0; start < buffer.length; start += MAX_COMPRESSED_LENGTH) {
73
+ writeCompressed.call(
74
+ // eslint-disable-next-line no-invalid-this
75
+ this,
76
+ buffer.slice(start, start + MAX_COMPRESSED_LENGTH)
77
+ );
78
+ }
79
+ return;
80
+ }
81
+
82
+ // eslint-disable-next-line no-invalid-this, consistent-this
83
+ const connection = this;
84
+
85
+ let packetLen = buffer.length;
86
+ const compressHeader = Buffer.allocUnsafe(7);
87
+
88
+ // seqqueue is used here because zlib async execution is routed via thread pool
89
+ // internally and when we have multiple compressed packets arriving we need
90
+ // to assemble uncompressed result sequentially
91
+ (function (seqId) {
92
+ connection.deflateQueue.push((task) => {
93
+ zlib.deflate(buffer, (err, compressed) => {
94
+ if (err) {
95
+ connection._handleFatalError(err);
96
+ return;
97
+ }
98
+ let compressedLength = compressed.length;
99
+
100
+ if (compressedLength < packetLen) {
101
+ compressHeader.writeUInt8(compressedLength & 0xff, 0);
102
+ compressHeader.writeUInt16LE(compressedLength >> 8, 1);
103
+ compressHeader.writeUInt8(seqId, 3);
104
+ compressHeader.writeUInt8(packetLen & 0xff, 4);
105
+ compressHeader.writeUInt16LE(packetLen >> 8, 5);
106
+ connection.writeUncompressed(compressHeader);
107
+ connection.writeUncompressed(compressed);
108
+ } else {
109
+ // http://dev.mysql.com/doc/internals/en/uncompressed-payload.html
110
+ // To send an uncompressed payload:
111
+ // - set length of payload before compression to 0
112
+ // - the compressed payload contains the uncompressed payload instead.
113
+ compressedLength = packetLen;
114
+ packetLen = 0;
115
+ compressHeader.writeUInt8(compressedLength & 0xff, 0);
116
+ compressHeader.writeUInt16LE(compressedLength >> 8, 1);
117
+ compressHeader.writeUInt8(seqId, 3);
118
+ compressHeader.writeUInt8(packetLen & 0xff, 4);
119
+ compressHeader.writeUInt16LE(packetLen >> 8, 5);
120
+ connection.writeUncompressed(compressHeader);
121
+ connection.writeUncompressed(buffer);
122
+ }
123
+ task.done();
124
+ });
125
+ });
126
+ })(connection.compressedSequenceId);
127
+ connection._bumpCompressedSequenceId(1);
128
+ }
129
+
130
+ function enableCompression(connection) {
131
+ connection._lastWrittenPacketId = 0;
132
+ connection._lastReceivedPacketId = 0;
133
+
134
+ connection._handleCompressedPacket = handleCompressedPacket;
135
+ connection._inflatedPacketsParser = new PacketParser((p) => {
136
+ connection.handlePacket(p);
137
+ }, 4);
138
+ connection._inflatedPacketsParser._lastPacket = 0;
139
+ connection.packetParser = new PacketParser((packet) => {
140
+ connection._handleCompressedPacket(packet);
141
+ }, 7);
142
+
143
+ connection.writeUncompressed = connection.write;
144
+ connection.write = writeCompressed;
145
+
146
+ connection.inflateQueue = new Queue();
147
+ connection.deflateQueue = new Queue();
148
+ }
149
+
150
+ module.exports = {
151
+ enableCompression: enableCompression,
152
+ Queue: Queue,
153
+ };
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ const BaseConnection = require('./base/connection.js');
4
+
5
+ class Connection extends BaseConnection {
6
+ promise(promiseImpl) {
7
+ const PromiseConnection = require('./promise/connection.js');
8
+ return new PromiseConnection(this, promiseImpl);
9
+ }
10
+ }
11
+
12
+ module.exports = Connection;
@@ -0,0 +1,293 @@
1
+ // This file was modified by Oracle on September 21, 2021.
2
+ // New connection options for additional authentication factors were
3
+ // introduced.
4
+ // Multi-factor authentication capability is now enabled if one of these
5
+ // options is used.
6
+ // Modifications copyright (c) 2021, Oracle and/or its affiliates.
7
+
8
+ 'use strict';
9
+
10
+ const { URL } = require('url');
11
+ const ClientConstants = require('./constants/client');
12
+ const Charsets = require('./constants/charsets');
13
+ const { version } = require('../package.json');
14
+ let SSLProfiles = null;
15
+
16
+ const validOptions = {
17
+ authPlugins: 1,
18
+ authSwitchHandler: 1,
19
+ bigNumberStrings: 1,
20
+ charset: 1,
21
+ charsetNumber: 1,
22
+ compress: 1,
23
+ connectAttributes: 1,
24
+ connectTimeout: 1,
25
+ database: 1,
26
+ dateStrings: 1,
27
+ debug: 1,
28
+ decimalNumbers: 1,
29
+ enableKeepAlive: 1,
30
+ flags: 1,
31
+ host: 1,
32
+ insecureAuth: 1,
33
+ infileStreamFactory: 1,
34
+ isServer: 1,
35
+ keepAliveInitialDelay: 1,
36
+ localAddress: 1,
37
+ maxPreparedStatements: 1,
38
+ multipleStatements: 1,
39
+ namedPlaceholders: 1,
40
+ nestTables: 1,
41
+ password: 1,
42
+ // with multi-factor authentication, the main password (used for the first
43
+ // authentication factor) can be provided via password1
44
+ password1: 1,
45
+ password2: 1,
46
+ password3: 1,
47
+ passwordSha1: 1,
48
+ pool: 1,
49
+ port: 1,
50
+ queryFormat: 1,
51
+ rowsAsArray: 1,
52
+ socketPath: 1,
53
+ ssl: 1,
54
+ stream: 1,
55
+ stringifyObjects: 1,
56
+ supportBigNumbers: 1,
57
+ timezone: 1,
58
+ trace: 1,
59
+ typeCast: 1,
60
+ uri: 1,
61
+ user: 1,
62
+ disableEval: 1,
63
+ // These options are used for Pool
64
+ connectionLimit: 1,
65
+ maxIdle: 1,
66
+ idleTimeout: 1,
67
+ Promise: 1,
68
+ queueLimit: 1,
69
+ waitForConnections: 1,
70
+ jsonStrings: 1,
71
+ gracefulEnd: 1,
72
+ };
73
+
74
+ class ConnectionConfig {
75
+ constructor(options) {
76
+ if (typeof options === 'string') {
77
+ options = ConnectionConfig.parseUrl(options);
78
+ } else if (options && options.uri) {
79
+ const uriOptions = ConnectionConfig.parseUrl(options.uri);
80
+ for (const key in uriOptions) {
81
+ if (!Object.prototype.hasOwnProperty.call(uriOptions, key)) continue;
82
+ if (options[key]) continue;
83
+ options[key] = uriOptions[key];
84
+ }
85
+ }
86
+ for (const key in options) {
87
+ if (!Object.prototype.hasOwnProperty.call(options, key)) continue;
88
+ if (validOptions[key] !== 1) {
89
+ // REVIEW: Should this be emitted somehow?
90
+ console.error(
91
+ `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`
92
+ );
93
+ }
94
+ }
95
+ this.isServer = options.isServer;
96
+ this.stream = options.stream;
97
+ this.host = options.host || 'localhost';
98
+ this.port =
99
+ (typeof options.port === 'string'
100
+ ? parseInt(options.port, 10)
101
+ : options.port) || 3306;
102
+ this.localAddress = options.localAddress;
103
+ this.socketPath = options.socketPath;
104
+ this.user = options.user || undefined;
105
+ // for the purpose of multi-factor authentication, or not, the main
106
+ // password (used for the 1st authentication factor) can also be
107
+ // provided via the "password1" option
108
+ this.password = options.password || options.password1 || undefined;
109
+ this.password2 = options.password2 || undefined;
110
+ this.password3 = options.password3 || undefined;
111
+ this.passwordSha1 = options.passwordSha1 || undefined;
112
+ this.database = options.database;
113
+ this.connectTimeout = isNaN(options.connectTimeout)
114
+ ? 10 * 1000
115
+ : options.connectTimeout;
116
+ this.insecureAuth = options.insecureAuth || false;
117
+ this.infileStreamFactory = options.infileStreamFactory || undefined;
118
+ this.supportBigNumbers = options.supportBigNumbers || false;
119
+ this.bigNumberStrings = options.bigNumberStrings || false;
120
+ this.decimalNumbers = options.decimalNumbers || false;
121
+ this.dateStrings = options.dateStrings || false;
122
+ this.debug = options.debug;
123
+ this.trace = options.trace !== false;
124
+ this.stringifyObjects = options.stringifyObjects || false;
125
+ this.enableKeepAlive = options.enableKeepAlive !== false;
126
+ this.keepAliveInitialDelay = options.keepAliveInitialDelay;
127
+ if (
128
+ options.timezone &&
129
+ !/^(?:local|Z|[ +-]\d\d:\d\d)$/.test(options.timezone)
130
+ ) {
131
+ // strictly supports timezones specified by mysqljs/mysql:
132
+ // https://github.com/mysqljs/mysql#user-content-connection-options
133
+
134
+ console.error(
135
+ `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`
136
+ );
137
+ // SqlStrings falls back to UTC on invalid timezone
138
+ this.timezone = 'Z';
139
+ } else {
140
+ this.timezone = options.timezone || 'local';
141
+ }
142
+ this.queryFormat = options.queryFormat;
143
+ this.pool = options.pool || undefined;
144
+ this.ssl =
145
+ typeof options.ssl === 'string'
146
+ ? ConnectionConfig.getSSLProfile(options.ssl)
147
+ : options.ssl || false;
148
+ this.multipleStatements = options.multipleStatements || false;
149
+ this.rowsAsArray = options.rowsAsArray || false;
150
+ this.namedPlaceholders = options.namedPlaceholders || false;
151
+ this.nestTables =
152
+ options.nestTables === undefined ? undefined : options.nestTables;
153
+ this.typeCast = options.typeCast === undefined ? true : options.typeCast;
154
+ this.disableEval = Boolean(options.disableEval);
155
+ if (this.timezone[0] === ' ') {
156
+ // "+" is a url encoded char for space so it
157
+ // gets translated to space when giving a
158
+ // connection string..
159
+ this.timezone = `+${this.timezone.slice(1)}`;
160
+ }
161
+ if (this.ssl) {
162
+ if (typeof this.ssl !== 'object') {
163
+ throw new TypeError(
164
+ `SSL profile must be an object, instead it's a ${typeof this.ssl}`
165
+ );
166
+ }
167
+ // Default rejectUnauthorized to true
168
+ this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
169
+ }
170
+ this.maxPacketSize = 0;
171
+ this.charsetNumber = options.charset
172
+ ? ConnectionConfig.getCharsetNumber(options.charset)
173
+ : options.charsetNumber || Charsets.UTF8MB4_UNICODE_CI;
174
+ this.compress = options.compress || false;
175
+ this.authPlugins = options.authPlugins;
176
+ this.authSwitchHandler = options.authSwitchHandler;
177
+ this.clientFlags = ConnectionConfig.mergeFlags(
178
+ ConnectionConfig.getDefaultFlags(options),
179
+ options.flags || ''
180
+ );
181
+ // Default connection attributes
182
+ // https://dev.mysql.com/doc/refman/8.0/en/performance-schema-connection-attribute-tables.html
183
+ const defaultConnectAttributes = {
184
+ _client_name: 'Node-MySQL-2',
185
+ _client_version: version,
186
+ };
187
+ this.connectAttributes = {
188
+ ...defaultConnectAttributes,
189
+ ...(options.connectAttributes || {}),
190
+ };
191
+ this.maxPreparedStatements = options.maxPreparedStatements || 16000;
192
+ this.jsonStrings = options.jsonStrings || false;
193
+ this.gracefulEnd = options.gracefulEnd || false;
194
+ }
195
+
196
+ static mergeFlags(default_flags, user_flags) {
197
+ let flags = 0x0,
198
+ i;
199
+ if (!Array.isArray(user_flags)) {
200
+ user_flags = String(user_flags || '')
201
+ .toUpperCase()
202
+ .split(/\s*,+\s*/);
203
+ }
204
+ // add default flags unless "blacklisted"
205
+ for (i in default_flags) {
206
+ if (user_flags.indexOf(`-${default_flags[i]}`) >= 0) {
207
+ continue;
208
+ }
209
+ flags |= ClientConstants[default_flags[i]] || 0x0;
210
+ }
211
+ // add user flags unless already already added
212
+ for (i in user_flags) {
213
+ if (user_flags[i][0] === '-') {
214
+ continue;
215
+ }
216
+ if (default_flags.indexOf(user_flags[i]) >= 0) {
217
+ continue;
218
+ }
219
+ flags |= ClientConstants[user_flags[i]] || 0x0;
220
+ }
221
+ return flags;
222
+ }
223
+
224
+ static getDefaultFlags(options) {
225
+ const defaultFlags = [
226
+ 'LONG_PASSWORD',
227
+ 'FOUND_ROWS',
228
+ 'LONG_FLAG',
229
+ 'CONNECT_WITH_DB',
230
+ 'ODBC',
231
+ 'LOCAL_FILES',
232
+ 'IGNORE_SPACE',
233
+ 'PROTOCOL_41',
234
+ 'IGNORE_SIGPIPE',
235
+ 'TRANSACTIONS',
236
+ 'RESERVED',
237
+ 'SECURE_CONNECTION',
238
+ 'MULTI_RESULTS',
239
+ 'TRANSACTIONS',
240
+ 'SESSION_TRACK',
241
+ 'CONNECT_ATTRS',
242
+ ];
243
+ if (options && options.multipleStatements) {
244
+ defaultFlags.push('MULTI_STATEMENTS');
245
+ }
246
+ defaultFlags.push('PLUGIN_AUTH');
247
+ defaultFlags.push('PLUGIN_AUTH_LENENC_CLIENT_DATA');
248
+
249
+ return defaultFlags;
250
+ }
251
+
252
+ static getCharsetNumber(charset) {
253
+ const num = Charsets[charset.toUpperCase()];
254
+ if (num === undefined) {
255
+ throw new TypeError(`Unknown charset '${charset}'`);
256
+ }
257
+ return num;
258
+ }
259
+
260
+ static getSSLProfile(name) {
261
+ if (!SSLProfiles) {
262
+ SSLProfiles = require('./constants/ssl_profiles.js');
263
+ }
264
+ const ssl = SSLProfiles[name];
265
+ if (ssl === undefined) {
266
+ throw new TypeError(`Unknown SSL profile '${name}'`);
267
+ }
268
+ return ssl;
269
+ }
270
+
271
+ static parseUrl(url) {
272
+ const parsedUrl = new URL(url);
273
+ const options = {
274
+ host: decodeURIComponent(parsedUrl.hostname),
275
+ port: parseInt(parsedUrl.port, 10),
276
+ database: decodeURIComponent(parsedUrl.pathname.slice(1)),
277
+ user: decodeURIComponent(parsedUrl.username),
278
+ password: decodeURIComponent(parsedUrl.password),
279
+ };
280
+ parsedUrl.searchParams.forEach((value, key) => {
281
+ try {
282
+ // Try to parse this as a JSON expression first
283
+ options[key] = JSON.parse(value);
284
+ } catch {
285
+ // Otherwise assume it is a plain string
286
+ options[key] = value;
287
+ }
288
+ });
289
+ return options;
290
+ }
291
+ }
292
+
293
+ module.exports = ConnectionConfig;