convex-ents 0.8.1 → 0.9.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.
@@ -144,37 +144,167 @@ interface PromiseEnts<EntsDataModel extends GenericEntsDataModel, Table extends
144
144
  }
145
145
  interface PromiseEntsOrNulls<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends Promise<(Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> | null)[]> {
146
146
  }
147
- interface PromiseEdgeEntsOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsOrNull<EntsDataModel, Table> {
147
+ interface PromiseEdgeOrderedEntsOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsOrNull<EntsDataModel, Table> {
148
+ /**
149
+ * Paginate the ents on the other end of the edge.
150
+ * Results are ordered by edge's `_creationTime`.
151
+ */
152
+ paginate(paginationOpts: PaginationOptions): PromisePaginationResultOrNull<EntsDataModel, Table>;
153
+ /**
154
+ * Take the first `n` ents on the other end of the edge
155
+ * ordered by edge's `_creationTime`.
156
+ */
157
+ take(n: number): PromiseEntsOrNull<EntsDataModel, Table>;
158
+ /**
159
+ * Returns the first ent on the other end of the edge
160
+ * ordered by edge's `_creationTime`, or `null`.
161
+ */
162
+ first(): PromiseEntOrNull<EntsDataModel, Table>;
163
+ /**
164
+ * Returns the only ent on the other end of the edge,
165
+ * `null` if there are none, or throws if there are more than one.
166
+ */
167
+ unique(): PromiseEntOrNull<EntsDataModel, Table>;
168
+ }
169
+ interface PromiseEdgeEntsOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table> {
148
170
  /**
149
171
  * Returns whether there is an ent with given ID on the other side
150
172
  * the edge. Returns null if chained to a null result.
151
173
  * @param id The ID of the ent on the other end of the edge
152
174
  */
153
175
  has(id: GenericId<Table>): Promise<boolean | null>;
176
+ /**
177
+ * Query the ents on the other end of the edge
178
+ * ordered by edge's `_creationTime`.
179
+ */
180
+ order(order: "asc" | "desc", indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>): PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table>;
154
181
  }
155
- interface PromiseEdgeEntsWriterOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsWriterOrNull<EntsDataModel, Table> {
182
+ interface PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsWriterOrNull<EntsDataModel, Table> {
183
+ /**
184
+ * Paginate the ents on the other end of the edge.
185
+ * Results are ordered by edge's `_creationTime`.
186
+ */
187
+ paginate(paginationOpts: PaginationOptions): PromisePaginationResultWriterOrNull<EntsDataModel, Table>;
188
+ /**
189
+ * Take the first `n` ents on the other end of the edge
190
+ * ordered by edge's `_creationTime`.
191
+ */
192
+ take(n: number): PromiseEntsWriterOrNull<EntsDataModel, Table>;
193
+ /**
194
+ * Returns the first ent on the other end of the edge
195
+ * ordered by edge's `_creationTime`, or `null`.
196
+ */
197
+ first(): PromiseEntWriterOrNull<EntsDataModel, Table>;
198
+ /**
199
+ * Returns the only ent on the other end of the edge,
200
+ * `null` if there are none, or throws if there are more than one.
201
+ */
202
+ unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;
203
+ }
204
+ interface PromiseEdgeEntsWriterOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table> {
156
205
  /**
157
206
  * Returns whether there is an ent with given ID on the other side
158
207
  * the edge. Returns null if chained to a null result.
159
208
  * @param id The ID of the ent on the other end of the edge
160
209
  */
161
210
  has(id: GenericId<Table>): Promise<boolean | null>;
211
+ /**
212
+ * Query the ents on the other end of the edge
213
+ * ordered by edge's `_creationTime`.
214
+ */
215
+ order(order: "asc" | "desc", indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>): PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table>;
162
216
  }
163
- interface PromiseEdgeEnts<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEnts<EntsDataModel, Table> {
217
+ interface PromiseEdgeOrderedEnts<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEnts<EntsDataModel, Table> {
218
+ /**
219
+ * Paginate the ents on the other end of the edge.
220
+ * Results are ordered by edge's `_creationTime`.
221
+ */
222
+ paginate(paginationOpts: PaginationOptions): PromisePaginationResult<EntsDataModel, Table>;
223
+ /**
224
+ * Take the first `n` ents on the other end of the edge
225
+ * ordered by edge's `_creationTime`.
226
+ */
227
+ take(n: number): PromiseEnts<EntsDataModel, Table>;
228
+ /**
229
+ * Returns the first ent on the other end of the edge
230
+ * ordered by edge's `_creationTime`, or `null`.
231
+ */
232
+ first(): PromiseEntOrNull<EntsDataModel, Table>;
233
+ /**
234
+ * Returns the first ent on the other end of the edge
235
+ * ordered by edge's `_creationTime`, or throws if there
236
+ * are no ents on the other end of the edge.
237
+ */
238
+ firstX(): PromiseEnt<EntsDataModel, Table>;
239
+ /**
240
+ * Returns the only ent on the other end of the edge,
241
+ * `null` if there are none, or throws if there are more than one.
242
+ */
243
+ unique(): PromiseEntOrNull<EntsDataModel, Table>;
244
+ /**
245
+ * Returns the only ent on the other end of the edge,
246
+ * or throws if there are none or more than one.
247
+ */
248
+ uniqueX(): PromiseEnt<EntsDataModel, Table>;
249
+ }
250
+ interface PromiseEdgeEnts<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEdgeOrderedEnts<EntsDataModel, Table> {
164
251
  /**
165
252
  * Returns whether there is an ent with given ID on the other side
166
253
  * the edge.
167
254
  * @param id The ID of the ent on the other end of the edge
168
255
  */
169
256
  has(id: GenericId<Table>): Promise<boolean>;
257
+ /**
258
+ * Query the ents on the other end of the edge
259
+ * ordered by edge's `_creationTime`.
260
+ */
261
+ order(order: "asc" | "desc", indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>): PromiseEdgeOrderedEnts<EntsDataModel, Table>;
262
+ }
263
+ interface PromiseEdgeOrderedEntsWriter<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsWriter<EntsDataModel, Table> {
264
+ /**
265
+ * Paginate the ents on the other end of the edge.
266
+ * Results are ordered by edge's `_creationTime`.
267
+ */
268
+ paginate(paginationOpts: PaginationOptions): PromisePaginationResultWriter<EntsDataModel, Table>;
269
+ /**
270
+ * Take the first `n` ents on the other end of the edge
271
+ * ordered by edge's `_creationTime`.
272
+ */
273
+ take(n: number): PromiseEntsWriter<EntsDataModel, Table>;
274
+ /**
275
+ * Returns the first ent on the other end of the edge
276
+ * ordered by edge's `_creationTime`, or `null`.
277
+ */
278
+ first(): PromiseEntWriterOrNull<EntsDataModel, Table>;
279
+ /**
280
+ * Returns the first ent on the other end of the edge
281
+ * ordered by edge's `_creationTime`, or throws if there
282
+ * are no ents on the other end of the edge.
283
+ */
284
+ firstX(): PromiseEntWriter<EntsDataModel, Table>;
285
+ /**
286
+ * Returns the only ent on the other end of the edge,
287
+ * `null` if there are none, or throws if there are more than one.
288
+ */
289
+ unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;
290
+ /**
291
+ * Returns the only ent on the other end of the edge,
292
+ * or throws if there are none or more than one.
293
+ */
294
+ uniqueX(): PromiseEntWriter<EntsDataModel, Table>;
170
295
  }
171
- interface PromiseEdgeEntsWriter<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEntsWriter<EntsDataModel, Table> {
296
+ interface PromiseEdgeEntsWriter<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends PromiseEdgeOrderedEntsWriter<EntsDataModel, Table> {
172
297
  /**
173
298
  * Returns whether there is an ent with given ID on the other side
174
299
  * the edge.
175
300
  * @param id The ID of the ent on the other end of the edge
176
301
  */
177
302
  has(id: GenericId<Table>): Promise<boolean>;
303
+ /**
304
+ * Query the ents on the other end of the edge
305
+ * ordered by edge's `_creationTime`.
306
+ */
307
+ order(order: "asc" | "desc", indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>): PromiseEdgeOrderedEntsWriter<EntsDataModel, Table>;
178
308
  }
179
309
  interface PromiseEntOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends Promise<Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> | null> {
180
310
  edge<Edge extends keyof EntsDataModel[Table]["edges"]>(edge: Edge): PromiseEdgeOrNull<EntsDataModel, Table, Edge>;
@@ -244,6 +374,10 @@ interface PromiseEntsWriter<EntsDataModel extends GenericEntsDataModel, Table ex
244
374
  firstX(): PromiseEntWriter<EntsDataModel, Table>;
245
375
  uniqueX(): PromiseEntWriter<EntsDataModel, Table>;
246
376
  }
377
+ interface PromisePaginationResultWriterOrNull<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends Promise<PaginationResult<EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>> | null> {
378
+ docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>> | null>;
379
+ map<TOutput>(callbackFn: (value: EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>, index: number, array: EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]) => Promise<TOutput> | TOutput): Promise<PaginationResult<TOutput> | null>;
380
+ }
247
381
  interface PromisePaginationResultWriter<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>> extends Promise<PaginationResult<EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>>> {
248
382
  docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>>>;
249
383
  map<TOutput>(callbackFn: (value: EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>, index: number, array: EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]) => Promise<TOutput> | TOutput): Promise<PaginationResult<TOutput>>;
@@ -414,4 +548,4 @@ declare function getWriteRule(entDefinitions: GenericEntsDataModel, table: strin
414
548
  declare function getEdgeDefinitions<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>>(entDefinitions: EntsDataModel, table: Table): Record<keyof EntsDataModel[Table]["edges"], EdgeConfig>;
415
549
  declare function getDeletionConfig<EntsDataModel extends GenericEntsDataModel, Table extends TableNamesInDataModel<EntsDataModel>>(entDefinitions: EntsDataModel, table: Table): DeletionConfig | undefined;
416
550
 
417
- export { getWriteRule as $, entsTableFactory as A, type EntsTable as B, type EntsTableWriter as C, type Ent as D, type EdgeChanges as E, type PromiseEdge as F, type GenericEnt as G, type PromiseEdgeOrThrow as H, type PromiseEdgeWriter as I, type PromiseEdgeWriterOrThrow as J, type PromiseEdgeWriterOrNull as K, type PromiseOrderedQueryWriter as L, type PromiseQueryWriter as M, type PromiseEntsWriter as N, type PromisePaginationResultWriter as O, type PromiseOrderedQueryOrNull as P, type PromiseTableWriter as Q, type PromiseEntWriterOrNull as R, type PromiseEntWriter as S, type GenericEntWriter as T, type PromiseEntId as U, type EntQueryCtx as V, WriterImplBase as W, type EntMutationCtx as X, type DocRetriever as Y, addEntRules as Z, getReadRule as _, type WithEdgeInserts as a, getEdgeDefinitions as a0, getDeletionConfig as a1, type WithEdges as b, type WithEdgePatches as c, type PromiseOrderedQueryWriterOrNull as d, type PromiseQueryOrNull as e, type PromiseQueryWriterOrNull as f, type PromiseTableBase as g, type PromiseTable as h, type PromiseOrderedQueryBase as i, type PromiseOrderedQuery as j, type PromiseQuery as k, type PromisePaginationResultOrNull as l, type PromisePaginationResult as m, type PromiseEntsOrNull as n, type PromiseEntsWriterOrNull as o, type PromiseEnts as p, type PromiseEntsOrNulls as q, type PromiseEdgeEntsOrNull as r, type PromiseEdgeEntsWriterOrNull as s, type PromiseEdgeEnts as t, type PromiseEdgeEntsWriter as u, type PromiseEntOrNull as v, type PromiseEnt as w, type PromiseArrayOrNull as x, type PromiseArray as y, entWrapper as z };
551
+ export { type EntQueryCtx as $, type PromiseEnt as A, type PromiseArrayOrNull as B, type PromiseArray as C, entWrapper as D, type EdgeChanges as E, entsTableFactory as F, type EntsTable as G, type EntsTableWriter as H, type Ent as I, type GenericEnt as J, type PromiseEdge as K, type PromiseEdgeOrThrow as L, type PromiseEdgeWriter as M, type PromiseEdgeWriterOrThrow as N, type PromiseEdgeWriterOrNull as O, type PromiseOrderedQueryOrNull as P, type PromiseOrderedQueryWriter as Q, type PromiseQueryWriter as R, type PromiseEntsWriter as S, type PromisePaginationResultWriterOrNull as T, type PromisePaginationResultWriter as U, type PromiseTableWriter as V, WriterImplBase as W, type PromiseEntWriterOrNull as X, type PromiseEntWriter as Y, type GenericEntWriter as Z, type PromiseEntId as _, type WithEdgeInserts as a, type EntMutationCtx as a0, type DocRetriever as a1, addEntRules as a2, getReadRule as a3, getWriteRule as a4, getEdgeDefinitions as a5, getDeletionConfig as a6, type WithEdges as b, type WithEdgePatches as c, type PromiseOrderedQueryWriterOrNull as d, type PromiseQueryOrNull as e, type PromiseQueryWriterOrNull as f, type PromiseTableBase as g, type PromiseTable as h, type PromiseOrderedQueryBase as i, type PromiseOrderedQuery as j, type PromiseQuery as k, type PromisePaginationResultOrNull as l, type PromisePaginationResult as m, type PromiseEntsOrNull as n, type PromiseEntsWriterOrNull as o, type PromiseEnts as p, type PromiseEntsOrNulls as q, type PromiseEdgeOrderedEntsOrNull as r, type PromiseEdgeEntsOrNull as s, type PromiseEdgeOrderedEntsWriterOrNull as t, type PromiseEdgeEntsWriterOrNull as u, type PromiseEdgeOrderedEnts as v, type PromiseEdgeEnts as w, type PromiseEdgeOrderedEntsWriter as x, type PromiseEdgeEntsWriter as y, type PromiseEntOrNull as z };
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, T as GenericEntWriter, t as PromiseEdgeEnts, r as PromiseEdgeEntsOrNull, u as PromiseEdgeEntsWriter, I as PromiseEdgeWriter, K as PromiseEdgeWriterOrNull, J as PromiseEdgeWriterOrThrow, w as PromiseEnt, U as PromiseEntId, v as PromiseEntOrNull, S as PromiseEntWriter, R as PromiseEntWriterOrNull, p as PromiseEnts, n as PromiseEntsOrNull, q as PromiseEntsOrNulls, N as PromiseEntsWriter, o as PromiseEntsWriterOrNull, j as PromiseOrderedQuery, i as PromiseOrderedQueryBase, P as PromiseOrderedQueryOrNull, L as PromiseOrderedQueryWriter, d as PromiseOrderedQueryWriterOrNull, k as PromiseQuery, e as PromiseQueryOrNull, M as PromiseQueryWriter, f as PromiseQueryWriterOrNull, h as PromiseTable, g as PromiseTableBase, Q as PromiseTableWriter, Z as addEntRules, A as entsTableFactory } from './index-uXk5iZ86.js';
2
+ export { J as GenericEnt, Z as GenericEntWriter, w as PromiseEdgeEnts, s as PromiseEdgeEntsOrNull, y as PromiseEdgeEntsWriter, M as PromiseEdgeWriter, O as PromiseEdgeWriterOrNull, N as PromiseEdgeWriterOrThrow, A as PromiseEnt, _ as PromiseEntId, z as PromiseEntOrNull, Y as PromiseEntWriter, X as PromiseEntWriterOrNull, p as PromiseEnts, n as PromiseEntsOrNull, q as PromiseEntsOrNulls, S as PromiseEntsWriter, o as PromiseEntsWriterOrNull, j as PromiseOrderedQuery, i as PromiseOrderedQueryBase, P as PromiseOrderedQueryOrNull, Q as PromiseOrderedQueryWriter, d as PromiseOrderedQueryWriterOrNull, k as PromiseQuery, e as PromiseQueryOrNull, R as PromiseQueryWriter, f as PromiseQueryWriterOrNull, h as PromiseTable, g as PromiseTableBase, V as PromiseTableWriter, a2 as addEntRules, F as entsTableFactory } from './index-nOBiMg01.js';
3
3
  export { scheduledDeleteFactory } from './deletion.js';
4
4
  import 'convex/server';
5
5
  import 'convex/values';
package/dist/index.js CHANGED
@@ -131,10 +131,18 @@ function defineEntSchema(schema, options) {
131
131
  const edgeTableName = edge.type === "ref" && edge.table !== void 0 ? edge.table : inverseEdge === void 0 ? `${tableName}_${edge.name}` : inverseEdge.name !== tableName ? `${tableName}_${inverseEdge.name}_to_${edge.name}` : `${inverseEdge.name}_to_${edge.name}`;
132
132
  const forwardId = edge.type === "ref" && edge.field !== void 0 ? edge.field : inverseEdge === void 0 ? "aId" : tableName === otherTableName ? inverseEdge.name + "Id" : tableName + "Id";
133
133
  const inverseId = isSelfDirected && edge.type === "ref" && edge.inverseField !== void 0 ? edge.inverseField : inverseEdge === void 0 ? "bId" : inverseEdge.type === "ref" && inverseEdge.field !== void 0 ? inverseEdge.field : tableName === otherTableName ? edge.name + "Id" : otherTableName + "Id";
134
- schema[edgeTableName] = defineEnt({
134
+ const edgeTable = defineEnt({
135
135
  [forwardId]: import_values.v.id(tableName),
136
136
  [inverseId]: import_values.v.id(otherTableName)
137
- }).index(forwardId, [forwardId, inverseId]).index(inverseId, [inverseId, forwardId]);
137
+ }).index(forwardId, [forwardId]).index(inverseId, [inverseId]).index(`${forwardId}-${inverseId}`, [forwardId, inverseId]);
138
+ const isSymmetric = inverseEdge === void 0;
139
+ if (!isSymmetric) {
140
+ edgeTable.index(`${inverseId}-${forwardId}`, [
141
+ forwardId,
142
+ inverseId
143
+ ]);
144
+ }
145
+ schema[edgeTableName] = edgeTable;
138
146
  edge.type = "ref";
139
147
  edge.table = edgeTableName;
140
148
  edge.field = forwardId;
@@ -694,8 +702,13 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
694
702
  this.ctx,
695
703
  this.entDefinitions,
696
704
  this.table,
697
- this.retrieve,
698
- paginationOpts
705
+ async () => {
706
+ const query = await this.retrieve();
707
+ if (query === null) {
708
+ return null;
709
+ }
710
+ return await query.paginate(paginationOpts);
711
+ }
699
712
  );
700
713
  }
701
714
  take(n) {
@@ -811,50 +824,23 @@ var PromiseQueryOrNullImpl = class _PromiseQueryOrNullImpl extends Promise {
811
824
  }
812
825
  async _take(n) {
813
826
  const query = await this.retrieve();
814
- if (query === null) {
815
- return null;
816
- }
817
- const readPolicy = getReadRule(this.entDefinitions, this.table);
818
- if (readPolicy === void 0) {
819
- return await query.take(n);
820
- }
821
- let numItems = n;
822
- const docs = [];
823
- let hasMore = true;
824
- const iterator = query[Symbol.asyncIterator]();
825
- while (hasMore && docs.length < n) {
826
- const page = [];
827
- for (let i = 0; i < numItems; i++) {
828
- const { done, value } = await iterator.next();
829
- if (done) {
830
- hasMore = false;
831
- break;
832
- }
833
- page.push(value);
834
- }
835
- docs.push(
836
- ...(await filterByReadRule(
837
- this.ctx,
838
- this.entDefinitions,
839
- this.table,
840
- page,
841
- false
842
- )).slice(0, n - docs.length)
843
- );
844
- numItems = Math.min(64, numItems * 2);
845
- }
846
- return docs;
827
+ return await takeFromQuery(
828
+ query,
829
+ n,
830
+ this.ctx,
831
+ this.entDefinitions,
832
+ this.table
833
+ );
847
834
  }
848
835
  };
849
836
  var PromisePaginationResultOrNullImpl = class extends Promise {
850
- constructor(ctx, entDefinitions, table, retrieve, paginationOpts) {
837
+ constructor(ctx, entDefinitions, table, retrieve) {
851
838
  super(() => {
852
839
  });
853
840
  this.ctx = ctx;
854
841
  this.entDefinitions = entDefinitions;
855
842
  this.table = table;
856
843
  this.retrieve = retrieve;
857
- this.paginationOpts = paginationOpts;
858
844
  }
859
845
  async map(callbackFn) {
860
846
  const result = await this;
@@ -867,11 +853,10 @@ var PromisePaginationResultOrNullImpl = class extends Promise {
867
853
  };
868
854
  }
869
855
  async docs() {
870
- const query = await this.retrieve();
871
- if (query === null) {
856
+ const result = await this.retrieve();
857
+ if (result === null) {
872
858
  return null;
873
859
  }
874
- const result = await query.paginate(this.paginationOpts);
875
860
  return {
876
861
  ...result,
877
862
  page: await filterByReadRule(
@@ -1147,15 +1132,185 @@ var PromiseEntsOrNullImpl = class extends Promise {
1147
1132
  ).then(onfulfilled, onrejected);
1148
1133
  }
1149
1134
  };
1150
- var PromiseEdgeOrNullImpl = class extends PromiseEntsOrNullImpl {
1151
- constructor(ctx, entDefinitions, table, field, retrieveRange) {
1152
- super(ctx, entDefinitions, table, () => retrieveRange((q) => q), false);
1153
- this.field = field;
1154
- this.retrieveRange = retrieveRange;
1135
+ var PromiseEdgeOrNullImpl = class _PromiseEdgeOrNullImpl extends PromiseEntsOrNullImpl {
1136
+ constructor(ctx, entDefinitions, table, edgeDefinition, retrieveSourceId, retrieveQuery, retrieveDoc = async (edgeDoc) => {
1137
+ const sourceId = edgeDoc[edgeDefinition.field];
1138
+ const targetId = edgeDoc[edgeDefinition.ref];
1139
+ const doc = await this.ctx.db.get(targetId);
1140
+ if (doc === null) {
1141
+ throw new Error(
1142
+ `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}").`
1143
+ );
1144
+ }
1145
+ return doc;
1146
+ }) {
1147
+ super(
1148
+ ctx,
1149
+ entDefinitions,
1150
+ table,
1151
+ async () => {
1152
+ const query = await retrieveQuery();
1153
+ if (query === null) {
1154
+ return null;
1155
+ }
1156
+ const edgeDocs = await query.collect();
1157
+ return await Promise.all(edgeDocs.map(retrieveDoc));
1158
+ },
1159
+ false
1160
+ );
1161
+ this.edgeDefinition = edgeDefinition;
1162
+ this.retrieveSourceId = retrieveSourceId;
1163
+ this.retrieveQuery = retrieveQuery;
1164
+ this.retrieveDoc = retrieveDoc;
1165
+ }
1166
+ async has(targetId) {
1167
+ const sourceId = await this.retrieveSourceId();
1168
+ if (sourceId === null) {
1169
+ return null;
1170
+ }
1171
+ const edgeDoc = this.ctx.db.query(this.edgeDefinition.table).withIndex(
1172
+ `${this.edgeDefinition.field}-${this.edgeDefinition.ref}`,
1173
+ (q) => q.eq(this.edgeDefinition.field, sourceId).eq(
1174
+ this.edgeDefinition.ref,
1175
+ targetId
1176
+ )
1177
+ ).first();
1178
+ return edgeDoc !== null;
1155
1179
  }
1156
- async has(id) {
1157
- const docs = await this.retrieveRange((q) => q.eq(this.field, id));
1158
- return (docs?.length ?? 0) > 0;
1180
+ order(order) {
1181
+ return new _PromiseEdgeOrNullImpl(
1182
+ this.ctx,
1183
+ this.entDefinitions,
1184
+ this.table,
1185
+ this.edgeDefinition,
1186
+ this.retrieveSourceId,
1187
+ async () => {
1188
+ const query = await this.retrieveQuery();
1189
+ if (query === null) {
1190
+ return null;
1191
+ }
1192
+ return query.order(order);
1193
+ }
1194
+ );
1195
+ }
1196
+ paginate(paginationOpts) {
1197
+ return new PromisePaginationResultOrNullImpl(
1198
+ this.ctx,
1199
+ this.entDefinitions,
1200
+ this.table,
1201
+ async () => {
1202
+ const query = await this.retrieveQuery();
1203
+ if (query === null) {
1204
+ return null;
1205
+ }
1206
+ const result = await query.paginate(paginationOpts);
1207
+ return {
1208
+ ...result,
1209
+ page: await Promise.all(result.page.map(this.retrieveDoc))
1210
+ };
1211
+ }
1212
+ );
1213
+ }
1214
+ take(n) {
1215
+ return new PromiseEntsOrNullImpl(
1216
+ this.ctx,
1217
+ this.entDefinitions,
1218
+ this.table,
1219
+ async () => {
1220
+ return await this._take(n);
1221
+ },
1222
+ false
1223
+ );
1224
+ }
1225
+ first() {
1226
+ return new PromiseEntOrNullImpl(
1227
+ this.ctx,
1228
+ this.entDefinitions,
1229
+ this.table,
1230
+ async () => {
1231
+ const docs = await this._take(1);
1232
+ if (docs === null) {
1233
+ return nullRetriever;
1234
+ }
1235
+ const [doc] = docs;
1236
+ return loadedRetriever(doc);
1237
+ },
1238
+ false
1239
+ );
1240
+ }
1241
+ firstX() {
1242
+ return new PromiseEntWriterImpl(
1243
+ this.ctx,
1244
+ this.entDefinitions,
1245
+ this.table,
1246
+ async () => {
1247
+ const docs = await this._take(1);
1248
+ if (docs === null) {
1249
+ return nullRetriever;
1250
+ }
1251
+ const [doc] = docs;
1252
+ if (doc === void 0) {
1253
+ throw new Error("Query returned no documents");
1254
+ }
1255
+ return loadedRetriever(doc);
1256
+ },
1257
+ false
1258
+ );
1259
+ }
1260
+ unique() {
1261
+ return new PromiseEntOrNullImpl(
1262
+ this.ctx,
1263
+ this.entDefinitions,
1264
+ this.table,
1265
+ async () => {
1266
+ const docs = await this._take(2);
1267
+ if (docs === null) {
1268
+ return nullRetriever;
1269
+ }
1270
+ if (docs.length === 0) {
1271
+ return nullRetriever;
1272
+ }
1273
+ if (docs.length === 2) {
1274
+ throw new Error("unique() query returned more than one result");
1275
+ }
1276
+ const [doc] = docs;
1277
+ return loadedRetriever(doc);
1278
+ },
1279
+ false
1280
+ );
1281
+ }
1282
+ uniqueX() {
1283
+ return new PromiseEntWriterImpl(
1284
+ this.ctx,
1285
+ this.entDefinitions,
1286
+ this.table,
1287
+ async () => {
1288
+ const docs = await this._take(2);
1289
+ if (docs === null) {
1290
+ return nullRetriever;
1291
+ }
1292
+ if (docs.length === 0) {
1293
+ throw new Error("Query returned no documents");
1294
+ }
1295
+ if (docs.length === 2) {
1296
+ throw new Error("unique() query returned more than one result");
1297
+ }
1298
+ const [doc] = docs;
1299
+ return loadedRetriever(doc);
1300
+ },
1301
+ true
1302
+ );
1303
+ }
1304
+ async _take(n) {
1305
+ const query = await this.retrieveQuery();
1306
+ return await takeFromQuery(
1307
+ query,
1308
+ n,
1309
+ this.ctx,
1310
+ this.entDefinitions,
1311
+ this.table,
1312
+ this.retrieveDoc
1313
+ );
1159
1314
  }
1160
1315
  };
1161
1316
  var PromiseEntOrNullImpl = class extends Promise {
@@ -1209,29 +1364,21 @@ var PromiseEntOrNullImpl = class extends Promise {
1209
1364
  return new PromiseEdgeOrNullImpl(
1210
1365
  this.ctx,
1211
1366
  this.entDefinitions,
1212
- edgeDefinition.to,
1213
- edgeDefinition.ref,
1214
- async (indexRange) => {
1367
+ this.table,
1368
+ edgeDefinition,
1369
+ async () => {
1370
+ const { id } = await this.retrieve();
1371
+ return id;
1372
+ },
1373
+ async () => {
1215
1374
  const { id } = await this.retrieve();
1216
1375
  if (id === null) {
1217
1376
  return null;
1218
1377
  }
1219
- const edgeDocs = await this.ctx.db.query(edgeDefinition.table).withIndex(
1378
+ return this.ctx.db.query(edgeDefinition.table).withIndex(
1220
1379
  edgeDefinition.field,
1221
- (q) => indexRange(q.eq(edgeDefinition.field, id))
1222
- ).collect();
1223
- return (await Promise.all(
1224
- edgeDocs.map(
1225
- (edgeDoc) => this.ctx.db.get(edgeDoc[edgeDefinition.ref])
1226
- )
1227
- )).filter((doc, i) => {
1228
- if (doc === null) {
1229
- throw new Error(
1230
- `Dangling reference for edge "${edgeDefinition.name}" in table "${this.table}" for document with ID "${id}": Could not find a document with ID "${edgeDocs[i][edgeDefinition.field]}" in table "${edgeDefinition.to}" (edge document ID is "${edgeDocs[i]._id}").`
1231
- );
1232
- }
1233
- return true;
1234
- });
1380
+ (q) => q.eq(edgeDefinition.field, id)
1381
+ );
1235
1382
  }
1236
1383
  );
1237
1384
  }
@@ -1623,6 +1770,45 @@ function loadedRetriever(doc) {
1623
1770
  function addEntRules(entDefinitions, rules) {
1624
1771
  return { ...entDefinitions, rules };
1625
1772
  }
1773
+ async function takeFromQuery(query, n, ctx, entDefinitions, table, mapToResult) {
1774
+ if (query === null) {
1775
+ return null;
1776
+ }
1777
+ const readPolicy = getReadRule(entDefinitions, table);
1778
+ if (readPolicy === void 0) {
1779
+ const results = await query.take(n);
1780
+ if (mapToResult === void 0) {
1781
+ return results;
1782
+ }
1783
+ return Promise.all(results.map(mapToResult));
1784
+ }
1785
+ let numItems = n;
1786
+ const docs = [];
1787
+ let hasMore = true;
1788
+ const iterator = query[Symbol.asyncIterator]();
1789
+ while (hasMore && docs.length < n) {
1790
+ const page = [];
1791
+ for (let i = 0; i < numItems; i++) {
1792
+ const { done, value } = await iterator.next();
1793
+ if (done) {
1794
+ hasMore = false;
1795
+ break;
1796
+ }
1797
+ page.push(mapToResult === void 0 ? value : await mapToResult(value));
1798
+ }
1799
+ docs.push(
1800
+ ...(await filterByReadRule(
1801
+ ctx,
1802
+ entDefinitions,
1803
+ table,
1804
+ page,
1805
+ false
1806
+ )).slice(0, n - docs.length)
1807
+ );
1808
+ numItems = Math.min(64, numItems * 2);
1809
+ }
1810
+ return docs;
1811
+ }
1626
1812
  async function filterByReadRule(ctx, entDefinitions, table, docs, throwIfNull) {
1627
1813
  if (docs === null) {
1628
1814
  return null;