@zodmon/core 0.6.0 → 0.7.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 +404 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +963 -456
- package/dist/index.d.ts +963 -456
- package/dist/index.js +394 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
$: () => $,
|
|
23
24
|
$and: () => $and,
|
|
24
25
|
$eq: () => $eq,
|
|
25
26
|
$exists: () => $exists,
|
|
@@ -42,41 +43,34 @@ __export(index_exports, {
|
|
|
42
43
|
ZodmonValidationError: () => ZodmonValidationError,
|
|
43
44
|
collection: () => collection,
|
|
44
45
|
createClient: () => createClient,
|
|
46
|
+
deleteMany: () => deleteMany,
|
|
47
|
+
deleteOne: () => deleteOne,
|
|
45
48
|
extractDbName: () => extractDbName,
|
|
46
49
|
extractFieldIndexes: () => extractFieldIndexes,
|
|
47
50
|
find: () => find,
|
|
48
51
|
findOne: () => findOne,
|
|
52
|
+
findOneAndDelete: () => findOneAndDelete,
|
|
53
|
+
findOneAndUpdate: () => findOneAndUpdate,
|
|
49
54
|
findOneOrThrow: () => findOneOrThrow,
|
|
50
55
|
getIndexMetadata: () => getIndexMetadata,
|
|
51
56
|
getRefMetadata: () => getRefMetadata,
|
|
52
57
|
index: () => index,
|
|
53
58
|
insertMany: () => insertMany,
|
|
54
59
|
insertOne: () => insertOne,
|
|
55
|
-
installExtensions: () => installExtensions,
|
|
56
|
-
installRefExtension: () => installRefExtension,
|
|
57
60
|
isOid: () => isOid,
|
|
58
61
|
objectId: () => objectId,
|
|
59
62
|
oid: () => oid,
|
|
60
|
-
raw: () => raw
|
|
63
|
+
raw: () => raw,
|
|
64
|
+
updateMany: () => updateMany,
|
|
65
|
+
updateOne: () => updateOne
|
|
61
66
|
});
|
|
62
67
|
module.exports = __toCommonJS(index_exports);
|
|
63
68
|
|
|
64
69
|
// src/client/client.ts
|
|
65
|
-
var
|
|
66
|
-
|
|
67
|
-
// src/crud/find.ts
|
|
68
|
-
var import_zod2 = require("zod");
|
|
70
|
+
var import_mongodb2 = require("mongodb");
|
|
69
71
|
|
|
70
|
-
// src/
|
|
71
|
-
var
|
|
72
|
-
name = "ZodmonNotFoundError";
|
|
73
|
-
/** The MongoDB collection name where the query found no results. */
|
|
74
|
-
collection;
|
|
75
|
-
constructor(collection2) {
|
|
76
|
-
super(`Document not found in "${collection2}"`);
|
|
77
|
-
this.collection = collection2;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
72
|
+
// src/crud/delete.ts
|
|
73
|
+
var import_zod = require("zod");
|
|
80
74
|
|
|
81
75
|
// src/errors/validation.ts
|
|
82
76
|
var ZodmonValidationError = class extends Error {
|
|
@@ -96,8 +90,113 @@ var ZodmonValidationError = class extends Error {
|
|
|
96
90
|
}
|
|
97
91
|
};
|
|
98
92
|
|
|
93
|
+
// src/crud/delete.ts
|
|
94
|
+
async function deleteOne(handle, filter) {
|
|
95
|
+
return await handle.native.deleteOne(filter);
|
|
96
|
+
}
|
|
97
|
+
async function deleteMany(handle, filter) {
|
|
98
|
+
return await handle.native.deleteMany(filter);
|
|
99
|
+
}
|
|
100
|
+
async function findOneAndDelete(handle, filter, options) {
|
|
101
|
+
const result = await handle.native.findOneAndDelete(
|
|
102
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter
|
|
103
|
+
filter,
|
|
104
|
+
{ includeResultMetadata: false }
|
|
105
|
+
);
|
|
106
|
+
if (!result) return null;
|
|
107
|
+
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
108
|
+
if (mode === false || mode === "passthrough") {
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return handle.definition.schema.parse(result);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
if (err instanceof import_zod.z.ZodError) {
|
|
115
|
+
throw new ZodmonValidationError(handle.definition.name, err);
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/crud/find.ts
|
|
122
|
+
var import_zod3 = require("zod");
|
|
123
|
+
|
|
124
|
+
// src/errors/not-found.ts
|
|
125
|
+
var ZodmonNotFoundError = class extends Error {
|
|
126
|
+
name = "ZodmonNotFoundError";
|
|
127
|
+
/** The MongoDB collection name where the query found no results. */
|
|
128
|
+
collection;
|
|
129
|
+
constructor(collection2) {
|
|
130
|
+
super(`Document not found in "${collection2}"`);
|
|
131
|
+
this.collection = collection2;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// src/query/cursor.ts
|
|
136
|
+
var import_zod2 = require("zod");
|
|
137
|
+
|
|
138
|
+
// src/crud/paginate.ts
|
|
139
|
+
var import_mongodb = require("mongodb");
|
|
140
|
+
function serializeValue(value) {
|
|
141
|
+
if (value instanceof import_mongodb.ObjectId) return { $oid: value.toHexString() };
|
|
142
|
+
if (value instanceof Date) return { $date: value.getTime() };
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
function deserializeValue(value) {
|
|
146
|
+
if (value != null && typeof value === "object") {
|
|
147
|
+
if ("$oid" in value) return new import_mongodb.ObjectId(value.$oid);
|
|
148
|
+
if ("$date" in value) return new Date(value.$date);
|
|
149
|
+
}
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
function encodeCursor(doc, sortKeys, direction) {
|
|
153
|
+
const values = sortKeys.map(([field]) => serializeValue(doc[field]));
|
|
154
|
+
return btoa(JSON.stringify([direction, ...values]));
|
|
155
|
+
}
|
|
156
|
+
function decodeCursor(cursor) {
|
|
157
|
+
let parsed;
|
|
158
|
+
try {
|
|
159
|
+
parsed = JSON.parse(atob(cursor));
|
|
160
|
+
} catch {
|
|
161
|
+
throw new Error("Invalid cursor: malformed encoding");
|
|
162
|
+
}
|
|
163
|
+
if (!Array.isArray(parsed) || parsed.length < 1) {
|
|
164
|
+
throw new Error("Invalid cursor: expected non-empty array");
|
|
165
|
+
}
|
|
166
|
+
const [direction, ...rawValues] = parsed;
|
|
167
|
+
if (direction !== "f" && direction !== "b") {
|
|
168
|
+
throw new Error("Invalid cursor: unknown direction flag");
|
|
169
|
+
}
|
|
170
|
+
return { direction, values: rawValues.map(deserializeValue) };
|
|
171
|
+
}
|
|
172
|
+
function buildCursorFilter(sortKeys, values, isBackward) {
|
|
173
|
+
const clauses = [];
|
|
174
|
+
for (let i = 0; i < sortKeys.length; i++) {
|
|
175
|
+
const clause = {};
|
|
176
|
+
for (let j = 0; j < i; j++) {
|
|
177
|
+
clause[sortKeys[j][0]] = values[j];
|
|
178
|
+
}
|
|
179
|
+
const [field, direction] = sortKeys[i];
|
|
180
|
+
const isAsc = direction === 1;
|
|
181
|
+
const op = isAsc !== isBackward ? "$gt" : "$lt";
|
|
182
|
+
if (values[i] === null) {
|
|
183
|
+
clause[field] = { $ne: null };
|
|
184
|
+
} else {
|
|
185
|
+
clause[field] = { [op]: values[i] };
|
|
186
|
+
}
|
|
187
|
+
clauses.push(clause);
|
|
188
|
+
}
|
|
189
|
+
return { $or: clauses };
|
|
190
|
+
}
|
|
191
|
+
function resolveSortKeys(sortSpec) {
|
|
192
|
+
const entries = sortSpec ? Object.entries(sortSpec) : [];
|
|
193
|
+
if (!entries.some(([field]) => field === "_id")) {
|
|
194
|
+
entries.push(["_id", 1]);
|
|
195
|
+
}
|
|
196
|
+
return entries;
|
|
197
|
+
}
|
|
198
|
+
|
|
99
199
|
// src/query/cursor.ts
|
|
100
|
-
var import_zod = require("zod");
|
|
101
200
|
var TypedFindCursor = class {
|
|
102
201
|
/** @internal */
|
|
103
202
|
cursor;
|
|
@@ -108,11 +207,21 @@ var TypedFindCursor = class {
|
|
|
108
207
|
/** @internal */
|
|
109
208
|
mode;
|
|
110
209
|
/** @internal */
|
|
111
|
-
|
|
210
|
+
nativeCollection;
|
|
211
|
+
/** @internal */
|
|
212
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedFilter is not assignable to MongoDB's Filter; stored opaquely for paginate
|
|
213
|
+
filter;
|
|
214
|
+
/** @internal */
|
|
215
|
+
sortSpec;
|
|
216
|
+
/** @internal */
|
|
217
|
+
constructor(cursor, definition, mode, nativeCollection, filter) {
|
|
112
218
|
this.cursor = cursor;
|
|
113
219
|
this.schema = definition.schema;
|
|
114
220
|
this.collectionName = definition.name;
|
|
115
221
|
this.mode = mode;
|
|
222
|
+
this.nativeCollection = nativeCollection;
|
|
223
|
+
this.filter = filter;
|
|
224
|
+
this.sortSpec = null;
|
|
116
225
|
}
|
|
117
226
|
/**
|
|
118
227
|
* Set the sort order for the query.
|
|
@@ -129,6 +238,7 @@ var TypedFindCursor = class {
|
|
|
129
238
|
* ```
|
|
130
239
|
*/
|
|
131
240
|
sort(spec) {
|
|
241
|
+
this.sortSpec = spec;
|
|
132
242
|
this.cursor.sort(spec);
|
|
133
243
|
return this;
|
|
134
244
|
}
|
|
@@ -162,6 +272,57 @@ var TypedFindCursor = class {
|
|
|
162
272
|
this.cursor.limit(n);
|
|
163
273
|
return this;
|
|
164
274
|
}
|
|
275
|
+
async paginate(opts) {
|
|
276
|
+
const sortRecord = this.sortSpec ? this.sortSpec : null;
|
|
277
|
+
const sortKeys = resolveSortKeys(sortRecord);
|
|
278
|
+
const sort = Object.fromEntries(sortKeys);
|
|
279
|
+
if ("page" in opts) {
|
|
280
|
+
return await this.offsetPaginate(sortKeys, sort, opts);
|
|
281
|
+
}
|
|
282
|
+
return await this.cursorPaginate(sortKeys, sort, opts);
|
|
283
|
+
}
|
|
284
|
+
/** @internal Offset pagination implementation. */
|
|
285
|
+
async offsetPaginate(_sortKeys, sort, opts) {
|
|
286
|
+
const [total, raw2] = await Promise.all([
|
|
287
|
+
this.nativeCollection.countDocuments(this.filter),
|
|
288
|
+
this.nativeCollection.find(this.filter).sort(sort).skip((opts.page - 1) * opts.perPage).limit(opts.perPage).toArray()
|
|
289
|
+
]);
|
|
290
|
+
const docs = raw2.map((doc) => this.validateDoc(doc));
|
|
291
|
+
const totalPages = Math.ceil(total / opts.perPage);
|
|
292
|
+
return {
|
|
293
|
+
docs,
|
|
294
|
+
total,
|
|
295
|
+
page: opts.page,
|
|
296
|
+
perPage: opts.perPage,
|
|
297
|
+
totalPages,
|
|
298
|
+
hasNext: opts.page < totalPages,
|
|
299
|
+
hasPrev: opts.page > 1
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/** @internal Cursor pagination implementation. */
|
|
303
|
+
async cursorPaginate(sortKeys, sort, opts) {
|
|
304
|
+
let isBackward = false;
|
|
305
|
+
let combinedFilter = this.filter;
|
|
306
|
+
if (opts.cursor) {
|
|
307
|
+
const decoded = decodeCursor(opts.cursor);
|
|
308
|
+
isBackward = decoded.direction === "b";
|
|
309
|
+
const cursorFilter = buildCursorFilter(sortKeys, decoded.values, isBackward);
|
|
310
|
+
combinedFilter = this.filter && Object.keys(this.filter).length > 0 ? { $and: [this.filter, cursorFilter] } : cursorFilter;
|
|
311
|
+
}
|
|
312
|
+
const effectiveSort = isBackward ? Object.fromEntries(sortKeys.map(([f, d]) => [f, d === 1 ? -1 : 1])) : sort;
|
|
313
|
+
const raw2 = await this.nativeCollection.find(combinedFilter).sort(effectiveSort).limit(opts.limit + 1).toArray();
|
|
314
|
+
const hasMore = raw2.length > opts.limit;
|
|
315
|
+
if (hasMore) raw2.pop();
|
|
316
|
+
if (isBackward) raw2.reverse();
|
|
317
|
+
const docs = raw2.map((doc) => this.validateDoc(doc));
|
|
318
|
+
return {
|
|
319
|
+
docs,
|
|
320
|
+
hasNext: isBackward ? true : hasMore,
|
|
321
|
+
hasPrev: isBackward ? hasMore : opts.cursor != null,
|
|
322
|
+
startCursor: docs.length > 0 ? encodeCursor(docs[0], sortKeys, "b") : null,
|
|
323
|
+
endCursor: docs.length > 0 ? encodeCursor(docs[docs.length - 1], sortKeys, "f") : null
|
|
324
|
+
};
|
|
325
|
+
}
|
|
165
326
|
/**
|
|
166
327
|
* Execute the query and return all matching documents as an array.
|
|
167
328
|
*
|
|
@@ -209,7 +370,7 @@ var TypedFindCursor = class {
|
|
|
209
370
|
try {
|
|
210
371
|
return this.schema.parse(raw2);
|
|
211
372
|
} catch (err) {
|
|
212
|
-
if (err instanceof
|
|
373
|
+
if (err instanceof import_zod2.z.ZodError) {
|
|
213
374
|
throw new ZodmonValidationError(this.collectionName, err);
|
|
214
375
|
}
|
|
215
376
|
throw err;
|
|
@@ -229,7 +390,7 @@ async function findOne(handle, filter, options) {
|
|
|
229
390
|
try {
|
|
230
391
|
return handle.definition.schema.parse(raw2);
|
|
231
392
|
} catch (err) {
|
|
232
|
-
if (err instanceof
|
|
393
|
+
if (err instanceof import_zod3.z.ZodError) {
|
|
233
394
|
throw new ZodmonValidationError(handle.definition.name, err);
|
|
234
395
|
}
|
|
235
396
|
throw err;
|
|
@@ -246,17 +407,17 @@ function find(handle, filter, options) {
|
|
|
246
407
|
const raw2 = handle.native.find(filter);
|
|
247
408
|
const cursor = raw2;
|
|
248
409
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
249
|
-
return new TypedFindCursor(cursor, handle.definition, mode);
|
|
410
|
+
return new TypedFindCursor(cursor, handle.definition, mode, handle.native, filter);
|
|
250
411
|
}
|
|
251
412
|
|
|
252
413
|
// src/crud/insert.ts
|
|
253
|
-
var
|
|
414
|
+
var import_zod4 = require("zod");
|
|
254
415
|
async function insertOne(handle, doc) {
|
|
255
416
|
let parsed;
|
|
256
417
|
try {
|
|
257
418
|
parsed = handle.definition.schema.parse(doc);
|
|
258
419
|
} catch (err) {
|
|
259
|
-
if (err instanceof
|
|
420
|
+
if (err instanceof import_zod4.z.ZodError) {
|
|
260
421
|
throw new ZodmonValidationError(handle.definition.name, err);
|
|
261
422
|
}
|
|
262
423
|
throw err;
|
|
@@ -271,7 +432,7 @@ async function insertMany(handle, docs) {
|
|
|
271
432
|
try {
|
|
272
433
|
parsed.push(handle.definition.schema.parse(doc));
|
|
273
434
|
} catch (err) {
|
|
274
|
-
if (err instanceof
|
|
435
|
+
if (err instanceof import_zod4.z.ZodError) {
|
|
275
436
|
throw new ZodmonValidationError(handle.definition.name, err);
|
|
276
437
|
}
|
|
277
438
|
throw err;
|
|
@@ -281,6 +442,45 @@ async function insertMany(handle, docs) {
|
|
|
281
442
|
return parsed;
|
|
282
443
|
}
|
|
283
444
|
|
|
445
|
+
// src/crud/update.ts
|
|
446
|
+
var import_zod5 = require("zod");
|
|
447
|
+
async function updateOne(handle, filter, update, options) {
|
|
448
|
+
return await handle.native.updateOne(filter, update, options);
|
|
449
|
+
}
|
|
450
|
+
async function updateMany(handle, filter, update, options) {
|
|
451
|
+
return await handle.native.updateMany(filter, update, options);
|
|
452
|
+
}
|
|
453
|
+
async function findOneAndUpdate(handle, filter, update, options) {
|
|
454
|
+
const driverOptions = {
|
|
455
|
+
returnDocument: options?.returnDocument ?? "after",
|
|
456
|
+
includeResultMetadata: false
|
|
457
|
+
};
|
|
458
|
+
if (options?.upsert !== void 0) {
|
|
459
|
+
driverOptions["upsert"] = options.upsert;
|
|
460
|
+
}
|
|
461
|
+
const result = await handle.native.findOneAndUpdate(
|
|
462
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter
|
|
463
|
+
filter,
|
|
464
|
+
// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter
|
|
465
|
+
update,
|
|
466
|
+
// biome-ignore lint/suspicious/noExplicitAny: dynamic options object is not assignable to driver's FindOneAndUpdateOptions under exactOptionalPropertyTypes
|
|
467
|
+
driverOptions
|
|
468
|
+
);
|
|
469
|
+
if (!result) return null;
|
|
470
|
+
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
471
|
+
if (mode === false || mode === "passthrough") {
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
return handle.definition.schema.parse(result);
|
|
476
|
+
} catch (err) {
|
|
477
|
+
if (err instanceof import_zod5.z.ZodError) {
|
|
478
|
+
throw new ZodmonValidationError(handle.definition.name, err);
|
|
479
|
+
}
|
|
480
|
+
throw err;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
284
484
|
// src/client/handle.ts
|
|
285
485
|
var CollectionHandle = class {
|
|
286
486
|
/** The collection definition containing schema, name, and index metadata. */
|
|
@@ -402,6 +602,139 @@ var CollectionHandle = class {
|
|
|
402
602
|
find(filter, options) {
|
|
403
603
|
return find(this, filter, options);
|
|
404
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Update a single document matching the filter.
|
|
607
|
+
*
|
|
608
|
+
* Applies the update operators to the first document that matches the filter.
|
|
609
|
+
* Does not validate the update against the Zod schema — validation happens
|
|
610
|
+
* at the field-operator level through {@link TypedUpdateFilter}.
|
|
611
|
+
*
|
|
612
|
+
* @param filter - Type-safe filter to match documents.
|
|
613
|
+
* @param update - Type-safe update operators to apply.
|
|
614
|
+
* @param options - Optional settings such as `upsert`.
|
|
615
|
+
* @returns The MongoDB `UpdateResult` with match/modify counts.
|
|
616
|
+
*
|
|
617
|
+
* @example
|
|
618
|
+
* ```ts
|
|
619
|
+
* const users = db.use(Users)
|
|
620
|
+
* const result = await users.updateOne({ name: 'Ada' }, { $set: { role: 'admin' } })
|
|
621
|
+
* console.log(result.modifiedCount) // 1
|
|
622
|
+
* ```
|
|
623
|
+
*/
|
|
624
|
+
async updateOne(filter, update, options) {
|
|
625
|
+
return await updateOne(this, filter, update, options);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Update all documents matching the filter.
|
|
629
|
+
*
|
|
630
|
+
* Applies the update operators to every document that matches the filter.
|
|
631
|
+
* Does not validate the update against the Zod schema — validation happens
|
|
632
|
+
* at the field-operator level through {@link TypedUpdateFilter}.
|
|
633
|
+
*
|
|
634
|
+
* @param filter - Type-safe filter to match documents.
|
|
635
|
+
* @param update - Type-safe update operators to apply.
|
|
636
|
+
* @param options - Optional settings such as `upsert`.
|
|
637
|
+
* @returns The MongoDB `UpdateResult` with match/modify counts.
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```ts
|
|
641
|
+
* const users = db.use(Users)
|
|
642
|
+
* const result = await users.updateMany({ role: 'guest' }, { $set: { role: 'user' } })
|
|
643
|
+
* console.log(result.modifiedCount) // number of guests promoted
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
async updateMany(filter, update, options) {
|
|
647
|
+
return await updateMany(this, filter, update, options);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Find a single document matching the filter, apply an update, and return the document.
|
|
651
|
+
*
|
|
652
|
+
* By default, returns the document **after** the update is applied. Set
|
|
653
|
+
* `returnDocument: 'before'` to get the pre-update snapshot. The returned
|
|
654
|
+
* document is validated against the collection's Zod schema using the same
|
|
655
|
+
* resolution logic as {@link findOne}.
|
|
656
|
+
*
|
|
657
|
+
* @param filter - Type-safe filter to match documents.
|
|
658
|
+
* @param update - Type-safe update operators to apply.
|
|
659
|
+
* @param options - Optional settings: `returnDocument`, `upsert`, `validate`.
|
|
660
|
+
* @returns The matched document (before or after update), or `null` if no document matches.
|
|
661
|
+
* @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* ```ts
|
|
665
|
+
* const users = db.use(Users)
|
|
666
|
+
* const user = await users.findOneAndUpdate(
|
|
667
|
+
* { name: 'Ada' },
|
|
668
|
+
* { $set: { role: 'admin' } },
|
|
669
|
+
* )
|
|
670
|
+
* if (user) console.log(user.role) // 'admin' (returned after update)
|
|
671
|
+
* ```
|
|
672
|
+
*/
|
|
673
|
+
async findOneAndUpdate(filter, update, options) {
|
|
674
|
+
return await findOneAndUpdate(this, filter, update, options);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Delete a single document matching the filter.
|
|
678
|
+
*
|
|
679
|
+
* Removes the first document that matches the filter from the collection.
|
|
680
|
+
* No validation is performed — the document is deleted directly through
|
|
681
|
+
* the MongoDB driver.
|
|
682
|
+
*
|
|
683
|
+
* @param filter - Type-safe filter to match documents.
|
|
684
|
+
* @returns The MongoDB `DeleteResult` with the deleted count.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```ts
|
|
688
|
+
* const users = db.use(Users)
|
|
689
|
+
* const result = await users.deleteOne({ name: 'Ada' })
|
|
690
|
+
* console.log(result.deletedCount) // 1
|
|
691
|
+
* ```
|
|
692
|
+
*/
|
|
693
|
+
async deleteOne(filter) {
|
|
694
|
+
return await deleteOne(this, filter);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Delete all documents matching the filter.
|
|
698
|
+
*
|
|
699
|
+
* Removes every document that matches the filter from the collection.
|
|
700
|
+
* No validation is performed — documents are deleted directly through
|
|
701
|
+
* the MongoDB driver.
|
|
702
|
+
*
|
|
703
|
+
* @param filter - Type-safe filter to match documents.
|
|
704
|
+
* @returns The MongoDB `DeleteResult` with the deleted count.
|
|
705
|
+
*
|
|
706
|
+
* @example
|
|
707
|
+
* ```ts
|
|
708
|
+
* const users = db.use(Users)
|
|
709
|
+
* const result = await users.deleteMany({ role: 'guest' })
|
|
710
|
+
* console.log(result.deletedCount) // number of guests removed
|
|
711
|
+
* ```
|
|
712
|
+
*/
|
|
713
|
+
async deleteMany(filter) {
|
|
714
|
+
return await deleteMany(this, filter);
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Find a single document matching the filter, delete it, and return the document.
|
|
718
|
+
*
|
|
719
|
+
* Returns the deleted document, or `null` if no document matches the filter.
|
|
720
|
+
* The returned document is validated against the collection's Zod schema
|
|
721
|
+
* using the same resolution logic as {@link findOne}.
|
|
722
|
+
*
|
|
723
|
+
* @param filter - Type-safe filter to match documents.
|
|
724
|
+
* @param options - Optional settings: `validate`.
|
|
725
|
+
* @returns The deleted document, or `null` if no document matches.
|
|
726
|
+
* @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```ts
|
|
730
|
+
* const users = db.use(Users)
|
|
731
|
+
* const user = await users.findOneAndDelete({ name: 'Ada' })
|
|
732
|
+
* if (user) console.log(user.name) // 'Ada' (the deleted document)
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
735
|
+
async findOneAndDelete(filter, options) {
|
|
736
|
+
return await findOneAndDelete(this, filter, options);
|
|
737
|
+
}
|
|
405
738
|
};
|
|
406
739
|
|
|
407
740
|
// src/client/client.ts
|
|
@@ -411,7 +744,7 @@ var Database = class {
|
|
|
411
744
|
/** Registered collection definitions, keyed by name. Used by syncIndexes(). */
|
|
412
745
|
_collections = /* @__PURE__ */ new Map();
|
|
413
746
|
constructor(uri, dbName, options) {
|
|
414
|
-
this._client = new
|
|
747
|
+
this._client = new import_mongodb2.MongoClient(uri, options);
|
|
415
748
|
this._db = this._client.db(dbName);
|
|
416
749
|
}
|
|
417
750
|
/**
|
|
@@ -479,14 +812,14 @@ function createClient(uri, dbNameOrOptions, maybeOptions) {
|
|
|
479
812
|
}
|
|
480
813
|
|
|
481
814
|
// src/collection/collection.ts
|
|
482
|
-
var
|
|
483
|
-
var
|
|
815
|
+
var import_mongodb4 = require("mongodb");
|
|
816
|
+
var import_zod9 = require("zod");
|
|
484
817
|
|
|
485
818
|
// src/schema/extensions.ts
|
|
486
|
-
var
|
|
819
|
+
var import_zod7 = require("zod");
|
|
487
820
|
|
|
488
821
|
// src/schema/ref.ts
|
|
489
|
-
var
|
|
822
|
+
var import_zod6 = require("zod");
|
|
490
823
|
var refMetadata = /* @__PURE__ */ new WeakMap();
|
|
491
824
|
function getRefMetadata(schema) {
|
|
492
825
|
if (typeof schema !== "object" || schema === null) return void 0;
|
|
@@ -494,7 +827,7 @@ function getRefMetadata(schema) {
|
|
|
494
827
|
}
|
|
495
828
|
var REF_GUARD = /* @__PURE__ */ Symbol.for("zodmon_ref");
|
|
496
829
|
function installRefExtension() {
|
|
497
|
-
const proto =
|
|
830
|
+
const proto = import_zod6.z.ZodType.prototype;
|
|
498
831
|
if (REF_GUARD in proto) return;
|
|
499
832
|
Object.defineProperty(proto, "ref", {
|
|
500
833
|
value(collection2) {
|
|
@@ -521,7 +854,7 @@ function getIndexMetadata(schema) {
|
|
|
521
854
|
}
|
|
522
855
|
var GUARD = /* @__PURE__ */ Symbol.for("zodmon_extensions");
|
|
523
856
|
function installExtensions() {
|
|
524
|
-
const proto =
|
|
857
|
+
const proto = import_zod7.z.ZodType.prototype;
|
|
525
858
|
if (GUARD in proto) return;
|
|
526
859
|
Object.defineProperty(proto, "index", {
|
|
527
860
|
/**
|
|
@@ -619,14 +952,14 @@ function installExtensions() {
|
|
|
619
952
|
installExtensions();
|
|
620
953
|
|
|
621
954
|
// src/schema/object-id.ts
|
|
622
|
-
var
|
|
623
|
-
var
|
|
955
|
+
var import_mongodb3 = require("mongodb");
|
|
956
|
+
var import_zod8 = require("zod");
|
|
624
957
|
var OBJECT_ID_HEX = /^[a-f\d]{24}$/i;
|
|
625
958
|
function objectId() {
|
|
626
|
-
return
|
|
627
|
-
if (val instanceof
|
|
959
|
+
return import_zod8.z.custom((val) => {
|
|
960
|
+
if (val instanceof import_mongodb3.ObjectId) return true;
|
|
628
961
|
return typeof val === "string" && OBJECT_ID_HEX.test(val);
|
|
629
|
-
}, "Invalid ObjectId").transform((val) => val instanceof
|
|
962
|
+
}, "Invalid ObjectId").transform((val) => val instanceof import_mongodb3.ObjectId ? val : import_mongodb3.ObjectId.createFromHexString(val));
|
|
630
963
|
}
|
|
631
964
|
|
|
632
965
|
// src/collection/collection.ts
|
|
@@ -641,8 +974,8 @@ function extractFieldIndexes(shape) {
|
|
|
641
974
|
return result;
|
|
642
975
|
}
|
|
643
976
|
function collection(name, shape, options) {
|
|
644
|
-
const resolvedShape = "_id" in shape ? shape : { _id: objectId().default(() => new
|
|
645
|
-
const schema =
|
|
977
|
+
const resolvedShape = "_id" in shape ? shape : { _id: objectId().default(() => new import_mongodb4.ObjectId()), ...shape };
|
|
978
|
+
const schema = import_zod9.z.object(resolvedShape);
|
|
646
979
|
const fieldIndexes = extractFieldIndexes(shape);
|
|
647
980
|
const { indexes: compoundIndexes, validation, ...rest } = options ?? {};
|
|
648
981
|
return {
|
|
@@ -693,14 +1026,14 @@ function index(fields) {
|
|
|
693
1026
|
}
|
|
694
1027
|
|
|
695
1028
|
// src/helpers/oid.ts
|
|
696
|
-
var
|
|
1029
|
+
var import_mongodb5 = require("mongodb");
|
|
697
1030
|
function oid(value) {
|
|
698
|
-
if (value === void 0) return new
|
|
699
|
-
if (value instanceof
|
|
700
|
-
return
|
|
1031
|
+
if (value === void 0) return new import_mongodb5.ObjectId();
|
|
1032
|
+
if (value instanceof import_mongodb5.ObjectId) return value;
|
|
1033
|
+
return import_mongodb5.ObjectId.createFromHexString(value);
|
|
701
1034
|
}
|
|
702
1035
|
function isOid(value) {
|
|
703
|
-
return value instanceof
|
|
1036
|
+
return value instanceof import_mongodb5.ObjectId;
|
|
704
1037
|
}
|
|
705
1038
|
|
|
706
1039
|
// src/query/operators.ts
|
|
@@ -723,8 +1056,28 @@ var $or = (...filters) => ({ $or: filters });
|
|
|
723
1056
|
var $and = (...filters) => ({ $and: filters });
|
|
724
1057
|
var $nor = (...filters) => ({ $nor: filters });
|
|
725
1058
|
var raw = (filter) => filter;
|
|
1059
|
+
|
|
1060
|
+
// src/query/namespace.ts
|
|
1061
|
+
var $ = {
|
|
1062
|
+
eq: $eq,
|
|
1063
|
+
ne: $ne,
|
|
1064
|
+
gt: $gt,
|
|
1065
|
+
gte: $gte,
|
|
1066
|
+
lt: $lt,
|
|
1067
|
+
lte: $lte,
|
|
1068
|
+
in: $in,
|
|
1069
|
+
nin: $nin,
|
|
1070
|
+
exists: $exists,
|
|
1071
|
+
regex: $regex,
|
|
1072
|
+
not: $not,
|
|
1073
|
+
or: $or,
|
|
1074
|
+
and: $and,
|
|
1075
|
+
nor: $nor,
|
|
1076
|
+
raw
|
|
1077
|
+
};
|
|
726
1078
|
// Annotate the CommonJS export names for ESM import in node:
|
|
727
1079
|
0 && (module.exports = {
|
|
1080
|
+
$,
|
|
728
1081
|
$and,
|
|
729
1082
|
$eq,
|
|
730
1083
|
$exists,
|
|
@@ -747,21 +1100,25 @@ var raw = (filter) => filter;
|
|
|
747
1100
|
ZodmonValidationError,
|
|
748
1101
|
collection,
|
|
749
1102
|
createClient,
|
|
1103
|
+
deleteMany,
|
|
1104
|
+
deleteOne,
|
|
750
1105
|
extractDbName,
|
|
751
1106
|
extractFieldIndexes,
|
|
752
1107
|
find,
|
|
753
1108
|
findOne,
|
|
1109
|
+
findOneAndDelete,
|
|
1110
|
+
findOneAndUpdate,
|
|
754
1111
|
findOneOrThrow,
|
|
755
1112
|
getIndexMetadata,
|
|
756
1113
|
getRefMetadata,
|
|
757
1114
|
index,
|
|
758
1115
|
insertMany,
|
|
759
1116
|
insertOne,
|
|
760
|
-
installExtensions,
|
|
761
|
-
installRefExtension,
|
|
762
1117
|
isOid,
|
|
763
1118
|
objectId,
|
|
764
1119
|
oid,
|
|
765
|
-
raw
|
|
1120
|
+
raw,
|
|
1121
|
+
updateMany,
|
|
1122
|
+
updateOne
|
|
766
1123
|
});
|
|
767
1124
|
//# sourceMappingURL=index.cjs.map
|