convex-verify 0.1.0 → 0.1.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/README.md CHANGED
@@ -13,12 +13,12 @@ Type-safe verification and validation for Convex database operations.
13
13
  ## Installation
14
14
 
15
15
  ```bash
16
- npm install convex-verify
16
+ pnpm install convex-verify
17
17
  ```
18
18
 
19
19
  **Peer Dependencies:**
20
20
 
21
- - `convex` >= 1.17.4
21
+ - `convex` >= 1.31.3
22
22
 
23
23
  ## Quick Start
24
24
 
@@ -29,43 +29,46 @@ import {
29
29
  uniqueColumnConfig,
30
30
  uniqueRowConfig,
31
31
  verifyConfig,
32
- } from 'convex-verify';
32
+ } from "convex-verify";
33
33
 
34
- import schema from './schema';
34
+ import schema from "./schema";
35
35
 
36
36
  export const { insert, patch, dangerouslyPatch } = verifyConfig(schema, {
37
37
  // Make fields optional with defaults
38
38
  defaultValues: defaultValuesConfig(schema, () => ({
39
- posts: { status: 'draft', views: 0 },
39
+ posts: { status: "draft", views: 0 },
40
40
  })),
41
41
 
42
42
  // Prevent patching critical fields
43
43
  protectedColumns: protectedColumnsConfig(schema, {
44
- posts: ['authorId'],
44
+ posts: ["authorId"],
45
45
  }),
46
46
 
47
- // Validation plugins
48
- plugins: [
49
- uniqueRowConfig(schema, {
50
- posts: ['by_author_slug'],
51
- }),
52
- uniqueColumnConfig(schema, {
53
- users: ['by_email', 'by_username'],
54
- }),
55
- ],
47
+ // Enforce unique row combinations
48
+ uniqueRow: uniqueRowConfig(schema, {
49
+ posts: ["by_author_slug"],
50
+ }),
51
+
52
+ // Enforce unique column values
53
+ uniqueColumn: uniqueColumnConfig(schema, {
54
+ users: ["by_email", "by_username"],
55
+ }),
56
+
57
+ // Custom/third-party plugins (optional)
58
+ plugins: [],
56
59
  });
57
60
  ```
58
61
 
59
62
  Then use in your mutations:
60
63
 
61
64
  ```ts
62
- import { insert, patch } from './verify';
65
+ import { insert, patch } from "./verify";
63
66
 
