@easy-cms/drizzle 1.7.1 → 1.8.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.
package/dist/index.d.ts CHANGED
@@ -214,4 +214,5 @@ declare class Migrator {
214
214
  private files;
215
215
  }
216
216
 
217
- export { type AnyColumn, type AnyTable, type ColumnBuilder, type Connection, DEFAULT_MIGRATION_DIR, DEFAULT_TABLE_PREFIX, type Dialect, type DrizzleAdapterOptions, type DrizzleDb, type IndexBuilder, type JsonElement, type JsonValueType, Migrator, type SchemaModel, type Snapshot, type SqlRunner, type Statement, buildSchema, connectDatabase, snake, unionSnapshot };
217
+ export { DEFAULT_MIGRATION_DIR, DEFAULT_TABLE_PREFIX, Migrator, buildSchema, connectDatabase, snake, unionSnapshot };
218
+ export type { AnyColumn, AnyTable, ColumnBuilder, Connection, Dialect, DrizzleAdapterOptions, DrizzleDb, IndexBuilder, JsonElement, JsonValueType, SchemaModel, Snapshot, SqlRunner, Statement };
package/dist/index.js CHANGED
@@ -1052,7 +1052,8 @@ async function connectDatabase(dialect, connection, args, options = {}) {
1052
1052
  });
1053
1053
  if (args.schema === "push") await migrator.push();
1054
1054
  else if (args.schema === "verify") await migrator.verify();
1055
- return new DrizzleDatabase(dialect, connection, schema, migrator, prefix);
1055
+ const countCacheMs = (args.config.countCacheSeconds ?? 5) * 1e3;
1056
+ return new DrizzleDatabase(dialect, connection, schema, migrator, prefix, countCacheMs);
1056
1057
  } catch (error) {
1057
1058
  await connection.close().catch(() => {
1058
1059
  });
@@ -1060,12 +1061,13 @@ async function connectDatabase(dialect, connection, args, options = {}) {
1060
1061
  }
1061
1062
  }
1062
1063
  var DrizzleDatabase = class {
1063
- constructor(dialect, connection, schema, migrator, tablePrefix) {
1064
+ constructor(dialect, connection, schema, migrator, tablePrefix, countCacheMs = 0) {
1064
1065
  this.dialect = dialect;
1065
1066
  this.connection = connection;
1066
1067
  this.schema = schema;
1067
1068
  this.migrator = migrator;
1068
1069
  this.tablePrefix = tablePrefix;
1070
+ this.countCacheMs = countCacheMs;
1069
1071
  this.db = connection.db;
1070
1072
  for (const [slug, model] of schema.collections) {
1071
1073
  this.builders.set(
@@ -1079,7 +1081,14 @@ var DrizzleDatabase = class {
1079
1081
  schema;
1080
1082
  migrator;
1081
1083
  tablePrefix;
1084
+ countCacheMs;
1082
1085
  builders = /* @__PURE__ */ new Map();
1086
+ /**
1087
+ * Totals of recent paginated finds, by collection and query, for `countCacheSeconds`: counting
1088
+ * can't use an index, and many people open the same lists. Writes don't clear them (on a busy
1089
+ * site they would all the time), so a total is up to that old, on every instance alike.
1090
+ */
1091
+ counts = /* @__PURE__ */ new Map();
1083
1092
  db;
1084
1093
  model(slug) {
1085
1094
  const model = this.schema.collections.get(slug);
@@ -1097,13 +1106,8 @@ var DrizzleDatabase = class {
1097
1106
  return rows.map((row, i) => toDocument(row, docs[i] ?? {}, model.config.drafts === true));
1098
1107
  }
1099
1108
  async find(args) {
1100
- const model = this.model(args.collection);
1101
- const condition = this.where(args.collection, args.where);
1102
- const orderBy = this.builder(args.collection).orderBy(model.root, args.sort);
1103
- let query = this.db.select().from(model.root.table).where(condition).orderBy(...orderBy).$dynamic();
1104
- if (args.limit > 0) query = query.limit(args.limit).offset((args.page - 1) * args.limit);
1105
- const rows = await query;
1106
- const totalDocs = args.limit > 0 && (args.page > 1 || rows.length === args.limit) ? await this.count({ collection: args.collection, where: args.where }) : (args.page - 1) * args.limit + rows.length;
1109
+ const { model, rows } = await this.findRows(args, args.limit);
1110
+ const totalDocs = args.limit > 0 && (args.page > 1 || rows.length === args.limit) ? await this.cachedCount(args.collection, args.where) : (args.page - 1) * args.limit + rows.length;
1107
1111
  const totalPages = args.limit > 0 ? Math.max(1, Math.ceil(totalDocs / args.limit)) : 1;
1108
1112
  return {
1109
1113
  docs: await this.load(model, rows),
@@ -1115,6 +1119,27 @@ var DrizzleDatabase = class {
1115
1119
  hasPrevPage: args.page > 1
1116
1120
  };
1117
1121
  }
1122
+ async findPage(args) {
1123
+ const { model, rows } = await this.findRows(args, args.limit + 1);
1124
+ const more = rows.length > args.limit;
1125
+ return {
1126
+ docs: await this.load(model, more ? rows.slice(0, args.limit) : rows),
1127
+ totalDocs: null,
1128
+ limit: args.limit,
1129
+ page: args.page,
1130
+ totalPages: null,
1131
+ hasNextPage: more,
1132
+ hasPrevPage: args.page > 1
1133
+ };
1134
+ }
1135
+ async findRows(args, take) {
1136
+ const model = this.model(args.collection);
1137
+ const condition = this.where(args.collection, args.where);
1138
+ const orderBy = this.builder(args.collection).orderBy(model.root, args.sort);
1139
+ let query = this.db.select().from(model.root.table).where(condition).orderBy(...orderBy).$dynamic();
1140
+ if (args.limit > 0) query = query.limit(take).offset((args.page - 1) * args.limit);
1141
+ return { model, rows: await query };
1142
+ }
1118
1143
  async findById(args) {
1119
1144
  const [doc] = await this.findByIds({ collection: args.collection, ids: [args.id] });
1120
1145
  return doc ?? null;
@@ -1125,6 +1150,18 @@ var DrizzleDatabase = class {
1125
1150
  const rows = await this.db.select().from(model.root.table).where(inArray3(model.root.table.id, [...args.ids]));
1126
1151
  return this.load(model, rows);
1127
1152
  }
1153
+ /** A paginated find's total, from `counts` while it is fresh. */
1154
+ cachedCount(collection, where) {
1155
+ if (this.countCacheMs <= 0) return this.count({ collection, where });
1156
+ const key = `${collection}\0${JSON.stringify(where ?? null)}`;
1157
+ const now = Date.now();
1158
+ const cached = this.counts.get(key);
1159
+ if (cached && cached.until > now) return cached.total;
1160
+ const total = this.count({ collection, where });
1161
+ this.counts.set(key, { total, until: now + this.countCacheMs });
1162
+ total.catch(() => this.counts.delete(key));
1163
+ return total;
1164
+ }
1128
1165
  async count(args) {
1129
1166
  const model = this.model(args.collection);
1130
1167
  const [row] = await this.db.select({ total: count() }).from(model.root.table).where(this.where(args.collection, args.where));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easy-cms/drizzle",
3
- "version": "1.7.1",
3
+ "version": "1.8.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.4"
24
24
  },
25
25
  "peerDependencies": {
26
- "@easy-cms/core": "^1.7.1"
26
+ "@easy-cms/core": "^1.8.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@easy-cms/core": "^1.7.1"
29
+ "@easy-cms/core": "^1.8.0"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"