@koishijs/plugin-database-mysql 4.0.0-alpha.8 → 4.0.0-beta.2
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/lib/index.d.ts +29 -15
- package/lib/index.js +58 -81
- package/lib/index.js.map +3 -3
- package/package.json +4 -3
package/lib/index.d.ts
CHANGED
|
@@ -7,21 +7,27 @@ declare module 'mysql' {
|
|
|
7
7
|
packet: UntypedFieldInfo;
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
+
declare module 'koishi' {
|
|
11
|
+
interface Database {
|
|
12
|
+
mysql: MysqlDatabase;
|
|
13
|
+
}
|
|
14
|
+
interface Modules {
|
|
15
|
+
'database-mysql': typeof import('.');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
10
18
|
export type TableType = keyof Tables;
|
|
11
19
|
export interface Tables extends Koishi.Tables {
|
|
12
20
|
}
|
|
13
|
-
export interface Config extends PoolConfig {
|
|
14
|
-
}
|
|
15
21
|
declare class MysqlDatabase extends Database {
|
|
16
22
|
ctx: Context;
|
|
17
23
|
pool: Pool;
|
|
18
|
-
config: Config;
|
|
24
|
+
config: MysqlDatabase.Config;
|
|
19
25
|
mysql: this;
|
|
20
26
|
sql: SQLBuilder;
|
|
21
27
|
escape: (value: any, table?: TableType, field?: string) => string;
|
|
22
28
|
escapeId: (value: string) => string;
|
|
23
29
|
inferFields<T extends TableType>(table: T, keys: readonly string[]): (keyof Tables[T])[];
|
|
24
|
-
constructor(ctx: Context, config?: Config);
|
|
30
|
+
constructor(ctx: Context, config?: MysqlDatabase.Config);
|
|
25
31
|
private columns;
|
|
26
32
|
private getColDefs;
|
|
27
33
|
start(): Promise<void>;
|
|
@@ -35,6 +41,25 @@ declare class MysqlDatabase extends Database {
|
|
|
35
41
|
stop(): void;
|
|
36
42
|
}
|
|
37
43
|
declare namespace MysqlDatabase {
|
|
44
|
+
export interface Config extends PoolConfig {
|
|
45
|
+
}
|
|
46
|
+
export const Config: Schema<{
|
|
47
|
+
host?: string;
|
|
48
|
+
port?: number;
|
|
49
|
+
user?: string;
|
|
50
|
+
password?: string;
|
|
51
|
+
database?: string;
|
|
52
|
+
} & {
|
|
53
|
+
[key: string]: any;
|
|
54
|
+
}, {
|
|
55
|
+
host?: string;
|
|
56
|
+
port?: number;
|
|
57
|
+
user?: string;
|
|
58
|
+
password?: string;
|
|
59
|
+
database?: string;
|
|
60
|
+
} & {
|
|
61
|
+
[key: string]: any;
|
|
62
|
+
}>;
|
|
38
63
|
type Declarations = {
|
|
39
64
|
[T in TableType]?: {
|
|
40
65
|
[K in keyof Tables[T]]?: string | (() => string) | Domain<Tables[T][K]>;
|
|
@@ -77,14 +102,3 @@ declare namespace MysqlDatabase {
|
|
|
77
102
|
}
|
|
78
103
|
}
|
|
79
104
|
export default MysqlDatabase;
|
|
80
|
-
declare module 'koishi' {
|
|
81
|
-
interface Database {
|
|
82
|
-
mysql: MysqlDatabase;
|
|
83
|
-
}
|
|
84
|
-
interface Modules {
|
|
85
|
-
'database-mysql': typeof import('.');
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
export const name = "database-mysql";
|
|
89
|
-
export const schema: Schema<Config>;
|
|
90
|
-
export function apply(ctx: Context, config?: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -23,13 +23,10 @@ var __spreadValues = (a, b) => {
|
|
|
23
23
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
24
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
25
25
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
26
|
-
var __require = typeof require !== "undefined" ? require : (x) => {
|
|
27
|
-
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
28
|
-
};
|
|
29
26
|
var __export = (target, all) => {
|
|
30
27
|
__markAsModule(target);
|
|
31
|
-
for (var
|
|
32
|
-
__defProp(target,
|
|
28
|
+
for (var name in all)
|
|
29
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
33
30
|
};
|
|
34
31
|
var __reExport = (target, module2, desc) => {
|
|
35
32
|
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
@@ -45,13 +42,8 @@ var __toModule = (module2) => {
|
|
|
45
42
|
|
|
46
43
|
// plugins/database/mysql/src/index.ts
|
|
47
44
|
__export(exports, {
|
|
48
|
-
|
|
49
|
-
default: () => src_default,
|
|
50
|
-
name: () => name,
|
|
51
|
-
schema: () => schema
|
|
45
|
+
default: () => src_default
|
|
52
46
|
});
|
|
53
|
-
|
|
54
|
-
// plugins/database/mysql/src/database.ts
|
|
55
47
|
var import_mysql = __toModule(require("mysql"));
|
|
56
48
|
var import_koishi = __toModule(require("koishi"));
|
|
57
49
|
var import_sql_utils = __toModule(require("@koishijs/sql-utils"));
|
|
@@ -184,21 +176,21 @@ var MysqlDatabase = class extends import_koishi.Database {
|
|
|
184
176
|
return typeof type === "function" ? `${type()} AS ${key}` : key;
|
|
185
177
|
});
|
|
186
178
|
}
|
|
187
|
-
getColDefs(
|
|
188
|
-
const table = Koishi.Tables.config[
|
|
179
|
+
getColDefs(name, cols = []) {
|
|
180
|
+
const table = Koishi.Tables.config[name];
|
|
189
181
|
const { primary, foreign, autoInc } = table;
|
|
190
182
|
const fields = __spreadValues({}, table.fields);
|
|
191
183
|
const unique = [...table.unique];
|
|
192
|
-
const keys = this.columns[
|
|
193
|
-
if (
|
|
184
|
+
const keys = this.columns[name] || [];
|
|
185
|
+
if (name === "user") {
|
|
194
186
|
const platforms = new Set(this.ctx.bots.map((bot) => bot.platform));
|
|
195
|
-
for (const
|
|
196
|
-
fields[
|
|
197
|
-
unique.push(
|
|
187
|
+
for (const name2 of platforms) {
|
|
188
|
+
fields[name2] = { type: "string", length: 63 };
|
|
189
|
+
unique.push(name2);
|
|
198
190
|
}
|
|
199
191
|
}
|
|
200
|
-
for (const key in MysqlDatabase.tables[
|
|
201
|
-
const value = MysqlDatabase.tables[
|
|
192
|
+
for (const key in MysqlDatabase.tables[name]) {
|
|
193
|
+
const value = MysqlDatabase.tables[name][key];
|
|
202
194
|
if (keys.includes(key) || typeof value === "function")
|
|
203
195
|
continue;
|
|
204
196
|
cols.push(`${(0, import_mysql.escapeId)(key)} ${MysqlDatabase.Domain.definition(value)}`);
|
|
@@ -214,7 +206,7 @@ var MysqlDatabase = class extends import_koishi.Database {
|
|
|
214
206
|
const typedef = getTypeDefinition(fields[key]);
|
|
215
207
|
def += " " + typedef + (nullable ? " " : " not ") + "null";
|
|
216
208
|
if (initial && !typedef.startsWith("text")) {
|
|
217
|
-
def += " default " + escape(initial,
|
|
209
|
+
def += " default " + escape(initial, name, key);
|
|
218
210
|
}
|
|
219
211
|
}
|
|
220
212
|
cols.push(def);
|
|
@@ -238,14 +230,14 @@ var MysqlDatabase = class extends import_koishi.Database {
|
|
|
238
230
|
for (const { TABLE_NAME, COLUMN_NAME } of data) {
|
|
239
231
|
((_a = this.columns)[TABLE_NAME] || (_a[TABLE_NAME] = [])).push(COLUMN_NAME);
|
|
240
232
|
}
|
|
241
|
-
for (const
|
|
242
|
-
const cols = this.getColDefs(
|
|
243
|
-
if (!this.columns[
|
|
244
|
-
logger.info("auto creating table %c",
|
|
245
|
-
await this.query(`CREATE TABLE ?? (${cols.join(",")}) COLLATE = ?`, [
|
|
233
|
+
for (const name in Koishi.Tables.config) {
|
|
234
|
+
const cols = this.getColDefs(name);
|
|
235
|
+
if (!this.columns[name]) {
|
|
236
|
+
logger.info("auto creating table %c", name);
|
|
237
|
+
await this.query(`CREATE TABLE ?? (${cols.join(",")}) COLLATE = ?`, [name, this.config.charset]);
|
|
246
238
|
} else if (cols.length) {
|
|
247
|
-
logger.info("auto updating table %c",
|
|
248
|
-
await this.query(`ALTER TABLE ?? ${cols.map((def) => "ADD " + def).join(",")}`, [
|
|
239
|
+
logger.info("auto updating table %c", name);
|
|
240
|
+
await this.query(`ALTER TABLE ?? ${cols.map((def) => "ADD " + def).join(",")}`, [name]);
|
|
249
241
|
}
|
|
250
242
|
}
|
|
251
243
|
}
|
|
@@ -294,6 +286,13 @@ __name(MysqlDatabase, "MysqlDatabase");
|
|
|
294
286
|
MysqlDatabase.prototype.escape = escape;
|
|
295
287
|
MysqlDatabase.prototype.escapeId = import_mysql.escapeId;
|
|
296
288
|
(function(MysqlDatabase2) {
|
|
289
|
+
MysqlDatabase2.Config = import_koishi.Schema.object({
|
|
290
|
+
host: import_koishi.Schema.string().description("要连接到的主机名。").default("localhost"),
|
|
291
|
+
port: import_koishi.Schema.number().description("要连接到的端口号。").default(3306),
|
|
292
|
+
user: import_koishi.Schema.string().description("要使用的用户名。").default("root"),
|
|
293
|
+
password: import_koishi.Schema.string().description("要使用的密码。"),
|
|
294
|
+
database: import_koishi.Schema.string().description("要访问的数据库名。").default("koishi")
|
|
295
|
+
});
|
|
297
296
|
MysqlDatabase2.tables = {
|
|
298
297
|
user: {},
|
|
299
298
|
channel: {}
|
|
@@ -348,16 +347,10 @@ MysqlDatabase.prototype.escapeId = import_mysql.escapeId;
|
|
|
348
347
|
Domain2.Json = Json;
|
|
349
348
|
})(Domain = MysqlDatabase2.Domain || (MysqlDatabase2.Domain = {}));
|
|
350
349
|
})(MysqlDatabase || (MysqlDatabase = {}));
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
var Koishi2 = __toModule(require("koishi"));
|
|
356
|
-
var src_default = database_default;
|
|
357
|
-
import_koishi2.Database.extend(database_default, {
|
|
358
|
-
async drop(name2) {
|
|
359
|
-
if (name2) {
|
|
360
|
-
await this.query(`DROP TABLE ${this.escapeId(name2)}`);
|
|
350
|
+
import_koishi.Database.extend(MysqlDatabase, {
|
|
351
|
+
async drop(name) {
|
|
352
|
+
if (name) {
|
|
353
|
+
await this.query(`DROP TABLE ${this.escapeId(name)}`);
|
|
361
354
|
} else {
|
|
362
355
|
const data = await this.select("information_schema.tables", ["TABLE_NAME"], "TABLE_SCHEMA = ?", [this.config.database]);
|
|
363
356
|
if (!data.length)
|
|
@@ -365,85 +358,69 @@ import_koishi2.Database.extend(database_default, {
|
|
|
365
358
|
await this.query(data.map(({ TABLE_NAME }) => `DROP TABLE ${this.escapeId(TABLE_NAME)}`).join("; "));
|
|
366
359
|
}
|
|
367
360
|
},
|
|
368
|
-
async get(
|
|
369
|
-
const filter = this.sql.parseQuery(
|
|
361
|
+
async get(name, query, modifier) {
|
|
362
|
+
const filter = this.sql.parseQuery(import_koishi.Query.resolve(name, query));
|
|
370
363
|
if (filter === "0")
|
|
371
364
|
return [];
|
|
372
|
-
const { fields, limit, offset } =
|
|
373
|
-
const keys = this.joinKeys(this.inferFields(
|
|
374
|
-
let sql = `SELECT ${keys} FROM ${
|
|
365
|
+
const { fields, limit, offset } = import_koishi.Query.resolveModifier(modifier);
|
|
366
|
+
const keys = this.joinKeys(this.inferFields(name, fields));
|
|
367
|
+
let sql = `SELECT ${keys} FROM ${name} _${name} WHERE ${filter}`;
|
|
375
368
|
if (limit)
|
|
376
369
|
sql += " LIMIT " + limit;
|
|
377
370
|
if (offset)
|
|
378
371
|
sql += " OFFSET " + offset;
|
|
379
372
|
return this.query(sql);
|
|
380
373
|
},
|
|
381
|
-
async set(
|
|
382
|
-
const filter = this.sql.parseQuery(
|
|
374
|
+
async set(name, query, data) {
|
|
375
|
+
const filter = this.sql.parseQuery(import_koishi.Query.resolve(name, query));
|
|
383
376
|
if (filter === "0")
|
|
384
377
|
return;
|
|
385
378
|
const keys = Object.keys(data);
|
|
386
379
|
const update = keys.map((key) => {
|
|
387
|
-
return `${this.escapeId(key)} = ${this.escape(data[key],
|
|
380
|
+
return `${this.escapeId(key)} = ${this.escape(data[key], name, key)}`;
|
|
388
381
|
}).join(", ");
|
|
389
|
-
await this.query(`UPDATE ${
|
|
382
|
+
await this.query(`UPDATE ${name} SET ${update} WHERE ${filter}`);
|
|
390
383
|
},
|
|
391
|
-
async remove(
|
|
392
|
-
const filter = this.sql.parseQuery(
|
|
384
|
+
async remove(name, query) {
|
|
385
|
+
const filter = this.sql.parseQuery(import_koishi.Query.resolve(name, query));
|
|
393
386
|
if (filter === "0")
|
|
394
387
|
return;
|
|
395
|
-
await this.query("DELETE FROM ?? WHERE " + filter, [
|
|
388
|
+
await this.query("DELETE FROM ?? WHERE " + filter, [name]);
|
|
396
389
|
},
|
|
397
|
-
async create(
|
|
398
|
-
data = __spreadValues(__spreadValues({},
|
|
390
|
+
async create(name, data) {
|
|
391
|
+
data = __spreadValues(__spreadValues({}, Koishi.Tables.create(name)), data);
|
|
399
392
|
const keys = Object.keys(data);
|
|
400
|
-
const header = await this.query(`INSERT INTO ?? (${this.joinKeys(keys)}) VALUES (${keys.map(() => "?").join(", ")})`, [
|
|
393
|
+
const header = await this.query(`INSERT INTO ?? (${this.joinKeys(keys)}) VALUES (${keys.map(() => "?").join(", ")})`, [name, ...this.formatValues(name, data, keys)]);
|
|
401
394
|
return __spreadProps(__spreadValues({}, data), { id: header.insertId });
|
|
402
395
|
},
|
|
403
|
-
async upsert(
|
|
396
|
+
async upsert(name, data, keys) {
|
|
404
397
|
if (!data.length)
|
|
405
398
|
return;
|
|
406
|
-
const { fields, primary } =
|
|
407
|
-
const fallback =
|
|
399
|
+
const { fields, primary } = Koishi.Tables.config[name];
|
|
400
|
+
const fallback = Koishi.Tables.create(name);
|
|
408
401
|
const initKeys = Object.keys(fields);
|
|
409
402
|
const updateKeys = Object.keys(data[0]);
|
|
410
403
|
data = data.map((item) => __spreadValues(__spreadValues({}, fallback), item));
|
|
411
|
-
keys = (0,
|
|
404
|
+
keys = (0, import_koishi.makeArray)(keys || primary);
|
|
412
405
|
const placeholder = `(${initKeys.map(() => "?").join(", ")})`;
|
|
413
|
-
const update = (0,
|
|
406
|
+
const update = (0, import_koishi.difference)(updateKeys, keys).map((key) => {
|
|
414
407
|
key = this.escapeId(key);
|
|
415
408
|
return `${key} = VALUES(${key})`;
|
|
416
409
|
}).join(", ");
|
|
417
|
-
await this.query(`INSERT INTO ${this.escapeId(
|
|
418
|
-
ON DUPLICATE KEY UPDATE ${update}`, [].concat(...data.map((data2) => this.formatValues(
|
|
410
|
+
await this.query(`INSERT INTO ${this.escapeId(name)} (${this.joinKeys(initKeys)}) VALUES ${data.map(() => placeholder).join(", ")}
|
|
411
|
+
ON DUPLICATE KEY UPDATE ${update}`, [].concat(...data.map((data2) => this.formatValues(name, data2, initKeys))));
|
|
419
412
|
},
|
|
420
|
-
async aggregate(
|
|
413
|
+
async aggregate(name, fields, query) {
|
|
421
414
|
const keys = Object.keys(fields);
|
|
422
415
|
if (!keys.length)
|
|
423
416
|
return {};
|
|
424
|
-
const filter = this.sql.parseQuery(
|
|
417
|
+
const filter = this.sql.parseQuery(import_koishi.Query.resolve(name, query));
|
|
425
418
|
const exprs = keys.map((key) => `${this.sql.parseEval(fields[key])} AS ${this.escapeId(key)}`).join(", ");
|
|
426
|
-
const [data] = await this.query(`SELECT ${exprs} FROM ${
|
|
419
|
+
const [data] = await this.query(`SELECT ${exprs} FROM ${name} WHERE ${filter}`);
|
|
427
420
|
return data;
|
|
428
421
|
}
|
|
429
422
|
});
|
|
430
|
-
var
|
|
431
|
-
var schema = import_koishi2.Schema.object({
|
|
432
|
-
host: import_koishi2.Schema.string("要连接到的主机名。").default("localhost"),
|
|
433
|
-
port: import_koishi2.Schema.number("要连接到的端口号。").default(3306),
|
|
434
|
-
user: import_koishi2.Schema.string("要使用的用户名。").default("root"),
|
|
435
|
-
password: import_koishi2.Schema.string("要使用的密码。"),
|
|
436
|
-
database: import_koishi2.Schema.string("要访问的数据库名。").default("koishi")
|
|
437
|
-
}, true);
|
|
438
|
-
function apply(ctx, config = {}) {
|
|
439
|
-
config = import_koishi2.Schema.validate(config, schema);
|
|
440
|
-
ctx.database = new database_default(ctx, config);
|
|
441
|
-
}
|
|
442
|
-
__name(apply, "apply");
|
|
423
|
+
var src_default = MysqlDatabase;
|
|
443
424
|
// Annotate the CommonJS export names for ESM import in node:
|
|
444
|
-
0 && (module.exports = {
|
|
445
|
-
apply,
|
|
446
|
-
name,
|
|
447
|
-
schema
|
|
448
|
-
});
|
|
425
|
+
0 && (module.exports = {});
|
|
449
426
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts"
|
|
4
|
-
"sourcesContent": ["import MysqlDatabase, { Config } from './database'\nimport { Database, Context, Query, makeArray, difference, Schema } from 'koishi'\nimport { OkPacket } from 'mysql'\nimport * as Koishi from 'koishi'\n\nexport * from './database'\nexport default MysqlDatabase\n\ndeclare module 'koishi' {\n interface Database {\n mysql: MysqlDatabase\n }\n\n interface Modules {\n 'database-mysql': typeof import('.')\n }\n}\n\nDatabase.extend(MysqlDatabase, {\n async drop(name) {\n if (name) {\n await this.query(`DROP TABLE ${this.escapeId(name)}`)\n } else {\n const data = await this.select('information_schema.tables', ['TABLE_NAME'], 'TABLE_SCHEMA = ?', [this.config.database])\n if (!data.length) return\n await this.query(data.map(({ TABLE_NAME }) => `DROP TABLE ${this.escapeId(TABLE_NAME)}`).join('; '))\n }\n },\n\n async get(name, query, modifier) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return []\n const { fields, limit, offset } = Query.resolveModifier(modifier)\n const keys = this.joinKeys(this.inferFields(name, fields))\n let sql = `SELECT ${keys} FROM ${name} _${name} WHERE ${filter}`\n if (limit) sql += ' LIMIT ' + limit\n if (offset) sql += ' OFFSET ' + offset\n return this.query(sql)\n },\n\n async set(name, query, data) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return\n const keys = Object.keys(data)\n const update = keys.map((key) => {\n return `${this.escapeId(key)} = ${this.escape(data[key], name, key)}`\n }).join(', ')\n await this.query(`UPDATE ${name} SET ${update} WHERE ${filter}`)\n },\n\n async remove(name, query) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return\n await this.query('DELETE FROM ?? WHERE ' + filter, [name])\n },\n\n async create(name, data) {\n data = { ...Koishi.Tables.create(name), ...data }\n const keys = Object.keys(data)\n const header = await this.query<OkPacket>(\n `INSERT INTO ?? (${this.joinKeys(keys)}) VALUES (${keys.map(() => '?').join(', ')})`,\n [name, ...this.formatValues(name, data, keys)],\n )\n return { ...data, id: header.insertId } as any\n },\n\n async upsert(name, data, keys: string | string[]) {\n if (!data.length) return\n const { fields, primary } = Koishi.Tables.config[name]\n const fallback = Koishi.Tables.create(name)\n const initKeys = Object.keys(fields)\n const updateKeys = Object.keys(data[0])\n data = data.map(item => ({ ...fallback, ...item }))\n keys = makeArray(keys || primary)\n const placeholder = `(${initKeys.map(() => '?').join(', ')})`\n const update = difference(updateKeys, keys).map((key) => {\n key = this.escapeId(key)\n return `${key} = VALUES(${key})`\n }).join(', ')\n await this.query(\n `INSERT INTO ${this.escapeId(name)} (${this.joinKeys(initKeys)}) VALUES ${data.map(() => placeholder).join(', ')}\n ON DUPLICATE KEY UPDATE ${update}`,\n [].concat(...data.map(data => this.formatValues(name, data, initKeys))),\n )\n },\n\n async aggregate(name, fields, query) {\n const keys = Object.keys(fields)\n if (!keys.length) return {}\n\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n const exprs = keys.map(key => `${this.sql.parseEval(fields[key])} AS ${this.escapeId(key)}`).join(', ')\n const [data] = await this.query(`SELECT ${exprs} FROM ${name} WHERE ${filter}`)\n return data\n },\n})\n\nexport const name = 'database-mysql'\n\nexport const schema: Schema<Config> = Schema.object({\n host: Schema.string('要连接到的主机名。').default('localhost'),\n port: Schema.number('要连接到的端口号。').default(3306),\n user: Schema.string('要使用的用户名。').default('root'),\n password: Schema.string('要使用的密码。'),\n database: Schema.string('要访问的数据库名。').default('koishi'),\n}, true)\n\nexport function apply(ctx: Context, config: Config = {}) {\n config = Schema.validate(config, schema)\n ctx.database = new MysqlDatabase(ctx, config)\n}\n", "import { createPool, Pool, PoolConfig, escape as mysqlEscape, escapeId, format, TypeCast } from 'mysql'\nimport { Context, Database, Logger, makeArray } from 'koishi'\nimport { SQLBuilder } from '@koishijs/sql-utils'\nimport * as Koishi from 'koishi'\nimport { types } from 'util'\n\ndeclare module 'mysql' {\n interface UntypedFieldInfo {\n packet: UntypedFieldInfo\n }\n}\n\nconst logger = new Logger('mysql')\n\nexport type TableType = keyof Tables\n\nexport interface Tables extends Koishi.Tables {}\n\nexport interface Config extends PoolConfig {}\n\nfunction stringify(value: any, table?: string, field?: string) {\n const type = MysqlDatabase.tables[table]?.[field]\n if (typeof type === 'object') return type.stringify(value)\n\n const meta = Koishi.Tables.config[table]?.fields[field]\n if (meta?.type === 'json') {\n return JSON.stringify(value)\n } else if (meta?.type === 'list') {\n return value.join(',')\n }\n\n return value\n}\n\nfunction escape(value: any, table?: string, field?: string) {\n return mysqlEscape(stringify(value, table, field))\n}\n\nfunction getIntegerType(length = 11) {\n if (length <= 4) return 'tinyint'\n if (length <= 6) return 'smallint'\n if (length <= 9) return 'mediumint'\n if (length <= 11) return 'int'\n return 'bigint'\n}\n\nfunction getTypeDefinition({ type, length, precision, scale }: Koishi.Tables.Field) {\n switch (type) {\n case 'float':\n case 'double':\n case 'date':\n case 'time':\n case 'timestamp': return type\n case 'integer': return getIntegerType(length)\n case 'unsigned': return `${getIntegerType(length)} unsigned`\n case 'decimal': return `decimal(${precision}, ${scale}) unsigned`\n case 'char': return `char(${length || 255})`\n case 'string': return `char(${length || 255})`\n case 'text': return `text(${length || 65535})`\n case 'list': return `text(${length || 65535})`\n case 'json': return `text(${length || 65535})`\n }\n}\n\nfunction createIndex(keys: string | string[]) {\n return makeArray(keys).map(key => escapeId(key)).join(', ')\n}\n\nclass MysqlDatabase extends Database {\n public pool: Pool\n public config: Config\n\n mysql = this\n sql: SQLBuilder\n\n escape: (value: any, table?: TableType, field?: string) => string\n escapeId: (value: string) => string\n\n inferFields<T extends TableType>(table: T, keys: readonly string[]) {\n if (!keys) return\n const types = MysqlDatabase.tables[table] || {}\n return keys.map((key) => {\n const type = types[key]\n return typeof type === 'function' ? `${type()} AS ${key}` : key\n }) as (keyof Tables[T])[]\n }\n\n constructor(public ctx: Context, config?: Config) {\n super(ctx)\n this.config = {\n host: 'localhost',\n port: 3306,\n user: 'root',\n database: 'koishi',\n charset: 'utf8mb4_general_ci',\n multipleStatements: true,\n typeCast: (field, next) => {\n const { orgName, orgTable } = field.packet\n const type = MysqlDatabase.tables[orgTable]?.[orgName]\n if (typeof type === 'object') return type.parse(field)\n\n const meta = Koishi.Tables.config[orgTable]?.fields[orgName]\n if (meta?.type === 'string') {\n return field.string()\n } else if (meta?.type === 'json') {\n return JSON.parse(field.string()) || meta.initial\n } else if (meta?.type === 'list') {\n const source = field.string()\n return source ? source.split(',') : []\n }\n\n if (field.type === 'BIT') {\n return Boolean(field.buffer()?.readUInt8(0))\n } else {\n return next()\n }\n },\n ...config,\n }\n\n this.sql = new class extends SQLBuilder {\n escape = escape\n escapeId = escapeId\n }()\n }\n\n private columns: Record<string, string[]> = {}\n\n private getColDefs(name: string, cols: string[] = []) {\n const table = Koishi.Tables.config[name]\n const { primary, foreign, autoInc } = table\n const fields = { ...table.fields }\n const unique = [...table.unique]\n const keys = this.columns[name] || []\n\n // create platform rows\n if (name === 'user') {\n const platforms = new Set<string>(this.ctx.bots.map(bot => bot.platform))\n for (const name of platforms) {\n fields[name] = { type: 'string', length: 63 }\n unique.push(name)\n }\n }\n\n // mysql definitions (FIXME: remove in v4)\n for (const key in MysqlDatabase.tables[name]) {\n const value = MysqlDatabase.tables[name][key]\n if (keys.includes(key) || typeof value === 'function') continue\n cols.push(`${escapeId(key)} ${MysqlDatabase.Domain.definition(value)}`)\n }\n\n // orm definitions\n for (const key in fields) {\n if (keys.includes(key)) continue\n const { initial, nullable = initial === undefined || initial === null } = fields[key]\n let def = escapeId(key)\n if (key === primary && autoInc) {\n def += ' int unsigned not null auto_increment'\n } else {\n const typedef = getTypeDefinition(fields[key])\n def += ' ' + typedef + (nullable ? ' ' : ' not ') + 'null'\n // blob, text, geometry or json columns cannot have default values\n if (initial && !typedef.startsWith('text')) {\n def += ' default ' + escape(initial, name, key)\n }\n }\n cols.push(def)\n }\n\n if (!keys.length) {\n cols.push(`primary key (${createIndex(primary)})`)\n for (const key of unique) {\n cols.push(`unique index (${createIndex(key)})`)\n }\n for (const key in foreign) {\n const [table, key2] = foreign[key]\n cols.push(`foreign key (${escapeId(key)}) references ${escapeId(table)} (${escapeId(key2)})`)\n }\n }\n\n return cols\n }\n\n async start() {\n this.pool = createPool(this.config)\n const data = await this.query<any[]>('SELECT TABLE_NAME, COLUMN_NAME from information_schema.columns WHERE TABLE_SCHEMA = ?', [this.config.database])\n for (const { TABLE_NAME, COLUMN_NAME } of data) {\n (this.columns[TABLE_NAME] ||= []).push(COLUMN_NAME)\n }\n\n for (const name in Koishi.Tables.config) {\n const cols = this.getColDefs(name)\n if (!this.columns[name]) {\n logger.info('auto creating table %c', name)\n await this.query(`CREATE TABLE ?? (${cols.join(',')}) COLLATE = ?`, [name, this.config.charset])\n } else if (cols.length) {\n logger.info('auto updating table %c', name)\n await this.query(`ALTER TABLE ?? ${cols.map(def => 'ADD ' + def).join(',')}`, [name])\n }\n }\n }\n\n joinKeys = (keys: readonly string[]) => {\n return keys ? keys.map(key => key.includes('`') ? key : `\\`${key}\\``).join(',') : '*'\n }\n\n $in = (table: TableType, key: string, values: readonly any[]) => {\n return `${this.escapeId(key)} IN (${values.map(val => this.escape(val, table, key)).join(', ')})`\n }\n\n formatValues = (table: string, data: object, keys: readonly string[]) => {\n return keys.map((key) => {\n if (typeof data[key] !== 'object' || types.isDate(data[key])) return data[key]\n return stringify(data[key], table as never, key)\n })\n }\n\n query<T extends {}>(source: string, values?: any): Promise<T>\n query<T extends {}>(source: string[], values?: any): Promise<T>\n async query<T extends {}>(source: string | string[], values?: any): Promise<T> {\n if (Array.isArray(source)) {\n if (this.config.multipleStatements) {\n return this.query(source.join(';'), values)\n } else {\n const result: any = []\n for (const sql of source) {\n result.push(await this.query(sql, values))\n }\n return result\n }\n }\n\n const error = new Error()\n return new Promise((resolve, reject) => {\n const sql = format(source, values)\n logger.debug('[sql]', sql)\n this.pool.query(sql, (err, results) => {\n if (!err) return resolve(results)\n logger.warn(sql)\n err.stack = err.message + error.stack.slice(7)\n if (err.code === 'ER_DUP_ENTRY') {\n err[Symbol.for('koishi.error-type')] = 'duplicate-entry'\n }\n reject(err)\n })\n })\n }\n\n select<T extends {}>(table: string, fields: readonly (string & keyof T)[], conditional?: string, values?: readonly any[]): Promise<T[]>\n select(table: string, fields: string[], conditional?: string, values: readonly any[] = []) {\n logger.debug(`[select] ${table}: ${fields ? fields.join(', ') : '*'}`)\n const sql = 'SELECT '\n + this.joinKeys(fields)\n + (table.includes('.') ? `FROM ${table}` : ' FROM `' + table + `\\` _${table}`)\n + (conditional ? ' WHERE ' + conditional : '')\n return this.query(sql, values)\n }\n\n async count<K extends TableType>(table: K, conditional?: string) {\n const [{ 'COUNT(*)': count }] = await this.query(`SELECT COUNT(*) FROM ?? ${conditional ? 'WHERE ' + conditional : ''}`, [table])\n return count as number\n }\n\n stop() {\n this.pool.end()\n }\n}\n\nMysqlDatabase.prototype.escape = escape\nMysqlDatabase.prototype.escapeId = escapeId\n\nnamespace MysqlDatabase {\n type Declarations = {\n [T in TableType]?: {\n [K in keyof Tables[T]]?: string | (() => string) | Domain<Tables[T][K]>\n }\n }\n\n /**\n * @deprecated use `import('koishi').Field` instead\n */\n export const tables: Declarations = {\n user: {},\n channel: {},\n }\n\n type FieldInfo = Parameters<Exclude<TypeCast, boolean>>[0]\n\n export interface Domain<T = any> {\n definition: string\n parse(source: FieldInfo): T\n stringify(value: T): string\n }\n\n /**\n * @deprecated use `import('koishi').Field` instead\n */\n export namespace Domain {\n export function definition(domain: string | Domain) {\n return typeof domain === 'string' ? domain : domain.definition\n }\n\n export class String implements Domain<string> {\n constructor(public definition = 'TEXT') {}\n\n parse(field: FieldInfo) {\n return field.string()\n }\n\n stringify(value: any) {\n return value\n }\n }\n\n export class Array implements Domain<string[]> {\n constructor(public definition = 'TEXT') {}\n\n parse(field: FieldInfo) {\n const source = field.string()\n return source ? source.split(',') : []\n }\n\n stringify(value: string[]) {\n return value.join(',')\n }\n }\n\n export class Json implements Domain {\n // mysql does not support text column with default value\n constructor(public definition = 'text', private defaultValue?: any) {}\n\n parse(field: FieldInfo) {\n return JSON.parse(field.string()) || this.defaultValue\n }\n\n stringify(value: any) {\n return JSON.stringify(value)\n }\n }\n }\n}\n\nexport default MysqlDatabase\n"],
|
|
5
|
-
"mappings": "
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { createPool, Pool, PoolConfig, escape as mysqlEscape, escapeId, format, TypeCast } from 'mysql'\nimport { Context, Database, difference, Logger, makeArray, Schema, Query } from 'koishi'\nimport { SQLBuilder } from '@koishijs/sql-utils'\nimport * as Koishi from 'koishi'\nimport { types } from 'util'\nimport { OkPacket } from 'mysql'\n\ndeclare module 'mysql' {\n interface UntypedFieldInfo {\n packet: UntypedFieldInfo\n }\n}\n\ndeclare module 'koishi' {\n interface Database {\n mysql: MysqlDatabase\n }\n\n interface Modules {\n 'database-mysql': typeof import('.')\n }\n}\n\nconst logger = new Logger('mysql')\n\nexport type TableType = keyof Tables\n\nexport interface Tables extends Koishi.Tables {}\n\nfunction stringify(value: any, table?: string, field?: string) {\n const type = MysqlDatabase.tables[table]?.[field]\n if (typeof type === 'object') return type.stringify(value)\n\n const meta = Koishi.Tables.config[table]?.fields[field]\n if (meta?.type === 'json') {\n return JSON.stringify(value)\n } else if (meta?.type === 'list') {\n return value.join(',')\n }\n\n return value\n}\n\nfunction escape(value: any, table?: string, field?: string) {\n return mysqlEscape(stringify(value, table, field))\n}\n\nfunction getIntegerType(length = 11) {\n if (length <= 4) return 'tinyint'\n if (length <= 6) return 'smallint'\n if (length <= 9) return 'mediumint'\n if (length <= 11) return 'int'\n return 'bigint'\n}\n\nfunction getTypeDefinition({ type, length, precision, scale }: Koishi.Tables.Field) {\n switch (type) {\n case 'float':\n case 'double':\n case 'date':\n case 'time':\n case 'timestamp': return type\n case 'integer': return getIntegerType(length)\n case 'unsigned': return `${getIntegerType(length)} unsigned`\n case 'decimal': return `decimal(${precision}, ${scale}) unsigned`\n case 'char': return `char(${length || 255})`\n case 'string': return `char(${length || 255})`\n case 'text': return `text(${length || 65535})`\n case 'list': return `text(${length || 65535})`\n case 'json': return `text(${length || 65535})`\n }\n}\n\nfunction createIndex(keys: string | string[]) {\n return makeArray(keys).map(key => escapeId(key)).join(', ')\n}\n\nclass MysqlDatabase extends Database {\n public pool: Pool\n public config: MysqlDatabase.Config\n\n mysql = this\n sql: SQLBuilder\n\n escape: (value: any, table?: TableType, field?: string) => string\n escapeId: (value: string) => string\n\n inferFields<T extends TableType>(table: T, keys: readonly string[]) {\n if (!keys) return\n const types = MysqlDatabase.tables[table] || {}\n return keys.map((key) => {\n const type = types[key]\n return typeof type === 'function' ? `${type()} AS ${key}` : key\n }) as (keyof Tables[T])[]\n }\n\n constructor(public ctx: Context, config?: MysqlDatabase.Config) {\n super(ctx)\n this.config = {\n host: 'localhost',\n port: 3306,\n user: 'root',\n database: 'koishi',\n charset: 'utf8mb4_general_ci',\n multipleStatements: true,\n typeCast: (field, next) => {\n const { orgName, orgTable } = field.packet\n const type = MysqlDatabase.tables[orgTable]?.[orgName]\n if (typeof type === 'object') return type.parse(field)\n\n const meta = Koishi.Tables.config[orgTable]?.fields[orgName]\n if (meta?.type === 'string') {\n return field.string()\n } else if (meta?.type === 'json') {\n return JSON.parse(field.string()) || meta.initial\n } else if (meta?.type === 'list') {\n const source = field.string()\n return source ? source.split(',') : []\n }\n\n if (field.type === 'BIT') {\n return Boolean(field.buffer()?.readUInt8(0))\n } else {\n return next()\n }\n },\n ...config,\n }\n\n this.sql = new class extends SQLBuilder {\n escape = escape\n escapeId = escapeId\n }()\n }\n\n private columns: Record<string, string[]> = {}\n\n private getColDefs(name: string, cols: string[] = []) {\n const table = Koishi.Tables.config[name]\n const { primary, foreign, autoInc } = table\n const fields = { ...table.fields }\n const unique = [...table.unique]\n const keys = this.columns[name] || []\n\n // create platform rows\n if (name === 'user') {\n const platforms = new Set<string>(this.ctx.bots.map(bot => bot.platform))\n for (const name of platforms) {\n fields[name] = { type: 'string', length: 63 }\n unique.push(name)\n }\n }\n\n // mysql definitions (FIXME: remove in v4)\n for (const key in MysqlDatabase.tables[name]) {\n const value = MysqlDatabase.tables[name][key]\n if (keys.includes(key) || typeof value === 'function') continue\n cols.push(`${escapeId(key)} ${MysqlDatabase.Domain.definition(value)}`)\n }\n\n // orm definitions\n for (const key in fields) {\n if (keys.includes(key)) continue\n const { initial, nullable = initial === undefined || initial === null } = fields[key]\n let def = escapeId(key)\n if (key === primary && autoInc) {\n def += ' int unsigned not null auto_increment'\n } else {\n const typedef = getTypeDefinition(fields[key])\n def += ' ' + typedef + (nullable ? ' ' : ' not ') + 'null'\n // blob, text, geometry or json columns cannot have default values\n if (initial && !typedef.startsWith('text')) {\n def += ' default ' + escape(initial, name, key)\n }\n }\n cols.push(def)\n }\n\n if (!keys.length) {\n cols.push(`primary key (${createIndex(primary)})`)\n for (const key of unique) {\n cols.push(`unique index (${createIndex(key)})`)\n }\n for (const key in foreign) {\n const [table, key2] = foreign[key]\n cols.push(`foreign key (${escapeId(key)}) references ${escapeId(table)} (${escapeId(key2)})`)\n }\n }\n\n return cols\n }\n\n async start() {\n this.pool = createPool(this.config)\n const data = await this.query<any[]>('SELECT TABLE_NAME, COLUMN_NAME from information_schema.columns WHERE TABLE_SCHEMA = ?', [this.config.database])\n for (const { TABLE_NAME, COLUMN_NAME } of data) {\n (this.columns[TABLE_NAME] ||= []).push(COLUMN_NAME)\n }\n\n for (const name in Koishi.Tables.config) {\n const cols = this.getColDefs(name)\n if (!this.columns[name]) {\n logger.info('auto creating table %c', name)\n await this.query(`CREATE TABLE ?? (${cols.join(',')}) COLLATE = ?`, [name, this.config.charset])\n } else if (cols.length) {\n logger.info('auto updating table %c', name)\n await this.query(`ALTER TABLE ?? ${cols.map(def => 'ADD ' + def).join(',')}`, [name])\n }\n }\n }\n\n joinKeys = (keys: readonly string[]) => {\n return keys ? keys.map(key => key.includes('`') ? key : `\\`${key}\\``).join(',') : '*'\n }\n\n $in = (table: TableType, key: string, values: readonly any[]) => {\n return `${this.escapeId(key)} IN (${values.map(val => this.escape(val, table, key)).join(', ')})`\n }\n\n formatValues = (table: string, data: object, keys: readonly string[]) => {\n return keys.map((key) => {\n if (typeof data[key] !== 'object' || types.isDate(data[key])) return data[key]\n return stringify(data[key], table as never, key)\n })\n }\n\n query<T extends {}>(source: string, values?: any): Promise<T>\n query<T extends {}>(source: string[], values?: any): Promise<T>\n async query<T extends {}>(source: string | string[], values?: any): Promise<T> {\n if (Array.isArray(source)) {\n if (this.config.multipleStatements) {\n return this.query(source.join(';'), values)\n } else {\n const result: any = []\n for (const sql of source) {\n result.push(await this.query(sql, values))\n }\n return result\n }\n }\n\n const error = new Error()\n return new Promise((resolve, reject) => {\n const sql = format(source, values)\n logger.debug('[sql]', sql)\n this.pool.query(sql, (err, results) => {\n if (!err) return resolve(results)\n logger.warn(sql)\n err.stack = err.message + error.stack.slice(7)\n if (err.code === 'ER_DUP_ENTRY') {\n err[Symbol.for('koishi.error-type')] = 'duplicate-entry'\n }\n reject(err)\n })\n })\n }\n\n select<T extends {}>(table: string, fields: readonly (string & keyof T)[], conditional?: string, values?: readonly any[]): Promise<T[]>\n select(table: string, fields: string[], conditional?: string, values: readonly any[] = []) {\n logger.debug(`[select] ${table}: ${fields ? fields.join(', ') : '*'}`)\n const sql = 'SELECT '\n + this.joinKeys(fields)\n + (table.includes('.') ? `FROM ${table}` : ' FROM `' + table + `\\` _${table}`)\n + (conditional ? ' WHERE ' + conditional : '')\n return this.query(sql, values)\n }\n\n async count<K extends TableType>(table: K, conditional?: string) {\n const [{ 'COUNT(*)': count }] = await this.query(`SELECT COUNT(*) FROM ?? ${conditional ? 'WHERE ' + conditional : ''}`, [table])\n return count as number\n }\n\n stop() {\n this.pool.end()\n }\n}\n\nMysqlDatabase.prototype.escape = escape\nMysqlDatabase.prototype.escapeId = escapeId\n\nnamespace MysqlDatabase {\n export interface Config extends PoolConfig {}\n\n export const Config = Schema.object({\n host: Schema.string().description('要连接到的主机名。').default('localhost'),\n port: Schema.number().description('要连接到的端口号。').default(3306),\n user: Schema.string().description('要使用的用户名。').default('root'),\n password: Schema.string().description('要使用的密码。'),\n database: Schema.string().description('要访问的数据库名。').default('koishi'),\n })\n\n type Declarations = {\n [T in TableType]?: {\n [K in keyof Tables[T]]?: string | (() => string) | Domain<Tables[T][K]>\n }\n }\n\n /**\n * @deprecated use `import('koishi').Field` instead\n */\n export const tables: Declarations = {\n user: {},\n channel: {},\n }\n\n type FieldInfo = Parameters<Exclude<TypeCast, boolean>>[0]\n\n export interface Domain<T = any> {\n definition: string\n parse(source: FieldInfo): T\n stringify(value: T): string\n }\n\n /**\n * @deprecated use `import('koishi').Field` instead\n */\n export namespace Domain {\n export function definition(domain: string | Domain) {\n return typeof domain === 'string' ? domain : domain.definition\n }\n\n export class String implements Domain<string> {\n constructor(public definition = 'TEXT') {}\n\n parse(field: FieldInfo) {\n return field.string()\n }\n\n stringify(value: any) {\n return value\n }\n }\n\n export class Array implements Domain<string[]> {\n constructor(public definition = 'TEXT') {}\n\n parse(field: FieldInfo) {\n const source = field.string()\n return source ? source.split(',') : []\n }\n\n stringify(value: string[]) {\n return value.join(',')\n }\n }\n\n export class Json implements Domain {\n // mysql does not support text column with default value\n constructor(public definition = 'text', private defaultValue?: any) {}\n\n parse(field: FieldInfo) {\n return JSON.parse(field.string()) || this.defaultValue\n }\n\n stringify(value: any) {\n return JSON.stringify(value)\n }\n }\n }\n}\n\nDatabase.extend(MysqlDatabase, {\n async drop(name) {\n if (name) {\n await this.query(`DROP TABLE ${this.escapeId(name)}`)\n } else {\n const data = await this.select('information_schema.tables', ['TABLE_NAME'], 'TABLE_SCHEMA = ?', [this.config.database])\n if (!data.length) return\n await this.query(data.map(({ TABLE_NAME }) => `DROP TABLE ${this.escapeId(TABLE_NAME)}`).join('; '))\n }\n },\n\n async get(name, query, modifier) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return []\n const { fields, limit, offset } = Query.resolveModifier(modifier)\n const keys = this.joinKeys(this.inferFields(name, fields))\n let sql = `SELECT ${keys} FROM ${name} _${name} WHERE ${filter}`\n if (limit) sql += ' LIMIT ' + limit\n if (offset) sql += ' OFFSET ' + offset\n return this.query(sql)\n },\n\n async set(name, query, data) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return\n const keys = Object.keys(data)\n const update = keys.map((key) => {\n return `${this.escapeId(key)} = ${this.escape(data[key], name, key)}`\n }).join(', ')\n await this.query(`UPDATE ${name} SET ${update} WHERE ${filter}`)\n },\n\n async remove(name, query) {\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n if (filter === '0') return\n await this.query('DELETE FROM ?? WHERE ' + filter, [name])\n },\n\n async create(name, data) {\n data = { ...Koishi.Tables.create(name), ...data }\n const keys = Object.keys(data)\n const header = await this.query<OkPacket>(\n `INSERT INTO ?? (${this.joinKeys(keys)}) VALUES (${keys.map(() => '?').join(', ')})`,\n [name, ...this.formatValues(name, data, keys)],\n )\n return { ...data, id: header.insertId } as any\n },\n\n async upsert(name, data, keys: string | string[]) {\n if (!data.length) return\n const { fields, primary } = Koishi.Tables.config[name]\n const fallback = Koishi.Tables.create(name)\n const initKeys = Object.keys(fields)\n const updateKeys = Object.keys(data[0])\n data = data.map(item => ({ ...fallback, ...item }))\n keys = makeArray(keys || primary)\n const placeholder = `(${initKeys.map(() => '?').join(', ')})`\n const update = difference(updateKeys, keys).map((key) => {\n key = this.escapeId(key)\n return `${key} = VALUES(${key})`\n }).join(', ')\n await this.query(\n `INSERT INTO ${this.escapeId(name)} (${this.joinKeys(initKeys)}) VALUES ${data.map(() => placeholder).join(', ')}\n ON DUPLICATE KEY UPDATE ${update}`,\n [].concat(...data.map(data => this.formatValues(name, data, initKeys))),\n )\n },\n\n async aggregate(name, fields, query) {\n const keys = Object.keys(fields)\n if (!keys.length) return {}\n\n const filter = this.sql.parseQuery(Query.resolve(name, query))\n const exprs = keys.map(key => `${this.sql.parseEval(fields[key])} AS ${this.escapeId(key)}`).join(', ')\n const [data] = await this.query(`SELECT ${exprs} FROM ${name} WHERE ${filter}`)\n return data\n },\n})\n\nexport default MysqlDatabase\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koishijs/plugin-database-mysql",
|
|
3
3
|
"description": "MySQL support for Koishi",
|
|
4
|
-
"version": "4.0.0-
|
|
4
|
+
"version": "4.0.0-beta.2",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"lib"
|
|
9
9
|
],
|
|
10
|
-
"author": "Shigma <
|
|
10
|
+
"author": "Shigma <shigma10826@gmail.com>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"scripts": {
|
|
13
13
|
"lint": "eslint src --ext .ts"
|
|
@@ -31,9 +31,10 @@
|
|
|
31
31
|
"mysql"
|
|
32
32
|
],
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"koishi": "^4.0.0-
|
|
34
|
+
"koishi": "^4.0.0-beta.3"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@koishijs/sql-utils": "^1.0.0-beta.2",
|
|
37
38
|
"@types/mysql": "^2.15.19",
|
|
38
39
|
"mysql": "^2.18.1"
|
|
39
40
|
}
|