@e-mc/db 0.13.9 → 0.14.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.
- package/README.md +14 -9
- package/index.js +50 -34
- package/package.json +4 -4
- package/pool.js +8 -6
- package/util.js +16 -15
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @e-mc/db
|
|
2
2
|
|
|
3
|
-
* NodeJS
|
|
3
|
+
* NodeJS 20 (Minimum 18)
|
|
4
4
|
* ES2022
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.14.0/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { DbDataSource } from "./squared";
|
|
@@ -18,7 +18,7 @@ import type { IHost } from "./index";
|
|
|
18
18
|
import type { ClientDbConstructor, IClientDb } from "./core";
|
|
19
19
|
import type { BatchQueryResult, DB_TYPE, ErrorQueryCallback, ExecuteBatchQueryOptions, ExecuteQueryOptions, HandleFailOptions, ProcessRowsOptions, QueryResult, SQL_COMMAND } from "./db";
|
|
20
20
|
import type { AuthValue } from "./http";
|
|
21
|
-
import type { DbCoerceSettings, DbModule, DbSourceOptions, PoolConfig } from "./settings";
|
|
21
|
+
import type { DbCoerceSettings, DbModule, DbSettings, DbSourceOptions, PoolConfig } from "./settings";
|
|
22
22
|
|
|
23
23
|
import type { SecureContextOptions } from "node:tls";
|
|
24
24
|
|
|
@@ -56,6 +56,8 @@ interface IDb extends IClientDb<IHost, DbModule, DbDataSource, DbSourceOptions,
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
interface DbConstructor extends ClientDbConstructor<IHost> {
|
|
59
|
+
readonly HASH_ALGORITHM: string;
|
|
60
|
+
loadSettings(settings: Settings & { db?: DbSettings }, password?: string): boolean;
|
|
59
61
|
setPoolConfig(value: Record<string, PoolConfig>): void;
|
|
60
62
|
getPoolConfig(source: string): Required<PoolConfig> | undefined;
|
|
61
63
|
readonly prototype: IDb;
|
|
@@ -126,7 +128,10 @@ interface DbModule {
|
|
|
126
128
|
settings?: {
|
|
127
129
|
broadcast_id?: string | string[];
|
|
128
130
|
users?: Record<string, Record<string, unknown>>;
|
|
129
|
-
|
|
131
|
+
cache?: {
|
|
132
|
+
dir?: string;
|
|
133
|
+
algorithm?: string;
|
|
134
|
+
};
|
|
130
135
|
session_expires?: number;
|
|
131
136
|
user_key?: Record<string, DbSourceOptions>;
|
|
132
137
|
imports?: StringMap;
|
|
@@ -214,11 +219,11 @@ const [rows1, rows2] = await instance.executeBatchQuery([
|
|
|
214
219
|
|
|
215
220
|
## References
|
|
216
221
|
|
|
217
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
218
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
219
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
220
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
221
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
222
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/squared.d.ts
|
|
223
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/core.d.ts
|
|
224
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/db.d.ts
|
|
225
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/http.d.ts
|
|
226
|
+
- https://www.unpkg.com/@e-mc/types@0.14.0/lib/settings.d.ts
|
|
222
227
|
|
|
223
228
|
* https://www.npmjs.com/package/@types/node
|
|
224
229
|
|
package/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { DB_TYPE, IMPORT_MAP, coerceObject, createAbortError, errorMessage, getAlgorithm, isArray, isError, isObject, isPlainObject, isString } = require('@e-mc/types');
|
|
5
|
+
const { ClientDb } = require('@e-mc/core');
|
|
6
|
+
const Request = require('@e-mc/request');
|
|
7
|
+
const { SQL_COMMAND } = require('@e-mc/db/util');
|
|
7
8
|
const kDb = Symbol.for('db:constructor');
|
|
8
9
|
const DB_CLIENT = new Map();
|
|
9
10
|
const POOL_CONFIG = new Map();
|
|
11
|
+
let HASH_ALGORITHM = 'sha256';
|
|
10
12
|
function sanitizePoolConfig(value) {
|
|
11
13
|
value.min ??= -1;
|
|
12
14
|
value.max ??= -1;
|
|
@@ -20,10 +22,23 @@ function sanitizePoolConfig(value) {
|
|
|
20
22
|
value.socket_timeout ??= -1;
|
|
21
23
|
return value;
|
|
22
24
|
}
|
|
23
|
-
class Db extends
|
|
25
|
+
class Db extends ClientDb {
|
|
24
26
|
static [kDb] = true;
|
|
25
27
|
static STORE_RESULT_PARTITION_SIZE = 16;
|
|
26
28
|
static STORE_RESULT_PARTITION_MULT = 2;
|
|
29
|
+
static get HASH_ALGORITHM() {
|
|
30
|
+
return HASH_ALGORITHM;
|
|
31
|
+
}
|
|
32
|
+
static loadSettings(settings, password) {
|
|
33
|
+
if (this.enabled("process.password") && !super.loadSettings({ process: settings.process }, password)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const algorithm = getAlgorithm(settings.db?.cache?.algorithm);
|
|
37
|
+
if (algorithm) {
|
|
38
|
+
HASH_ALGORITHM = algorithm;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
27
42
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
28
43
|
let result = 0;
|
|
29
44
|
if (percent > 0 && percent <= 1) {
|
|
@@ -46,7 +61,7 @@ class Db extends core_1.ClientDb {
|
|
|
46
61
|
static setPoolConfig(value) {
|
|
47
62
|
for (const name in value) {
|
|
48
63
|
const source = value[name];
|
|
49
|
-
if (
|
|
64
|
+
if (isPlainObject(source)) {
|
|
50
65
|
POOL_CONFIG.set(name, sanitizePoolConfig(source));
|
|
51
66
|
}
|
|
52
67
|
}
|
|
@@ -61,7 +76,7 @@ class Db extends core_1.ClientDb {
|
|
|
61
76
|
return this.getClient(item.source).setCredential.call(this, item);
|
|
62
77
|
}
|
|
63
78
|
catch (err) {
|
|
64
|
-
if (err
|
|
79
|
+
if (isError(err)) {
|
|
65
80
|
throw err;
|
|
66
81
|
}
|
|
67
82
|
throw new Error("Invalid credentials", { cause: err });
|
|
@@ -73,9 +88,9 @@ class Db extends core_1.ClientDb {
|
|
|
73
88
|
credential = this.module[item.source]?.[credential];
|
|
74
89
|
stored = true;
|
|
75
90
|
}
|
|
76
|
-
if (
|
|
91
|
+
if (isPlainObject(credential)) {
|
|
77
92
|
if (this.settingsOf(item.source, 'coerce', 'credential') === true) {
|
|
78
|
-
|
|
93
|
+
coerceObject(credential, stored);
|
|
79
94
|
}
|
|
80
95
|
return stored ? item.credential = { ...credential } : credential;
|
|
81
96
|
}
|
|
@@ -96,13 +111,13 @@ class Db extends core_1.ClientDb {
|
|
|
96
111
|
const item = items[i];
|
|
97
112
|
const command = item.withCommand;
|
|
98
113
|
if (command) {
|
|
99
|
-
if (!settings && !
|
|
114
|
+
if (!settings && !isPlainObject(settings = this.getUserSettings()?.[item.source]?.commands)) {
|
|
100
115
|
return;
|
|
101
116
|
}
|
|
102
117
|
let name, table;
|
|
103
118
|
const [group, procedure] = Array.isArray(command) ? command : ({ name, table } = item, [(name || table ? name && table ? name + ':' + table : table || name : typeof item.document === 'string' && item.document) || '', command]);
|
|
104
119
|
const data = settings[group]?.[procedure];
|
|
105
|
-
if (
|
|
120
|
+
if (isPlainObject(data)) {
|
|
106
121
|
if ('uri' in data) {
|
|
107
122
|
delete data.uri;
|
|
108
123
|
}
|
|
@@ -119,7 +134,7 @@ class Db extends core_1.ClientDb {
|
|
|
119
134
|
}
|
|
120
135
|
async executeQuery(item, options) {
|
|
121
136
|
if (this.aborted) {
|
|
122
|
-
return
|
|
137
|
+
return createAbortError(true);
|
|
123
138
|
}
|
|
124
139
|
if (typeof options === 'function') {
|
|
125
140
|
options = { errorQuery: options };
|
|
@@ -128,7 +143,7 @@ class Db extends core_1.ClientDb {
|
|
|
128
143
|
}
|
|
129
144
|
async executeBatchQuery(batch, options, outResult) {
|
|
130
145
|
if (this.aborted) {
|
|
131
|
-
return
|
|
146
|
+
return createAbortError(true);
|
|
132
147
|
}
|
|
133
148
|
if (typeof options === 'function') {
|
|
134
149
|
options = { errorQuery: options };
|
|
@@ -137,7 +152,7 @@ class Db extends core_1.ClientDb {
|
|
|
137
152
|
}
|
|
138
153
|
async processRows(batch, tasks, parallel, outResult) {
|
|
139
154
|
let disconnect;
|
|
140
|
-
if (
|
|
155
|
+
if (isObject(parallel)) {
|
|
141
156
|
({ disconnect, parallel } = parallel);
|
|
142
157
|
}
|
|
143
158
|
const terminate = () => {
|
|
@@ -213,7 +228,7 @@ class Db extends core_1.ClientDb {
|
|
|
213
228
|
}
|
|
214
229
|
async commit(items) {
|
|
215
230
|
if (this.aborted) {
|
|
216
|
-
return
|
|
231
|
+
return createAbortError(true);
|
|
217
232
|
}
|
|
218
233
|
const tasks = (items || this.pending).map(async (data) => {
|
|
219
234
|
data.ignoreCache ??= true;
|
|
@@ -225,32 +240,32 @@ class Db extends core_1.ClientDb {
|
|
|
225
240
|
return tasks.length === 0 ? false : this.allSettled(tasks, ["Execute unassigned queries", this.moduleName]).then(result => result.length > 0).catch(() => false);
|
|
226
241
|
}
|
|
227
242
|
readTLSCert(value, cache) {
|
|
228
|
-
if (
|
|
229
|
-
if (
|
|
243
|
+
if (isString(value)) {
|
|
244
|
+
if (Request.isCert(value)) {
|
|
230
245
|
return value.trim();
|
|
231
246
|
}
|
|
232
247
|
const pathname = path.resolve(value);
|
|
233
248
|
if (Db.isPath(pathname) && this.canRead(pathname, { ownPermissionOnly: true })) {
|
|
234
|
-
return
|
|
249
|
+
return Request.readCACert(pathname, cache);
|
|
235
250
|
}
|
|
236
251
|
}
|
|
237
252
|
return '';
|
|
238
253
|
}
|
|
239
254
|
readTLSConfig(options, cache = true) {
|
|
240
|
-
if (
|
|
255
|
+
if (isPlainObject(options)) {
|
|
241
256
|
const { ca, cert, key } = options;
|
|
242
257
|
if (ca) {
|
|
243
|
-
options.ca = this.#
|
|
258
|
+
options.ca = this.#checkTLSCert(ca);
|
|
244
259
|
}
|
|
245
260
|
if (cert) {
|
|
246
|
-
options.cert = this.#
|
|
261
|
+
options.cert = this.#checkTLSCert(cert);
|
|
247
262
|
}
|
|
248
263
|
if (key) {
|
|
249
|
-
if (
|
|
264
|
+
if (isString(key)) {
|
|
250
265
|
options.key = this.readTLSCert(key, cache);
|
|
251
266
|
}
|
|
252
|
-
else if (
|
|
253
|
-
options.key = key.map(item =>
|
|
267
|
+
else if (isArray(key)) {
|
|
268
|
+
options.key = key.map(item => isString(item) ? { pem: this.readTLSCert(item, cache) } : Buffer.isBuffer(item) ? { pem: item.toString('utf8') } : item).filter(item => item.pem);
|
|
254
269
|
}
|
|
255
270
|
}
|
|
256
271
|
}
|
|
@@ -258,7 +273,7 @@ class Db extends core_1.ClientDb {
|
|
|
258
273
|
resolveSource(source, folder) {
|
|
259
274
|
let result;
|
|
260
275
|
if (!source.startsWith('@')) {
|
|
261
|
-
result = this.settings.imports?.[source] ||
|
|
276
|
+
result = this.settings.imports?.[source] || IMPORT_MAP[source];
|
|
262
277
|
}
|
|
263
278
|
else if (!folder && !source.includes('/')) {
|
|
264
279
|
folder = 'client';
|
|
@@ -302,23 +317,24 @@ class Db extends core_1.ClientDb {
|
|
|
302
317
|
}
|
|
303
318
|
catch {
|
|
304
319
|
}
|
|
305
|
-
throw
|
|
320
|
+
throw errorMessage(source, "Database provider not found");
|
|
306
321
|
}
|
|
307
|
-
#
|
|
322
|
+
#checkTLSCert(items, cache) {
|
|
308
323
|
if (Array.isArray(items)) {
|
|
309
|
-
return items.map(cert =>
|
|
324
|
+
return items.map(cert => isString(cert) ? this.readTLSCert(cert, cache) : Buffer.isBuffer(cert) ? cert : null).filter(cert => cert);
|
|
310
325
|
}
|
|
311
|
-
if (
|
|
326
|
+
if (isString(items)) {
|
|
312
327
|
return this.readTLSCert(items, cache);
|
|
313
328
|
}
|
|
314
329
|
}
|
|
315
330
|
get sourceType() {
|
|
316
|
-
return
|
|
331
|
+
return DB_TYPE;
|
|
317
332
|
}
|
|
318
333
|
get commandType() {
|
|
319
|
-
return
|
|
334
|
+
return SQL_COMMAND;
|
|
320
335
|
}
|
|
321
336
|
}
|
|
322
|
-
Object.freeze(
|
|
323
|
-
Object.freeze(
|
|
337
|
+
Object.freeze(DB_TYPE);
|
|
338
|
+
Object.freeze(SQL_COMMAND);
|
|
339
|
+
|
|
324
340
|
module.exports = Db;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "DB modules for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/core": "0.
|
|
23
|
-
"@e-mc/request": "0.
|
|
24
|
-
"@e-mc/types": "0.
|
|
22
|
+
"@e-mc/core": "0.14.0",
|
|
23
|
+
"@e-mc/request": "0.14.0",
|
|
24
|
+
"@e-mc/types": "0.14.0"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/pool.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
2
|
+
|
|
3
|
+
const { randomUUID } = require('node:crypto');
|
|
4
|
+
const { validateUUID } = require('@e-mc/types');
|
|
5
|
+
const { setUUIDKey } = require('@e-mc/db/util');
|
|
5
6
|
class DbPool {
|
|
6
7
|
client;
|
|
7
8
|
poolKey;
|
|
@@ -9,7 +10,7 @@ class DbPool {
|
|
|
9
10
|
static CACHE_UNUSED = [];
|
|
10
11
|
static CACHE_IGNORE = [];
|
|
11
12
|
static asString(credential) {
|
|
12
|
-
return
|
|
13
|
+
return randomUUID();
|
|
13
14
|
}
|
|
14
15
|
static canCache(credential) {
|
|
15
16
|
if (credential.uuidKey) {
|
|
@@ -64,7 +65,7 @@ class DbPool {
|
|
|
64
65
|
return null;
|
|
65
66
|
}
|
|
66
67
|
static validateKey(pools, username, uuidKey) {
|
|
67
|
-
if (
|
|
68
|
+
if (validateUUID(uuidKey)) {
|
|
68
69
|
for (const key in pools) {
|
|
69
70
|
const pool = pools[key];
|
|
70
71
|
const auth = pool.uuidKey;
|
|
@@ -107,7 +108,7 @@ class DbPool {
|
|
|
107
108
|
add(item, uuidKey) {
|
|
108
109
|
this.#items.add(item);
|
|
109
110
|
if (uuidKey ||= this.uuidKey?.password) {
|
|
110
|
-
|
|
111
|
+
setUUIDKey(item, uuidKey);
|
|
111
112
|
}
|
|
112
113
|
this.lastAccessed = Date.now();
|
|
113
114
|
return this;
|
|
@@ -171,4 +172,5 @@ class DbPool {
|
|
|
171
172
|
this.#parent = value;
|
|
172
173
|
}
|
|
173
174
|
}
|
|
175
|
+
|
|
174
176
|
module.exports = DbPool;
|
package/util.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.
|
|
6
|
-
exports.setUUIDKey = setUUIDKey;
|
|
7
|
-
const types_1 = require("@e-mc/types");
|
|
8
|
-
const util_1 = require("@e-mc/request/util");
|
|
9
|
-
Object.defineProperty(exports, "getBasicAuth", { enumerable: true, get: function () { return util_1.getBasicAuth; } });
|
|
10
|
-
Object.defineProperty(exports, "hasBasicAuth", { enumerable: true, get: function () { return util_1.hasBasicAuth; } });
|
|
11
|
-
var SQL_COMMAND;
|
|
2
|
+
|
|
3
|
+
const { isObject, isPlainObject, isString } = require('@e-mc/types');
|
|
4
|
+
const { getBasicAuth, hasBasicAuth } = require('@e-mc/request/util');
|
|
5
|
+
exports.SQL_COMMAND = void 0;
|
|
12
6
|
(function (SQL_COMMAND) {
|
|
13
7
|
SQL_COMMAND[SQL_COMMAND["SELECT"] = 1] = "SELECT";
|
|
14
8
|
SQL_COMMAND[SQL_COMMAND["INSERT"] = 2] = "INSERT";
|
|
15
9
|
SQL_COMMAND[SQL_COMMAND["UPDATE"] = 3] = "UPDATE";
|
|
16
10
|
SQL_COMMAND[SQL_COMMAND["DELETE"] = 4] = "DELETE";
|
|
17
|
-
})(SQL_COMMAND || (exports.SQL_COMMAND =
|
|
11
|
+
})(exports.SQL_COMMAND || (exports.SQL_COMMAND = {}));
|
|
18
12
|
function parseServerAuth(credential, port, all) {
|
|
19
13
|
if (typeof port === 'boolean') {
|
|
20
14
|
all = port;
|
|
@@ -84,7 +78,7 @@ function parseConnectionString(value, scheme = 'http') {
|
|
|
84
78
|
}
|
|
85
79
|
try {
|
|
86
80
|
const { protocol, username, password, hostname, pathname, port, search } = new URL(value);
|
|
87
|
-
const database = pathname.
|
|
81
|
+
const database = pathname.slice(1);
|
|
88
82
|
return { protocol, username: decodeURIComponent(username), password: decodeURIComponent(password), hostname, port, database: decodeURIComponent(/^([^?/#]+)/.exec(database)?.[1] || database), pathname, search };
|
|
89
83
|
}
|
|
90
84
|
catch {
|
|
@@ -92,13 +86,20 @@ function parseConnectionString(value, scheme = 'http') {
|
|
|
92
86
|
}
|
|
93
87
|
}
|
|
94
88
|
function checkEmpty(value) {
|
|
95
|
-
return value === undefined || value === null ? false : value === 0 || (value instanceof Set || value instanceof Map ? value.size === 0 : (Array.isArray(value) ||
|
|
89
|
+
return value === undefined || value === null ? false : value === 0 || (value instanceof Set || value instanceof Map ? value.size === 0 : (Array.isArray(value) || isObject(value)) && value.length === 0);
|
|
96
90
|
}
|
|
97
91
|
function setUUIDKey(item, value) {
|
|
98
|
-
if (
|
|
99
|
-
if (!
|
|
92
|
+
if (isString(value)) {
|
|
93
|
+
if (!isPlainObject(item.credential)) {
|
|
100
94
|
item.credential = {};
|
|
101
95
|
}
|
|
102
96
|
item.credential.uuidKey ||= value;
|
|
103
97
|
}
|
|
104
98
|
}
|
|
99
|
+
|
|
100
|
+
exports.checkEmpty = checkEmpty;
|
|
101
|
+
exports.getBasicAuth = getBasicAuth;
|
|
102
|
+
exports.hasBasicAuth = hasBasicAuth;
|
|
103
|
+
exports.parseConnectionString = parseConnectionString;
|
|
104
|
+
exports.parseServerAuth = parseServerAuth;
|
|
105
|
+
exports.setUUIDKey = setUUIDKey;
|