oceanbase 0.0.1

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 +250 -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 +108 -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 +978 -0
  13. package/lib/base/pool.js +237 -0
  14. package/lib/base/pool_connection.js +70 -0
  15. package/lib/commands/auth_switch.js +111 -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 +241 -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 +366 -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 +203 -0
  29. package/lib/compressed_protocol.js +127 -0
  30. package/lib/connection.js +12 -0
  31. package/lib/connection_config.js +326 -0
  32. package/lib/constants/charset_encodings.js +316 -0
  33. package/lib/constants/charsets.js +317 -0
  34. package/lib/constants/client.js +40 -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 +86 -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 +144 -0
  62. package/lib/packets/index.js +152 -0
  63. package/lib/packets/packet.js +931 -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 +369 -0
  79. package/lib/pool_config.js +30 -0
  80. package/lib/pool_connection.js +12 -0
  81. package/lib/promise/connection.js +222 -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 +112 -0
  85. package/lib/promise/pool_cluster.js +54 -0
  86. package/lib/promise/pool_connection.js +19 -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 +80 -0
  91. package/promise.d.ts +131 -0
  92. package/promise.js +202 -0
  93. package/typings/mysql/LICENSE.txt +15 -0
  94. package/typings/mysql/index.d.ts +95 -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 +453 -0
  98. package/typings/mysql/lib/Pool.d.ts +69 -0
  99. package/typings/mysql/lib/PoolCluster.d.ts +90 -0
  100. package/typings/mysql/lib/PoolConnection.d.ts +10 -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 +40 -0
  119. package/typings/mysql/lib/protocol/sequences/Prepare.d.ts +65 -0
  120. package/typings/mysql/lib/protocol/sequences/Query.d.ts +170 -0
  121. package/typings/mysql/lib/protocol/sequences/QueryableBase.d.ts +40 -0
  122. package/typings/mysql/lib/protocol/sequences/Sequence.d.ts +5 -0
  123. package/typings/mysql/lib/protocol/sequences/promise/ExecutableBase.d.ts +21 -0
  124. package/typings/mysql/lib/protocol/sequences/promise/QueryableBase.d.ts +21 -0
