@bunnykit/orm 0.1.28 → 0.1.29

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.
@@ -434,9 +434,27 @@ export class Model {
434
434
  return !numericTypes.has(type);
435
435
  }
436
436
  static async prepareBulkRecords(records) {
437
+ const generatePk = await this.shouldAutoGeneratePrimaryKey();
438
+ const now = this.timestamps ? new Date().toISOString() : null;
437
439
  const prepared = [];
438
440
  for (const record of records) {
439
- prepared.push(await this.prepareBulkRecord(record));
441
+ const instance = new this();
442
+ instance.fill(record);
443
+ const attributes = { ...instance.$attributes };
444
+ if (now) {
445
+ if (attributes.created_at === undefined)
446
+ attributes.created_at = now;
447
+ if (attributes.updated_at === undefined)
448
+ attributes.updated_at = now;
449
+ }
450
+ if (generatePk) {
451
+ const pk = this.primaryKey;
452
+ const pkValue = attributes[pk];
453
+ if (pkValue === null || pkValue === undefined || pkValue === "") {
454
+ attributes[pk] = crypto.randomUUID();
455
+ }
456
+ }
457
+ prepared.push(attributes);
440
458
  }
441
459
  return prepared;
442
460
  }
@@ -501,8 +519,8 @@ export class Model {
501
519
  return result;
502
520
  }
503
521
  static async updateOrInsert(attributes, values = {}) {
504
- const existing = await this.where(attributes).first();
505
- if (existing) {
522
+ const exists = await this.where(attributes).exists();
523
+ if (exists) {
506
524
  const update = await this.prepareBulkRecord(values, { touchUpdatedAt: true, touchCreatedAt: false, generatePrimaryKey: false });
507
525
  await this.where(attributes).update(update);
508
526
  return true;
@@ -718,8 +718,7 @@ export class Builder {
718
718
  return rows;
719
719
  }
720
720
  async first() {
721
- const results = await this.limit(1).get();
722
- return results[0] || null;
721
+ return (await this.limit(1).get())[0] || null;
723
722
  }
724
723
  async find(id, column = "id") {
725
724
  return this.where(column, id).first();
@@ -773,8 +772,15 @@ export class Builder {
773
772
  return instance;
774
773
  }
775
774
  async pluck(column) {
776
- const results = await this.select(column).get();
777
- return results.map((row) => row[column]);
775
+ const model = this.model;
776
+ this.model = undefined;
777
+ this.bindings = [];
778
+ this.parameterize = true;
779
+ const sql = this.select(column).toSql();
780
+ this.parameterize = false;
781
+ const rows = await this.connection.query(sql, this.bindings);
782
+ this.model = model;
783
+ return Array.from(rows).map((row) => row[column]);
778
784
  }
779
785
  async aggregate(sql, alias) {
780
786
  const query = this.clone();
@@ -790,19 +796,55 @@ export class Builder {
790
796
  return result ? result[alias] : null;
791
797
  }
792
798
  async count(column = "*") {
793
- return Number(await this.aggregate(`COUNT(${column})`, "count") ?? 0);
799
+ const countSql = column === "*" ? "COUNT(*)" : `COUNT(${this.grammar.wrap(column)})`;
800
+ this.bindings = [];
801
+ this.parameterize = true;
802
+ const from = this.fromRaw || this.grammar.wrap(this.tableName);
803
+ const whereSql = this.compileWheres();
804
+ this.parameterize = false;
805
+ const sql = `SELECT ${countSql} as cnt FROM ${from}${whereSql ? " " + whereSql : ""}`;
806
+ const rows = await this.connection.query(sql, this.bindings);
807
+ return rows.length > 0 ? Number(rows[0].cnt) : 0;
794
808
  }
795
809
  async sum(column) {
796
- return Number(await this.aggregate(`SUM(${column})`, "sum") ?? 0);
810
+ const sql = `SELECT SUM(${this.grammar.wrap(column)}) as sum_val FROM ${this.fromRaw || this.grammar.wrap(this.tableName)}`;
811
+ this.bindings = [];
812
+ this.parameterize = true;
813
+ const whereSql = this.compileWheres();
814
+ this.parameterize = false;
815
+ const fullSql = whereSql ? `${sql}${whereSql}` : sql;
816
+ const rows = await this.connection.query(fullSql, this.bindings);
817
+ return rows.length > 0 ? Number(rows[0].sum_val || 0) : 0;
797
818
  }
798
819
  async avg(column) {
799
- return Number(await this.aggregate(`AVG(${column})`, "avg") ?? 0);
820
+ const sql = `SELECT AVG(${this.grammar.wrap(column)}) as avg_val FROM ${this.fromRaw || this.grammar.wrap(this.tableName)}`;
821
+ this.bindings = [];
822
+ this.parameterize = true;
823
+ const whereSql = this.compileWheres();
824
+ this.parameterize = false;
825
+ const fullSql = whereSql ? `${sql}${whereSql}` : sql;
826
+ const rows = await this.connection.query(fullSql, this.bindings);
827
+ return rows.length > 0 ? Number(rows[0].avg_val || 0) : 0;
800
828
  }
801
829
  async min(column) {
802
- return await this.aggregate(`MIN(${column})`, "min");
830
+ const sql = `SELECT MIN(${this.grammar.wrap(column)}) as min_val FROM ${this.fromRaw || this.grammar.wrap(this.tableName)}`;
831
+ this.bindings = [];
832
+ this.parameterize = true;
833
+ const whereSql = this.compileWheres();
834
+ this.parameterize = false;
835
+ const fullSql = whereSql ? `${sql}${whereSql}` : sql;
836
+ const rows = await this.connection.query(fullSql, this.bindings);
837
+ return rows.length > 0 ? rows[0].min_val : null;
803
838
  }
804
839
  async max(column) {
805
- return await this.aggregate(`MAX(${column})`, "max");
840
+ const sql = `SELECT MAX(${this.grammar.wrap(column)}) as max_val FROM ${this.fromRaw || this.grammar.wrap(this.tableName)}`;
841
+ this.bindings = [];
842
+ this.parameterize = true;
843
+ const whereSql = this.compileWheres();
844
+ this.parameterize = false;
845
+ const fullSql = whereSql ? `${sql}${whereSql}` : sql;
846
+ const rows = await this.connection.query(fullSql, this.bindings);
847
+ return rows.length > 0 ? rows[0].max_val : null;
806
848
  }
807
849
  async paginate(perPage = 15, page = 1) {
808
850
  const countQuery = this.clone();
@@ -1040,8 +1082,14 @@ export class Builder {
1040
1082
  return this.withTrashed().update({ [model.deletedAtColumn]: null });
1041
1083
  }
1042
1084
  async exists() {
1043
- const result = await this.select("1 as exists_check").limit(1).get();
1044
- return result.length > 0;
1085
+ this.bindings = [];
1086
+ this.parameterize = true;
1087
+ const from = this.fromRaw || this.grammar.wrap(this.tableName);
1088
+ const whereSql = this.compileWheres();
1089
+ this.parameterize = false;
1090
+ const sql = `SELECT 1 FROM ${from}${whereSql ? whereSql : ""} LIMIT 1`;
1091
+ const rows = await this.connection.query(sql, this.bindings);
1092
+ return rows.length > 0;
1045
1093
  }
1046
1094
  async doesntExist() {
1047
1095
  return !(await this.exists());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunnykit/orm",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "An Eloquent-inspired ORM for Bun's native SQL client supporting SQLite, MySQL, and PostgreSQL.",
5
5
  "license": "MIT",
6
6
  "packageManager": "bun@1.3.12",