convex-ents 0.14.0-alpha.0 → 0.14.0-alpha.1
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/functions.js.map +1 -1
- package/dist/index.js +42 -16
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +6 -4
- package/dist/schema.js +42 -16
- package/dist/schema.js.map +1 -1
- package/dist/writer.js.map +1 -1
- package/package.json +1 -1
package/dist/schema.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { DefineSchemaOptions, SchemaDefinition, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, TableDefinition, SearchIndexConfig, VectorIndexConfig, GenericDataModel, DataModelFromSchemaDefinition } from 'convex/server';
|
|
2
|
-
import {
|
|
2
|
+
import { Validator, GenericValidator, VObject, ObjectType, VId, GenericId, VOptional, VFloat64, VUnion, VAny } from 'convex/values';
|
|
3
3
|
|
|
4
4
|
declare function defineEntSchema<Schema extends Record<string, EntDefinition>, StrictTableNameTypes extends boolean = true>(schema: Schema, options?: DefineSchemaOptions<StrictTableNameTypes>): SchemaDefinition<Schema, StrictTableNameTypes>;
|
|
5
5
|
declare function edgeCompoundIndexName(edgeDefinition: EdgeConfig & {
|
|
6
6
|
cardinality: "multiple";
|
|
7
7
|
type: "ref";
|
|
8
8
|
}): string;
|
|
9
|
-
declare function defineEnt<DocumentSchema extends
|
|
9
|
+
declare function defineEnt<DocumentSchema extends Validator<Record<string, any>, "required", any>>(documentSchema: DocumentSchema): EntDefinition<DocumentSchema>;
|
|
10
|
+
declare function defineEnt<DocumentSchema extends Record<string, GenericValidator>>(documentSchema: DocumentSchema): EntDefinition<VObject<ObjectType<DocumentSchema>, DocumentSchema>>;
|
|
10
11
|
declare function defineEntFromTable<DocumentType extends GenericValidator = GenericValidator, Indexes extends GenericTableIndexes = {}, SearchIndexes extends GenericTableSearchIndexes = {}, VectorIndexes extends GenericTableVectorIndexes = {}>(definition: TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes>): EntDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes>;
|
|
11
12
|
type DefineEntFromTables<T extends {
|
|
12
13
|
[key: string]: TableDefinition<any, any, any, any>;
|
|
@@ -32,7 +33,9 @@ type ObjectFieldType<FieldName extends string, T extends Validator<any, any, any
|
|
|
32
33
|
};
|
|
33
34
|
type AddField<V extends GenericValidator, FieldName extends string, P extends GenericValidator> = V extends VObject<infer TypeScriptType, infer Fields, infer IsOptional, infer FieldPaths> ? VObject<Expand<TypeScriptType & ObjectFieldType<FieldName, P>>, Expand<Fields & {
|
|
34
35
|
FieldName: P;
|
|
35
|
-
}>, IsOptional, FieldPaths | FieldName> : V extends
|
|
36
|
+
}>, IsOptional, FieldPaths | FieldName> : V extends VUnion<infer TypeScriptType, infer Members, infer IsOptional, infer FieldPaths> ? VUnion<Expand<TypeScriptType & ObjectFieldType<FieldName, P>>, {
|
|
37
|
+
[key in keyof Members]: AddField<Members[key], FieldName, P>;
|
|
38
|
+
}, IsOptional, FieldPaths> : V extends VAny ? VAny : never;
|
|
36
39
|
interface EntDefinition<DocumentType extends Validator<any, any, any> = Validator<any, any, any>, Indexes extends GenericTableIndexes = {}, SearchIndexes extends GenericTableSearchIndexes = {}, VectorIndexes extends GenericTableVectorIndexes = {}, Edges extends GenericEdges = {}> extends TableDefinition<DocumentType, Indexes, SearchIndexes, VectorIndexes> {
|
|
37
40
|
/**
|
|
38
41
|
* Define an index on this table.
|
|
@@ -366,7 +369,6 @@ type Expand<ObjectType extends Record<any, any>> = ObjectType extends Record<any
|
|
|
366
369
|
type SystemFields = {
|
|
367
370
|
_creationTime: number;
|
|
368
371
|
};
|
|
369
|
-
type ObjectValidator<Validators extends PropertyValidators> = VObject<ObjectType<Validators>, Validators>;
|
|
370
372
|
type GenericEntsDataModel = GenericDataModel & Record<string, GenericEntModel>;
|
|
371
373
|
type GenericEntModel = {
|
|
372
374
|
edges: Record<string, GenericEdgeConfig>;
|
package/dist/schema.js
CHANGED
|
@@ -222,7 +222,15 @@ function deletionConfigFromEntDefinition(table) {
|
|
|
222
222
|
return table.deletionConfig;
|
|
223
223
|
}
|
|
224
224
|
function defineEnt(documentSchema) {
|
|
225
|
-
|
|
225
|
+
if (isValidator(documentSchema)) {
|
|
226
|
+
if (!(documentSchema.kind === "object" || documentSchema.kind === "union" && documentSchema.members.every((member) => member.kind === "object"))) {
|
|
227
|
+
throw new Error("Ent shape must be an object or a union of objects");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return new EntDefinitionImpl((0, import_values.asObjectValidator)(documentSchema));
|
|
231
|
+
}
|
|
232
|
+
function isValidator(v2) {
|
|
233
|
+
return !!v2.isConvexValidator;
|
|
226
234
|
}
|
|
227
235
|
function defineEntFromTable(definition) {
|
|
228
236
|
const validator = definition.validator;
|
|
@@ -255,14 +263,12 @@ var EntDefinitionImpl = class {
|
|
|
255
263
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
256
264
|
// @ts-ignore
|
|
257
265
|
vectorIndexes = [];
|
|
258
|
-
documentSchema;
|
|
259
266
|
edgeConfigs = {};
|
|
260
267
|
fieldConfigs = {};
|
|
261
268
|
defaults = {};
|
|
262
269
|
deletionConfig;
|
|
263
270
|
constructor(documentSchema) {
|
|
264
|
-
this.
|
|
265
|
-
this.validator = import_values.v.object(documentSchema);
|
|
271
|
+
this.validator = documentSchema;
|
|
266
272
|
}
|
|
267
273
|
index(name, fields) {
|
|
268
274
|
this.indexes.push({ indexDescriptor: name, fields });
|
|
@@ -296,15 +302,15 @@ var EntDefinitionImpl = class {
|
|
|
296
302
|
indexes: this.indexes,
|
|
297
303
|
searchIndexes: this.searchIndexes,
|
|
298
304
|
vectorIndexes: this.vectorIndexes,
|
|
299
|
-
documentType:
|
|
305
|
+
documentType: this.validator.json
|
|
300
306
|
};
|
|
301
307
|
}
|
|
302
308
|
field(name, validator, options) {
|
|
303
|
-
if (this.
|
|
309
|
+
if (this._has(name)) {
|
|
304
310
|
throw new Error(`Duplicate field "${name}"`);
|
|
305
311
|
}
|
|
306
312
|
const finalValidator = options?.default !== void 0 ? import_values.v.optional(validator) : validator;
|
|
307
|
-
this.
|
|
313
|
+
this._expand(name, finalValidator);
|
|
308
314
|
if (options?.unique === true || options?.index === true) {
|
|
309
315
|
this.indexes.push({ indexDescriptor: name, fields: [name] });
|
|
310
316
|
}
|
|
@@ -328,10 +334,10 @@ var EntDefinitionImpl = class {
|
|
|
328
334
|
}
|
|
329
335
|
if (options?.field !== void 0 || options?.ref === void 0) {
|
|
330
336
|
const fieldName = options?.field ?? edgeName + "Id";
|
|
331
|
-
this.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
this._expand(
|
|
338
|
+
fieldName,
|
|
339
|
+
options?.optional === true ? import_values.v.optional(import_values.v.id(to)) : import_values.v.id(to)
|
|
340
|
+
);
|
|
335
341
|
this.edgeConfigs[edgeName] = {
|
|
336
342
|
name: edgeName,
|
|
337
343
|
to,
|
|
@@ -390,7 +396,7 @@ var EntDefinitionImpl = class {
|
|
|
390
396
|
return this;
|
|
391
397
|
}
|
|
392
398
|
deletion(type, options) {
|
|
393
|
-
if (this.
|
|
399
|
+
if (this._has("deletionTime")) {
|
|
394
400
|
throw new Error(
|
|
395
401
|
`Cannot enable "${type}" deletion because "deletionTime" field was already defined.`
|
|
396
402
|
);
|
|
@@ -398,13 +404,33 @@ var EntDefinitionImpl = class {
|
|
|
398
404
|
if (this.deletionConfig !== void 0) {
|
|
399
405
|
throw new Error(`Deletion behavior can only be specified once.`);
|
|
400
406
|
}
|
|
401
|
-
this.
|
|
402
|
-
...this.documentSchema,
|
|
403
|
-
deletionTime: import_values.v.optional(import_values.v.number())
|
|
404
|
-
};
|
|
407
|
+
this._expand("deletionTime", import_values.v.optional(import_values.v.number()));
|
|
405
408
|
this.deletionConfig = { type, ...options };
|
|
406
409
|
return this;
|
|
407
410
|
}
|
|
411
|
+
_has(name) {
|
|
412
|
+
if (this.validator.kind === "object") {
|
|
413
|
+
return this.validator.fields[name] !== void 0;
|
|
414
|
+
}
|
|
415
|
+
if (this.validator.kind === "union") {
|
|
416
|
+
return this.validator.members.some(
|
|
417
|
+
(member) => member.kind === "object" && member.fields[name] !== void 0
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
_expand(name, validator) {
|
|
423
|
+
if (this.validator.kind === "object") {
|
|
424
|
+
this.validator.fields[name] = validator;
|
|
425
|
+
}
|
|
426
|
+
if (this.validator.kind === "union") {
|
|
427
|
+
this.validator.members.forEach((member) => {
|
|
428
|
+
if (member.kind === "object") {
|
|
429
|
+
member.fields[name] = validator;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
408
434
|
};
|
|
409
435
|
function getEntDefinitions(schema) {
|
|
410
436
|
const tables = schema.tables;
|
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 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<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 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 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 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 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: 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?.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.documentSchema = {\n ...this.documentSchema,\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.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 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\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 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\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 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 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\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","v","acc"]}
|