64
67
  export const createPost = mutation({
65
68
  args: { title: v.string(), content: v.string() },
66
69
  handler: async (ctx, args) => {
67
70
  // status and views are optional - defaults are applied
68
- return await insert(ctx, 'posts', {
71
+ return await insert(ctx, "posts", {
69
72
  title: args.title,
70
73
  content: args.content,
71
74
  authorId: ctx.auth.userId,
@@ -74,10 +77,10 @@ export const createPost = mutation({
74
77
  });
75
78
 
76
79
  export const updatePost = mutation({
77
- args: { id: v.id('posts'), title: v.string() },
80
+ args: { id: v.id("posts"), title: v.string() },
78
81
  handler: async (ctx, args) => {
79
82
  // authorId is protected - TypeScript won't allow it here
80
- await patch(ctx, 'posts', args.id, {
83
+ await patch(ctx, "posts", args.id, {
81
84
  title: args.title,
82
85
  });
83
86
  },
@@ -94,8 +97,15 @@ Main configuration function that returns typed `insert`, `patch`, and `dangerous
94
97
 
95
98
  ```ts
96
99
  const { insert, patch, dangerouslyPatch, configs } = verifyConfig(schema, {
100
+ // Type-affecting configs
97
101
  defaultValues?: DefaultValuesConfig,
98
102
  protectedColumns?: ProtectedColumnsConfig,
103
+
104
+ // Built-in validation configs
105
+ uniqueRow?: UniqueRowConfig,
106
+ uniqueColumn?: UniqueColumnConfig,
107
+
108
+ // Custom/third-party plugins
99
109
  plugins?: ValidatePlugin[],
100
110
  });
101
111
  ```
@@ -120,16 +130,16 @@ Transforms modify the input type of `insert()`.
120
130
  Makes specified fields optional in `insert()` by providing default values.
121
131
 
122
132
  ```ts
123
- import { defaultValuesConfig } from 'convex-verify';
133
+ import { defaultValuesConfig } from "convex-verify";
124
134
  // or
125
- import { defaultValuesConfig } from 'convex-verify/transforms';
135
+ import { defaultValuesConfig } from "convex-verify/transforms";
126
136
  ```
127
137
 
128
138
  #### Static Config
129
139
 
130
140
  ```ts
131
141
  const defaults = defaultValuesConfig(schema, {
132
- posts: { status: 'draft', views: 0 },
142
+ posts: { status: "draft", views: 0 },
133
143
  comments: { likes: 0 },
134
144
  });
135
145
  ```
@@ -141,7 +151,7 @@ Use a function for values that should be generated fresh on each insert:
141
151
  ```ts
142
152
  const defaults = defaultValuesConfig(schema, () => ({
143
153
  posts: {
144
- status: 'draft',
154
+ status: "draft",
145
155
  slug: generateRandomSlug(),
146
156
  createdAt: Date.now(),
147
157
  },
@@ -169,17 +179,17 @@ Configs modify the input type of `patch()`.
169
179
  Removes specified columns from the `patch()` input type, preventing accidental updates.
170
180
 
171
181
  ```ts
172
- import { protectedColumnsConfig } from 'convex-verify';
182
+ import { protectedColumnsConfig } from "convex-verify";
173
183
  // or
174
- import { protectedColumnsConfig } from 'convex-verify/configs';
184
+ import { protectedColumnsConfig } from "convex-verify/configs";
175
185
  ```
176
186
 
177
187
  #### Example
178
188
 
179
189
  ```ts
180
190
  const protected = protectedColumnsConfig(schema, {
181
- posts: ['authorId', 'createdAt'],
182
- comments: ['postId', 'authorId'],
191
+ posts: ["authorId", "createdAt"],
192
+ comments: ["postId", "authorId"],
183
193
  });
184
194
  ```
185
195
 
@@ -189,15 +199,15 @@ Use `dangerouslyPatch()` when you need to update protected columns:
189
199
 
190
200
  ```ts
191
201
  // Regular patch - authorId not allowed
192
- await patch(ctx, 'posts', id, {
202
+ await patch(ctx, "posts", id, {
193
203
  authorId: newAuthorId, // ❌ TypeScript error
194
- title: 'New Title', // ✅ OK
204
+ title: "New Title", // ✅ OK
195
205
  });
196
206
 
197
207
  // Dangerous patch - full access
198
- await dangerouslyPatch(ctx, 'posts', id, {
208
+ await dangerouslyPatch(ctx, "posts", id, {
199
209
  authorId: newAuthorId, // ✅ OK (bypasses protection)
200
- title: 'New Title',
210
+ title: "New Title",
201
211
  });
202
212
  ```
203
213
 
@@ -205,26 +215,46 @@ await dangerouslyPatch(ctx, 'posts', id, {
205
215
 
206
216
  ---
207
217
 
208
- ## Plugins
218
+ ## Validation
209
219
 
210
- Plugins validate data during `insert()` and `patch()` operations. They run after transforms and can throw errors to prevent the operation.
220
+ Validation configs check data during `insert()` and `patch()` operations. They run after transforms and can throw errors to prevent the operation.
211
221
 
212
222
  ### `uniqueRowConfig(schema, config)`
213
223
 
214
224
  Enforces uniqueness across multiple columns using composite indexes.
215
225
 
216
226
  ```ts
217
- import { uniqueRowConfig } from 'convex-verify';
227
+ import { uniqueRowConfig } from "convex-verify";
218
228
  // or
219
- import { uniqueRowConfig } from 'convex-verify/plugins';
229
+ import { uniqueRowConfig } from "convex-verify/plugins";
230
+ ```
231
+
232
+ #### Usage
233
+
234
+ ```ts
235
+ // As a named config key (recommended)
236
+ verifyConfig(schema, {
237
+ uniqueRow: uniqueRowConfig(schema, {
238
+ posts: ["by_author_slug"],
239
+ }),
240
+ });
241
+
242
+ // Or in the plugins array
243
+ verifyConfig(schema, {
244
+ plugins: [
245
+ uniqueRowConfig(schema, {
246
+ posts: ["by_author_slug"],
247
+ }),
248
+ ],
249
+ });
220
250
  ```
221
251
 
222
252
  #### Shorthand (Index Names)
223
253
 
224
254
  ```ts
225
255
  const uniqueRows = uniqueRowConfig(schema, {
226
- posts: ['by_author_slug'], // Unique author + slug combo
227
- projects: ['by_org_slug'], // Unique org + slug combo
256
+ posts: ["by_author_slug"], // Unique author + slug combo
257
+ projects: ["by_org_slug"], // Unique org + slug combo
228
258
  });
229
259
  ```
230
260
 
@@ -234,8 +264,8 @@ const uniqueRows = uniqueRowConfig(schema, {
234
264
  const uniqueRows = uniqueRowConfig(schema, {
235
265
  posts: [
236
266
  {
237
- index: 'by_author_slug',
238
- identifiers: ['_id', 'authorId'], // Fields to check for "same document"
267
+ index: "by_author_slug",
268
+ identifiers: ["_id", "authorId"], // Fields to check for "same document"
239
269
  },
240
270
  ],
241
271
  });
@@ -246,9 +276,29 @@ const uniqueRows = uniqueRowConfig(schema, {
246
276
  Enforces uniqueness on single columns using indexes.
247
277
 
248
278
  ```ts
249
- import { uniqueColumnConfig } from 'convex-verify';
279
+ import { uniqueColumnConfig } from "convex-verify";
250
280
  // or
251
- import { uniqueColumnConfig } from 'convex-verify/plugins';
281
+ import { uniqueColumnConfig } from "convex-verify/plugins";
282
+ ```
283
+
284
+ #### Usage
285
+
286
+ ```ts
287
+ // As a named config key (recommended)
288
+ verifyConfig(schema, {
289
+ uniqueColumn: uniqueColumnConfig(schema, {
290
+ users: ["by_email", "by_username"],
291
+ }),
292
+ });
293
+
294
+ // Or in the plugins array
295
+ verifyConfig(schema, {
296
+ plugins: [
297
+ uniqueColumnConfig(schema, {
298
+ users: ["by_email", "by_username"],
299
+ }),
300
+ ],
301
+ });
252
302
  ```
253
303
 
254
304
  The column name is derived from the index name by removing `by_` prefix:
@@ -256,12 +306,12 @@ The column name is derived from the index name by removing `by_` prefix:
256
306
  - `by_username` → checks `username` column
257
307
  - `by_email` → checks `email` column
258
308
 
259
- #### Example
309
+ #### Shorthand (Index Names)
260
310
 
261
311
  ```ts
262
312
  const uniqueColumns = uniqueColumnConfig(schema, {
263
- users: ['by_username', 'by_email'],
264
- organizations: ['by_slug'],
313
+ users: ["by_username", "by_email"],
314
+ organizations: ["by_slug"],
265
315
  });
266
316
  ```
267
317
 
@@ -270,38 +320,44 @@ const uniqueColumns = uniqueColumnConfig(schema, {
270
320
  ```ts
271
321
  const uniqueColumns = uniqueColumnConfig(schema, {
272
322
  users: [
273
- 'by_username', // shorthand
274
- { index: 'by_email', identifiers: ['_id', 'clerkId'] }, // with options
323
+ "by_username", // shorthand
324
+ { index: "by_email", identifiers: ["_id", "clerkId"] }, // with options
275
325
  ],
276
326
  });
277
327
  ```
278
328
 
329
+ ## Custom Plugins
330
+
331
+ The `plugins` array accepts custom validation plugins for extensibility.
332
+
279
333
  ### `createValidatePlugin(name, config, handlers)`
280
334
 
281
335
  Create custom validation plugins.
282
336
 
283
337
  ```ts
284
- import { createValidatePlugin } from 'convex-verify';
338
+ import { createValidatePlugin } from "convex-verify";
285
339
  // or
286
- import { createValidatePlugin } from 'convex-verify/core';
340
+ import { createValidatePlugin } from "convex-verify/core";
287
341
  ```
288
342
 
289
343
  #### Example: Required Fields Plugin
290
344
 
291
345
  ```ts
292
346
  const requiredFields = createValidatePlugin(
293
- 'requiredFields',
294
- { fields: ['title', 'content'] },
347
+ "requiredFields",
348
+ { fields: ["title", "content"] },
295
349
  {
296
350
  insert: (context, data) => {
297
351
  for (const field of context.config.fields) {
298
352
  if (!data[field]) {
299
- throw new ConvexError({ message: `Missing required field: ${field}` });
353
+ throw new ConvexError({
354
+ message: `Missing required field: ${field}`,
355
+ });
300
356
  }
301
357
  }
302
358
  return data;
303
359
  },
304
- }
360
+ },
305
361
  );
306
362
  ```
307
363
 
@@ -309,7 +365,7 @@ const requiredFields = createValidatePlugin(
309
365
 
310
366
  ```ts
311
367
  const checkOwnership = createValidatePlugin(
312
- 'checkOwnership',
368
+ "checkOwnership",
313
369
  {},
314
370
  {
315
371
  patch: async (context, data) => {
@@ -317,11 +373,13 @@ const checkOwnership = createValidatePlugin(
317
373
  const user = await getCurrentUser(context.ctx);
318
374
 
319
375
  if (existing?.authorId !== user._id) {
320
- throw new ConvexError({ message: 'Not authorized to edit this document' });
376
+ throw new ConvexError({
377
+ message: "Not authorized to edit this document",
378
+ });
321
379
  }
322
380
  return data;
323
381
  },
324
- }
382
+ },
325
383
  );
326
384
  ```
327
385
 
@@ -333,7 +391,7 @@ Plugins receive a `ValidateContext` object:
333
391
  type ValidateContext = {
334
392
  ctx: GenericMutationCtx; // Convex mutation context
335
393
  tableName: string; // Table being operated on
336
- operation: 'insert' | 'patch';
394
+ operation: "insert" | "patch";
337
395
  patchId?: GenericId; // Document ID (patch only)
338
396
  onFail?: OnFailCallback; // Callback for failure details
339
397
  schema?: SchemaDefinition; // Schema reference
@@ -348,13 +406,13 @@ For smaller bundle sizes, you can import from specific subpaths:
348
406
 
349
407
  ```ts
350
408
  // Import everything from root
351
- import { uniqueRowConfig, verifyConfig } from 'convex-verify';
352
- import { protectedColumnsConfig } from 'convex-verify/configs';
409
+ import { uniqueRowConfig, verifyConfig } from "convex-verify";
410
+ import { protectedColumnsConfig } from "convex-verify/configs";
353
411
  // Or import from specific subpaths
354
- import { createValidatePlugin, verifyConfig } from 'convex-verify/core';
355
- import { uniqueColumnConfig, uniqueRowConfig } from 'convex-verify/plugins';
356
- import { defaultValuesConfig } from 'convex-verify/transforms';
357
- import { getTableIndexes } from 'convex-verify/utils';
412
+ import { createValidatePlugin, verifyConfig } from "convex-verify/core";
413
+ import { uniqueColumnConfig, uniqueRowConfig } from "convex-verify/plugins";
414
+ import { defaultValuesConfig } from "convex-verify/transforms";
415
+ import { getTableIndexes } from "convex-verify/utils";
358
416
  ```
359
417
 
360
418
  ---
@@ -366,13 +424,13 @@ import { getTableIndexes } from 'convex-verify/utils';
366
424
  All operations accept an optional `onFail` callback for handling validation failures:
367
425
 
368
426
  ```ts
369
- await insert(ctx, 'posts', data, {
427
+ await insert(ctx, "posts", data, {
370
428
  onFail: (args) => {
371
429
  if (args.uniqueRow) {
372
- console.log('Duplicate row:', args.uniqueRow.existingData);
430
+ console.log("Duplicate row:", args.uniqueRow.existingData);
373
431
  }
374
432
  if (args.uniqueColumn) {
375
- console.log('Duplicate column:', args.uniqueColumn.conflictingColumn);
433
+ console.log("Duplicate column:", args.uniqueColumn.conflictingColumn);
376
434
  }
377
435
  },
378
436
  });
@@ -1,4 +1,4 @@
1
- import { SchemaDefinition, GenericSchema, DataModelFromSchemaDefinition, TableNamesInDataModel, DocumentByName, GenericMutationCtx, WithoutSystemFields } from 'convex/server';
1
+ import { GenericSchema, DataModelFromSchemaDefinition, SchemaDefinition, TableNamesInDataModel, DocumentByName, GenericMutationCtx, WithoutSystemFields } from 'convex/server';
2
2
  import { GenericId } from 'convex/values';
3
3
  import { a as ValidatePlugin } from '../plugin-mHMV2-SG.mjs';
4
4
  export { V as ValidateContext, b as ValidatePluginRecord, c as createValidatePlugin, i as isValidatePlugin, r as runValidatePlugins } from '../plugin-mHMV2-SG.mjs';
@@ -10,8 +10,25 @@ export { B as BaseConfigReturn, k as DMGeneric, D as DefaultValuesConfigData, l
10
10
  */
11
11
  type VerifyConfigInputWithPlugins = VerifyConfigInput & {
12
12
  /**
13
- * Validate plugins to run after transforms.
13
+ * Unique row validation config.
14
+ * Enforces uniqueness across multiple columns using composite indexes.
15
+ *
16
+ * Can also be added to the `plugins` array.
17
+ */
18
+ uniqueRow?: ValidatePlugin<"uniqueRow", any>;
19
+ /**
20
+ * Unique column validation config.
21
+ * Enforces uniqueness on single columns using indexes.
22
+ *
23
+ * Can also be added to the `plugins` array.
24
+ */
25
+ uniqueColumn?: ValidatePlugin<"uniqueColumn", any>;
26
+ /**
27
+ * Additional validate plugins to run after transforms.
14
28
  * These plugins can validate data but don't affect input types.
29
+ *
30
+ * Built-in plugins (uniqueRow, uniqueColumn) can be added here
31
+ * as an alternative to using their dedicated config keys.
15
32
  */
16
33
  plugins?: ValidatePlugin[];
17
34
  };
@@ -24,25 +41,38 @@ type VerifyConfigInputWithPlugins = VerifyConfigInput & {
24
41
  *
25
42
  * @example
26
43
  * ```ts
27
- * import { verifyConfig, defaultValuesConfig, protectedColumnsConfig, uniqueRowConfig } from 'convex-verify';
44
+ * import {
45
+ * verifyConfig,
46
+ * defaultValuesConfig,
47
+ * protectedColumnsConfig,
48
+ * uniqueRowConfig,
49
+ * uniqueColumnConfig,
50
+ * } from 'convex-verify';
28
51
  * import schema from './schema';
29
52
  *
30
53
  * export const { insert, patch, dangerouslyPatch } = verifyConfig(schema, {
54
+ * // Type-affecting configs
31
55
  * defaultValues: defaultValuesConfig(schema, () => ({
32
56
  * posts: { status: 'draft', views: 0 },
33
57
  * })),
34
58
  * protectedColumns: protectedColumnsConfig(schema, {
35
59
  * posts: ['authorId'],
36
60
  * }),
37
- * plugins: [
38
- * uniqueRowConfig(schema, {
39
- * posts: ['by_slug'],
40
- * }),
41
- * ],
61
+ *
62
+ * // Built-in validation configs
63
+ * uniqueRow: uniqueRowConfig(schema, {
64
+ * posts: ['by_author_slug'],
65
+ * }),
66
+ * uniqueColumn: uniqueColumnConfig(schema, {
67
+ * users: ['by_email', 'by_username'],
68
+ * }),
69
+ *
70
+ * // Custom/third-party plugins
71
+ * plugins: [myCustomPlugin()],
42
72
  * });
43
73
  * ```
44
74
  */
45
- declare const verifyConfig: <S extends SchemaDefinition<GenericSchema, boolean>, DataModel extends DataModelFromSchemaDefinition<S>, const VC extends VerifyConfigInputWithPlugins>(_schema: S, configs: VC) => {
75
+ declare const verifyConfig: <S extends GenericSchema, DataModel extends DataModelFromSchemaDefinition<SchemaDefinition<S, boolean>>, const VC extends VerifyConfigInputWithPlugins>(_schema: SchemaDefinition<S, boolean>, configs: VC) => {
46
76
  insert: <const TN extends TableNamesInDataModel<DataModel>, const D extends DocumentByName<DataModel, TN>>(ctx: Omit<GenericMutationCtx<DataModel>, never>, tableName: TN, data: HasKey<VC, "defaultValues"> extends true ? MakeOptional<WithoutSystemFields<D>, OptionalKeysForTable<VC, TN> & keyof WithoutSystemFields<D>> : WithoutSystemFields<D>, options?: {
47
77
  onFail?: OnFailCallback<D>;
48
78
  }) => Promise<GenericId<TN>>;
@@ -1,4 +1,4 @@
1
- import { SchemaDefinition, GenericSchema, DataModelFromSchemaDefinition, TableNamesInDataModel, DocumentByName, GenericMutationCtx, WithoutSystemFields } from 'convex/server';
1
+ import { GenericSchema, DataModelFromSchemaDefinition, SchemaDefinition, TableNamesInDataModel, DocumentByName, GenericMutationCtx, WithoutSystemFields } from 'convex/server';
2
2
  import { GenericId } from 'convex/values';
3
3
  import { a as ValidatePlugin } from '../plugin-BjJ7yjrc.js';
4
4
  export { V as ValidateContext, b as ValidatePluginRecord, c as createValidatePlugin, i as isValidatePlugin, r as runValidatePlugins } from '../plugin-BjJ7yjrc.js';
@@ -10,8 +10,25 @@ export { B as BaseConfigReturn, k as DMGeneric, D as DefaultValuesConfigData, l
10
10
  */
11
11
  type VerifyConfigInputWithPlugins = VerifyConfigInput & {
12
12
  /**
13
- * Validate plugins to run after transforms.
13
+ * Unique row validation config.
14
+ * Enforces uniqueness across multiple columns using composite indexes.
15
+ *
16
+ * Can also be added to the `plugins` array.
17
+ */
18
+ uniqueRow?: ValidatePlugin<"uniqueRow", any>;
19
+ /**
20
+ * Unique column validation config.
21
+ * Enforces uniqueness on single columns using indexes.
22
+ *
23
+ * Can also be added to the `plugins` array.
24
+ */
25
+ uniqueColumn?: ValidatePlugin<"uniqueColumn", any>;
26
+ /**
27
+ * Additional validate plugins to run after transforms.
14
28
  * These plugins can validate data but don't affect input types.
29
+ *
30
+ * Built-in plugins (uniqueRow, uniqueColumn) can be added here
31
+ * as an alternative to using their dedicated config keys.
15
32
  */
16
33
  plugins?: ValidatePlugin[];
17
34
  };
@@ -24,25 +41,38 @@ type VerifyConfigInputWithPlugins = VerifyConfigInput & {
24
41
  *
25
42
  * @example
26
43
  * ```ts
27
- * import { verifyConfig, defaultValuesConfig, protectedColumnsConfig, uniqueRowConfig } from 'convex-verify';
44
+ * import {
45
+ * verifyConfig,
46
+ * defaultValuesConfig,
47
+ * protectedColumnsConfig,
48
+ * uniqueRowConfig,
49
+ * uniqueColumnConfig,
50
+ * } from 'convex-verify';
28
51
  * import schema from './schema';
29
52
  *
30
53
  * export const { insert, patch, dangerouslyPatch } = verifyConfig(schema, {
54
+ * // Type-affecting configs
31
55
  * defaultValues: defaultValuesConfig(schema, () => ({
32
56
  * posts: { status: 'draft', views: 0 },
33
57
  * })),
34
58
  * protectedColumns: protectedColumnsConfig(schema, {
35
59
  * posts: ['authorId'],
36
60
  * }),
37
- * plugins: [
38
- * uniqueRowConfig(schema, {
39
- * posts: ['by_slug'],
40
- * }),
41
- * ],
61
+ *
62
+ * // Built-in validation configs
63
+ * uniqueRow: uniqueRowConfig(schema, {
64
+ * posts: ['by_author_slug'],
65
+ * }),
66
+ * uniqueColumn: uniqueColumnConfig(schema, {
67
+ * users: ['by_email', 'by_username'],
68
+ * }),
69
+ *
70
+ * // Custom/third-party plugins
71
+ * plugins: [myCustomPlugin()],
42
72
  * });
43
73
  * ```
44
74
  */
45
- declare const verifyConfig: <S extends SchemaDefinition<GenericSchema, boolean>, DataModel extends DataModelFromSchemaDefinition<S>, const VC extends VerifyConfigInputWithPlugins>(_schema: S, configs: VC) => {
75
+ declare const verifyConfig: <S extends GenericSchema, DataModel extends DataModelFromSchemaDefinition<SchemaDefinition<S, boolean>>, const VC extends VerifyConfigInputWithPlugins>(_schema: SchemaDefinition<S, boolean>, configs: VC) => {
46
76
  insert: <const TN extends TableNamesInDataModel<DataModel>, const D extends DocumentByName<DataModel, TN>>(ctx: Omit<GenericMutationCtx<DataModel>, never>, tableName: TN, data: HasKey<VC, "defaultValues"> extends true ? MakeOptional<WithoutSystemFields<D>, OptionalKeysForTable<VC, TN> & keyof WithoutSystemFields<D>> : WithoutSystemFields<D>, options?: {
47
77
  onFail?: OnFailCallback<D>;
48
78
  }) => Promise<GenericId<TN>>;
@@ -52,11 +52,20 @@ function createValidatePlugin(type, config, verify) {
52
52
 
53
53
  // src/core/verifyConfig.ts
54
54
  var verifyConfig = (_schema, configs) => {
55
- const validatePlugins = configs.plugins ?? [];
55
+ const validatePlugins = [
56
+ // Built-in validation configs (if provided as named keys)
57
+ ...configs.uniqueRow ? [configs.uniqueRow] : [],
58
+ ...configs.uniqueColumn ? [configs.uniqueColumn] : [],
59
+ // Additional plugins from the plugins array
60
+ ...configs.plugins ?? []
61
+ ];
56
62
  const insert = async (ctx, tableName, data, options) => {
57
63
  let verifiedData = data;
58
64
  if (configs.defaultValues) {
59
- verifiedData = await configs.defaultValues.verify(tableName, verifiedData);
65
+ verifiedData = await configs.defaultValues.verify(
66
+ tableName,
67
+ verifiedData
68
+ );
60
69
  }
61
70
  if (validatePlugins.length > 0) {
62
71
  verifiedData = await runValidatePlugins(