convex-ents 0.18.1 → 0.20.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
@@ -1,5 +1,5 @@
1
1
  export { EntDefinition, defineEnt, defineEntFromTable, defineEntSchema, defineEntsFromTables, getEntDefinitions } from './schema.js';
2
- export { G as GenericEnt, U as GenericEntWriter, t as PromiseEdgeEnts, p as PromiseEdgeEntsOrNull, v as PromiseEdgeEntsWriter, I as PromiseEdgeWriter, K as PromiseEdgeWriterOrNull, J as PromiseEdgeWriterOrThrow, x as PromiseEnt, V as PromiseEntId, w as PromiseEntOrNull, T as PromiseEntWriter, S as PromiseEntWriterOrNull, m as PromiseEnts, k as PromiseEntsOrNull, n as PromiseEntsOrNulls, N as PromiseEntsWriter, l as PromiseEntsWriterOrNull, g as PromiseOrderedQuery, f as PromiseOrderedQueryBase, P as PromiseOrderedQueryOrNull, L as PromiseOrderedQueryWriter, a as PromiseOrderedQueryWriterOrNull, h as PromiseQuery, b as PromiseQueryOrNull, M as PromiseQueryWriter, c as PromiseQueryWriterOrNull, e as PromiseTable, d as PromiseTableBase, R as PromiseTableWriter, Z as addEntRules, B as entsTableFactory } from './writer.js';
2
+ export { L as GenericEnt, _ as GenericEntWriter, z as PromiseEdgeEnts, v as PromiseEdgeEntsOrNull, B as PromiseEdgeEntsWriter, O as PromiseEdgeWriter, R as PromiseEdgeWriterOrNull, Q as PromiseEdgeWriterOrThrow, D as PromiseEnt, $ as PromiseEntId, C as PromiseEntOrNull, Z as PromiseEntWriter, Y as PromiseEntWriterOrNull, q as PromiseEnts, o as PromiseEntsOrNull, r as PromiseEntsOrNulls, U as PromiseEntsWriter, p as PromiseEntsWriterOrNull, h as PromiseOrderedQuery, g as PromiseOrderedQueryBase, P as PromiseOrderedQueryOrNull, S as PromiseOrderedQueryWriter, b as PromiseOrderedQueryWriterOrNull, j as PromiseQuery, c as PromiseQueryOrNull, T as PromiseQueryWriter, d as PromiseQueryWriterOrNull, f as PromiseTable, e as PromiseTableBase, X as PromiseTableWriter, a3 as addEntRules, H as entsTableFactory } from './writer.js';
3
3
  export { scheduledDeleteFactory } from './deletion.js';
4
4
  import 'convex/server';
5
5
  import 'convex/values';
