@classytic/mongokit 3.11.1 → 3.13.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/README.md +75 -5
- package/dist/{PaginationEngine-CvDFfVXT.mjs → PaginationEngine-CfQRM1yz.mjs} +16 -16
- package/dist/Repository-BY40uhcv.mjs +3603 -0
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/adapter/index.d.mts +190 -0
- package/dist/adapter/index.mjs +2 -0
- package/dist/adapter-DTDMnUOH.mjs +158 -0
- package/dist/ai/index.d.mts +1 -1
- package/dist/ai/index.mjs +3 -3
- package/dist/better-auth/index.d.mts +149 -0
- package/dist/better-auth/index.mjs +81 -0
- package/dist/field-selection-Br3WPOEb.mjs +99 -0
- package/dist/{index-dNTmpgK8.d.mts → index-BbHaKwi5.d.mts} +33 -13
- package/dist/index.d.mts +678 -36
- package/dist/index.mjs +240 -17
- package/dist/{logger-DJ7egMnd.mjs → logger-DprijP5h.mjs} +1 -5
- package/dist/{mongooseToJsonSchema-D1sdCOmj.mjs → mongooseToJsonSchema-BYbG894y.mjs} +68 -20
- package/dist/{mongooseToJsonSchema-DXxjFkLB.d.mts → mongooseToJsonSchema-BgRAaXX-.d.mts} +10 -2
- package/dist/pagination/PaginationEngine.d.mts +3 -2
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/index.mjs +2 -2
- package/dist/query/primitives/coercion.d.mts +1 -1
- package/dist/query/primitives/coercion.mjs +1 -1
- package/dist/query/primitives/indexes.d.mts +1 -1
- package/dist/{types-Dc2aDVUi.d.mts → types-BbaPZleN.d.mts} +419 -205
- package/dist/{update-DEJYcgfV.mjs → update-DLcSSa5b.mjs} +184 -45
- package/dist/utils/index.d.mts +2 -91
- package/dist/utils/index.mjs +5 -5
- package/dist/{validation-chain.plugin-B0VSdcwa.d.mts → validation-chain.plugin-CAPYCj_T.d.mts} +228 -98
- package/dist/validation-chain.plugin-_-WuNml2.mjs +2399 -0
- package/package.json +25 -5
- package/dist/field-selection-dI0m4RBs.mjs +0 -221
- package/dist/validation-chain.plugin-Dllv-cml.mjs +0 -5122
- /package/dist/{coercion-oM8G4b6m.d.mts → coercion-TRMmR49h.d.mts} +0 -0
- /package/dist/{id-resolution-e4BT9zAV.mjs → id-resolution-B0Odvvou.mjs} +0 -0
- /package/dist/{indexes-C26GNZRU.d.mts → indexes-CgOF7Wjd.d.mts} +0 -0
|
@@ -1,6 +1,103 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { n as warn } from "./logger-DprijP5h.mjs";
|
|
3
3
|
import { t as createError } from "./error-B00pI7dV.mjs";
|
|
4
|
+
import { isFilter } from "@classytic/repo-core/filter";
|
|
5
|
+
//#region src/filter/compile.ts
|
|
6
|
+
/**
|
|
7
|
+
* Compile a Filter IR node to a MongoDB query object. Returns `{}`
|
|
8
|
+
* when the node is `TRUE` (or an empty `and`) so callers can merge
|
|
9
|
+
* with other scopes without special-casing.
|
|
10
|
+
*
|
|
11
|
+
* The `input` is typed as `unknown` so callers can pass either a
|
|
12
|
+
* Filter IR node or an already-built Mongo query and we dispatch
|
|
13
|
+
* appropriately. This keeps the portable API ergonomic for apps that
|
|
14
|
+
* write Mongo queries directly today.
|
|
15
|
+
*/
|
|
16
|
+
function compileFilterToMongo(input) {
|
|
17
|
+
if (!input) return {};
|
|
18
|
+
if (!isFilter(input)) return input;
|
|
19
|
+
return compile(input);
|
|
20
|
+
}
|
|
21
|
+
function compile(filter) {
|
|
22
|
+
switch (filter.op) {
|
|
23
|
+
case "true": return {};
|
|
24
|
+
case "false": return { $expr: false };
|
|
25
|
+
case "eq": return { [filter.field]: filter.value };
|
|
26
|
+
case "ne": return filter.value === null ? { [filter.field]: { $ne: null } } : { $and: [{ [filter.field]: { $ne: filter.value } }, { [filter.field]: { $ne: null } }] };
|
|
27
|
+
case "gt": return { [filter.field]: { $gt: filter.value } };
|
|
28
|
+
case "gte": return { [filter.field]: { $gte: filter.value } };
|
|
29
|
+
case "lt": return { [filter.field]: { $lt: filter.value } };
|
|
30
|
+
case "lte": return { [filter.field]: { $lte: filter.value } };
|
|
31
|
+
case "in":
|
|
32
|
+
if (filter.values.length === 0) return { $expr: false };
|
|
33
|
+
return { [filter.field]: { $in: [...filter.values] } };
|
|
34
|
+
case "nin":
|
|
35
|
+
if (filter.values.length === 0) return {};
|
|
36
|
+
return { [filter.field]: { $nin: [...filter.values] } };
|
|
37
|
+
case "exists": return filter.exists ? { [filter.field]: { $ne: null } } : { [filter.field]: null };
|
|
38
|
+
case "like": return { [filter.field]: likeToRegex(filter.pattern, filter.caseSensitivity) };
|
|
39
|
+
case "regex": return { [filter.field]: { $regex: filter.pattern } };
|
|
40
|
+
case "and": {
|
|
41
|
+
if (filter.children.length === 0) return {};
|
|
42
|
+
const parts = filter.children.map(compile);
|
|
43
|
+
if (parts.length === 1) return parts[0];
|
|
44
|
+
return { $and: parts };
|
|
45
|
+
}
|
|
46
|
+
case "or": {
|
|
47
|
+
if (filter.children.length === 0) return { $expr: false };
|
|
48
|
+
const parts = filter.children.map(compile);
|
|
49
|
+
if (parts.length === 1) return parts[0];
|
|
50
|
+
return { $or: parts };
|
|
51
|
+
}
|
|
52
|
+
case "not": return { $nor: [compile(filter.child)] };
|
|
53
|
+
case "raw": throw new Error("mongokit/filter: `raw` is a SQL escape hatch and has no safe MongoDB translation. Pass a Mongo query object directly to the filter slot instead.");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Translate a SQL-style LIKE pattern to a MongoDB regex.
|
|
58
|
+
*
|
|
59
|
+
* SQL semantics:
|
|
60
|
+
* - `%` → match zero or more characters (`.*`)
|
|
61
|
+
* - `_` → match exactly one character (`.`)
|
|
62
|
+
* - `\%` → literal percent (escape via backslash)
|
|
63
|
+
* - `\_` → literal underscore
|
|
64
|
+
* - `\\` → literal backslash
|
|
65
|
+
* - everything else is literal — regex metacharacters get escaped.
|
|
66
|
+
*
|
|
67
|
+
* The naive implementation `pattern.replace(/%/g, '.*')` is wrong:
|
|
68
|
+
* it also expands escaped `\%` into a wildcard. We walk the pattern
|
|
69
|
+
* char-by-char, honoring backslash escapes, so `like('notes', '50\\% off')`
|
|
70
|
+
* matches the literal string `50% off` instead of `50<anything> off`.
|
|
71
|
+
*
|
|
72
|
+
* Anchored with `^` / `$` so LIKE matches the whole field value, the
|
|
73
|
+
* same way sqlitekit's `LIKE` semantically does.
|
|
74
|
+
*/
|
|
75
|
+
function likeToRegex(pattern, caseSensitivity) {
|
|
76
|
+
let out = "^";
|
|
77
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
78
|
+
const ch = pattern[i];
|
|
79
|
+
if (ch === "\\" && i + 1 < pattern.length) {
|
|
80
|
+
const next = pattern[i + 1];
|
|
81
|
+
if (next === "%" || next === "_" || next === "\\") {
|
|
82
|
+
out += escapeRegexChar(next);
|
|
83
|
+
i++;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (ch === "%") out += ".*";
|
|
88
|
+
else if (ch === "_") out += ".";
|
|
89
|
+
else out += escapeRegexChar(ch);
|
|
90
|
+
}
|
|
91
|
+
out += "$";
|
|
92
|
+
return caseSensitivity === "sensitive" ? { $regex: out } : {
|
|
93
|
+
$regex: out,
|
|
94
|
+
$options: "i"
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function escapeRegexChar(ch) {
|
|
98
|
+
return /[.*+?^${}()|[\]\\]/.test(ch) ? `\\${ch}` : ch;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
4
101
|
//#region src/query/LookupBuilder.ts
|
|
5
102
|
/** Stages that are never valid inside a $lookup pipeline */
|
|
6
103
|
const BLOCKED_PIPELINE_STAGES = [
|
|
@@ -191,28 +288,24 @@ var LookupBuilder = class LookupBuilder {
|
|
|
191
288
|
const builder = new LookupBuilder(lookup.from).localField(lookup.localField).foreignField(lookup.foreignField);
|
|
192
289
|
if (lookup.as) builder.as(lookup.as);
|
|
193
290
|
if (lookup.single) builder.single(lookup.single);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
]);
|
|
291
|
+
const stages = [];
|
|
292
|
+
const appendCallerStages = (raw) => {
|
|
293
|
+
if (raw.length === 0) return;
|
|
294
|
+
stages.push(...LookupBuilder.sanitizePipeline(raw));
|
|
295
|
+
};
|
|
296
|
+
const compiledWhere = lookup.where ? compileFilterToMongo(lookup.where) : void 0;
|
|
297
|
+
const hasWhere = !!compiledWhere && Object.keys(compiledWhere).length > 0;
|
|
298
|
+
if (!!(lookup.select || lookup.pipeline || hasWhere)) {
|
|
299
|
+
stages.push({ $match: { $expr: { $eq: [`$${lookup.foreignField}`, "$$lookupJoinVal"] } } });
|
|
300
|
+
if (hasWhere && compiledWhere) appendCallerStages([{ $match: compiledWhere }]);
|
|
301
|
+
if (lookup.pipeline) appendCallerStages(lookup.pipeline);
|
|
302
|
+
if (lookup.select) stages.push({ $project: compileSelectToProjection(lookup.select) });
|
|
303
|
+
builder.pipeline(stages);
|
|
208
304
|
builder.let({
|
|
209
305
|
lookupJoinVal: `$${lookup.localField}`,
|
|
210
306
|
...lookup.let || {}
|
|
211
307
|
});
|
|
212
308
|
builder.sanitize(false);
|
|
213
|
-
} else if (lookup.pipeline) {
|
|
214
|
-
builder.pipeline(lookup.pipeline);
|
|
215
|
-
if (lookup.let) builder.let(lookup.let);
|
|
216
309
|
} else if (lookup.let) builder.let(lookup.let);
|
|
217
310
|
return builder.build();
|
|
218
311
|
});
|
|
@@ -281,6 +374,38 @@ var LookupBuilder = class LookupBuilder {
|
|
|
281
374
|
}
|
|
282
375
|
};
|
|
283
376
|
/**
|
|
377
|
+
* Normalize the three accepted `LookupOptions.select` shapes into a single
|
|
378
|
+
* Mongo `$project` map.
|
|
379
|
+
*
|
|
380
|
+
* - `string` → CSV form, leading `-` excludes (`'name,-status'`)
|
|
381
|
+
* - `readonly string[]` → array form, leading `-` excludes (`['-status']`)
|
|
382
|
+
* - `Record<string, 0|1>` → already a projection map, copied as-is
|
|
383
|
+
*
|
|
384
|
+
* The array form mirrors `repo-core`'s `LookupSpec.select` so cross-kit
|
|
385
|
+
* callers (`select: ['name']`) compile identically on mongokit and sqlitekit.
|
|
386
|
+
*/
|
|
387
|
+
function compileSelectToProjection(select) {
|
|
388
|
+
if (typeof select === "string") {
|
|
389
|
+
const projection = {};
|
|
390
|
+
for (const field of select.split(",").map((f) => f.trim())) {
|
|
391
|
+
if (!field) continue;
|
|
392
|
+
if (field.startsWith("-")) projection[field.substring(1)] = 0;
|
|
393
|
+
else projection[field] = 1;
|
|
394
|
+
}
|
|
395
|
+
return projection;
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(select)) {
|
|
398
|
+
const projection = {};
|
|
399
|
+
for (const field of select) {
|
|
400
|
+
if (!field) continue;
|
|
401
|
+
if (field.startsWith("-")) projection[field.substring(1)] = 0;
|
|
402
|
+
else projection[field] = 1;
|
|
403
|
+
}
|
|
404
|
+
return projection;
|
|
405
|
+
}
|
|
406
|
+
return { ...select };
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
284
409
|
* Performance Guidelines for $lookup at Scale:
|
|
285
410
|
*
|
|
286
411
|
* 1. **Index Requirements** (Critical for millions of records):
|
|
@@ -350,17 +475,17 @@ async function aggregatePaginate(Model, pipeline, options = {}) {
|
|
|
350
475
|
const skip = (page - 1) * limit;
|
|
351
476
|
if (limit > 1e3) warn(`[mongokit] Large aggregation limit (${limit}). $facet results must be <16MB. Consider using Repository.aggregatePaginate() for safer handling of large datasets.`);
|
|
352
477
|
const facetPipeline = [...pipeline, { $facet: {
|
|
353
|
-
|
|
478
|
+
data: [{ $skip: skip }, { $limit: limit }],
|
|
354
479
|
total: [{ $count: "count" }]
|
|
355
480
|
} }];
|
|
356
481
|
const aggregation = Model.aggregate(facetPipeline);
|
|
357
482
|
if (options.session) aggregation.session(options.session);
|
|
358
483
|
const [result] = await aggregation.exec();
|
|
359
|
-
const
|
|
484
|
+
const data = result.data || [];
|
|
360
485
|
const total = result.total[0]?.count || 0;
|
|
361
486
|
const pages = Math.ceil(total / limit);
|
|
362
487
|
return {
|
|
363
|
-
|
|
488
|
+
data,
|
|
364
489
|
total,
|
|
365
490
|
page,
|
|
366
491
|
limit,
|
|
@@ -537,54 +662,49 @@ var delete_exports = /* @__PURE__ */ __exportAll({
|
|
|
537
662
|
softDelete: () => softDelete
|
|
538
663
|
});
|
|
539
664
|
/**
|
|
540
|
-
* Delete by ID
|
|
665
|
+
* Delete by ID. Returns `null` on miss (matches `update()` convention) —
|
|
666
|
+
* a second delete on the same id is a no-op, not an error.
|
|
541
667
|
*/
|
|
542
668
|
async function deleteById(Model, id, options = {}) {
|
|
543
669
|
const query = {
|
|
544
670
|
_id: id,
|
|
545
671
|
...options.query
|
|
546
672
|
};
|
|
547
|
-
if (!await Model.findOneAndDelete(query).session(options.session ?? null)) return
|
|
548
|
-
success: false,
|
|
549
|
-
message: "Document not found",
|
|
550
|
-
id: String(id)
|
|
551
|
-
};
|
|
673
|
+
if (!await Model.findOneAndDelete(query).session(options.session ?? null)) return null;
|
|
552
674
|
return {
|
|
553
|
-
success: true,
|
|
554
675
|
message: "Deleted successfully",
|
|
555
676
|
id: String(id)
|
|
556
677
|
};
|
|
557
678
|
}
|
|
558
679
|
/**
|
|
559
|
-
* Delete many documents
|
|
680
|
+
* Delete many documents. Always returns a {@link DeleteResult} (never
|
|
681
|
+
* null) — a deleteMany with zero matches is a successful op with
|
|
682
|
+
* `count: 0`, not a miss.
|
|
560
683
|
*/
|
|
561
684
|
async function deleteMany(Model, query, options = {}) {
|
|
562
685
|
return {
|
|
563
|
-
success: true,
|
|
564
686
|
count: (await Model.deleteMany(query).session(options.session ?? null)).deletedCount,
|
|
565
687
|
message: "Deleted successfully"
|
|
566
688
|
};
|
|
567
689
|
}
|
|
568
690
|
/**
|
|
569
|
-
* Delete by query
|
|
691
|
+
* Delete by query. Returns `null` on miss unless `throwOnNotFound: true`.
|
|
570
692
|
*/
|
|
571
693
|
async function deleteByQuery(Model, query, options = {}) {
|
|
572
694
|
const document = await Model.findOneAndDelete(query).session(options.session ?? null);
|
|
573
695
|
if (!document) {
|
|
574
696
|
if (options.throwOnNotFound === true) throw createError(404, "Document not found");
|
|
575
|
-
return
|
|
576
|
-
success: false,
|
|
577
|
-
message: "Document not found"
|
|
578
|
-
};
|
|
697
|
+
return null;
|
|
579
698
|
}
|
|
580
699
|
return {
|
|
581
|
-
success: true,
|
|
582
700
|
message: "Deleted successfully",
|
|
583
701
|
id: String(document._id)
|
|
584
702
|
};
|
|
585
703
|
}
|
|
586
704
|
/**
|
|
587
|
-
* Soft delete (set deleted flag)
|
|
705
|
+
* Soft delete (set deleted flag). Returns `null` on miss for parity with
|
|
706
|
+
* `deleteById`; callers that prefer a throw can wrap or use `throwOnNotFound`
|
|
707
|
+
* pattern at the call site.
|
|
588
708
|
*/
|
|
589
709
|
async function softDelete(Model, id, options = {}) {
|
|
590
710
|
if (!await Model.findByIdAndUpdate(id, {
|
|
@@ -594,16 +714,15 @@ async function softDelete(Model, id, options = {}) {
|
|
|
594
714
|
}, {
|
|
595
715
|
returnDocument: "after",
|
|
596
716
|
session: options.session
|
|
597
|
-
}))
|
|
717
|
+
})) return null;
|
|
598
718
|
return {
|
|
599
|
-
success: true,
|
|
600
719
|
message: "Soft deleted successfully",
|
|
601
720
|
id: String(id),
|
|
602
721
|
soft: true
|
|
603
722
|
};
|
|
604
723
|
}
|
|
605
724
|
/**
|
|
606
|
-
* Restore soft
|
|
725
|
+
* Restore soft-deleted document. Returns `null` on miss.
|
|
607
726
|
*/
|
|
608
727
|
async function restore(Model, id, options = {}) {
|
|
609
728
|
if (!await Model.findByIdAndUpdate(id, {
|
|
@@ -613,9 +732,8 @@ async function restore(Model, id, options = {}) {
|
|
|
613
732
|
}, {
|
|
614
733
|
returnDocument: "after",
|
|
615
734
|
session: options.session
|
|
616
|
-
}))
|
|
735
|
+
})) return null;
|
|
617
736
|
return {
|
|
618
|
-
success: true,
|
|
619
737
|
message: "Restored successfully",
|
|
620
738
|
id: String(id)
|
|
621
739
|
};
|
|
@@ -709,16 +827,37 @@ async function getAll(Model, query = {}, options = {}) {
|
|
|
709
827
|
return mongoQuery.exec();
|
|
710
828
|
}
|
|
711
829
|
/**
|
|
712
|
-
* Get or create document (upsert)
|
|
830
|
+
* Get or create document (atomic upsert).
|
|
831
|
+
*
|
|
832
|
+
* Returns `{ doc, created }` so callers can disambiguate the two
|
|
833
|
+
* outcomes without a follow-up read — load-bearing for race-detection
|
|
834
|
+
* in idempotency stores, lock acquisition, and "ensure-exists" flows.
|
|
835
|
+
*
|
|
836
|
+
* `created: true` ⇔ this caller's `createData` won the race and was
|
|
837
|
+
* just inserted; `created: false` ⇔ a doc matching `query` already
|
|
838
|
+
* existed and was returned unchanged.
|
|
839
|
+
*
|
|
840
|
+
* Mongo: `includeResultMetadata: true` returns the raw `ModifyResult`
|
|
841
|
+
* (`{ value, lastErrorObject, ok }`). `lastErrorObject.upserted` is
|
|
842
|
+
* the `_id` of a freshly-inserted row — present iff this call inserted.
|
|
713
843
|
*/
|
|
714
844
|
async function getOrCreate(Model, query, createData, options = {}) {
|
|
715
|
-
|
|
845
|
+
const result = await Model.findOneAndUpdate(query, { $setOnInsert: createData }, {
|
|
716
846
|
upsert: true,
|
|
717
847
|
returnDocument: "after",
|
|
718
848
|
runValidators: true,
|
|
849
|
+
includeResultMetadata: true,
|
|
719
850
|
session: options.session,
|
|
720
851
|
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
721
852
|
});
|
|
853
|
+
if (result && typeof result === "object" && "value" in result) return {
|
|
854
|
+
doc: result.value,
|
|
855
|
+
created: result.lastErrorObject?.upserted != null
|
|
856
|
+
};
|
|
857
|
+
return {
|
|
858
|
+
doc: result,
|
|
859
|
+
created: false
|
|
860
|
+
};
|
|
722
861
|
}
|
|
723
862
|
/**
|
|
724
863
|
* Count documents matching query
|
|
@@ -918,4 +1057,4 @@ async function pullFromArray(Model, id, field, value, options = {}) {
|
|
|
918
1057
|
return update(Model, id, { $pull: { [field]: value } }, options);
|
|
919
1058
|
}
|
|
920
1059
|
//#endregion
|
|
921
|
-
export { upsert as _, count as a, LookupBuilder as b, getByQuery as c, deleteById as d, deleteByQuery as f, create_exports as g, createMany as h, update_exports as i, getOrCreate as l, create as m, update as n, exists as o, delete_exports as p, updateByQuery as r, getById as s, findOneAndUpdate as t, read_exports as u, aggregate_exports as v, distinct as y };
|
|
1060
|
+
export { upsert as _, count as a, LookupBuilder as b, getByQuery as c, deleteById as d, deleteByQuery as f, create_exports as g, createMany as h, update_exports as i, getOrCreate as l, create as m, update as n, exists as o, delete_exports as p, updateByQuery as r, getById as s, findOneAndUpdate as t, read_exports as u, aggregate_exports as v, compileFilterToMongo as x, distinct as y };
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,94 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as createFieldPreset, c as getMongooseProjection, i as configureLogger, l as createError, n as buildCrudSchemasFromMongooseSchema, o as filterResponseData, r as createMemoryCache, s as getFieldsForUser, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-DXxjFkLB.mjs";
|
|
1
|
+
import { a as createFieldPreset, c as getMongooseProjection, i as configureLogger, l as createError, n as buildCrudSchemasFromMongooseSchema, o as filterResponseData, r as createMemoryCache, s as getFieldsForUser, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-BgRAaXX-.mjs";
|
|
3
2
|
|
|
4
|
-
//#region src/utils/cache-keys.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Generate cache key for getById operations
|
|
7
|
-
*
|
|
8
|
-
* Includes select/populate/lean in the key so different query shapes
|
|
9
|
-
* (e.g., plain vs populated, lean vs hydrated) never collide.
|
|
10
|
-
*
|
|
11
|
-
* Format: {prefix}:id:{model}:{documentId} (no options)
|
|
12
|
-
* Format: {prefix}:id:{model}:{documentId}:{optionsHash} (with options)
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* byIdKey('mk', 'User', '507f1f77bcf86cd799439011')
|
|
16
|
-
* // => 'mk:id:User:507f1f77bcf86cd799439011'
|
|
17
|
-
* byIdKey('mk', 'User', '507f1f77bcf86cd799439011', { select: 'name email' })
|
|
18
|
-
* // => 'mk:id:User:507f1f77bcf86cd799439011:a1b2c3d4'
|
|
19
|
-
*/
|
|
20
|
-
declare function byIdKey(prefix: string, model: string, id: string, options?: {
|
|
21
|
-
select?: SelectSpec;
|
|
22
|
-
populate?: PopulateSpec;
|
|
23
|
-
lean?: boolean;
|
|
24
|
-
}): string;
|
|
25
|
-
/**
|
|
26
|
-
* Generate cache key for single-document queries
|
|
27
|
-
*
|
|
28
|
-
* Format: {prefix}:one:{model}:{queryHash}
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* byQueryKey('mk', 'User', { email: 'john@example.com' })
|
|
32
|
-
* // => 'mk:one:User:a1b2c3d4'
|
|
33
|
-
*/
|
|
34
|
-
declare function byQueryKey(prefix: string, model: string, version: number, query: Record<string, unknown>, options?: {
|
|
35
|
-
select?: SelectSpec;
|
|
36
|
-
populate?: PopulateSpec;
|
|
37
|
-
}): string;
|
|
38
|
-
/**
|
|
39
|
-
* Generate cache key for paginated list queries
|
|
40
|
-
*
|
|
41
|
-
* Format: {prefix}:list:{model}:{version}:{queryHash}
|
|
42
|
-
*
|
|
43
|
-
* The version component enables efficient bulk invalidation:
|
|
44
|
-
* - On any mutation, bump the version
|
|
45
|
-
* - All list cache keys become invalid without scanning/deleting each
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* listQueryKey('mk', 'User', 1, { filters: { status: 'active' }, page: 1, limit: 20 })
|
|
49
|
-
* // => 'mk:list:User:1:e5f6g7h8'
|
|
50
|
-
*/
|
|
51
|
-
declare function listQueryKey(prefix: string, model: string, version: number, params: {
|
|
52
|
-
filters?: Record<string, unknown>;
|
|
53
|
-
sort?: SortSpec;
|
|
54
|
-
page?: number;
|
|
55
|
-
limit?: number;
|
|
56
|
-
after?: string;
|
|
57
|
-
select?: SelectSpec;
|
|
58
|
-
populate?: PopulateSpec;
|
|
59
|
-
search?: string;
|
|
60
|
-
mode?: string;
|
|
61
|
-
lean?: boolean;
|
|
62
|
-
readPreference?: string;
|
|
63
|
-
hint?: string | Record<string, unknown>;
|
|
64
|
-
maxTimeMS?: number;
|
|
65
|
-
countStrategy?: string;
|
|
66
|
-
}): string;
|
|
67
|
-
/**
|
|
68
|
-
* Generate cache key for collection version tag
|
|
69
|
-
*
|
|
70
|
-
* Format: {prefix}:ver:{model}
|
|
71
|
-
*
|
|
72
|
-
* Used to track mutation version for list invalidation
|
|
73
|
-
*/
|
|
74
|
-
declare function versionKey(prefix: string, model: string): string;
|
|
75
|
-
/**
|
|
76
|
-
* Generate pattern for clearing all cache keys for a model
|
|
77
|
-
*
|
|
78
|
-
* Format: {prefix}:*:{model}:*
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* modelPattern('mk', 'User')
|
|
82
|
-
* // => 'mk:*:User:*'
|
|
83
|
-
*/
|
|
84
|
-
declare function modelPattern(prefix: string, model: string): string;
|
|
85
|
-
/**
|
|
86
|
-
* Generate pattern for clearing all list cache keys for a model
|
|
87
|
-
*
|
|
88
|
-
* Format: {prefix}:list:{model}:*
|
|
89
|
-
*/
|
|
90
|
-
declare function listPattern(prefix: string, model: string): string;
|
|
91
|
-
//#endregion
|
|
92
3
|
//#region src/utils/id-resolution.d.ts
|
|
93
4
|
/**
|
|
94
5
|
* ID Resolution Primitive
|
|
@@ -146,4 +57,4 @@ declare function getSchemaIdType(schema?: SchemaLike | null): IdType;
|
|
|
146
57
|
*/
|
|
147
58
|
declare function isValidIdForType(id: unknown, idType: IdType): boolean;
|
|
148
59
|
//#endregion
|
|
149
|
-
export { type IdType, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema,
|
|
60
|
+
export { type IdType, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, isObjectIdInstance, isValidIdForType };
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as configureLogger } from "../logger-
|
|
1
|
+
import { t as configureLogger } from "../logger-DprijP5h.mjs";
|
|
2
2
|
import { t as createError } from "../error-B00pI7dV.mjs";
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
5
|
-
import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-
|
|
6
|
-
export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema,
|
|
3
|
+
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "../field-selection-Br3WPOEb.mjs";
|
|
4
|
+
import { n as isObjectIdInstance, r as isValidIdForType, t as getSchemaIdType } from "../id-resolution-B0Odvvou.mjs";
|
|
5
|
+
import { n as buildCrudSchemasFromMongooseSchema, r as createMemoryCache, t as buildCrudSchemasFromModel } from "../mongooseToJsonSchema-BYbG894y.mjs";
|
|
6
|
+
export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, configureLogger, createError, createFieldPreset, createMemoryCache, filterResponseData, getFieldsForUser, getMongooseProjection, getSchemaIdType, isObjectIdInstance, isValidIdForType };
|