@minatojs/driver-mysql
Advanced tools
Comparing version 1.3.0 to 2.0.0
import type { Pool, PoolConfig } from 'mysql'; | ||
import { Dict } from 'cosmokit'; | ||
import { Database, Driver, Eval, Executable, Model, Modifier } from '@minatojs/core'; | ||
import { Database, Driver, Eval, Field, Model, Selection } from '@minatojs/core'; | ||
import { Builder } from '@minatojs/sql-utils'; | ||
@@ -11,8 +11,4 @@ declare module 'mysql' { | ||
declare class MySQLBuilder extends Builder { | ||
private models; | ||
constructor(models: Dict<Model>); | ||
format(sql: string, values: any[], stringifyObjects?: boolean, timeZone?: string): string; | ||
escapeId(value: string, forbidQualified?: boolean): string; | ||
escape(value: any, table?: string, field?: string): string; | ||
stringify(value: any, table?: string, field?: string): any; | ||
constructor(tables: Dict<Model>); | ||
escape(value: any, field?: Field<any>): string; | ||
} | ||
@@ -34,5 +30,4 @@ declare namespace MySQLDriver { | ||
prepare(name: string): Promise<any>; | ||
_inferFields(table: string, keys: readonly string[]): readonly string[]; | ||
_joinKeys: (keys: readonly string[]) => string; | ||
_formatValues: (table: string, data: object, keys: readonly string[]) => any[]; | ||
_formatValues: (table: string, data: object, keys: readonly string[]) => string; | ||
query<T = any>(sql: string, values?: any): Promise<T>; | ||
@@ -44,10 +39,10 @@ queue<T = any>(sql: string, values?: any): Promise<T>; | ||
stats(): Promise<Driver.Stats>; | ||
get(sel: Executable, modifier: Modifier): Promise<any>; | ||
eval(sel: Executable, expr: Eval.Expr): Promise<any>; | ||
get(sel: Selection.Immutable): Promise<any>; | ||
eval(sel: Selection.Immutable, expr: Eval.Expr): Promise<any>; | ||
private toUpdateExpr; | ||
set(sel: Executable, data: {}): Promise<void>; | ||
remove(sel: Executable): Promise<void>; | ||
create(sel: Executable, data: {}): Promise<any>; | ||
upsert(sel: Executable, data: any[], keys: string[]): Promise<void>; | ||
set(sel: Selection.Mutable, data: {}): Promise<void>; | ||
remove(sel: Selection.Mutable): Promise<void>; | ||
create(sel: Selection.Mutable, data: {}): Promise<any>; | ||
upsert(sel: Selection.Mutable, data: any[], keys: string[]): Promise<void>; | ||
} | ||
export default MySQLDriver; |
122
lib/index.js
@@ -81,35 +81,20 @@ var __create = Object.create; | ||
__name(getTypeDefinition, "getTypeDefinition"); | ||
function backtick(str) { | ||
return "`" + str + "`"; | ||
} | ||
__name(backtick, "backtick"); | ||
function createIndex(keys) { | ||
return (0, import_cosmokit.makeArray)(keys).map(backtick).join(", "); | ||
return (0, import_cosmokit.makeArray)(keys).map(import_sql_utils.escapeId).join(", "); | ||
} | ||
__name(createIndex, "createIndex"); | ||
var MySQLBuilder = class extends import_sql_utils.Builder { | ||
constructor(models) { | ||
super(); | ||
this.models = models; | ||
constructor(tables) { | ||
super(tables); | ||
this.define({ | ||
types: ["list"], | ||
dump: (value) => value.join(","), | ||
load: (value) => value ? value.split(",") : [] | ||
}); | ||
} | ||
format(sql, values, stringifyObjects, timeZone) { | ||
return (0, import_mysql.format)(sql, values, stringifyObjects, timeZone); | ||
} | ||
escapeId(value, forbidQualified) { | ||
return (0, import_mysql.escapeId)(value, forbidQualified); | ||
} | ||
escape(value, table, field) { | ||
return (0, import_mysql.escape)(this.stringify(value, table, field)); | ||
} | ||
stringify(value, table, field) { | ||
var _a; | ||
const meta = (_a = this.models[table]) == null ? void 0 : _a.fields[field]; | ||
if ((meta == null ? void 0 : meta.type) === "json") { | ||
return JSON.stringify(value); | ||
} else if ((meta == null ? void 0 : meta.type) === "list") { | ||
return value.join(","); | ||
} else if (import_core.Field.date.includes(meta == null ? void 0 : meta.type)) { | ||
return import_cosmokit.Time.template("yyyy-MM-dd hh:mm:ss", value); | ||
escape(value, field) { | ||
if (value instanceof Date) { | ||
value = import_cosmokit.Time.template("yyyy-MM-dd hh:mm:ss", value); | ||
} | ||
return value; | ||
return super.escape(value, field); | ||
} | ||
@@ -126,3 +111,7 @@ }; | ||
this._formatValues = (table, data, keys) => { | ||
return keys.map((key) => this.sql.stringify(data[key], table, key)); | ||
return keys.map((key) => { | ||
var _a; | ||
const field = (_a = this.database.tables[table]) == null ? void 0 : _a.fields[key]; | ||
return this.sql.escape(data[key], field); | ||
}).join(", "); | ||
}; | ||
@@ -184,3 +173,3 @@ this.config = { | ||
const { initial, nullable = true } = fields[key]; | ||
let def = backtick(key); | ||
let def = (0, import_sql_utils.escapeId)(key); | ||
if (key === primary && autoInc) { | ||
@@ -197,3 +186,3 @@ def += " int unsigned not null auto_increment"; | ||
if (initial && !typedef.startsWith("text")) { | ||
def += " default " + this.sql.escape(initial, name, key); | ||
def += " default " + this.sql.escape(initial, fields[key]); | ||
} | ||
@@ -211,3 +200,3 @@ } | ||
const [table2, key2] = foreign[key]; | ||
create.push(`foreign key (${backtick(key)}) references ${(0, import_mysql.escapeId)(table2)} (${backtick(key2)})`); | ||
create.push(`foreign key (${(0, import_sql_utils.escapeId)(key)}) references ${(0, import_sql_utils.escapeId)(table2)} (${(0, import_sql_utils.escapeId)(key2)})`); | ||
} | ||
@@ -250,7 +239,2 @@ } | ||
} | ||
_inferFields(table, keys) { | ||
if (!keys) | ||
return; | ||
return keys; | ||
} | ||
query(sql, values) { | ||
@@ -308,3 +292,3 @@ const error = new Error(); | ||
return; | ||
await this.query(data.map(({ TABLE_NAME }) => `DROP TABLE ${this.sql.escapeId(TABLE_NAME)}`).join("; ")); | ||
await this.query(data.map(({ TABLE_NAME }) => `DROP TABLE ${(0, import_sql_utils.escapeId)(TABLE_NAME)}`).join("; ")); | ||
} | ||
@@ -320,16 +304,8 @@ async stats() { | ||
} | ||
async get(sel, modifier) { | ||
const { table, fields, query, model } = sel; | ||
const filter = this.sql.parseQuery(query); | ||
if (filter === "0") | ||
async get(sel) { | ||
const { model, tables } = sel; | ||
const builder = new MySQLBuilder(tables); | ||
const sql = builder.get(sel); | ||
if (!sql) | ||
return []; | ||
const { limit, offset, sort } = modifier; | ||
const keys = this._joinKeys(this._inferFields(table, fields ? Object.keys(fields) : null)); | ||
let sql = `SELECT ${keys} FROM ${table} _${table} WHERE ${filter}`; | ||
if (sort.length) | ||
sql += " ORDER BY " + sort.map(([key, order]) => `${backtick(key["$"][1])} ${order}`).join(", "); | ||
if (limit < Infinity) | ||
sql += " LIMIT " + limit; | ||
if (offset > 0) | ||
sql += " OFFSET " + offset; | ||
return this.queue(sql).then((data) => { | ||
@@ -340,13 +316,18 @@ return data.map((row) => model.parse(row)); | ||
async eval(sel, expr) { | ||
const { table, query } = sel; | ||
const filter = this.sql.parseQuery(query); | ||
const output = this.sql.parseEval(expr); | ||
const [data] = await this.queue(`SELECT ${output} AS value FROM ${table} WHERE ${filter}`); | ||
let sql = this.sql.get(sel.table); | ||
const prefix = `SELECT ${output} AS value `; | ||
if (sql.startsWith("SELECT * ")) { | ||
sql = prefix + sql.slice(9); | ||
} else { | ||
sql = `${prefix}FROM (${sql}) ${sql.ref}`; | ||
} | ||
const [data] = await this.queue(sql); | ||
return data.value; | ||
} | ||
toUpdateExpr(table, item, field, upsert) { | ||
const escaped = backtick(field); | ||
toUpdateExpr(item, field, upsert) { | ||
const escaped = (0, import_sql_utils.escapeId)(field); | ||
if (field in item) { | ||
if ((0, import_core.isEvalExpr)(item[field]) || !upsert) { | ||
return this.sql.parseEval(item[field], table, field); | ||
return this.sql.parseEval(item[field]); | ||
} else { | ||
@@ -380,4 +361,4 @@ return `VALUES(${escaped})`; | ||
const update = updateFields.map((field) => { | ||
const escaped = backtick(field); | ||
return `${escaped} = ${this.toUpdateExpr(table, data, field, false)}`; | ||
const escaped = (0, import_sql_utils.escapeId)(field); | ||
return `${escaped} = ${this.toUpdateExpr(data, field, false)}`; | ||
}).join(", "); | ||
@@ -395,9 +376,9 @@ await this.query(`UPDATE ${table} SET ${update} WHERE ${filter}`); | ||
const { table, model } = sel; | ||
const formatted = model.format(data); | ||
const { autoInc, primary } = model; | ||
const formatted = this.sql.dump(model, data); | ||
const keys = Object.keys(formatted); | ||
const header = await this.query( | ||
`INSERT INTO ?? (${this._joinKeys(keys)}) VALUES (${keys.map(() => "?").join(", ")})`, | ||
[table, ...this._formatValues(table, formatted, keys)] | ||
); | ||
const header = await this.query([ | ||
`INSERT INTO ${(0, import_sql_utils.escapeId)(table)} (${keys.map(import_sql_utils.escapeId).join(", ")})`, | ||
`VALUES (${keys.map((key) => this.sql.escape(formatted[key])).join(", ")})` | ||
].join(" ")); | ||
if (!autoInc) | ||
@@ -433,7 +414,7 @@ return data; | ||
const update = updateFields.map((field) => { | ||
const escaped = backtick(field); | ||
const escaped = (0, import_sql_utils.escapeId)(field); | ||
const branches = {}; | ||
data.forEach((item) => { | ||
var _a, _b; | ||
((_b = branches[_a = this.toUpdateExpr(table, item, field, true)]) != null ? _b : branches[_a] = []).push(item); | ||
((_b = branches[_a = this.toUpdateExpr(item, field, true)]) != null ? _b : branches[_a] = []).push(item); | ||
}); | ||
@@ -447,8 +428,7 @@ const entries = Object.entries(branches).map(([expr, items]) => [createMultiFilter(items), expr]).sort(([a], [b]) => a.length - b.length).reverse(); | ||
}).join(", "); | ||
const placeholder = `(${initFields.map(() => "?").join(", ")})`; | ||
await this.query( | ||
`INSERT INTO ${this.sql.escapeId(table)} (${this._joinKeys(initFields)}) VALUES ${data.map(() => placeholder).join(", ")} | ||
ON DUPLICATE KEY UPDATE ${update}`, | ||
[].concat(...insertion.map((item) => this._formatValues(table, item, initFields))) | ||
); | ||
await this.query([ | ||
`INSERT INTO ${(0, import_sql_utils.escapeId)(table)} (${initFields.map(import_sql_utils.escapeId).join(", ")})`, | ||
`VALUES (${insertion.map((item) => this._formatValues(table, item, initFields)).join("), (")})`, | ||
`ON DUPLICATE KEY UPDATE ${update}` | ||
].join(" ")); | ||
} | ||
@@ -455,0 +435,0 @@ }; |
{ | ||
"name": "@minatojs/driver-mysql", | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"description": "MySQL Driver for Minato", | ||
@@ -28,6 +28,6 @@ "main": "lib/index.js", | ||
"peerDependencies": { | ||
"@minatojs/core": "^1.3.0" | ||
"@minatojs/core": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@minatojs/tests": "^1.2.0", | ||
"@minatojs/tests": "^1.3.0", | ||
"@types/mysql": "^2.15.21" | ||
@@ -38,5 +38,5 @@ }, | ||
"@vlasky/mysql": "^2.18.5", | ||
"cosmokit": "^1.2.1", | ||
"reggol": "^1.1.0" | ||
"cosmokit": "^1.3.3", | ||
"reggol": "^1.3.1" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44723
471
+ Added@minatojs/core@2.9.0(transitive)
Updatedcosmokit@^1.3.3
Updatedreggol@^1.3.1