@zodmon/core 0.7.0 → 0.8.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 +316 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +439 -15
- package/dist/index.d.ts +439 -15
- package/dist/index.js +309 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,168 @@
|
|
|
1
1
|
// src/client/client.ts
|
|
2
2
|
import { MongoClient } from "mongodb";
|
|
3
3
|
|
|
4
|
+
// src/indexes/spec.ts
|
|
5
|
+
function toFieldIndexSpec(def) {
|
|
6
|
+
const direction = def.text ? "text" : def.descending ? -1 : 1;
|
|
7
|
+
const key = { [def.field]: direction };
|
|
8
|
+
const options = {};
|
|
9
|
+
if (def.unique) options["unique"] = true;
|
|
10
|
+
if (def.sparse) options["sparse"] = true;
|
|
11
|
+
if (def.expireAfter !== void 0) options["expireAfterSeconds"] = def.expireAfter;
|
|
12
|
+
if (def.partial) options["partialFilterExpression"] = def.partial;
|
|
13
|
+
return { key, options };
|
|
14
|
+
}
|
|
15
|
+
function toCompoundIndexSpec(def) {
|
|
16
|
+
const key = { ...def.fields };
|
|
17
|
+
const options = {};
|
|
18
|
+
if (def.options?.unique) options["unique"] = true;
|
|
19
|
+
if (def.options?.sparse) options["sparse"] = true;
|
|
20
|
+
if (def.options?.name) options["name"] = def.options.name;
|
|
21
|
+
if (def.options?.partial) options["partialFilterExpression"] = def.options.partial;
|
|
22
|
+
return { key, options };
|
|
23
|
+
}
|
|
24
|
+
function serializeIndexKey(key) {
|
|
25
|
+
return Object.entries(key).map(([field, dir]) => `${field}:${dir}`).join(",");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/indexes/sync.ts
|
|
29
|
+
var COMPARABLE_OPTION_KEYS = [
|
|
30
|
+
"unique",
|
|
31
|
+
"sparse",
|
|
32
|
+
"expireAfterSeconds",
|
|
33
|
+
"partialFilterExpression"
|
|
34
|
+
];
|
|
35
|
+
function extractComparableOptions(info) {
|
|
36
|
+
const result = {};
|
|
37
|
+
for (const key of COMPARABLE_OPTION_KEYS) {
|
|
38
|
+
if (info[key] !== void 0) {
|
|
39
|
+
result[key] = info[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
function generateIndexName(key) {
|
|
45
|
+
return Object.entries(key).map(([field, dir]) => `${field}_${dir}`).join("_");
|
|
46
|
+
}
|
|
47
|
+
function sortKeys(obj) {
|
|
48
|
+
const sorted = {};
|
|
49
|
+
for (const key of Object.keys(obj).sort()) {
|
|
50
|
+
sorted[key] = obj[key];
|
|
51
|
+
}
|
|
52
|
+
return sorted;
|
|
53
|
+
}
|
|
54
|
+
function resolveSpecName(spec) {
|
|
55
|
+
const specName = spec.options["name"];
|
|
56
|
+
return typeof specName === "string" ? specName : generateIndexName(spec.key);
|
|
57
|
+
}
|
|
58
|
+
function resolveExistingName(info, key) {
|
|
59
|
+
const infoName = info["name"];
|
|
60
|
+
if (typeof infoName === "string") return infoName;
|
|
61
|
+
return generateIndexName(key);
|
|
62
|
+
}
|
|
63
|
+
function optionsMatch(a, b) {
|
|
64
|
+
return JSON.stringify(sortKeys(stripName(a))) === JSON.stringify(sortKeys(stripName(b)));
|
|
65
|
+
}
|
|
66
|
+
function stripName(obj) {
|
|
67
|
+
const { name: _, ...rest } = obj;
|
|
68
|
+
return rest;
|
|
69
|
+
}
|
|
70
|
+
async function processDesiredSpec(spec, existingByKey, native, dryRun, dropOrphaned, acc) {
|
|
71
|
+
const serialized = serializeIndexKey(spec.key);
|
|
72
|
+
const existing = existingByKey.get(serialized);
|
|
73
|
+
if (!existing) {
|
|
74
|
+
if (!dryRun) await native.createIndex(spec.key, spec.options);
|
|
75
|
+
acc.created.push(resolveSpecName(spec));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
acc.matchedKeys.add(serialized);
|
|
79
|
+
const existingName = resolveExistingName(existing, spec.key);
|
|
80
|
+
const existingOpts = extractComparableOptions(existing);
|
|
81
|
+
if (optionsMatch(existingOpts, spec.options)) {
|
|
82
|
+
acc.skipped.push(existingName);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (dropOrphaned) {
|
|
86
|
+
if (!dryRun) {
|
|
87
|
+
await native.dropIndex(existingName);
|
|
88
|
+
await native.createIndex(spec.key, spec.options);
|
|
89
|
+
}
|
|
90
|
+
acc.dropped.push(existingName);
|
|
91
|
+
acc.created.push(resolveSpecName(spec));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
acc.stale.push({
|
|
95
|
+
name: existingName,
|
|
96
|
+
key: spec.key,
|
|
97
|
+
existing: existingOpts,
|
|
98
|
+
desired: spec.options
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function processOrphanedIndexes(existingIndexes, desiredKeys, matchedKeys, native, dryRun, dropOrphaned, dropped) {
|
|
102
|
+
for (const idx of existingIndexes) {
|
|
103
|
+
const rawName = idx["name"];
|
|
104
|
+
const name = typeof rawName === "string" ? rawName : "";
|
|
105
|
+
if (name === "_id_") continue;
|
|
106
|
+
const serialized = serializeIndexKey(idx["key"]);
|
|
107
|
+
if (matchedKeys.has(serialized) || desiredKeys.has(serialized)) continue;
|
|
108
|
+
if (dropOrphaned) {
|
|
109
|
+
if (!dryRun) await native.dropIndex(name);
|
|
110
|
+
dropped.push(name);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function listIndexesSafe(native) {
|
|
115
|
+
try {
|
|
116
|
+
return await native.listIndexes().toArray();
|
|
117
|
+
} catch (err) {
|
|
118
|
+
if (err instanceof Error && err.message.includes("ns does not exist")) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function syncIndexes(handle, options) {
|
|
125
|
+
const { dryRun = false, dropOrphaned = false } = options ?? {};
|
|
126
|
+
const native = handle.native;
|
|
127
|
+
const def = handle.definition;
|
|
128
|
+
const desiredSpecs = [
|
|
129
|
+
...def.fieldIndexes.map(toFieldIndexSpec),
|
|
130
|
+
...def.compoundIndexes.map(toCompoundIndexSpec)
|
|
131
|
+
];
|
|
132
|
+
const existingIndexes = await listIndexesSafe(native);
|
|
133
|
+
const existingByKey = /* @__PURE__ */ new Map();
|
|
134
|
+
for (const idx of existingIndexes) {
|
|
135
|
+
const serialized = serializeIndexKey(idx["key"]);
|
|
136
|
+
existingByKey.set(serialized, idx);
|
|
137
|
+
}
|
|
138
|
+
const acc = {
|
|
139
|
+
created: [],
|
|
140
|
+
dropped: [],
|
|
141
|
+
skipped: [],
|
|
142
|
+
stale: [],
|
|
143
|
+
matchedKeys: /* @__PURE__ */ new Set()
|
|
144
|
+
};
|
|
145
|
+
for (const spec of desiredSpecs) {
|
|
146
|
+
await processDesiredSpec(spec, existingByKey, native, dryRun, dropOrphaned, acc);
|
|
147
|
+
}
|
|
148
|
+
const desiredKeys = new Set(desiredSpecs.map((s) => serializeIndexKey(s.key)));
|
|
149
|
+
await processOrphanedIndexes(
|
|
150
|
+
existingIndexes,
|
|
151
|
+
desiredKeys,
|
|
152
|
+
acc.matchedKeys,
|
|
153
|
+
native,
|
|
154
|
+
dryRun,
|
|
155
|
+
dropOrphaned,
|
|
156
|
+
acc.dropped
|
|
157
|
+
);
|
|
158
|
+
return {
|
|
159
|
+
created: acc.created,
|
|
160
|
+
dropped: acc.dropped,
|
|
161
|
+
skipped: acc.skipped,
|
|
162
|
+
stale: acc.stale
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
4
166
|
// src/crud/delete.ts
|
|
5
167
|
import { z } from "zod";
|
|
6
168
|
|
|
@@ -64,6 +226,29 @@ var ZodmonNotFoundError = class extends Error {
|
|
|
64
226
|
}
|
|
65
227
|
};
|
|
66
228
|
|
|
229
|
+
// src/indexes/warn.ts
|
|
230
|
+
var SKIP_OPERATORS = /* @__PURE__ */ new Set(["$or", "$and", "$nor", "$text", "$where", "$expr", "$comment"]);
|
|
231
|
+
function checkUnindexedFields(definition, filter) {
|
|
232
|
+
if (definition.options.warnUnindexedQueries !== true) return;
|
|
233
|
+
const covered = /* @__PURE__ */ new Set();
|
|
234
|
+
for (const fi of definition.fieldIndexes) {
|
|
235
|
+
covered.add(fi.field);
|
|
236
|
+
}
|
|
237
|
+
for (const ci of definition.compoundIndexes) {
|
|
238
|
+
const firstField = Object.keys(ci.fields)[0];
|
|
239
|
+
if (firstField !== void 0) {
|
|
240
|
+
covered.add(firstField);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
for (const key of Object.keys(filter)) {
|
|
244
|
+
if (key === "_id") continue;
|
|
245
|
+
if (SKIP_OPERATORS.has(key)) continue;
|
|
246
|
+
if (!covered.has(key)) {
|
|
247
|
+
console.warn(`[zodmon] warn: query on '${definition.name}' uses unindexed field '${key}'`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
67
252
|
// src/query/cursor.ts
|
|
68
253
|
import { z as z2 } from "zod";
|
|
69
254
|
|
|
@@ -81,8 +266,8 @@ function deserializeValue(value) {
|
|
|
81
266
|
}
|
|
82
267
|
return value;
|
|
83
268
|
}
|
|
84
|
-
function encodeCursor(doc,
|
|
85
|
-
const values =
|
|
269
|
+
function encodeCursor(doc, sortKeys2, direction) {
|
|
270
|
+
const values = sortKeys2.map(([field]) => serializeValue(doc[field]));
|
|
86
271
|
return btoa(JSON.stringify([direction, ...values]));
|
|
87
272
|
}
|
|
88
273
|
function decodeCursor(cursor) {
|
|
@@ -101,14 +286,14 @@ function decodeCursor(cursor) {
|
|
|
101
286
|
}
|
|
102
287
|
return { direction, values: rawValues.map(deserializeValue) };
|
|
103
288
|
}
|
|
104
|
-
function buildCursorFilter(
|
|
289
|
+
function buildCursorFilter(sortKeys2, values, isBackward) {
|
|
105
290
|
const clauses = [];
|
|
106
|
-
for (let i = 0; i <
|
|
291
|
+
for (let i = 0; i < sortKeys2.length; i++) {
|
|
107
292
|
const clause = {};
|
|
108
293
|
for (let j = 0; j < i; j++) {
|
|
109
|
-
clause[
|
|
294
|
+
clause[sortKeys2[j][0]] = values[j];
|
|
110
295
|
}
|
|
111
|
-
const [field, direction] =
|
|
296
|
+
const [field, direction] = sortKeys2[i];
|
|
112
297
|
const isAsc = direction === 1;
|
|
113
298
|
const op = isAsc !== isBackward ? "$gt" : "$lt";
|
|
114
299
|
if (values[i] === null) {
|
|
@@ -204,14 +389,37 @@ var TypedFindCursor = class {
|
|
|
204
389
|
this.cursor.limit(n);
|
|
205
390
|
return this;
|
|
206
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Force the query optimizer to use the specified index.
|
|
394
|
+
*
|
|
395
|
+
* Only accepts index names that were declared via `.name()` in the
|
|
396
|
+
* collection definition. If no named indexes exist, any string is accepted.
|
|
397
|
+
*
|
|
398
|
+
* @param indexName - The name of a declared compound index.
|
|
399
|
+
* @returns `this` for chaining.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* ```ts
|
|
403
|
+
* const Users = collection('users', { email: z.string(), role: z.string() }, {
|
|
404
|
+
* indexes: [index({ email: 1, role: -1 }).name('email_role_idx')],
|
|
405
|
+
* })
|
|
406
|
+
* const admins = await users.find({ role: 'admin' })
|
|
407
|
+
* .hint('email_role_idx')
|
|
408
|
+
* .toArray()
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
hint(indexName) {
|
|
412
|
+
this.cursor.hint(indexName);
|
|
413
|
+
return this;
|
|
414
|
+
}
|
|
207
415
|
async paginate(opts) {
|
|
208
416
|
const sortRecord = this.sortSpec ? this.sortSpec : null;
|
|
209
|
-
const
|
|
210
|
-
const sort = Object.fromEntries(
|
|
417
|
+
const sortKeys2 = resolveSortKeys(sortRecord);
|
|
418
|
+
const sort = Object.fromEntries(sortKeys2);
|
|
211
419
|
if ("page" in opts) {
|
|
212
|
-
return await this.offsetPaginate(
|
|
420
|
+
return await this.offsetPaginate(sortKeys2, sort, opts);
|
|
213
421
|
}
|
|
214
|
-
return await this.cursorPaginate(
|
|
422
|
+
return await this.cursorPaginate(sortKeys2, sort, opts);
|
|
215
423
|
}
|
|
216
424
|
/** @internal Offset pagination implementation. */
|
|
217
425
|
async offsetPaginate(_sortKeys, sort, opts) {
|
|
@@ -232,16 +440,16 @@ var TypedFindCursor = class {
|
|
|
232
440
|
};
|
|
233
441
|
}
|
|
234
442
|
/** @internal Cursor pagination implementation. */
|
|
235
|
-
async cursorPaginate(
|
|
443
|
+
async cursorPaginate(sortKeys2, sort, opts) {
|
|
236
444
|
let isBackward = false;
|
|
237
445
|
let combinedFilter = this.filter;
|
|
238
446
|
if (opts.cursor) {
|
|
239
447
|
const decoded = decodeCursor(opts.cursor);
|
|
240
448
|
isBackward = decoded.direction === "b";
|
|
241
|
-
const cursorFilter = buildCursorFilter(
|
|
449
|
+
const cursorFilter = buildCursorFilter(sortKeys2, decoded.values, isBackward);
|
|
242
450
|
combinedFilter = this.filter && Object.keys(this.filter).length > 0 ? { $and: [this.filter, cursorFilter] } : cursorFilter;
|
|
243
451
|
}
|
|
244
|
-
const effectiveSort = isBackward ? Object.fromEntries(
|
|
452
|
+
const effectiveSort = isBackward ? Object.fromEntries(sortKeys2.map(([f, d]) => [f, d === 1 ? -1 : 1])) : sort;
|
|
245
453
|
const raw2 = await this.nativeCollection.find(combinedFilter).sort(effectiveSort).limit(opts.limit + 1).toArray();
|
|
246
454
|
const hasMore = raw2.length > opts.limit;
|
|
247
455
|
if (hasMore) raw2.pop();
|
|
@@ -251,8 +459,8 @@ var TypedFindCursor = class {
|
|
|
251
459
|
docs,
|
|
252
460
|
hasNext: isBackward ? true : hasMore,
|
|
253
461
|
hasPrev: isBackward ? hasMore : opts.cursor != null,
|
|
254
|
-
startCursor: docs.length > 0 ? encodeCursor(docs[0],
|
|
255
|
-
endCursor: docs.length > 0 ? encodeCursor(docs[docs.length - 1],
|
|
462
|
+
startCursor: docs.length > 0 ? encodeCursor(docs[0], sortKeys2, "b") : null,
|
|
463
|
+
endCursor: docs.length > 0 ? encodeCursor(docs[docs.length - 1], sortKeys2, "f") : null
|
|
256
464
|
};
|
|
257
465
|
}
|
|
258
466
|
/**
|
|
@@ -312,6 +520,7 @@ var TypedFindCursor = class {
|
|
|
312
520
|
|
|
313
521
|
// src/crud/find.ts
|
|
314
522
|
async function findOne(handle, filter, options) {
|
|
523
|
+
checkUnindexedFields(handle.definition, filter);
|
|
315
524
|
const findOptions = options?.project ? { projection: options.project } : void 0;
|
|
316
525
|
const raw2 = await handle.native.findOne(filter, findOptions);
|
|
317
526
|
if (!raw2) return null;
|
|
@@ -336,6 +545,7 @@ async function findOneOrThrow(handle, filter, options) {
|
|
|
336
545
|
return doc;
|
|
337
546
|
}
|
|
338
547
|
function find(handle, filter, options) {
|
|
548
|
+
checkUnindexedFields(handle.definition, filter);
|
|
339
549
|
const raw2 = handle.native.find(filter);
|
|
340
550
|
const cursor = raw2;
|
|
341
551
|
const mode = options?.validate !== void 0 ? options.validate : handle.definition.options.validation;
|
|
@@ -667,6 +877,36 @@ var CollectionHandle = class {
|
|
|
667
877
|
async findOneAndDelete(filter, options) {
|
|
668
878
|
return await findOneAndDelete(this, filter, options);
|
|
669
879
|
}
|
|
880
|
+
/**
|
|
881
|
+
* Synchronize the indexes declared in this collection's schema with MongoDB.
|
|
882
|
+
*
|
|
883
|
+
* Compares the desired indexes (from field-level `.index()` / `.unique()` /
|
|
884
|
+
* `.text()` / `.expireAfter()` and compound `indexes` in collection options)
|
|
885
|
+
* with the indexes that currently exist in MongoDB, then creates, drops, or
|
|
886
|
+
* reports differences depending on the options.
|
|
887
|
+
*
|
|
888
|
+
* @param options - Optional sync behavior (dryRun, dropOrphaned).
|
|
889
|
+
* @returns A summary of created, dropped, skipped, and stale indexes.
|
|
890
|
+
*
|
|
891
|
+
* @example
|
|
892
|
+
* ```ts
|
|
893
|
+
* const users = db.use(Users)
|
|
894
|
+
* const result = await users.syncIndexes()
|
|
895
|
+
* console.log('Created:', result.created)
|
|
896
|
+
* console.log('Stale:', result.stale.map(s => s.name))
|
|
897
|
+
* ```
|
|
898
|
+
*
|
|
899
|
+
* @example
|
|
900
|
+
* ```ts
|
|
901
|
+
* // Dry run to preview changes without modifying the database
|
|
902
|
+
* const diff = await users.syncIndexes({ dryRun: true })
|
|
903
|
+
* console.log('Would create:', diff.created)
|
|
904
|
+
* console.log('Would drop:', diff.dropped)
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
async syncIndexes(options) {
|
|
908
|
+
return await syncIndexes(this, options);
|
|
909
|
+
}
|
|
670
910
|
};
|
|
671
911
|
|
|
672
912
|
// src/client/client.ts
|
|
@@ -692,19 +932,42 @@ var Database = class {
|
|
|
692
932
|
*/
|
|
693
933
|
use(def) {
|
|
694
934
|
this._collections.set(def.name, def);
|
|
695
|
-
const native = this._db.collection(
|
|
935
|
+
const native = this._db.collection(
|
|
936
|
+
def.name
|
|
937
|
+
);
|
|
696
938
|
return new CollectionHandle(
|
|
697
939
|
def,
|
|
698
940
|
native
|
|
699
941
|
);
|
|
700
942
|
}
|
|
701
943
|
/**
|
|
702
|
-
* Synchronize indexes
|
|
944
|
+
* Synchronize indexes for all registered collections with MongoDB.
|
|
945
|
+
*
|
|
946
|
+
* Iterates every collection registered via {@link use} and calls
|
|
947
|
+
* {@link syncIndexes} on each one. Returns a record keyed by collection
|
|
948
|
+
* name with the sync result for each.
|
|
949
|
+
*
|
|
950
|
+
* @param options - Optional sync behavior (dryRun, dropOrphaned).
|
|
951
|
+
* @returns A record mapping collection names to their sync results.
|
|
703
952
|
*
|
|
704
|
-
*
|
|
953
|
+
* @example
|
|
954
|
+
* ```ts
|
|
955
|
+
* const db = createClient('mongodb://localhost:27017', 'myapp')
|
|
956
|
+
* db.use(Users)
|
|
957
|
+
* db.use(Posts)
|
|
958
|
+
* const results = await db.syncIndexes()
|
|
959
|
+
* console.log(results['users'].created) // ['email_1']
|
|
960
|
+
* console.log(results['posts'].created) // ['title_1']
|
|
961
|
+
* ```
|
|
705
962
|
*/
|
|
706
|
-
syncIndexes() {
|
|
707
|
-
|
|
963
|
+
async syncIndexes(options) {
|
|
964
|
+
const results = {};
|
|
965
|
+
for (const [name, def] of this._collections) {
|
|
966
|
+
const native = this._db.collection(name);
|
|
967
|
+
const handle = new CollectionHandle(def, native);
|
|
968
|
+
results[name] = await syncIndexes(handle, options);
|
|
969
|
+
}
|
|
970
|
+
return results;
|
|
708
971
|
}
|
|
709
972
|
/**
|
|
710
973
|
* Execute a function within a MongoDB transaction with auto-commit/rollback.
|
|
@@ -919,6 +1182,8 @@ function collection(name, shape, options) {
|
|
|
919
1182
|
schema,
|
|
920
1183
|
shape,
|
|
921
1184
|
fieldIndexes,
|
|
1185
|
+
// Safe cast: compoundIndexes is TIndexes at runtime (or an empty array when
|
|
1186
|
+
// no options provided). The spread into [...TIndexes] preserves the tuple type.
|
|
922
1187
|
compoundIndexes: compoundIndexes ?? [],
|
|
923
1188
|
options: {
|
|
924
1189
|
validation: validation ?? "strict",
|
|
@@ -943,12 +1208,29 @@ var IndexBuilder = class _IndexBuilder {
|
|
|
943
1208
|
options
|
|
944
1209
|
});
|
|
945
1210
|
}
|
|
1211
|
+
// Safe cast: _clone returns IndexBuilder<TKeys> but `this` may carry an
|
|
1212
|
+
// intersection from .name(). The cast is safe because _clone preserves all fields.
|
|
946
1213
|
unique() {
|
|
947
1214
|
return this._clone({ ...this.options, unique: true });
|
|
948
1215
|
}
|
|
1216
|
+
// Safe cast: same reasoning as unique().
|
|
949
1217
|
sparse() {
|
|
950
1218
|
return this._clone({ ...this.options, sparse: true });
|
|
951
1219
|
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Set a custom name for this index, preserving the literal type.
|
|
1222
|
+
*
|
|
1223
|
+
* The returned builder carries the literal name type via an intersection,
|
|
1224
|
+
* enabling type-safe `.hint()` on cursors that only accepts declared names.
|
|
1225
|
+
*
|
|
1226
|
+
* @param name - The index name.
|
|
1227
|
+
* @returns A new IndexBuilder with the name recorded at the type level.
|
|
1228
|
+
*
|
|
1229
|
+
* @example
|
|
1230
|
+
* ```ts
|
|
1231
|
+
* index({ email: 1, role: -1 }).name('email_role_idx')
|
|
1232
|
+
* ```
|
|
1233
|
+
*/
|
|
952
1234
|
name(name) {
|
|
953
1235
|
return this._clone({ ...this.options, name });
|
|
954
1236
|
}
|
|
@@ -1029,10 +1311,12 @@ export {
|
|
|
1029
1311
|
TypedFindCursor,
|
|
1030
1312
|
ZodmonNotFoundError,
|
|
1031
1313
|
ZodmonValidationError,
|
|
1314
|
+
checkUnindexedFields,
|
|
1032
1315
|
collection,
|
|
1033
1316
|
createClient,
|
|
1034
1317
|
deleteMany,
|
|
1035
1318
|
deleteOne,
|
|
1319
|
+
extractComparableOptions,
|
|
1036
1320
|
extractDbName,
|
|
1037
1321
|
extractFieldIndexes,
|
|
1038
1322
|
find,
|
|
@@ -1040,6 +1324,7 @@ export {
|
|
|
1040
1324
|
findOneAndDelete,
|
|
1041
1325
|
findOneAndUpdate,
|
|
1042
1326
|
findOneOrThrow,
|
|
1327
|
+
generateIndexName,
|
|
1043
1328
|
getIndexMetadata,
|
|
1044
1329
|
getRefMetadata,
|
|
1045
1330
|
index,
|
|
@@ -1049,6 +1334,10 @@ export {
|
|
|
1049
1334
|
objectId,
|
|
1050
1335
|
oid,
|
|
1051
1336
|
raw,
|
|
1337
|
+
serializeIndexKey,
|
|
1338
|
+
syncIndexes,
|
|
1339
|
+
toCompoundIndexSpec,
|
|
1340
|
+
toFieldIndexSpec,
|
|
1052
1341
|
updateMany,
|
|
1053
1342
|
updateOne
|
|
1054
1343
|
};
|