@zodmon/core 0.9.0 → 0.11.0
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/index.cjs +545 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +842 -134
- package/dist/index.d.ts +842 -134
- package/dist/index.js +516 -146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -49,8 +49,18 @@ __export(index_exports, {
|
|
|
49
49
|
Database: () => Database,
|
|
50
50
|
IndexBuilder: () => IndexBuilder,
|
|
51
51
|
TypedFindCursor: () => TypedFindCursor,
|
|
52
|
+
ZodmonAuthError: () => ZodmonAuthError,
|
|
53
|
+
ZodmonBulkWriteError: () => ZodmonBulkWriteError,
|
|
54
|
+
ZodmonDocValidationError: () => ZodmonDocValidationError,
|
|
55
|
+
ZodmonDuplicateKeyError: () => ZodmonDuplicateKeyError,
|
|
56
|
+
ZodmonError: () => ZodmonError,
|
|
57
|
+
ZodmonIndexError: () => ZodmonIndexError,
|
|
58
|
+
ZodmonNetworkError: () => ZodmonNetworkError,
|
|
52
59
|
ZodmonNotFoundError: () => ZodmonNotFoundError,
|
|
60
|
+
ZodmonQueryError: () => ZodmonQueryError,
|
|
61
|
+
ZodmonTimeoutError: () => ZodmonTimeoutError,
|
|
53
62
|
ZodmonValidationError: () => ZodmonValidationError,
|
|
63
|
+
ZodmonWriteConflictError: () => ZodmonWriteConflictError,
|
|
54
64
|
aggregate: () => aggregate,
|
|
55
65
|
checkUnindexedFields: () => checkUnindexedFields,
|
|
56
66
|
collection: () => collection,
|
|
@@ -59,6 +69,7 @@ __export(index_exports, {
|
|
|
59
69
|
createExpressionBuilder: () => createExpressionBuilder,
|
|
60
70
|
deleteMany: () => deleteMany,
|
|
61
71
|
deleteOne: () => deleteOne,
|
|
72
|
+
deriveProjectedSchema: () => deriveProjectedSchema,
|
|
62
73
|
extractComparableOptions: () => extractComparableOptions,
|
|
63
74
|
extractDbName: () => extractDbName,
|
|
64
75
|
extractFieldIndexes: () => extractFieldIndexes,
|
|
@@ -73,6 +84,7 @@ __export(index_exports, {
|
|
|
73
84
|
index: () => index,
|
|
74
85
|
insertMany: () => insertMany,
|
|
75
86
|
insertOne: () => insertOne,
|
|
87
|
+
isInclusionProjection: () => isInclusionProjection,
|
|
76
88
|
isOid: () => isOid,
|
|
77
89
|
objectId: () => objectId,
|
|
78
90
|
oid: () => oid,
|
|
@@ -82,7 +94,8 @@ __export(index_exports, {
|
|
|
82
94
|
toCompoundIndexSpec: () => toCompoundIndexSpec,
|
|
83
95
|
toFieldIndexSpec: () => toFieldIndexSpec,
|
|
84
96
|
updateMany: () => updateMany,
|
|
85
|
-
updateOne: () => updateOne
|
|
97
|
+
updateOne: () => updateOne,
|
|
98
|
+
wrapMongoError: () => wrapMongoError
|
|
86
99
|
});
|
|
87
100
|
module.exports = __toCommonJS(index_exports);
|
|
88
101
|
|
|
@@ -99,30 +112,24 @@ var $avg = (field) => ({
|
|
|
99
112
|
__accum: true,
|
|
100
113
|
expr: { $avg: field }
|
|
101
114
|
});
|
|
102
|
-
|
|
103
|
-
__accum: true,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
expr: { $
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
__accum: true,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
expr: { $push: field }
|
|
121
|
-
});
|
|
122
|
-
var $addToSet = (field) => ({
|
|
123
|
-
__accum: true,
|
|
124
|
-
expr: { $addToSet: field }
|
|
125
|
-
});
|
|
115
|
+
function $min(field) {
|
|
116
|
+
return { __accum: true, expr: { $min: field } };
|
|
117
|
+
}
|
|
118
|
+
function $max(field) {
|
|
119
|
+
return { __accum: true, expr: { $max: field } };
|
|
120
|
+
}
|
|
121
|
+
function $first(field) {
|
|
122
|
+
return { __accum: true, expr: { $first: field } };
|
|
123
|
+
}
|
|
124
|
+
function $last(field) {
|
|
125
|
+
return { __accum: true, expr: { $last: field } };
|
|
126
|
+
}
|
|
127
|
+
function $push(field) {
|
|
128
|
+
return { __accum: true, expr: { $push: field } };
|
|
129
|
+
}
|
|
130
|
+
function $addToSet(field) {
|
|
131
|
+
return { __accum: true, expr: { $addToSet: field } };
|
|
132
|
+
}
|
|
126
133
|
function createAccumulatorBuilder() {
|
|
127
134
|
return {
|
|
128
135
|
count: () => ({ __accum: true, expr: { $sum: 1 } }),
|
|
@@ -187,6 +194,245 @@ function createExpressionBuilder() {
|
|
|
187
194
|
};
|
|
188
195
|
}
|
|
189
196
|
|
|
197
|
+
// src/errors/wrap.ts
|
|
198
|
+
var import_mongodb = require("mongodb");
|
|
199
|
+
|
|
200
|
+
// src/errors/base.ts
|
|
201
|
+
var ZodmonError = class extends Error {
|
|
202
|
+
name = "ZodmonError";
|
|
203
|
+
/** The MongoDB collection name associated with this error. */
|
|
204
|
+
collection;
|
|
205
|
+
/** The underlying error that caused this error, if any. */
|
|
206
|
+
cause;
|
|
207
|
+
constructor(message, collection2, options) {
|
|
208
|
+
super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
209
|
+
this.collection = collection2;
|
|
210
|
+
if (options?.cause !== void 0) {
|
|
211
|
+
this.cause = options.cause;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/errors/auth.ts
|
|
217
|
+
var ZodmonAuthError = class extends ZodmonError {
|
|
218
|
+
name = "ZodmonAuthError";
|
|
219
|
+
/** The MongoDB error code (13 or 18). */
|
|
220
|
+
code;
|
|
221
|
+
constructor(collection2, code, cause) {
|
|
222
|
+
const message = code === 18 ? `Authentication failed for "${collection2}": check connection credentials` : `Not authorized to perform this operation on "${collection2}"`;
|
|
223
|
+
super(message, collection2, { cause });
|
|
224
|
+
this.code = code;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/errors/bulk-write.ts
|
|
229
|
+
var ZodmonBulkWriteError = class extends ZodmonError {
|
|
230
|
+
name = "ZodmonBulkWriteError";
|
|
231
|
+
/** Number of documents successfully inserted. */
|
|
232
|
+
insertedCount;
|
|
233
|
+
/** Number of documents matched by update filters. */
|
|
234
|
+
matchedCount;
|
|
235
|
+
/** Number of documents actually modified. */
|
|
236
|
+
modifiedCount;
|
|
237
|
+
/** Number of documents deleted. */
|
|
238
|
+
deletedCount;
|
|
239
|
+
/** Individual write errors with their operation index, code, and message. */
|
|
240
|
+
writeErrors;
|
|
241
|
+
constructor(collection2, cause, totalOps) {
|
|
242
|
+
const bulkErr = cause;
|
|
243
|
+
const result = bulkErr["result"] ?? {};
|
|
244
|
+
const rawErrors = bulkErr["writeErrors"] ?? [];
|
|
245
|
+
const writeErrors = rawErrors.map((e) => ({
|
|
246
|
+
index: e["index"] ?? 0,
|
|
247
|
+
code: e["code"] ?? 0,
|
|
248
|
+
message: e["errmsg"] ?? e["message"] ?? "unknown error"
|
|
249
|
+
}));
|
|
250
|
+
const failedMsg = totalOps !== void 0 ? `${writeErrors.length} of ${totalOps} operations failed` : `${writeErrors.length} operations failed`;
|
|
251
|
+
super(`Bulk write failed on "${collection2}": ${failedMsg}`, collection2, { cause });
|
|
252
|
+
this.insertedCount = result["insertedCount"] ?? 0;
|
|
253
|
+
this.matchedCount = result["matchedCount"] ?? 0;
|
|
254
|
+
this.modifiedCount = result["modifiedCount"] ?? 0;
|
|
255
|
+
this.deletedCount = result["deletedCount"] ?? 0;
|
|
256
|
+
this.writeErrors = writeErrors;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// src/errors/doc-validation.ts
|
|
261
|
+
var ZodmonDocValidationError = class extends ZodmonError {
|
|
262
|
+
name = "ZodmonDocValidationError";
|
|
263
|
+
/** Server-provided validation failure details. */
|
|
264
|
+
errInfo;
|
|
265
|
+
constructor(collection2, errInfo, cause) {
|
|
266
|
+
super(
|
|
267
|
+
`Server-side document validation failed for "${collection2}": ${cause.message}`,
|
|
268
|
+
collection2,
|
|
269
|
+
{ cause }
|
|
270
|
+
);
|
|
271
|
+
this.errInfo = errInfo;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// src/errors/duplicate-key.ts
|
|
276
|
+
var INDEX_REGEX = /index:\s+(\S+)/;
|
|
277
|
+
var DUP_KEY_FIELD_REGEX = /dup key:\s*\{\s*(\w+):/;
|
|
278
|
+
var ZodmonDuplicateKeyError = class extends ZodmonError {
|
|
279
|
+
name = "ZodmonDuplicateKeyError";
|
|
280
|
+
/** The first field that caused the duplicate key violation. */
|
|
281
|
+
field;
|
|
282
|
+
/** The duplicate value, or `undefined` if it could not be extracted. */
|
|
283
|
+
value;
|
|
284
|
+
/** The name of the index that was violated. */
|
|
285
|
+
index;
|
|
286
|
+
/** The key pattern of the violated index (e.g. `{ email: 1 }`). */
|
|
287
|
+
keyPattern;
|
|
288
|
+
/** The key values that caused the violation. */
|
|
289
|
+
keyValue;
|
|
290
|
+
constructor(collection2, cause) {
|
|
291
|
+
const serverErr = cause;
|
|
292
|
+
const kp = serverErr["keyPattern"];
|
|
293
|
+
const kv = serverErr["keyValue"];
|
|
294
|
+
let field;
|
|
295
|
+
let value;
|
|
296
|
+
let keyPattern;
|
|
297
|
+
let keyValue;
|
|
298
|
+
if (kp && kv) {
|
|
299
|
+
const firstKey = Object.keys(kp)[0] ?? "unknown";
|
|
300
|
+
field = firstKey;
|
|
301
|
+
value = kv[firstKey];
|
|
302
|
+
keyPattern = kp;
|
|
303
|
+
keyValue = kv;
|
|
304
|
+
} else {
|
|
305
|
+
const fieldMatch = cause.message.match(DUP_KEY_FIELD_REGEX);
|
|
306
|
+
field = fieldMatch?.[1] ?? "unknown";
|
|
307
|
+
value = void 0;
|
|
308
|
+
keyPattern = field !== "unknown" ? { [field]: 1 } : {};
|
|
309
|
+
keyValue = {};
|
|
310
|
+
}
|
|
311
|
+
const indexMatch = cause.message.match(INDEX_REGEX);
|
|
312
|
+
const index2 = indexMatch?.[1] ?? "unknown";
|
|
313
|
+
const valueStr = typeof value === "string" ? `"${value}"` : String(value);
|
|
314
|
+
super(
|
|
315
|
+
`Duplicate key in "${collection2}": ${field} = ${valueStr} (index: ${index2})`,
|
|
316
|
+
collection2,
|
|
317
|
+
{ cause }
|
|
318
|
+
);
|
|
319
|
+
this.field = field;
|
|
320
|
+
this.value = value;
|
|
321
|
+
this.index = index2;
|
|
322
|
+
this.keyPattern = keyPattern;
|
|
323
|
+
this.keyValue = keyValue;
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// src/errors/index-error.ts
|
|
328
|
+
var ZodmonIndexError = class extends ZodmonError {
|
|
329
|
+
name = "ZodmonIndexError";
|
|
330
|
+
/** The MongoDB error code (67, 85, or 86). */
|
|
331
|
+
code;
|
|
332
|
+
constructor(collection2, code, errmsg, cause) {
|
|
333
|
+
const prefix = code === 67 ? "Cannot create index" : code === 85 ? "Index options conflict" : "Index key specs conflict";
|
|
334
|
+
super(`${prefix} on "${collection2}": ${errmsg}`, collection2, { cause });
|
|
335
|
+
this.code = code;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// src/errors/network.ts
|
|
340
|
+
var ZodmonNetworkError = class extends ZodmonError {
|
|
341
|
+
name = "ZodmonNetworkError";
|
|
342
|
+
constructor(collection2, cause) {
|
|
343
|
+
super(`Network error on "${collection2}": ${cause.message}`, collection2, { cause });
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/errors/query.ts
|
|
348
|
+
var ZodmonQueryError = class extends ZodmonError {
|
|
349
|
+
name = "ZodmonQueryError";
|
|
350
|
+
/** The MongoDB error code (2, 9, or 292). */
|
|
351
|
+
code;
|
|
352
|
+
constructor(collection2, code, errmsg, cause) {
|
|
353
|
+
const message = code === 292 ? `Query exceeded memory limit on "${collection2}": enable allowDiskUse for large sorts or aggregations` : code === 9 ? `Failed to parse query on "${collection2}": ${errmsg}` : `Bad value in query on "${collection2}": ${errmsg}`;
|
|
354
|
+
super(message, collection2, { cause });
|
|
355
|
+
this.code = code;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// src/errors/timeout.ts
|
|
360
|
+
var ZodmonTimeoutError = class extends ZodmonError {
|
|
361
|
+
name = "ZodmonTimeoutError";
|
|
362
|
+
/** The MongoDB error code (50 or 262). */
|
|
363
|
+
code;
|
|
364
|
+
constructor(collection2, code, cause) {
|
|
365
|
+
super(`Operation timed out on "${collection2}": exceeded server time limit`, collection2, {
|
|
366
|
+
cause
|
|
367
|
+
});
|
|
368
|
+
this.code = code;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// src/errors/write-conflict.ts
|
|
373
|
+
var ZodmonWriteConflictError = class extends ZodmonError {
|
|
374
|
+
name = "ZodmonWriteConflictError";
|
|
375
|
+
constructor(collection2, cause) {
|
|
376
|
+
super(
|
|
377
|
+
`Write conflict in "${collection2}": another operation modified this document concurrently \u2014 retry the transaction`,
|
|
378
|
+
collection2,
|
|
379
|
+
{ cause }
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// src/errors/wrap.ts
|
|
385
|
+
function wrapMongoError(err, collection2) {
|
|
386
|
+
if (err instanceof ZodmonError) {
|
|
387
|
+
throw err;
|
|
388
|
+
}
|
|
389
|
+
if (err instanceof import_mongodb.MongoBulkWriteError) {
|
|
390
|
+
throw new ZodmonBulkWriteError(collection2, err);
|
|
391
|
+
}
|
|
392
|
+
if (err instanceof import_mongodb.MongoNetworkError) {
|
|
393
|
+
throw new ZodmonNetworkError(collection2, err);
|
|
394
|
+
}
|
|
395
|
+
if (err instanceof import_mongodb.MongoServerError) {
|
|
396
|
+
switch (err.code) {
|
|
397
|
+
case 11e3:
|
|
398
|
+
case 11001:
|
|
399
|
+
throw new ZodmonDuplicateKeyError(collection2, err);
|
|
400
|
+
case 112:
|
|
401
|
+
throw new ZodmonWriteConflictError(collection2, err);
|
|
402
|
+
case 50:
|
|
403
|
+
case 262:
|
|
404
|
+
throw new ZodmonTimeoutError(collection2, err.code, err);
|
|
405
|
+
case 13:
|
|
406
|
+
case 18:
|
|
407
|
+
throw new ZodmonAuthError(collection2, err.code, err);
|
|
408
|
+
case 67:
|
|
409
|
+
case 85:
|
|
410
|
+
case 86:
|
|
411
|
+
throw new ZodmonIndexError(collection2, err.code, err.message, err);
|
|
412
|
+
case 2:
|
|
413
|
+
case 9:
|
|
414
|
+
case 292:
|
|
415
|
+
throw new ZodmonQueryError(collection2, err.code, err.message, err);
|
|
416
|
+
case 121:
|
|
417
|
+
throw new ZodmonDocValidationError(
|
|
418
|
+
collection2,
|
|
419
|
+
err.errInfo,
|
|
420
|
+
err
|
|
421
|
+
);
|
|
422
|
+
default:
|
|
423
|
+
throw new ZodmonError(`MongoDB error on "${collection2}": ${err.message}`, collection2, {
|
|
424
|
+
cause: err
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (err instanceof Error) {
|
|
429
|
+
throw new ZodmonError(`Unexpected error on "${collection2}": ${err.message}`, collection2, {
|
|
430
|
+
cause: err
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
throw new ZodmonError(`Unexpected error on "${collection2}": ${String(err)}`, collection2);
|
|
434
|
+
}
|
|
435
|
+
|
|
190
436
|
// src/schema/ref.ts
|
|
191
437
|
var import_zod = require("zod");
|
|
192
438
|
var refMetadata = /* @__PURE__ */ new WeakMap();
|
|
@@ -272,8 +518,12 @@ var AggregatePipeline = class _AggregatePipeline {
|
|
|
272
518
|
* ```
|
|
273
519
|
*/
|
|
274
520
|
async toArray() {
|
|
275
|
-
|
|
276
|
-
|
|
521
|
+
try {
|
|
522
|
+
const cursor = this.nativeCollection.aggregate(this.stages);
|
|
523
|
+
return await cursor.toArray();
|
|
524
|
+
} catch (err) {
|
|
525
|
+
wrapMongoError(err, this.definition.name);
|
|
526
|
+
}
|
|
277
527
|
}
|
|
278
528
|
/**
|
|
279
529
|
* Stream pipeline results one document at a time via `for await...of`.
|
|
@@ -288,9 +538,13 @@ var AggregatePipeline = class _AggregatePipeline {
|
|
|
288
538
|
* ```
|
|
289
539
|
*/
|
|
290
540
|
async *[Symbol.asyncIterator]() {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
541
|
+
try {
|
|
542
|
+
const cursor = this.nativeCollection.aggregate(this.stages);
|
|
543
|
+
for await (const doc of cursor) {
|
|
544
|
+
yield doc;
|
|
545
|
+
}
|
|
546
|
+
} catch (err) {
|
|
547
|
+
wrapMongoError(err, this.definition.name);
|
|
294
548
|
}
|
|
295
549
|
}
|
|
296
550
|
/**
|
|
@@ -310,8 +564,12 @@ var AggregatePipeline = class _AggregatePipeline {
|
|
|
310
564
|
* ```
|
|
311
565
|
*/
|
|
312
566
|
async explain() {
|
|
313
|
-
|
|
314
|
-
|
|
567
|
+
try {
|
|
568
|
+
const cursor = this.nativeCollection.aggregate(this.stages);
|
|
569
|
+
return await cursor.explain();
|
|
570
|
+
} catch (err) {
|
|
571
|
+
wrapMongoError(err, this.definition.name);
|
|
572
|
+
}
|
|
315
573
|
}
|
|
316
574
|
// ── Shape-preserving stages ──────────────────────────────────────
|
|
317
575
|
/**
|
|
@@ -736,7 +994,7 @@ function aggregate(handle) {
|
|
|
736
994
|
}
|
|
737
995
|
|
|
738
996
|
// src/client/client.ts
|
|
739
|
-
var
|
|
997
|
+
var import_mongodb3 = require("mongodb");
|
|
740
998
|
|
|
741
999
|
// src/indexes/spec.ts
|
|
742
1000
|
function toFieldIndexSpec(def) {
|
|
@@ -808,7 +1066,7 @@ async function processDesiredSpec(spec, existingByKey, native, dryRun, dropOrpha
|
|
|
808
1066
|
const serialized = serializeIndexKey(spec.key);
|
|
809
1067
|
const existing = existingByKey.get(serialized);
|
|
810
1068
|
if (!existing) {
|
|
811
|
-
if (!dryRun) await native
|
|
1069
|
+
if (!dryRun) await safeCreateIndex(native, spec.key, spec.options);
|
|
812
1070
|
acc.created.push(resolveSpecName(spec));
|
|
813
1071
|
return;
|
|
814
1072
|
}
|
|
@@ -821,8 +1079,8 @@ async function processDesiredSpec(spec, existingByKey, native, dryRun, dropOrpha
|
|
|
821
1079
|
}
|
|
822
1080
|
if (dropOrphaned) {
|
|
823
1081
|
if (!dryRun) {
|
|
824
|
-
await native
|
|
825
|
-
await native
|
|
1082
|
+
await safeDropIndex(native, existingName);
|
|
1083
|
+
await safeCreateIndex(native, spec.key, spec.options);
|
|
826
1084
|
}
|
|
827
1085
|
acc.dropped.push(existingName);
|
|
828
1086
|
acc.created.push(resolveSpecName(spec));
|
|
@@ -835,6 +1093,20 @@ async function processDesiredSpec(spec, existingByKey, native, dryRun, dropOrpha
|
|
|
835
1093
|
desired: spec.options
|
|
836
1094
|
});
|
|
837
1095
|
}
|
|
1096
|
+
async function safeCreateIndex(native, key, options) {
|
|
1097
|
+
try {
|
|
1098
|
+
await native.createIndex(key, options);
|
|
1099
|
+
} catch (err) {
|
|
1100
|
+
wrapMongoError(err, native.collectionName);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
async function safeDropIndex(native, name) {
|
|
1104
|
+
try {
|
|
1105
|
+
await native.dropIndex(name);
|
|
1106
|
+
} catch (err) {
|
|
1107
|
+
wrapMongoError(err, native.collectionName);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
838
1110
|
async function processOrphanedIndexes(existingIndexes, desiredKeys, matchedKeys, native, dryRun, dropOrphaned, dropped) {
|
|
839
1111
|
for (const idx of existingIndexes) {
|
|
840
1112
|
const rawName = idx["name"];
|
|
@@ -843,7 +1115,7 @@ async function processOrphanedIndexes(existingIndexes, desiredKeys, matchedKeys,
|
|
|
843
1115
|
const serialized = serializeIndexKey(idx["key"]);
|
|
844
1116
|
if (matchedKeys.has(serialized) || desiredKeys.has(serialized)) continue;
|
|
845
1117
|
if (dropOrphaned) {
|
|
846
|
-
if (!dryRun) await native
|
|
1118
|
+
if (!dryRun) await safeDropIndex(native, name);
|
|
847
1119
|
dropped.push(name);
|
|
848
1120
|
}
|
|
849
1121
|
}
|
|
@@ -855,7 +1127,7 @@ async function listIndexesSafe(native) {
|
|
|
855
1127
|
if (err instanceof Error && err.message.includes("ns does not exist")) {
|
|
856
1128
|
return [];
|
|
857
1129
|
}
|
|
858
|
-
|
|
1130
|
+
wrapMongoError(err, native.collectionName);
|
|
859
1131
|
}
|
|
860
1132
|
}
|
|
861
1133
|
async function syncIndexes(handle, options) {
|
|
@@ -904,36 +1176,49 @@ async function syncIndexes(handle, options) {
|
|
|
904
1176
|
var import_zod2 = require("zod");
|
|
905
1177
|
|
|
906
1178
|
// src/errors/validation.ts
|
|
907
|
-
var ZodmonValidationError = class extends
|
|
1179
|
+
var ZodmonValidationError = class extends ZodmonError {
|
|
908
1180
|
name = "ZodmonValidationError";
|
|
909
|
-
/** The MongoDB collection name where the validation failed. */
|
|
910
|
-
collection;
|
|
911
1181
|
/** The original Zod validation error with detailed issue information. */
|
|
912
1182
|
zodError;
|
|
913
|
-
|
|
1183
|
+
/** The document that failed validation. */
|
|
1184
|
+
document;
|
|
1185
|
+
constructor(collection2, zodError, document) {
|
|
914
1186
|
const fields = zodError.issues.map((issue) => {
|
|
915
1187
|
const path = issue.path.join(".") || "(root)";
|
|
916
1188
|
return `${path} (${issue.message})`;
|
|
917
1189
|
}).join(", ");
|
|
918
|
-
super(`Validation failed for "${collection2}": ${fields}
|
|
919
|
-
this.collection = collection2;
|
|
1190
|
+
super(`Validation failed for "${collection2}": ${fields}`, collection2, { cause: zodError });
|
|
920
1191
|
this.zodError = zodError;
|
|
1192
|
+
this.document = document;
|
|
921
1193
|
}
|
|
922
1194
|
};
|
|
923
1195
|
|
|
924
1196
|
// src/crud/delete.ts
|
|
925
1197
|
async function deleteOne(handle, filter) {
|
|
926
|
-
|
|
1198
|
+
try {
|
|
1199
|
+
return await handle.native.deleteOne(filter);
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
wrapMongoError(err, handle.definition.name);
|
|
1202
|
+
}
|
|
927
1203
|
}
|
|
928
1204
|
async function deleteMany(handle, filter) {
|
|
929
|
-
|
|
1205
|
+
try {
|
|
1206
|
+
return await handle.native.deleteMany(filter);
|
|
1207
|
+
} catch (err) {
|
|
1208
|
+
wrapMongoError(err, handle.definition.name);
|
|
1209
|
+
}
|
|
930
1210
|
}
|
|
931
1211
|
async function findOneAndDelete(handle, filter, options) {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1212
|
+
let result;
|
|
1213
|
+
try {
|
|
1214
|
+
result = await handle.native.findOneAndDelete(
|
|
1215
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter
|
|
1216
|
+
filter,
|
|
1217
|
+
{ includeResultMetadata: false }
|
|
1218
|
+
);
|
|
1219
|
+
} catch (err) {
|
|
1220
|
+
wrapMongoError(err, handle.definition.name);
|
|
1221
|
+
}
|
|
937
1222
|
if (!result) return null;
|
|
938
1223
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
939
1224
|
if (mode === false || mode === "passthrough") {
|
|
@@ -943,7 +1228,7 @@ async function findOneAndDelete(handle, filter, options) {
|
|
|
943
1228
|
return handle.definition.schema.parse(result);
|
|
944
1229
|
} catch (err) {
|
|
945
1230
|
if (err instanceof import_zod2.z.ZodError) {
|
|
946
|
-
throw new ZodmonValidationError(handle.definition.name, err);
|
|
1231
|
+
throw new ZodmonValidationError(handle.definition.name, err, result);
|
|
947
1232
|
}
|
|
948
1233
|
throw err;
|
|
949
1234
|
}
|
|
@@ -953,13 +1238,13 @@ async function findOneAndDelete(handle, filter, options) {
|
|
|
953
1238
|
var import_zod4 = require("zod");
|
|
954
1239
|
|
|
955
1240
|
// src/errors/not-found.ts
|
|
956
|
-
var ZodmonNotFoundError = class extends
|
|
1241
|
+
var ZodmonNotFoundError = class extends ZodmonError {
|
|
957
1242
|
name = "ZodmonNotFoundError";
|
|
958
|
-
/** The
|
|
959
|
-
|
|
960
|
-
constructor(collection2) {
|
|
961
|
-
super(`Document not found in "${collection2}"
|
|
962
|
-
this.
|
|
1243
|
+
/** The filter that produced no results. */
|
|
1244
|
+
filter;
|
|
1245
|
+
constructor(collection2, filter) {
|
|
1246
|
+
super(`Document not found in "${collection2}"`, collection2);
|
|
1247
|
+
this.filter = filter;
|
|
963
1248
|
}
|
|
964
1249
|
};
|
|
965
1250
|
|
|
@@ -990,15 +1275,15 @@ function checkUnindexedFields(definition, filter) {
|
|
|
990
1275
|
var import_zod3 = require("zod");
|
|
991
1276
|
|
|
992
1277
|
// src/crud/paginate.ts
|
|
993
|
-
var
|
|
1278
|
+
var import_mongodb2 = require("mongodb");
|
|
994
1279
|
function serializeValue(value) {
|
|
995
|
-
if (value instanceof
|
|
1280
|
+
if (value instanceof import_mongodb2.ObjectId) return { $oid: value.toHexString() };
|
|
996
1281
|
if (value instanceof Date) return { $date: value.getTime() };
|
|
997
1282
|
return value;
|
|
998
1283
|
}
|
|
999
1284
|
function deserializeValue(value) {
|
|
1000
1285
|
if (value != null && typeof value === "object") {
|
|
1001
|
-
if ("$oid" in value) return new
|
|
1286
|
+
if ("$oid" in value) return new import_mongodb2.ObjectId(value.$oid);
|
|
1002
1287
|
if ("$date" in value) return new Date(value.$date);
|
|
1003
1288
|
}
|
|
1004
1289
|
return value;
|
|
@@ -1050,6 +1335,54 @@ function resolveSortKeys(sortSpec) {
|
|
|
1050
1335
|
return entries;
|
|
1051
1336
|
}
|
|
1052
1337
|
|
|
1338
|
+
// src/query/projection.ts
|
|
1339
|
+
function isIncludeValue(value) {
|
|
1340
|
+
return value === 1 || value === true;
|
|
1341
|
+
}
|
|
1342
|
+
function isExcludeValue(value) {
|
|
1343
|
+
return value === 0 || value === false;
|
|
1344
|
+
}
|
|
1345
|
+
function isInclusionProjection(projection) {
|
|
1346
|
+
for (const key of Object.keys(projection)) {
|
|
1347
|
+
if (key === "_id") continue;
|
|
1348
|
+
const value = projection[key];
|
|
1349
|
+
if (value !== void 0 && isIncludeValue(value)) return true;
|
|
1350
|
+
}
|
|
1351
|
+
return false;
|
|
1352
|
+
}
|
|
1353
|
+
function buildPickMask(projection, schemaKeys) {
|
|
1354
|
+
const mask = {};
|
|
1355
|
+
const idValue = projection._id;
|
|
1356
|
+
if (!(idValue !== void 0 && isExcludeValue(idValue)) && schemaKeys.has("_id")) {
|
|
1357
|
+
mask._id = true;
|
|
1358
|
+
}
|
|
1359
|
+
for (const key of Object.keys(projection)) {
|
|
1360
|
+
if (key === "_id") continue;
|
|
1361
|
+
const value = projection[key];
|
|
1362
|
+
if (value !== void 0 && isIncludeValue(value) && schemaKeys.has(key)) {
|
|
1363
|
+
mask[key] = true;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
return mask;
|
|
1367
|
+
}
|
|
1368
|
+
function buildOmitMask(projection, schemaKeys) {
|
|
1369
|
+
const mask = {};
|
|
1370
|
+
for (const key of Object.keys(projection)) {
|
|
1371
|
+
const value = projection[key];
|
|
1372
|
+
if (value !== void 0 && isExcludeValue(value) && schemaKeys.has(key)) {
|
|
1373
|
+
mask[key] = true;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
return mask;
|
|
1377
|
+
}
|
|
1378
|
+
function deriveProjectedSchema(schema, projection) {
|
|
1379
|
+
const schemaKeys = new Set(Object.keys(schema.shape));
|
|
1380
|
+
if (isInclusionProjection(projection)) {
|
|
1381
|
+
return schema.pick(buildPickMask(projection, schemaKeys));
|
|
1382
|
+
}
|
|
1383
|
+
return schema.omit(buildOmitMask(projection, schemaKeys));
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1053
1386
|
// src/query/cursor.ts
|
|
1054
1387
|
var TypedFindCursor = class {
|
|
1055
1388
|
/** @internal */
|
|
@@ -1068,6 +1401,8 @@ var TypedFindCursor = class {
|
|
|
1068
1401
|
/** @internal */
|
|
1069
1402
|
sortSpec;
|
|
1070
1403
|
/** @internal */
|
|
1404
|
+
projectedSchema;
|
|
1405
|
+
/** @internal */
|
|
1071
1406
|
constructor(cursor, definition, mode, nativeCollection, filter) {
|
|
1072
1407
|
this.cursor = cursor;
|
|
1073
1408
|
this.schema = definition.schema;
|
|
@@ -1076,6 +1411,7 @@ var TypedFindCursor = class {
|
|
|
1076
1411
|
this.nativeCollection = nativeCollection;
|
|
1077
1412
|
this.filter = filter;
|
|
1078
1413
|
this.sortSpec = null;
|
|
1414
|
+
this.projectedSchema = null;
|
|
1079
1415
|
}
|
|
1080
1416
|
/**
|
|
1081
1417
|
* Set the sort order for the query.
|
|
@@ -1149,6 +1485,40 @@ var TypedFindCursor = class {
|
|
|
1149
1485
|
this.cursor.hint(indexName);
|
|
1150
1486
|
return this;
|
|
1151
1487
|
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Apply a projection to narrow the returned fields.
|
|
1490
|
+
*
|
|
1491
|
+
* Inclusion projections (`{ name: 1 }`) return only the specified fields
|
|
1492
|
+
* plus `_id` (unless `_id: 0`). Exclusion projections (`{ email: 0 }`)
|
|
1493
|
+
* return all fields except those excluded.
|
|
1494
|
+
*
|
|
1495
|
+
* The cursor's output type is narrowed at compile time. A derived Zod
|
|
1496
|
+
* schema is built for runtime validation of the projected fields.
|
|
1497
|
+
*
|
|
1498
|
+
* Projects from the original document type, not from a previous projection.
|
|
1499
|
+
* Calling `.project()` twice overrides the previous projection.
|
|
1500
|
+
*
|
|
1501
|
+
* @param spec - Type-safe projection document.
|
|
1502
|
+
* @returns A new cursor with the narrowed output type.
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* ```ts
|
|
1506
|
+
* const names = await find(users, {})
|
|
1507
|
+
* .project({ name: 1 })
|
|
1508
|
+
* .sort({ name: 1 })
|
|
1509
|
+
* .toArray()
|
|
1510
|
+
* // names[0].name ✓
|
|
1511
|
+
* // names[0].email TS error
|
|
1512
|
+
* ```
|
|
1513
|
+
*/
|
|
1514
|
+
project(spec) {
|
|
1515
|
+
this.cursor.project(spec);
|
|
1516
|
+
this.projectedSchema = deriveProjectedSchema(
|
|
1517
|
+
this.schema,
|
|
1518
|
+
spec
|
|
1519
|
+
);
|
|
1520
|
+
return this;
|
|
1521
|
+
}
|
|
1152
1522
|
async paginate(opts) {
|
|
1153
1523
|
const sortRecord = this.sortSpec ? this.sortSpec : null;
|
|
1154
1524
|
const sortKeys2 = resolveSortKeys(sortRecord);
|
|
@@ -1160,10 +1530,17 @@ var TypedFindCursor = class {
|
|
|
1160
1530
|
}
|
|
1161
1531
|
/** @internal Offset pagination implementation. */
|
|
1162
1532
|
async offsetPaginate(_sortKeys, sort, opts) {
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1533
|
+
let total;
|
|
1534
|
+
let raw2;
|
|
1535
|
+
try {
|
|
1536
|
+
;
|
|
1537
|
+
[total, raw2] = await Promise.all([
|
|
1538
|
+
this.nativeCollection.countDocuments(this.filter),
|
|
1539
|
+
this.nativeCollection.find(this.filter).sort(sort).skip((opts.page - 1) * opts.perPage).limit(opts.perPage).toArray()
|
|
1540
|
+
]);
|
|
1541
|
+
} catch (err) {
|
|
1542
|
+
wrapMongoError(err, this.collectionName);
|
|
1543
|
+
}
|
|
1167
1544
|
const docs = raw2.map((doc) => this.validateDoc(doc));
|
|
1168
1545
|
const totalPages = Math.ceil(total / opts.perPage);
|
|
1169
1546
|
return {
|
|
@@ -1187,7 +1564,12 @@ var TypedFindCursor = class {
|
|
|
1187
1564
|
combinedFilter = this.filter && Object.keys(this.filter).length > 0 ? { $and: [this.filter, cursorFilter] } : cursorFilter;
|
|
1188
1565
|
}
|
|
1189
1566
|
const effectiveSort = isBackward ? Object.fromEntries(sortKeys2.map(([f, d]) => [f, d === 1 ? -1 : 1])) : sort;
|
|
1190
|
-
|
|
1567
|
+
let raw2;
|
|
1568
|
+
try {
|
|
1569
|
+
raw2 = await this.nativeCollection.find(combinedFilter).sort(effectiveSort).limit(opts.limit + 1).toArray();
|
|
1570
|
+
} catch (err) {
|
|
1571
|
+
wrapMongoError(err, this.collectionName);
|
|
1572
|
+
}
|
|
1191
1573
|
const hasMore = raw2.length > opts.limit;
|
|
1192
1574
|
if (hasMore) raw2.pop();
|
|
1193
1575
|
if (isBackward) raw2.reverse();
|
|
@@ -1215,7 +1597,12 @@ var TypedFindCursor = class {
|
|
|
1215
1597
|
* ```
|
|
1216
1598
|
*/
|
|
1217
1599
|
async toArray() {
|
|
1218
|
-
|
|
1600
|
+
let raw2;
|
|
1601
|
+
try {
|
|
1602
|
+
raw2 = await this.cursor.toArray();
|
|
1603
|
+
} catch (err) {
|
|
1604
|
+
wrapMongoError(err, this.collectionName);
|
|
1605
|
+
}
|
|
1219
1606
|
return raw2.map((doc) => this.validateDoc(doc));
|
|
1220
1607
|
}
|
|
1221
1608
|
/**
|
|
@@ -1235,8 +1622,12 @@ var TypedFindCursor = class {
|
|
|
1235
1622
|
* ```
|
|
1236
1623
|
*/
|
|
1237
1624
|
async *[Symbol.asyncIterator]() {
|
|
1238
|
-
|
|
1239
|
-
|
|
1625
|
+
try {
|
|
1626
|
+
for await (const doc of this.cursor) {
|
|
1627
|
+
yield this.validateDoc(doc);
|
|
1628
|
+
}
|
|
1629
|
+
} catch (err) {
|
|
1630
|
+
wrapMongoError(err, this.collectionName);
|
|
1240
1631
|
}
|
|
1241
1632
|
}
|
|
1242
1633
|
/** @internal Validate a single raw document against the schema. */
|
|
@@ -1244,11 +1635,12 @@ var TypedFindCursor = class {
|
|
|
1244
1635
|
if (this.mode === false || this.mode === "passthrough") {
|
|
1245
1636
|
return raw2;
|
|
1246
1637
|
}
|
|
1638
|
+
const schema = this.projectedSchema ?? this.schema;
|
|
1247
1639
|
try {
|
|
1248
|
-
return
|
|
1640
|
+
return schema.parse(raw2);
|
|
1249
1641
|
} catch (err) {
|
|
1250
1642
|
if (err instanceof import_zod3.z.ZodError) {
|
|
1251
|
-
throw new ZodmonValidationError(this.collectionName, err);
|
|
1643
|
+
throw new ZodmonValidationError(this.collectionName, err, raw2);
|
|
1252
1644
|
}
|
|
1253
1645
|
throw err;
|
|
1254
1646
|
}
|
|
@@ -1258,18 +1650,28 @@ var TypedFindCursor = class {
|
|
|
1258
1650
|
// src/crud/find.ts
|
|
1259
1651
|
async function findOne(handle, filter, options) {
|
|
1260
1652
|
checkUnindexedFields(handle.definition, filter);
|
|
1261
|
-
const
|
|
1262
|
-
const
|
|
1653
|
+
const project = options && "project" in options ? options.project : void 0;
|
|
1654
|
+
const findOptions = project ? { projection: project } : void 0;
|
|
1655
|
+
let raw2;
|
|
1656
|
+
try {
|
|
1657
|
+
raw2 = await handle.native.findOne(filter, findOptions);
|
|
1658
|
+
} catch (err) {
|
|
1659
|
+
wrapMongoError(err, handle.definition.name);
|
|
1660
|
+
}
|
|
1263
1661
|
if (!raw2) return null;
|
|
1264
1662
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
1265
1663
|
if (mode === false || mode === "passthrough") {
|
|
1266
1664
|
return raw2;
|
|
1267
1665
|
}
|
|
1666
|
+
const schema = project ? deriveProjectedSchema(
|
|
1667
|
+
handle.definition.schema,
|
|
1668
|
+
project
|
|
1669
|
+
) : handle.definition.schema;
|
|
1268
1670
|
try {
|
|
1269
|
-
return
|
|
1671
|
+
return schema.parse(raw2);
|
|
1270
1672
|
} catch (err) {
|
|
1271
1673
|
if (err instanceof import_zod4.z.ZodError) {
|
|
1272
|
-
throw new ZodmonValidationError(handle.definition.name, err);
|
|
1674
|
+
throw new ZodmonValidationError(handle.definition.name, err, raw2);
|
|
1273
1675
|
}
|
|
1274
1676
|
throw err;
|
|
1275
1677
|
}
|
|
@@ -1277,7 +1679,7 @@ async function findOne(handle, filter, options) {
|
|
|
1277
1679
|
async function findOneOrThrow(handle, filter, options) {
|
|
1278
1680
|
const doc = await findOne(handle, filter, options);
|
|
1279
1681
|
if (!doc) {
|
|
1280
|
-
throw new ZodmonNotFoundError(handle.definition.name);
|
|
1682
|
+
throw new ZodmonNotFoundError(handle.definition.name, filter);
|
|
1281
1683
|
}
|
|
1282
1684
|
return doc;
|
|
1283
1685
|
}
|
|
@@ -1286,7 +1688,12 @@ function find(handle, filter, options) {
|
|
|
1286
1688
|
const raw2 = handle.native.find(filter);
|
|
1287
1689
|
const cursor = raw2;
|
|
1288
1690
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
1289
|
-
|
|
1691
|
+
const typedCursor = new TypedFindCursor(cursor, handle.definition, mode, handle.native, filter);
|
|
1692
|
+
const project = options && "project" in options ? options.project : void 0;
|
|
1693
|
+
if (project) {
|
|
1694
|
+
return typedCursor.project(project);
|
|
1695
|
+
}
|
|
1696
|
+
return typedCursor;
|
|
1290
1697
|
}
|
|
1291
1698
|
|
|
1292
1699
|
// src/crud/insert.ts
|
|
@@ -1297,11 +1704,15 @@ async function insertOne(handle, doc) {
|
|
|
1297
1704
|
parsed = handle.definition.schema.parse(doc);
|
|
1298
1705
|
} catch (err) {
|
|
1299
1706
|
if (err instanceof import_zod5.z.ZodError) {
|
|
1300
|
-
throw new ZodmonValidationError(handle.definition.name, err);
|
|
1707
|
+
throw new ZodmonValidationError(handle.definition.name, err, doc);
|
|
1301
1708
|
}
|
|
1302
1709
|
throw err;
|
|
1303
1710
|
}
|
|
1304
|
-
|
|
1711
|
+
try {
|
|
1712
|
+
await handle.native.insertOne(parsed);
|
|
1713
|
+
} catch (err) {
|
|
1714
|
+
wrapMongoError(err, handle.definition.name);
|
|
1715
|
+
}
|
|
1305
1716
|
return parsed;
|
|
1306
1717
|
}
|
|
1307
1718
|
async function insertMany(handle, docs) {
|
|
@@ -1312,22 +1723,34 @@ async function insertMany(handle, docs) {
|
|
|
1312
1723
|
parsed.push(handle.definition.schema.parse(doc));
|
|
1313
1724
|
} catch (err) {
|
|
1314
1725
|
if (err instanceof import_zod5.z.ZodError) {
|
|
1315
|
-
throw new ZodmonValidationError(handle.definition.name, err);
|
|
1726
|
+
throw new ZodmonValidationError(handle.definition.name, err, doc);
|
|
1316
1727
|
}
|
|
1317
1728
|
throw err;
|
|
1318
1729
|
}
|
|
1319
1730
|
}
|
|
1320
|
-
|
|
1731
|
+
try {
|
|
1732
|
+
await handle.native.insertMany(parsed);
|
|
1733
|
+
} catch (err) {
|
|
1734
|
+
wrapMongoError(err, handle.definition.name);
|
|
1735
|
+
}
|
|
1321
1736
|
return parsed;
|
|
1322
1737
|
}
|
|
1323
1738
|
|
|
1324
1739
|
// src/crud/update.ts
|
|
1325
1740
|
var import_zod6 = require("zod");
|
|
1326
1741
|
async function updateOne(handle, filter, update, options) {
|
|
1327
|
-
|
|
1742
|
+
try {
|
|
1743
|
+
return await handle.native.updateOne(filter, update, options);
|
|
1744
|
+
} catch (err) {
|
|
1745
|
+
wrapMongoError(err, handle.definition.name);
|
|
1746
|
+
}
|
|
1328
1747
|
}
|
|
1329
1748
|
async function updateMany(handle, filter, update, options) {
|
|
1330
|
-
|
|
1749
|
+
try {
|
|
1750
|
+
return await handle.native.updateMany(filter, update, options);
|
|
1751
|
+
} catch (err) {
|
|
1752
|
+
wrapMongoError(err, handle.definition.name);
|
|
1753
|
+
}
|
|
1331
1754
|
}
|
|
1332
1755
|
async function findOneAndUpdate(handle, filter, update, options) {
|
|
1333
1756
|
const driverOptions = {
|
|
@@ -1337,14 +1760,19 @@ async function findOneAndUpdate(handle, filter, update, options) {
|
|
|
1337
1760
|
if (options?.upsert !== void 0) {
|
|
1338
1761
|
driverOptions["upsert"] = options.upsert;
|
|
1339
1762
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1763
|
+
let result;
|
|
1764
|
+
try {
|
|
1765
|
+
result = await handle.native.findOneAndUpdate(
|
|
1766
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter
|
|
1767
|
+
filter,
|
|
1768
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter
|
|
1769
|
+
update,
|
|
1770
|
+
// biome-ignore lint/suspicious/noExplicitAny: dynamic options object is not assignable to driver's FindOneAndUpdateOptions under exactOptionalPropertyTypes
|
|
1771
|
+
driverOptions
|
|
1772
|
+
);
|
|
1773
|
+
} catch (err) {
|
|
1774
|
+
wrapMongoError(err, handle.definition.name);
|
|
1775
|
+
}
|
|
1348
1776
|
if (!result) return null;
|
|
1349
1777
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
1350
1778
|
if (mode === false || mode === "passthrough") {
|
|
@@ -1354,7 +1782,7 @@ async function findOneAndUpdate(handle, filter, update, options) {
|
|
|
1354
1782
|
return handle.definition.schema.parse(result);
|
|
1355
1783
|
} catch (err) {
|
|
1356
1784
|
if (err instanceof import_zod6.z.ZodError) {
|
|
1357
|
-
throw new ZodmonValidationError(handle.definition.name, err);
|
|
1785
|
+
throw new ZodmonValidationError(handle.definition.name, err, result);
|
|
1358
1786
|
}
|
|
1359
1787
|
throw err;
|
|
1360
1788
|
}
|
|
@@ -1414,70 +1842,12 @@ var CollectionHandle = class {
|
|
|
1414
1842
|
async insertMany(docs) {
|
|
1415
1843
|
return await insertMany(this, docs);
|
|
1416
1844
|
}
|
|
1417
|
-
/**
|
|
1418
|
-
* Find a single document matching the filter.
|
|
1419
|
-
*
|
|
1420
|
-
* Queries MongoDB, then validates the fetched document against the collection's
|
|
1421
|
-
* Zod schema. Validation mode is resolved from the per-query option, falling
|
|
1422
|
-
* back to the collection-level default (which defaults to `'strict'`).
|
|
1423
|
-
*
|
|
1424
|
-
* @param filter - Type-safe filter to match documents.
|
|
1425
|
-
* @param options - Optional projection and validation overrides.
|
|
1426
|
-
* @returns The matched document, or `null` if no document matches.
|
|
1427
|
-
* @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.
|
|
1428
|
-
*
|
|
1429
|
-
* @example
|
|
1430
|
-
* ```ts
|
|
1431
|
-
* const users = db.use(Users)
|
|
1432
|
-
* const user = await users.findOne({ name: 'Ada' })
|
|
1433
|
-
* if (user) console.log(user.role)
|
|
1434
|
-
* ```
|
|
1435
|
-
*/
|
|
1436
1845
|
async findOne(filter, options) {
|
|
1437
1846
|
return await findOne(this, filter, options);
|
|
1438
1847
|
}
|
|
1439
|
-
/**
|
|
1440
|
-
* Find a single document matching the filter, or throw if none exists.
|
|
1441
|
-
*
|
|
1442
|
-
* Behaves identically to {@link findOne} but throws {@link ZodmonNotFoundError}
|
|
1443
|
-
* instead of returning `null` when no document matches the filter.
|
|
1444
|
-
*
|
|
1445
|
-
* @param filter - Type-safe filter to match documents.
|
|
1446
|
-
* @param options - Optional projection and validation overrides.
|
|
1447
|
-
* @returns The matched document (never null).
|
|
1448
|
-
* @throws {ZodmonNotFoundError} When no document matches the filter.
|
|
1449
|
-
* @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.
|
|
1450
|
-
*
|
|
1451
|
-
* @example
|
|
1452
|
-
* ```ts
|
|
1453
|
-
* const users = db.use(Users)
|
|
1454
|
-
* const user = await users.findOneOrThrow({ name: 'Ada' })
|
|
1455
|
-
* console.log(user.role) // guaranteed non-null
|
|
1456
|
-
* ```
|
|
1457
|
-
*/
|
|
1458
1848
|
async findOneOrThrow(filter, options) {
|
|
1459
1849
|
return await findOneOrThrow(this, filter, options);
|
|
1460
1850
|
}
|
|
1461
|
-
/**
|
|
1462
|
-
* Find all documents matching the filter, returning a chainable typed cursor.
|
|
1463
|
-
*
|
|
1464
|
-
* The cursor is lazy — no query is executed until a terminal method
|
|
1465
|
-
* (`toArray`, `for await`) is called. Use `sort`, `skip`, and `limit`
|
|
1466
|
-
* to shape the query before executing.
|
|
1467
|
-
*
|
|
1468
|
-
* @param filter - Type-safe filter to match documents.
|
|
1469
|
-
* @param options - Optional validation overrides.
|
|
1470
|
-
* @returns A typed cursor for chaining query modifiers.
|
|
1471
|
-
*
|
|
1472
|
-
* @example
|
|
1473
|
-
* ```ts
|
|
1474
|
-
* const users = db.use(Users)
|
|
1475
|
-
* const admins = await users.find({ role: 'admin' })
|
|
1476
|
-
* .sort({ name: 1 })
|
|
1477
|
-
* .limit(10)
|
|
1478
|
-
* .toArray()
|
|
1479
|
-
* ```
|
|
1480
|
-
*/
|
|
1481
1851
|
find(filter, options) {
|
|
1482
1852
|
return find(this, filter, options);
|
|
1483
1853
|
}
|
|
@@ -1674,7 +2044,7 @@ var Database = class {
|
|
|
1674
2044
|
/** Registered collection definitions, keyed by name. Used by syncIndexes(). */
|
|
1675
2045
|
_collections = /* @__PURE__ */ new Map();
|
|
1676
2046
|
constructor(uri, dbName, options) {
|
|
1677
|
-
this._client = new
|
|
2047
|
+
this._client = new import_mongodb3.MongoClient(uri, options);
|
|
1678
2048
|
this._db = this._client.db(dbName);
|
|
1679
2049
|
}
|
|
1680
2050
|
/**
|
|
@@ -1763,7 +2133,7 @@ function createClient(uri, dbNameOrOptions, maybeOptions) {
|
|
|
1763
2133
|
}
|
|
1764
2134
|
|
|
1765
2135
|
// src/collection/collection.ts
|
|
1766
|
-
var
|
|
2136
|
+
var import_mongodb5 = require("mongodb");
|
|
1767
2137
|
var import_zod9 = require("zod");
|
|
1768
2138
|
|
|
1769
2139
|
// src/schema/extensions.ts
|
|
@@ -1873,14 +2243,14 @@ function installExtensions() {
|
|
|
1873
2243
|
installExtensions();
|
|
1874
2244
|
|
|
1875
2245
|
// src/schema/object-id.ts
|
|
1876
|
-
var
|
|
2246
|
+
var import_mongodb4 = require("mongodb");
|
|
1877
2247
|
var import_zod8 = require("zod");
|
|
1878
2248
|
var OBJECT_ID_HEX = /^[a-f\d]{24}$/i;
|
|
1879
2249
|
function objectId() {
|
|
1880
2250
|
return import_zod8.z.custom((val) => {
|
|
1881
|
-
if (val instanceof
|
|
2251
|
+
if (val instanceof import_mongodb4.ObjectId) return true;
|
|
1882
2252
|
return typeof val === "string" && OBJECT_ID_HEX.test(val);
|
|
1883
|
-
}, "Invalid ObjectId").transform((val) => val instanceof
|
|
2253
|
+
}, "Invalid ObjectId").transform((val) => val instanceof import_mongodb4.ObjectId ? val : import_mongodb4.ObjectId.createFromHexString(val));
|
|
1884
2254
|
}
|
|
1885
2255
|
|
|
1886
2256
|
// src/collection/collection.ts
|
|
@@ -1895,7 +2265,7 @@ function extractFieldIndexes(shape) {
|
|
|
1895
2265
|
return result;
|
|
1896
2266
|
}
|
|
1897
2267
|
function collection(name, shape, options) {
|
|
1898
|
-
const resolvedShape = "_id" in shape ? shape : { _id: objectId().default(() => new
|
|
2268
|
+
const resolvedShape = "_id" in shape ? shape : { _id: objectId().default(() => new import_mongodb5.ObjectId()), ...shape };
|
|
1899
2269
|
const schema = import_zod9.z.object(resolvedShape);
|
|
1900
2270
|
const fieldIndexes = extractFieldIndexes(shape);
|
|
1901
2271
|
const { indexes: compoundIndexes, validation, ...rest } = options ?? {};
|
|
@@ -1966,14 +2336,14 @@ function index(fields) {
|
|
|
1966
2336
|
}
|
|
1967
2337
|
|
|
1968
2338
|
// src/helpers/oid.ts
|
|
1969
|
-
var
|
|
2339
|
+
var import_mongodb6 = require("mongodb");
|
|
1970
2340
|
function oid(value) {
|
|
1971
|
-
if (value === void 0) return new
|
|
1972
|
-
if (value instanceof
|
|
1973
|
-
return
|
|
2341
|
+
if (value === void 0) return new import_mongodb6.ObjectId();
|
|
2342
|
+
if (value instanceof import_mongodb6.ObjectId) return value;
|
|
2343
|
+
return import_mongodb6.ObjectId.createFromHexString(value);
|
|
1974
2344
|
}
|
|
1975
2345
|
function isOid(value) {
|
|
1976
|
-
return value instanceof
|
|
2346
|
+
return value instanceof import_mongodb6.ObjectId;
|
|
1977
2347
|
}
|
|
1978
2348
|
|
|
1979
2349
|
// src/query/operators.ts
|
|
@@ -2046,8 +2416,18 @@ var $ = {
|
|
|
2046
2416
|
Database,
|
|
2047
2417
|
IndexBuilder,
|
|
2048
2418
|
TypedFindCursor,
|
|
2419
|
+
ZodmonAuthError,
|
|
2420
|
+
ZodmonBulkWriteError,
|
|
2421
|
+
ZodmonDocValidationError,
|
|
2422
|
+
ZodmonDuplicateKeyError,
|
|
2423
|
+
ZodmonError,
|
|
2424
|
+
ZodmonIndexError,
|
|
2425
|
+
ZodmonNetworkError,
|
|
2049
2426
|
ZodmonNotFoundError,
|
|
2427
|
+
ZodmonQueryError,
|
|
2428
|
+
ZodmonTimeoutError,
|
|
2050
2429
|
ZodmonValidationError,
|
|
2430
|
+
ZodmonWriteConflictError,
|
|
2051
2431
|
aggregate,
|
|
2052
2432
|
checkUnindexedFields,
|
|
2053
2433
|
collection,
|
|
@@ -2056,6 +2436,7 @@ var $ = {
|
|
|
2056
2436
|
createExpressionBuilder,
|
|
2057
2437
|
deleteMany,
|
|
2058
2438
|
deleteOne,
|
|
2439
|
+
deriveProjectedSchema,
|
|
2059
2440
|
extractComparableOptions,
|
|
2060
2441
|
extractDbName,
|
|
2061
2442
|
extractFieldIndexes,
|
|
@@ -2070,6 +2451,7 @@ var $ = {
|
|
|
2070
2451
|
index,
|
|
2071
2452
|
insertMany,
|
|
2072
2453
|
insertOne,
|
|
2454
|
+
isInclusionProjection,
|
|
2073
2455
|
isOid,
|
|
2074
2456
|
objectId,
|
|
2075
2457
|
oid,
|
|
@@ -2079,6 +2461,7 @@ var $ = {
|
|
|
2079
2461
|
toCompoundIndexSpec,
|
|
2080
2462
|
toFieldIndexSpec,
|
|
2081
2463
|
updateMany,
|
|
2082
|
-
updateOne
|
|
2464
|
+
updateOne,
|
|
2465
|
+
wrapMongoError
|
|
2083
2466
|
});
|
|
2084
2467
|
//# sourceMappingURL=index.cjs.map
|