@easy-cms/drizzle 0.44.0 → 0.46.0

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.
Files changed (2) hide show
  1. package/dist/index.js +56 -17
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // src/database.ts
2
2
  import { resolve } from "path";
3
3
  import { QueryError as QueryError2 } from "@easy-cms/core";
4
- import { asc as asc3, count, eq as eq3, getTableColumns, getTableName, inArray as inArray3 } from "drizzle-orm";
4
+ import { and as and3, asc as asc3, count, eq as eq3, getTableColumns, getTableName, inArray as inArray3, sql as sql2 } from "drizzle-orm";
5
5
 
6
6
  // src/documents.ts
7
- import { asc, eq, inArray } from "drizzle-orm";
7
+ import { and, asc, eq, inArray } from "drizzle-orm";
8
8
  var col = (model, name) => model.table[name];
9
9
  function getAt(data, path) {
10
10
  let current = data;
@@ -154,10 +154,12 @@ async function insertDocument(db, model, data, drafts) {
154
154
  await insertChildren(db, model, id, data);
155
155
  return id;
156
156
  }
157
- async function replaceDocument(db, model, id, data, drafts) {
158
- await db.update(model.table).set({ ...dataToRow(model, data), ...systemRow(data, drafts) }).where(eq(col(model, "id"), id));
157
+ async function replaceDocument(db, model, id, data, drafts, condition) {
158
+ const updated = await db.update(model.table).set({ ...dataToRow(model, data), ...systemRow(data, drafts) }).where(condition ? and(eq(col(model, "id"), id), condition) : eq(col(model, "id"), id)).returning({ id: col(model, "id") });
159
+ if (updated.length === 0) return false;
159
160
  await deleteChildren(db, model, [id]);
160
161
  await insertChildren(db, model, id, data);
162
+ return true;
161
163
  }
162
164
  async function deleteDocument(db, model, id) {
163
165
  await deleteChildren(db, model, [id]);
@@ -387,7 +389,12 @@ function buildTable(builder, name, kind, fields, options) {
387
389
  }
388
390
  );
389
391
  if (topLevel && kind === "root" && (field.unique || field.type === "slug") && field.uniqueWithin !== void 0) {
390
- indexes.push({ column, unique: true, within: snake(field.uniqueWithin) });
392
+ const within = [field.uniqueWithin].flat().map(snake);
393
+ indexes.push({
394
+ column,
395
+ unique: true,
396
+ within: within.length === 1 ? within[0] : within
397
+ });
391
398
  indexes.push({ column, unique: false });
392
399
  } else if (topLevel && kind === "root" && (field.unique || field.type === "slug")) {
393
400
  indexes.push({ column, unique: true });
@@ -404,8 +411,10 @@ function buildTable(builder, name, kind, fields, options) {
404
411
  columns,
405
412
  (t) => indexes.map(({ column, unique, within }) => {
406
413
  const col3 = t[column];
407
- if (within)
408
- return dialect.uniqueIndex(`${name}_${within}_${column}_unique`).on(t[within], col3);
414
+ if (within) {
415
+ const columns2 = [within].flat();
416
+ return dialect.uniqueIndex(`${name}_${columns2.join("_")}_${column}_unique`).on(...columns2.map((w) => t[w]), col3);
417
+ }
409
418
  return unique ? dialect.uniqueIndex(`${name}_${column}_unique`).on(col3) : dialect.index(`${name}_${column}_idx`).on(col3);
410
419
  })
411
420
  );
@@ -563,7 +572,7 @@ var Migrator = class {
563
572
  this.options.logger.warn("Schema push drops tables or columns; data in them is lost.");
564
573
  }
565
574
  await this.runner.transaction([
566
- ...statements.map((sql2) => ({ sql: sql2 })),
575
+ ...statements.map((sql3) => ({ sql: sql3 })),
567
576
  this.record(DEV_PUSH, this.options.schema.hash, cur, true)
568
577
  ]);
569
578
  if (statements.length > 0)
@@ -632,7 +641,7 @@ ${BREAKPOINT}
632
641
  for (const migration of pending) {
633
642
  try {
634
643
  await this.runner.transaction([
635
- ...migration.statements.map((sql2) => ({ sql: sql2 })),
644
+ ...migration.statements.map((sql3) => ({ sql: sql3 })),
636
645
  this.record(migration.name, migration.hash, migration.snapshot, false)
637
646
  ]);
638
647
  } catch (error) {
@@ -683,7 +692,7 @@ function timestamp() {
683
692
  // src/query.ts
684
693
  import { parseId, QueryError } from "@easy-cms/core";
685
694
  import {
686
- and,
695
+ and as and2,
687
696
  asc as asc2,
688
697
  desc,
689
698
  eq as eq2,
@@ -903,12 +912,12 @@ var WhereBuilder = class {
903
912
  if (key === "and" || key === "or") {
904
913
  if (!Array.isArray(value)) throw new QueryError(`"${key}" must be an array`);
905
914
  const inner = value.map((w) => this.build(model, w)).filter((s) => s !== void 0);
906
- if (inner.length > 0) parts.push(key === "and" ? and(...inner) : or(...inner));
915
+ if (inner.length > 0) parts.push(key === "and" ? and2(...inner) : or(...inner));
907
916
  continue;
908
917
  }
909
918
  parts.push(this.field(model, key, value));
910
919
  }
911
- return parts.length === 0 ? void 0 : parts.length === 1 ? parts[0] : and(...parts);
920
+ return parts.length === 0 ? void 0 : parts.length === 1 ? parts[0] : and2(...parts);
912
921
  }
913
922
  field(model, path, operators) {
914
923
  if (typeof operators !== "object" || operators === null || Array.isArray(operators)) {
@@ -929,7 +938,7 @@ var WhereBuilder = class {
929
938
  if (target.kind === "blocks") return this.blocks(target, op, value, path);
930
939
  return this.child(model, target.child, target.rest, op, value, path, target.locale);
931
940
  });
932
- return parts.length === 1 ? parts[0] : and(...parts);
941
+ return parts.length === 1 ? parts[0] : and2(...parts);
933
942
  }
934
943
  /**
935
944
  * Conditions inside blocks test the JSON rows: some block (and, for nested lists, some row in
@@ -976,9 +985,9 @@ var WhereBuilder = class {
976
985
  child(parent, child, rest, op, value, path, locale) {
977
986
  const table = child.table;
978
987
  const parentLink = eq2(col2(table, "_parent_id"), col2(parent, "id"));
979
- const link = locale === void 0 ? parentLink : and(parentLink, eq2(col2(table, "_locale"), locale));
988
+ const link = locale === void 0 ? parentLink : and2(parentLink, eq2(col2(table, "_locale"), locale));
980
989
  const subquery = (condition) => exists(
981
- this.db.select({ one: sql`1` }).from(table.table).where(condition ? and(link, condition) : link)
990
+ this.db.select({ one: sql`1` }).from(table.table).where(condition ? and2(link, condition) : link)
982
991
  );
983
992
  if (child.kind === "values") {
984
993
  if (rest.length > 0) throw new QueryError(`Cannot query inside "${path}"`);
@@ -1150,13 +1159,43 @@ var DrizzleDatabase = class {
1150
1159
  }
1151
1160
  async update(args) {
1152
1161
  const model = this.model(args.collection);
1153
- await this.write(
1162
+ const condition = args.where ? this.where(args.collection, args.where) : void 0;
1163
+ const written = await this.write(
1154
1164
  () => this.db.transaction(
1155
- (tx) => replaceDocument(tx, model.root, args.id, args.data, model.config.drafts === true)
1165
+ (tx) => replaceDocument(
1166
+ tx,
1167
+ model.root,
1168
+ args.id,
1169
+ args.data,
1170
+ model.config.drafts === true,
1171
+ condition
1172
+ )
1156
1173
  )
1157
1174
  );
1175
+ if (!written) return null;
1158
1176
  return await this.findById({ collection: args.collection, id: args.id });
1159
1177
  }
1178
+ async increment(args) {
1179
+ const model = this.model(args.collection);
1180
+ const target = model.root.columns.find(
1181
+ (c) => c.locale === void 0 && c.path.length === 1 && c.path[0] === args.field
1182
+ );
1183
+ if (target?.field.type !== "number")
1184
+ throw new QueryError2(
1185
+ `"${args.field}" of "${args.collection}" is not a top-level number field`
1186
+ );
1187
+ if (!Number.isFinite(args.by)) throw new QueryError2('increment: "by" must be a number');
1188
+ const column = model.root.table[target.column];
1189
+ const next = sql2`coalesce(${column}, 0) + ${args.by}`;
1190
+ const conditions = [eq3(model.root.table.id, args.id)];
1191
+ if (args.min !== void 0) conditions.push(sql2`${next} >= ${args.min}`);
1192
+ if (args.max !== void 0) conditions.push(sql2`${next} <= ${args.max}`);
1193
+ const rows = await this.write(
1194
+ () => this.db.update(model.root.table).set({ [target.column]: next }).where(and3(...conditions)).returning({ value: column })
1195
+ );
1196
+ const [row] = rows;
1197
+ return row ? Number(row.value) : null;
1198
+ }
1160
1199
  async delete(args) {
1161
1200
  const model = this.model(args.collection);
1162
1201
  await this.write(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easy-cms/drizzle",
3
- "version": "0.44.0",
3
+ "version": "0.46.0",
4
4
  "description": "Shared Drizzle ORM layer for Easy CMS database adapters",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,10 +23,10 @@
23
23
  "drizzle-orm": "0.45.3"
24
24
  },
25
25
  "peerDependencies": {
26
- "@easy-cms/core": "^0.44.0"
26
+ "@easy-cms/core": "^0.46.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@easy-cms/core": "^0.44.0"
29
+ "@easy-cms/core": "^0.46.0"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"