@bunnykit/orm 0.1.2 → 0.1.4
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.
|
@@ -82,6 +82,9 @@ export declare class Model<T extends Record<string, any> = Record<string, any>>
|
|
|
82
82
|
static timestamps: boolean;
|
|
83
83
|
static connection?: Connection;
|
|
84
84
|
static dateFormat: string;
|
|
85
|
+
static keyType: "int" | "string" | "uuid";
|
|
86
|
+
static incrementing: boolean;
|
|
87
|
+
static usesUuids: boolean;
|
|
85
88
|
static morphName?: string;
|
|
86
89
|
static casts: Record<string, CastDefinition>;
|
|
87
90
|
static fillable: string[];
|
|
@@ -103,6 +106,7 @@ export declare class Model<T extends Record<string, any> = Record<string, any>>
|
|
|
103
106
|
static removeGlobalScope(name: string): void;
|
|
104
107
|
static applyGlobalScopes(builder: Builder<any>): void;
|
|
105
108
|
static getQualifiedDeletedAtColumn(): string;
|
|
109
|
+
static shouldAutoGeneratePrimaryKey(): Promise<boolean>;
|
|
106
110
|
static create<M extends typeof Model>(this: M, attributes: Partial<InstanceType<M> extends Model<infer U> ? U : Record<string, any>>): Promise<InstanceType<M>>;
|
|
107
111
|
static find<M extends typeof Model>(this: M, id: any): Promise<InstanceType<M> | null>;
|
|
108
112
|
static first<M extends typeof Model>(this: M): Promise<InstanceType<M> | null>;
|
package/dist/src/model/Model.js
CHANGED
|
@@ -3,6 +3,7 @@ import { snakeCase } from "../utils.js";
|
|
|
3
3
|
import { ObserverRegistry } from "./Observer.js";
|
|
4
4
|
import { MorphTo, MorphOne, MorphMany, MorphToMany } from "./MorphRelations.js";
|
|
5
5
|
import { BelongsToMany } from "./BelongsToMany.js";
|
|
6
|
+
import { Schema } from "../schema/Schema.js";
|
|
6
7
|
const globalScopes = new WeakMap();
|
|
7
8
|
function getGlobalScopes(model) {
|
|
8
9
|
const scopes = new Map();
|
|
@@ -276,6 +277,9 @@ export class Model {
|
|
|
276
277
|
static timestamps = true;
|
|
277
278
|
static connection;
|
|
278
279
|
static dateFormat = "YYYY-MM-DD HH:mm:ss";
|
|
280
|
+
static keyType = "int";
|
|
281
|
+
static incrementing = true;
|
|
282
|
+
static usesUuids = false;
|
|
279
283
|
static morphName;
|
|
280
284
|
static casts = {};
|
|
281
285
|
static fillable = [];
|
|
@@ -370,6 +374,20 @@ export class Model {
|
|
|
370
374
|
static getQualifiedDeletedAtColumn() {
|
|
371
375
|
return `${this.getTable()}.${this.deletedAtColumn}`;
|
|
372
376
|
}
|
|
377
|
+
static async shouldAutoGeneratePrimaryKey() {
|
|
378
|
+
if (this.usesUuids || this.keyType === "uuid")
|
|
379
|
+
return true;
|
|
380
|
+
const column = await Schema.getColumn(this.getTable(), this.primaryKey);
|
|
381
|
+
if (!column)
|
|
382
|
+
return false;
|
|
383
|
+
if (!column.primary)
|
|
384
|
+
return false;
|
|
385
|
+
if (column.autoIncrement)
|
|
386
|
+
return false;
|
|
387
|
+
const type = String(column.type || "").toLowerCase();
|
|
388
|
+
const numericTypes = new Set(["integer", "int", "bigint", "smallint", "tinyint", "real", "float", "double", "decimal", "numeric"]);
|
|
389
|
+
return !numericTypes.has(type);
|
|
390
|
+
}
|
|
373
391
|
static async create(attributes) {
|
|
374
392
|
const instance = new this();
|
|
375
393
|
instance.fill(attributes);
|
|
@@ -632,9 +650,21 @@ export class Model {
|
|
|
632
650
|
this.$attributes["created_at"] = now;
|
|
633
651
|
this.$attributes["updated_at"] = now;
|
|
634
652
|
}
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
653
|
+
const primaryKey = constructor.primaryKey;
|
|
654
|
+
const primaryKeyValue = this.getAttribute(primaryKey);
|
|
655
|
+
const shouldGeneratePrimaryKey = await constructor.shouldAutoGeneratePrimaryKey();
|
|
656
|
+
if ((primaryKeyValue === null || primaryKeyValue === undefined || primaryKeyValue === "") && shouldGeneratePrimaryKey) {
|
|
657
|
+
const generated = crypto.randomUUID();
|
|
658
|
+
this.$attributes[primaryKey] = generated;
|
|
659
|
+
}
|
|
660
|
+
if (shouldGeneratePrimaryKey || primaryKeyValue !== null && primaryKeyValue !== undefined && primaryKeyValue !== "") {
|
|
661
|
+
await new Builder(constructor.getConnection(), constructor.getTable()).insert(this.$attributes);
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
const result = await new Builder(constructor.getConnection(), constructor.getTable()).insertGetId(this.$attributes);
|
|
665
|
+
if (result) {
|
|
666
|
+
this.$attributes[constructor.primaryKey] = result;
|
|
667
|
+
}
|
|
638
668
|
}
|
|
639
669
|
this.$exists = true;
|
|
640
670
|
this.$original = { ...this.$attributes };
|
|
@@ -13,4 +13,10 @@ export declare class Schema {
|
|
|
13
13
|
static rename(from: string, to: string): Promise<void>;
|
|
14
14
|
static hasTable(table: string): Promise<boolean>;
|
|
15
15
|
static hasColumn(table: string, column: string): Promise<boolean>;
|
|
16
|
+
static getColumn(table: string, column: string): Promise<{
|
|
17
|
+
name: string;
|
|
18
|
+
type: string;
|
|
19
|
+
primary: boolean;
|
|
20
|
+
autoIncrement: boolean;
|
|
21
|
+
} | null>;
|
|
16
22
|
}
|
|
@@ -132,4 +132,31 @@ export class Schema {
|
|
|
132
132
|
const result = await this.getConnection().query(sql);
|
|
133
133
|
return result.length > 0;
|
|
134
134
|
}
|
|
135
|
+
static async getColumn(table, column) {
|
|
136
|
+
const driver = this.getConnection().getDriverName();
|
|
137
|
+
if (driver === "sqlite") {
|
|
138
|
+
const rows = await this.getConnection().query(`PRAGMA table_info(${table})`);
|
|
139
|
+
const row = rows.find((item) => item.name === column);
|
|
140
|
+
return row ? { name: row.name, type: row.type, primary: row.pk > 0, autoIncrement: false } : null;
|
|
141
|
+
}
|
|
142
|
+
if (driver === "mysql") {
|
|
143
|
+
const rows = await this.getConnection().query(`SHOW COLUMNS FROM ${table} LIKE '${column}'`);
|
|
144
|
+
const row = rows[0];
|
|
145
|
+
return row ? { name: row.Field, type: row.Type, primary: row.Key === "PRI", autoIncrement: String(row.Extra || "").toLowerCase().includes("auto_increment") } : null;
|
|
146
|
+
}
|
|
147
|
+
const rows = await this.getConnection().query(`SELECT c.column_name, c.data_type, COALESCE(tc.constraint_type = 'PRIMARY KEY', false) AS primary_key
|
|
148
|
+
FROM information_schema.columns c
|
|
149
|
+
LEFT JOIN information_schema.key_column_usage kcu
|
|
150
|
+
ON c.table_schema = kcu.table_schema
|
|
151
|
+
AND c.table_name = kcu.table_name
|
|
152
|
+
AND c.column_name = kcu.column_name
|
|
153
|
+
LEFT JOIN information_schema.table_constraints tc
|
|
154
|
+
ON kcu.table_schema = tc.table_schema
|
|
155
|
+
AND kcu.constraint_name = tc.constraint_name
|
|
156
|
+
WHERE c.table_schema = 'public'
|
|
157
|
+
AND c.table_name = '${table}'
|
|
158
|
+
AND c.column_name = '${column}'`);
|
|
159
|
+
const row = rows[0];
|
|
160
|
+
return row ? { name: row.column_name, type: row.data_type, primary: !!row.primary_key, autoIncrement: false } : null;
|
|
161
|
+
}
|
|
135
162
|
}
|
|
@@ -48,6 +48,8 @@ export class SQLiteGrammar extends Grammar {
|
|
|
48
48
|
let sql = `${this.wrap(column.name)} ${this.getType(column)}`;
|
|
49
49
|
if (column.autoIncrement)
|
|
50
50
|
sql += this.modifyAutoIncrement(column);
|
|
51
|
+
else if (column.primary)
|
|
52
|
+
sql += " PRIMARY KEY";
|
|
51
53
|
if (!column.nullable)
|
|
52
54
|
sql += " NOT NULL";
|
|
53
55
|
if (column.default !== undefined)
|
package/package.json
CHANGED