convex-ents 0.16.0 → 0.18.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/functions.ts","../src/schema.ts","../src/shared.ts","../src/writer.ts"],"sourcesContent":["import {\n DocumentByName,\n ExpressionOrValue,\n FieldTypeFromFieldPath,\n FilterBuilder,\n GenericDataModel,\n GenericDatabaseReader,\n GenericDatabaseWriter,\n GenericDocument,\n GenericTableInfo,\n IndexNames,\n IndexRange,\n IndexRangeBuilder,\n NamedIndex,\n NamedSearchIndex,\n NamedTableInfo,\n PaginationOptions,\n PaginationResult,\n Query,\n QueryInitializer,\n Scheduler,\n SearchFilter,\n SearchFilterBuilder,\n SearchIndexNames,\n StorageWriter,\n TableNamesInDataModel,\n WithOptionalSystemFields,\n WithoutSystemFields,\n} from \"convex/server\";\nimport { GenericId } from \"convex/values\";\nimport { ScheduledDeleteFuncRef } from \"./deletion\";\nimport {\n DeletionConfig,\n EdgeConfig,\n Expand,\n GenericEdgeConfig,\n GenericEntsDataModel,\n edgeCompoundIndexName,\n} from \"./schema\";\nimport {\n EntsSystemDataModel,\n IndexFieldTypesForEq,\n PromiseEdgeResult,\n getEdgeDefinitions,\n} from \"./shared\";\nimport {\n EdgeChanges,\n WithEdgeInserts,\n WithEdgePatches,\n WithEdges,\n WriterImplBase,\n isSystemTable,\n} from \"./writer\";\n\nexport interface PromiseOrderedQueryOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ): PromiseArrayOrNull<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n take(n: number): PromiseEntsOrNull<EntsDataModel, Table>;\n\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseOrderedQueryWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n take(n: number): PromiseEntsWriterOrNull<EntsDataModel, Table>;\n\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseQueryOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryOrNull<EntsDataModel, Table> {\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseQueryWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryWriterOrNull<EntsDataModel, Table> {\n // TODO: The index variant should not be allowed if\n // this query already used an index\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseTableBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n getMany<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n values: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n Indexes[Index][0]\n >[],\n ): PromiseEntsOrNulls<EntsDataModel, Table>;\n getMany(ids: GenericId<Table>[]): PromiseEntsOrNulls<EntsDataModel, Table>;\n getManyX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n values: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n Indexes[Index][0]\n >[],\n ): PromiseEnts<EntsDataModel, Table>;\n getManyX(ids: GenericId<Table>[]): PromiseEnts<EntsDataModel, Table>;\n /**\n * If given a valid ID for the given table, returns it, or returns null if the ID\n * is from a different table or is not a valid ID.\n *\n * This does not guarantee that the ID exists (i.e. `table(\"foo\").get(id)` may return `null`).\n */\n normalizeId(id: string): GenericId<Table> | null;\n /**\n * If given a valid ID for the given table, returns it, or throws if the ID\n * is from a different table or is not a valid ID.\n *\n * This does not guarantee that the ID exists (i.e. `table(\"foo\").get(id)` may return `null`).\n */\n normalizeIdX(id: string): GenericId<Table>;\n}\n\nexport interface PromiseTable<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseQuery<EntsDataModel, Table>,\n PromiseTableBase<EntsDataModel, Table> {\n get<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntOrNull<EntsDataModel, Table>;\n get(id: GenericId<Table>): PromiseEntOrNull<EntsDataModel, Table>;\n /**\n * Fetch a unique document from the DB using given index, throw if it doesn't exist.\n */\n getX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEnt<EntsDataModel, Table>;\n /**\n * Fetch a document from the DB for a given ID, throw if it doesn't exist.\n */\n getX(id: GenericId<Table>): PromiseEnt<EntsDataModel, Table>;\n\n /**\n * Return all documents in the table in given order.\n * Sort either by given index or by _creationTime.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQuery<EntsDataModel, Table>;\n\n /**\n * Query by running a full text search against a search index.\n *\n * Search queries must always search for some text within the index's\n * `searchField`. This query can optionally add equality filters for any\n * `filterFields` specified in the index.\n *\n * Documents will be returned in relevance order based on how well they\n * match the search text.\n *\n * To learn about full text search, see [Indexes](https://docs.convex.dev/text-search).\n *\n * @param indexName - The name of the search index to query.\n * @param searchFilter - A search filter expression constructed with the\n * supplied {@link SearchFilterBuilder}. This defines the full text search to run\n * along with equality filtering to run within the search index.\n * @returns - A query that searches for matching documents, returning them\n * in relevancy order.\n */\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ): PromiseOrderedQuery<EntsDataModel, Table>;\n}\n\nexport interface PromiseOrderedQueryBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[]>;\n}\n\nexport interface PromiseOrderedQuery<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n >,\n PromiseOrderedQueryBase<EntsDataModel, Table> {\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResult<EntsDataModel, Table>;\n\n take(n: number): PromiseEnts<EntsDataModel, Table>;\n\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n firstX(): PromiseEnt<EntsDataModel, Table>;\n\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n uniqueX(): PromiseEnt<EntsDataModel, Table>;\n}\n\nexport interface PromiseQuery<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQuery<EntsDataModel, Table> {\n order(order: \"asc\" | \"desc\"): PromiseOrderedQuery<EntsDataModel, Table>;\n}\n\nclass PromiseQueryOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n >\n implements PromiseQueryOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: () => Promise<Query<\n NamedTableInfo<EntsDataModel, Table>\n > | null>,\n ) {\n super(() => {});\n }\n\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): any {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n return query.filter(predicate);\n },\n );\n }\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ) {\n return new PromiseArrayImpl(async () => {\n const array = await this;\n if (array === null) {\n return null as TOutput[] | null;\n }\n return await Promise.all(array.map(callbackFn));\n });\n }\n\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): any {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n if (indexName !== undefined) {\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n )\n .withIndex(indexName)\n .order(order);\n }\n return query.order(order) as any;\n },\n );\n }\n\n paginate(paginationOpts: PaginationOptions) {\n return new PromisePaginationResultOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n return await query.paginate(paginationOpts);\n },\n );\n }\n\n take(n: number) {\n return new PromiseEntsOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n return await this._take(n);\n },\n false,\n );\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n return nullRetriever;\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n throw new Error(\"Query returned no documents\");\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n async docs() {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n const docs = await query.collect();\n return filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n docs,\n false,\n );\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value:\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((documents) =>\n documents === null\n ? null\n : documents.map((doc) =>\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n )\n .then(onfulfilled, onrejected);\n }\n\n async _take(n: number) {\n const query = await this.retrieve();\n return await takeFromQuery(\n query,\n n,\n this.ctx,\n this.entDefinitions,\n this.table,\n );\n }\n}\n\nexport interface PromisePaginationResultOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null> {\n docs(): Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput> | null>;\n}\n\nexport interface PromisePaginationResult<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n >\n > {\n docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>>>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput>>;\n}\n\nclass PromisePaginationResultOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null>\n implements PromisePaginationResultOrNull<EntsDataModel, Table>\n{\n constructor(\n private ctx: EntQueryCtx<EntsDataModel>,\n private entDefinitions: EntsDataModel,\n private table: Table,\n protected retrieve: () => Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>,\n ) {\n super(() => {});\n }\n\n async map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ) {\n const result = await this;\n if (result === null) {\n return null;\n }\n return {\n ...result,\n page: await Promise.all(result.page.map(callbackFn)),\n };\n }\n\n async docs() {\n const result = await this.retrieve();\n if (result === null) {\n return null;\n }\n return {\n ...result,\n page: (await filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n result.page,\n false,\n ))!,\n };\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value: PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((result) =>\n result === null\n ? null\n : {\n ...result,\n page: result.page.map((doc) =>\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n },\n )\n .then(onfulfilled, onrejected);\n }\n}\n\nclass PromiseTableImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseQueryOrNullImpl<EntsDataModel, Table> {\n constructor(\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n ) {\n super(ctx, entDefinitions, table, async () =>\n isSystemTable(table)\n ? (ctx.db.system.query(table as any) as any)\n : ctx.db.query(table),\n );\n }\n\n get(...args: any[]) {\n return this.getImpl(args);\n }\n\n getX(...args: any[]) {\n return this.getImpl(args, true);\n }\n\n getMany(...args: any[]) {\n return this.getManyImpl(args);\n }\n\n getManyX(...args: any[]) {\n return this.getManyImpl(args, true);\n }\n\n getImpl(args: any[], throwIfNull = false) {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n args.length === 1\n ? async () => {\n const id = args[0] as GenericId<Table>;\n if (this.normalizeId(id) === null) {\n throw new Error(`Invalid id \\`${id}\\` for table \"${this.table}\"`);\n }\n return {\n id,\n doc: async () => {\n const doc = await (isSystemTable(this.table)\n ? this.ctx.db.system.get(id as any)\n : this.ctx.db.get(id));\n if (throwIfNull && doc === null) {\n throw new Error(\n `Document not found with id \\`${id}\\` in table \"${this.table}\"`,\n );\n }\n return doc;\n },\n } as any; // any because PromiseEntWriterImpl expects non-nullable\n }\n : async () => {\n const [indexName, ...values] = args;\n const fieldNames = getIndexFields(\n this.entDefinitions,\n this.table,\n indexName,\n );\n const doc = await this.ctx.db\n .query(this.table)\n .withIndex(indexName, (q) =>\n values.reduce((q, value, i) => q.eq(fieldNames[i], value), q),\n )\n .unique();\n if (throwIfNull && doc === null) {\n throw new Error(\n `Table \"${this.table}\" does not contain document with field${values.reduce(\n (message, value, i) =>\n `${message} \"${fieldNames[i]}\" = \\`${value}\\``,\n \"\",\n )}`,\n );\n }\n return loadedRetriever(doc);\n },\n throwIfNull,\n );\n }\n\n getManyImpl(args: any[], throwIfNull = false) {\n return new PromiseEntsOrNullImpl(\n this.ctx as any,\n this.entDefinitions as any,\n this.table,\n args.length === 1\n ? async () => {\n const ids = args[0] as GenericId<Table>[];\n ids.forEach((id) => {\n if (this.normalizeId(id) === null) {\n throw new Error(\n `Invalid id \\`${id}\\` for table \"${this.table}\"`,\n );\n }\n });\n return await Promise.all(\n ids.map(async (id) => {\n const doc = await (isSystemTable(this.table)\n ? this.ctx.db.system.get(id as any)\n : this.ctx.db.get(id));\n if (throwIfNull && doc === null) {\n throw new Error(\n `Document not found with id \\`${id}\\` in table \"${this.table}\"`,\n );\n }\n return doc;\n }),\n );\n }\n : async () => {\n const [indexName, values] = args;\n return (await Promise.all(\n (values as any[]).map(async (value) => {\n const doc = await this.ctx.db\n .query(this.table)\n .withIndex(indexName, (q) => q.eq(indexName, value))\n .unique();\n if (throwIfNull && doc === null) {\n throw new Error(\n `Table \"${this.table}\" does not contain document with field \"${indexName}\" = \\`${value}\\``,\n );\n }\n return doc;\n }),\n )) as any;\n },\n throwIfNull,\n );\n }\n\n normalizeId(id: string): GenericId<Table> | null {\n return isSystemTable(this.table)\n ? this.ctx.db.system.normalizeId(this.table as any, id)\n : this.ctx.db.normalizeId(this.table, id);\n }\n\n // normalizeId or throw\n normalizeIdX(id: string): GenericId<Table> {\n const normalized = this.normalizeId(id);\n if (normalized === null) {\n throw new Error(`Invalid id \\`${id}\\` for table \"${this.table}\"`);\n }\n return normalized;\n }\n\n withIndex(\n indexName: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, typeof indexName>\n >,\n ) => IndexRange,\n ) {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n ).withIndex(indexName, indexRange);\n },\n );\n }\n\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ) {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n ).withSearchIndex(indexName, searchFilter) as any;\n },\n );\n }\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using `Promise.all()`.\nexport interface PromiseEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n // TODO: At this point there is nothing query specific here, and we can either:\n // 1. Return a generic lazy promise of the list.\n // 2. Not give any methods, because they might lead devs down the wrong path.\n // // This just returns the first retrieved document, it does not optimize\n // // the previous steps in the query.\n // first(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, it does not optimize\n // // the previous steps in the query. Otherwise it behaves like db.query().unique().\n // unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n | EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null\n > {\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\nexport interface PromiseEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n > {\n // TODO: At this point there is nothing query specific here, and we can either:\n // 1. Return a generic lazy promise of the list.\n // 2. Not give any methods, because they might lead devs down the wrong path.\n // // This just returns the first retrieved document, it does not optimize\n // // the previous steps in the query.\n // first(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the first retrieved document, or throws if there\n // // are no documents. It does not optimize the previous steps in the query.\n // firstX(): PromiseEnt<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, it does not optimize\n // // the previous steps in the query. Otherwise it behaves like db.query().unique().\n // unique(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, or throws if there\n // // are no documents. It does not optimize the previous steps in the query.\n // // Otherwise it behaves like db.query().unique().\n // uniqueX(): PromiseEnt<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[]>;\n}\n\n// Also implements `PromiseEntsOrNulls`, so individual docs can be null\nclass PromiseEntsOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n >\n implements PromiseEntsOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n private retrieve: () => Promise<\n DocumentByName<EntsDataModel, Table>[] | null\n >,\n private throwIfNull: boolean,\n ) {\n super(() => {});\n }\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ) {\n return new PromiseArrayImpl(async () => {\n const array = await this;\n if (array === null) {\n return null as TOutput[] | null;\n }\n return await Promise.all(array.map(callbackFn));\n });\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n return loadedRetriever(docs[0] ?? null);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n const doc = docs[0] ?? undefined;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length > 1) {\n throw new Error(\"unique() query returned more than one result\");\n }\n return loadedRetriever(docs[0] ?? null);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length > 1) {\n throw new Error(\"unique() query returned more than one result\");\n }\n if (docs.length < 1) {\n throw new Error(\"unique() query returned no documents\");\n }\n return loadedRetriever(docs[0]);\n },\n true,\n );\n }\n\n async docs() {\n const docs = await this.retrieve();\n return filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n docs,\n this.throwIfNull,\n );\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value:\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((docs) =>\n // Handles PromiseEntsOrNulls\n docs === null\n ? null\n : docs.map((doc) =>\n doc === null\n ? (null as any)\n : entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n )\n .then(onfulfilled, onrejected);\n }\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\nexport interface PromiseEntsOrNulls<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n (Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> | null)[]\n > {}\n\nexport interface PromiseEdgeOrderedEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsOrNull<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge. Returns null if chained to a null result.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean | null>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsWriterOrNull<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge. Returns null if chained to a null result.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean | null>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEnts<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResult<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEnts<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or throws if there\n * are no ents on the other end of the edge.\n */\n firstX(): PromiseEnt<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * or throws if there are none or more than one.\n */\n uniqueX(): PromiseEnt<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEnts<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEnts<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsWriter<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriter<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsWriter<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or throws if there\n * are no ents on the other end of the edge.\n */\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * or throws if there are none or more than one.\n */\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsWriter<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsWriter<EntsDataModel, Table>;\n}\n\nclass PromiseEdgeOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends PromiseEntsOrNullImpl<EntsDataModel, Table>\n implements PromiseEdgeEntsOrNull<EntsDataModel, Table>\n{\n constructor(\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n private edgeDefinition: EdgeConfig & {\n cardinality: \"multiple\";\n type: \"ref\";\n },\n private retrieveSourceId: () => Promise<GenericId<string> | null>,\n private retrieveQuery: () => Promise<Query<GenericTableInfo> | null>,\n private retrieveDoc: (\n edgeDoc: GenericDocument,\n ) => Promise<DocumentByName<EntsDataModel, Table>> = async (edgeDoc) => {\n const sourceId = edgeDoc[edgeDefinition.field] as string;\n const targetId = edgeDoc[edgeDefinition.ref] as string;\n const doc = await this.ctx.db.get(targetId as any);\n if (doc === null) {\n throw new Error(\n `Dangling reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" for ` +\n `document with ID \"${sourceId}\": ` +\n `Could not find a document with ID \"${targetId}\"` +\n ` in table \"${edgeDefinition.to}\" (edge document ID is \"${\n edgeDoc._id as string\n }\").`,\n );\n }\n return doc;\n },\n ) {\n super(\n ctx,\n entDefinitions,\n table,\n async () => {\n const query = await retrieveQuery();\n if (query === null) {\n return null;\n }\n const edgeDocs = await query.collect();\n return await Promise.all(edgeDocs.map(retrieveDoc));\n },\n false,\n );\n }\n\n async has(targetId: GenericId<Table>) {\n const sourceId = await this.retrieveSourceId();\n if (sourceId === null) {\n return null;\n }\n const edgeDoc = await this.ctx.db\n .query(this.edgeDefinition.table)\n .withIndex(edgeCompoundIndexName(this.edgeDefinition), (q) =>\n (q.eq(this.edgeDefinition.field, sourceId as any) as any).eq(\n this.edgeDefinition.ref,\n targetId,\n ),\n )\n .first();\n return edgeDoc !== null;\n }\n\n order(order: \"asc\" | \"desc\") {\n return new PromiseEdgeOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n this.edgeDefinition,\n this.retrieveSourceId,\n async () => {\n const query = await this.retrieveQuery();\n if (query === null) {\n return null;\n }\n // This class supports both ordered and unordered queries,\n // so we pretend this one can be ordered again, interface types\n // won't allow it.\n return query.order(order) as Query<GenericTableInfo>;\n },\n );\n }\n\n paginate(paginationOpts: PaginationOptions) {\n return new PromisePaginationResultOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieveQuery();\n if (query === null) {\n return null;\n }\n const result = await query.paginate(paginationOpts);\n return {\n ...result,\n page: await Promise.all(result.page.map(this.retrieveDoc)),\n };\n },\n );\n }\n\n take(n: number) {\n return new PromiseEntsOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n return await this._take(n);\n },\n false,\n );\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n return nullRetriever;\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n throw new Error(\"Query returned no documents\");\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n async _take(n: number) {\n const query = await this.retrieveQuery();\n return await takeFromQuery(\n query,\n n,\n this.ctx,\n this.entDefinitions,\n this.table,\n this.retrieveDoc,\n );\n }\n}\n\nexport interface PromiseEntOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrNull<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table> | null>;\n}\n\nexport interface PromiseEnt<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdge<EntsDataModel, Table, Edge>;\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrThrow<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table>>;\n}\n\nclass PromiseEntOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null>\n implements PromiseEntOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: DocRetriever<\n GenericId<Table> | null,\n DocumentByName<EntsDataModel, Table> | null\n >,\n protected throwIfNull: boolean,\n ) {\n super(() => {});\n }\n\n async doc() {\n const { id, doc: getDoc } = await this.retrieve();\n if (id === null) {\n return null;\n }\n const doc = await getDoc();\n if (doc === null) {\n return null;\n }\n const readPolicy = getReadRule(this.entDefinitions, this.table);\n if (readPolicy !== undefined) {\n const decision = await readPolicy(\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n );\n if (this.throwIfNull && !decision) {\n throw new Error(\n `Document cannot be read with id \\`${doc._id as string}\\` in table \"${\n this.table\n }\"`,\n );\n }\n return decision ? doc : null;\n }\n return doc;\n }\n\n then<\n TResult1 = Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.doc()\n .then((doc) =>\n doc === null\n ? null\n : entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n )\n .then(onfulfilled, onrejected);\n }\n\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(edge: Edge) {\n return this.edgeImpl(edge);\n }\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(edge: Edge) {\n return this.edgeImpl(edge, true);\n }\n\n edgeImpl<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n throwIfNull = false,\n ) {\n const edgeDefinition = getEdgeDefinitions(this.entDefinitions, this.table)[\n edge\n ];\n\n if (edgeDefinition.cardinality === \"multiple\") {\n if (edgeDefinition.type === \"ref\") {\n return new PromiseEdgeOrNullImpl(\n this.ctx,\n this.entDefinitions,\n edgeDefinition.to,\n edgeDefinition,\n async () => {\n const { id } = await this.retrieve();\n return id;\n },\n async () => {\n const { id } = await this.retrieve();\n if (id === null) {\n return null;\n }\n return this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeDefinition.field,\n (q) => q.eq(edgeDefinition.field, id as any) as any,\n );\n },\n ) as any;\n }\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n edgeDefinition.to,\n async () => {\n const { id } = await this.retrieve();\n if (id === null) {\n return null;\n }\n return this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n );\n },\n ) as any;\n }\n\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n edgeDefinition.to,\n async () => {\n const { id, doc: getDoc } = await this.retrieve();\n if (id === null) {\n return nullRetriever;\n }\n\n if (edgeDefinition.type === \"ref\") {\n const otherDoc = await this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .unique();\n if (throwIfNull && otherDoc === null) {\n throw new Error(\n `Edge \"${\n edgeDefinition.name\n }\" does not exist for document with ID \"${id as string}\"`,\n );\n }\n return loadedRetriever(otherDoc);\n }\n const doc = (await getDoc())!;\n const otherId = doc[edgeDefinition.field] as any;\n return {\n id: otherId,\n doc: async () => {\n if (otherId === undefined) {\n if (edgeDefinition.optional) {\n return null;\n }\n throw new Error(\n `Unexpected null reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" on document with ID \"${id}\": ` +\n `Expected an ID for a document in table \"${edgeDefinition.to}\".`,\n );\n }\n const otherDoc = await this.ctx.db.get(otherId);\n // _scheduled_functions cannot be made dangling-reference-free,\n // because they are deleted by Convex automatically.\n if (\n otherDoc === null &&\n edgeDefinition.to !== \"_scheduled_functions\"\n ) {\n throw new Error(\n `Dangling reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" on document with ID \"${id}\": ` +\n `Could not find a document with ID \"${otherId}\"` +\n ` in table \"${edgeDefinition.to}\".`,\n );\n }\n return otherDoc;\n },\n };\n },\n throwIfNull,\n ) as any;\n }\n}\n\nexport interface PromiseArrayOrNull<T> extends Promise<T[] | null> {\n filter<S extends T>(\n predicate: (value: T, index: number, array: T[] | null) => value is S,\n ): Promise<S[] | null>;\n\n filter(\n predicate: (value: T, index: number, array: T[] | null) => unknown,\n ): Promise<T[] | null>;\n}\n\nexport interface PromiseArray<T> extends Promise<T[]> {\n filter<S extends T>(\n predicate: (value: T, index: number, array: T[]) => value is S,\n ): Promise<S[]>;\n\n filter(\n predicate: (value: T, index: number, array: T[]) => unknown,\n ): Promise<T[]>;\n}\n\nclass PromiseArrayImpl<T>\n extends Promise<T[] | null>\n implements PromiseArrayOrNull<T>\n{\n constructor(protected retrieve: () => Promise<T[] | null>) {\n super(() => {});\n }\n\n async filter<S extends T>(\n predicate: (value: T, index: number, array: T[] | null) => value is S,\n ) {\n const array = await this.retrieve();\n if (array === null) {\n return null;\n }\n return array.filter(predicate);\n }\n\n then<TResult1 = T[] | null, TResult2 = never>(\n onfulfilled?:\n | ((value: T[] | null) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.retrieve().then(onfulfilled, onrejected);\n }\n}\n\nexport function entWrapper<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(\n fields: DocumentByName<EntsDataModel, Table>,\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n): Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> {\n const doc = { ...fields };\n const queryInterface = new PromiseEntWriterImpl(\n ctx as any,\n entDefinitions as any,\n table,\n async () => ({ id: doc._id as any, doc: async () => doc }),\n // this `true` doesn't matter, the queryInterface cannot be awaited\n true,\n );\n Object.defineProperty(doc, \"edge\", {\n value: (edge: any) => {\n return queryInterface.edge(edge);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"edgeX\", {\n value: (edge: any) => {\n return queryInterface.edgeX(edge);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"_edges\", {\n value: () => {\n return getEdgeDefinitions(entDefinitions, table);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"doc\", {\n value: () => {\n return doc;\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"patch\", {\n value: (value: any) => {\n return queryInterface.patch(value);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"replace\", {\n value: (value: any) => {\n return queryInterface.replace(value);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"delete\", {\n value: () => {\n return queryInterface.delete();\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.entries((entDefinitions as any)[table]?.defaults ?? []).map(\n ([field, value]) => {\n if (doc[field] === undefined) {\n (doc as any)[field] = value;\n }\n },\n );\n return doc as any;\n}\n\nexport function entsTableFactory<\n Ctx extends EntQueryCtx<any>,\n EntsDataModel extends GenericEntsDataModel,\n>(\n ctx: Ctx,\n entDefinitions: EntsDataModel,\n options?: {\n scheduledDelete?: ScheduledDeleteFuncRef;\n },\n): Ctx extends EntMutationCtx<any>\n ? EntsTableWriter<EntsDataModel>\n : EntsTable<EntsDataModel> {\n const enrichedCtx = options !== undefined ? { ...ctx, ...options } : ctx;\n const table = (\n table: TableNamesInDataModel<EntsDataModel>,\n indexName?: string,\n indexRange?: any,\n ) => {\n // Consider being strict here if people struggle with setup:\n // if (typeof ctx.db?.query !== \"function\") {\n // throw new Error(\n // `Expected context with \\`db\\`, got \\`${JSON.stringify(ctx)}\\``\n // );\n // }\n if (typeof table !== \"string\") {\n throw new Error(`Expected table name, got \\`${table as any}\\``);\n }\n\n if (indexName !== undefined) {\n return new PromiseTableImpl(\n enrichedCtx as any,\n entDefinitions,\n table,\n ).withIndex(indexName, indexRange);\n }\n if ((ctx.db as any).insert !== undefined) {\n return new PromiseTableWriterImpl(\n enrichedCtx as any,\n entDefinitions,\n table,\n );\n }\n return new PromiseTableImpl(enrichedCtx as any, entDefinitions, table);\n };\n table.system = table;\n return table as any;\n}\n\ntype EntsTableReader<EntsDataModel extends GenericEntsDataModel> = {\n <\n Table extends TableNamesInDataModel<EntsDataModel>,\n IndexName extends IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n table: Table,\n indexName: IndexName,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => IndexRange,\n ): PromiseQuery<EntsDataModel, Table>;\n <Table extends TableNamesInDataModel<EntsDataModel>>(\n table: Table,\n ): PromiseTable<EntsDataModel, Table>;\n};\n\nexport type EntsTable<EntsDataModel extends GenericEntsDataModel> =\n EntsTableReader<EntsDataModel> & {\n system: EntsTableReader<EntsSystemDataModel>;\n };\n\nexport type EntsTableWriter<EntsDataModel extends GenericEntsDataModel> = {\n <\n Table extends TableNamesInDataModel<EntsDataModel>,\n IndexName extends IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n table: Table,\n indexName: IndexName,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => IndexRange,\n ): PromiseQueryWriter<EntsDataModel, Table>;\n <Table extends TableNamesInDataModel<EntsDataModel>>(\n table: Table,\n ): PromiseTableWriter<Table, EntsDataModel>;\n\n system: EntsTableReader<EntsSystemDataModel>;\n};\n\ndeclare class EntInstance<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdge<EntsDataModel, Table, Edge>;\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrThrow<EntsDataModel, Table, Edge>;\n doc(): DocumentByName<EntsDataModel, Table>;\n}\n\nexport type Ent<\n Table extends TableNamesInDataModel<EntsDataModel>,\n Doc extends DocumentByName<EntsDataModel, Table>,\n EntsDataModel extends GenericEntsDataModel,\n> = Doc & EntInstance<EntsDataModel, Table>;\n\nexport type GenericEnt<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> = Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>;\n\nexport type PromiseEdge<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEnts<EntsDataModel, ToTable>,\n PromiseQuery<EntsDataModel, ToTable>,\n ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? PromiseEntOrNull<EntsSystemDataModel, ToTable>\n : PromiseEntOrNull<EntsDataModel, ToTable>,\n ToTable extends \"_storage\"\n ? PromiseEnt<EntsSystemDataModel, ToTable>\n : ToTable extends \"_scheduled_functions\"\n ? PromiseEntOrNull<EntsSystemDataModel, ToTable>\n : PromiseEnt<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeOrThrow<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEnts<EntsDataModel, ToTable>,\n PromiseQuery<EntsDataModel, ToTable>,\n PromiseEnt<EntsDataModel, ToTable>,\n PromiseEnt<EntsDataModel, ToTable>\n>;\n\ntype PromiseEdgeOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsOrNull<EntsDataModel, ToTable>,\n PromiseQueryOrNull<EntsDataModel, ToTable>,\n PromiseEntOrNull<EntsDataModel, ToTable>,\n PromiseEntOrNull<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriter<EntsDataModel, ToTable>,\n PromiseQueryWriter<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriterOrThrow<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriter<EntsDataModel, ToTable>,\n PromiseQueryWriter<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriterOrNull<EntsDataModel, ToTable>,\n PromiseQueryWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>\n>;\n\nexport interface PromiseOrderedQueryWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n >,\n PromiseOrderedQueryBase<EntsDataModel, Table> {\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriter<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n take(n: number): PromiseEntsWriter<EntsDataModel, Table>;\n\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromiseQueryWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryWriter<EntsDataModel, Table> {\n order(order: \"asc\" | \"desc\"): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\nexport interface PromiseEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEnts<EntsDataModel, Table> {\n // This just returns the first retrieved document, or throws if there\n // are no documents. It does not optimize the previous steps in the query.\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n // This just returns the unique retrieved document, or throws if there\n // are no documents. It does not optimize the previous steps in the query.\n // Otherwise it behaves like db.query().unique().\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromisePaginationResultWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<PaginationResult<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null> {\n docs(): Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput> | null>;\n}\n\nexport interface PromisePaginationResultWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n PaginationResult<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n >\n > {\n docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>>>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput>>;\n}\n\nexport interface PromiseTableWriter<\n Table extends TableNamesInDataModel<EntsDataModel>,\n EntsDataModel extends GenericEntsDataModel,\n> extends PromiseQueryWriter<EntsDataModel, Table>,\n PromiseTableBase<EntsDataModel, Table> {\n get<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntWriterOrNull<EntsDataModel, Table>;\n get(id: GenericId<Table>): PromiseEntWriterOrNull<EntsDataModel, Table>;\n /**\n * Fetch a unique document from the DB using given index, throw if it doesn't exist.\n */\n getX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntWriter<EntsDataModel, Table>;\n /**\n * Fetch a document from the DB for a given ID, throw if it doesn't exist.\n */\n getX(id: GenericId<Table>): PromiseEntWriter<EntsDataModel, Table>;\n\n /**\n * Return all documents in the table in given order.\n * Sort either by given index or by _creationTime.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n\n /**\n * Query by running a full text search against a search index.\n *\n * Search queries must always search for some text within the index's\n * `searchField`. This query can optionally add equality filters for any\n * `filterFields` specified in the index.\n *\n * Documents will be returned in relevance order based on how well they\n * match the search text.\n *\n * To learn about full text search, see [Indexes](https://docs.convex.dev/text-search).\n *\n * @param indexName - The name of the search index to query.\n * @param searchFilter - A search filter expression constructed with the\n * supplied {@link SearchFilterBuilder}. This defines the full text search to run\n * along with equality filtering to run within the search index.\n * @returns - A query that searches for matching documents, returning them\n * in relevancy order.\n */\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n /**\n * Insert a new document into a table.\n *\n * @param table - The name of the table to insert a new document into.\n * @param value - The {@link Value} to insert into the given table.\n * @returns - {@link GenericId} of the new document.\n */\n insert(\n value: Expand<\n WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n /**\n * Insert new documents into a table.\n *\n * @param table - The name of the table to insert a new document into.\n * @param value - The {@link Value} to insert into the given table.\n * @returns - {@link GenericId} of the new document.\n */\n // TODO: Chain methods to get the written documents?\n insertMany(\n values: Expand<\n WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >[],\n ): Promise<GenericId<Table>[]>;\n}\n\nclass PromiseTableWriterImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseTableImpl<EntsDataModel, Table> {\n private base: WriterImplBase<EntsDataModel, Table>;\n\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n ) {\n super(ctx, entDefinitions, table);\n this.base = new WriterImplBase(ctx, entDefinitions, table);\n }\n\n insert(\n value: WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n await this.base.checkReadAndWriteRule(\"create\", undefined, value);\n await this.base.checkUniqueness(value);\n const fields = this.base.fieldsOnly(value as any);\n const docId = await this.ctx.db.insert(this.table, fields as any);\n const edges: EdgeChanges = {};\n Object.keys(value).forEach((key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\")\n ) {\n return;\n }\n\n edges[key] = {\n add:\n edgeDefinition.cardinality === \"single\"\n ? [value[key] as GenericId<any>]\n : (value[key] as GenericId<any>[]),\n };\n });\n await this.base.writeEdges(docId, edges);\n return docId;\n },\n );\n }\n\n // TODO: fluent API\n async insertMany(\n values: WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >[],\n ) {\n return await Promise.all(values.map((value) => this.insert(value)));\n }\n}\n\nexport interface PromiseEntWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriterOrNull<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table> | null>;\n}\n\nexport interface PromiseEntWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriter<EntsDataModel, Table, Edge>;\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriterOrThrow<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table>>;\n\n /**\n * Patch this existing document, shallow merging it with the given partial\n * document.\n *\n * New fields are added. Existing fields are overwritten. Fields set to\n * `undefined` are removed.\n *\n * @param value - The partial {@link GenericDocument} to merge into this document. If this new value\n * specifies system fields like `_id`, they must match the document's existing field values.\n */\n patch(\n value: Partial<\n Expand<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Replace the value of an existing document, overwriting its old value.\n *\n * @param value - The new {@link GenericDocument} for the document. This value can omit the system fields,\n * and the database will preserve them in.\n */\n replace(\n value: Expand<\n WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Delete this existing document.\n *\n * @param id - The {@link GenericId} of the document to remove.\n */\n delete(): Promise<GenericId<Table>>;\n}\n\nclass PromiseEntWriterImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntOrNullImpl<EntsDataModel, Table> {\n private base: WriterImplBase<EntsDataModel, Table>;\n\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: DocRetriever<\n GenericId<Table> | null,\n DocumentByName<EntsDataModel, Table> | null\n >,\n protected throwIfNull: boolean,\n ) {\n super(ctx, entDefinitions, table, retrieve, throwIfNull);\n this.base = new WriterImplBase(ctx, entDefinitions, table);\n }\n\n patch(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const { id: docId } = await this.retrieve();\n const id = docId!;\n await this.base.checkReadAndWriteRule(\"update\", id, value);\n await this.base.checkUniqueness(value, id);\n const fields = this.base.fieldsOnly(value);\n await this.ctx.db.patch(id, fields as any);\n\n const edges: EdgeChanges = {};\n await Promise.all(\n Object.keys(value).map(async (key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\")\n ) {\n // The built-in patch takes care of updating the field\n return;\n }\n if (edgeDefinition.cardinality === \"single\") {\n throw new Error(\n `Cannot set 1:1 edge \"${edgeDefinition.name}\" on ent in table ` +\n `\"${this.table}\", update the ent in \"${edgeDefinition.to}\" ` +\n `table instead.`,\n );\n // const existing = await this.ctx.db\n // .query(edgeDefinition.to)\n // .withIndex(edgeDefinition.ref, (q) =>\n // q.eq(edgeDefinition.ref, docId as any)\n // )\n // .unique();\n\n // edges[key] = {\n // add: value[key] as GenericId<any>,\n // remove: existing?._id as GenericId<any> | undefined,\n // };\n } else {\n if (edgeDefinition.type === \"field\") {\n throw new Error(\n `Cannot set 1:many edges \"${edgeDefinition.name}\" on ent in table ` +\n `\"${this.table}\", update the ents in \"${edgeDefinition.to}\" ` +\n `table instead.`,\n );\n } else {\n const { add, remove } = value[key]!;\n const removeEdges = (\n await Promise.all(\n (remove ?? []).map(async (otherId) =>\n (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeCompoundIndexName(edgeDefinition),\n (q) =>\n (q.eq(edgeDefinition.field, id as any) as any).eq(\n edgeDefinition.ref,\n otherId,\n ),\n )\n .collect()\n ).concat(\n edgeDefinition.symmetric\n ? await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeCompoundIndexName(edgeDefinition),\n (q) =>\n (\n q.eq(\n edgeDefinition.field,\n otherId as any,\n ) as any\n ).eq(edgeDefinition.ref, id),\n )\n .collect()\n : [],\n ),\n ),\n )\n )\n .flat()\n .map((edgeDoc) => edgeDoc._id as GenericId<any>);\n edges[key] = {\n add,\n removeEdges,\n };\n }\n }\n }),\n );\n await this.base.writeEdges(id, edges);\n return id;\n },\n );\n }\n\n replace(\n value: WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const { id } = await this.retrieve();\n const docId = id!;\n await this.base.checkReadAndWriteRule(\"update\", docId, value);\n await this.base.checkUniqueness(value, docId);\n const fields = this.base.fieldsOnly(value as any);\n await this.ctx.db.replace(docId, fields as any);\n\n const edges: EdgeChanges = {};\n\n await Promise.all(\n Object.values(\n getEdgeDefinitions(this.entDefinitions, this.table),\n ).map(async (edgeDefinition) => {\n const key = edgeDefinition.name;\n const idOrIds = value[key];\n if (idOrIds === undefined) {\n return;\n }\n if (edgeDefinition.cardinality === \"single\") {\n if (edgeDefinition.type === \"ref\") {\n const oldDoc = (await this.ctx.db.get(docId))!;\n if (oldDoc[key] !== undefined && oldDoc[key] !== idOrIds) {\n // This would be only allowed if the edge is optional\n // on the field side, which is not supported\n\n // TODO: Fix!\n\n throw new Error(\"Cannot set 1:1 edge from ref end.\");\n // edges[key] = {\n // add: idOrIds as GenericId<any>,\n // remove: oldDoc[key] as GenericId<any> | undefined,\n // };\n }\n }\n } else {\n if (edgeDefinition.type === \"field\") {\n throw new Error(\"Cannot set 1:many edge from many end.\");\n // const existing = (\n // await this.ctx.db\n // .query(edgeDefinition.to)\n // .withIndex(edgeDefinition.ref, (q) =>\n // q.eq(edgeDefinition.ref, docId as any)\n // )\n // .collect()\n // ).map((doc) => doc._id);\n // edges[key] = {\n // add: idOrIds as GenericId<any>[],\n // remove: { remove: true },\n // };\n } else {\n const requested = new Set(idOrIds);\n const removeEdges = (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.field, (q) =>\n q.eq(edgeDefinition.field, docId as any),\n )\n .collect()\n )\n .map((doc) => [doc._id, doc[edgeDefinition.ref]] as const)\n .concat(\n edgeDefinition.symmetric\n ? (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, docId as any),\n )\n .collect()\n ).map(\n (doc) =>\n [doc._id, doc[edgeDefinition.field]] as const,\n )\n : [],\n )\n .filter(([_edgeId, otherId]) => {\n if (requested.has(otherId as any)) {\n requested.delete(otherId as any);\n return false;\n }\n return true;\n })\n .map(([edgeId]) => edgeId as GenericId<any>);\n edges[key] = {\n add: idOrIds as GenericId<any>[],\n removeEdges,\n };\n }\n }\n }),\n );\n await this.base.writeEdges(docId, edges);\n return docId;\n },\n );\n }\n\n async delete() {\n const { id: docId } = await this.retrieve();\n const id = docId!;\n return this.base.deleteId(id, \"default\");\n }\n}\n\ndeclare class EntWriterInstance<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends EntInstance<EntsDataModel, Table> {\n /**\n * Patch this existing document, shallow merging it with the given partial\n * document.\n *\n * New fields are added. Existing fields are overwritten. Fields set to\n * `undefined` are removed.\n *\n * @param value - The partial {@link GenericDocument} to merge into this document. If this new value\n * specifies system fields like `_id`, they must match the document's existing field values.\n */\n patch(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Replace the value of this existing document, overwriting its old value.\n *\n * @param value - The new {@link GenericDocument} for the document. This value can omit the system fields,\n * and the database will preserve them in.\n */\n replace(\n value: WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Delete this existing document.\n *\n * @param id - The {@link GenericId} of the document to remove.\n */\n delete(): Promise<GenericId<Table>>;\n}\n\n// This type is strange: The ordering is strange,\n// and the `Doc` would not have to be generic:\n// This is all just so that the type shows useful\n// informatin when hovering values.\ntype EntWriter<\n Table extends TableNamesInDataModel<EntsDataModel>,\n Doc extends DocumentByName<EntsDataModel, Table>,\n EntsDataModel extends GenericEntsDataModel,\n> = Doc & EntWriterInstance<EntsDataModel, Table>;\n\nexport type GenericEntWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> = EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>;\n\nexport interface PromiseEntId<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<GenericId<Table>> {\n get(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nclass PromiseEntIdImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<GenericId<Table>>\n implements PromiseEntId<EntsDataModel, Table>\n{\n constructor(\n private ctx: EntMutationCtx<EntsDataModel>,\n private entDefinitions: EntsDataModel,\n private table: Table,\n private retrieve: () => Promise<GenericId<Table>>,\n ) {\n super(() => {});\n }\n\n get() {\n return new PromiseEntWriterImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const id = await this.retrieve();\n return { id, doc: async () => this.ctx.db.get(id) };\n },\n true,\n ) as any;\n }\n\n then<TResult1 = GenericId<Table>, TResult2 = never>(\n onfulfilled?:\n | ((value: GenericId<Table>) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null,\n ): Promise<TResult1 | TResult2> {\n return this.retrieve().then(onfulfilled, onrejected);\n }\n}\n\nexport interface EntQueryCtx<DataModel extends GenericDataModel> {\n db: GenericDatabaseReader<DataModel>;\n vectorSearch?: undefined;\n}\n\nexport interface EntMutationCtx<DataModel extends GenericDataModel>\n extends EntQueryCtx<DataModel> {\n db: GenericDatabaseWriter<DataModel>;\n\n storage: StorageWriter;\n scheduler: Scheduler;\n}\n\nexport type DocRetriever<ID, Doc> = () => Promise<{\n id: ID;\n doc: () => Promise<Doc>;\n}>;\n\nconst nullRetriever = {\n id: null,\n doc: async () => null,\n};\n\n// function idRetriever<\n// DataModel extends GenericDataModel,\n// Table extends TableNamesInDataModel<DataModel>\n// >(ctx: EntQueryCtx<DataModel>, id: GenericId<Table>) {\n// return {\n// id,\n// doc: async () => ctx.db.get(id),\n// };\n// }\n\nfunction loadedRetriever<\n DataModel extends GenericDataModel,\n Table extends TableNamesInDataModel<DataModel>,\n>(doc: DocumentByName<DataModel, Table> | null) {\n return {\n id: (doc?._id ?? null) as GenericId<Table> | null,\n doc: async () => doc,\n };\n}\n\ntype Rules = Record<string, RuleConfig>;\n\ntype RuleConfig = {\n read?: (doc: GenericDocument) => Promise<boolean>;\n write?: (\n args:\n | {\n operation: \"create\";\n ent: undefined;\n value: WithoutSystemFields<GenericDocument>;\n }\n | {\n operation: \"update\";\n ent: Ent<any, GenericDocument, any>;\n value: Partial<WithoutSystemFields<GenericDocument>>;\n }\n | {\n operation: \"delete\";\n ent: Ent<any, GenericDocument, any>;\n value: undefined;\n },\n ) => Promise<boolean>;\n};\n\nexport function addEntRules<EntsDataModel extends GenericEntsDataModel>(\n entDefinitions: EntsDataModel,\n rules: {\n [Table in keyof EntsDataModel]?: Table extends TableNamesInDataModel<EntsDataModel>\n ? {\n read?: (\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n ) => Promise<boolean>;\n write?: (\n args:\n | {\n operation: \"create\";\n ent: undefined;\n value: WithoutSystemFields<\n DocumentByName<EntsDataModel, Table>\n >;\n }\n | {\n operation: \"update\";\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >;\n value: Partial<\n WithoutSystemFields<DocumentByName<EntsDataModel, Table>>\n >;\n }\n | {\n operation: \"delete\";\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >;\n value: undefined;\n },\n ) => Promise<boolean>;\n }\n : never;\n },\n): EntsDataModel {\n return { ...entDefinitions, rules };\n}\n\nasync function takeFromQuery(\n query: Query<GenericTableInfo> | null,\n n: number,\n ctx: EntQueryCtx<any>,\n entDefinitions: GenericEntsDataModel,\n table: string,\n mapToResult?: (retrieved: GenericDocument) => Promise<GenericDocument>,\n) {\n if (query === null) {\n return null;\n }\n const readPolicy = getReadRule(entDefinitions, table);\n if (readPolicy === undefined) {\n const results = await query.take(n);\n if (mapToResult === undefined) {\n return results;\n }\n return Promise.all(results.map(mapToResult));\n }\n let numItems = n;\n const docs = [];\n let hasMore = true;\n const iterator = query[Symbol.asyncIterator]();\n while (hasMore && docs.length < n) {\n const page = [];\n for (let i = 0; i < numItems; i++) {\n const { done, value } = await iterator.next();\n if (done) {\n hasMore = false;\n break;\n }\n page.push(mapToResult === undefined ? value : await mapToResult(value));\n }\n docs.push(\n ...(await filterByReadRule(\n ctx,\n entDefinitions,\n table,\n page,\n false,\n ))!.slice(0, n - docs.length),\n );\n numItems = Math.min(64, numItems * 2);\n }\n return docs;\n}\n\nasync function filterByReadRule<Doc extends GenericDocument>(\n ctx: EntQueryCtx<any>,\n entDefinitions: GenericEntsDataModel,\n table: string,\n docs: Doc[] | null,\n throwIfNull: boolean,\n) {\n if (docs === null) {\n return null;\n }\n const readPolicy = getReadRule(entDefinitions, table);\n if (readPolicy === undefined) {\n return docs;\n }\n const decisions = await Promise.all(\n docs.map(async (doc) => {\n const decision = await readPolicy(\n entWrapper(doc, ctx, entDefinitions, table),\n );\n if (throwIfNull && !decision) {\n throw new Error(\n `Document cannot be read with id \\`${\n doc._id as string\n }\\` in table \"${table}\"`,\n );\n }\n return decision;\n }),\n );\n return docs.filter((_, i) => decisions[i]);\n}\n\nfunction getIndexFields(\n entDefinitions: GenericEntsDataModel,\n table: string,\n index: string,\n) {\n return (entDefinitions[table].indexes as unknown as Record<string, string[]>)[\n index\n ];\n}\n\nexport function getReadRule(\n entDefinitions: GenericEntsDataModel,\n table: string,\n) {\n return (entDefinitions.rules as Rules)?.[table]?.read;\n}\n\nexport function getWriteRule(\n entDefinitions: GenericEntsDataModel,\n table: string,\n) {\n return (entDefinitions.rules as Rules)?.[table]?.write;\n}\n\nexport function getDeletionConfig<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(entDefinitions: EntsDataModel, table: Table) {\n return (entDefinitions[table] as any).deletionConfig as\n | DeletionConfig\n | undefined;\n}\n","import {\n DataModelFromSchemaDefinition,\n DefineSchemaOptions,\n GenericDataModel,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IndexTiebreakerField,\n SchemaDefinition,\n SearchIndexConfig,\n TableDefinition,\n VectorIndexConfig,\n defineSchema,\n} from \"convex/server\";\nimport {\n GenericId,\n GenericValidator,\n ObjectType,\n VAny,\n VFloat64,\n VId,\n VObject,\n VOptional,\n VUnion,\n Validator,\n asObjectValidator,\n v,\n} from \"convex/values\";\n\nexport function defineEntSchema<\n Schema extends Record<string, EntDefinition>,\n StrictTableNameTypes extends boolean = true,\n>(\n schema: Schema,\n options?: DefineSchemaOptions<StrictTableNameTypes>,\n): SchemaDefinition<Schema, StrictTableNameTypes> {\n // Set the properties of edges which requires knowing their inverses,\n // and add edge tables.\n const tableNames = Object.keys(schema);\n for (const tableName of tableNames) {\n const table = schema[tableName];\n for (const edge of edgeConfigsBeforeDefineSchema(table)) {\n if (\n // Skip inverse edges, we process their forward edges\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n (edge.inverse !== undefined ||\n // symmetric is only set by defineEntSchema,\n // so we already processed the pair\n (edge as unknown as EdgeConfigMultipleRef).symmetric !== undefined)\n ) {\n continue;\n }\n\n const otherTableName = edge.to;\n if (otherTableName.startsWith(\"_\")) {\n if (edge.cardinality !== \"single\") {\n throw new Error(\n `Many:many edge \"${edge.name}\" in table \"${tableName}\" ` +\n `points to a system table \"${otherTableName}\", but only 1:1 ` +\n `edges can point to system tables`,\n );\n }\n if (edge.type !== \"field\") {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `pointing to a system table \"${otherTableName}\" must store ` +\n `the edge by storing the system document ID. Remove ` +\n `the \\`ref\\` option.`,\n );\n }\n if (edge.deletion === \"soft\") {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `pointing to a system table \"${otherTableName}\" cannot use ` +\n `soft deletion, because system documents cannot be soft deleted.`,\n );\n }\n // Nothing else to do, the edge is set up.\n continue;\n }\n const otherTable = schema[otherTableName];\n if (otherTable === undefined) {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `points to an undefined table \"${otherTableName}\"`,\n );\n }\n\n const isSelfDirected = edge.to === tableName;\n\n const inverseEdgeCandidates = edgeConfigsBeforeDefineSchema(\n otherTable,\n ).filter(canBeInverseEdge(tableName, edge, isSelfDirected));\n if (inverseEdgeCandidates.length > 1) {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `has too many potential inverse edges in table \"${otherTableName}\": ` +\n `${inverseEdgeCandidates\n .map((edge) => `\"${edge.name}\"`)\n .join(\", \")}`,\n );\n }\n const inverseEdge: EdgeConfigBeforeDefineSchema | undefined =\n inverseEdgeCandidates[0];\n\n if (\n edge.cardinality === \"single\" &&\n edge.type === \"field\" &&\n inverseEdge === undefined\n ) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ` +\n `for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n\n // Default `ref` on the multiple end of the edge,\n if (edge.cardinality === \"single\" && edge.type === \"ref\") {\n if (inverseEdge === undefined) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ${\n edge.ref !== null ? `with field \"${edge.ref}\" ` : \"\"\n }for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n if (\n inverseEdge.cardinality === \"single\" &&\n inverseEdge.type === \"ref\"\n ) {\n throw new Error(\n `Both edge \"${edge.name}\" in table \"${inverseEdge.to}\" and ` +\n `edge \"${inverseEdge.name}\" in table \"${edge.to}\" are marked ` +\n `as references, choose one to store the edge by removing ` +\n `the \\`ref\\` option.`,\n );\n }\n if (\n inverseEdge.cardinality !== \"single\" ||\n inverseEdge.type !== \"field\"\n ) {\n throw new Error(\n `Unexpected inverse edge type ${edge.name}, ${inverseEdge?.name}`,\n );\n }\n if (edge.ref === null) {\n (edge as EdgeConfigSingleRef).ref = inverseEdge.field;\n }\n // For now the the non-optional end is always unique\n (inverseEdge as EdgeConfigSingleField).unique = true;\n }\n if (\n edge.cardinality === \"single\" ||\n (edge.cardinality === \"multiple\" && edge.type === \"field\")\n ) {\n if (\n edge.deletion !== undefined &&\n deletionConfigFromEntDefinition(otherTable) === undefined\n ) {\n throw new Error(\n `Cannot specify soft deletion behavior for edge ` +\n `\"${edge.name}\" in table \"${tableName}\" ` +\n `because the target table \"${otherTableName}\" does not have ` +\n `a \"soft\" or \"scheduled\" deletion behavior ` +\n `configured.`,\n );\n }\n }\n if (edge.cardinality === \"multiple\") {\n if (!isSelfDirected && inverseEdge === undefined) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ` +\n `for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n\n if (inverseEdge?.cardinality === \"single\") {\n if (inverseEdge.type === \"ref\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `specified \\`ref\\`, but it must store the 1:many edge as a field. ` +\n `Check the its inverse edge \"${edge.name}\" in table \"${tableName}\".`,\n );\n }\n if (edge.type === \"ref\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `cannot be singular, as the edge \"${edge.name}\" in table \"${tableName}\" did not ` +\n `specify the \\`ref\\` option.`,\n );\n }\n (edge as EdgeConfigMultipleField).type = \"field\";\n (edge as EdgeConfigMultipleField).ref = inverseEdge.field;\n }\n\n if (inverseEdge?.cardinality === \"multiple\" || isSelfDirected) {\n if (!isSelfDirected && edge?.type === \"field\") {\n throw new Error(\n `The edge \"${edge.name}\" in table \"${tableName}\" ` +\n `specified \\`ref\\`, but its inverse edge \"${inverseEdge.name}\" ` +\n `in table \"${otherTableName}\" is not the singular end of a 1:many edge.`,\n );\n }\n if (inverseEdge?.type === \"field\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `specified \\`ref\\`, but its inverse edge \"${edge.name}\" ` +\n `in table \"${tableName}\" is not the singular end of a 1:many edge.`,\n );\n }\n\n const edgeTableName =\n edge.type === \"ref\" && edge.table !== undefined\n ? edge.table\n : inverseEdge === undefined\n ? `${tableName}_${edge.name}`\n : inverseEdge.name !== tableName\n ? `${tableName}_${inverseEdge.name}_to_${edge.name}`\n : `${inverseEdge.name}_to_${edge.name}`;\n\n const forwardId =\n edge.type === \"ref\" && edge.field !== undefined\n ? edge.field\n : inverseEdge === undefined\n ? \"aId\"\n : tableName === otherTableName\n ? inverseEdge.name + \"Id\"\n : tableName + \"Id\";\n const inverseId =\n isSelfDirected &&\n edge.type === \"ref\" &&\n edge.inverseField !== undefined\n ? edge.inverseField\n : inverseEdge === undefined\n ? \"bId\"\n : inverseEdge.type === \"ref\" && inverseEdge.field !== undefined\n ? inverseEdge.field\n : tableName === otherTableName\n ? edge.name + \"Id\"\n : otherTableName + \"Id\";\n // Add the table\n const edgeTable = defineEnt({\n [forwardId]: v.id(tableName),\n [inverseId]: v.id(otherTableName),\n })\n .index(forwardId, [forwardId])\n .index(inverseId, [inverseId])\n .index(edgeCompoundIndexNameRaw(forwardId, inverseId), [\n forwardId,\n inverseId,\n ]);\n const isSymmetric = inverseEdge === undefined;\n if (!isSymmetric) {\n edgeTable.index(edgeCompoundIndexNameRaw(inverseId, forwardId), [\n inverseId,\n forwardId,\n ]);\n }\n (schema as Record<string, EntDefinition>)[edgeTableName] = edgeTable;\n const edgeConfig = edge as unknown as EdgeConfigMultipleRef;\n edgeConfig.type = \"ref\";\n edgeConfig.table = edgeTableName;\n edgeConfig.field = forwardId;\n edgeConfig.ref = inverseId;\n edgeConfig.symmetric = inverseEdge === undefined;\n if (inverseEdge !== undefined) {\n inverseEdge.type = \"ref\";\n const inverseEdgeConfig =\n inverseEdge as unknown as EdgeConfigMultipleRef;\n inverseEdgeConfig.table = edgeTableName;\n inverseEdgeConfig.field = inverseId;\n inverseEdgeConfig.ref = forwardId;\n inverseEdgeConfig.symmetric = false;\n }\n }\n }\n }\n }\n return defineSchema(schema, options);\n}\n\nexport function edgeCompoundIndexName(\n edgeDefinition: EdgeConfig & { cardinality: \"multiple\"; type: \"ref\" },\n) {\n return edgeCompoundIndexNameRaw(edgeDefinition.field, edgeDefinition.ref);\n}\n\nfunction edgeCompoundIndexNameRaw(idA: string, idB: string) {\n return `${idA}_${idB}`;\n}\n\nfunction canBeInverseEdge(\n tableName: string,\n edge: EdgeConfigBeforeDefineSchema,\n isSelfDirected: boolean,\n) {\n return (candidate: EdgeConfigBeforeDefineSchema) => {\n if (candidate.to !== tableName) {\n return false;\n }\n // Simple: pick out explicit inverse edges\n if (isSelfDirected) {\n return (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n candidate.inverse === edge.name\n );\n }\n // If both ref and field are known, only consider matching edges (from the ref side)\n if (\n (edge.cardinality === \"single\" &&\n edge.type === \"ref\" &&\n edge.ref !== null) ||\n (edge.cardinality === \"multiple\" &&\n edge.type === \"field\" &&\n edge.ref !== true)\n ) {\n if (candidate.cardinality === \"single\" && candidate.type === \"field\") {\n return edge.ref === candidate.field;\n }\n }\n // If both ref and field are known, only consider matching edges (from the field side)\n if (\n edge.cardinality === \"single\" &&\n edge.type === \"field\" &&\n edge.field !== null\n ) {\n if (\n (candidate.cardinality === \"single\" &&\n candidate.type === \"ref\" &&\n candidate.ref !== null) ||\n (candidate.cardinality === \"multiple\" &&\n candidate.type === \"field\" &&\n candidate.ref !== true)\n ) {\n return edge.field === candidate.ref;\n }\n }\n\n // If table is known on both ends, only consider matching edges\n if (\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n edge.table !== undefined\n ) {\n return (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n edge.table === candidate.table\n );\n }\n if (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n candidate.table !== undefined\n ) {\n return (\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n edge.table === candidate.table\n );\n }\n return true;\n };\n}\n\nfunction edgeConfigsBeforeDefineSchema(table: EntDefinition) {\n return Object.values(\n (table as any).edgeConfigs as Record<string, EdgeConfigBeforeDefineSchema>,\n );\n}\n\nfunction deletionConfigFromEntDefinition(table: EntDefinition) {\n return (table as any).deletionConfig as DeletionConfig | undefined;\n}\n\nexport function defineEnt<\n DocumentSchema extends Validator<Record<string, any>, \"required\", any>,\n>(documentSchema: DocumentSchema): EntDefinition<DocumentSchema>;\n\nexport function defineEnt<\n DocumentSchema extends Record<string, GenericValidator>,\n>(\n documentSchema: DocumentSchema,\n): EntDefinition<VObject<ObjectType<DocumentSchema>, DocumentSchema>>;\n\nexport function defineEnt<\n DocumentSchema extends\n | Validator<Record<string, any>, \"required\", any>\n | Record<string, GenericValidator>,\n>(documentSchema: DocumentSchema): EntDefinition<any> {\n if (isValidator(documentSchema)) {\n if (\n !(\n documentSchema.kind === \"object\" ||\n (documentSchema.kind === \"union\" &&\n documentSchema.members.every((member) => member.kind === \"object\"))\n )\n ) {\n throw new Error(\"Ent shape must be an object or a union of objects\");\n }\n }\n return new EntDefinitionImpl(asObjectValidator(documentSchema)) as any;\n}\n\nfunction isValidator(v: any): v is GenericValidator {\n return !!v.isConvexValidator;\n}\n\nexport function defineEntFromTable<\n DocumentType extends GenericValidator = GenericValidator,\n // eslint-disable-next-line @typescript-eslint/ban-types\n Indexes extends GenericTableIndexes = {},\n // eslint-disable-next-line @typescript-eslint/ban-types\n SearchIndexes extends GenericTableSearchIndexes = {},\n // eslint-disable-next-line @typescript-eslint/ban-types\n VectorIndexes extends GenericTableVectorIndexes = {},\n>(\n definition: TableDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes\n >,\n): EntDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes> {\n const validator: DocumentType = definition.validator;\n if (validator.kind !== \"object\") {\n throw new Error(\n \"Only tables with object definition are supported in Ents, not unions\",\n );\n }\n\n const entDefinition = defineEnt(validator.fields);\n // @ts-expect-error Private fields\n entDefinition.indexes = definition.indexes;\n // @ts-expect-error Private fields\n entDefinition.searchIndexes = definition.searchIndexes;\n // @ts-expect-error Private fields\n entDefinition.vectorIndexes = definition.vectorIndexes;\n return entDefinition as any;\n}\n\ntype DefineEntFromTables<\n T extends { [key: string]: TableDefinition<any, any, any, any> },\n> = {\n [K in keyof T]: T[K] extends TableDefinition<\n infer D,\n infer I,\n infer S,\n infer V\n >\n ? EntDefinition<D, I, S, V>\n : never;\n};\n\nexport function defineEntsFromTables<\n T extends { [key: string]: TableDefinition<any, any, any, any> },\n>(definitions: T): DefineEntFromTables<T> {\n const result: any = {};\n for (const key in definitions) {\n result[key] = defineEntFromTable(definitions[key]);\n }\n return result;\n}\n\ntype GenericEdges = Record<string, GenericEdgeConfig>;\n\nexport type GenericEdgeConfig = {\n name: string;\n to: string;\n cardinality: \"single\" | \"multiple\";\n type: \"field\" | \"ref\";\n optional?: boolean;\n};\n\ntype ExtractFieldPaths<T extends Validator<any, any, any>> =\n // Add in the system fields available in index definitions.\n // This should be everything except for `_id` because thats added to indexes\n // automatically.\n T[\"fieldPaths\"] | keyof SystemFields;\n\ntype ObjectFieldType<\n FieldName extends string,\n T extends Validator<any, any, any>,\n> = T[\"isOptional\"] extends \"optional\"\n ? { [key in FieldName]?: T[\"type\"] }\n : { [key in FieldName]: T[\"type\"] };\n\ntype AddField<\n V extends GenericValidator,\n FieldName extends string,\n P extends GenericValidator,\n> =\n // Note: We can't use the `AddField` type to add fields to a union type, but ents\n // do not support schemas with top level unions\n V extends VObject<\n infer TypeScriptType,\n infer Fields,\n infer IsOptional,\n infer FieldPaths\n >\n ? VObject<\n Expand<TypeScriptType & ObjectFieldType<FieldName, P>>,\n Expand<Fields & { FieldName: P }>,\n IsOptional,\n FieldPaths | FieldName\n >\n : V extends VUnion<\n infer TypeScriptType,\n infer Members,\n infer IsOptional,\n infer FieldPaths\n >\n ? VUnion<\n Expand<TypeScriptType & ObjectFieldType<FieldName, P>>,\n { [key in keyof Members]: AddField<Members[key], FieldName, P> },\n IsOptional,\n FieldPaths | FieldName\n >\n : V extends VAny\n ? VAny\n : never;\n\nexport interface EntDefinition<\n DocumentType extends Validator<any, any, any> = Validator<any, any, any>,\n // eslint-disable-next-line @typescript-eslint/ban-types\n Indexes extends GenericTableIndexes = {},\n // eslint-disable-next-line @typescript-eslint/ban-types\n SearchIndexes extends GenericTableSearchIndexes = {},\n // eslint-disable-next-line @typescript-eslint/ban-types\n VectorIndexes extends GenericTableVectorIndexes = {},\n // eslint-disable-next-line @typescript-eslint/ban-types\n Edges extends GenericEdges = {},\n> extends TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes> {\n /**\n * Define an index on this table.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param indexConfig - The index configuration object.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n indexConfig: Expand<\n DbIndexConfig<FirstFieldPath, RestFieldPaths> &\n IndexOptions & { staged?: false }\n >,\n ): TableDefinition<\n DocumentType,\n Expand<\n Indexes &\n Record<\n IndexName,\n [FirstFieldPath, ...RestFieldPaths, IndexTiebreakerField]\n >\n >,\n SearchIndexes,\n VectorIndexes\n >;\n\n /**\n * Define an index on this table.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param fields - The fields to index, in order. Must specify at least one\n * field.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n fields: [FirstFieldPath, ...RestFieldPaths],\n ): EntDefinition<\n DocumentType,\n Expand<\n Indexes &\n Record<IndexName, [FirstFieldPath, ...RestFieldPaths, \"_creationTime\"]>\n >,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n\n /**\n * Define a staged index on this table.\n *\n * For large tables, index backfill can be slow. Staging an index allows you\n * to push the schema and enable the index later.\n *\n * If `staged` is `true`, the index will be staged and will not be enabled\n * until the staged flag is removed. Staged indexes do not block push\n * completion. Staged indexes cannot be used in queries.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param indexConfig - The index configuration object.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n indexConfig: Expand<\n DbIndexConfig<FirstFieldPath, RestFieldPaths> &\n IndexOptions & { staged: true }\n >,\n ): TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes>;\n\n /**\n * Define a search index on this table.\n *\n * To learn about search indexes, see [Search](https://docs.convex.dev/text-search).\n *\n * @param name - The name of the index.\n * @param indexConfig - The search index configuration object.\n * @returns A {@link TableDefinition} with this search index included.\n */\n searchIndex<\n IndexName extends string,\n SearchField extends ExtractFieldPaths<DocumentType>,\n FilterFields extends ExtractFieldPaths<DocumentType> = never,\n >(\n name: IndexName,\n indexConfig: Expand<SearchIndexConfig<SearchField, FilterFields>>,\n ): EntDefinition<\n DocumentType,\n Indexes,\n Expand<\n SearchIndexes &\n Record<\n IndexName,\n {\n searchField: SearchField;\n filterFields: FilterFields;\n }\n >\n >,\n VectorIndexes,\n Edges\n >;\n\n // /**\n // * Define a vector index on this table.\n // *\n // * To learn about vector indexes, see [Vector Search](https://docs.convex.dev/vector-search).\n // *\n // * @param name - The name of the index.\n // * @param indexConfig - The vector index configuration object.\n // * @returns A {@link TableDefinition} with this vector index included.\n // */\n vectorIndex<\n IndexName extends string,\n VectorField extends ExtractFieldPaths<DocumentType>,\n FilterFields extends ExtractFieldPaths<DocumentType> = never,\n >(\n name: IndexName,\n indexConfig: Expand<VectorIndexConfig<VectorField, FilterFields>>,\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n Expand<\n VectorIndexes &\n Record<\n IndexName,\n {\n vectorField: VectorField;\n dimensions: number;\n filterFields: FilterFields;\n }\n >\n >,\n Edges\n >;\n\n field<FieldName extends string, T extends GenericValidator>(\n field: FieldName,\n validator: T,\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, any, any>>(\n field: FieldName,\n validator: T,\n options: { index: true },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes & { [key in FieldName]: [FieldName, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, any, any>>(\n field: FieldName,\n validator: T,\n options: { unique: true },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes & { [key in FieldName]: [FieldName, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, \"required\", any>>(\n field: FieldName,\n validator: T,\n options: { default: T[\"type\"] },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n\n edge<EdgeName extends string>(\n edge: EdgeName,\n options?: { deletion: \"hard\" | \"soft\" },\n ): EntDefinition<\n AddField<DocumentType, `${EdgeName}Id`, VId<GenericId<`${EdgeName}s`>>>,\n Indexes & { [key in `${EdgeName}Id`]: [`${EdgeName}Id`, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: { field: FieldName; deletion?: \"hard\" | \"soft\" },\n ): EntDefinition<\n AddField<DocumentType, NoInfer<FieldName>, VId<GenericId<`${EdgeName}s`>>>,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: {\n field: FieldName;\n optional: true;\n deletion?: \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<\n DocumentType,\n NoInfer<FieldName>,\n VOptional<VId<GenericId<`${EdgeName}s`>>>\n >,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: true;\n };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: {\n field: FieldName;\n to: ToTable;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<DocumentType, NoInfer<FieldName>, VId<GenericId<`${ToTable}`>>>,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const ToTable extends string>(\n edge: EdgeName,\n options: {\n to: ToTable;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<DocumentType, `${EdgeName}Id`, VId<GenericId<`${ToTable}`>>>,\n Indexes & {\n [key in `${EdgeName}Id`]: [`${EdgeName}Id`, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: {\n field: FieldName;\n to: ToTable;\n optional: true;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<\n DocumentType,\n NoInfer<FieldName>,\n VOptional<VId<GenericId<ToTable>>>\n >,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: true;\n };\n }\n >;\n edge<EdgeName extends string>(\n edge: EdgeName,\n options: {\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"ref\";\n cardinality: \"single\";\n };\n }\n >;\n edge<EdgeName extends string, const ToTable extends string>(\n edge: EdgeName,\n options: {\n to: ToTable;\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: NoInfer<ToTable>;\n type: \"ref\";\n cardinality: \"single\";\n };\n }\n >;\n\n /**\n * Define many:1 edge to another table.\n * @param edge The name of the edge, also the name of the target table.\n * @param options.ref The name of the field that stores the many:1 edge\n * on the other table, or `true` to infer it.\n */\n edges<EdgesName extends string>(\n edge: EdgesName,\n options: {\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: EdgesName;\n type: \"field\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define many:1 edge to another table.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * If it's the same as the table this edge is defined on, this edge is\n * a symmetric, self-directed many:many edge.\n * @param options.ref The name of the field that stores the many:1 edge\n * on the other table, or `true` to infer it.\n */\n edges<EdgesName extends string, TableName extends string>(\n edge: EdgesName,\n options: {\n to: TableName;\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"field\";\n cardinality: \"multiple\";\n };\n }\n >;\n\n /**\n * Define many:many edge to another table.\n * @param edge The name of the edge, also the name of the target table.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * this end of the many:many edge.\n */\n edges<EdgesName extends string>(\n edge: EdgesName,\n options?: {\n table?: string;\n field?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: EdgesName;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define many:many edge to another table.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * If it's the same as the table this edge is defined on, this edge is\n * a symmetric, self-directed many:many edge.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * of the source end of the forward many:many edge.\n * @param options.inverseField Optional, name of the field to store the ID\n * of the target end of the forward edge. Only allowed for symmetric,\n * self-directed many:many edges.\n */\n edges<EdgesName extends string, TableName extends string>(\n edge: EdgesName,\n options: {\n to: TableName;\n table?: string;\n field?: string;\n inverseField?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define self-directed, assymetric, many:many edge.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * Must be the same as the table this edge is defined on.\n * @param options.inverse Name of the inverse edge.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * of the source end of the forward many:many edge.\n * @param options.inverseField Optional, name of the field to store the ID\n * of the target end of the forward many:many edge.\n */\n edges<\n EdgesName extends string,\n TableName extends string,\n InverseEdgesNames extends string,\n >(\n edge: EdgesName,\n options: {\n to: TableName;\n inverse: InverseEdgesNames;\n table?: string;\n field?: string;\n inverseField?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n } & {\n [key in NoInfer<InverseEdgesNames>]: {\n name: NoInfer<InverseEdgesNames>;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n\n /**\n * Add the \"soft\" deletion behavior to this ent.\n *\n * When the ent is \"soft\" deleted, its `deletionTime` field is set to the\n * current time and it is not actually deleted.\n *\n * @param type `\"soft\"`\n */\n deletion(\n type: \"soft\",\n ): EntDefinition<\n AddField<DocumentType, \"deletionTime\", VOptional<VFloat64>>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n /**\n * Add the \"scheduled\" deletion behavior to this ent.\n *\n * The ent is first \"soft\" deleted and its hard deletion is scheduled\n * to run in a separate mutation.\n *\n * @param type `\"scheduled\"`\n * @param options.delayMs If the `delayMs` option is specified,\n * the hard deletion is scheduled to happen after the specified\n * time duration.\n */\n deletion(\n type: \"scheduled\",\n options?: {\n delayMs: number;\n },\n ): EntDefinition<\n AddField<DocumentType, \"deletionTime\", VOptional<VFloat64>>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n}\n\ntype NoInfer<T> = [T][T extends any ? 0 : never];\n\ntype FieldOptions = {\n index?: true;\n unique?: true;\n default?: any;\n};\n\ntype EdgeOptions = {\n optional?: true;\n field?: string;\n ref?: true | string;\n to?: string;\n deletion?: \"soft\" | \"hard\";\n};\n\ntype EdgesOptions = {\n to?: string;\n inverse?: string;\n ref?: string;\n table?: string;\n field?: string;\n inverseField?: string;\n deletion: \"soft\";\n};\n\nclass EntDefinitionImpl {\n validator: Validator<Record<string, any>, \"required\", any>;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private indexes: Index[] = [];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private searchIndexes: SearchIndex[] = [];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private vectorIndexes: VectorIndex[] = [];\n\n private edgeConfigs: Record<string, EdgeConfigBeforeDefineSchema> = {};\n\n private fieldConfigs: Record<string, FieldConfig> = {};\n\n private defaults: Record<string, any> = {};\n\n private deletionConfig: DeletionConfig | undefined;\n\n constructor(documentSchema: Validator<Record<string, any>, \"required\", any>) {\n this.validator = documentSchema;\n }\n\n index(name: any, fields: any) {\n this.indexes.push({ indexDescriptor: name, fields });\n return this;\n }\n\n searchIndex(name: any, indexConfig: any) {\n this.searchIndexes.push({\n indexDescriptor: name,\n searchField: indexConfig.searchField,\n filterFields: indexConfig.filterFields || [],\n });\n return this;\n }\n\n vectorIndex(name: any, indexConfig: any) {\n this.vectorIndexes.push({\n indexDescriptor: name,\n vectorField: indexConfig.vectorField,\n dimensions: indexConfig.dimensions,\n filterFields: indexConfig.filterFields || [],\n });\n return this;\n }\n\n /**\n * Export the contents of this definition.\n *\n * This is called internally by the Convex framework.\n * @internal\n */\n export() {\n return {\n indexes: this.indexes,\n searchIndexes: this.searchIndexes,\n vectorIndexes: this.vectorIndexes,\n documentType: (this.validator as any).json,\n };\n }\n\n field(name: string, validator: any, options?: FieldOptions): this {\n if (this._has(name)) {\n // TODO: Store the fieldConfigs in an array so that we can\n // do the uniqueness check in defineEntSchema where we\n // know the table name.\n throw new Error(`Duplicate field \"${name}\"`);\n }\n const finalValidator =\n options?.default !== undefined ? v.optional(validator) : validator;\n this._expand(name, finalValidator);\n if (options?.unique === true || options?.index === true) {\n this.indexes.push({ indexDescriptor: name, fields: [name] });\n }\n if (options?.default !== undefined) {\n this.defaults[name] = options.default;\n }\n if (options?.unique === true) {\n this.fieldConfigs[name] = { name, unique: true };\n }\n return this;\n }\n\n edge(edgeName: string, options?: EdgeOptions): this {\n if (this.edgeConfigs[edgeName] !== undefined) {\n // TODO: Store the edgeConfigs in an array so that we can\n // do the uniqueness check in defineEntSchema where we\n // know the source table name.\n throw new Error(`Duplicate edge \"${edgeName}\"`);\n }\n const to = options?.to ?? edgeName + \"s\";\n if (options?.field !== undefined && options?.ref !== undefined) {\n throw new Error(\n `Cannot specify both \\`field\\` and \\`ref\\` for the same edge, ` +\n `choose one to be the reference and the other to store ` +\n `the foreign key.`,\n );\n }\n if (options?.field !== undefined || options?.ref === undefined) {\n const fieldName = options?.field ?? edgeName + \"Id\";\n this._expand(\n fieldName,\n options?.optional === true ? v.optional(v.id(to)) : v.id(to),\n );\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"field\",\n field: fieldName,\n optional: options?.optional === true,\n deletion: options?.deletion,\n };\n this.indexes.push({\n indexDescriptor: fieldName,\n fields: [fieldName],\n });\n return this;\n }\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"ref\",\n ref: options.ref === true ? null : options.ref,\n deletion: options.deletion as \"soft\" | undefined,\n };\n return this;\n }\n\n edges(name: string, options?: EdgesOptions): this {\n const cardinality = \"multiple\";\n const to = options?.to ?? name;\n const ref = options?.ref;\n const table = options?.table;\n // TODO: Do this later when we have the table name,\n // or rework schema to use a builder pattern.\n if (ref !== undefined && table !== undefined) {\n throw new Error(\n `Cannot specify both \\`ref\\` and \\`table\\` for the same edge, ` +\n `as the former is for 1:many edges and the latter ` +\n `for many:many edges. Config: \\`${JSON.stringify(options)}\\``,\n );\n }\n const field = options?.field;\n const inverseField = options?.inverseField;\n // TODO: Do this later when we have the table name,\n // or rework schema to use a builder pattern.\n if (\n (field !== undefined || inverseField !== undefined) &&\n table === undefined\n ) {\n throw new Error(\n `Specify \\`table\\` if you're customizing the \\`field\\` or ` +\n `\\`inverseField\\` for a many:many edge. ` +\n `Config: \\`${JSON.stringify(options)}\\``,\n );\n }\n const inverseName = options?.inverse;\n const deletion = options?.deletion;\n this.edgeConfigs[name] =\n ref !== undefined\n ? { name, to, cardinality, type: \"field\", ref, deletion }\n : { name, to, cardinality, type: \"ref\", table, field, inverseField };\n if (inverseName !== undefined) {\n this.edgeConfigs[inverseName] = {\n name: inverseName,\n to,\n cardinality,\n type: \"ref\",\n inverse: name,\n table,\n };\n }\n return this;\n }\n\n deletion(type: \"soft\" | \"scheduled\", options?: { delayMs: number }): this {\n if (this._has(\"deletionTime\")) {\n // TODO: Put the check where we know the table name.\n throw new Error(\n `Cannot enable \"${type}\" deletion because \"deletionTime\" field ` +\n `was already defined.`,\n );\n }\n if (this.deletionConfig !== undefined) {\n // TODO: Put the check where we know the table name.\n throw new Error(`Deletion behavior can only be specified once.`);\n }\n this._expand(\"deletionTime\", v.optional(v.number()));\n this.deletionConfig = { type, ...options };\n return this;\n }\n\n private _has(name: string): boolean {\n if (this.validator.kind === \"object\") {\n return this.validator.fields[name] !== undefined;\n }\n if (this.validator.kind === \"union\") {\n return this.validator.members.some(\n (member) =>\n member.kind === \"object\" && member.fields[name] !== undefined,\n );\n }\n return false;\n }\n\n private _expand(name: string, validator: GenericValidator) {\n if (this.validator.kind === \"object\") {\n this.validator.fields[name] = validator;\n }\n if (this.validator.kind === \"union\") {\n this.validator.members.forEach((member) => {\n if (member.kind === \"object\") {\n member.fields[name] = validator;\n }\n });\n }\n }\n}\n\nexport type EdgeConfig = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\n unique: boolean;\n optional: boolean;\n deletion?: \"soft\" | \"hard\";\n }\n | {\n type: \"ref\";\n ref: string;\n deletion?: \"soft\";\n }\n ))\n | ({\n cardinality: \"multiple\";\n } & (\n | {\n type: \"field\";\n ref: string;\n deletion?: \"soft\";\n }\n | {\n type: \"ref\";\n table: string;\n field: string;\n ref: string;\n inverse: boolean;\n symmetric: boolean;\n }\n ))\n);\n\ntype EdgeConfigSingleField = Extract<\n EdgeConfig,\n {\n type: \"field\";\n cardinality: \"single\";\n }\n>;\ntype EdgeConfigSingleRef = Extract<\n EdgeConfig,\n {\n type: \"ref\";\n cardinality: \"single\";\n }\n>;\ntype EdgeConfigMultipleField = Extract<\n EdgeConfig,\n {\n type: \"field\";\n cardinality: \"multiple\";\n }\n>;\ntype EdgeConfigMultipleRef = Extract<\n EdgeConfig,\n {\n type: \"ref\";\n cardinality: \"multiple\";\n }\n>;\n\ntype EdgeConfigBeforeDefineSchema = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\n optional: boolean;\n deletion?: \"soft\" | \"hard\";\n }\n | {\n type: \"ref\";\n ref: null | string;\n deletion?: \"soft\";\n }\n ))\n | ({\n cardinality: \"multiple\";\n } & (\n | {\n type: \"field\";\n ref: true | string;\n deletion?: \"soft\";\n }\n | {\n type: \"ref\";\n table?: string;\n field?: string;\n inverseField?: string;\n inverse?: string;\n }\n ))\n);\n\nexport type FieldConfig = {\n name: string;\n unique: boolean;\n};\n\nexport type Expand<ObjectType extends Record<any, any>> =\n ObjectType extends Record<any, any>\n ? {\n [Key in keyof ObjectType]: ObjectType[Key];\n }\n : never;\nexport type SystemFields = {\n _creationTime: number;\n};\n\ninterface IndexOptions {\n /**\n * Whether the index should be staged.\n *\n * For large tables, index backfill can be slow. Staging an index allows you\n * to push the schema and enable the index later.\n *\n * If `staged` is `true`, the index will be staged and will not be enabled\n * until the staged flag is removed. Staged indexes do not block push\n * completion. Staged indexes cannot be used in queries.\n */\n staged?: boolean;\n}\n\ninterface DbIndexConfig<\n FirstFieldPath extends string,\n RestFieldPaths extends string[],\n> {\n /**\n * The fields to index, in order. Must specify at least one field.\n */\n fields: [FirstFieldPath, ...RestFieldPaths];\n}\n\nexport type GenericEntsDataModel = GenericDataModel &\n Record<string, GenericEntModel>;\n\nexport type GenericEntModel = {\n edges: Record<string, GenericEdgeConfig>;\n};\n\nexport type DeletionConfig =\n | {\n type: \"soft\";\n }\n | {\n type: \"scheduled\";\n delayMs?: number;\n };\n\nexport type EntDataModelFromSchema<\n SchemaDef extends SchemaDefinition<any, boolean>,\n> = DataModelFromSchemaDefinition<SchemaDef> & {\n [TableName in keyof SchemaDef[\"tables\"] &\n string]: SchemaDef[\"tables\"][TableName] extends EntDefinition<\n any,\n any,\n any,\n any,\n infer Edges\n >\n ? {\n edges: Edges;\n }\n : never;\n};\n\nexport function getEntDefinitions<\n SchemaDef extends SchemaDefinition<any, boolean>,\n>(schema: SchemaDef): EntDataModelFromSchema<typeof schema> {\n const tables = schema.tables;\n return Object.entries(tables).reduce(\n (acc, [tableName, table]: [any, any]) => {\n acc[tableName] = {\n indexes: (\n table.indexes as {\n indexDescriptor: string;\n fields: string[];\n }[]\n ).reduce(\n (acc, { indexDescriptor, fields }) => {\n acc[indexDescriptor] = fields;\n return acc;\n },\n {} as Record<string, string[]>,\n ),\n defaults: table.defaults,\n edges: table.edgeConfigs,\n fields: table.fieldConfigs,\n deletionConfig: table.deletionConfig,\n };\n return acc;\n },\n {} as Record<string, any>,\n ) as any;\n}\n","import {\n DocumentByName,\n FieldTypeFromFieldPath,\n SystemDataModel,\n TableNamesInDataModel,\n} from \"convex/server\";\nimport { EdgeConfig, GenericEdgeConfig, GenericEntsDataModel } from \"./schema\";\n\nexport type EntsSystemDataModel = {\n [key in keyof SystemDataModel]: SystemDataModel[key] & {\n edges: Record<string, never>;\n };\n};\n\nexport type PromiseEdgeResult<\n EdgeConfig extends GenericEdgeConfig,\n MultipleRef,\n MultipleField,\n SingleOptional,\n Single,\n> = EdgeConfig[\"cardinality\"] extends \"multiple\"\n ? EdgeConfig[\"type\"] extends \"ref\"\n ? MultipleRef\n : MultipleField\n : EdgeConfig[\"type\"] extends \"ref\"\n ? SingleOptional\n : EdgeConfig[\"optional\"] extends true\n ? SingleOptional\n : Single;\n\nexport type IndexFieldTypesForEq<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n T extends string[],\n> = Pop<{\n [K in keyof T]: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n T[K]\n >;\n}>;\n\ntype Pop<T extends any[]> = T extends [...infer Rest, infer _Last]\n ? Rest\n : never;\n\nexport function getEdgeDefinitions<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(entDefinitions: EntsDataModel, table: Table) {\n return entDefinitions[table].edges as Record<\n keyof EntsDataModel[Table][\"edges\"],\n EdgeConfig\n >;\n}\n","import {\n DocumentByName,\n GenericDocument,\n TableNamesInDataModel,\n makeFunctionReference,\n} from \"convex/server\";\nimport { GenericId } from \"convex/values\";\nimport {\n EntMutationCtx,\n entWrapper,\n getDeletionConfig,\n getReadRule,\n getWriteRule,\n} from \"./functions\";\nimport {\n FieldConfig,\n GenericEdgeConfig,\n GenericEntsDataModel,\n edgeCompoundIndexName,\n} from \"./schema\";\nimport { ScheduledDeleteFuncRef } from \"./deletion\";\nimport { getEdgeDefinitions } from \"./shared\";\n\nexport class WriterImplBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n ) {}\n\n async deleteId(id: GenericId<any>, behavior: \"default\" | \"soft\" | \"hard\") {\n await this.checkReadAndWriteRule(\"delete\", id, undefined);\n\n const deletionConfig = getDeletionConfig(this.entDefinitions, this.table);\n\n const isDeletingSoftly =\n behavior !== \"hard\" &&\n deletionConfig !== undefined &&\n (deletionConfig.type === \"soft\" || deletionConfig.type === \"scheduled\");\n\n if (behavior === \"soft\" && !isDeletingSoftly) {\n throw new Error(\n `Cannot soft delete document with ID \"${id}\" in ` +\n `table \"${this.table}\" because it does not have ` +\n `a \"soft\" or \"scheduled\" deletion behavior configured.`,\n );\n }\n const edges: EdgeChanges = {};\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n const key = edgeDefinition.name;\n if (\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"ref\") ||\n (edgeDefinition.cardinality === \"multiple\" &&\n edgeDefinition.type === \"field\")\n ) {\n if (!isDeletingSoftly || edgeDefinition.deletion === \"soft\") {\n const remove = (\n await this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .collect()\n ).map((doc) => doc._id as GenericId<any>);\n edges[key] = { remove };\n }\n } else if (edgeDefinition.cardinality === \"single\") {\n if (\n edgeDefinition.deletion !== undefined &&\n (!isDeletingSoftly || edgeDefinition.deletion === \"soft\")\n ) {\n const doc = await this.ctx.db.get(id);\n if (doc !== null) {\n const otherId = doc[edgeDefinition.field] as\n | GenericId<any>\n | undefined;\n edges[key] = {\n remove: otherId !== undefined ? [otherId] : [],\n };\n }\n }\n } else if (edgeDefinition.cardinality === \"multiple\") {\n if (!isDeletingSoftly) {\n const removeEdges = (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.field, (q) =>\n q.eq(edgeDefinition.field, id as any),\n )\n .collect()\n )\n .concat(\n edgeDefinition.symmetric\n ? await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .collect()\n : [],\n )\n .map((doc) => doc._id as GenericId<any>);\n edges[key] = { removeEdges };\n }\n }\n },\n ),\n );\n const deletionTime = +new Date();\n if (isDeletingSoftly) {\n await this.ctx.db.patch(id, { deletionTime });\n } else {\n try {\n await this.ctx.db.delete(id);\n } catch (e) {\n // TODO:\n // For now we're gonna ignore errors here,\n // because we assume that the only error\n // is \"document not found\", which\n // can be caused by concurrent deletions.\n // In the future we could track which\n // edges are being deleted by this mutation,\n // and skip the call to delete altogether\n // - or Convex could implement this.\n }\n }\n await this.writeEdges(id, edges, isDeletingSoftly);\n if (deletionConfig !== undefined && deletionConfig.type === \"scheduled\") {\n const fnRef = ((this.ctx as any).scheduledDelete ??\n makeFunctionReference(\n \"functions:scheduledDelete\",\n )) as ScheduledDeleteFuncRef;\n await this.ctx.scheduler.runAfter(deletionConfig.delayMs ?? 0, fnRef, {\n origin: {\n id,\n table: this.table,\n deletionTime,\n },\n inProgress: false,\n stack: [],\n });\n }\n return id;\n }\n\n async deleteIdIn(id: GenericId<any>, table: string, cascadingSoft: boolean) {\n await new WriterImplBase(this.ctx, this.entDefinitions, table).deleteId(\n id,\n cascadingSoft ? \"soft\" : \"hard\",\n );\n }\n\n async deleteSystem(table: string, id: GenericId<any>) {\n switch (table) {\n case \"_storage\":\n await this.ctx.storage.delete(id);\n break;\n case \"_scheduled_functions\":\n await this.ctx.scheduler.cancel(id);\n break;\n default:\n throw new Error(\n `Cannot cascade deletion to unsupported system table \"${table}\".`,\n );\n }\n }\n\n async writeEdges(\n docId: GenericId<any>,\n changes: EdgeChanges,\n deleteSoftly?: boolean,\n ) {\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n const idOrIds = changes[edgeDefinition.name];\n if (idOrIds === undefined) {\n return;\n }\n if (\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"ref\") ||\n (edgeDefinition.cardinality === \"multiple\" &&\n edgeDefinition.type === \"field\")\n ) {\n if (idOrIds.remove !== undefined && idOrIds.remove.length > 0) {\n // Cascading delete because 1:many edges are not optional\n // on the stored field end.\n await Promise.all(\n idOrIds.remove.map((id) =>\n this.deleteIdIn(\n id,\n edgeDefinition.to,\n (deleteSoftly ?? false) &&\n edgeDefinition.deletion === \"soft\",\n ),\n ),\n );\n // This would be behavior for optional edge:\n // await Promise.all(\n // idsToDelete.map((id) =>\n // this.ctx.db.patch(id, {\n // [edgeDefinition.ref]: undefined,\n // } as any)\n // )\n // );\n }\n if (idOrIds.add !== undefined && idOrIds.add.length > 0) {\n await Promise.all(\n idOrIds.add.map(async (id) =>\n this.ctx.db.patch(id, {\n [edgeDefinition.ref]: docId,\n } as any),\n ),\n );\n }\n } else if (edgeDefinition.cardinality === \"single\") {\n if (idOrIds.remove !== undefined && idOrIds.remove.length > 0) {\n await Promise.all(\n idOrIds.remove.map(\n isSystemTable(edgeDefinition.to)\n ? (id) => this.deleteSystem(edgeDefinition.to, id)\n : (id) =>\n this.deleteIdIn(\n id,\n edgeDefinition.to,\n (deleteSoftly ?? false) &&\n edgeDefinition.deletion === \"soft\",\n ),\n ),\n );\n }\n } else if (edgeDefinition.cardinality === \"multiple\") {\n if ((idOrIds.removeEdges ?? []).length > 0) {\n await Promise.all(\n idOrIds.removeEdges!.map(async (id) => {\n try {\n await this.ctx.db.delete(id);\n } catch (e) {\n // TODO:\n // For now we're gonna ignore errors here,\n // because we assume that the only error\n // is \"document not found\", which\n // can be caused by concurrent deletions.\n // In the future we could track which\n // edges are being deleted by this mutation,\n // and skip the call to delete altogether\n // - or Convex could implement this.\n }\n }),\n );\n }\n\n if (idOrIds.add !== undefined) {\n await Promise.all(\n [...new Set(idOrIds.add)].map(async (id) => {\n const existing = await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeCompoundIndexName(edgeDefinition), (q) =>\n (q.eq(edgeDefinition.field, docId as any) as any).eq(\n edgeDefinition.ref,\n id,\n ),\n )\n .first();\n if (existing === null) {\n await this.ctx.db.insert(edgeDefinition.table, {\n [edgeDefinition.field]: docId,\n [edgeDefinition.ref]: id,\n } as any);\n if (edgeDefinition.symmetric) {\n await this.ctx.db.insert(edgeDefinition.table, {\n [edgeDefinition.field]: id,\n [edgeDefinition.ref]: docId,\n } as any);\n }\n }\n }),\n );\n }\n }\n },\n ),\n );\n }\n\n async checkUniqueness(value: Partial<GenericDocument>, id?: GenericId<any>) {\n await Promise.all(\n Object.values(\n (this.entDefinitions[this.table] as any).fields as Record<\n string,\n FieldConfig\n >,\n ).map(async (fieldDefinition) => {\n if (fieldDefinition.unique) {\n const key = fieldDefinition.name;\n const fieldValue = value[key];\n const existing = await this.ctx.db\n .query(this.table)\n .withIndex(key, (q) => q.eq(key, value[key] as any))\n .unique();\n if (existing !== null && (id === undefined || existing._id !== id)) {\n throw new Error(\n `In table \"${\n this.table\n }\" cannot create a duplicate document with field \"${key}\" of value \\`${\n fieldValue as string\n }\\`, existing document with ID \"${\n existing._id as string\n }\" already has it.`,\n );\n }\n }\n }),\n );\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n if (\n edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\" &&\n edgeDefinition.unique\n ) {\n const key = edgeDefinition.field;\n if (value[key] === undefined) {\n return;\n }\n // Enforce uniqueness\n const existing = await this.ctx.db\n .query(this.table)\n .withIndex(key, (q) => q.eq(key, value[key] as any))\n .unique();\n if (\n existing !== null &&\n (id === undefined || existing._id !== id)\n ) {\n throw new Error(\n `In table \"${this.table}\" cannot create a duplicate 1:1 edge \"${\n edgeDefinition.name\n }\" to ID \"${\n value[key] as string\n }\", existing document with ID \"${\n existing._id as string\n }\" already has it.`,\n );\n }\n }\n },\n ),\n );\n }\n\n fieldsOnly(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n const fields: GenericDocument = {};\n Object.keys(value).forEach((key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\" &&\n edgeDefinition.field === key)\n ) {\n fields[key] = value[key]!;\n }\n });\n return fields;\n }\n\n async checkReadAndWriteRule(\n operation: \"create\" | \"update\" | \"delete\",\n id: GenericId<Table> | undefined,\n value: Partial<GenericDocument> | undefined,\n ) {\n if (id !== undefined) {\n const readPolicy = getReadRule(this.entDefinitions, this.table);\n if (readPolicy !== undefined) {\n const doc = await this.ctx.db.get(id);\n if (doc === null) {\n throw new Error(\n `Cannot update document with ID \"${id}\" in table \"${this.table} because it does not exist\"`,\n );\n }\n const decision = await readPolicy(doc);\n if (!decision) {\n throw new Error(\n `Cannot update document with ID \"${id}\" from table \"${this.table}\"`,\n );\n }\n }\n }\n const writePolicy = getWriteRule(this.entDefinitions, this.table);\n if (writePolicy === undefined) {\n return;\n }\n const ent =\n id === undefined\n ? undefined\n : entWrapper(\n (await this.ctx.db.get(id))!,\n this.ctx,\n this.entDefinitions,\n this.table,\n );\n // Replace allows _id and _creationTime, but rules should not\n // rely on them.\n const { _id, _creationTime, ...safeValue } = value ?? {};\n const decision = await writePolicy({\n operation,\n ent: ent as any,\n value: value !== undefined ? (safeValue as any) : undefined,\n });\n if (!decision) {\n if (id === undefined) {\n throw new Error(\n `Cannot insert into table \"${this.table}\": \\`${JSON.stringify(\n value,\n )}\\``,\n );\n } else if (value === undefined) {\n throw new Error(\n `Cannot delete from table \"${this.table}\" with ID \"${id}\"`,\n );\n } else {\n throw new Error(\n `Cannot update document with ID \"${id}\" in table \"${\n this.table\n }\" with: \\`${JSON.stringify(value)}\\``,\n );\n }\n }\n }\n}\n\nexport type WithEdgeInserts<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"single\"\n ? Edges[key][\"type\"] extends \"field\"\n ? never\n : key\n : key]?: Edges[key][\"cardinality\"] extends \"single\"\n ? GenericId<Edges[key][\"to\"]>\n : GenericId<Edges[key][\"to\"]>[];\n};\n\nexport type WithEdges<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"multiple\"\n ? Edges[key][\"type\"] extends \"ref\"\n ? key\n : never\n : never]?: GenericId<Edges[key][\"to\"]>[];\n};\n\nexport type WithEdgePatches<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"multiple\"\n ? Edges[key][\"type\"] extends \"ref\"\n ? key\n : never\n : never]?: {\n add?: GenericId<Edges[key][\"to\"]>[];\n remove?: GenericId<Edges[key][\"to\"]>[];\n };\n};\n\nexport type EdgeChanges = Record<\n string,\n {\n add?: GenericId<any>[];\n remove?: GenericId<any>[];\n removeEdges?: GenericId<any>[];\n }\n>;\n\nexport function isSystemTable(table: string) {\n return table.startsWith(\"_\");\n}\n"],"mappings":"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","names":["import_server","decision","q","table"]}
1
+ {"version":3,"sources":["../src/functions.ts","../src/schema.ts","../src/shared.ts","../src/writer.ts"],"sourcesContent":["import {\n DocumentByName,\n ExpressionOrValue,\n FieldTypeFromFieldPath,\n FilterBuilder,\n GenericDataModel,\n GenericDatabaseReader,\n GenericDatabaseWriter,\n GenericDocument,\n GenericTableInfo,\n IndexNames,\n IndexRange,\n IndexRangeBuilder,\n NamedIndex,\n NamedSearchIndex,\n NamedTableInfo,\n PaginationOptions,\n PaginationResult,\n Query,\n QueryInitializer,\n Scheduler,\n SearchFilter,\n SearchFilterBuilder,\n SearchIndexNames,\n StorageWriter,\n TableNamesInDataModel,\n WithOptionalSystemFields,\n WithoutSystemFields,\n} from \"convex/server\";\nimport { GenericId } from \"convex/values\";\nimport { ScheduledDeleteFuncRef } from \"./deletion\";\nimport {\n DeletionConfig,\n EdgeConfig,\n Expand,\n GenericEdgeConfig,\n GenericEntsDataModel,\n edgeCompoundIndexName,\n} from \"./schema\";\nimport {\n EntsSystemDataModel,\n IndexFieldTypesForEq,\n PromiseEdgeResult,\n getEdgeDefinitions,\n} from \"./shared\";\nimport {\n EdgeChanges,\n WithEdgeInserts,\n WithEdgePatches,\n WithEdges,\n WriterImplBase,\n isSystemTable,\n} from \"./writer\";\n\nexport interface PromiseOrderedQueryOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ): PromiseArrayOrNull<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n take(n: number): PromiseEntsOrNull<EntsDataModel, Table>;\n\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseOrderedQueryWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n take(n: number): PromiseEntsWriterOrNull<EntsDataModel, Table>;\n\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseQueryOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryOrNull<EntsDataModel, Table> {\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseQueryWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryWriterOrNull<EntsDataModel, Table> {\n // TODO: The index variant should not be allowed if\n // this query already used an index\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseTableBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n getMany<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n values: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n Indexes[Index][0]\n >[],\n ): PromiseEntsOrNulls<EntsDataModel, Table>;\n getMany(ids: GenericId<Table>[]): PromiseEntsOrNulls<EntsDataModel, Table>;\n getManyX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n values: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n Indexes[Index][0]\n >[],\n ): PromiseEnts<EntsDataModel, Table>;\n getManyX(ids: GenericId<Table>[]): PromiseEnts<EntsDataModel, Table>;\n /**\n * If given a valid ID for the given table, returns it, or returns null if the ID\n * is from a different table or is not a valid ID.\n *\n * This does not guarantee that the ID exists (i.e. `table(\"foo\").get(id)` may return `null`).\n */\n normalizeId(id: string): GenericId<Table> | null;\n /**\n * If given a valid ID for the given table, returns it, or throws if the ID\n * is from a different table or is not a valid ID.\n *\n * This does not guarantee that the ID exists (i.e. `table(\"foo\").get(id)` may return `null`).\n */\n normalizeIdX(id: string): GenericId<Table>;\n}\n\nexport interface PromiseTable<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseQuery<EntsDataModel, Table>,\n PromiseTableBase<EntsDataModel, Table> {\n get<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntOrNull<EntsDataModel, Table>;\n get(id: GenericId<Table>): PromiseEntOrNull<EntsDataModel, Table>;\n /**\n * Fetch a unique document from the DB using given index, throw if it doesn't exist.\n */\n getX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEnt<EntsDataModel, Table>;\n /**\n * Fetch a document from the DB for a given ID, throw if it doesn't exist.\n */\n getX(id: GenericId<Table>): PromiseEnt<EntsDataModel, Table>;\n\n /**\n * Return all documents in the table in given order.\n * Sort either by given index or by _creationTime.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQuery<EntsDataModel, Table>;\n\n /**\n * Query by running a full text search against a search index.\n *\n * Search queries must always search for some text within the index's\n * `searchField`. This query can optionally add equality filters for any\n * `filterFields` specified in the index.\n *\n * Documents will be returned in relevance order based on how well they\n * match the search text.\n *\n * To learn about full text search, see [Indexes](https://docs.convex.dev/text-search).\n *\n * @param indexName - The name of the search index to query.\n * @param searchFilter - A search filter expression constructed with the\n * supplied {@link SearchFilterBuilder}. This defines the full text search to run\n * along with equality filtering to run within the search index.\n * @returns - A query that searches for matching documents, returning them\n * in relevancy order.\n */\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ): PromiseOrderedQuery<EntsDataModel, Table>;\n}\n\nexport interface PromiseOrderedQueryBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): this;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[]>;\n}\n\nexport interface PromiseOrderedQuery<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n >,\n PromiseOrderedQueryBase<EntsDataModel, Table> {\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResult<EntsDataModel, Table>;\n\n take(n: number): PromiseEnts<EntsDataModel, Table>;\n\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n firstX(): PromiseEnt<EntsDataModel, Table>;\n\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n uniqueX(): PromiseEnt<EntsDataModel, Table>;\n}\n\nexport interface PromiseQuery<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQuery<EntsDataModel, Table> {\n order(order: \"asc\" | \"desc\"): PromiseOrderedQuery<EntsDataModel, Table>;\n}\n\nclass PromiseQueryOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n >\n implements PromiseQueryOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: () => Promise<Query<\n NamedTableInfo<EntsDataModel, Table>\n > | null>,\n ) {\n super(() => {});\n }\n\n filter(\n predicate: (\n q: FilterBuilder<NamedTableInfo<EntsDataModel, Table>>,\n ) => ExpressionOrValue<boolean>,\n ): any {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n return query.filter(predicate);\n },\n );\n }\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ) {\n return new PromiseArrayImpl(async () => {\n const array = await this;\n if (array === null) {\n return null as TOutput[] | null;\n }\n return await Promise.all(array.map(callbackFn));\n });\n }\n\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): any {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n if (indexName !== undefined) {\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n )\n .withIndex(indexName)\n .order(order);\n }\n return query.order(order) as any;\n },\n );\n }\n\n paginate(paginationOpts: PaginationOptions) {\n return new PromisePaginationResultOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n return await query.paginate(paginationOpts);\n },\n );\n }\n\n take(n: number) {\n return new PromiseEntsOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n return await this._take(n);\n },\n false,\n );\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n return nullRetriever;\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n throw new Error(\"Query returned no documents\");\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n async docs() {\n const query = await this.retrieve();\n if (query === null) {\n return null;\n }\n const docs = await query.collect();\n return filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n docs,\n false,\n );\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value:\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((documents) =>\n documents === null\n ? null\n : documents.map((doc) =>\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n )\n .then(onfulfilled, onrejected);\n }\n\n async _take(n: number) {\n const query = await this.retrieve();\n return await takeFromQuery(\n query,\n n,\n this.ctx,\n this.entDefinitions,\n this.table,\n );\n }\n}\n\nexport interface PromisePaginationResultOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null> {\n docs(): Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput> | null>;\n}\n\nexport interface PromisePaginationResult<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n >\n > {\n docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>>>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput>>;\n}\n\nclass PromisePaginationResultOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null>\n implements PromisePaginationResultOrNull<EntsDataModel, Table>\n{\n constructor(\n private ctx: EntQueryCtx<EntsDataModel>,\n private entDefinitions: EntsDataModel,\n private table: Table,\n protected retrieve: () => Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>,\n ) {\n super(() => {});\n }\n\n async map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ) {\n const result = await this;\n if (result === null) {\n return null;\n }\n return {\n ...result,\n page: await Promise.all(result.page.map(callbackFn)),\n };\n }\n\n async docs() {\n const result = await this.retrieve();\n if (result === null) {\n return null;\n }\n return {\n ...result,\n page: (await filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n result.page,\n false,\n ))!,\n };\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value: PaginationResult<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((result) =>\n result === null\n ? null\n : {\n ...result,\n page: result.page.map((doc) =>\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n },\n )\n .then(onfulfilled, onrejected);\n }\n}\n\nclass PromiseTableImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseQueryOrNullImpl<EntsDataModel, Table> {\n constructor(\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n ) {\n super(ctx, entDefinitions, table, async () =>\n isSystemTable(table)\n ? (ctx.db.system.query(table as any) as any)\n : ctx.db.query(table),\n );\n }\n\n get(...args: any[]) {\n return this.getImpl(args);\n }\n\n getX(...args: any[]) {\n return this.getImpl(args, true);\n }\n\n getMany(...args: any[]) {\n return this.getManyImpl(args);\n }\n\n getManyX(...args: any[]) {\n return this.getManyImpl(args, true);\n }\n\n getImpl(args: any[], throwIfNull = false) {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n args.length === 1\n ? async () => {\n const id = args[0] as GenericId<Table>;\n if (this.normalizeId(id) === null) {\n throw new Error(`Invalid id \\`${id}\\` for table \"${this.table}\"`);\n }\n return {\n id,\n doc: async () => {\n const doc = await (isSystemTable(this.table)\n ? this.ctx.db.system.get(id as any)\n : this.ctx.db.get(id));\n if (throwIfNull && doc === null) {\n throw new Error(\n `Document not found with id \\`${id}\\` in table \"${this.table}\"`,\n );\n }\n return doc;\n },\n } as any; // any because PromiseEntWriterImpl expects non-nullable\n }\n : async () => {\n const [indexName, ...values] = args;\n const fieldNames = getIndexFields(\n this.entDefinitions,\n this.table,\n indexName,\n );\n const doc = await this.ctx.db\n .query(this.table)\n .withIndex(indexName, (q) =>\n values.reduce((q, value, i) => q.eq(fieldNames[i], value), q),\n )\n .unique();\n if (throwIfNull && doc === null) {\n throw new Error(\n `Table \"${this.table}\" does not contain document with field${values.reduce(\n (message, value, i) =>\n `${message} \"${fieldNames[i]}\" = \\`${value}\\``,\n \"\",\n )}`,\n );\n }\n return loadedRetriever(doc);\n },\n throwIfNull,\n );\n }\n\n getManyImpl(args: any[], throwIfNull = false) {\n return new PromiseEntsOrNullImpl(\n this.ctx as any,\n this.entDefinitions as any,\n this.table,\n args.length === 1\n ? async () => {\n const ids = args[0] as GenericId<Table>[];\n ids.forEach((id) => {\n if (this.normalizeId(id) === null) {\n throw new Error(\n `Invalid id \\`${id}\\` for table \"${this.table}\"`,\n );\n }\n });\n return await Promise.all(\n ids.map(async (id) => {\n const doc = await (isSystemTable(this.table)\n ? this.ctx.db.system.get(id as any)\n : this.ctx.db.get(id));\n if (throwIfNull && doc === null) {\n throw new Error(\n `Document not found with id \\`${id}\\` in table \"${this.table}\"`,\n );\n }\n return doc;\n }),\n );\n }\n : async () => {\n const [indexName, values] = args;\n return (await Promise.all(\n (values as any[]).map(async (value) => {\n const doc = await this.ctx.db\n .query(this.table)\n .withIndex(indexName, (q) => q.eq(indexName, value))\n .unique();\n if (throwIfNull && doc === null) {\n throw new Error(\n `Table \"${this.table}\" does not contain document with field \"${indexName}\" = \\`${value}\\``,\n );\n }\n return doc;\n }),\n )) as any;\n },\n throwIfNull,\n );\n }\n\n normalizeId(id: string): GenericId<Table> | null {\n return isSystemTable(this.table)\n ? this.ctx.db.system.normalizeId(this.table as any, id)\n : this.ctx.db.normalizeId(this.table, id);\n }\n\n // normalizeId or throw\n normalizeIdX(id: string): GenericId<Table> {\n const normalized = this.normalizeId(id);\n if (normalized === null) {\n throw new Error(`Invalid id \\`${id}\\` for table \"${this.table}\"`);\n }\n return normalized;\n }\n\n withIndex(\n indexName: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, typeof indexName>\n >,\n ) => IndexRange,\n ) {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n ).withIndex(indexName, indexRange);\n },\n );\n }\n\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ) {\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieve();\n return (\n query as QueryInitializer<NamedTableInfo<EntsDataModel, Table>>\n ).withSearchIndex(indexName, searchFilter) as any;\n },\n );\n }\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using `Promise.all()`.\nexport interface PromiseEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n > {\n // TODO: At this point there is nothing query specific here, and we can either:\n // 1. Return a generic lazy promise of the list.\n // 2. Not give any methods, because they might lead devs down the wrong path.\n // // This just returns the first retrieved document, it does not optimize\n // // the previous steps in the query.\n // first(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, it does not optimize\n // // the previous steps in the query. Otherwise it behaves like db.query().unique().\n // unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\nexport interface PromiseEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n | EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null\n > {\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArrayOrNull<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[] | null>;\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\nexport interface PromiseEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n > {\n // TODO: At this point there is nothing query specific here, and we can either:\n // 1. Return a generic lazy promise of the list.\n // 2. Not give any methods, because they might lead devs down the wrong path.\n // // This just returns the first retrieved document, it does not optimize\n // // the previous steps in the query.\n // first(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the first retrieved document, or throws if there\n // // are no documents. It does not optimize the previous steps in the query.\n // firstX(): PromiseEnt<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, it does not optimize\n // // the previous steps in the query. Otherwise it behaves like db.query().unique().\n // unique(): PromiseEntOrNull<EntsDataModel, Table>;\n // // This just returns the unique retrieved document, or throws if there\n // // are no documents. It does not optimize the previous steps in the query.\n // // Otherwise it behaves like db.query().unique().\n // uniqueX(): PromiseEnt<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n docs(): Promise<DocumentByName<EntsDataModel, Table>[]>;\n}\n\n// Also implements `PromiseEntsOrNulls`, so individual docs can be null\nclass PromiseEntsOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[] | null\n >\n implements PromiseEntsOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n private retrieve: () => Promise<\n DocumentByName<EntsDataModel, Table>[] | null\n >,\n private throwIfNull: boolean,\n ) {\n super(() => {});\n }\n\n map<TOutput>(\n callbackFn: (\n value: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>,\n index: number,\n array: Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[],\n ) => TOutput | Promise<TOutput>,\n ) {\n return new PromiseArrayImpl(async () => {\n const array = await this;\n if (array === null) {\n return null as TOutput[] | null;\n }\n return await Promise.all(array.map(callbackFn));\n });\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n return loadedRetriever(docs[0] ?? null);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n const doc = docs[0] ?? undefined;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length > 1) {\n throw new Error(\"unique() query returned more than one result\");\n }\n return loadedRetriever(docs[0] ?? null);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this.retrieve();\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length > 1) {\n throw new Error(\"unique() query returned more than one result\");\n }\n if (docs.length < 1) {\n throw new Error(\"unique() query returned no documents\");\n }\n return loadedRetriever(docs[0]);\n },\n true,\n );\n }\n\n async docs() {\n const docs = await this.retrieve();\n return filterByReadRule(\n this.ctx,\n this.entDefinitions,\n this.table,\n docs,\n this.throwIfNull,\n );\n }\n\n then<\n TResult1 =\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value:\n | Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.docs()\n .then((docs) =>\n // Handles PromiseEntsOrNulls\n docs === null\n ? null\n : docs.map((doc) =>\n doc === null\n ? (null as any)\n : entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n ),\n )\n .then(onfulfilled, onrejected);\n }\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface PromiseEntsOrNulls<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n (Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> | null)[]\n > {}\n\nexport interface PromiseEdgeOrderedEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsOrNull<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultOrNull<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge. Returns null if chained to a null result.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean | null>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsWriterOrNull<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge. Returns null if chained to a null result.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean | null>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsWriterOrNull<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEnts<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResult<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEnts<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or throws if there\n * are no ents on the other end of the edge.\n */\n firstX(): PromiseEnt<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * or throws if there are none or more than one.\n */\n uniqueX(): PromiseEnt<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEnts<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEnts<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEnts<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeOrderedEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntsWriter<EntsDataModel, Table> {\n /**\n * Paginate the ents on the other end of the edge.\n * Results are ordered by edge's `_creationTime`.\n */\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriter<EntsDataModel, Table>;\n\n /**\n * Take the first `n` ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n take(n: number): PromiseEntsWriter<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or `null`.\n */\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the first ent on the other end of the edge\n * ordered by edge's `_creationTime`, or throws if there\n * are no ents on the other end of the edge.\n */\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * `null` if there are none, or throws if there are more than one.\n */\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n /**\n * Returns the only ent on the other end of the edge,\n * or throws if there are none or more than one.\n */\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromiseEdgeEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEdgeOrderedEntsWriter<EntsDataModel, Table> {\n /**\n * Returns whether there is an ent with given ID on the other side\n * the edge.\n * @param id The ID of the ent on the other end of the edge\n */\n has(id: GenericId<Table>): Promise<boolean>;\n\n /**\n * Query the ents on the other end of the edge\n * ordered by edge's `_creationTime`.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseEdgeOrderedEntsWriter<EntsDataModel, Table>;\n}\n\nclass PromiseEdgeOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends PromiseEntsOrNullImpl<EntsDataModel, Table>\n implements PromiseEdgeEntsOrNull<EntsDataModel, Table>\n{\n constructor(\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n private edgeDefinition: EdgeConfig & {\n cardinality: \"multiple\";\n type: \"ref\";\n },\n private retrieveSourceId: () => Promise<GenericId<string> | null>,\n private retrieveQuery: () => Promise<Query<GenericTableInfo> | null>,\n private retrieveDoc: (\n edgeDoc: GenericDocument,\n ) => Promise<DocumentByName<EntsDataModel, Table>> = async (edgeDoc) => {\n const sourceId = edgeDoc[edgeDefinition.field] as string;\n const targetId = edgeDoc[edgeDefinition.ref] as string;\n const doc = await this.ctx.db.get(targetId as any);\n if (doc === null) {\n throw new Error(\n `Dangling reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" for ` +\n `document with ID \"${sourceId}\": ` +\n `Could not find a document with ID \"${targetId}\"` +\n ` in table \"${edgeDefinition.to}\" (edge document ID is \"${\n edgeDoc._id as string\n }\").`,\n );\n }\n return doc;\n },\n ) {\n super(\n ctx,\n entDefinitions,\n table,\n async () => {\n const query = await retrieveQuery();\n if (query === null) {\n return null;\n }\n const edgeDocs = await query.collect();\n return await Promise.all(edgeDocs.map(retrieveDoc));\n },\n false,\n );\n }\n\n async has(targetId: GenericId<Table>) {\n const sourceId = await this.retrieveSourceId();\n if (sourceId === null) {\n return null;\n }\n const edgeDoc = await this.ctx.db\n .query(this.edgeDefinition.table)\n .withIndex(edgeCompoundIndexName(this.edgeDefinition), (q) =>\n (q.eq(this.edgeDefinition.field, sourceId as any) as any).eq(\n this.edgeDefinition.ref,\n targetId,\n ),\n )\n .first();\n return edgeDoc !== null;\n }\n\n order(order: \"asc\" | \"desc\") {\n return new PromiseEdgeOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n this.edgeDefinition,\n this.retrieveSourceId,\n async () => {\n const query = await this.retrieveQuery();\n if (query === null) {\n return null;\n }\n // This class supports both ordered and unordered queries,\n // so we pretend this one can be ordered again, interface types\n // won't allow it.\n return query.order(order) as Query<GenericTableInfo>;\n },\n );\n }\n\n paginate(paginationOpts: PaginationOptions) {\n return new PromisePaginationResultOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const query = await this.retrieveQuery();\n if (query === null) {\n return null;\n }\n const result = await query.paginate(paginationOpts);\n return {\n ...result,\n page: await Promise.all(result.page.map(this.retrieveDoc)),\n };\n },\n );\n }\n\n take(n: number) {\n return new PromiseEntsOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n return await this._take(n);\n },\n false,\n );\n }\n\n first() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n firstX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(1);\n if (docs === null) {\n return nullRetriever;\n }\n const [doc] = docs;\n if (doc === undefined) {\n throw new Error(\"Query returned no documents\");\n }\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n unique() {\n return new PromiseEntOrNullImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n return nullRetriever;\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n false,\n );\n }\n\n uniqueX() {\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n this.table,\n async () => {\n const docs = await this._take(2);\n if (docs === null) {\n return nullRetriever;\n }\n if (docs.length === 0) {\n throw new Error(\"Query returned no documents\");\n }\n if (docs.length === 2) {\n throw new Error(\"unique() query returned more than one result\");\n }\n const [doc] = docs;\n return loadedRetriever(doc);\n },\n true,\n );\n }\n\n async _take(n: number) {\n const query = await this.retrieveQuery();\n return await takeFromQuery(\n query,\n n,\n this.ctx,\n this.entDefinitions,\n this.table,\n this.retrieveDoc,\n );\n }\n}\n\nexport interface PromiseEntOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrNull<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table> | null>;\n}\n\nexport interface PromiseEnt<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdge<EntsDataModel, Table, Edge>;\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrThrow<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table>>;\n}\n\nclass PromiseEntOrNullImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null>\n implements PromiseEntOrNull<EntsDataModel, Table>\n{\n constructor(\n protected ctx: EntQueryCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: DocRetriever<\n GenericId<Table> | null,\n DocumentByName<EntsDataModel, Table> | null\n >,\n protected throwIfNull: boolean,\n ) {\n super(() => {});\n }\n\n async doc() {\n const { id, doc: getDoc } = await this.retrieve();\n if (id === null) {\n return null;\n }\n const doc = await getDoc();\n if (doc === null) {\n return null;\n }\n const readPolicy = getReadRule(this.entDefinitions, this.table);\n if (readPolicy !== undefined) {\n const decision = await readPolicy(\n entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n );\n if (this.throwIfNull && !decision) {\n throw new Error(\n `Document cannot be read with id \\`${doc._id as string}\\` in table \"${\n this.table\n }\"`,\n );\n }\n return decision ? doc : null;\n }\n return doc;\n }\n\n then<\n TResult1 = Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null,\n TResult2 = never,\n >(\n onfulfilled?:\n | ((\n value: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null,\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.doc()\n .then((doc) =>\n doc === null\n ? null\n : entWrapper(doc, this.ctx, this.entDefinitions, this.table),\n )\n .then(onfulfilled, onrejected);\n }\n\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(edge: Edge) {\n return this.edgeImpl(edge);\n }\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(edge: Edge) {\n return this.edgeImpl(edge, true);\n }\n\n edgeImpl<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n throwIfNull = false,\n ) {\n const edgeDefinition = getEdgeDefinitions(this.entDefinitions, this.table)[\n edge\n ];\n\n if (edgeDefinition.cardinality === \"multiple\") {\n if (edgeDefinition.type === \"ref\") {\n return new PromiseEdgeOrNullImpl(\n this.ctx,\n this.entDefinitions,\n edgeDefinition.to,\n edgeDefinition,\n async () => {\n const { id } = await this.retrieve();\n return id;\n },\n async () => {\n const { id } = await this.retrieve();\n if (id === null) {\n return null;\n }\n return this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeDefinition.field,\n (q) => q.eq(edgeDefinition.field, id as any) as any,\n );\n },\n ) as any;\n }\n return new PromiseQueryOrNullImpl(\n this.ctx,\n this.entDefinitions,\n edgeDefinition.to,\n async () => {\n const { id } = await this.retrieve();\n if (id === null) {\n return null;\n }\n return this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n );\n },\n ) as any;\n }\n\n return new PromiseEntWriterImpl(\n this.ctx as any,\n this.entDefinitions,\n edgeDefinition.to,\n async () => {\n const { id, doc: getDoc } = await this.retrieve();\n if (id === null) {\n return nullRetriever;\n }\n\n if (edgeDefinition.type === \"ref\") {\n const otherDoc = await this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .unique();\n if (throwIfNull && otherDoc === null) {\n throw new Error(\n `Edge \"${\n edgeDefinition.name\n }\" does not exist for document with ID \"${id as string}\"`,\n );\n }\n return loadedRetriever(otherDoc);\n }\n const doc = (await getDoc())!;\n const otherId = doc[edgeDefinition.field] as any;\n return {\n id: otherId,\n doc: async () => {\n if (otherId === undefined) {\n if (edgeDefinition.optional) {\n return null;\n }\n throw new Error(\n `Unexpected null reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" on document with ID \"${id}\": ` +\n `Expected an ID for a document in table \"${edgeDefinition.to}\".`,\n );\n }\n const otherDoc = await this.ctx.db.get(otherId);\n // _scheduled_functions cannot be made dangling-reference-free,\n // because they are deleted by Convex automatically.\n if (\n otherDoc === null &&\n edgeDefinition.to !== \"_scheduled_functions\"\n ) {\n throw new Error(\n `Dangling reference for edge \"${edgeDefinition.name}\" in ` +\n `table \"${this.table}\" on document with ID \"${id}\": ` +\n `Could not find a document with ID \"${otherId}\"` +\n ` in table \"${edgeDefinition.to}\".`,\n );\n }\n return otherDoc;\n },\n };\n },\n throwIfNull,\n ) as any;\n }\n}\n\nexport interface PromiseArrayOrNull<T> extends Promise<T[] | null> {\n filter<S extends T>(\n predicate: (value: T, index: number, array: T[] | null) => value is S,\n ): Promise<S[] | null>;\n\n filter(\n predicate: (value: T, index: number, array: T[] | null) => unknown,\n ): Promise<T[] | null>;\n}\n\nexport interface PromiseArray<T> extends Promise<T[]> {\n filter<S extends T>(\n predicate: (value: T, index: number, array: T[]) => value is S,\n ): Promise<S[]>;\n\n filter(\n predicate: (value: T, index: number, array: T[]) => unknown,\n ): Promise<T[]>;\n}\n\nclass PromiseArrayImpl<T>\n extends Promise<T[] | null>\n implements PromiseArrayOrNull<T>\n{\n constructor(protected retrieve: () => Promise<T[] | null>) {\n super(() => {});\n }\n\n async filter<S extends T>(\n predicate: (value: T, index: number, array: T[] | null) => value is S,\n ) {\n const array = await this.retrieve();\n if (array === null) {\n return null;\n }\n return array.filter(predicate);\n }\n\n then<TResult1 = T[] | null, TResult2 = never>(\n onfulfilled?:\n | ((value: T[] | null) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.retrieve().then(onfulfilled, onrejected);\n }\n}\n\nexport function entWrapper<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(\n fields: DocumentByName<EntsDataModel, Table>,\n ctx: EntQueryCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n): Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel> {\n const doc = { ...fields };\n const queryInterface = new PromiseEntWriterImpl(\n ctx as any,\n entDefinitions as any,\n table,\n async () => ({ id: doc._id as any, doc: async () => doc }),\n // this `true` doesn't matter, the queryInterface cannot be awaited\n true,\n );\n Object.defineProperty(doc, \"edge\", {\n value: (edge: any) => {\n return queryInterface.edge(edge);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"edgeX\", {\n value: (edge: any) => {\n return queryInterface.edgeX(edge);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"_edges\", {\n value: () => {\n return getEdgeDefinitions(entDefinitions, table);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"doc\", {\n value: () => {\n return doc;\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"patch\", {\n value: (value: any) => {\n return queryInterface.patch(value);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"replace\", {\n value: (value: any) => {\n return queryInterface.replace(value);\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.defineProperty(doc, \"delete\", {\n value: () => {\n return queryInterface.delete();\n },\n enumerable: false,\n writable: false,\n configurable: false,\n });\n Object.entries((entDefinitions as any)[table]?.defaults ?? []).map(\n ([field, value]) => {\n if (doc[field] === undefined) {\n (doc as any)[field] = value;\n }\n },\n );\n return doc as any;\n}\n\nexport function entsTableFactory<\n Ctx extends EntQueryCtx<any>,\n EntsDataModel extends GenericEntsDataModel,\n>(\n ctx: Ctx,\n entDefinitions: EntsDataModel,\n options?: {\n scheduledDelete?: ScheduledDeleteFuncRef;\n },\n): Ctx extends EntMutationCtx<any>\n ? EntsTableWriter<EntsDataModel>\n : EntsTable<EntsDataModel> {\n const enrichedCtx = options !== undefined ? { ...ctx, ...options } : ctx;\n const table = (\n table: TableNamesInDataModel<EntsDataModel>,\n indexName?: string,\n indexRange?: any,\n ) => {\n // Consider being strict here if people struggle with setup:\n // if (typeof ctx.db?.query !== \"function\") {\n // throw new Error(\n // `Expected context with \\`db\\`, got \\`${JSON.stringify(ctx)}\\``\n // );\n // }\n if (typeof table !== \"string\") {\n throw new Error(`Expected table name, got \\`${table as any}\\``);\n }\n\n if (indexName !== undefined) {\n return new PromiseTableImpl(\n enrichedCtx as any,\n entDefinitions,\n table,\n ).withIndex(indexName, indexRange);\n }\n if ((ctx.db as any).insert !== undefined) {\n return new PromiseTableWriterImpl(\n enrichedCtx as any,\n entDefinitions,\n table,\n );\n }\n return new PromiseTableImpl(enrichedCtx as any, entDefinitions, table);\n };\n table.system = table;\n return table as any;\n}\n\ntype EntsTableReader<EntsDataModel extends GenericEntsDataModel> = {\n <\n Table extends TableNamesInDataModel<EntsDataModel>,\n IndexName extends IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n table: Table,\n indexName: IndexName,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => IndexRange,\n ): PromiseQuery<EntsDataModel, Table>;\n <Table extends TableNamesInDataModel<EntsDataModel>>(\n table: Table,\n ): PromiseTable<EntsDataModel, Table>;\n};\n\nexport type EntsTable<EntsDataModel extends GenericEntsDataModel> =\n EntsTableReader<EntsDataModel> & {\n system: EntsTableReader<EntsSystemDataModel>;\n };\n\nexport type EntsTableWriter<EntsDataModel extends GenericEntsDataModel> = {\n <\n Table extends TableNamesInDataModel<EntsDataModel>,\n IndexName extends IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n table: Table,\n indexName: IndexName,\n indexRange?: (\n q: IndexRangeBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => IndexRange,\n ): PromiseQueryWriter<EntsDataModel, Table>;\n <Table extends TableNamesInDataModel<EntsDataModel>>(\n table: Table,\n ): PromiseTableWriter<Table, EntsDataModel>;\n\n system: EntsTableReader<EntsSystemDataModel>;\n};\n\ndeclare class EntInstance<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdge<EntsDataModel, Table, Edge>;\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeOrThrow<EntsDataModel, Table, Edge>;\n doc(): DocumentByName<EntsDataModel, Table>;\n}\n\nexport type Ent<\n Table extends TableNamesInDataModel<EntsDataModel>,\n Doc extends DocumentByName<EntsDataModel, Table>,\n EntsDataModel extends GenericEntsDataModel,\n> = Doc & EntInstance<EntsDataModel, Table>;\n\nexport type GenericEnt<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> = Ent<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>;\n\nexport type PromiseEdge<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEnts<EntsDataModel, ToTable>,\n PromiseQuery<EntsDataModel, ToTable>,\n ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? PromiseEntOrNull<EntsSystemDataModel, ToTable>\n : PromiseEntOrNull<EntsDataModel, ToTable>,\n ToTable extends \"_storage\"\n ? PromiseEnt<EntsSystemDataModel, ToTable>\n : ToTable extends \"_scheduled_functions\"\n ? PromiseEntOrNull<EntsSystemDataModel, ToTable>\n : PromiseEnt<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeOrThrow<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEnts<EntsDataModel, ToTable>,\n PromiseQuery<EntsDataModel, ToTable>,\n PromiseEnt<EntsDataModel, ToTable>,\n PromiseEnt<EntsDataModel, ToTable>\n>;\n\ntype PromiseEdgeOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsOrNull<EntsDataModel, ToTable>,\n PromiseQueryOrNull<EntsDataModel, ToTable>,\n PromiseEntOrNull<EntsDataModel, ToTable>,\n PromiseEntOrNull<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriter<EntsDataModel, ToTable>,\n PromiseQueryWriter<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriterOrThrow<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriter<EntsDataModel, ToTable>,\n PromiseQueryWriter<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>,\n PromiseEntWriter<EntsDataModel, ToTable>\n>;\n\nexport type PromiseEdgeWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n Edge extends keyof EntsDataModel[Table][\"edges\"],\n Config extends GenericEdgeConfig = EntsDataModel[Table][\"edges\"][Edge],\n ToTable extends\n TableNamesInDataModel<EntsDataModel> = EntsDataModel[Table][\"edges\"][Edge][\"to\"],\n> = PromiseEdgeResult<\n Config,\n PromiseEdgeEntsWriterOrNull<EntsDataModel, ToTable>,\n PromiseQueryWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>,\n PromiseEntWriterOrNull<EntsDataModel, ToTable>\n>;\n\nexport interface PromiseOrderedQueryWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>[]\n >,\n PromiseOrderedQueryBase<EntsDataModel, Table> {\n paginate(\n paginationOpts: PaginationOptions,\n ): PromisePaginationResultWriter<EntsDataModel, Table>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): PromiseArray<TOutput>;\n\n take(n: number): PromiseEntsWriter<EntsDataModel, Table>;\n\n first(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n unique(): PromiseEntWriterOrNull<EntsDataModel, Table>;\n\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromiseQueryWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseOrderedQueryWriter<EntsDataModel, Table> {\n order(order: \"asc\" | \"desc\"): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n}\n\n// This lazy promise materializes objects, so chaining to this type of\n// lazy promise performs one operation for each\n// retrieved document in JavaScript, basically as if using\n// `Promise.all()`.\nexport interface PromiseEntsWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEnts<EntsDataModel, Table> {\n // This just returns the first retrieved document, or throws if there\n // are no documents. It does not optimize the previous steps in the query.\n firstX(): PromiseEntWriter<EntsDataModel, Table>;\n\n // This just returns the unique retrieved document, or throws if there\n // are no documents. It does not optimize the previous steps in the query.\n // Otherwise it behaves like db.query().unique().\n uniqueX(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nexport interface PromisePaginationResultWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<PaginationResult<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > | null> {\n docs(): Promise<PaginationResult<\n DocumentByName<EntsDataModel, Table>\n > | null>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput> | null>;\n}\n\nexport interface PromisePaginationResultWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n PaginationResult<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n >\n > {\n docs(): Promise<PaginationResult<DocumentByName<EntsDataModel, Table>>>;\n\n map<TOutput>(\n callbackFn: (\n value: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n index: number,\n array: EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >[],\n ) => Promise<TOutput> | TOutput,\n ): Promise<PaginationResult<TOutput>>;\n}\n\nexport interface PromiseTableWriter<\n Table extends TableNamesInDataModel<EntsDataModel>,\n EntsDataModel extends GenericEntsDataModel,\n> extends PromiseQueryWriter<EntsDataModel, Table>,\n PromiseTableBase<EntsDataModel, Table> {\n get<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntWriterOrNull<EntsDataModel, Table>;\n get(id: GenericId<Table>): PromiseEntWriterOrNull<EntsDataModel, Table>;\n /**\n * Fetch a unique document from the DB using given index, throw if it doesn't exist.\n */\n getX<\n Indexes extends EntsDataModel[Table][\"indexes\"],\n Index extends keyof Indexes,\n >(\n indexName: Index,\n ...values: IndexFieldTypesForEq<EntsDataModel, Table, Indexes[Index]>\n ): PromiseEntWriter<EntsDataModel, Table>;\n /**\n * Fetch a document from the DB for a given ID, throw if it doesn't exist.\n */\n getX(id: GenericId<Table>): PromiseEntWriter<EntsDataModel, Table>;\n\n /**\n * Return all documents in the table in given order.\n * Sort either by given index or by _creationTime.\n */\n order(\n order: \"asc\" | \"desc\",\n indexName?: IndexNames<NamedTableInfo<EntsDataModel, Table>>,\n ): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n\n /**\n * Query by running a full text search against a search index.\n *\n * Search queries must always search for some text within the index's\n * `searchField`. This query can optionally add equality filters for any\n * `filterFields` specified in the index.\n *\n * Documents will be returned in relevance order based on how well they\n * match the search text.\n *\n * To learn about full text search, see [Indexes](https://docs.convex.dev/text-search).\n *\n * @param indexName - The name of the search index to query.\n * @param searchFilter - A search filter expression constructed with the\n * supplied {@link SearchFilterBuilder}. This defines the full text search to run\n * along with equality filtering to run within the search index.\n * @returns - A query that searches for matching documents, returning them\n * in relevancy order.\n */\n search<\n IndexName extends SearchIndexNames<NamedTableInfo<EntsDataModel, Table>>,\n >(\n indexName: IndexName,\n searchFilter: (\n q: SearchFilterBuilder<\n DocumentByName<EntsDataModel, Table>,\n NamedSearchIndex<NamedTableInfo<EntsDataModel, Table>, IndexName>\n >,\n ) => SearchFilter,\n ): PromiseOrderedQueryWriter<EntsDataModel, Table>;\n /**\n * Insert a new document into a table.\n *\n * @param table - The name of the table to insert a new document into.\n * @param value - The {@link Value} to insert into the given table.\n * @returns - {@link GenericId} of the new document.\n */\n insert(\n value: Expand<\n WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n /**\n * Insert new documents into a table.\n *\n * @param table - The name of the table to insert a new document into.\n * @param value - The {@link Value} to insert into the given table.\n * @returns - {@link GenericId} of the new document.\n */\n // TODO: Chain methods to get the written documents?\n insertMany(\n values: Expand<\n WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >[],\n ): Promise<GenericId<Table>[]>;\n}\n\nclass PromiseTableWriterImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseTableImpl<EntsDataModel, Table> {\n private base: WriterImplBase<EntsDataModel, Table>;\n\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n entDefinitions: EntsDataModel,\n table: Table,\n ) {\n super(ctx, entDefinitions, table);\n this.base = new WriterImplBase(ctx, entDefinitions, table);\n }\n\n insert(\n value: WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n await this.base.checkReadAndWriteRule(\"create\", undefined, value);\n await this.base.checkUniqueness(value);\n const fields = this.base.fieldsOnly(value as any);\n const docId = await this.ctx.db.insert(this.table, fields as any);\n const edges: EdgeChanges = {};\n Object.keys(value).forEach((key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\")\n ) {\n return;\n }\n\n edges[key] = {\n add:\n edgeDefinition.cardinality === \"single\"\n ? [value[key] as GenericId<any>]\n : (value[key] as GenericId<any>[]),\n };\n });\n await this.base.writeEdges(docId, edges);\n return docId;\n },\n );\n }\n\n // TODO: fluent API\n async insertMany(\n values: WithoutSystemFields<\n WithEdgeInserts<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >[],\n ) {\n return await Promise.all(values.map((value) => this.insert(value)));\n }\n}\n\nexport interface PromiseEntWriterOrNull<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<EntWriter<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n > | null> {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriterOrNull<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table> | null>;\n}\n\nexport interface PromiseEntWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<\n EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>\n > {\n edge<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriter<EntsDataModel, Table, Edge>;\n\n edgeX<Edge extends keyof EntsDataModel[Table][\"edges\"]>(\n edge: Edge,\n ): PromiseEdgeWriterOrThrow<EntsDataModel, Table, Edge>;\n\n doc(): Promise<DocumentByName<EntsDataModel, Table>>;\n\n /**\n * Patch this existing document, shallow merging it with the given partial\n * document.\n *\n * New fields are added. Existing fields are overwritten. Fields set to\n * `undefined` are removed.\n *\n * @param value - The partial {@link GenericDocument} to merge into this document. If this new value\n * specifies system fields like `_id`, they must match the document's existing field values.\n */\n patch(\n value: Partial<\n Expand<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Replace the value of an existing document, overwriting its old value.\n *\n * @param value - The new {@link GenericDocument} for the document. This value can omit the system fields,\n * and the database will preserve them in.\n */\n replace(\n value: Expand<\n WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Delete this existing document.\n *\n * @param id - The {@link GenericId} of the document to remove.\n */\n delete(): Promise<GenericId<Table>>;\n}\n\nclass PromiseEntWriterImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends PromiseEntOrNullImpl<EntsDataModel, Table> {\n private base: WriterImplBase<EntsDataModel, Table>;\n\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n protected retrieve: DocRetriever<\n GenericId<Table> | null,\n DocumentByName<EntsDataModel, Table> | null\n >,\n protected throwIfNull: boolean,\n ) {\n super(ctx, entDefinitions, table, retrieve, throwIfNull);\n this.base = new WriterImplBase(ctx, entDefinitions, table);\n }\n\n patch(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const { id: docId } = await this.retrieve();\n const id = docId!;\n await this.base.checkReadAndWriteRule(\"update\", id, value);\n await this.base.checkUniqueness(value, id);\n const fields = this.base.fieldsOnly(value);\n if (Object.keys(fields).length > 0) {\n await this.ctx.db.patch(this.table, id, fields as any);\n }\n\n const edges: EdgeChanges = {};\n await Promise.all(\n Object.keys(value).map(async (key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\")\n ) {\n // The built-in patch takes care of updating the field\n return;\n }\n if (edgeDefinition.cardinality === \"single\") {\n throw new Error(\n `Cannot set 1:1 edge \"${edgeDefinition.name}\" on ent in table ` +\n `\"${this.table}\", update the ent in \"${edgeDefinition.to}\" ` +\n `table instead.`,\n );\n // const existing = await this.ctx.db\n // .query(edgeDefinition.to)\n // .withIndex(edgeDefinition.ref, (q) =>\n // q.eq(edgeDefinition.ref, docId as any)\n // )\n // .unique();\n\n // edges[key] = {\n // add: value[key] as GenericId<any>,\n // remove: existing?._id as GenericId<any> | undefined,\n // };\n } else {\n if (edgeDefinition.type === \"field\") {\n throw new Error(\n `Cannot set 1:many edges \"${edgeDefinition.name}\" on ent in table ` +\n `\"${this.table}\", update the ents in \"${edgeDefinition.to}\" ` +\n `table instead.`,\n );\n } else {\n const { add, remove } = value[key]!;\n const removeEdges = (\n await Promise.all(\n (remove ?? []).map(async (otherId) =>\n (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeCompoundIndexName(edgeDefinition),\n (q) =>\n (q.eq(edgeDefinition.field, id as any) as any).eq(\n edgeDefinition.ref,\n otherId,\n ),\n )\n .collect()\n ).concat(\n edgeDefinition.symmetric\n ? await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(\n edgeCompoundIndexName(edgeDefinition),\n (q) =>\n (\n q.eq(\n edgeDefinition.field,\n otherId as any,\n ) as any\n ).eq(edgeDefinition.ref, id),\n )\n .collect()\n : [],\n ),\n ),\n )\n )\n .flat()\n .map((edgeDoc) => edgeDoc._id as GenericId<any>);\n edges[key] = {\n add,\n removeEdges,\n };\n }\n }\n }),\n );\n await this.base.writeEdges(id, edges);\n return id;\n },\n );\n }\n\n replace(\n value: WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n return new PromiseEntIdImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const { id } = await this.retrieve();\n const docId = id!;\n await this.base.checkReadAndWriteRule(\"update\", docId, value);\n await this.base.checkUniqueness(value, docId);\n const fields = this.base.fieldsOnly(value as any);\n await this.ctx.db.replace(this.table, docId, fields as any);\n\n const edges: EdgeChanges = {};\n\n await Promise.all(\n Object.values(\n getEdgeDefinitions(this.entDefinitions, this.table),\n ).map(async (edgeDefinition) => {\n const key = edgeDefinition.name;\n const idOrIds = value[key];\n if (idOrIds === undefined) {\n return;\n }\n if (edgeDefinition.cardinality === \"single\") {\n if (edgeDefinition.type === \"ref\") {\n const oldDoc = (await this.ctx.db.get(docId))!;\n if (oldDoc[key] !== undefined && oldDoc[key] !== idOrIds) {\n // This would be only allowed if the edge is optional\n // on the field side, which is not supported\n\n // TODO: Fix!\n\n throw new Error(\"Cannot set 1:1 edge from ref end.\");\n // edges[key] = {\n // add: idOrIds as GenericId<any>,\n // remove: oldDoc[key] as GenericId<any> | undefined,\n // };\n }\n }\n } else {\n if (edgeDefinition.type === \"field\") {\n throw new Error(\"Cannot set 1:many edge from many end.\");\n // const existing = (\n // await this.ctx.db\n // .query(edgeDefinition.to)\n // .withIndex(edgeDefinition.ref, (q) =>\n // q.eq(edgeDefinition.ref, docId as any)\n // )\n // .collect()\n // ).map((doc) => doc._id);\n // edges[key] = {\n // add: idOrIds as GenericId<any>[],\n // remove: { remove: true },\n // };\n } else {\n const requested = new Set(idOrIds);\n const removeEdges = (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.field, (q) =>\n q.eq(edgeDefinition.field, docId as any),\n )\n .collect()\n )\n .map((doc) => [doc._id, doc[edgeDefinition.ref]] as const)\n .concat(\n edgeDefinition.symmetric\n ? (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, docId as any),\n )\n .collect()\n ).map(\n (doc) =>\n [doc._id, doc[edgeDefinition.field]] as const,\n )\n : [],\n )\n .filter(([_edgeId, otherId]) => {\n if (requested.has(otherId as any)) {\n requested.delete(otherId as any);\n return false;\n }\n return true;\n })\n .map(([edgeId]) => edgeId as GenericId<any>);\n edges[key] = {\n add: idOrIds as GenericId<any>[],\n removeEdges,\n };\n }\n }\n }),\n );\n await this.base.writeEdges(docId, edges);\n return docId;\n },\n );\n }\n\n async delete() {\n const { id: docId } = await this.retrieve();\n const id = docId!;\n return this.base.deleteId(id, \"default\");\n }\n}\n\ndeclare class EntWriterInstance<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends EntInstance<EntsDataModel, Table> {\n /**\n * Patch this existing document, shallow merging it with the given partial\n * document.\n *\n * New fields are added. Existing fields are overwritten. Fields set to\n * `undefined` are removed.\n *\n * @param value - The partial {@link GenericDocument} to merge into this document. If this new value\n * specifies system fields like `_id`, they must match the document's existing field values.\n */\n patch(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Replace the value of this existing document, overwriting its old value.\n *\n * @param value - The new {@link GenericDocument} for the document. This value can omit the system fields,\n * and the database will preserve them in.\n */\n replace(\n value: WithOptionalSystemFields<\n WithEdges<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ): PromiseEntId<EntsDataModel, Table>;\n\n /**\n * Delete this existing document.\n *\n * @param id - The {@link GenericId} of the document to remove.\n */\n delete(): Promise<GenericId<Table>>;\n}\n\n// This type is strange: The ordering is strange,\n// and the `Doc` would not have to be generic:\n// This is all just so that the type shows useful\n// informatin when hovering values.\ntype EntWriter<\n Table extends TableNamesInDataModel<EntsDataModel>,\n Doc extends DocumentByName<EntsDataModel, Table>,\n EntsDataModel extends GenericEntsDataModel,\n> = Doc & EntWriterInstance<EntsDataModel, Table>;\n\nexport type GenericEntWriter<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> = EntWriter<Table, DocumentByName<EntsDataModel, Table>, EntsDataModel>;\n\nexport interface PromiseEntId<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> extends Promise<GenericId<Table>> {\n get(): PromiseEntWriter<EntsDataModel, Table>;\n}\n\nclass PromiseEntIdImpl<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n >\n extends Promise<GenericId<Table>>\n implements PromiseEntId<EntsDataModel, Table>\n{\n constructor(\n private ctx: EntMutationCtx<EntsDataModel>,\n private entDefinitions: EntsDataModel,\n private table: Table,\n private retrieve: () => Promise<GenericId<Table>>,\n ) {\n super(() => {});\n }\n\n get() {\n return new PromiseEntWriterImpl(\n this.ctx,\n this.entDefinitions,\n this.table,\n async () => {\n const id = await this.retrieve();\n return { id, doc: async () => this.ctx.db.get(id) };\n },\n true,\n ) as any;\n }\n\n then<TResult1 = GenericId<Table>, TResult2 = never>(\n onfulfilled?:\n | ((value: GenericId<Table>) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.retrieve().then(onfulfilled, onrejected);\n }\n}\n\nexport interface EntQueryCtx<DataModel extends GenericDataModel> {\n db: GenericDatabaseReader<DataModel>;\n vectorSearch?: undefined;\n}\n\nexport interface EntMutationCtx<DataModel extends GenericDataModel>\n extends EntQueryCtx<DataModel> {\n db: GenericDatabaseWriter<DataModel>;\n\n storage: StorageWriter;\n scheduler: Scheduler;\n}\n\nexport type DocRetriever<ID, Doc> = () => Promise<{\n id: ID;\n doc: () => Promise<Doc>;\n}>;\n\nconst nullRetriever = {\n id: null,\n doc: async () => null,\n};\n\n// function idRetriever<\n// DataModel extends GenericDataModel,\n// Table extends TableNamesInDataModel<DataModel>\n// >(ctx: EntQueryCtx<DataModel>, id: GenericId<Table>) {\n// return {\n// id,\n// doc: async () => ctx.db.get(id),\n// };\n// }\n\nfunction loadedRetriever<\n DataModel extends GenericDataModel,\n Table extends TableNamesInDataModel<DataModel>,\n>(doc: DocumentByName<DataModel, Table> | null) {\n return {\n id: (doc?._id ?? null) as GenericId<Table> | null,\n doc: async () => doc,\n };\n}\n\ntype Rules = Record<string, RuleConfig>;\n\ntype RuleConfig = {\n read?: (doc: GenericDocument) => Promise<boolean>;\n write?: (\n args:\n | {\n operation: \"create\";\n ent: undefined;\n value: WithoutSystemFields<GenericDocument>;\n }\n | {\n operation: \"update\";\n ent: Ent<any, GenericDocument, any>;\n value: Partial<WithoutSystemFields<GenericDocument>>;\n }\n | {\n operation: \"delete\";\n ent: Ent<any, GenericDocument, any>;\n value: undefined;\n },\n ) => Promise<boolean>;\n};\n\nexport function addEntRules<EntsDataModel extends GenericEntsDataModel>(\n entDefinitions: EntsDataModel,\n rules: {\n [Table in keyof EntsDataModel]?: Table extends TableNamesInDataModel<EntsDataModel>\n ? {\n read?: (\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >,\n ) => Promise<boolean>;\n write?: (\n args:\n | {\n operation: \"create\";\n ent: undefined;\n value: WithoutSystemFields<\n DocumentByName<EntsDataModel, Table>\n >;\n }\n | {\n operation: \"update\";\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >;\n value: Partial<\n WithoutSystemFields<DocumentByName<EntsDataModel, Table>>\n >;\n }\n | {\n operation: \"delete\";\n ent: Ent<\n Table,\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel\n >;\n value: undefined;\n },\n ) => Promise<boolean>;\n }\n : never;\n },\n): EntsDataModel {\n return { ...entDefinitions, rules };\n}\n\nasync function takeFromQuery(\n query: Query<GenericTableInfo> | null,\n n: number,\n ctx: EntQueryCtx<any>,\n entDefinitions: GenericEntsDataModel,\n table: string,\n mapToResult?: (retrieved: GenericDocument) => Promise<GenericDocument>,\n) {\n if (query === null) {\n return null;\n }\n const readPolicy = getReadRule(entDefinitions, table);\n if (readPolicy === undefined) {\n const results = await query.take(n);\n if (mapToResult === undefined) {\n return results;\n }\n return Promise.all(results.map(mapToResult));\n }\n let numItems = n;\n const docs = [];\n let hasMore = true;\n const iterator = query[Symbol.asyncIterator]();\n while (hasMore && docs.length < n) {\n const page = [];\n for (let i = 0; i < numItems; i++) {\n const { done, value } = await iterator.next();\n if (done) {\n hasMore = false;\n break;\n }\n page.push(mapToResult === undefined ? value : await mapToResult(value));\n }\n docs.push(\n ...(await filterByReadRule(\n ctx,\n entDefinitions,\n table,\n page,\n false,\n ))!.slice(0, n - docs.length),\n );\n numItems = Math.min(64, numItems * 2);\n }\n return docs;\n}\n\nasync function filterByReadRule<Doc extends GenericDocument>(\n ctx: EntQueryCtx<any>,\n entDefinitions: GenericEntsDataModel,\n table: string,\n docs: Doc[] | null,\n throwIfNull: boolean,\n) {\n if (docs === null) {\n return null;\n }\n const readPolicy = getReadRule(entDefinitions, table);\n if (readPolicy === undefined) {\n return docs;\n }\n const decisions = await Promise.all(\n docs.map(async (doc) => {\n const decision = await readPolicy(\n entWrapper(doc, ctx, entDefinitions, table),\n );\n if (throwIfNull && !decision) {\n throw new Error(\n `Document cannot be read with id \\`${\n doc._id as string\n }\\` in table \"${table}\"`,\n );\n }\n return decision;\n }),\n );\n return docs.filter((_, i) => decisions[i]);\n}\n\nfunction getIndexFields(\n entDefinitions: GenericEntsDataModel,\n table: string,\n index: string,\n) {\n return (entDefinitions[table].indexes as unknown as Record<string, string[]>)[\n index\n ];\n}\n\nexport function getReadRule(\n entDefinitions: GenericEntsDataModel,\n table: string,\n) {\n return (entDefinitions.rules as Rules)?.[table]?.read;\n}\n\nexport function getWriteRule(\n entDefinitions: GenericEntsDataModel,\n table: string,\n) {\n return (entDefinitions.rules as Rules)?.[table]?.write;\n}\n\nexport function getDeletionConfig<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(entDefinitions: EntsDataModel, table: Table) {\n return (entDefinitions[table] as any).deletionConfig as\n | DeletionConfig\n | undefined;\n}\n","import {\n DataModelFromSchemaDefinition,\n DefineSchemaOptions,\n GenericDataModel,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n IndexTiebreakerField,\n SchemaDefinition,\n SearchIndexConfig,\n TableDefinition,\n VectorIndexConfig,\n defineSchema,\n} from \"convex/server\";\nimport {\n GenericId,\n GenericValidator,\n ObjectType,\n VAny,\n VFloat64,\n VId,\n VObject,\n VOptional,\n VUnion,\n Validator,\n asObjectValidator,\n v,\n} from \"convex/values\";\n\nexport function defineEntSchema<\n Schema extends Record<string, EntDefinition>,\n StrictTableNameTypes extends boolean = true,\n>(\n schema: Schema,\n options?: DefineSchemaOptions<StrictTableNameTypes>,\n): SchemaDefinition<Schema, StrictTableNameTypes> {\n // Set the properties of edges which requires knowing their inverses,\n // and add edge tables.\n const tableNames = Object.keys(schema);\n for (const tableName of tableNames) {\n const table = schema[tableName];\n for (const edge of edgeConfigsBeforeDefineSchema(table)) {\n if (\n // Skip inverse edges, we process their forward edges\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n (edge.inverse !== undefined ||\n // symmetric is only set by defineEntSchema,\n // so we already processed the pair\n (edge as unknown as EdgeConfigMultipleRef).symmetric !== undefined)\n ) {\n continue;\n }\n\n const otherTableName = edge.to;\n if (otherTableName.startsWith(\"_\")) {\n if (edge.cardinality !== \"single\") {\n throw new Error(\n `Many:many edge \"${edge.name}\" in table \"${tableName}\" ` +\n `points to a system table \"${otherTableName}\", but only 1:1 ` +\n `edges can point to system tables`,\n );\n }\n if (edge.type !== \"field\") {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `pointing to a system table \"${otherTableName}\" must store ` +\n `the edge by storing the system document ID. Remove ` +\n `the \\`ref\\` option.`,\n );\n }\n if (edge.deletion === \"soft\") {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `pointing to a system table \"${otherTableName}\" cannot use ` +\n `soft deletion, because system documents cannot be soft deleted.`,\n );\n }\n // Nothing else to do, the edge is set up.\n continue;\n }\n const otherTable = schema[otherTableName];\n if (otherTable === undefined) {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `points to an undefined table \"${otherTableName}\"`,\n );\n }\n\n const isSelfDirected = edge.to === tableName;\n\n const inverseEdgeCandidates = edgeConfigsBeforeDefineSchema(\n otherTable,\n ).filter(canBeInverseEdge(tableName, edge, isSelfDirected));\n if (inverseEdgeCandidates.length > 1) {\n throw new Error(\n `Edge \"${edge.name}\" in table \"${tableName}\" ` +\n `has too many potential inverse edges in table \"${otherTableName}\": ` +\n `${inverseEdgeCandidates\n .map((edge) => `\"${edge.name}\"`)\n .join(\", \")}`,\n );\n }\n const inverseEdge: EdgeConfigBeforeDefineSchema | undefined =\n inverseEdgeCandidates[0];\n\n if (\n edge.cardinality === \"single\" &&\n edge.type === \"field\" &&\n inverseEdge === undefined\n ) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ` +\n `for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n\n // Default `ref` on the multiple end of the edge,\n if (edge.cardinality === \"single\" && edge.type === \"ref\") {\n if (inverseEdge === undefined) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ${\n edge.ref !== null ? `with field \"${edge.ref}\" ` : \"\"\n }for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n if (\n inverseEdge.cardinality === \"single\" &&\n inverseEdge.type === \"ref\"\n ) {\n throw new Error(\n `Both edge \"${edge.name}\" in table \"${inverseEdge.to}\" and ` +\n `edge \"${inverseEdge.name}\" in table \"${edge.to}\" are marked ` +\n `as references, choose one to store the edge by removing ` +\n `the \\`ref\\` option.`,\n );\n }\n if (\n inverseEdge.cardinality !== \"single\" ||\n inverseEdge.type !== \"field\"\n ) {\n throw new Error(\n `Unexpected inverse edge type ${edge.name}, ${inverseEdge?.name}`,\n );\n }\n if (edge.ref === null) {\n (edge as EdgeConfigSingleRef).ref = inverseEdge.field;\n }\n // For now the the non-optional end is always unique\n (inverseEdge as EdgeConfigSingleField).unique = true;\n }\n if (\n edge.cardinality === \"single\" ||\n (edge.cardinality === \"multiple\" && edge.type === \"field\")\n ) {\n if (\n edge.deletion !== undefined &&\n deletionConfigFromEntDefinition(otherTable) === undefined\n ) {\n throw new Error(\n `Cannot specify soft deletion behavior for edge ` +\n `\"${edge.name}\" in table \"${tableName}\" ` +\n `because the target table \"${otherTableName}\" does not have ` +\n `a \"soft\" or \"scheduled\" deletion behavior ` +\n `configured.`,\n );\n }\n }\n if (edge.cardinality === \"multiple\") {\n if (!isSelfDirected && inverseEdge === undefined) {\n throw new Error(\n `Missing inverse edge in table \"${otherTableName}\" ` +\n `for edge \"${edge.name}\" in table \"${tableName}\"`,\n );\n }\n\n if (inverseEdge?.cardinality === \"single\") {\n if (inverseEdge.type === \"ref\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `specified \\`ref\\`, but it must store the 1:many edge as a field. ` +\n `Check the its inverse edge \"${edge.name}\" in table \"${tableName}\".`,\n );\n }\n if (edge.type === \"ref\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `cannot be singular, as the edge \"${edge.name}\" in table \"${tableName}\" did not ` +\n `specify the \\`ref\\` option.`,\n );\n }\n (edge as EdgeConfigMultipleField).type = \"field\";\n (edge as EdgeConfigMultipleField).ref = inverseEdge.field;\n }\n\n if (inverseEdge?.cardinality === \"multiple\" || isSelfDirected) {\n if (!isSelfDirected && edge?.type === \"field\") {\n throw new Error(\n `The edge \"${edge.name}\" in table \"${tableName}\" ` +\n `specified \\`ref\\`, but its inverse edge \"${inverseEdge.name}\" ` +\n `in table \"${otherTableName}\" is not the singular end of a 1:many edge.`,\n );\n }\n if (inverseEdge?.type === \"field\") {\n throw new Error(\n `The edge \"${inverseEdge.name}\" in table \"${otherTableName}\" ` +\n `specified \\`ref\\`, but its inverse edge \"${edge.name}\" ` +\n `in table \"${tableName}\" is not the singular end of a 1:many edge.`,\n );\n }\n\n const edgeTableName =\n edge.type === \"ref\" && edge.table !== undefined\n ? edge.table\n : inverseEdge === undefined\n ? `${tableName}_${edge.name}`\n : inverseEdge.name !== tableName\n ? `${tableName}_${inverseEdge.name}_to_${edge.name}`\n : `${inverseEdge.name}_to_${edge.name}`;\n\n const forwardId =\n edge.type === \"ref\" && edge.field !== undefined\n ? edge.field\n : inverseEdge === undefined\n ? \"aId\"\n : tableName === otherTableName\n ? inverseEdge.name + \"Id\"\n : tableName + \"Id\";\n const inverseId =\n isSelfDirected &&\n edge.type === \"ref\" &&\n edge.inverseField !== undefined\n ? edge.inverseField\n : inverseEdge === undefined\n ? \"bId\"\n : inverseEdge.type === \"ref\" && inverseEdge.field !== undefined\n ? inverseEdge.field\n : tableName === otherTableName\n ? edge.name + \"Id\"\n : otherTableName + \"Id\";\n // Add the table\n const edgeTable = defineEnt({\n [forwardId]: v.id(tableName),\n [inverseId]: v.id(otherTableName),\n })\n .index(forwardId, [forwardId])\n .index(inverseId, [inverseId])\n .index(edgeCompoundIndexNameRaw(forwardId, inverseId), [\n forwardId,\n inverseId,\n ]);\n const isSymmetric = inverseEdge === undefined;\n if (!isSymmetric) {\n edgeTable.index(edgeCompoundIndexNameRaw(inverseId, forwardId), [\n inverseId,\n forwardId,\n ]);\n }\n (schema as Record<string, EntDefinition>)[edgeTableName] = edgeTable;\n const edgeConfig = edge as unknown as EdgeConfigMultipleRef;\n edgeConfig.type = \"ref\";\n edgeConfig.table = edgeTableName;\n edgeConfig.field = forwardId;\n edgeConfig.ref = inverseId;\n edgeConfig.symmetric = inverseEdge === undefined;\n if (inverseEdge !== undefined) {\n inverseEdge.type = \"ref\";\n const inverseEdgeConfig =\n inverseEdge as unknown as EdgeConfigMultipleRef;\n inverseEdgeConfig.table = edgeTableName;\n inverseEdgeConfig.field = inverseId;\n inverseEdgeConfig.ref = forwardId;\n inverseEdgeConfig.symmetric = false;\n }\n }\n }\n }\n }\n return defineSchema(schema, options);\n}\n\nexport function edgeCompoundIndexName(\n edgeDefinition: EdgeConfig & { cardinality: \"multiple\"; type: \"ref\" },\n) {\n return edgeCompoundIndexNameRaw(edgeDefinition.field, edgeDefinition.ref);\n}\n\nfunction edgeCompoundIndexNameRaw(idA: string, idB: string) {\n return `${idA}_${idB}`;\n}\n\nfunction canBeInverseEdge(\n tableName: string,\n edge: EdgeConfigBeforeDefineSchema,\n isSelfDirected: boolean,\n) {\n return (candidate: EdgeConfigBeforeDefineSchema) => {\n if (candidate.to !== tableName) {\n return false;\n }\n // Simple: pick out explicit inverse edges\n if (isSelfDirected) {\n return (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n candidate.inverse === edge.name\n );\n }\n // If both ref and field are known, only consider matching edges (from the ref side)\n if (\n (edge.cardinality === \"single\" &&\n edge.type === \"ref\" &&\n edge.ref !== null) ||\n (edge.cardinality === \"multiple\" &&\n edge.type === \"field\" &&\n edge.ref !== true)\n ) {\n if (candidate.cardinality === \"single\" && candidate.type === \"field\") {\n return edge.ref === candidate.field;\n }\n }\n // If both ref and field are known, only consider matching edges (from the field side)\n if (\n edge.cardinality === \"single\" &&\n edge.type === \"field\" &&\n edge.field !== null\n ) {\n if (\n (candidate.cardinality === \"single\" &&\n candidate.type === \"ref\" &&\n candidate.ref !== null) ||\n (candidate.cardinality === \"multiple\" &&\n candidate.type === \"field\" &&\n candidate.ref !== true)\n ) {\n return edge.field === candidate.ref;\n }\n }\n\n // If table is known on both ends, only consider matching edges\n if (\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n edge.table !== undefined\n ) {\n return (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n edge.table === candidate.table\n );\n }\n if (\n candidate.cardinality === \"multiple\" &&\n candidate.type === \"ref\" &&\n candidate.table !== undefined\n ) {\n return (\n edge.cardinality === \"multiple\" &&\n edge.type === \"ref\" &&\n edge.table === candidate.table\n );\n }\n return true;\n };\n}\n\nfunction edgeConfigsBeforeDefineSchema(table: EntDefinition) {\n return Object.values(\n (table as any).edgeConfigs as Record<string, EdgeConfigBeforeDefineSchema>,\n );\n}\n\nfunction deletionConfigFromEntDefinition(table: EntDefinition) {\n return (table as any).deletionConfig as DeletionConfig | undefined;\n}\n\nexport function defineEnt<\n DocumentSchema extends Validator<Record<string, any>, \"required\", any>,\n>(documentSchema: DocumentSchema): EntDefinition<DocumentSchema>;\n\nexport function defineEnt<\n DocumentSchema extends Record<string, GenericValidator>,\n>(\n documentSchema: DocumentSchema,\n): EntDefinition<VObject<ObjectType<DocumentSchema>, DocumentSchema>>;\n\nexport function defineEnt<\n DocumentSchema extends\n | Validator<Record<string, any>, \"required\", any>\n | Record<string, GenericValidator>,\n>(documentSchema: DocumentSchema): EntDefinition<any> {\n if (isValidator(documentSchema)) {\n if (\n !(\n documentSchema.kind === \"object\" ||\n (documentSchema.kind === \"union\" &&\n documentSchema.members.every((member) => member.kind === \"object\"))\n )\n ) {\n throw new Error(\"Ent shape must be an object or a union of objects\");\n }\n }\n return new EntDefinitionImpl(asObjectValidator(documentSchema)) as any;\n}\n\nfunction isValidator(v: any): v is GenericValidator {\n return !!v.isConvexValidator;\n}\n\nexport function defineEntFromTable<\n DocumentType extends GenericValidator = GenericValidator,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n Indexes extends GenericTableIndexes = {},\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n SearchIndexes extends GenericTableSearchIndexes = {},\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n VectorIndexes extends GenericTableVectorIndexes = {},\n>(\n definition: TableDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes\n >,\n): EntDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes> {\n const validator: DocumentType = definition.validator;\n if (validator.kind !== \"object\") {\n throw new Error(\n \"Only tables with object definition are supported in Ents, not unions\",\n );\n }\n\n const entDefinition = defineEnt(validator.fields);\n // @ts-expect-error Private fields\n entDefinition.indexes = definition.indexes;\n // @ts-expect-error Private fields\n entDefinition.searchIndexes = definition.searchIndexes;\n // @ts-expect-error Private fields\n entDefinition.vectorIndexes = definition.vectorIndexes;\n return entDefinition as any;\n}\n\ntype DefineEntFromTables<\n T extends { [key: string]: TableDefinition<any, any, any, any> },\n> = {\n [K in keyof T]: T[K] extends TableDefinition<\n infer D,\n infer I,\n infer S,\n infer V\n >\n ? EntDefinition<D, I, S, V>\n : never;\n};\n\nexport function defineEntsFromTables<\n T extends { [key: string]: TableDefinition<any, any, any, any> },\n>(definitions: T): DefineEntFromTables<T> {\n const result: any = {};\n for (const key in definitions) {\n result[key] = defineEntFromTable(definitions[key]);\n }\n return result;\n}\n\ntype GenericEdges = Record<string, GenericEdgeConfig>;\n\nexport type GenericEdgeConfig = {\n name: string;\n to: string;\n cardinality: \"single\" | \"multiple\";\n type: \"field\" | \"ref\";\n optional?: boolean;\n};\n\ntype ExtractFieldPaths<T extends Validator<any, any, any>> =\n // Add in the system fields available in index definitions.\n // This should be everything except for `_id` because thats added to indexes\n // automatically.\n T[\"fieldPaths\"] | keyof SystemFields;\n\ntype ObjectFieldType<\n FieldName extends string,\n T extends Validator<any, any, any>,\n> = T[\"isOptional\"] extends \"optional\"\n ? { [key in FieldName]?: T[\"type\"] }\n : { [key in FieldName]: T[\"type\"] };\n\ntype AddField<\n V extends GenericValidator,\n FieldName extends string,\n P extends GenericValidator,\n> =\n // Note: We can't use the `AddField` type to add fields to a union type, but ents\n // do not support schemas with top level unions\n V extends VObject<\n infer TypeScriptType,\n infer Fields,\n infer IsOptional,\n infer FieldPaths\n >\n ? VObject<\n Expand<TypeScriptType & ObjectFieldType<FieldName, P>>,\n Expand<Fields & { FieldName: P }>,\n IsOptional,\n FieldPaths | FieldName\n >\n : V extends VUnion<\n infer TypeScriptType,\n infer Members,\n infer IsOptional,\n infer FieldPaths\n >\n ? VUnion<\n Expand<TypeScriptType & ObjectFieldType<FieldName, P>>,\n { [key in keyof Members]: AddField<Members[key], FieldName, P> },\n IsOptional,\n FieldPaths | FieldName\n >\n : V extends VAny\n ? VAny\n : never;\n\nexport interface EntDefinition<\n DocumentType extends Validator<any, any, any> = Validator<any, any, any>,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n Indexes extends GenericTableIndexes = {},\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n SearchIndexes extends GenericTableSearchIndexes = {},\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n VectorIndexes extends GenericTableVectorIndexes = {},\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n Edges extends GenericEdges = {},\n> extends TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes> {\n /**\n * Define an index on this table.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param indexConfig - The index configuration object.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n indexConfig: Expand<\n DbIndexConfig<FirstFieldPath, RestFieldPaths> &\n IndexOptions & { staged?: false }\n >,\n ): TableDefinition<\n DocumentType,\n Expand<\n Indexes &\n Record<\n IndexName,\n [FirstFieldPath, ...RestFieldPaths, IndexTiebreakerField]\n >\n >,\n SearchIndexes,\n VectorIndexes\n >;\n\n /**\n * Define an index on this table.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param fields - The fields to index, in order. Must specify at least one\n * field.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n fields: [FirstFieldPath, ...RestFieldPaths],\n ): EntDefinition<\n DocumentType,\n Expand<\n Indexes &\n Record<IndexName, [FirstFieldPath, ...RestFieldPaths, \"_creationTime\"]>\n >,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n\n /**\n * Define a staged index on this table.\n *\n * For large tables, index backfill can be slow. Staging an index allows you\n * to push the schema and enable the index later.\n *\n * If `staged` is `true`, the index will be staged and will not be enabled\n * until the staged flag is removed. Staged indexes do not block push\n * completion. Staged indexes cannot be used in queries.\n *\n * To learn about indexes, see [Defining Indexes](https://docs.convex.dev/using/indexes).\n *\n * @param name - The name of the index.\n * @param indexConfig - The index configuration object.\n * @returns A {@link TableDefinition} with this index included.\n */\n index<\n IndexName extends string,\n FirstFieldPath extends ExtractFieldPaths<DocumentType>,\n RestFieldPaths extends ExtractFieldPaths<DocumentType>[],\n >(\n name: IndexName,\n indexConfig: Expand<\n DbIndexConfig<FirstFieldPath, RestFieldPaths> &\n IndexOptions & { staged: true }\n >,\n ): TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes>;\n\n /**\n * Define a search index on this table.\n *\n * To learn about search indexes, see [Search](https://docs.convex.dev/text-search).\n *\n * @param name - The name of the index.\n * @param indexConfig - The search index configuration object.\n * @returns A {@link TableDefinition} with this search index included.\n */\n searchIndex<\n IndexName extends string,\n SearchField extends ExtractFieldPaths<DocumentType>,\n FilterFields extends ExtractFieldPaths<DocumentType> = never,\n >(\n name: IndexName,\n indexConfig: Expand<SearchIndexConfig<SearchField, FilterFields>>,\n ): EntDefinition<\n DocumentType,\n Indexes,\n Expand<\n SearchIndexes &\n Record<\n IndexName,\n {\n searchField: SearchField;\n filterFields: FilterFields;\n }\n >\n >,\n VectorIndexes,\n Edges\n >;\n\n // /**\n // * Define a vector index on this table.\n // *\n // * To learn about vector indexes, see [Vector Search](https://docs.convex.dev/vector-search).\n // *\n // * @param name - The name of the index.\n // * @param indexConfig - The vector index configuration object.\n // * @returns A {@link TableDefinition} with this vector index included.\n // */\n vectorIndex<\n IndexName extends string,\n VectorField extends ExtractFieldPaths<DocumentType>,\n FilterFields extends ExtractFieldPaths<DocumentType> = never,\n >(\n name: IndexName,\n indexConfig: Expand<VectorIndexConfig<VectorField, FilterFields>>,\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n Expand<\n VectorIndexes &\n Record<\n IndexName,\n {\n vectorField: VectorField;\n dimensions: number;\n filterFields: FilterFields;\n }\n >\n >,\n Edges\n >;\n\n field<FieldName extends string, T extends GenericValidator>(\n field: FieldName,\n validator: T,\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, any, any>>(\n field: FieldName,\n validator: T,\n options: { index: true },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes & { [key in FieldName]: [FieldName, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, any, any>>(\n field: FieldName,\n validator: T,\n options: { unique: true },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes & { [key in FieldName]: [FieldName, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n field<FieldName extends string, T extends Validator<any, \"required\", any>>(\n field: FieldName,\n validator: T,\n options: { default: T[\"type\"] },\n ): EntDefinition<\n AddField<DocumentType, FieldName, T>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n\n edge<EdgeName extends string>(\n edge: EdgeName,\n options?: { deletion: \"hard\" | \"soft\" },\n ): EntDefinition<\n AddField<DocumentType, `${EdgeName}Id`, VId<GenericId<`${EdgeName}s`>>>,\n Indexes & { [key in `${EdgeName}Id`]: [`${EdgeName}Id`, \"_creationTime\"] },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: { field: FieldName; deletion?: \"hard\" | \"soft\" },\n ): EntDefinition<\n AddField<DocumentType, NoInfer<FieldName>, VId<GenericId<`${EdgeName}s`>>>,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: {\n field: FieldName;\n optional: true;\n deletion?: \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<\n DocumentType,\n NoInfer<FieldName>,\n VOptional<VId<GenericId<`${EdgeName}s`>>>\n >,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"field\";\n cardinality: \"single\";\n optional: true;\n };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: {\n field: FieldName;\n to: ToTable;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<DocumentType, NoInfer<FieldName>, VId<GenericId<`${ToTable}`>>>,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<EdgeName extends string, const ToTable extends string>(\n edge: EdgeName,\n options: {\n to: ToTable;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<DocumentType, `${EdgeName}Id`, VId<GenericId<`${ToTable}`>>>,\n Indexes & {\n [key in `${EdgeName}Id`]: [`${EdgeName}Id`, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: false;\n };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: {\n field: FieldName;\n to: ToTable;\n optional: true;\n deletion?: ToTable extends \"_storage\" | \"_scheduled_functions\"\n ? \"hard\"\n : \"hard\" | \"soft\";\n },\n ): EntDefinition<\n AddField<\n DocumentType,\n NoInfer<FieldName>,\n VOptional<VId<GenericId<ToTable>>>\n >,\n Indexes & {\n [key in NoInfer<FieldName>]: [NoInfer<FieldName>, \"_creationTime\"];\n },\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: ToTable;\n type: \"field\";\n cardinality: \"single\";\n optional: true;\n };\n }\n >;\n edge<EdgeName extends string>(\n edge: EdgeName,\n options: {\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: `${EdgeName}s`;\n type: \"ref\";\n cardinality: \"single\";\n };\n }\n >;\n edge<EdgeName extends string, const ToTable extends string>(\n edge: EdgeName,\n options: {\n to: ToTable;\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgeName]: {\n name: EdgeName;\n to: NoInfer<ToTable>;\n type: \"ref\";\n cardinality: \"single\";\n };\n }\n >;\n\n /**\n * Define many:1 edge to another table.\n * @param edge The name of the edge, also the name of the target table.\n * @param options.ref The name of the field that stores the many:1 edge\n * on the other table, or `true` to infer it.\n */\n edges<EdgesName extends string>(\n edge: EdgesName,\n options: {\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: EdgesName;\n type: \"field\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define many:1 edge to another table.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * If it's the same as the table this edge is defined on, this edge is\n * a symmetric, self-directed many:many edge.\n * @param options.ref The name of the field that stores the many:1 edge\n * on the other table, or `true` to infer it.\n */\n edges<EdgesName extends string, TableName extends string>(\n edge: EdgesName,\n options: {\n to: TableName;\n ref: true | string;\n deletion?: \"soft\";\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"field\";\n cardinality: \"multiple\";\n };\n }\n >;\n\n /**\n * Define many:many edge to another table.\n * @param edge The name of the edge, also the name of the target table.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * this end of the many:many edge.\n */\n edges<EdgesName extends string>(\n edge: EdgesName,\n options?: {\n table?: string;\n field?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: EdgesName;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define many:many edge to another table.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * If it's the same as the table this edge is defined on, this edge is\n * a symmetric, self-directed many:many edge.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * of the source end of the forward many:many edge.\n * @param options.inverseField Optional, name of the field to store the ID\n * of the target end of the forward edge. Only allowed for symmetric,\n * self-directed many:many edges.\n */\n edges<EdgesName extends string, TableName extends string>(\n edge: EdgesName,\n options: {\n to: TableName;\n table?: string;\n field?: string;\n inverseField?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n /**\n * Define self-directed, assymetric, many:many edge.\n * @param edge The name of the edge.\n * @param options.to Name of the table the edge points to.\n * Must be the same as the table this edge is defined on.\n * @param options.inverse Name of the inverse edge.\n * @param options.table Optional, name of the table to store the many:many edge in.\n * @param options.field Optional, name of the field to store the ID of the\n * of the source end of the forward many:many edge.\n * @param options.inverseField Optional, name of the field to store the ID\n * of the target end of the forward many:many edge.\n */\n edges<\n EdgesName extends string,\n TableName extends string,\n InverseEdgesNames extends string,\n >(\n edge: EdgesName,\n options: {\n to: TableName;\n inverse: InverseEdgesNames;\n table?: string;\n field?: string;\n inverseField?: string;\n },\n ): EntDefinition<\n DocumentType,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges & {\n [key in EdgesName]: {\n name: EdgesName;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n } & {\n [key in NoInfer<InverseEdgesNames>]: {\n name: NoInfer<InverseEdgesNames>;\n to: NoInfer<TableName>;\n type: \"ref\";\n cardinality: \"multiple\";\n };\n }\n >;\n\n /**\n * Add the \"soft\" deletion behavior to this ent.\n *\n * When the ent is \"soft\" deleted, its `deletionTime` field is set to the\n * current time and it is not actually deleted.\n *\n * @param type `\"soft\"`\n */\n deletion(\n type: \"soft\",\n ): EntDefinition<\n AddField<DocumentType, \"deletionTime\", VOptional<VFloat64>>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n /**\n * Add the \"scheduled\" deletion behavior to this ent.\n *\n * The ent is first \"soft\" deleted and its hard deletion is scheduled\n * to run in a separate mutation.\n *\n * @param type `\"scheduled\"`\n * @param options.delayMs If the `delayMs` option is specified,\n * the hard deletion is scheduled to happen after the specified\n * time duration.\n */\n deletion(\n type: \"scheduled\",\n options?: {\n delayMs: number;\n },\n ): EntDefinition<\n AddField<DocumentType, \"deletionTime\", VOptional<VFloat64>>,\n Indexes,\n SearchIndexes,\n VectorIndexes,\n Edges\n >;\n}\n\ntype NoInfer<T> = [T][T extends any ? 0 : never];\n\ntype FieldOptions = {\n index?: true;\n unique?: true;\n default?: any;\n};\n\ntype EdgeOptions = {\n optional?: true;\n field?: string;\n ref?: true | string;\n to?: string;\n deletion?: \"soft\" | \"hard\";\n};\n\ntype EdgesOptions = {\n to?: string;\n inverse?: string;\n ref?: string;\n table?: string;\n field?: string;\n inverseField?: string;\n deletion: \"soft\";\n};\n\nclass EntDefinitionImpl {\n validator: Validator<Record<string, any>, \"required\", any>;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private indexes: Index[] = [];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private searchIndexes: SearchIndex[] = [];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n private vectorIndexes: VectorIndex[] = [];\n\n private edgeConfigs: Record<string, EdgeConfigBeforeDefineSchema> = {};\n\n private fieldConfigs: Record<string, FieldConfig> = {};\n\n private defaults: Record<string, any> = {};\n\n private deletionConfig: DeletionConfig | undefined;\n\n constructor(documentSchema: Validator<Record<string, any>, \"required\", any>) {\n this.validator = documentSchema;\n }\n\n index(name: any, fields: any) {\n this.indexes.push({ indexDescriptor: name, fields });\n return this;\n }\n\n searchIndex(name: any, indexConfig: any) {\n this.searchIndexes.push({\n indexDescriptor: name,\n searchField: indexConfig.searchField,\n filterFields: indexConfig.filterFields || [],\n });\n return this;\n }\n\n vectorIndex(name: any, indexConfig: any) {\n this.vectorIndexes.push({\n indexDescriptor: name,\n vectorField: indexConfig.vectorField,\n dimensions: indexConfig.dimensions,\n filterFields: indexConfig.filterFields || [],\n });\n return this;\n }\n\n /**\n * Export the contents of this definition.\n *\n * This is called internally by the Convex framework.\n * @internal\n */\n export() {\n return {\n indexes: this.indexes,\n searchIndexes: this.searchIndexes,\n vectorIndexes: this.vectorIndexes,\n documentType: (this.validator as any).json,\n };\n }\n\n field(name: string, validator: any, options?: FieldOptions): this {\n if (this._has(name)) {\n // TODO: Store the fieldConfigs in an array so that we can\n // do the uniqueness check in defineEntSchema where we\n // know the table name.\n throw new Error(`Duplicate field \"${name}\"`);\n }\n const finalValidator =\n options?.default !== undefined ? v.optional(validator) : validator;\n this._expand(name, finalValidator);\n if (options?.unique === true || options?.index === true) {\n this.indexes.push({ indexDescriptor: name, fields: [name] });\n }\n if (options?.default !== undefined) {\n this.defaults[name] = options.default;\n }\n if (options?.unique === true) {\n this.fieldConfigs[name] = { name, unique: true };\n }\n return this;\n }\n\n edge(edgeName: string, options?: EdgeOptions): this {\n if (this.edgeConfigs[edgeName] !== undefined) {\n // TODO: Store the edgeConfigs in an array so that we can\n // do the uniqueness check in defineEntSchema where we\n // know the source table name.\n throw new Error(`Duplicate edge \"${edgeName}\"`);\n }\n const to = options?.to ?? edgeName + \"s\";\n if (options?.field !== undefined && options?.ref !== undefined) {\n throw new Error(\n `Cannot specify both \\`field\\` and \\`ref\\` for the same edge, ` +\n `choose one to be the reference and the other to store ` +\n `the foreign key.`,\n );\n }\n if (options?.field !== undefined || options?.ref === undefined) {\n const fieldName = options?.field ?? edgeName + \"Id\";\n this._expand(\n fieldName,\n options?.optional === true ? v.optional(v.id(to)) : v.id(to),\n );\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"field\",\n field: fieldName,\n optional: options?.optional === true,\n deletion: options?.deletion,\n };\n this.indexes.push({\n indexDescriptor: fieldName,\n fields: [fieldName],\n });\n return this;\n }\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"ref\",\n ref: options.ref === true ? null : options.ref,\n deletion: options.deletion as \"soft\" | undefined,\n };\n return this;\n }\n\n edges(name: string, options?: EdgesOptions): this {\n const cardinality = \"multiple\";\n const to = options?.to ?? name;\n const ref = options?.ref;\n const table = options?.table;\n // TODO: Do this later when we have the table name,\n // or rework schema to use a builder pattern.\n if (ref !== undefined && table !== undefined) {\n throw new Error(\n `Cannot specify both \\`ref\\` and \\`table\\` for the same edge, ` +\n `as the former is for 1:many edges and the latter ` +\n `for many:many edges. Config: \\`${JSON.stringify(options)}\\``,\n );\n }\n const field = options?.field;\n const inverseField = options?.inverseField;\n // TODO: Do this later when we have the table name,\n // or rework schema to use a builder pattern.\n if (\n (field !== undefined || inverseField !== undefined) &&\n table === undefined\n ) {\n throw new Error(\n `Specify \\`table\\` if you're customizing the \\`field\\` or ` +\n `\\`inverseField\\` for a many:many edge. ` +\n `Config: \\`${JSON.stringify(options)}\\``,\n );\n }\n const inverseName = options?.inverse;\n const deletion = options?.deletion;\n this.edgeConfigs[name] =\n ref !== undefined\n ? { name, to, cardinality, type: \"field\", ref, deletion }\n : { name, to, cardinality, type: \"ref\", table, field, inverseField };\n if (inverseName !== undefined) {\n this.edgeConfigs[inverseName] = {\n name: inverseName,\n to,\n cardinality,\n type: \"ref\",\n inverse: name,\n table,\n };\n }\n return this;\n }\n\n deletion(type: \"soft\" | \"scheduled\", options?: { delayMs: number }): this {\n if (this._has(\"deletionTime\")) {\n // TODO: Put the check where we know the table name.\n throw new Error(\n `Cannot enable \"${type}\" deletion because \"deletionTime\" field ` +\n `was already defined.`,\n );\n }\n if (this.deletionConfig !== undefined) {\n // TODO: Put the check where we know the table name.\n throw new Error(`Deletion behavior can only be specified once.`);\n }\n this._expand(\"deletionTime\", v.optional(v.number()));\n this.deletionConfig = { type, ...options };\n return this;\n }\n\n private _has(name: string): boolean {\n if (this.validator.kind === \"object\") {\n return this.validator.fields[name] !== undefined;\n }\n if (this.validator.kind === \"union\") {\n return this.validator.members.some(\n (member) =>\n member.kind === \"object\" && member.fields[name] !== undefined,\n );\n }\n return false;\n }\n\n private _expand(name: string, validator: GenericValidator) {\n if (this.validator.kind === \"object\") {\n this.validator.fields[name] = validator;\n }\n if (this.validator.kind === \"union\") {\n this.validator.members.forEach((member) => {\n if (member.kind === \"object\") {\n member.fields[name] = validator;\n }\n });\n }\n }\n}\n\nexport type EdgeConfig = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\n unique: boolean;\n optional: boolean;\n deletion?: \"soft\" | \"hard\";\n }\n | {\n type: \"ref\";\n ref: string;\n deletion?: \"soft\";\n }\n ))\n | ({\n cardinality: \"multiple\";\n } & (\n | {\n type: \"field\";\n ref: string;\n deletion?: \"soft\";\n }\n | {\n type: \"ref\";\n table: string;\n field: string;\n ref: string;\n inverse: boolean;\n symmetric: boolean;\n }\n ))\n);\n\ntype EdgeConfigSingleField = Extract<\n EdgeConfig,\n {\n type: \"field\";\n cardinality: \"single\";\n }\n>;\ntype EdgeConfigSingleRef = Extract<\n EdgeConfig,\n {\n type: \"ref\";\n cardinality: \"single\";\n }\n>;\ntype EdgeConfigMultipleField = Extract<\n EdgeConfig,\n {\n type: \"field\";\n cardinality: \"multiple\";\n }\n>;\ntype EdgeConfigMultipleRef = Extract<\n EdgeConfig,\n {\n type: \"ref\";\n cardinality: \"multiple\";\n }\n>;\n\ntype EdgeConfigBeforeDefineSchema = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\n optional: boolean;\n deletion?: \"soft\" | \"hard\";\n }\n | {\n type: \"ref\";\n ref: null | string;\n deletion?: \"soft\";\n }\n ))\n | ({\n cardinality: \"multiple\";\n } & (\n | {\n type: \"field\";\n ref: true | string;\n deletion?: \"soft\";\n }\n | {\n type: \"ref\";\n table?: string;\n field?: string;\n inverseField?: string;\n inverse?: string;\n }\n ))\n);\n\nexport type FieldConfig = {\n name: string;\n unique: boolean;\n};\n\nexport type Expand<ObjectType extends Record<any, any>> =\n ObjectType extends Record<any, any>\n ? {\n [Key in keyof ObjectType]: ObjectType[Key];\n }\n : never;\nexport type SystemFields = {\n _creationTime: number;\n};\n\ninterface IndexOptions {\n /**\n * Whether the index should be staged.\n *\n * For large tables, index backfill can be slow. Staging an index allows you\n * to push the schema and enable the index later.\n *\n * If `staged` is `true`, the index will be staged and will not be enabled\n * until the staged flag is removed. Staged indexes do not block push\n * completion. Staged indexes cannot be used in queries.\n */\n staged?: boolean;\n}\n\ninterface DbIndexConfig<\n FirstFieldPath extends string,\n RestFieldPaths extends string[],\n> {\n /**\n * The fields to index, in order. Must specify at least one field.\n */\n fields: [FirstFieldPath, ...RestFieldPaths];\n}\n\nexport type GenericEntsDataModel = GenericDataModel &\n Record<string, GenericEntModel>;\n\nexport type GenericEntModel = {\n edges: Record<string, GenericEdgeConfig>;\n};\n\nexport type DeletionConfig =\n | {\n type: \"soft\";\n }\n | {\n type: \"scheduled\";\n delayMs?: number;\n };\n\nexport type EntDataModelFromSchema<\n SchemaDef extends SchemaDefinition<any, boolean>,\n> = DataModelFromSchemaDefinition<SchemaDef> & {\n [TableName in keyof SchemaDef[\"tables\"] &\n string]: SchemaDef[\"tables\"][TableName] extends EntDefinition<\n any,\n any,\n any,\n any,\n infer Edges\n >\n ? {\n edges: Edges;\n }\n : never;\n};\n\nexport function getEntDefinitions<\n SchemaDef extends SchemaDefinition<any, boolean>,\n>(schema: SchemaDef): EntDataModelFromSchema<typeof schema> {\n const tables = schema.tables;\n return Object.entries(tables).reduce(\n (acc, [tableName, table]: [any, any]) => {\n acc[tableName] = {\n indexes: (\n table.indexes as {\n indexDescriptor: string;\n fields: string[];\n }[]\n ).reduce(\n (acc, { indexDescriptor, fields }) => {\n acc[indexDescriptor] = fields;\n return acc;\n },\n {} as Record<string, string[]>,\n ),\n defaults: table.defaults,\n edges: table.edgeConfigs,\n fields: table.fieldConfigs,\n deletionConfig: table.deletionConfig,\n };\n return acc;\n },\n {} as Record<string, any>,\n ) as any;\n}\n","import {\n DocumentByName,\n FieldTypeFromFieldPath,\n SystemDataModel,\n TableNamesInDataModel,\n} from \"convex/server\";\nimport { EdgeConfig, GenericEdgeConfig, GenericEntsDataModel } from \"./schema\";\n\nexport type EntsSystemDataModel = {\n [key in keyof SystemDataModel]: SystemDataModel[key] & {\n edges: Record<string, never>;\n };\n};\n\nexport type PromiseEdgeResult<\n EdgeConfig extends GenericEdgeConfig,\n MultipleRef,\n MultipleField,\n SingleOptional,\n Single,\n> = EdgeConfig[\"cardinality\"] extends \"multiple\"\n ? EdgeConfig[\"type\"] extends \"ref\"\n ? MultipleRef\n : MultipleField\n : EdgeConfig[\"type\"] extends \"ref\"\n ? SingleOptional\n : EdgeConfig[\"optional\"] extends true\n ? SingleOptional\n : Single;\n\nexport type IndexFieldTypesForEq<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n T extends string[],\n> = Pop<{\n [K in keyof T]: FieldTypeFromFieldPath<\n DocumentByName<EntsDataModel, Table>,\n T[K]\n >;\n}>;\n\ntype Pop<T extends any[]> = T extends [...infer Rest, infer _Last]\n ? Rest\n : never;\n\nexport function getEdgeDefinitions<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n>(entDefinitions: EntsDataModel, table: Table) {\n return entDefinitions[table].edges as Record<\n keyof EntsDataModel[Table][\"edges\"],\n EdgeConfig\n >;\n}\n","import {\n DocumentByName,\n GenericDocument,\n TableNamesInDataModel,\n makeFunctionReference,\n} from \"convex/server\";\nimport { GenericId } from \"convex/values\";\nimport {\n EntMutationCtx,\n entWrapper,\n getDeletionConfig,\n getReadRule,\n getWriteRule,\n} from \"./functions\";\nimport {\n FieldConfig,\n GenericEdgeConfig,\n GenericEntsDataModel,\n edgeCompoundIndexName,\n} from \"./schema\";\nimport { ScheduledDeleteFuncRef } from \"./deletion\";\nimport { getEdgeDefinitions } from \"./shared\";\n\nexport class WriterImplBase<\n EntsDataModel extends GenericEntsDataModel,\n Table extends TableNamesInDataModel<EntsDataModel>,\n> {\n constructor(\n protected ctx: EntMutationCtx<EntsDataModel>,\n protected entDefinitions: EntsDataModel,\n protected table: Table,\n ) {}\n\n async deleteId(id: GenericId<any>, behavior: \"default\" | \"soft\" | \"hard\") {\n await this.checkReadAndWriteRule(\"delete\", id, undefined);\n\n const deletionConfig = getDeletionConfig(this.entDefinitions, this.table);\n\n const isDeletingSoftly =\n behavior !== \"hard\" &&\n deletionConfig !== undefined &&\n (deletionConfig.type === \"soft\" || deletionConfig.type === \"scheduled\");\n\n if (behavior === \"soft\" && !isDeletingSoftly) {\n throw new Error(\n `Cannot soft delete document with ID \"${id}\" in ` +\n `table \"${this.table}\" because it does not have ` +\n `a \"soft\" or \"scheduled\" deletion behavior configured.`,\n );\n }\n const edges: EdgeChanges = {};\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n const key = edgeDefinition.name;\n if (\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"ref\") ||\n (edgeDefinition.cardinality === \"multiple\" &&\n edgeDefinition.type === \"field\")\n ) {\n if (!isDeletingSoftly || edgeDefinition.deletion === \"soft\") {\n const remove = (\n await this.ctx.db\n .query(edgeDefinition.to)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .collect()\n ).map((doc) => doc._id as GenericId<any>);\n edges[key] = { remove };\n }\n } else if (edgeDefinition.cardinality === \"single\") {\n if (\n edgeDefinition.deletion !== undefined &&\n (!isDeletingSoftly || edgeDefinition.deletion === \"soft\")\n ) {\n const doc = await this.ctx.db.get(id);\n if (doc !== null) {\n const otherId = doc[edgeDefinition.field] as\n | GenericId<any>\n | undefined;\n edges[key] = {\n remove: otherId !== undefined ? [otherId] : [],\n };\n }\n }\n } else if (edgeDefinition.cardinality === \"multiple\") {\n if (!isDeletingSoftly) {\n const removeEdges = (\n await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.field, (q) =>\n q.eq(edgeDefinition.field, id as any),\n )\n .collect()\n )\n .concat(\n edgeDefinition.symmetric\n ? await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeDefinition.ref, (q) =>\n q.eq(edgeDefinition.ref, id as any),\n )\n .collect()\n : [],\n )\n .map((doc) => doc._id as GenericId<any>);\n edges[key] = { removeEdges };\n }\n }\n },\n ),\n );\n const deletionTime = +new Date();\n if (isDeletingSoftly) {\n await this.ctx.db.patch(this.table, id, { deletionTime });\n } else {\n try {\n await this.ctx.db.delete(this.table, id);\n } catch {\n // TODO:\n // For now we're gonna ignore errors here,\n // because we assume that the only error\n // is \"document not found\", which\n // can be caused by concurrent deletions.\n // In the future we could track which\n // edges are being deleted by this mutation,\n // and skip the call to delete altogether\n // - or Convex could implement this.\n }\n }\n await this.writeEdges(id, edges, isDeletingSoftly);\n if (deletionConfig !== undefined && deletionConfig.type === \"scheduled\") {\n const fnRef = ((this.ctx as any).scheduledDelete ??\n makeFunctionReference(\n \"functions:scheduledDelete\",\n )) as ScheduledDeleteFuncRef;\n await this.ctx.scheduler.runAfter(deletionConfig.delayMs ?? 0, fnRef, {\n origin: {\n id,\n table: this.table,\n deletionTime,\n },\n inProgress: false,\n stack: [],\n });\n }\n return id;\n }\n\n async deleteIdIn(id: GenericId<any>, table: string, cascadingSoft: boolean) {\n await new WriterImplBase(this.ctx, this.entDefinitions, table).deleteId(\n id,\n cascadingSoft ? \"soft\" : \"hard\",\n );\n }\n\n async deleteSystem(table: string, id: GenericId<any>) {\n switch (table) {\n case \"_storage\":\n await this.ctx.storage.delete(id);\n break;\n case \"_scheduled_functions\":\n await this.ctx.scheduler.cancel(id);\n break;\n default:\n throw new Error(\n `Cannot cascade deletion to unsupported system table \"${table}\".`,\n );\n }\n }\n\n async writeEdges(\n docId: GenericId<any>,\n changes: EdgeChanges,\n deleteSoftly?: boolean,\n ) {\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n const idOrIds = changes[edgeDefinition.name];\n if (idOrIds === undefined) {\n return;\n }\n if (\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"ref\") ||\n (edgeDefinition.cardinality === \"multiple\" &&\n edgeDefinition.type === \"field\")\n ) {\n if (idOrIds.remove !== undefined && idOrIds.remove.length > 0) {\n // Cascading delete because 1:many edges are not optional\n // on the stored field end.\n await Promise.all(\n idOrIds.remove.map((id) =>\n this.deleteIdIn(\n id,\n edgeDefinition.to,\n (deleteSoftly ?? false) &&\n edgeDefinition.deletion === \"soft\",\n ),\n ),\n );\n // This would be behavior for optional edge:\n // await Promise.all(\n // idsToDelete.map((id) =>\n // this.ctx.db.patch(id, {\n // [edgeDefinition.ref]: undefined,\n // } as any)\n // )\n // );\n }\n if (idOrIds.add !== undefined && idOrIds.add.length > 0) {\n await Promise.all(\n idOrIds.add.map(async (id) =>\n this.ctx.db.patch(edgeDefinition.to, id, {\n [edgeDefinition.ref]: docId,\n } as any),\n ),\n );\n }\n } else if (edgeDefinition.cardinality === \"single\") {\n if (idOrIds.remove !== undefined && idOrIds.remove.length > 0) {\n await Promise.all(\n idOrIds.remove.map(\n isSystemTable(edgeDefinition.to)\n ? (id) => this.deleteSystem(edgeDefinition.to, id)\n : (id) =>\n this.deleteIdIn(\n id,\n edgeDefinition.to,\n (deleteSoftly ?? false) &&\n edgeDefinition.deletion === \"soft\",\n ),\n ),\n );\n }\n } else if (edgeDefinition.cardinality === \"multiple\") {\n if ((idOrIds.removeEdges ?? []).length > 0) {\n await Promise.all(\n idOrIds.removeEdges!.map(async (id) => {\n try {\n await this.ctx.db.delete(edgeDefinition.table, id);\n } catch {\n // TODO:\n // For now we're gonna ignore errors here,\n // because we assume that the only error\n // is \"document not found\", which\n // can be caused by concurrent deletions.\n // In the future we could track which\n // edges are being deleted by this mutation,\n // and skip the call to delete altogether\n // - or Convex could implement this.\n }\n }),\n );\n }\n\n if (idOrIds.add !== undefined) {\n await Promise.all(\n [...new Set(idOrIds.add)].map(async (id) => {\n const existing = await this.ctx.db\n .query(edgeDefinition.table)\n .withIndex(edgeCompoundIndexName(edgeDefinition), (q) =>\n (q.eq(edgeDefinition.field, docId as any) as any).eq(\n edgeDefinition.ref,\n id,\n ),\n )\n .first();\n if (existing === null) {\n await this.ctx.db.insert(edgeDefinition.table, {\n [edgeDefinition.field]: docId,\n [edgeDefinition.ref]: id,\n } as any);\n if (edgeDefinition.symmetric) {\n await this.ctx.db.insert(edgeDefinition.table, {\n [edgeDefinition.field]: id,\n [edgeDefinition.ref]: docId,\n } as any);\n }\n }\n }),\n );\n }\n }\n },\n ),\n );\n }\n\n async checkUniqueness(value: Partial<GenericDocument>, id?: GenericId<any>) {\n await Promise.all(\n Object.values(\n (this.entDefinitions[this.table] as any).fields as Record<\n string,\n FieldConfig\n >,\n ).map(async (fieldDefinition) => {\n if (fieldDefinition.unique) {\n const key = fieldDefinition.name;\n const fieldValue = value[key];\n const existing = await this.ctx.db\n .query(this.table)\n .withIndex(key, (q) => q.eq(key, value[key] as any))\n .unique();\n if (existing !== null && (id === undefined || existing._id !== id)) {\n throw new Error(\n `In table \"${\n this.table\n }\" cannot create a duplicate document with field \"${key}\" of value \\`${\n fieldValue as string\n }\\`, existing document with ID \"${\n existing._id as string\n }\" already has it.`,\n );\n }\n }\n }),\n );\n await Promise.all(\n Object.values(getEdgeDefinitions(this.entDefinitions, this.table)).map(\n async (edgeDefinition) => {\n if (\n edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\" &&\n edgeDefinition.unique\n ) {\n const key = edgeDefinition.field;\n if (value[key] === undefined) {\n return;\n }\n // Enforce uniqueness\n const existing = await this.ctx.db\n .query(this.table)\n .withIndex(key, (q) => q.eq(key, value[key] as any))\n .unique();\n if (\n existing !== null &&\n (id === undefined || existing._id !== id)\n ) {\n throw new Error(\n `In table \"${this.table}\" cannot create a duplicate 1:1 edge \"${\n edgeDefinition.name\n }\" to ID \"${\n value[key] as string\n }\", existing document with ID \"${\n existing._id as string\n }\" already has it.`,\n );\n }\n }\n },\n ),\n );\n }\n\n fieldsOnly(\n value: Partial<\n WithEdgePatches<\n DocumentByName<EntsDataModel, Table>,\n EntsDataModel[Table][\"edges\"]\n >\n >,\n ) {\n const fields: GenericDocument = {};\n Object.keys(value).forEach((key) => {\n const edgeDefinition = getEdgeDefinitions(\n this.entDefinitions,\n this.table,\n )[key];\n if (\n edgeDefinition === undefined ||\n (edgeDefinition.cardinality === \"single\" &&\n edgeDefinition.type === \"field\" &&\n edgeDefinition.field === key)\n ) {\n fields[key] = value[key]!;\n }\n });\n return fields;\n }\n\n async checkReadAndWriteRule(\n operation: \"create\" | \"update\" | \"delete\",\n id: GenericId<Table> | undefined,\n value: Partial<GenericDocument> | undefined,\n ) {\n if (id !== undefined) {\n const readPolicy = getReadRule(this.entDefinitions, this.table);\n if (readPolicy !== undefined) {\n const doc = await this.ctx.db.get(id);\n if (doc === null) {\n throw new Error(\n `Cannot update document with ID \"${id}\" in table \"${this.table} because it does not exist\"`,\n );\n }\n const decision = await readPolicy(doc);\n if (!decision) {\n throw new Error(\n `Cannot update document with ID \"${id}\" from table \"${this.table}\"`,\n );\n }\n }\n }\n const writePolicy = getWriteRule(this.entDefinitions, this.table);\n if (writePolicy === undefined) {\n return;\n }\n const ent =\n id === undefined\n ? undefined\n : entWrapper(\n (await this.ctx.db.get(id))!,\n this.ctx,\n this.entDefinitions,\n this.table,\n );\n // Replace allows _id and _creationTime, but rules should not\n // rely on them.\n const { _id, _creationTime, ...safeValue } = value ?? {};\n const decision = await writePolicy({\n operation,\n ent: ent as any,\n value: value !== undefined ? (safeValue as any) : undefined,\n });\n if (!decision) {\n if (id === undefined) {\n throw new Error(\n `Cannot insert into table \"${this.table}\": \\`${JSON.stringify(\n value,\n )}\\``,\n );\n } else if (value === undefined) {\n throw new Error(\n `Cannot delete from table \"${this.table}\" with ID \"${id}\"`,\n );\n } else {\n throw new Error(\n `Cannot update document with ID \"${id}\" in table \"${\n this.table\n }\" with: \\`${JSON.stringify(value)}\\``,\n );\n }\n }\n }\n}\n\nexport type WithEdgeInserts<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"single\"\n ? Edges[key][\"type\"] extends \"field\"\n ? never\n : key\n : key]?: Edges[key][\"cardinality\"] extends \"single\"\n ? GenericId<Edges[key][\"to\"]>\n : GenericId<Edges[key][\"to\"]>[];\n};\n\nexport type WithEdges<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"multiple\"\n ? Edges[key][\"type\"] extends \"ref\"\n ? key\n : never\n : never]?: GenericId<Edges[key][\"to\"]>[];\n};\n\nexport type WithEdgePatches<\n Document extends GenericDocument,\n Edges extends Record<string, GenericEdgeConfig>,\n> = Document & {\n [key in keyof Edges as Edges[key][\"cardinality\"] extends \"multiple\"\n ? Edges[key][\"type\"] extends \"ref\"\n ? key\n : never\n : never]?: {\n add?: GenericId<Edges[key][\"to\"]>[];\n remove?: GenericId<Edges[key][\"to\"]>[];\n };\n};\n\nexport type EdgeChanges = Record<\n string,\n {\n add?: GenericId<any>[];\n remove?: GenericId<any>[];\n removeEdges?: GenericId<any>[];\n }\n>;\n\nexport function isSystemTable(table: string) {\n return table.startsWith(\"_\");\n}\n"],"mappings":"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","names":["import_server","decision","q","table"]}