package/dist/index.js CHANGED
@@ -463,6 +463,15 @@ function getEntDefinitions(schema) {
463
463
  function getEdgeDefinitions(entDefinitions, table) {
464
464
  return entDefinitions[table].edges;
465
465
  }
466
+ function systemAwareGet(db, table, id) {
467
+ return isSystemTable(table) ? db.system.get(table, id) : db.get(table, id);
468
+ }
469
+ function systemAwareQuery(db, table) {
470
+ return isSystemTable(table) ? db.system.query(table) : db.query(table);
471
+ }
472
+ function isSystemTable(table) {
473
+ return table.startsWith("_");
474
+ }
466
475
 
467
476
  // src/writer.ts
468
477
  var import_server2 = require("convex/server");
@@ -496,7 +505,7 @@ var WriterImplBase = class _WriterImplBase {
496
505
  }
497
506
  } else if (edgeDefinition.cardinality === "single") {
498
507
  if (edgeDefinition.deletion !== void 0 && (!isDeletingSoftly || edgeDefinition.deletion === "soft")) {
499
- const doc = await this.ctx.db.get(id);
508
+ const doc = await this.ctx.db.get(this.table, id);
500
509
  if (doc !== null) {
501
510
  const otherId = doc[edgeDefinition.field];
502
511
  edges[key] = {
@@ -702,7 +711,7 @@ var WriterImplBase = class _WriterImplBase {
702
711
  if (id !== void 0) {
703
712
  const readPolicy = getReadRule(this.entDefinitions, this.table);
704
713
  if (readPolicy !== void 0) {
705
- const doc = await this.ctx.db.get(id);
714
+ const doc = await this.ctx.db.get(this.table, id);
706
715
  if (doc === null) {
707
716
  throw new Error(
708
717
  `Cannot update document with ID "${id}" in table "${this.table} because it does not exist"`
@@ -721,7 +730,7 @@ var WriterImplBase = class _WriterImplBase {
721
730
  return;
722
731
  }
723
732
  const ent = id === void 0 ? void 0 : entWrapper(
724
- await this.ctx.db.get(id),
733
+ await this.ctx.db.get(this.table, id),
725
734
  this.ctx,
726
735
  this.entDefinitions,
727
736
  this.table
@@ -751,9 +760,6 @@ var WriterImplBase = class _WriterImplBase {
751
760
  }
752
761
  }
753
762
  };
754
- function isSystemTable(table) {
755
- return table.startsWith("_");
756
- }
757
763
 
758
764
  // src/functions.ts
759
765
  var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
@@ -780,7 +786,7 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
780
786
  );
781
787
  }
782
788
  map(callbackFn) {
783
- return new PromiseArrayImpl(async () => {
789
+ return new PromiseArrayOrNullImpl(async () => {
784
790
  const array = await this;
785
791
  if (array === null) {
786
792
  return null;
@@ -941,6 +947,90 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
941
947
  );
942
948
  }
943
949
  };
950
+ var PromiseIdsQueryOrNullImpl = class extends Promise {
951
+ constructor(retrieve, field) {
952
+ super(() => {
953
+ });
954
+ this.retrieve = retrieve;
955
+ this.field = field;
956
+ }
957
+ map(callbackFn) {
958
+ return new PromiseArrayOrNullImpl(async () => {
959
+ const array = await this;
960
+ if (array === null) {
961
+ return null;
962
+ }
963
+ return await Promise.all(array.map(callbackFn));
964
+ });
965
+ }
966
+ paginate(paginationOpts) {
967
+ return new PromiseIdsPaginationResultOrNullImpl(async () => {
968
+ const query = await this.retrieve();
969
+ if (query === null) {
970
+ return null;
971
+ }
972
+ const result = await query.paginate(paginationOpts);
973
+ return {
974
+ ...result,
975
+ page: result.page.map((id) => this._getId(id))
976
+ };
977
+ });
978
+ }
979
+ take(n) {
980
+ return new PromiseIdsOrNullImpl(async () => {
981
+ const query = await this.retrieve();
982
+ if (query === null) {
983
+ return null;
984
+ }
985
+ const result = await query.take(n);
986
+ return result.map((id) => this._getId(id));
987
+ });
988
+ }
989
+ async first() {
990
+ const query = await this.retrieve();
991
+ if (query === null) {
992
+ return null;
993
+ }
994
+ const doc = await query.first();
995
+ if (doc === null) {
996
+ return null;
997
+ }
998
+ return this._getId(doc);
999
+ }
1000
+ async firstX() {
1001
+ const id = await this.first();
1002
+ if (id === null) {
1003
+ throw new Error("Expected at least one ID, but got none");
1004
+ }
1005
+ return id;
1006
+ }
1007
+ async unique() {
1008
+ const query = await this.retrieve();
1009
+ if (query === null) {
1010
+ return null;
1011
+ }
1012
+ const result = await query.unique();
1013
+ if (result === null) {
1014
+ return null;
1015
+ }
1016
+ return this._getId(result);
1017
+ }
1018
+ async uniqueX() {
1019
+ const id = await this.unique();
1020
+ if (id === null) {
1021
+ throw new Error("Expected one unique ID, but got none");
1022
+ }
1023
+ return id;
1024
+ }
1025
+ then(onfulfilled, onrejected) {
1026
+ return this.retrieve().then((query) => query === null ? null : query.collect()).then(
1027
+ (docs) => docs === null ? null : docs.map((doc) => this._getId(doc))
1028
+ ).then(onfulfilled, onrejected);
1029
+ }
1030
+ _getId(doc) {
1031
+ return doc[this.field];
1032
+ }
1033
+ };
944
1034
  var PromisePaginationResultOrNullImpl = class extends Promise {
945
1035
  constructor(ctx, entDefinitions, table, retrieve) {
946
1036
  super(() => {
@@ -987,13 +1077,33 @@ var PromisePaginationResultOrNullImpl = class extends Promise {
987
1077
  ).then(onfulfilled, onrejected);
988
1078
  }
989
1079
  };
1080
+ var PromiseIdsPaginationResultOrNullImpl = class extends Promise {
1081
+ constructor(retrieve) {
1082
+ super(() => {
1083
+ });
1084
+ this.retrieve = retrieve;
1085
+ }
1086
+ async map(callbackFn) {
1087
+ const result = await this;
1088
+ if (result === null) {
1089
+ return null;
1090
+ }
1091
+ return {
1092
+ ...result,
1093
+ page: await Promise.all(result.page.map(callbackFn))
1094
+ };
1095
+ }
1096
+ then(onfulfilled, onrejected) {
1097
+ return this.retrieve().then(onfulfilled, onrejected);
1098
+ }
1099
+ };
990
1100
  var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
991
1101
  constructor(ctx, entDefinitions, table) {
992
1102
  super(
993
1103
  ctx,
994
1104
  entDefinitions,
995
1105
  table,
996
- async () => isSystemTable(table) ? ctx.db.system.query(table) : ctx.db.query(table)
1106
+ async () => systemAwareQuery(ctx.db, table)
997
1107
  );
998
1108
  }
999
1109
  get(...args) {
@@ -1021,7 +1131,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
1021
1131
  return {
1022
1132
  id,
1023
1133
  doc: async () => {
1024
- const doc = await (isSystemTable(this.table) ? this.ctx.db.system.get(id) : this.ctx.db.get(id));
1134
+ const doc = await systemAwareGet(this.ctx.db, this.table, id);
1025
1135
  if (throwIfNull && doc === null) {
1026
1136
  throw new Error(
1027
1137
  `Document not found with id \`${id}\` in table "${this.table}"`
@@ -1037,7 +1147,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
1037
1147
  this.table,
1038
1148
  indexName
1039
1149
  );
1040
- const doc = await this.ctx.db.query(this.table).withIndex(
1150
+ const doc = await systemAwareQuery(this.ctx.db, this.table).withIndex(
1041
1151
  indexName,
1042
1152
  (q) => values.reduce((q2, value, i) => q2.eq(fieldNames[i], value), q)
1043
1153
  ).unique();
@@ -1070,7 +1180,7 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
1070
1180
  });
1071
1181
  return await Promise.all(
1072
1182
  ids.map(async (id) => {
1073
- const doc = await (isSystemTable(this.table) ? this.ctx.db.system.get(id) : this.ctx.db.get(id));
1183
+ const doc = await systemAwareGet(this.ctx.db, this.table, id);
1074
1184
  if (throwIfNull && doc === null) {
1075
1185
  throw new Error(
1076
1186
  `Document not found with id \`${id}\` in table "${this.table}"`
@@ -1081,12 +1191,23 @@ var PromiseTableImpl = class extends PromiseQueryOrNullImpl {
1081
1191
  );
1082
1192
  } : async () => {
1083
1193
  const [indexName, values] = args;
1194
+ const fieldNames = getIndexFields(
1195
+ this.entDefinitions,
1196
+ this.table,
1197
+ indexName
1198
+ );
1199
+ if (fieldNames.length > 1) {
1200
+ throw new Error(
1201
+ `Index "${indexName}" has ${fieldNames.length} fields, but getMany() supports only single field indexes`
1202
+ );
1203
+ }
1204
+ const fieldName = fieldNames[0];
1084
1205
  return await Promise.all(
1085
1206
  values.map(async (value) => {
1086
- const doc = await this.ctx.db.query(this.table).withIndex(indexName, (q) => q.eq(indexName, value)).unique();
1207
+ const doc = await systemAwareQuery(this.ctx.db, this.table).withIndex(indexName, (q) => q.eq(fieldName, value)).unique();
1087
1208
  if (throwIfNull && doc === null) {
1088
1209
  throw new Error(
1089
- `Table "${this.table}" does not contain document with field "${indexName}" = \`${value}\``
1210
+ `Table "${this.table}" does not contain document with field "${fieldName}" = \`${value}\``
1090
1211
  );
1091
1212
  }
1092
1213
  return doc;
@@ -1141,7 +1262,7 @@ var PromiseEntsOrNullImpl = class extends Promise {
1141
1262
  this.throwIfNull = throwIfNull;
1142
1263
  }
1143
1264
  map(callbackFn) {
1144
- return new PromiseArrayImpl(async () => {
1265
+ return new PromiseArrayOrNullImpl(async () => {
1145
1266
  const array = await this;
1146
1267
  if (array === null) {
1147
1268
  return null;
@@ -1243,11 +1364,34 @@ var PromiseEntsOrNullImpl = class extends Promise {
1243
1364
  ).then(onfulfilled, onrejected);
1244
1365
  }
1245
1366
  };
1367
+ var PromiseIdsOrNullImpl = class extends Promise {
1368
+ constructor(retrieve) {
1369
+ super(() => {
1370
+ });
1371
+ this.retrieve = retrieve;
1372
+ }
1373
+ map(callbackFn) {
1374
+ return new PromiseArrayOrNullImpl(async () => {
1375
+ const array = await this;
1376
+ if (array === null) {
1377
+ return null;
1378
+ }
1379
+ return await Promise.all(array.map(callbackFn));
1380
+ });
1381
+ }
1382
+ then(onfulfilled, onrejected) {
1383
+ return this.retrieve().then(onfulfilled, onrejected);
1384
+ }
1385
+ };
1246
1386
  var PromiseEdgeOrNullImpl = class _PromiseEdgeOrNullImpl extends PromiseEntsOrNullImpl {
1247
1387
  constructor(ctx, entDefinitions, table, edgeDefinition, retrieveSourceId, retrieveQuery, retrieveDoc = async (edgeDoc) => {
1248
1388
  const sourceId = edgeDoc[edgeDefinition.field];
1249
1389
  const targetId = edgeDoc[edgeDefinition.ref];
1250
- const doc = await this.ctx.db.get(targetId);
1390
+ const doc = await systemAwareGet(
1391
+ this.ctx.db,
1392
+ edgeDefinition.to,
1393
+ targetId
1394
+ );
1251
1395
  if (doc === null) {
1252
1396
  throw new Error(
1253
1397
  `Dangling reference for edge "${edgeDefinition.name}" in table "${this.table}" for document with ID "${sourceId}": Could not find a document with ID "${targetId}" in table "${edgeDefinition.to}" (edge document ID is "${edgeDoc._id}").`
@@ -1274,6 +1418,12 @@ var PromiseEdgeOrNullImpl = class _PromiseEdgeOrNullImpl extends PromiseEntsOrNu
1274
1418
  this.retrieveQuery = retrieveQuery;
1275
1419
  this.retrieveDoc = retrieveDoc;
1276
1420
  }
1421
+ ids() {
1422
+ return new PromiseIdsQueryOrNullImpl(
1423
+ () => this.retrieveQuery(),
1424
+ this.edgeDefinition.ref
1425
+ );
1426
+ }
1277
1427
  async has(targetId) {
1278
1428
  const sourceId = await this.retrieveSourceId();
1279
1429
  if (sourceId === null) {
@@ -1543,7 +1693,11 @@ var PromiseEntOrNullImpl = class extends Promise {
1543
1693
  `Unexpected null reference for edge "${edgeDefinition.name}" in table "${this.table}" on document with ID "${id}": Expected an ID for a document in table "${edgeDefinition.to}".`
1544
1694
  );
1545
1695
  }
1546
- const otherDoc = await this.ctx.db.get(otherId);
1696
+ const otherDoc = await systemAwareGet(
1697
+ this.ctx.db,
1698
+ edgeDefinition.to,
1699
+ otherId
1700
+ );
1547
1701
  if (otherDoc === null && edgeDefinition.to !== "_scheduled_functions") {
1548
1702
  throw new Error(
1549
1703
  `Dangling reference for edge "${edgeDefinition.name}" in table "${this.table}" on document with ID "${id}": Could not find a document with ID "${otherId}" in table "${edgeDefinition.to}".`
@@ -1557,7 +1711,7 @@ var PromiseEntOrNullImpl = class extends Promise {
1557
1711
  );
1558
1712
  }
1559
1713
  };
1560
- var PromiseArrayImpl = class extends Promise {
1714
+ var PromiseArrayOrNullImpl = class extends Promise {
1561
1715
  constructor(retrieve) {
1562
1716
  super(() => {
1563
1717
  });
@@ -1816,7 +1970,7 @@ var PromiseEntWriterImpl = class extends PromiseEntOrNullImpl {
1816
1970
  }
1817
1971
  if (edgeDefinition.cardinality === "single") {
1818
1972
  if (edgeDefinition.type === "ref") {
1819
- const oldDoc = await this.ctx.db.get(docId);
1973
+ const oldDoc = await this.ctx.db.get(this.table, docId);
1820
1974
  if (oldDoc[key] !== void 0 && oldDoc[key] !== idOrIds) {
1821
1975
  throw new Error("Cannot set 1:1 edge from ref end.");
1822
1976
  }
@@ -1878,7 +2032,10 @@ var PromiseEntIdImpl = class extends Promise {
1878
2032
  this.table,
1879
2033
  async () => {
1880
2034
  const id = await this.retrieve();
1881
- return { id, doc: async () => this.ctx.db.get(id) };
2035
+ return {
2036
+ id,
2037
+ doc: async () => systemAwareGet(this.ctx.db, this.table, id)
2038
+ };
1882
2039
  },
1883
2040
  true
1884
2041
  );
@@ -1963,6 +2120,12 @@ async function filterByReadRule(ctx, entDefinitions, table, docs, throwIfNull) {
1963
2120
  return docs.filter((_, i) => decisions[i]);
1964
2121
  }
1965
2122
  function getIndexFields(entDefinitions, table, index) {
2123
+ if (index === "by_id") {
2124
+ return ["_id"];
2125
+ }
2126
+ if (index === "by_creation_time") {
2127
+ return ["_creationTime"];
2128
+ }
1966
2129
  return entDefinitions[table].indexes[index];
1967
2130
  }
1968
2131
  function getReadRule(entDefinitions, table) {
@@ -2015,11 +2178,7 @@ function scheduledDeleteFactory(entDefinitions, options) {
2015
2178
  inProgress: import_values2.v.boolean()
2016
2179
  },
2017
2180
  handler: async (ctx, { origin, stack, inProgress }) => {
2018
- const originId = ctx.db.normalizeId(origin.table, origin.id);
2019
- if (originId === null) {
2020
- throw new Error(`Invalid ID "${origin.id}" for table ${origin.table}`);
2021
- }
2022
- const doc = await ctx.db.get(originId);
2181
+ const doc = await ctx.db.get(origin.table, origin.id);
2023
2182
  if (doc.deletionTime !== origin.deletionTime) {
2024
2183
  if (inProgress) {
2025
2184
  console.error(
@@ -2037,7 +2196,7 @@ function scheduledDeleteFactory(entDefinitions, options) {
2037
2196
  newCounter(),
2038
2197
  inProgress ? stack : [
2039
2198
  {
2040
- id: originId,
2199
+ id: origin.id,
2041
2200
  table: origin.table,
2042
2201
  edges: getEdgeArgs(entDefinitions, origin.table)
2043
2202
  }