Skip to content

Commit 1e96aca

Browse files
committed
leverage types
1 parent 8065d84 commit 1e96aca

File tree

1 file changed

+17
-25
lines changed
  • packages/convex-helpers/server

1 file changed

+17
-25
lines changed

packages/convex-helpers/server/crud.ts

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import type {
2121
GenericId,
2222
Infer,
2323
Validator,
24+
VObject,
25+
VUnion,
2426
} from "convex/values";
2527
import { v } from "convex/values";
26-
import { doc, partial } from "../validators.js";
28+
import { doc, partial, systemFields } from "../validators.js";
2729
/**
2830
* Create CRUD operations for a table.
2931
* You can expose these operations in your API. For example, in convex/users.ts:
@@ -71,52 +73,40 @@ export function crud<
7173
> = internalMutationGeneric as any,
7274
) {
7375
type DataModel = DataModelFromSchemaDefinition<SchemaDefinition<Schema, any>>;
74-
75-
const validator = schema.tables[table]?.validator
76+
const validator = schema.tables[table]?.validator;
7677
if (!validator) {
7778
throw new Error(
7879
`Table ${table} not found in schema. Did you define it in defineSchema?`,
7980
);
8081
}
82+
if (validator.kind !== "object" && validator.kind !== "union") {
83+
throw new Error("Validator must be an object or union");
84+
}
8185

82-
const systemFields = v.object({
83-
_id: v.id(table),
84-
_creationTime: v.number(),
85-
});
86-
87-
const partialSystemFields = partial(systemFields).fields;
88-
89-
90-
const makeSystemFieldsOptional = (
91-
validator: Validator<any, any, any>,
92-
): Validator<any, any, any> => {
86+
const makeSystemFieldsOptional = <V extends Validator<any, any, any>>(
87+
validator: V,
88+
): V => {
9389
if (validator.kind === "object") {
9490
return v.object({
9591
...validator.fields,
96-
...partialSystemFields,
92+
...partial(systemFields(table)),
9793
}) as any;
9894
} else if (validator.kind === "union") {
9995
return v.union(
100-
...validator.members.map((value) => makeSystemFieldsOptional(value) as any),
96+
...validator.members.map((value) => makeSystemFieldsOptional(value)),
10197
) as any;
10298
} else {
103-
return validator;
99+
throw new Error("Validator must be an object or union");
104100
}
105101
};
106102

107-
108103
return {
109104
create: mutation({
110105
args: makeSystemFieldsOptional(validator),
111106
handler: async (ctx, args) => {
112107
if ("_id" in args) delete args._id;
113108
if ("_creationTime" in args) delete args._creationTime;
114-
const id = await ctx.db.insert(
115-
table,
116-
args as unknown as WithoutSystemFields<
117-
DocumentByName<DataModel, TableName>
118-
>,
119-
);
109+
const id = await ctx.db.insert(table, args);
120110
return (await ctx.db.get(id))!;
121111
},
122112
}) as RegisteredMutation<
@@ -151,7 +141,9 @@ export function crud<
151141
id: v.id(table),
152142
// this could be partial(table.withSystemFields) but keeping
153143
// the api less coupled to Table
154-
patch: partial(v.union(doc(schema, table)))
144+
patch: partial(
145+
doc(schema, table) as VObject<any, any, any> | VUnion<any, any, any>,
146+
),
155147
},
156148
handler: async (ctx, args) => {
157149
await ctx.db.patch(

0 commit comments

Comments
 (0)