@bunnykit/orm 0.1.22 → 0.1.23
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/dist/src/connection/Connection.d.ts +1 -0
- package/dist/src/connection/Connection.js +26 -5
- package/dist/src/migration/Migrator.js +10 -10
- package/dist/src/model/Model.js +6 -5
- package/dist/src/query/Builder.d.ts +1 -0
- package/dist/src/query/Builder.js +28 -8
- package/dist/src/query/grammars/MySqlGrammar.js +1 -1
- package/dist/src/query/grammars/PostgresGrammar.js +1 -1
- package/dist/src/query/grammars/SQLiteGrammar.js +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ export class Connection {
|
|
|
10
10
|
schema;
|
|
11
11
|
ownsDriver;
|
|
12
12
|
transactionDepth = 0;
|
|
13
|
+
savepointId = 0;
|
|
13
14
|
constructor(config, options = {}) {
|
|
14
15
|
this.config = config;
|
|
15
16
|
this.schema = options.schema || ("schema" in config ? config.schema : undefined);
|
|
@@ -83,16 +84,36 @@ export class Connection {
|
|
|
83
84
|
return await this.driver.unsafe(sqlString, bindings);
|
|
84
85
|
}
|
|
85
86
|
async beginTransaction() {
|
|
86
|
-
|
|
87
|
+
if (this.transactionDepth === 0) {
|
|
88
|
+
await this.driver.unsafe("BEGIN");
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
await this.driver.unsafe(`SAVEPOINT bunny_trans_${++this.savepointId}`);
|
|
92
|
+
}
|
|
87
93
|
this.transactionDepth++;
|
|
88
94
|
}
|
|
89
95
|
async commit() {
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
if (this.transactionDepth <= 0)
|
|
97
|
+
return;
|
|
98
|
+
if (this.transactionDepth === 1) {
|
|
99
|
+
await this.driver.unsafe("COMMIT");
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
await this.driver.unsafe(`RELEASE SAVEPOINT bunny_trans_${this.savepointId--}`);
|
|
103
|
+
}
|
|
104
|
+
this.transactionDepth--;
|
|
92
105
|
}
|
|
93
106
|
async rollback() {
|
|
94
|
-
|
|
95
|
-
|
|
107
|
+
if (this.transactionDepth <= 0)
|
|
108
|
+
return;
|
|
109
|
+
if (this.transactionDepth === 1) {
|
|
110
|
+
await this.driver.unsafe("ROLLBACK");
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
await this.driver.unsafe(`ROLLBACK TO SAVEPOINT bunny_trans_${this.savepointId}`);
|
|
114
|
+
await this.driver.unsafe(`RELEASE SAVEPOINT bunny_trans_${this.savepointId--}`);
|
|
115
|
+
}
|
|
116
|
+
this.transactionDepth--;
|
|
96
117
|
}
|
|
97
118
|
isInTransaction() {
|
|
98
119
|
return this.transactionDepth > 0;
|
|
@@ -195,30 +195,30 @@ export class Migrator {
|
|
|
195
195
|
const statements = [];
|
|
196
196
|
for (const row of tables) {
|
|
197
197
|
const table = row[key];
|
|
198
|
-
const createRows = await this.connection.query(`SHOW CREATE TABLE ${table}`);
|
|
198
|
+
const createRows = await this.connection.query(`SHOW CREATE TABLE ${this.connection.getGrammar().wrap(table)}`);
|
|
199
199
|
statements.push(`${createRows[0]["Create Table"]};`);
|
|
200
200
|
}
|
|
201
201
|
return statements.join("\n\n") + "\n";
|
|
202
202
|
}
|
|
203
203
|
const schema = this.connection.getSchema() || "public";
|
|
204
|
-
const tables = await this.connection.query(
|
|
204
|
+
const tables = await this.connection.query("SELECT table_name FROM information_schema.tables WHERE table_schema = $1 AND table_type = 'BASE TABLE' ORDER BY table_name", [schema]);
|
|
205
205
|
const statements = [];
|
|
206
206
|
for (const tableRow of tables) {
|
|
207
207
|
const table = tableRow.table_name;
|
|
208
208
|
const columns = await this.connection.query(`SELECT column_name, data_type, is_nullable, column_default, character_maximum_length, numeric_precision, numeric_scale
|
|
209
209
|
FROM information_schema.columns
|
|
210
|
-
WHERE table_schema =
|
|
211
|
-
ORDER BY ordinal_position
|
|
210
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
211
|
+
ORDER BY ordinal_position`, [schema, table]);
|
|
212
212
|
const primaryKeys = await this.connection.query(`SELECT kcu.column_name
|
|
213
213
|
FROM information_schema.table_constraints tc
|
|
214
214
|
JOIN information_schema.key_column_usage kcu
|
|
215
215
|
ON tc.constraint_name = kcu.constraint_name
|
|
216
216
|
AND tc.table_schema = kcu.table_schema
|
|
217
217
|
AND tc.table_name = kcu.table_name
|
|
218
|
-
WHERE tc.table_schema =
|
|
219
|
-
AND tc.table_name =
|
|
218
|
+
WHERE tc.table_schema = $1
|
|
219
|
+
AND tc.table_name = $2
|
|
220
220
|
AND tc.constraint_type = 'PRIMARY KEY'
|
|
221
|
-
ORDER BY kcu.ordinal_position
|
|
221
|
+
ORDER BY kcu.ordinal_position`, [schema, table]);
|
|
222
222
|
const pkColumns = primaryKeys.map((row) => row.column_name);
|
|
223
223
|
const columnSql = columns.map((column) => {
|
|
224
224
|
let type = String(column.data_type).toUpperCase();
|
|
@@ -228,7 +228,7 @@ export class Migrator {
|
|
|
228
228
|
else if ((type === "NUMERIC" || type === "DECIMAL") && column.numeric_precision) {
|
|
229
229
|
type = `${type}(${column.numeric_precision}${column.numeric_scale ? `, ${column.numeric_scale}` : ""})`;
|
|
230
230
|
}
|
|
231
|
-
let sql = `
|
|
231
|
+
let sql = ` ${this.connection.getGrammar().wrap(column.column_name)} ${type}`;
|
|
232
232
|
if (column.is_nullable === "NO")
|
|
233
233
|
sql += " NOT NULL";
|
|
234
234
|
if (column.column_default !== null && column.column_default !== undefined)
|
|
@@ -236,9 +236,9 @@ export class Migrator {
|
|
|
236
236
|
return sql;
|
|
237
237
|
});
|
|
238
238
|
if (pkColumns.length > 0) {
|
|
239
|
-
columnSql.push(` PRIMARY KEY (${pkColumns.map((column) =>
|
|
239
|
+
columnSql.push(` PRIMARY KEY (${pkColumns.map((column) => this.connection.getGrammar().wrap(column)).join(", ")})`);
|
|
240
240
|
}
|
|
241
|
-
statements.push(`CREATE TABLE
|
|
241
|
+
statements.push(`CREATE TABLE ${this.connection.getGrammar().wrap(`${schema}.${table}`)} (\n${columnSql.join(",\n")}\n);`);
|
|
242
242
|
}
|
|
243
243
|
return statements.join("\n\n") + "\n";
|
|
244
244
|
}
|
package/dist/src/model/Model.js
CHANGED
|
@@ -815,21 +815,22 @@ export class Model {
|
|
|
815
815
|
async save() {
|
|
816
816
|
const constructor = this.constructor;
|
|
817
817
|
if (this.$exists) {
|
|
818
|
-
await ObserverRegistry.dispatch("updating", this);
|
|
819
818
|
await ObserverRegistry.dispatch("saving", this);
|
|
820
|
-
|
|
819
|
+
let dirty = this.getDirty();
|
|
820
|
+
if (Object.keys(dirty).length > 0 && constructor.timestamps) {
|
|
821
821
|
this.$attributes["updated_at"] = this.freshTimestamp();
|
|
822
|
+
dirty = this.getDirty();
|
|
822
823
|
}
|
|
823
|
-
const dirty = this.getDirty();
|
|
824
824
|
if (Object.keys(dirty).length > 0) {
|
|
825
|
+
await ObserverRegistry.dispatch("updating", this);
|
|
825
826
|
const pk = this.getAttribute(constructor.primaryKey);
|
|
826
827
|
const connection = this.getConnection();
|
|
827
828
|
await new Builder(connection, connection.qualifyTable(constructor.getTable()))
|
|
828
829
|
.where(constructor.primaryKey, pk)
|
|
829
830
|
.update(dirty);
|
|
831
|
+
await ObserverRegistry.dispatch("updated", this);
|
|
830
832
|
}
|
|
831
833
|
this.$original = { ...this.$attributes };
|
|
832
|
-
await ObserverRegistry.dispatch("updated", this);
|
|
833
834
|
await ObserverRegistry.dispatch("saved", this);
|
|
834
835
|
}
|
|
835
836
|
else {
|
|
@@ -930,10 +931,10 @@ export class Model {
|
|
|
930
931
|
}
|
|
931
932
|
async delete() {
|
|
932
933
|
const constructor = this.constructor;
|
|
933
|
-
await ObserverRegistry.dispatch("deleting", this);
|
|
934
934
|
const pk = this.getAttribute(constructor.primaryKey);
|
|
935
935
|
if (!pk)
|
|
936
936
|
return false;
|
|
937
|
+
await ObserverRegistry.dispatch("deleting", this);
|
|
937
938
|
if (constructor.softDeletes) {
|
|
938
939
|
const deletedAt = this.freshTimestamp();
|
|
939
940
|
const connection = this.getConnection();
|
|
@@ -168,6 +168,7 @@ export declare class Builder<T = Record<string, any>> {
|
|
|
168
168
|
insertGetId(data: ModelAttributeInput<T>, idColumn?: ModelColumn<T>): Promise<any>;
|
|
169
169
|
insertOrIgnore(data: ModelAttributeInput<T> | ModelAttributeInput<T>[]): Promise<any>;
|
|
170
170
|
upsert(data: ModelAttributeInput<T> | ModelAttributeInput<T>[], uniqueBy: ModelColumn<T> | ModelColumn<T>[], updateColumns?: ModelColumn<T>[]): Promise<any>;
|
|
171
|
+
private getUniformColumns;
|
|
171
172
|
update(data: ModelAttributeInput<T>): Promise<any>;
|
|
172
173
|
delete(): Promise<any>;
|
|
173
174
|
increment(column: ModelColumn<T>, amount?: number, extra?: ModelAttributeInput<T>): Promise<any>;
|
|
@@ -717,10 +717,15 @@ export class Builder {
|
|
|
717
717
|
return results.map((row) => row[column]);
|
|
718
718
|
}
|
|
719
719
|
async aggregate(sql, alias) {
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
720
|
+
const query = this.clone();
|
|
721
|
+
query.model = undefined;
|
|
722
|
+
query.columns = [`${sql} as ${alias}`];
|
|
723
|
+
query.orders = [];
|
|
724
|
+
query.limitValue = undefined;
|
|
725
|
+
query.offsetValue = undefined;
|
|
726
|
+
query.eagerLoads = [];
|
|
727
|
+
query.lockMode = undefined;
|
|
728
|
+
const result = await query.first();
|
|
724
729
|
return result ? result[alias] : null;
|
|
725
730
|
}
|
|
726
731
|
async count(column = "*") {
|
|
@@ -739,7 +744,11 @@ export class Builder {
|
|
|
739
744
|
return await this.aggregate(`MAX(${column})`, "max");
|
|
740
745
|
}
|
|
741
746
|
async paginate(perPage = 15, page = 1) {
|
|
742
|
-
const
|
|
747
|
+
const countQuery = this.clone();
|
|
748
|
+
countQuery.limitValue = undefined;
|
|
749
|
+
countQuery.offsetValue = undefined;
|
|
750
|
+
countQuery.orders = [];
|
|
751
|
+
const total = await countQuery.count();
|
|
743
752
|
const data = await this.clone().forPage(page, perPage).get();
|
|
744
753
|
return {
|
|
745
754
|
data,
|
|
@@ -867,7 +876,7 @@ export class Builder {
|
|
|
867
876
|
const records = Array.isArray(data) ? data : [data];
|
|
868
877
|
if (records.length === 0)
|
|
869
878
|
return;
|
|
870
|
-
const columns =
|
|
879
|
+
const columns = this.getUniformColumns(records);
|
|
871
880
|
const bindings = [];
|
|
872
881
|
const values = records.map((record) => {
|
|
873
882
|
return `(${columns.map((col) => {
|
|
@@ -886,7 +895,7 @@ export class Builder {
|
|
|
886
895
|
const records = Array.isArray(data) ? data : [data];
|
|
887
896
|
if (records.length === 0)
|
|
888
897
|
return;
|
|
889
|
-
const columns =
|
|
898
|
+
const columns = this.getUniformColumns(records);
|
|
890
899
|
const bindings = [];
|
|
891
900
|
const values = records.map((record) => {
|
|
892
901
|
return `(${columns.map((col) => {
|
|
@@ -901,7 +910,7 @@ export class Builder {
|
|
|
901
910
|
const records = Array.isArray(data) ? data : [data];
|
|
902
911
|
if (records.length === 0)
|
|
903
912
|
return;
|
|
904
|
-
const columns =
|
|
913
|
+
const columns = this.getUniformColumns(records);
|
|
905
914
|
const bindings = [];
|
|
906
915
|
const values = records.map((record) => {
|
|
907
916
|
return `(${columns.map((col) => {
|
|
@@ -914,6 +923,17 @@ export class Builder {
|
|
|
914
923
|
const sql = this.grammar.compileUpsert(this.grammar.wrap(this.tableName), columns, values, uniqueCols, updateCols);
|
|
915
924
|
return await this.connection.run(sql, bindings);
|
|
916
925
|
}
|
|
926
|
+
getUniformColumns(records) {
|
|
927
|
+
const columns = Object.keys(records[0]);
|
|
928
|
+
const signature = [...columns].sort().join("\0");
|
|
929
|
+
for (let i = 1; i < records.length; i++) {
|
|
930
|
+
const recordSignature = Object.keys(records[i]).sort().join("\0");
|
|
931
|
+
if (recordSignature !== signature) {
|
|
932
|
+
throw new Error("Bulk insert records must have the same columns.");
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return columns;
|
|
936
|
+
}
|
|
917
937
|
async update(data) {
|
|
918
938
|
this.bindings = [];
|
|
919
939
|
this.parameterize = true;
|
package/package.json
CHANGED