@classytic/mongokit 3.3.2 → 3.4.1
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 +137 -7
- package/dist/PaginationEngine-nY04eGUM.mjs +290 -0
- package/dist/actions/index.d.mts +2 -9
- package/dist/actions/index.mjs +3 -5
- package/dist/ai/index.d.mts +1 -1
- package/dist/ai/index.mjs +3 -3
- package/dist/chunk-CfYAbeIz.mjs +13 -0
- package/dist/{limits-s1-d8rWb.mjs → cursor-CHToazHy.mjs} +122 -171
- package/dist/{logger-D8ily-PP.mjs → error-Bpbi_NKo.mjs} +34 -22
- package/dist/{cache-keys-CzFwVnLy.mjs → field-selection-reyDRzXf.mjs} +110 -112
- package/dist/{aggregate-BkOG9qwr.d.mts → index-BuoZIZ15.d.mts} +132 -129
- package/dist/index.d.mts +549 -543
- package/dist/index.mjs +33 -101
- package/dist/{mongooseToJsonSchema-D_i2Am_O.mjs → mongooseToJsonSchema-B6Qyl8BK.mjs} +13 -12
- package/dist/{mongooseToJsonSchema-B6O2ED3n.d.mts → mongooseToJsonSchema-RX9YfJLu.d.mts} +24 -17
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/pagination/PaginationEngine.mjs +2 -209
- package/dist/plugins/index.d.mts +1 -2
- package/dist/plugins/index.mjs +2 -3
- package/dist/sort-C-BJEWUZ.mjs +57 -0
- package/dist/{types-pVY0w1Pp.d.mts → types-COINbsdL.d.mts} +57 -27
- package/dist/{aggregate-BClp040M.mjs → update-DGKMmBgG.mjs} +575 -565
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +4 -5
- package/dist/{custom-id.plugin-BJ3FSnzt.d.mts → validation-chain.plugin-BNoaKDOm.d.mts} +832 -832
- package/dist/{custom-id.plugin-FInXDsUX.mjs → validation-chain.plugin-da3fOo8A.mjs} +2410 -2246
- package/package.json +11 -6
- package/dist/chunk-DQk6qfdC.mjs +0 -18
package/dist/index.mjs
CHANGED
|
@@ -1,87 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
|
|
4
|
-
import { A as AggregationBuilder, C as methodRegistryPlugin, D as fieldFilterPlugin, E as timestampPlugin, O as HOOK_PRIORITY, S as validationChainPlugin, T as auditLogPlugin, _ as autoInject, a as sequentialId, b as requireField, c as auditTrailPlugin, d as cascadePlugin, f as cachePlugin, g as mongoOperationsPlugin, h as batchOperationsPlugin, i as prefixedId, k as Repository, l as observabilityPlugin, m as aggregateHelpersPlugin, n as dateSequentialId, o as elasticSearchPlugin, p as subdocumentPlugin, r as getNextSequence, s as AuditTrailQuery, t as customIdPlugin, u as multiTenantPlugin, v as blockIf, w as softDeletePlugin, x as uniqueField, y as immutableField } from "./custom-id.plugin-FInXDsUX.mjs";
|
|
5
|
-
import { c as filterResponseData, l as getFieldsForUser, s as createFieldPreset, u as getMongooseProjection } from "./cache-keys-CzFwVnLy.mjs";
|
|
6
|
-
import { a as isFieldUpdateAllowed, i as getSystemManagedFields, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-D_i2Am_O.mjs";
|
|
1
|
+
import { a as warn, n as parseDuplicateKeyError, r as configureLogger, t as createError } from "./error-Bpbi_NKo.mjs";
|
|
2
|
+
import { _ as LookupBuilder } from "./update-DGKMmBgG.mjs";
|
|
7
3
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
4
|
+
import { t as PaginationEngine } from "./PaginationEngine-nY04eGUM.mjs";
|
|
5
|
+
import { A as aggregateHelpersPlugin, C as HOOK_PRIORITY, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, T as AggregationBuilder, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-da3fOo8A.mjs";
|
|
6
|
+
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-reyDRzXf.mjs";
|
|
7
|
+
import { a as isFieldUpdateAllowed, i as getSystemManagedFields, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-B6Qyl8BK.mjs";
|
|
8
8
|
import mongoose from "mongoose";
|
|
9
|
-
|
|
10
9
|
//#region src/query/QueryParser.ts
|
|
11
10
|
/**
|
|
12
|
-
* Modern Query Parser - URL to MongoDB Query Transpiler
|
|
13
|
-
*
|
|
14
|
-
* Next-generation query parser that converts URL parameters to MongoDB aggregation pipelines.
|
|
15
|
-
* Smarter than Prisma/tRPC for MongoDB with support for:
|
|
16
|
-
* - Custom field lookups ($lookup)
|
|
17
|
-
* - Complex filtering with operators
|
|
18
|
-
* - Full-text search
|
|
19
|
-
* - Aggregations via URL
|
|
20
|
-
* - Security hardening
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```typescript
|
|
24
|
-
* // Simple usage
|
|
25
|
-
* const parser = new QueryParser();
|
|
26
|
-
* const query = parser.parse(req.query);
|
|
27
|
-
*
|
|
28
|
-
* // URL: ?status=active&lookup[department]=slug&sort=-createdAt&page=1&limit=20
|
|
29
|
-
* // Result: Complete MongoDB query with $lookup, filters, sort, pagination
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* ## SECURITY CONSIDERATIONS FOR PRODUCTION
|
|
33
|
-
*
|
|
34
|
-
* ### Aggregation Security (enableAggregations option)
|
|
35
|
-
*
|
|
36
|
-
* **IMPORTANT:** The `enableAggregations` option exposes powerful MongoDB aggregation
|
|
37
|
-
* pipeline capabilities via URL parameters. While this feature includes sanitization
|
|
38
|
-
* (blocks $where, $function, $accumulator), it should be used with caution:
|
|
39
|
-
*
|
|
40
|
-
* **Recommended security practices:**
|
|
41
|
-
* 1. **Disable by default for public endpoints:**
|
|
42
|
-
* ```typescript
|
|
43
|
-
* const parser = new QueryParser({
|
|
44
|
-
* enableAggregations: false // Default: disabled
|
|
45
|
-
* });
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* 2. **Use per-route allowlists for trusted clients:**
|
|
49
|
-
* ```typescript
|
|
50
|
-
* // Admin/internal routes only
|
|
51
|
-
* if (req.user?.role === 'admin') {
|
|
52
|
-
* const allowedStages = ['$match', '$project', '$sort', '$limit'];
|
|
53
|
-
* // Validate aggregate parameter against allowlist
|
|
54
|
-
* }
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
|
-
* 3. **Validate stage structure:** Even with sanitization, complex pipelines can
|
|
58
|
-
* cause performance issues. Consider limiting:
|
|
59
|
-
* - Number of pipeline stages (e.g., max 5)
|
|
60
|
-
* - Specific allowed operators per stage
|
|
61
|
-
* - Allowed fields in $project/$match
|
|
62
|
-
*
|
|
63
|
-
* 4. **Monitor resource usage:** Aggregation pipelines can be expensive.
|
|
64
|
-
* Use MongoDB profiling to track slow operations.
|
|
65
|
-
*
|
|
66
|
-
* ### Lookup Security
|
|
67
|
-
*
|
|
68
|
-
* Lookup pipelines are sanitized by default:
|
|
69
|
-
* - Dangerous stages blocked ($out, $merge, $unionWith, $collStats, $currentOp, $listSessions)
|
|
70
|
-
* - Dangerous operators blocked inside $match/$addFields/$set ($where, $function, $accumulator, $expr)
|
|
71
|
-
* - Optional collection whitelist via `allowedLookupCollections`
|
|
72
|
-
* For maximum security, use per-collection field allowlists in your controller layer.
|
|
73
|
-
*
|
|
74
|
-
* ### Filter Security
|
|
75
|
-
*
|
|
76
|
-
* All filters are sanitized:
|
|
77
|
-
* - Dangerous operators blocked ($where, $function, $accumulator, $expr)
|
|
78
|
-
* - Regex patterns validated (ReDoS protection)
|
|
79
|
-
* - Max filter depth enforced (prevents filter bombs)
|
|
80
|
-
* - Max limit enforced (prevents resource exhaustion)
|
|
81
|
-
*
|
|
82
|
-
* @see {@link https://github.com/classytic/mongokit/blob/main/docs/SECURITY.md}
|
|
83
|
-
*/
|
|
84
|
-
/**
|
|
85
11
|
* Modern Query Parser
|
|
86
12
|
* Converts URL parameters to MongoDB queries with $lookup support
|
|
87
13
|
*/
|
|
@@ -113,7 +39,7 @@ var QueryParser = class {
|
|
|
113
39
|
* - Backreferences: \1, \2, etc.
|
|
114
40
|
* - Complex character classes: [...]...[...]
|
|
115
41
|
*/
|
|
116
|
-
dangerousRegexPatterns = /(\{[0-9,]+\}|\*\+|\+\+|\?\+|(\(.+\))\+|\(
|
|
42
|
+
dangerousRegexPatterns = /(\{[0-9,]+\}|\*\+|\+\+|\?\+|(\(.+\))\+|\(\?:|\\[0-9]|(\[.+\]).+(\[.+\]))/;
|
|
117
43
|
constructor(options = {}) {
|
|
118
44
|
this.options = {
|
|
119
45
|
maxRegexLength: options.maxRegexLength ?? 500,
|
|
@@ -155,7 +81,7 @@ var QueryParser = class {
|
|
|
155
81
|
parse(query) {
|
|
156
82
|
const { page, limit = 20, sort = "-createdAt", populate, search, after, cursor, select, lookup, aggregate, ...filters } = query || {};
|
|
157
83
|
let parsedLimit = parseInt(String(limit), 10);
|
|
158
|
-
if (isNaN(parsedLimit) || parsedLimit < 1) parsedLimit = 20;
|
|
84
|
+
if (Number.isNaN(parsedLimit) || parsedLimit < 1) parsedLimit = 20;
|
|
159
85
|
if (parsedLimit > this.options.maxLimit) {
|
|
160
86
|
warn(`[mongokit] Limit ${parsedLimit} exceeds maximum ${this.options.maxLimit}, capping to max`);
|
|
161
87
|
parsedLimit = this.options.maxLimit;
|
|
@@ -248,15 +174,15 @@ var QueryParser = class {
|
|
|
248
174
|
description: "Cursor value for keyset pagination"
|
|
249
175
|
}
|
|
250
176
|
};
|
|
251
|
-
if (this.options.enableLookups) properties
|
|
177
|
+
if (this.options.enableLookups) properties.lookup = {
|
|
252
178
|
type: "object",
|
|
253
179
|
description: "Custom field lookups ($lookup). Example: lookup[department]=slug or lookup[department][localField]=deptId&lookup[department][foreignField]=_id"
|
|
254
180
|
};
|
|
255
|
-
if (this.options.enableAggregations) properties
|
|
181
|
+
if (this.options.enableAggregations) properties.aggregate = {
|
|
256
182
|
type: "object",
|
|
257
183
|
description: "Aggregation pipeline stages. Supports: group, match, sort, project. Example: aggregate[group][_id]=$status"
|
|
258
184
|
};
|
|
259
|
-
const availableOperators = this.options.allowedOperators ? Object.entries(this.operators).filter(([key]) => this.options.allowedOperators
|
|
185
|
+
const availableOperators = this.options.allowedOperators ? Object.entries(this.operators).filter(([key]) => this.options.allowedOperators?.includes(key)) : Object.entries(this.operators);
|
|
260
186
|
if (this.options.allowedFilterFields && this.options.allowedFilterFields.length > 0) for (const field of this.options.allowedFilterFields) {
|
|
261
187
|
properties[field] = {
|
|
262
188
|
type: "string",
|
|
@@ -283,8 +209,8 @@ var QueryParser = class {
|
|
|
283
209
|
*/
|
|
284
210
|
getOpenAPIQuerySchema() {
|
|
285
211
|
const schema = this.getQuerySchema();
|
|
286
|
-
const availableOperators = this.options.allowedOperators ? Object.entries(this.operators).filter(([key]) => this.options.allowedOperators
|
|
287
|
-
schema.properties
|
|
212
|
+
const availableOperators = this.options.allowedOperators ? Object.entries(this.operators).filter(([key]) => this.options.allowedOperators?.includes(key)) : Object.entries(this.operators);
|
|
213
|
+
schema.properties._filterOperators = {
|
|
288
214
|
type: "string",
|
|
289
215
|
description: this._buildOperatorDescription(availableOperators),
|
|
290
216
|
"x-internal": true
|
|
@@ -420,6 +346,7 @@ var QueryParser = class {
|
|
|
420
346
|
foreignField,
|
|
421
347
|
as: opts.as || collectionName,
|
|
422
348
|
single: opts.single === true || opts.single === "true",
|
|
349
|
+
...opts.select ? { select: String(opts.select) } : {},
|
|
423
350
|
...opts.pipeline && Array.isArray(opts.pipeline) ? { pipeline: this._sanitizePipeline(opts.pipeline) } : {}
|
|
424
351
|
};
|
|
425
352
|
}
|
|
@@ -486,7 +413,14 @@ var QueryParser = class {
|
|
|
486
413
|
*/
|
|
487
414
|
_parsePopulate(populate) {
|
|
488
415
|
if (!populate) return {};
|
|
489
|
-
if (typeof populate === "string")
|
|
416
|
+
if (typeof populate === "string") {
|
|
417
|
+
const paths = populate.split(",").map((p) => p.trim()).filter(Boolean);
|
|
418
|
+
if (paths.length > 0) return {
|
|
419
|
+
simplePopulate: populate,
|
|
420
|
+
populateOptions: paths.map((path) => ({ path }))
|
|
421
|
+
};
|
|
422
|
+
return {};
|
|
423
|
+
}
|
|
490
424
|
if (typeof populate === "object" && populate !== null) {
|
|
491
425
|
const populateObj = populate;
|
|
492
426
|
if (Object.keys(populateObj).length === 0) return {};
|
|
@@ -525,7 +459,7 @@ var QueryParser = class {
|
|
|
525
459
|
if (opts.match && typeof opts.match === "object") option.match = this._convertPopulateMatch(opts.match);
|
|
526
460
|
if (opts.limit !== void 0) {
|
|
527
461
|
const limit = parseInt(String(opts.limit), 10);
|
|
528
|
-
if (!isNaN(limit) && limit > 0) {
|
|
462
|
+
if (!Number.isNaN(limit) && limit > 0) {
|
|
529
463
|
option.options = option.options || {};
|
|
530
464
|
option.options.limit = limit;
|
|
531
465
|
}
|
|
@@ -539,7 +473,7 @@ var QueryParser = class {
|
|
|
539
473
|
}
|
|
540
474
|
if (opts.skip !== void 0) {
|
|
541
475
|
const skip = parseInt(String(opts.skip), 10);
|
|
542
|
-
if (!isNaN(skip) && skip >= 0) {
|
|
476
|
+
if (!Number.isNaN(skip) && skip >= 0) {
|
|
543
477
|
option.options = option.options || {};
|
|
544
478
|
option.options.skip = skip;
|
|
545
479
|
}
|
|
@@ -603,7 +537,7 @@ var QueryParser = class {
|
|
|
603
537
|
}
|
|
604
538
|
if (operatorMatch) {
|
|
605
539
|
const [, , operator] = operatorMatch;
|
|
606
|
-
if (this.dangerousOperators.includes(
|
|
540
|
+
if (this.dangerousOperators.includes(`$${operator}`)) {
|
|
607
541
|
warn(`[mongokit] Blocked dangerous operator: ${operator}`);
|
|
608
542
|
continue;
|
|
609
543
|
}
|
|
@@ -662,7 +596,7 @@ var QueryParser = class {
|
|
|
662
596
|
"size"
|
|
663
597
|
].includes(op)) {
|
|
664
598
|
processedValue = parseFloat(String(value));
|
|
665
|
-
if (isNaN(processedValue)) return;
|
|
599
|
+
if (Number.isNaN(processedValue)) return;
|
|
666
600
|
} else if (op === "in" || op === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
667
601
|
else processedValue = this._convertValue(value);
|
|
668
602
|
if (typeof filters[field] !== "object" || filters[field] === null || Array.isArray(filters[field])) filters[field] = {};
|
|
@@ -699,7 +633,7 @@ var QueryParser = class {
|
|
|
699
633
|
"size"
|
|
700
634
|
].includes(operator)) {
|
|
701
635
|
processedValue = parseFloat(String(value));
|
|
702
|
-
if (isNaN(processedValue)) continue;
|
|
636
|
+
if (Number.isNaN(processedValue)) continue;
|
|
703
637
|
} else if (operator === "in" || operator === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
704
638
|
else if (operator === "like" || operator === "contains" || operator === "regex") {
|
|
705
639
|
const safeRegex = this._createSafeRegex(value);
|
|
@@ -741,7 +675,7 @@ var QueryParser = class {
|
|
|
741
675
|
}
|
|
742
676
|
_toMongoOperator(operator) {
|
|
743
677
|
const op = operator.toLowerCase();
|
|
744
|
-
return op.startsWith("$") ? op :
|
|
678
|
+
return op.startsWith("$") ? op : `$${op}`;
|
|
745
679
|
}
|
|
746
680
|
_createSafeRegex(pattern, flags = "i") {
|
|
747
681
|
if (pattern === null || pattern === void 0) return null;
|
|
@@ -890,22 +824,21 @@ var QueryParser = class {
|
|
|
890
824
|
const fromDate = from ? new Date(from) : void 0;
|
|
891
825
|
const toDate = to ? new Date(to) : void 0;
|
|
892
826
|
const range = {};
|
|
893
|
-
if (fromDate && !isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
894
|
-
if (toDate && !isNaN(toDate.getTime())) range.$lte = toDate;
|
|
827
|
+
if (fromDate && !Number.isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
828
|
+
if (toDate && !Number.isNaN(toDate.getTime())) range.$lte = toDate;
|
|
895
829
|
output[key] = range;
|
|
896
830
|
}
|
|
897
831
|
return output;
|
|
898
832
|
}
|
|
899
833
|
_pluralize(str) {
|
|
900
|
-
if (str.endsWith("y")) return str.slice(0, -1)
|
|
834
|
+
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
901
835
|
if (str.endsWith("s")) return str;
|
|
902
|
-
return str
|
|
836
|
+
return `${str}s`;
|
|
903
837
|
}
|
|
904
838
|
_capitalize(str) {
|
|
905
839
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
906
840
|
}
|
|
907
841
|
};
|
|
908
|
-
|
|
909
842
|
//#endregion
|
|
910
843
|
//#region src/index.ts
|
|
911
844
|
/**
|
|
@@ -922,6 +855,5 @@ function createRepository(Model, plugins = [], paginationConfig = {}, options =
|
|
|
922
855
|
return new Repository(Model, plugins, paginationConfig, options);
|
|
923
856
|
}
|
|
924
857
|
var src_default = Repository;
|
|
925
|
-
|
|
926
858
|
//#endregion
|
|
927
|
-
export { AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, PaginationEngine, QueryParser, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin };
|
|
859
|
+
export { AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, PaginationEngine, QueryParser, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, configureLogger, createError, createFieldPreset, createMemoryCache, createRepository, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getNextSequence, getSystemManagedFields, immutableField, isFieldUpdateAllowed, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, parseDuplicateKeyError, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin };
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import "mongoose";
|
|
3
2
|
//#region src/utils/memory-cache.ts
|
|
4
3
|
/**
|
|
5
4
|
* Creates an in-memory cache adapter
|
|
6
|
-
*
|
|
5
|
+
*
|
|
7
6
|
* Features:
|
|
8
7
|
* - Automatic TTL expiration
|
|
9
8
|
* - Pattern-based clearing (simple glob with *)
|
|
10
9
|
* - Max entries limit to prevent memory leaks
|
|
11
|
-
*
|
|
10
|
+
*
|
|
12
11
|
* @param maxEntries - Maximum cache entries before oldest are evicted (default: 1000)
|
|
13
12
|
*/
|
|
14
13
|
function createMemoryCache(maxEntries = 1e3) {
|
|
@@ -60,12 +59,11 @@ function createMemoryCache(maxEntries = 1e3) {
|
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
61
|
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
63
|
-
const regex = new RegExp(
|
|
62
|
+
const regex = new RegExp(`^${escaped}$`);
|
|
64
63
|
for (const key of cache.keys()) if (regex.test(key)) cache.delete(key);
|
|
65
64
|
}
|
|
66
65
|
};
|
|
67
66
|
}
|
|
68
|
-
|
|
69
67
|
//#endregion
|
|
70
68
|
//#region src/utils/mongooseToJsonSchema.ts
|
|
71
69
|
/**
|
|
@@ -91,7 +89,7 @@ function buildCrudSchemasFromMongooseSchema(mongooseSchema, options = {}) {
|
|
|
91
89
|
* Build CRUD schemas from Mongoose model
|
|
92
90
|
*/
|
|
93
91
|
function buildCrudSchemasFromModel(mongooseModel, options = {}) {
|
|
94
|
-
if (!mongooseModel
|
|
92
|
+
if (!mongooseModel?.schema) throw new Error("Invalid mongoose model");
|
|
95
93
|
return buildCrudSchemasFromMongooseSchema(mongooseModel.schema, options);
|
|
96
94
|
}
|
|
97
95
|
/**
|
|
@@ -161,7 +159,7 @@ function buildJsonSchemaFromPaths(mongooseSchema, options) {
|
|
|
161
159
|
if (path === "_id" || path === "__v") continue;
|
|
162
160
|
const rootField = path.split(".")[0];
|
|
163
161
|
if (!rootFields.has(rootField)) rootFields.set(rootField, []);
|
|
164
|
-
rootFields.get(rootField)
|
|
162
|
+
rootFields.get(rootField)?.push({
|
|
165
163
|
path,
|
|
166
164
|
schemaType
|
|
167
165
|
});
|
|
@@ -185,7 +183,9 @@ function buildJsonSchemaFromPaths(mongooseSchema, options) {
|
|
|
185
183
|
"updatedAt",
|
|
186
184
|
"__v"
|
|
187
185
|
]);
|
|
188
|
-
(options?.create?.omitFields || []).forEach((f) =>
|
|
186
|
+
(options?.create?.omitFields || []).forEach((f) => {
|
|
187
|
+
fieldsToOmit.add(f);
|
|
188
|
+
});
|
|
189
189
|
const fieldRules = options?.fieldRules || {};
|
|
190
190
|
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
191
191
|
if (rules.systemManaged) fieldsToOmit.add(field);
|
|
@@ -281,7 +281,9 @@ function buildJsonSchemaForUpdate(createJson, options) {
|
|
|
281
281
|
const clone = JSON.parse(JSON.stringify(createJson));
|
|
282
282
|
delete clone.required;
|
|
283
283
|
const fieldsToOmit = /* @__PURE__ */ new Set();
|
|
284
|
-
(options?.update?.omitFields || []).forEach((f) =>
|
|
284
|
+
(options?.update?.omitFields || []).forEach((f) => {
|
|
285
|
+
fieldsToOmit.add(f);
|
|
286
|
+
});
|
|
285
287
|
const fieldRules = options?.fieldRules || {};
|
|
286
288
|
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
287
289
|
if (rules.immutable || rules.immutableAfterCreate) fieldsToOmit.add(field);
|
|
@@ -312,6 +314,5 @@ function buildJsonSchemaForQuery(_tree, options) {
|
|
|
312
314
|
for (const [k, v] of Object.entries(filterable)) if (basePagination.properties) basePagination.properties[k] = v && typeof v === "object" && "type" in v ? v : { type: "string" };
|
|
313
315
|
return basePagination;
|
|
314
316
|
}
|
|
315
|
-
|
|
316
317
|
//#endregion
|
|
317
|
-
export { isFieldUpdateAllowed as a, getSystemManagedFields as i, buildCrudSchemasFromMongooseSchema as n, validateUpdateBody as o, getImmutableFields as r, createMemoryCache as s, buildCrudSchemasFromModel as t };
|
|
318
|
+
export { isFieldUpdateAllowed as a, getSystemManagedFields as i, buildCrudSchemasFromMongooseSchema as n, validateUpdateBody as o, getImmutableFields as r, createMemoryCache as s, buildCrudSchemasFromModel as t };
|
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as HttpError, S as FieldPreset, et as SchemaBuilderOptions, ft as UserContext, h as CrudSchemas, mt as ValidationResult, o as CacheAdapter } from "./types-COINbsdL.mjs";
|
|
2
2
|
import mongoose, { Schema } from "mongoose";
|
|
3
3
|
|
|
4
|
+
//#region src/utils/error.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates an error with HTTP status code
|
|
7
|
+
*
|
|
8
|
+
* @param status - HTTP status code
|
|
9
|
+
* @param message - Error message
|
|
10
|
+
* @returns Error with status property
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* throw createError(404, 'Document not found');
|
|
14
|
+
* throw createError(400, 'Invalid input');
|
|
15
|
+
* throw createError(403, 'Access denied');
|
|
16
|
+
*/
|
|
17
|
+
declare function createError(status: number, message: string): HttpError;
|
|
18
|
+
/**
|
|
19
|
+
* Detect and convert a MongoDB E11000 duplicate-key error into
|
|
20
|
+
* a 409 HttpError with an actionable message.
|
|
21
|
+
*
|
|
22
|
+
* Returns `null` when the error is not a duplicate-key error.
|
|
23
|
+
*/
|
|
24
|
+
declare function parseDuplicateKeyError(error: unknown): HttpError | null;
|
|
25
|
+
//#endregion
|
|
4
26
|
//#region src/utils/field-selection.d.ts
|
|
5
27
|
/**
|
|
6
28
|
* Get allowed fields for a user based on their context
|
|
@@ -69,21 +91,6 @@ declare function filterResponseData<T extends Record<string, unknown>>(data: T |
|
|
|
69
91
|
*/
|
|
70
92
|
declare function createFieldPreset(config: Partial<FieldPreset>): FieldPreset;
|
|
71
93
|
//#endregion
|
|
72
|
-
//#region src/utils/error.d.ts
|
|
73
|
-
/**
|
|
74
|
-
* Creates an error with HTTP status code
|
|
75
|
-
*
|
|
76
|
-
* @param status - HTTP status code
|
|
77
|
-
* @param message - Error message
|
|
78
|
-
* @returns Error with status property
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* throw createError(404, 'Document not found');
|
|
82
|
-
* throw createError(400, 'Invalid input');
|
|
83
|
-
* throw createError(403, 'Access denied');
|
|
84
|
-
*/
|
|
85
|
-
declare function createError(status: number, message: string): HttpError;
|
|
86
|
-
//#endregion
|
|
87
94
|
//#region src/utils/logger.d.ts
|
|
88
95
|
/**
|
|
89
96
|
* Internal Logger
|
|
@@ -155,4 +162,4 @@ declare function isFieldUpdateAllowed(fieldName: string, options?: SchemaBuilder
|
|
|
155
162
|
*/
|
|
156
163
|
declare function validateUpdateBody(body?: Record<string, unknown>, options?: SchemaBuilderOptions): ValidationResult;
|
|
157
164
|
//#endregion
|
|
158
|
-
export { isFieldUpdateAllowed as a, configureLogger as c,
|
|
165
|
+
export { isFieldUpdateAllowed as a, configureLogger as c, getFieldsForUser as d, getMongooseProjection as f, getSystemManagedFields as i, createFieldPreset as l, parseDuplicateKeyError as m, buildCrudSchemasFromMongooseSchema as n, validateUpdateBody as o, createError as p, getImmutableFields as r, createMemoryCache as s, buildCrudSchemasFromModel as t, filterResponseData as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as PaginationConfig, L as OffsetPaginationOptions, M as KeysetPaginationResult, R as OffsetPaginationResult, i as AnyDocument, j as KeysetPaginationOptions, n as AggregatePaginationResult, t as AggregatePaginationOptions } from "../types-COINbsdL.mjs";
|
|
2
2
|
import { Model } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/pagination/PaginationEngine.d.ts
|
|
@@ -1,209 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//#region src/pagination/PaginationEngine.ts
|
|
5
|
-
/**
|
|
6
|
-
* Production-grade pagination engine for MongoDB
|
|
7
|
-
* Supports offset, keyset (cursor), and aggregate pagination
|
|
8
|
-
*/
|
|
9
|
-
var PaginationEngine = class {
|
|
10
|
-
Model;
|
|
11
|
-
config;
|
|
12
|
-
/**
|
|
13
|
-
* Create a new pagination engine
|
|
14
|
-
*
|
|
15
|
-
* @param Model - Mongoose model to paginate
|
|
16
|
-
* @param config - Pagination configuration
|
|
17
|
-
*/
|
|
18
|
-
constructor(Model, config = {}) {
|
|
19
|
-
this.Model = Model;
|
|
20
|
-
this.config = {
|
|
21
|
-
defaultLimit: config.defaultLimit || 10,
|
|
22
|
-
maxLimit: config.maxLimit || 100,
|
|
23
|
-
maxPage: config.maxPage || 1e4,
|
|
24
|
-
deepPageThreshold: config.deepPageThreshold || 100,
|
|
25
|
-
cursorVersion: config.cursorVersion || 1,
|
|
26
|
-
useEstimatedCount: config.useEstimatedCount || false
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Offset-based pagination using skip/limit
|
|
31
|
-
* Best for small datasets and when users need random page access
|
|
32
|
-
* O(n) performance - slower for deep pages
|
|
33
|
-
*
|
|
34
|
-
* @param options - Pagination options
|
|
35
|
-
* @returns Pagination result with total count
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* const result = await engine.paginate({
|
|
39
|
-
* filters: { status: 'active' },
|
|
40
|
-
* sort: { createdAt: -1 },
|
|
41
|
-
* page: 1,
|
|
42
|
-
* limit: 20
|
|
43
|
-
* });
|
|
44
|
-
* console.log(result.docs, result.total, result.hasNext);
|
|
45
|
-
*/
|
|
46
|
-
async paginate(options = {}) {
|
|
47
|
-
const { filters = {}, sort = { _id: -1 }, page = 1, limit = this.config.defaultLimit, select, populate = [], lean = true, session, hint, maxTimeMS, countStrategy = "exact", readPreference } = options;
|
|
48
|
-
const sanitizedPage = validatePage(page, this.config);
|
|
49
|
-
const sanitizedLimit = validateLimit(limit, this.config);
|
|
50
|
-
const skip = calculateSkip(sanitizedPage, sanitizedLimit);
|
|
51
|
-
const fetchLimit = countStrategy === "none" ? sanitizedLimit + 1 : sanitizedLimit;
|
|
52
|
-
let query = this.Model.find(filters);
|
|
53
|
-
if (select) query = query.select(select);
|
|
54
|
-
if (populate && (Array.isArray(populate) ? populate.length : populate)) query = query.populate(populate);
|
|
55
|
-
query = query.sort(sort).skip(skip).limit(fetchLimit).lean(lean);
|
|
56
|
-
if (session) query = query.session(session);
|
|
57
|
-
if (hint) query = query.hint(hint);
|
|
58
|
-
if (maxTimeMS) query = query.maxTimeMS(maxTimeMS);
|
|
59
|
-
if (readPreference) query = query.read(readPreference);
|
|
60
|
-
const hasFilters = Object.keys(filters).length > 0;
|
|
61
|
-
const useEstimated = this.config.useEstimatedCount && !hasFilters;
|
|
62
|
-
let total = 0;
|
|
63
|
-
if (countStrategy === "estimated" || useEstimated && countStrategy !== "exact") total = await this.Model.estimatedDocumentCount();
|
|
64
|
-
else if (countStrategy === "exact") {
|
|
65
|
-
const countQuery = this.Model.countDocuments(filters).session(session ?? null);
|
|
66
|
-
if (hint) countQuery.hint(hint);
|
|
67
|
-
if (maxTimeMS) countQuery.maxTimeMS(maxTimeMS);
|
|
68
|
-
if (readPreference) countQuery.read(readPreference);
|
|
69
|
-
total = await countQuery;
|
|
70
|
-
}
|
|
71
|
-
const [docs] = await Promise.all([query.exec()]);
|
|
72
|
-
const totalPages = countStrategy === "none" ? 0 : calculateTotalPages(total, sanitizedLimit);
|
|
73
|
-
let hasNext;
|
|
74
|
-
if (countStrategy === "none") {
|
|
75
|
-
hasNext = docs.length > sanitizedLimit;
|
|
76
|
-
if (hasNext) docs.pop();
|
|
77
|
-
} else hasNext = sanitizedPage < totalPages;
|
|
78
|
-
const warning = shouldWarnDeepPagination(sanitizedPage, this.config.deepPageThreshold) ? `Deep pagination (page ${sanitizedPage}). Consider getAll({ after, sort, limit }) for better performance.` : void 0;
|
|
79
|
-
return {
|
|
80
|
-
method: "offset",
|
|
81
|
-
docs,
|
|
82
|
-
page: sanitizedPage,
|
|
83
|
-
limit: sanitizedLimit,
|
|
84
|
-
total,
|
|
85
|
-
pages: totalPages,
|
|
86
|
-
hasNext,
|
|
87
|
-
hasPrev: sanitizedPage > 1,
|
|
88
|
-
...warning && { warning }
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Keyset (cursor-based) pagination for high-performance streaming
|
|
93
|
-
* Best for large datasets, infinite scroll, real-time feeds
|
|
94
|
-
* O(1) performance - consistent speed regardless of position
|
|
95
|
-
*
|
|
96
|
-
* @param options - Pagination options (sort is required)
|
|
97
|
-
* @returns Pagination result with next cursor
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* // First page
|
|
101
|
-
* const page1 = await engine.stream({
|
|
102
|
-
* sort: { createdAt: -1 },
|
|
103
|
-
* limit: 20
|
|
104
|
-
* });
|
|
105
|
-
*
|
|
106
|
-
* // Next page using cursor
|
|
107
|
-
* const page2 = await engine.stream({
|
|
108
|
-
* sort: { createdAt: -1 },
|
|
109
|
-
* after: page1.next,
|
|
110
|
-
* limit: 20
|
|
111
|
-
* });
|
|
112
|
-
*/
|
|
113
|
-
async stream(options) {
|
|
114
|
-
const { filters = {}, sort, after, limit = this.config.defaultLimit, select, populate = [], lean = true, session, hint, maxTimeMS, readPreference } = options;
|
|
115
|
-
if (!sort) throw createError(400, "sort is required for keyset pagination");
|
|
116
|
-
const sanitizedLimit = validateLimit(limit, this.config);
|
|
117
|
-
const normalizedSort = validateKeysetSort(sort);
|
|
118
|
-
const filterKeys = Object.keys(filters).filter((k) => !k.startsWith("$"));
|
|
119
|
-
const sortFields = Object.keys(normalizedSort);
|
|
120
|
-
if (filterKeys.length > 0 && sortFields.length > 0) {
|
|
121
|
-
const indexFields = [...filterKeys.map((f) => `${f}: 1`), ...sortFields.map((f) => `${f}: ${normalizedSort[f]}`)];
|
|
122
|
-
warn(`[mongokit] Keyset pagination with filters [${filterKeys.join(", ")}] and sort [${sortFields.join(", ")}] requires a compound index for O(1) performance. Ensure index exists: { ${indexFields.join(", ")} }`);
|
|
123
|
-
}
|
|
124
|
-
let query = { ...filters };
|
|
125
|
-
if (after) {
|
|
126
|
-
const cursor = decodeCursor(after);
|
|
127
|
-
validateCursorVersion(cursor.version, this.config.cursorVersion);
|
|
128
|
-
validateCursorSort(cursor.sort, normalizedSort);
|
|
129
|
-
query = buildKeysetFilter(query, normalizedSort, cursor.value, cursor.id);
|
|
130
|
-
}
|
|
131
|
-
let mongoQuery = this.Model.find(query);
|
|
132
|
-
if (select) mongoQuery = mongoQuery.select(select);
|
|
133
|
-
if (populate && (Array.isArray(populate) ? populate.length : populate)) mongoQuery = mongoQuery.populate(populate);
|
|
134
|
-
mongoQuery = mongoQuery.sort(normalizedSort).limit(sanitizedLimit + 1).lean(lean);
|
|
135
|
-
if (session) mongoQuery = mongoQuery.session(session);
|
|
136
|
-
if (hint) mongoQuery = mongoQuery.hint(hint);
|
|
137
|
-
if (maxTimeMS) mongoQuery = mongoQuery.maxTimeMS(maxTimeMS);
|
|
138
|
-
if (readPreference) mongoQuery = mongoQuery.read(readPreference);
|
|
139
|
-
const docs = await mongoQuery.exec();
|
|
140
|
-
const hasMore = docs.length > sanitizedLimit;
|
|
141
|
-
if (hasMore) docs.pop();
|
|
142
|
-
const primaryField = getPrimaryField(normalizedSort);
|
|
143
|
-
return {
|
|
144
|
-
method: "keyset",
|
|
145
|
-
docs,
|
|
146
|
-
limit: sanitizedLimit,
|
|
147
|
-
hasMore,
|
|
148
|
-
next: hasMore && docs.length > 0 ? encodeCursor(docs[docs.length - 1], primaryField, normalizedSort, this.config.cursorVersion) : null
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Aggregate pipeline with pagination
|
|
153
|
-
* Best for complex queries requiring aggregation stages
|
|
154
|
-
* Uses $facet to combine results and count in single query
|
|
155
|
-
*
|
|
156
|
-
* @param options - Aggregation options
|
|
157
|
-
* @returns Pagination result with total count
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* const result = await engine.aggregatePaginate({
|
|
161
|
-
* pipeline: [
|
|
162
|
-
* { $match: { status: 'active' } },
|
|
163
|
-
* { $group: { _id: '$category', count: { $sum: 1 } } },
|
|
164
|
-
* { $sort: { count: -1 } }
|
|
165
|
-
* ],
|
|
166
|
-
* page: 1,
|
|
167
|
-
* limit: 20
|
|
168
|
-
* });
|
|
169
|
-
*/
|
|
170
|
-
async aggregatePaginate(options = {}) {
|
|
171
|
-
const { pipeline = [], page = 1, limit = this.config.defaultLimit, session, hint, maxTimeMS, countStrategy = "exact", readPreference } = options;
|
|
172
|
-
const sanitizedPage = validatePage(page, this.config);
|
|
173
|
-
const sanitizedLimit = validateLimit(limit, this.config);
|
|
174
|
-
const skip = calculateSkip(sanitizedPage, sanitizedLimit);
|
|
175
|
-
const fetchLimit = countStrategy === "none" ? sanitizedLimit + 1 : sanitizedLimit;
|
|
176
|
-
const facetStages = { docs: [{ $skip: skip }, { $limit: fetchLimit }] };
|
|
177
|
-
if (countStrategy !== "none") facetStages.total = [{ $count: "count" }];
|
|
178
|
-
const facetPipeline = [...pipeline, { $facet: facetStages }];
|
|
179
|
-
const aggregation = this.Model.aggregate(facetPipeline);
|
|
180
|
-
if (session) aggregation.session(session);
|
|
181
|
-
if (hint) aggregation.hint(hint);
|
|
182
|
-
if (maxTimeMS) aggregation.option({ maxTimeMS });
|
|
183
|
-
if (readPreference) aggregation.read(readPreference);
|
|
184
|
-
const [result] = await aggregation.exec();
|
|
185
|
-
const docs = result.docs;
|
|
186
|
-
const total = result.total?.[0]?.count || 0;
|
|
187
|
-
const totalPages = countStrategy === "none" ? 0 : calculateTotalPages(total, sanitizedLimit);
|
|
188
|
-
let hasNext;
|
|
189
|
-
if (countStrategy === "none") {
|
|
190
|
-
hasNext = docs.length > sanitizedLimit;
|
|
191
|
-
if (hasNext) docs.pop();
|
|
192
|
-
} else hasNext = sanitizedPage < totalPages;
|
|
193
|
-
const warning = shouldWarnDeepPagination(sanitizedPage, this.config.deepPageThreshold) ? `Deep pagination in aggregate (page ${sanitizedPage}). Uses $skip internally.` : void 0;
|
|
194
|
-
return {
|
|
195
|
-
method: "aggregate",
|
|
196
|
-
docs,
|
|
197
|
-
page: sanitizedPage,
|
|
198
|
-
limit: sanitizedLimit,
|
|
199
|
-
total,
|
|
200
|
-
pages: totalPages,
|
|
201
|
-
hasNext,
|
|
202
|
-
hasPrev: sanitizedPage > 1,
|
|
203
|
-
...warning && { warning }
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
//#endregion
|
|
209
|
-
export { PaginationEngine };
|
|
1
|
+
import { t as PaginationEngine } from "../PaginationEngine-nY04eGUM.mjs";
|
|
2
|
+
export { PaginationEngine };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import { A as subdocumentPlugin, B as immutableField, C as observabilityPlugin, D as CacheMethods, E as cascadePlugin, F as batchOperationsPlugin, G as methodRegistryPlugin, H as uniqueField, I as MongoOperationsMethods, J as auditLogPlugin, K as SoftDeleteMethods, L as mongoOperationsPlugin, M as aggregateHelpersPlugin, N as BatchOperationsMethods, O as cachePlugin, R as autoInject, S as OperationMetric, T as multiTenantPlugin, U as validationChainPlugin, V as requireField, W as MethodRegistryRepository, X as fieldFilterPlugin, Y as timestampPlugin, _ as AuditTrailMethods, a as SequentialIdOptions, b as auditTrailPlugin, c as getNextSequence, d as ElasticSearchOptions, f as elasticSearchPlugin, g as AuditQueryResult, h as AuditQueryOptions, i as PrefixedIdOptions, j as AggregateHelpersMethods, k as SubdocumentMethods, l as prefixedId, m as AuditOperation, n as DateSequentialIdOptions, o as customIdPlugin, p as AuditEntry, q as softDeletePlugin, r as IdGenerator, s as dateSequentialId, t as CustomIdOptions, u as sequentialId, v as AuditTrailOptions, w as MultiTenantOptions, x as ObservabilityOptions, y as AuditTrailQuery, z as blockIf } from "../custom-id.plugin-BJ3FSnzt.mjs";
|
|
1
|
+
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-BNoaKDOm.mjs";
|
|
3
2
|
export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheMethods, type CustomIdOptions, type DateSequentialIdOptions, type ElasticSearchOptions, type IdGenerator, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type PrefixedIdOptions, type SequentialIdOptions, type SoftDeleteMethods, type SubdocumentMethods, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
|
1
|
+
import { A as aggregateHelpersPlugin, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-da3fOo8A.mjs";
|
|
2
|
+
export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|