convex-verify 1.1.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -80
- package/dist/core/index.d.mts +14 -55
- package/dist/core/index.d.ts +14 -55
- package/dist/core/index.js +492 -92
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +491 -92
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -6
- package/dist/index.d.ts +9 -6
- package/dist/index.js +378 -271
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +378 -267
- package/dist/index.mjs.map +1 -1
- package/dist/types-B8ZkLuJ2.d.mts +141 -0
- package/dist/types-B8ZkLuJ2.d.ts +141 -0
- package/dist/utils/index.d.mts +3 -2
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/index.mjs.map +1 -1
- package/dist/verifyConfig-CTrtqMr_.d.ts +94 -0
- package/dist/verifyConfig-Kn3Ikj00.d.mts +94 -0
- package/package.json +1 -16
- package/dist/configs/index.d.mts +0 -51
- package/dist/configs/index.d.ts +0 -51
- package/dist/configs/index.js +0 -38
- package/dist/configs/index.js.map +0 -1
- package/dist/configs/index.mjs +0 -11
- package/dist/configs/index.mjs.map +0 -1
- package/dist/plugin-BOb1Kw1A.d.ts +0 -47
- package/dist/plugin-DlsboiCF.d.mts +0 -47
- package/dist/plugins/index.d.mts +0 -85
- package/dist/plugins/index.d.ts +0 -85
- package/dist/plugins/index.js +0 -312
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/index.mjs +0 -284
- package/dist/plugins/index.mjs.map +0 -1
- package/dist/transforms/index.d.mts +0 -38
- package/dist/transforms/index.d.ts +0 -38
- package/dist/transforms/index.js +0 -46
- package/dist/transforms/index.js.map +0 -1
- package/dist/transforms/index.mjs +0 -19
- package/dist/transforms/index.mjs.map +0 -1
- package/dist/types-DvJMYubf.d.mts +0 -151
- package/dist/types-DvJMYubf.d.ts +0 -151
package/dist/index.js
CHANGED
|
@@ -22,154 +22,17 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
constructColumnData: () => constructColumnData,
|
|
24
24
|
constructIndexData: () => constructIndexData,
|
|
25
|
-
createExtension: () =>
|
|
26
|
-
defaultValuesConfig: () => defaultValuesConfig,
|
|
25
|
+
createExtension: () => createExtension3,
|
|
27
26
|
getTableIndexes: () => getTableIndexes,
|
|
28
|
-
isExtension: () =>
|
|
27
|
+
isExtension: () => isExtension3,
|
|
29
28
|
normalizeIndexConfigEntry: () => normalizeIndexConfigEntry,
|
|
30
|
-
|
|
31
|
-
runExtensions: () => runExtensions,
|
|
32
|
-
uniqueColumnConfig: () => uniqueColumnConfig,
|
|
33
|
-
uniqueRowConfig: () => uniqueRowConfig,
|
|
29
|
+
runExtensions: () => runExtensions3,
|
|
34
30
|
verifyConfig: () => verifyConfig
|
|
35
31
|
});
|
|
36
32
|
module.exports = __toCommonJS(src_exports);
|
|
37
33
|
|
|
38
|
-
// src/core/
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
_type: "extension",
|
|
42
|
-
verify(input) {
|
|
43
|
-
return verify(input);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function isExtension(value) {
|
|
48
|
-
return typeof value === "object" && value !== null && "verify" in value && typeof value.verify === "function";
|
|
49
|
-
}
|
|
50
|
-
async function runExtensions(extensions, input) {
|
|
51
|
-
let verifiedData = input.data;
|
|
52
|
-
for (const extension of extensions) {
|
|
53
|
-
verifiedData = await extension.verify({
|
|
54
|
-
...input,
|
|
55
|
-
data: verifiedData
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
return verifiedData;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// src/core/verifyConfig.ts
|
|
62
|
-
var verifyConfig = (_schema, configs) => {
|
|
63
|
-
const customExtensions = configs.extensions ?? [];
|
|
64
|
-
const builtInExtensions = [
|
|
65
|
-
...configs.uniqueRow ? [configs.uniqueRow] : [],
|
|
66
|
-
...configs.uniqueColumn ? [configs.uniqueColumn] : []
|
|
67
|
-
];
|
|
68
|
-
const extensions = [...customExtensions, ...builtInExtensions];
|
|
69
|
-
const protectedColumns = configs.protectedColumns?.config ?? {};
|
|
70
|
-
const stripProtectedPatchColumns = (tableName, data) => {
|
|
71
|
-
const protectedKeys = protectedColumns[tableName] ?? [];
|
|
72
|
-
if (protectedKeys.length === 0) {
|
|
73
|
-
return {
|
|
74
|
-
filteredData: data,
|
|
75
|
-
removedColumns: []
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
const removedColumns = protectedKeys.filter((key) => key in data).map(String);
|
|
79
|
-
if (removedColumns.length === 0) {
|
|
80
|
-
return {
|
|
81
|
-
filteredData: data,
|
|
82
|
-
removedColumns
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const filteredData = Object.fromEntries(
|
|
86
|
-
Object.entries(data).filter(([key]) => !protectedKeys.includes(key))
|
|
87
|
-
);
|
|
88
|
-
return {
|
|
89
|
-
filteredData,
|
|
90
|
-
removedColumns
|
|
91
|
-
};
|
|
92
|
-
};
|
|
93
|
-
const insert = async (ctx, tableName, data, options) => {
|
|
94
|
-
let verifiedData = data;
|
|
95
|
-
if (configs.defaultValues) {
|
|
96
|
-
verifiedData = await configs.defaultValues.verify(tableName, verifiedData);
|
|
97
|
-
}
|
|
98
|
-
if (extensions.length > 0) {
|
|
99
|
-
verifiedData = await runExtensions(
|
|
100
|
-
extensions,
|
|
101
|
-
{
|
|
102
|
-
ctx,
|
|
103
|
-
tableName,
|
|
104
|
-
operation: "insert",
|
|
105
|
-
onFail: options?.onFail,
|
|
106
|
-
schema: _schema,
|
|
107
|
-
data: verifiedData
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
return await ctx.db.insert(tableName, verifiedData);
|
|
112
|
-
};
|
|
113
|
-
const patch = async (ctx, tableName, id, data, options) => {
|
|
114
|
-
let verifiedData = data;
|
|
115
|
-
const removedProtectedColumns = /* @__PURE__ */ new Set();
|
|
116
|
-
const stripProtectedColumns = () => {
|
|
117
|
-
const filtered = stripProtectedPatchColumns(tableName, verifiedData);
|
|
118
|
-
for (const column of filtered.removedColumns) {
|
|
119
|
-
removedProtectedColumns.add(column);
|
|
120
|
-
}
|
|
121
|
-
verifiedData = filtered.filteredData;
|
|
122
|
-
};
|
|
123
|
-
stripProtectedColumns();
|
|
124
|
-
if (extensions.length > 0) {
|
|
125
|
-
verifiedData = await runExtensions(
|
|
126
|
-
extensions,
|
|
127
|
-
{
|
|
128
|
-
ctx,
|
|
129
|
-
tableName,
|
|
130
|
-
operation: "patch",
|
|
131
|
-
patchId: id,
|
|
132
|
-
onFail: options?.onFail,
|
|
133
|
-
schema: _schema,
|
|
134
|
-
data: verifiedData
|
|
135
|
-
}
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
stripProtectedColumns();
|
|
139
|
-
if (removedProtectedColumns.size > 0) {
|
|
140
|
-
options?.onFail?.({
|
|
141
|
-
editableColumn: {
|
|
142
|
-
removedColumns: [...removedProtectedColumns],
|
|
143
|
-
filteredData: verifiedData
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
await ctx.db.patch(id, verifiedData);
|
|
148
|
-
};
|
|
149
|
-
const dangerouslyPatch = async (ctx, tableName, id, data, options) => {
|
|
150
|
-
let verifiedData = data;
|
|
151
|
-
if (extensions.length > 0) {
|
|
152
|
-
verifiedData = await runExtensions(
|
|
153
|
-
extensions,
|
|
154
|
-
{
|
|
155
|
-
ctx,
|
|
156
|
-
tableName,
|
|
157
|
-
operation: "patch",
|
|
158
|
-
patchId: id,
|
|
159
|
-
onFail: options?.onFail,
|
|
160
|
-
schema: _schema,
|
|
161
|
-
data: verifiedData
|
|
162
|
-
}
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
await ctx.db.patch(id, verifiedData);
|
|
166
|
-
};
|
|
167
|
-
return {
|
|
168
|
-
insert,
|
|
169
|
-
patch,
|
|
170
|
-
dangerouslyPatch
|
|
171
|
-
};
|
|
172
|
-
};
|
|
34
|
+
// src/core/builtins.ts
|
|
35
|
+
var import_values = require("convex/values");
|
|
173
36
|
|
|
174
37
|
// src/core/types.ts
|
|
175
38
|
function normalizeIndexConfigEntry(entry, defaultIdentifiers = ["_id"]) {
|
|
@@ -187,33 +50,6 @@ function normalizeIndexConfigEntry(entry, defaultIdentifiers = ["_id"]) {
|
|
|
187
50
|
};
|
|
188
51
|
}
|
|
189
52
|
|
|
190
|
-
// src/transforms/defaultValuesConfig.ts
|
|
191
|
-
var defaultValuesConfig = (_schema, config) => {
|
|
192
|
-
const verify = async (tableName, data) => {
|
|
193
|
-
const resolvedConfig = typeof config === "function" ? await config() : config;
|
|
194
|
-
return {
|
|
195
|
-
...resolvedConfig[tableName],
|
|
196
|
-
...data
|
|
197
|
-
};
|
|
198
|
-
};
|
|
199
|
-
return {
|
|
200
|
-
_type: "defaultValues",
|
|
201
|
-
verify,
|
|
202
|
-
config
|
|
203
|
-
};
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// src/configs/protectedColumnsConfig.ts
|
|
207
|
-
var protectedColumnsConfig = (_schema, config) => {
|
|
208
|
-
return {
|
|
209
|
-
_type: "protectedColumns",
|
|
210
|
-
config
|
|
211
|
-
};
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
// src/plugins/uniqueRowConfig.ts
|
|
215
|
-
var import_values = require("convex/values");
|
|
216
|
-
|
|
217
53
|
// src/utils/helpers.ts
|
|
218
54
|
var getTableIndexes = (schema, tableName) => {
|
|
219
55
|
return schema.tables[tableName][" indexes"]();
|
|
@@ -226,7 +62,7 @@ var constructColumnData = (fields, data, {
|
|
|
226
62
|
const columnData = fields.map((_, index) => {
|
|
227
63
|
const column = fields?.[index];
|
|
228
64
|
const value = data?.[column];
|
|
229
|
-
if (!column || !allowNullishValue &&
|
|
65
|
+
if (!column || !allowNullishValue && (value === void 0 || value === null)) {
|
|
230
66
|
return;
|
|
231
67
|
}
|
|
232
68
|
return {
|
|
@@ -270,37 +106,108 @@ var constructIndexData = (schema, tableName, indexConfig) => {
|
|
|
270
106
|
});
|
|
271
107
|
};
|
|
272
108
|
|
|
273
|
-
// src/
|
|
274
|
-
var
|
|
109
|
+
// src/core/builtins.ts
|
|
110
|
+
var stripProtectedPatchColumns = (protectedColumns, tableName, data) => {
|
|
111
|
+
const protectedKeys = protectedColumns[tableName] ?? [];
|
|
112
|
+
if (protectedKeys.length === 0) {
|
|
113
|
+
return {
|
|
114
|
+
filteredData: data,
|
|
115
|
+
removedColumns: []
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const protectedKeyStrings = protectedKeys.map(String);
|
|
119
|
+
const protectedKeySet = new Set(protectedKeyStrings);
|
|
120
|
+
const removedColumns = protectedKeyStrings.filter((key) => key in data);
|
|
121
|
+
if (removedColumns.length === 0) {
|
|
122
|
+
return {
|
|
123
|
+
filteredData: data,
|
|
124
|
+
removedColumns
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const filteredData = Object.fromEntries(
|
|
128
|
+
Object.entries(data).filter(([key]) => !protectedKeySet.has(key))
|
|
129
|
+
);
|
|
130
|
+
return {
|
|
131
|
+
filteredData,
|
|
132
|
+
removedColumns
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
var buildDefaultValuesVerifier = (config) => {
|
|
136
|
+
const verify = (async (...args) => {
|
|
137
|
+
const input = args.length === 2 ? {
|
|
138
|
+
tableName: args[0],
|
|
139
|
+
operation: "insert",
|
|
140
|
+
data: args[1]
|
|
141
|
+
} : args[0];
|
|
142
|
+
if (input.operation === "patch") {
|
|
143
|
+
return input.data;
|
|
144
|
+
}
|
|
145
|
+
const resolvedConfig = typeof config === "function" ? await config() : config;
|
|
146
|
+
return {
|
|
147
|
+
...resolvedConfig[input.tableName] ?? {},
|
|
148
|
+
...input.data
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
_type: "defaultValues",
|
|
153
|
+
config,
|
|
154
|
+
verify
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
var buildProtectedColumnsVerifier = (config) => {
|
|
158
|
+
const verify = (async (...args) => {
|
|
159
|
+
const input = args.length === 2 ? {
|
|
160
|
+
tableName: args[0],
|
|
161
|
+
operation: "patch",
|
|
162
|
+
data: args[1]
|
|
163
|
+
} : args[0];
|
|
164
|
+
if (input.operation === "insert") {
|
|
165
|
+
return input.data;
|
|
166
|
+
}
|
|
167
|
+
return stripProtectedPatchColumns(config, input.tableName, input.data).filteredData;
|
|
168
|
+
});
|
|
169
|
+
return {
|
|
170
|
+
_type: "protectedColumns",
|
|
171
|
+
config,
|
|
172
|
+
verify
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
var buildUniqueRowVerifier = (schema, config) => {
|
|
275
176
|
const uniqueRowError = (message) => {
|
|
276
177
|
throw new import_values.ConvexError({
|
|
277
178
|
message,
|
|
278
179
|
code: "UNIQUE_ROW_VERIFICATION_ERROR"
|
|
279
180
|
});
|
|
280
181
|
};
|
|
281
|
-
const
|
|
282
|
-
const
|
|
182
|
+
const verify = (async (...args) => {
|
|
183
|
+
const input = args.length === 3 ? {
|
|
184
|
+
ctx: args[0],
|
|
185
|
+
tableName: args[1],
|
|
186
|
+
operation: "insert",
|
|
187
|
+
data: args[2]
|
|
188
|
+
} : args.length === 4 ? {
|
|
189
|
+
ctx: args[0],
|
|
190
|
+
tableName: args[1],
|
|
191
|
+
operation: "patch",
|
|
192
|
+
patchId: args[2],
|
|
193
|
+
data: args[3]
|
|
194
|
+
} : args[0];
|
|
195
|
+
const { ctx, tableName, operation, patchId, onFail, data } = input;
|
|
283
196
|
const indexesData = constructIndexData(schema, tableName, config);
|
|
284
|
-
if (!indexesData && !!config[tableName]) {
|
|
285
|
-
uniqueRowError(`Index data was not found where there should have been.`);
|
|
286
|
-
}
|
|
287
197
|
if (!indexesData) {
|
|
288
198
|
return data;
|
|
289
199
|
}
|
|
290
200
|
for (const indexInfo of indexesData) {
|
|
291
|
-
const { name, fields, identifiers
|
|
292
|
-
|
|
293
|
-
if (!fields[0] && !fields[1]) {
|
|
201
|
+
const { name, fields, identifiers } = indexInfo;
|
|
202
|
+
if (fields.length < 2) {
|
|
294
203
|
uniqueRowError(
|
|
295
|
-
`Error in 'verifyRowUniqueness()'. There must be two columns to test against. If you are attempting to enforce a unique column, use the '
|
|
204
|
+
`Error in 'verifyRowUniqueness()'. There must be two columns to test against. If you are attempting to enforce a unique column, use the 'uniqueColumn' config option.`
|
|
296
205
|
);
|
|
297
206
|
}
|
|
298
207
|
const columnData = constructColumnData(fields, data, {});
|
|
299
208
|
const getExisting = async (cd) => {
|
|
300
209
|
let existingByIndex = [];
|
|
301
|
-
if (
|
|
302
|
-
existingByIndex = [];
|
|
303
|
-
} else {
|
|
210
|
+
if (cd) {
|
|
304
211
|
existingByIndex = await ctx.db.query(tableName).withIndex(
|
|
305
212
|
name,
|
|
306
213
|
(q) => cd.reduce((query, { column, value }) => query.eq(column, value), q)
|
|
@@ -309,10 +216,10 @@ var uniqueRowConfig = (schema, config) => {
|
|
|
309
216
|
if (existingByIndex.length > 1) {
|
|
310
217
|
console.warn(
|
|
311
218
|
`There was more than one existing result found for index ${name}. Check the following IDs:`,
|
|
312
|
-
existingByIndex.map((
|
|
219
|
+
existingByIndex.map((row) => row._id)
|
|
313
220
|
);
|
|
314
221
|
console.warn(
|
|
315
|
-
|
|
222
|
+
"It is recommended that you triage the rows listed above since they have data that go against a rule of row uniqueness."
|
|
316
223
|
);
|
|
317
224
|
}
|
|
318
225
|
return existingByIndex.length > 0 ? existingByIndex[0] : null;
|
|
@@ -328,95 +235,89 @@ var uniqueRowConfig = (schema, config) => {
|
|
|
328
235
|
}
|
|
329
236
|
});
|
|
330
237
|
uniqueRowError(
|
|
331
|
-
`Unable to [${operation}] document. In table [${tableName}], there is an existing row that has the same data combination in the columns: [${fields.join(
|
|
238
|
+
`Unable to [${operation}] document. In table [${tableName}], there is an existing row that has the same data combination in the columns: [${fields.join(", ")}].`
|
|
332
239
|
);
|
|
333
240
|
}
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
241
|
+
if (!patchId) {
|
|
242
|
+
uniqueRowError("Unable to patch document without an id.");
|
|
243
|
+
}
|
|
244
|
+
const matchedToExisting = (_existing, _data) => {
|
|
245
|
+
let idMatchedToExisting = null;
|
|
246
|
+
if (_existing) {
|
|
247
|
+
for (const identifier of identifiers) {
|
|
248
|
+
if (_existing[identifier] !== void 0 && _data[identifier] !== void 0 && _existing[identifier] === _data[identifier] || identifier === "_id" && _existing[identifier] === patchId) {
|
|
249
|
+
idMatchedToExisting = String(identifier);
|
|
250
|
+
break;
|
|
346
251
|
}
|
|
347
252
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
uniqueRow: {
|
|
360
|
-
existingData: _existing
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
uniqueRowError(
|
|
364
|
-
`In '${tableName}' table, there already exists a value match of the columns: [${fields.join(`,`)}].`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
if (!existing && !columnData && patchId) {
|
|
369
|
-
const match = await ctx.db.get(patchId);
|
|
370
|
-
if (!match) {
|
|
371
|
-
uniqueRowError(`No document found for id ${patchId}`);
|
|
372
|
-
return data;
|
|
373
|
-
}
|
|
374
|
-
const extensiveColumnData = constructColumnData(
|
|
375
|
-
fields,
|
|
376
|
-
{
|
|
377
|
-
...match,
|
|
378
|
-
...data
|
|
379
|
-
},
|
|
380
|
-
{}
|
|
381
|
-
);
|
|
382
|
-
if (extensiveColumnData) {
|
|
383
|
-
const extensiveExisting = await getExisting(extensiveColumnData);
|
|
384
|
-
checkExisting(extensiveExisting, data);
|
|
385
|
-
} else {
|
|
386
|
-
uniqueRowError(`Incomplete data when there should have been enough.`);
|
|
253
|
+
}
|
|
254
|
+
return idMatchedToExisting;
|
|
255
|
+
};
|
|
256
|
+
const checkExisting = (_existing, _data) => {
|
|
257
|
+
const matchedId = matchedToExisting(_existing, _data);
|
|
258
|
+
if (!_existing || matchedId) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
onFail?.({
|
|
262
|
+
uniqueRow: {
|
|
263
|
+
existingData: _existing
|
|
387
264
|
}
|
|
388
|
-
}
|
|
389
|
-
|
|
265
|
+
});
|
|
266
|
+
uniqueRowError(
|
|
267
|
+
`In '${tableName}' table, there already exists a value match of the columns: [${fields.join(",")}].`
|
|
268
|
+
);
|
|
269
|
+
};
|
|
270
|
+
if (!existing && !columnData) {
|
|
271
|
+
const match = await ctx.db.get(patchId);
|
|
272
|
+
if (!match) {
|
|
273
|
+
uniqueRowError(`No document found for id ${patchId}`);
|
|
274
|
+
}
|
|
275
|
+
const extensiveColumnData = constructColumnData(
|
|
276
|
+
fields,
|
|
277
|
+
{
|
|
278
|
+
...match,
|
|
279
|
+
...data
|
|
280
|
+
},
|
|
281
|
+
{}
|
|
282
|
+
);
|
|
283
|
+
if (!extensiveColumnData) {
|
|
284
|
+
uniqueRowError("Incomplete data when there should have been enough.");
|
|
390
285
|
}
|
|
286
|
+
const extensiveExisting = await getExisting(extensiveColumnData);
|
|
287
|
+
checkExisting(extensiveExisting, data);
|
|
288
|
+
continue;
|
|
391
289
|
}
|
|
290
|
+
checkExisting(existing, data);
|
|
392
291
|
}
|
|
393
292
|
return data;
|
|
394
|
-
};
|
|
395
|
-
|
|
293
|
+
});
|
|
294
|
+
return {
|
|
396
295
|
_type: "uniqueRow",
|
|
397
296
|
config,
|
|
398
|
-
|
|
399
|
-
return await verifyUniqueness(
|
|
400
|
-
input,
|
|
401
|
-
input.data,
|
|
402
|
-
input.tableName
|
|
403
|
-
);
|
|
404
|
-
}
|
|
297
|
+
verify
|
|
405
298
|
};
|
|
406
|
-
return extension;
|
|
407
299
|
};
|
|
408
|
-
|
|
409
|
-
// src/plugins/uniqueColumnConfig.ts
|
|
410
|
-
var import_values2 = require("convex/values");
|
|
411
|
-
var uniqueColumnConfig = (_schema, config) => {
|
|
300
|
+
var buildUniqueColumnVerifier = (config) => {
|
|
412
301
|
const uniqueColumnError = (message) => {
|
|
413
|
-
throw new
|
|
302
|
+
throw new import_values.ConvexError({
|
|
414
303
|
message,
|
|
415
304
|
code: "UNIQUE_COLUMN_VERIFICATION_ERROR"
|
|
416
305
|
});
|
|
417
306
|
};
|
|
418
|
-
const
|
|
419
|
-
const
|
|
307
|
+
const verify = (async (...args) => {
|
|
308
|
+
const input = args.length === 3 ? {
|
|
309
|
+
ctx: args[0],
|
|
310
|
+
tableName: args[1],
|
|
311
|
+
operation: "insert",
|
|
312
|
+
data: args[2]
|
|
313
|
+
} : args.length === 4 ? {
|
|
314
|
+
ctx: args[0],
|
|
315
|
+
tableName: args[1],
|
|
316
|
+
operation: "patch",
|
|
317
|
+
patchId: args[2],
|
|
318
|
+
data: args[3]
|
|
319
|
+
} : args[0];
|
|
320
|
+
const { ctx, tableName, patchId, onFail, data } = input;
|
|
420
321
|
const tableConfig = config[tableName];
|
|
421
322
|
if (!tableConfig) {
|
|
422
323
|
return data;
|
|
@@ -440,9 +341,7 @@ var uniqueColumnConfig = (_schema, config) => {
|
|
|
440
341
|
isOwnDocument = true;
|
|
441
342
|
break;
|
|
442
343
|
}
|
|
443
|
-
|
|
444
|
-
const incomingValue = data[identifier];
|
|
445
|
-
if (existingValue !== void 0 && incomingValue !== void 0 && existingValue === incomingValue) {
|
|
344
|
+
if (existing[identifier] !== void 0 && data[identifier] !== void 0 && existing[identifier] === data[identifier]) {
|
|
446
345
|
isOwnDocument = true;
|
|
447
346
|
break;
|
|
448
347
|
}
|
|
@@ -461,32 +360,240 @@ var uniqueColumnConfig = (_schema, config) => {
|
|
|
461
360
|
);
|
|
462
361
|
}
|
|
463
362
|
return data;
|
|
464
|
-
};
|
|
465
|
-
|
|
363
|
+
});
|
|
364
|
+
return {
|
|
466
365
|
_type: "uniqueColumn",
|
|
467
366
|
config,
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
367
|
+
verify
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// src/core/plugin.ts
|
|
372
|
+
function createExtension(schemaOrVerify, verify) {
|
|
373
|
+
const extensionVerify = typeof verify === "function" ? verify : schemaOrVerify;
|
|
374
|
+
return {
|
|
375
|
+
_type: "extension",
|
|
376
|
+
verify(input) {
|
|
377
|
+
return extensionVerify(input);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function isExtension(value) {
|
|
382
|
+
return typeof value === "object" && value !== null && "verify" in value && typeof value.verify === "function";
|
|
383
|
+
}
|
|
384
|
+
async function runExtensions(extensions, input) {
|
|
385
|
+
let verifiedData = input.data;
|
|
386
|
+
for (const extension of extensions) {
|
|
387
|
+
verifiedData = await extension.verify({
|
|
388
|
+
...input,
|
|
389
|
+
data: verifiedData
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
return verifiedData;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/core/verifyConfig.ts
|
|
396
|
+
var verifyConfig = (_schema, configs) => {
|
|
397
|
+
const builtins = {
|
|
398
|
+
...configs.defaultValues ? {
|
|
399
|
+
defaultValues: buildDefaultValuesVerifier(configs.defaultValues)
|
|
400
|
+
} : {},
|
|
401
|
+
...configs.protectedColumns ? {
|
|
402
|
+
protectedColumns: buildProtectedColumnsVerifier(configs.protectedColumns)
|
|
403
|
+
} : {},
|
|
404
|
+
...configs.uniqueRow ? {
|
|
405
|
+
uniqueRow: buildUniqueRowVerifier(
|
|
406
|
+
_schema,
|
|
407
|
+
configs.uniqueRow
|
|
408
|
+
)
|
|
409
|
+
} : {},
|
|
410
|
+
...configs.uniqueColumn ? {
|
|
411
|
+
uniqueColumn: buildUniqueColumnVerifier(configs.uniqueColumn)
|
|
412
|
+
} : {}
|
|
413
|
+
};
|
|
414
|
+
const verify = {
|
|
415
|
+
...builtins.defaultValues ? { defaultValues: builtins.defaultValues.verify } : {},
|
|
416
|
+
...builtins.protectedColumns ? { protectedColumns: builtins.protectedColumns.verify } : {},
|
|
417
|
+
...builtins.uniqueRow ? { uniqueRow: builtins.uniqueRow.verify } : {},
|
|
418
|
+
...builtins.uniqueColumn ? { uniqueColumn: builtins.uniqueColumn.verify } : {}
|
|
419
|
+
};
|
|
420
|
+
const config = {
|
|
421
|
+
...configs.defaultValues ? { defaultValues: configs.defaultValues } : {},
|
|
422
|
+
...configs.protectedColumns ? { protectedColumns: configs.protectedColumns } : {},
|
|
423
|
+
...configs.uniqueRow ? { uniqueRow: configs.uniqueRow } : {},
|
|
424
|
+
...configs.uniqueColumn ? { uniqueColumn: configs.uniqueColumn } : {}
|
|
425
|
+
};
|
|
426
|
+
const customExtensions = configs.extensions ?? [];
|
|
427
|
+
const insert = async (ctx, tableName, data, options) => {
|
|
428
|
+
let verifiedData = data;
|
|
429
|
+
if (builtins.defaultValues) {
|
|
430
|
+
verifiedData = await builtins.defaultValues.verify({
|
|
431
|
+
ctx,
|
|
432
|
+
tableName,
|
|
433
|
+
operation: "insert",
|
|
434
|
+
onFail: options?.onFail,
|
|
435
|
+
schema: _schema,
|
|
436
|
+
data: verifiedData
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
if (customExtensions.length > 0) {
|
|
440
|
+
verifiedData = await runExtensions(customExtensions, {
|
|
441
|
+
ctx,
|
|
442
|
+
tableName,
|
|
443
|
+
operation: "insert",
|
|
444
|
+
onFail: options?.onFail,
|
|
445
|
+
schema: _schema,
|
|
446
|
+
data: verifiedData
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
if (builtins.uniqueRow) {
|
|
450
|
+
verifiedData = await builtins.uniqueRow.verify({
|
|
451
|
+
ctx,
|
|
452
|
+
tableName,
|
|
453
|
+
operation: "insert",
|
|
454
|
+
onFail: options?.onFail,
|
|
455
|
+
schema: _schema,
|
|
456
|
+
data: verifiedData
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
if (builtins.uniqueColumn) {
|
|
460
|
+
verifiedData = await builtins.uniqueColumn.verify({
|
|
461
|
+
ctx,
|
|
462
|
+
tableName,
|
|
463
|
+
operation: "insert",
|
|
464
|
+
onFail: options?.onFail,
|
|
465
|
+
schema: _schema,
|
|
466
|
+
data: verifiedData
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
return await ctx.db.insert(tableName, verifiedData);
|
|
470
|
+
};
|
|
471
|
+
const patch = async (ctx, tableName, id, data, options) => {
|
|
472
|
+
let verifiedData = data;
|
|
473
|
+
const removedProtectedColumns = /* @__PURE__ */ new Set();
|
|
474
|
+
const stripProtectedColumns = () => {
|
|
475
|
+
if (!builtins.protectedColumns) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const filtered = stripProtectedPatchColumns(
|
|
479
|
+
builtins.protectedColumns.config,
|
|
480
|
+
tableName,
|
|
481
|
+
verifiedData
|
|
472
482
|
);
|
|
483
|
+
for (const column of filtered.removedColumns) {
|
|
484
|
+
removedProtectedColumns.add(column);
|
|
485
|
+
}
|
|
486
|
+
verifiedData = filtered.filteredData;
|
|
487
|
+
};
|
|
488
|
+
stripProtectedColumns();
|
|
489
|
+
if (customExtensions.length > 0) {
|
|
490
|
+
verifiedData = await runExtensions(customExtensions, {
|
|
491
|
+
ctx,
|
|
492
|
+
tableName,
|
|
493
|
+
operation: "patch",
|
|
494
|
+
patchId: id,
|
|
495
|
+
onFail: options?.onFail,
|
|
496
|
+
schema: _schema,
|
|
497
|
+
data: verifiedData
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
if (builtins.uniqueRow) {
|
|
501
|
+
verifiedData = await builtins.uniqueRow.verify({
|
|
502
|
+
ctx,
|
|
503
|
+
tableName,
|
|
504
|
+
operation: "patch",
|
|
505
|
+
patchId: id,
|
|
506
|
+
onFail: options?.onFail,
|
|
507
|
+
schema: _schema,
|
|
508
|
+
data: verifiedData
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
if (builtins.uniqueColumn) {
|
|
512
|
+
verifiedData = await builtins.uniqueColumn.verify({
|
|
513
|
+
ctx,
|
|
514
|
+
tableName,
|
|
515
|
+
operation: "patch",
|
|
516
|
+
patchId: id,
|
|
517
|
+
onFail: options?.onFail,
|
|
518
|
+
schema: _schema,
|
|
519
|
+
data: verifiedData
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
stripProtectedColumns();
|
|
523
|
+
if (removedProtectedColumns.size > 0) {
|
|
524
|
+
options?.onFail?.({
|
|
525
|
+
editableColumn: {
|
|
526
|
+
removedColumns: [...removedProtectedColumns],
|
|
527
|
+
filteredData: verifiedData
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
await ctx.db.patch(id, verifiedData);
|
|
532
|
+
};
|
|
533
|
+
const dangerouslyPatch = async (ctx, tableName, id, data, options) => {
|
|
534
|
+
let verifiedData = data;
|
|
535
|
+
if (customExtensions.length > 0) {
|
|
536
|
+
verifiedData = await runExtensions(customExtensions, {
|
|
537
|
+
ctx,
|
|
538
|
+
tableName,
|
|
539
|
+
operation: "patch",
|
|
540
|
+
patchId: id,
|
|
541
|
+
onFail: options?.onFail,
|
|
542
|
+
schema: _schema,
|
|
543
|
+
data: verifiedData
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
if (builtins.uniqueRow) {
|
|
547
|
+
verifiedData = await builtins.uniqueRow.verify({
|
|
548
|
+
ctx,
|
|
549
|
+
tableName,
|
|
550
|
+
operation: "patch",
|
|
551
|
+
patchId: id,
|
|
552
|
+
onFail: options?.onFail,
|
|
553
|
+
schema: _schema,
|
|
554
|
+
data: verifiedData
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
if (builtins.uniqueColumn) {
|
|
558
|
+
verifiedData = await builtins.uniqueColumn.verify({
|
|
559
|
+
ctx,
|
|
560
|
+
tableName,
|
|
561
|
+
operation: "patch",
|
|
562
|
+
patchId: id,
|
|
563
|
+
onFail: options?.onFail,
|
|
564
|
+
schema: _schema,
|
|
565
|
+
data: verifiedData
|
|
566
|
+
});
|
|
473
567
|
}
|
|
568
|
+
await ctx.db.patch(id, verifiedData);
|
|
569
|
+
};
|
|
570
|
+
return {
|
|
571
|
+
insert,
|
|
572
|
+
patch,
|
|
573
|
+
dangerouslyPatch,
|
|
574
|
+
verify,
|
|
575
|
+
config
|
|
474
576
|
};
|
|
475
|
-
return extension;
|
|
476
577
|
};
|
|
578
|
+
|
|
579
|
+
// src/core/index.ts
|
|
580
|
+
var createExtension2 = createExtension;
|
|
581
|
+
var isExtension2 = isExtension;
|
|
582
|
+
var runExtensions2 = runExtensions;
|
|
583
|
+
|
|
584
|
+
// src/index.ts
|
|
585
|
+
var createExtension3 = createExtension2;
|
|
586
|
+
var isExtension3 = isExtension2;
|
|
587
|
+
var runExtensions3 = runExtensions2;
|
|
477
588
|
// Annotate the CommonJS export names for ESM import in node:
|
|
478
589
|
0 && (module.exports = {
|
|
479
590
|
constructColumnData,
|
|
480
591
|
constructIndexData,
|
|
481
592
|
createExtension,
|
|
482
|
-
defaultValuesConfig,
|
|
483
593
|
getTableIndexes,
|
|
484
594
|
isExtension,
|
|
485
595
|
normalizeIndexConfigEntry,
|
|
486
|
-
protectedColumnsConfig,
|
|
487
596
|
runExtensions,
|
|
488
|
-
uniqueColumnConfig,
|
|
489
|
-
uniqueRowConfig,
|
|
490
597
|
verifyConfig
|
|
491
598
|
});
|
|
492
599
|
//# sourceMappingURL=index.js.map
|