package/License ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ [npm-image]: https://img.shields.io/npm/v/oceanbase.svg
2
+ [npm-url]: https://npmjs.com/package/oceanbase
3
+ [node-version-image]: https://img.shields.io/node/v/oceanbase.svg
4
+ [node-version-url]: https://nodejs.org/en/download
5
+ [downloads-image]: https://img.shields.io/npm/dm/oceanbase.svg
6
+ [downloads-url]: https://npmjs.com/package/oceanbase
7
+ [license-url]: https://github.com/sidorares/node-mysql2/blob/master/License
8
+ [license-image]: https://img.shields.io/npm/l/oceanbase.svg?maxAge=2592000
9
+ [node-mysql]: https://github.com/mysqljs/mysql
10
+ [mysqljs]: https://github.com/mysqljs
11
+ [mysql-native]: https://github.com/sidorares/nodejs-mysql-native
12
+ [sidorares]: https://github.com/sidorares
13
+ [TooTallNate]: https://gist.github.com/TooTallNate
14
+ [starttls.js]: https://gist.github.com/TooTallNate/848444
15
+ [node-mariasql]: https://github.com/mscdex/node-mariasql
16
+ [contributors]: https://github.com/sidorares/node-mysql2/graphs/contributors
17
+ [contributing]: https://github.com/sidorares/node-mysql2/blob/master/Contributing.md
18
+ [docs-base]: https://sidorares.github.io/node-mysql2/docs
19
+ [docs-base-zh-CN]: https://sidorares.github.io/node-mysql2/zh-CN/docs
20
+ [docs-base-pt-BR]: https://sidorares.github.io/node-mysql2/pt-BR/docs
21
+ [docs-prepared-statements]: https://sidorares.github.io/node-mysql2/docs/documentation/prepared-statements
22
+ [docs-mysql-server]: https://sidorares.github.io/node-mysql2/docs/documentation/mysql-server
23
+ [docs-promise-wrapper]: https://sidorares.github.io/node-mysql2/docs/documentation/promise-wrapper
24
+ [docs-authentication-switch]: https://sidorares.github.io/node-mysql2/docs/documentation/authentication-switch
25
+ [docs-streams]: https://sidorares.github.io/node-mysql2/docs/documentation/extras
26
+ [docs-typescript-docs]: https://sidorares.github.io/node-mysql2/docs/documentation/typescript-examples
27
+ [docs-qs-pooling]: https://sidorares.github.io/node-mysql2/docs#using-connection-pools
28
+ [docs-qs-first-query]: https://sidorares.github.io/node-mysql2/docs#first-query
29
+ [docs-qs-using-prepared-statements]: https://sidorares.github.io/node-mysql2/docs#using-prepared-statements
30
+ [docs-examples]: https://sidorares.github.io/node-mysql2/docs/examples
31
+ [docs-faq]: https://sidorares.github.io/node-mysql2/docs/faq
32
+ [docs-documentation]: https://sidorares.github.io/node-mysql2/docs/documentation
33
+ [docs-contributing]: https://sidorares.github.io/node-mysql2/docs/contributing/website
34
+ [coverage]: https://img.shields.io/codecov/c/github/sidorares/node-mysql2
35
+ [coverage-url]: https://app.codecov.io/github/sidorares/node-mysql2
36
+ [ci-url]: https://github.com/sidorares/node-mysql2/actions/workflows/ci-coverage.yml?query=branch%3Amaster
37
+ [ci-image]: https://img.shields.io/github/actions/workflow/status/sidorares/node-mysql2/ci-coverage.yml?event=push&style=flat&label=CI&branch=master
38
+
39
+ # OceanBase Driver for Node.js
40
+
41
+ [![NPM Version][npm-image]][npm-url]
42
+ [![NPM Downloads][downloads-image]][downloads-url]
43
+ [![Node.js Version][node-version-image]][node-version-url]
44
+ [![GitHub Workflow Status (with event)][ci-image]][ci-url]
45
+ [![Codecov][coverage]][coverage-url]
46
+ [![License][license-image]][license-url]
47
+
48
+ > High-performance OceanBase database client driver built on top of [MySQL2][node-mysql]. Fully compatible with MySQL protocol, with additional support for OceanBase Oracle tenant protocol. Supports prepared statements, non-utf8 encodings, binary log protocol, compression, SSL and [much more][docs-documentation].
49
+
50
+ **Table of Contents**
51
+
52
+ - [About This Driver](#about-this-driver)
53
+ - [Key Features](#key-features)
54
+ - [Installation](#installation)
55
+ - [Quick Start](#quick-start)
56
+ - [Documentation](#documentation)
57
+ - [Acknowledgements](#acknowledgements)
58
+ - [Contributing](#contributing)
59
+
60
+ ## About This Driver
61
+
62
+ This driver is built on top of the [MySQL2][node-mysql] project, extending support for OceanBase database while maintaining all MySQL2 functionality.
63
+
64
+ **OceanBase** is a distributed relational database that is fully compatible with MySQL protocol. This driver extends the MySQL protocol with additional support for **OceanBase Oracle tenant protocol**, enabling you to:
65
+
66
+ - Connect to OceanBase MySQL tenants using MySQL mode
67
+ - Connect to OceanBase Oracle tenants using Oracle mode
68
+ - Seamlessly migrate existing MySQL2 code without API changes
69
+
70
+ This driver is fully API compatible with [MySQL2][node-mysql], and you can directly refer to the [MySQL2 official documentation][docs-documentation] for usage.
71
+
72
+ ## Key Features
73
+
74
+ ### OceanBase-Specific Features
75
+
76
+ - ✅ **OceanBase MySQL Tenant Support** - Fully compatible with MySQL protocol
77
+ - ✅ **OceanBase Oracle Tenant Support** - Enable Oracle compatibility mode via `mode: 'oracle'` option
78
+ - ✅ **Dual Mode Support** - Single driver supports both MySQL and Oracle modes
79
+
80
+ ### MySQL2 Original Features
81
+
82
+ - ⚡ **Faster / Better Performance** - Optimized performance
83
+ - 📝 **[Prepared Statements][docs-prepared-statements]** - Support for prepared statements, improving performance and security
84
+ - 📊 **MySQL Binary Log Protocol** - Support for binary log parsing
85
+ - 🖥️ **[MySQL Server][docs-mysql-server]** - Can create MySQL-compatible servers
86
+ - 🌐 **Extended support for Encoding and Collation** - Support for multiple character sets and collations
87
+ - 🔄 **[Promise Wrapper][docs-promise-wrapper]** - Native Promise support
88
+ - 🗜️ **Compression** - Support for connection compression
89
+ - 🔒 **SSL and [Authentication Switch][docs-authentication-switch]** - Support for SSL connections and multiple authentication methods
90
+ - 🌊 **[Custom Streams][docs-streams]** - Support for custom data streams
91
+ - 💧 **[Connection Pooling][docs-qs-pooling]** - Built-in connection pool management
92
+
93
+ ## Installation
94
+
95
+ This driver is free from native bindings and can be installed on Linux, Mac OS or Windows without any issues.
96
+
97
+ ```bash
98
+ npm install --save oceanbase
99
+ ```
100
+
101
+
102
+ ## Quick Start
103
+
104
+ ### Connecting to OceanBase MySQL Tenant
105
+
106
+ ```javascript
107
+ const oceanbase = require('oceanbase');
108
+
109
+ const connection = oceanbase.createConnection({
110
+ host: 'localhost',
111
+ user: 'root',
112
+ password: 'password',
113
+ database: 'test'
114
+ });
115
+
116
+ connection.query('SELECT * FROM users', (err, results) => {
117
+ if (err) throw err;
118
+ console.log(results);
119
+ });
120
+ ```
121
+
122
+ ### Connecting to OceanBase Oracle Tenant
123
+
124
+ ```javascript
125
+ const oceanbase = require('oceanbase');
126
+
127
+ // Use mode: 'oracle' option to enable Oracle mode
128
+ const connection = oceanbase.createConnection({
129
+ host: 'localhost',
130
+ user: 'oracle_user',
131
+ password: 'password',
132
+ database: 'oracle_db',
133
+ mode: 'oracle' // Key: Enable Oracle tenant mode
134
+ });
135
+
136
+ connection.query('SELECT * FROM users', (err, results) => {
137
+ if (err) throw err;
138
+ console.log(results);
139
+ });
140
+ ```
141
+
142
+ ### Connecting with Tenant and Cluster
143
+
144
+ OceanBase supports cluster and tenant fields. When connecting, you can specify `tenant` and `cluster` options, and the driver will automatically format the username as `username@tenant#cluster`:
145
+
146
+ ```javascript
147
+ const oceanbase = require('oceanbase');
148
+
149
+ // Using tenant and cluster options
150
+ const connection = oceanbase.createConnection({
151
+ host: 'localhost',
152
+ user: 'myuser',
153
+ password: 'password',
154
+ database: 'mydb',
155
+ tenant: 'mytenant', // Tenant name
156
+ cluster: 'mycluster' // Cluster name
157
+ // Username will be automatically formatted as: myuser@mytenant#mycluster
158
+ });
159
+
160
+ // You can also use URL query parameters
161
+ const connection2 = oceanbase.createConnection({
162
+ uri: 'mysql://myuser:password@localhost:3306/mydb?tenant=mytenant&cluster=mycluster'
163
+ });
164
+
165
+ // If username already contains @ or #, it will be used as-is
166
+ const connection3 = oceanbase.createConnection({
167
+ host: 'localhost',
168
+ user: 'myuser@mytenant#mycluster', // Already formatted
169
+ password: 'password',
170
+ database: 'mydb'
171
+ // tenant and cluster options will be ignored if username is already formatted
172
+ });
173
+ ```
174
+
175
+ ### Using Connection Pool (Oracle Mode)
176
+
177
+ ```javascript
178
+ const oceanbase = require('oceanbase');
179
+
180
+ const pool = oceanbase.createPool({
181
+ host: 'localhost',
182
+ user: 'oracle_user',
183
+ password: 'password',
184
+ database: 'oracle_db',
185
+ mode: 'oracle' // Oracle tenant mode
186
+ });
187
+
188
+ pool.query('SELECT * FROM users', (err, results) => {
189
+ if (err) throw err;
190
+ console.log(results);
191
+ });
192
+ ```
193
+
194
+ ### Using Promise API
195
+
196
+ ```javascript
197
+ const oceanbase = require('oceanbase/promise');
198
+
199
+ async function queryData() {
200
+ const connection = await oceanbase.createConnection({
201
+ host: 'localhost',
202
+ user: 'root',
203
+ password: 'password',
204
+ database: 'test',
205
+ mode: 'oracle' // Optional: Oracle mode
206
+ });
207
+
208
+ const [rows] = await connection.execute('SELECT * FROM users WHERE id = ?', [1]);
209
+ console.log(rows);
210
+
211
+ await connection.end();
212
+ }
213
+ ```
214
+
215
+ ## Documentation
216
+
217
+ This driver's usage documentation is fully compatible with [MySQL2][node-mysql]. You can refer to the following MySQL2 official documentation:
218
+
219
+ - [Quickstart][docs-base]
220
+ - [First Query][docs-qs-first-query], [Using Prepared Statements][docs-qs-using-prepared-statements], [Using Connection Pools][docs-qs-pooling] and more.
221
+ - [Documentation][docs-documentation]
222
+ - [Examples][docs-examples]
223
+ - [FAQ][docs-faq]
224
+
225
+ ### Oracle Mode Notes
226
+
227
+ When connecting to OceanBase Oracle tenants, you need to add the `mode: 'oracle'` option to your connection configuration:
228
+
229
+ ```javascript
230
+ {
231
+ host: 'your-host',
232
+ user: 'your-user',
233
+ password: 'your-password',
234
+ database: 'your-database',
235
+ mode: 'oracle' // Enable Oracle tenant mode
236
+ }
237
+ ```
238
+
239
+ When `mode` is not specified or set to `mode: 'mysql'`, the standard MySQL protocol will be used (suitable for MySQL tenants).
240
+
241
+ ### Tenant and Cluster Configuration
242
+
243
+ OceanBase supports multi-tenant architecture with cluster and tenant concepts. The driver automatically formats usernames when `tenant` and/or `cluster` options are provided:
244
+
245
+ - **`tenant`** (optional): The tenant name. When provided, username will be formatted as `username@tenant`
246
+ - **`cluster`** (optional): The cluster name. When provided, username will be formatted as `username@tenant#cluster` (if tenant is also provided) or `username#cluster` (if only cluster is provided)
247
+
248
+ **Note**: If the username already contains `@` or `#` characters, the driver will use it as-is and ignore the `tenant` and `cluster` options to avoid duplicate formatting.
249
+
250
+
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './typings/mysql/index.js';
package/index.js ADDED
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ const SqlString = require('sqlstring');
4
+
5
+ const ConnectionConfig = require('./lib/connection_config.js');
6
+ const parserCache = require('./lib/parsers/parser_cache.js');
7
+
8
+ const Connection = require('./lib/connection.js');
9
+
10
+ exports.createConnection = require('./lib/create_connection.js');
11
+ exports.connect = exports.createConnection;
12
+ exports.Connection = Connection;
13
+ exports.ConnectionConfig = ConnectionConfig;
14
+
15
+ const Pool = require('./lib/pool.js');
16
+ const PoolCluster = require('./lib/pool_cluster.js');
17
+ const createPool = require('./lib/create_pool.js');
18
+ const createPoolCluster = require('./lib/create_pool_cluster.js');
19
+
20
+ exports.createPool = createPool;
21
+
22
+ exports.createPoolCluster = createPoolCluster;
23
+
24
+ exports.createQuery = Connection.createQuery;
25
+
26
+ exports.Pool = Pool;
27
+
28
+ exports.PoolCluster = PoolCluster;
29
+
30
+ exports.createServer = function (handler) {
31
+ const Server = require('./lib/server.js');
32
+ const s = new Server();
33
+ if (handler) {
34
+ s.on('connection', handler);
35
+ }
36
+ return s;
37
+ };
38
+
39
+ exports.PoolConnection = require('./lib/pool_connection.js');
40
+ exports.authPlugins = require('./lib/auth_plugins');
41
+ exports.escape = SqlString.escape;
42
+ exports.escapeId = SqlString.escapeId;
43
+ exports.format = SqlString.format;
44
+ exports.raw = SqlString.raw;
45
+
46
+ exports.__defineGetter__(
47
+ 'createConnectionPromise',
48
+ () => require('./promise.js').createConnection
49
+ );
50
+
51
+ exports.__defineGetter__(
52
+ 'createPoolPromise',
53
+ () => require('./promise.js').createPool
54
+ );
55
+
56
+ exports.__defineGetter__(
57
+ 'createPoolClusterPromise',
58
+ () => require('./promise.js').createPoolCluster
59
+ );
60
+
61
+ exports.__defineGetter__('Types', () => require('./lib/constants/types.js'));
62
+
63
+ exports.__defineGetter__('Charsets', () =>
64
+ require('./lib/constants/charsets.js')
65
+ );
66
+
67
+ exports.__defineGetter__('CharsetToEncoding', () =>
68
+ require('./lib/constants/charset_encodings.js')
69
+ );
70
+
71
+ exports.setMaxParserCache = function (max) {
72
+ parserCache.setMaxCache(max);
73
+ };
74
+
75
+ exports.clearParserCache = function () {
76
+ parserCache.clearCache();
77
+ };
package/lib/auth_41.js ADDED
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ /*
4
+ 4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
5
+
6
+ SERVER: public_seed=create_random_string()
7
+ send(public_seed)
8
+
9
+ CLIENT: recv(public_seed)
10
+ hash_stage1=sha1("password")
11
+ hash_stage2=sha1(hash_stage1)
12
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
13
+
14
+ // this three steps are done in scramble()
15
+
16
+ send(reply)
17
+
18
+
19
+ SERVER: recv(reply)
20
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
21
+ candidate_hash2=sha1(hash_stage1)
22
+ check(candidate_hash2==hash_stage2)
23
+
24
+ server stores sha1(sha1(password)) ( hash_stag2)
25
+ */
26
+
27
+ const crypto = require('crypto');
28
+
29
+ function sha1(msg, msg1, msg2) {
30
+ const hash = crypto.createHash('sha1');
31
+ hash.update(msg);
32
+ if (msg1) {
33
+ hash.update(msg1);
34
+ }
35
+
36
+ if (msg2) {
37
+ hash.update(msg2);
38
+ }
39
+
40
+ return hash.digest();
41
+ }
42
+
43
+ function xor(a, b) {
44
+ const result = Buffer.allocUnsafe(a.length);
45
+ for (let i = 0; i < a.length; i++) {
46
+ result[i] = a[i] ^ b[i];
47
+ }
48
+ return result;
49
+ }
50
+
51
+ exports.xor = xor;
52
+
53
+ function token(password, scramble1, scramble2) {
54
+ if (!password) {
55
+ return Buffer.alloc(0);
56
+ }
57
+ const stage1 = sha1(password);
58
+ return exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
59
+ }
60
+
61
+ exports.calculateTokenFromPasswordSha = function (
62
+ passwordSha,
63
+ scramble1,
64
+ scramble2
65
+ ) {
66
+ // we use AUTH 41 here, and we need only the bytes we just need.
67
+ const authPluginData1 = scramble1.slice(0, 8);
68
+ const authPluginData2 = scramble2.slice(0, 12);
69
+ const stage2 = sha1(passwordSha);
70
+ const stage3 = sha1(authPluginData1, authPluginData2, stage2);
71
+ return xor(stage3, passwordSha);
72
+ };
73
+
74
+ exports.calculateToken = token;
75
+
76
+ exports.verifyToken = function (publicSeed1, publicSeed2, token, doubleSha) {
77
+ const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
78
+ const candidateHash2 = sha1(hashStage1);
79
+ return candidateHash2.compare(doubleSha) === 0;
80
+ };
81
+
82
+ exports.doubleSha1 = function (password) {
83
+ return sha1(sha1(password));
84
+ };
85
+
86
+ function xorRotating(a, seed) {
87
+ const result = Buffer.allocUnsafe(a.length);
88
+ const seedLen = seed.length;
89
+
90
+ for (let i = 0; i < a.length; i++) {
91
+ result[i] = a[i] ^ seed[i % seedLen];
92
+ }
93
+ return result;
94
+ }
95
+ exports.xorRotating = xorRotating;
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ // https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/
4
+
5
+ const PLUGIN_NAME = 'caching_sha2_password';
6
+ const crypto = require('crypto');
7
+ const { xor, xorRotating } = require('../auth_41');
8
+
9
+ const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
10
+ const FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
11
+ const PERFORM_FULL_AUTHENTICATION_PACKET = Buffer.from([4]);
12
+
13
+ const STATE_INITIAL = 0;
14
+ const STATE_TOKEN_SENT = 1;
15
+ const STATE_WAIT_SERVER_KEY = 2;
16
+ const STATE_FINAL = -1;
17
+
18
+ function sha256(msg) {
19
+ const hash = crypto.createHash('sha256');
20
+ hash.update(msg);
21
+ return hash.digest();
22
+ }
23
+
24
+ function calculateToken(password, scramble) {
25
+ if (!password) {
26
+ return Buffer.alloc(0);
27
+ }
28
+ const stage1 = sha256(Buffer.from(password));
29
+ const stage2 = sha256(stage1);
30
+ const stage3 = sha256(Buffer.concat([stage2, scramble]));
31
+ return xor(stage1, stage3);
32
+ }
33
+
34
+ function encrypt(password, scramble, key) {
35
+ const stage1 = xorRotating(Buffer.from(`${password}\0`, 'utf8'), scramble);
36
+ return crypto.publicEncrypt(
37
+ {
38
+ key,
39
+ padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
40
+ },
41
+ stage1
42
+ );
43
+ }
44
+
45
+ module.exports =
46
+ (pluginOptions = {}) =>
47
+ ({ connection }) => {
48
+ let state = 0;
49
+ let scramble = null;
50
+
51
+ const password = connection.config.password;
52
+
53
+ const authWithKey = (serverKey) => {
54
+ const _password = encrypt(password, scramble, serverKey);
55
+ state = STATE_FINAL;
56
+ return _password;
57
+ };
58
+
59
+ return (data) => {
60
+ switch (state) {
61
+ case STATE_INITIAL:
62
+ scramble = data.slice(0, 20);
63
+ state = STATE_TOKEN_SENT;
64
+ return calculateToken(password, scramble);
65
+
66
+ case STATE_TOKEN_SENT:
67
+ if (FAST_AUTH_SUCCESS_PACKET.equals(data)) {
68
+ state = STATE_FINAL;
69
+ return null;
70
+ }
71
+
72
+ if (PERFORM_FULL_AUTHENTICATION_PACKET.equals(data)) {
73
+ const isSecureConnection =
74
+ typeof pluginOptions.overrideIsSecure === 'undefined'
75
+ ? connection.config.ssl || connection.config.socketPath
76
+ : pluginOptions.overrideIsSecure;
77
+ if (isSecureConnection) {
78
+ state = STATE_FINAL;
79
+ return Buffer.from(`${password}\0`, 'utf8');
80
+ }
81
+
82
+ // if client provides key we can save one extra roundrip on first connection
83
+ if (pluginOptions.serverPublicKey) {
84
+ return authWithKey(pluginOptions.serverPublicKey);
85
+ }
86
+
87
+ state = STATE_WAIT_SERVER_KEY;
88
+ return REQUEST_SERVER_KEY_PACKET;
89
+ }
90
+ throw new Error(
91
+ `Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.`
92
+ );
93
+ case STATE_WAIT_SERVER_KEY:
94
+ if (pluginOptions.onServerPublicKey) {
95
+ pluginOptions.onServerPublicKey(data);
96
+ }
97
+ return authWithKey(data);
98
+ case STATE_FINAL:
99
+ throw new Error(
100
+ `Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
101
+ );
102
+ }
103
+
104
+ throw new Error(
105
+ `Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
106
+ );
107
+ };
108
+ };
@@ -0,0 +1,18 @@
1
+ ##
2
+
3
+ https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html
4
+
5
+ ```js
6
+ const mysql = require('mysql');
7
+ mysql.createConnection({
8
+ authPlugins: {
9
+ caching_sha2_password: mysql.authPlugins.caching_sha2_password({
10
+ onServerPublikKey: function (key) {
11
+ console.log(key);
12
+ },
13
+ serverPublicKey: 'xxxyyy',
14
+ overrideIsSecure: true, //
15
+ }),
16
+ },
17
+ });
18
+ ```
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ caching_sha2_password: require('./caching_sha2_password'),
5
+ mysql_clear_password: require('./mysql_clear_password'),
6
+ mysql_native_password: require('./mysql_native_password'),
7
+ sha256_password: require('./sha256_password'),
8
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ function bufferFromStr(str) {
4
+ return Buffer.from(`${str}\0`);
5
+ }
6
+
7
+ const create_mysql_clear_password_plugin = (pluginOptions) =>
8
+ function mysql_clear_password_plugin({ connection, command }) {
9
+ const password =
10
+ command.password || pluginOptions.password || connection.config.password;
11
+
12
+ return function (/* pluginData */) {
13
+ return bufferFromStr(password);
14
+ };
15
+ };
16
+
17
+ module.exports = create_mysql_clear_password_plugin;
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ //const PLUGIN_NAME = 'mysql_native_password';
4
+ const auth41 = require('../auth_41.js');
5
+
6
+ module.exports =
7
+ (pluginOptions) =>
8
+ ({ connection, command }) => {
9
+ const password =
10
+ command.password || pluginOptions.password || connection.config.password;
11
+ const passwordSha1 =
12
+ command.passwordSha1 ||
13
+ pluginOptions.passwordSha1 ||
14
+ connection.config.passwordSha1;
15
+ return (data) => {
16
+ const authPluginData1 = data.slice(0, 8);
17
+ const authPluginData2 = data.slice(8, 20);
18
+ let authToken;
19
+ if (passwordSha1) {
20
+ authToken = auth41.calculateTokenFromPasswordSha(
21
+ passwordSha1,
22
+ authPluginData1,
23
+ authPluginData2
24
+ );
25
+ } else {
26
+ authToken = auth41.calculateToken(
27
+ password,
28
+ authPluginData1,
29
+ authPluginData2
30
+ );
31
+ }
32
+ return authToken;
33
+ };
34
+ };