convex-ents 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deletion.js.map +1 -1
- package/dist/functions.js +1 -1
- package/dist/functions.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/schema.js +4 -4
- package/dist/schema.js.map +1 -1
- package/dist/writer.js +1 -1
- package/dist/writer.js.map +1 -1
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -129,12 +129,12 @@ function defineEntSchema(schema, options) {
|
|
|
129
129
|
const edgeTable = defineEnt({
|
|
130
130
|
[forwardId]: import_values.v.id(tableName),
|
|
131
131
|
[inverseId]: import_values.v.id(otherTableName)
|
|
132
|
-
}).index(forwardId, [forwardId]).index(inverseId, [inverseId]).index(`${forwardId}
|
|
132
|
+
}).index(forwardId, [forwardId]).index(inverseId, [inverseId]).index(`${forwardId}_${inverseId}`, [forwardId, inverseId]);
|
|
133
133
|
const isSymmetric = inverseEdge === void 0;
|
|
134
134
|
if (!isSymmetric) {
|
|
135
|
-
edgeTable.index(`${inverseId}
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
edgeTable.index(`${inverseId}_${forwardId}`, [
|
|
136
|
+
inverseId,
|
|
137
|
+
forwardId
|
|
138
138
|
]);
|
|
139
139
|
}
|
|
140
140
|
schema[edgeTableName] = edgeTable;
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import {\n DataModelFromSchemaDefinition,\n DefineSchemaOptions,\n GenericDataModel,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n SchemaDefinition,\n SearchIndexConfig,\n TableDefinition,\n VectorIndexConfig,\n defineSchema,\n} from \"convex/server\";\nimport {\n GenericId,\n GenericValidator,\n ObjectType,\n PropertyValidators,\n VAny,\n VFloat64,\n VId,\n VObject,\n VOptional,\n Validator,\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 any).symmetric !== undefined\n ) {\n continue;\n }\n\n const otherTableName = edge.to;\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 // TODO: If we want to support optional 1:1 edges in the future\n // throw new Error(\n // `Both edge \"${edge.name}\" on ent \"${inverseEdge.to}\" and ` +\n // `edge \"${inverseEdge.name}\" on ent \"${edge.to}\" are marked ` +\n // `as optional, specify which table should store the 1:1 edge by ` +\n // `providing a \\`field\\` name.`\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 optional, choose one to be required.`,\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 any).ref = inverseEdge.field;\n }\n // For now the the non-optional end is always unique\n (inverseEdge as any).unique = true;\n }\n if (\n (edge.cardinality === \"single\" && edge.type === \"ref\") ||\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 `cannot be optional, as 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 any).type = \"field\";\n (edge as any).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(`${forwardId}-${inverseId}`, [forwardId, inverseId]);\n const isSymmetric = inverseEdge === undefined;\n if (!isSymmetric) {\n edgeTable.index(`${inverseId}-${forwardId}`, [\n forwardId,\n inverseId,\n ]);\n }\n (schema as any)[edgeTableName] = edgeTable;\n (edge as any).type = \"ref\";\n (edge as any).table = edgeTableName;\n (edge as any).field = forwardId;\n (edge as any).ref = inverseId;\n (edge as any).symmetric = inverseEdge === undefined;\n if (inverseEdge !== undefined) {\n inverseEdge.type = \"ref\";\n (inverseEdge as any).table = edgeTableName;\n (inverseEdge as any).field = inverseId;\n (inverseEdge as any).ref = forwardId;\n (inverseEdge as any).symmetric = false;\n }\n }\n }\n }\n }\n return defineSchema(schema, options);\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<DocumentSchema extends PropertyValidators>(\n documentSchema: DocumentSchema,\n): EntDefinition<ObjectValidator<DocumentSchema>> {\n return new EntDefinitionImpl(documentSchema) as any;\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};\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 VAny\n ? VAny\n : never;\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 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 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 ): 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 };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: { field: FieldName },\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 };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: { field: FieldName; to: ToTable },\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 };\n }\n >;\n edge<EdgeName extends string>(\n edge: EdgeName,\n options: {\n optional: true;\n ref?: 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 optional: true;\n to: ToTable;\n ref?: 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?: string;\n to?: string;\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: GenericValidator;\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 documentSchema: Record<string, Validator<any, any, any>>;\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: Record<string, Validator<any, any, any>>) {\n this.documentSchema = documentSchema;\n this.validator = v.object(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: (v.object(this.documentSchema) as any).json,\n };\n }\n\n field(name: string, validator: any, options?: FieldOptions): this {\n if (this.documentSchema[name] !== undefined) {\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.documentSchema = { ...this.documentSchema, [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?.optional !== true) {\n const fieldName = options?.field ?? edgeName + \"Id\";\n this.documentSchema = { ...this.documentSchema, [fieldName]: v.id(to) };\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"field\",\n field: fieldName,\n };\n this.indexes.push({\n indexDescriptor: fieldName,\n fields: [fieldName],\n });\n return this;\n }\n if (options.optional === true) {\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"ref\",\n ref: options.ref ?? null,\n };\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.documentSchema.deletionTime !== undefined) {\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.documentSchema = {\n ...this.documentSchema,\n deletionTime: v.optional(v.number()),\n };\n this.deletionConfig = { type, ...options };\n return this;\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 }\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 EdgeConfigBeforeDefineSchema = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\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\ntype ObjectValidator<Validators extends PropertyValidators> = VObject<\n // Compute the TypeScript type this validator refers to.\n ObjectType<Validators>,\n Validators\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"],"mappings":"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","names":["edge","acc"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import {\n DataModelFromSchemaDefinition,\n DefineSchemaOptions,\n GenericDataModel,\n GenericTableIndexes,\n GenericTableSearchIndexes,\n GenericTableVectorIndexes,\n SchemaDefinition,\n SearchIndexConfig,\n TableDefinition,\n VectorIndexConfig,\n defineSchema,\n} from \"convex/server\";\nimport {\n GenericId,\n GenericValidator,\n ObjectType,\n PropertyValidators,\n VAny,\n VFloat64,\n VId,\n VObject,\n VOptional,\n Validator,\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 any).symmetric !== undefined\n ) {\n continue;\n }\n\n const otherTableName = edge.to;\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 // TODO: If we want to support optional 1:1 edges in the future\n // throw new Error(\n // `Both edge \"${edge.name}\" on ent \"${inverseEdge.to}\" and ` +\n // `edge \"${inverseEdge.name}\" on ent \"${edge.to}\" are marked ` +\n // `as optional, specify which table should store the 1:1 edge by ` +\n // `providing a \\`field\\` name.`\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 optional, choose one to be required.`,\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 any).ref = inverseEdge.field;\n }\n // For now the the non-optional end is always unique\n (inverseEdge as any).unique = true;\n }\n if (\n (edge.cardinality === \"single\" && edge.type === \"ref\") ||\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 `cannot be optional, as 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 any).type = \"field\";\n (edge as any).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(`${forwardId}_${inverseId}`, [forwardId, inverseId]);\n const isSymmetric = inverseEdge === undefined;\n if (!isSymmetric) {\n edgeTable.index(`${inverseId}_${forwardId}`, [\n inverseId,\n forwardId,\n ]);\n }\n (schema as any)[edgeTableName] = edgeTable;\n (edge as any).type = \"ref\";\n (edge as any).table = edgeTableName;\n (edge as any).field = forwardId;\n (edge as any).ref = inverseId;\n (edge as any).symmetric = inverseEdge === undefined;\n if (inverseEdge !== undefined) {\n inverseEdge.type = \"ref\";\n (inverseEdge as any).table = edgeTableName;\n (inverseEdge as any).field = inverseId;\n (inverseEdge as any).ref = forwardId;\n (inverseEdge as any).symmetric = false;\n }\n }\n }\n }\n }\n return defineSchema(schema, options);\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<DocumentSchema extends PropertyValidators>(\n documentSchema: DocumentSchema,\n): EntDefinition<ObjectValidator<DocumentSchema>> {\n return new EntDefinitionImpl(documentSchema) as any;\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};\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 VAny\n ? VAny\n : never;\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 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 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 ): 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 };\n }\n >;\n edge<EdgeName extends string, const FieldName extends string>(\n edge: EdgeName,\n options: { field: FieldName },\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 };\n }\n >;\n edge<\n EdgeName extends string,\n const FieldName extends string,\n const ToTable extends string,\n >(\n edge: EdgeName,\n options: { field: FieldName; to: ToTable },\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 };\n }\n >;\n edge<EdgeName extends string>(\n edge: EdgeName,\n options: {\n optional: true;\n ref?: 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 optional: true;\n to: ToTable;\n ref?: 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?: string;\n to?: string;\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: GenericValidator;\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 documentSchema: Record<string, Validator<any, any, any>>;\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: Record<string, Validator<any, any, any>>) {\n this.documentSchema = documentSchema;\n this.validator = v.object(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: (v.object(this.documentSchema) as any).json,\n };\n }\n\n field(name: string, validator: any, options?: FieldOptions): this {\n if (this.documentSchema[name] !== undefined) {\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.documentSchema = { ...this.documentSchema, [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?.optional !== true) {\n const fieldName = options?.field ?? edgeName + \"Id\";\n this.documentSchema = { ...this.documentSchema, [fieldName]: v.id(to) };\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"field\",\n field: fieldName,\n };\n this.indexes.push({\n indexDescriptor: fieldName,\n fields: [fieldName],\n });\n return this;\n }\n if (options.optional === true) {\n this.edgeConfigs[edgeName] = {\n name: edgeName,\n to,\n cardinality: \"single\",\n type: \"ref\",\n ref: options.ref ?? null,\n };\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.documentSchema.deletionTime !== undefined) {\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.documentSchema = {\n ...this.documentSchema,\n deletionTime: v.optional(v.number()),\n };\n this.deletionConfig = { type, ...options };\n return this;\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 }\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 EdgeConfigBeforeDefineSchema = {\n name: string;\n to: string;\n} & (\n | ({\n cardinality: \"single\";\n } & (\n | {\n type: \"field\";\n field: string;\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\ntype ObjectValidator<Validators extends PropertyValidators> = VObject<\n // Compute the TypeScript type this validator refers to.\n ObjectType<Validators>,\n Validators\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"],"mappings":"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","names":["edge","acc"]}
|
package/dist/writer.js
CHANGED
|
@@ -404,7 +404,7 @@ var PromiseEdgeOrNullImpl = class _PromiseEdgeOrNullImpl extends PromiseEntsOrNu
|
|
|
404
404
|
return null;
|
|
405
405
|
}
|
|
406
406
|
const edgeDoc = this.ctx.db.query(this.edgeDefinition.table).withIndex(
|
|
407
|
-
`${this.edgeDefinition.field}
|
|
407
|
+
`${this.edgeDefinition.field}_${this.edgeDefinition.ref}`,
|
|
408
408
|
(q) => q.eq(this.edgeDefinition.field, sourceId).eq(
|
|
409
409
|
this.edgeDefinition.ref,
|
|
410
410
|
targetId
|