@classytic/mongokit 3.3.1 → 3.4.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 +135 -5
- package/dist/{limits-s1-d8rWb.mjs → PaginationEngine-PLyDhrO7.mjs} +260 -60
- 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 +1 -2
- package/dist/chunk-CfYAbeIz.mjs +13 -0
- package/dist/{logger-D8ily-PP.mjs → error-Bpbi_NKo.mjs} +34 -22
- package/dist/{cache-keys-CzFwVnLy.mjs → field-selection-CalOB7yM.mjs} +110 -112
- package/dist/{aggregate-BkOG9qwr.d.mts → index-Df3ernpC.d.mts} +132 -129
- package/dist/index.d.mts +554 -544
- package/dist/index.mjs +39 -103
- package/dist/{mongooseToJsonSchema-B6O2ED3n.d.mts → mongooseToJsonSchema-BqgVOlrR.d.mts} +24 -17
- package/dist/{mongooseToJsonSchema-D_i2Am_O.mjs → mongooseToJsonSchema-OmdmnHtx.mjs} +13 -12
- 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/{types-pVY0w1Pp.d.mts → types-BlCwDszq.d.mts} +25 -23
- package/dist/{aggregate-BClp040M.mjs → update-DXwVh6M1.mjs} +674 -671
- 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-DxqiHv-E.d.mts} +832 -832
- package/dist/{custom-id.plugin-FInXDsUX.mjs → validation-chain.plugin-Ow6EUIoo.mjs} +2272 -2210
- package/package.json +10 -5
- 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-DXwVh6M1.mjs";
|
|
7
3
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
4
|
+
import { t as PaginationEngine } from "./PaginationEngine-PLyDhrO7.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-Ow6EUIoo.mjs";
|
|
6
|
+
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-CalOB7yM.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-OmdmnHtx.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",
|
|
@@ -270,17 +196,28 @@ var QueryParser = class {
|
|
|
270
196
|
};
|
|
271
197
|
}
|
|
272
198
|
}
|
|
273
|
-
properties["_filterOperators"] = {
|
|
274
|
-
type: "string",
|
|
275
|
-
description: this._buildOperatorDescription(availableOperators),
|
|
276
|
-
"x-internal": true
|
|
277
|
-
};
|
|
278
199
|
return {
|
|
279
200
|
type: "object",
|
|
280
201
|
properties
|
|
281
202
|
};
|
|
282
203
|
}
|
|
283
204
|
/**
|
|
205
|
+
* Get the query schema with OpenAPI extensions (x-internal metadata).
|
|
206
|
+
* Use this when generating OpenAPI/Swagger docs — it includes a documentary
|
|
207
|
+
* `_filterOperators` property describing available filter operators.
|
|
208
|
+
* For validation-only schemas, use `getQuerySchema()` instead.
|
|
209
|
+
*/
|
|
210
|
+
getOpenAPIQuerySchema() {
|
|
211
|
+
const schema = this.getQuerySchema();
|
|
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 = {
|
|
214
|
+
type: "string",
|
|
215
|
+
description: this._buildOperatorDescription(availableOperators),
|
|
216
|
+
"x-internal": true
|
|
217
|
+
};
|
|
218
|
+
return schema;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
284
221
|
* Get the JSON Schema type for a filter operator
|
|
285
222
|
*/
|
|
286
223
|
_getOperatorSchemaType(op) {
|
|
@@ -409,6 +346,7 @@ var QueryParser = class {
|
|
|
409
346
|
foreignField,
|
|
410
347
|
as: opts.as || collectionName,
|
|
411
348
|
single: opts.single === true || opts.single === "true",
|
|
349
|
+
...opts.select ? { select: String(opts.select) } : {},
|
|
412
350
|
...opts.pipeline && Array.isArray(opts.pipeline) ? { pipeline: this._sanitizePipeline(opts.pipeline) } : {}
|
|
413
351
|
};
|
|
414
352
|
}
|
|
@@ -514,7 +452,7 @@ var QueryParser = class {
|
|
|
514
452
|
if (opts.match && typeof opts.match === "object") option.match = this._convertPopulateMatch(opts.match);
|
|
515
453
|
if (opts.limit !== void 0) {
|
|
516
454
|
const limit = parseInt(String(opts.limit), 10);
|
|
517
|
-
if (!isNaN(limit) && limit > 0) {
|
|
455
|
+
if (!Number.isNaN(limit) && limit > 0) {
|
|
518
456
|
option.options = option.options || {};
|
|
519
457
|
option.options.limit = limit;
|
|
520
458
|
}
|
|
@@ -528,7 +466,7 @@ var QueryParser = class {
|
|
|
528
466
|
}
|
|
529
467
|
if (opts.skip !== void 0) {
|
|
530
468
|
const skip = parseInt(String(opts.skip), 10);
|
|
531
|
-
if (!isNaN(skip) && skip >= 0) {
|
|
469
|
+
if (!Number.isNaN(skip) && skip >= 0) {
|
|
532
470
|
option.options = option.options || {};
|
|
533
471
|
option.options.skip = skip;
|
|
534
472
|
}
|
|
@@ -592,7 +530,7 @@ var QueryParser = class {
|
|
|
592
530
|
}
|
|
593
531
|
if (operatorMatch) {
|
|
594
532
|
const [, , operator] = operatorMatch;
|
|
595
|
-
if (this.dangerousOperators.includes(
|
|
533
|
+
if (this.dangerousOperators.includes(`$${operator}`)) {
|
|
596
534
|
warn(`[mongokit] Blocked dangerous operator: ${operator}`);
|
|
597
535
|
continue;
|
|
598
536
|
}
|
|
@@ -651,7 +589,7 @@ var QueryParser = class {
|
|
|
651
589
|
"size"
|
|
652
590
|
].includes(op)) {
|
|
653
591
|
processedValue = parseFloat(String(value));
|
|
654
|
-
if (isNaN(processedValue)) return;
|
|
592
|
+
if (Number.isNaN(processedValue)) return;
|
|
655
593
|
} else if (op === "in" || op === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
656
594
|
else processedValue = this._convertValue(value);
|
|
657
595
|
if (typeof filters[field] !== "object" || filters[field] === null || Array.isArray(filters[field])) filters[field] = {};
|
|
@@ -688,7 +626,7 @@ var QueryParser = class {
|
|
|
688
626
|
"size"
|
|
689
627
|
].includes(operator)) {
|
|
690
628
|
processedValue = parseFloat(String(value));
|
|
691
|
-
if (isNaN(processedValue)) continue;
|
|
629
|
+
if (Number.isNaN(processedValue)) continue;
|
|
692
630
|
} else if (operator === "in" || operator === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
693
631
|
else if (operator === "like" || operator === "contains" || operator === "regex") {
|
|
694
632
|
const safeRegex = this._createSafeRegex(value);
|
|
@@ -730,7 +668,7 @@ var QueryParser = class {
|
|
|
730
668
|
}
|
|
731
669
|
_toMongoOperator(operator) {
|
|
732
670
|
const op = operator.toLowerCase();
|
|
733
|
-
return op.startsWith("$") ? op :
|
|
671
|
+
return op.startsWith("$") ? op : `$${op}`;
|
|
734
672
|
}
|
|
735
673
|
_createSafeRegex(pattern, flags = "i") {
|
|
736
674
|
if (pattern === null || pattern === void 0) return null;
|
|
@@ -879,22 +817,21 @@ var QueryParser = class {
|
|
|
879
817
|
const fromDate = from ? new Date(from) : void 0;
|
|
880
818
|
const toDate = to ? new Date(to) : void 0;
|
|
881
819
|
const range = {};
|
|
882
|
-
if (fromDate && !isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
883
|
-
if (toDate && !isNaN(toDate.getTime())) range.$lte = toDate;
|
|
820
|
+
if (fromDate && !Number.isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
821
|
+
if (toDate && !Number.isNaN(toDate.getTime())) range.$lte = toDate;
|
|
884
822
|
output[key] = range;
|
|
885
823
|
}
|
|
886
824
|
return output;
|
|
887
825
|
}
|
|
888
826
|
_pluralize(str) {
|
|
889
|
-
if (str.endsWith("y")) return str.slice(0, -1)
|
|
827
|
+
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
890
828
|
if (str.endsWith("s")) return str;
|
|
891
|
-
return str
|
|
829
|
+
return `${str}s`;
|
|
892
830
|
}
|
|
893
831
|
_capitalize(str) {
|
|
894
832
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
895
833
|
}
|
|
896
834
|
};
|
|
897
|
-
|
|
898
835
|
//#endregion
|
|
899
836
|
//#region src/index.ts
|
|
900
837
|
/**
|
|
@@ -911,6 +848,5 @@ function createRepository(Model, plugins = [], paginationConfig = {}, options =
|
|
|
911
848
|
return new Repository(Model, plugins, paginationConfig, options);
|
|
912
849
|
}
|
|
913
850
|
var src_default = Repository;
|
|
914
|
-
|
|
915
851
|
//#endregion
|
|
916
|
-
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 };
|
|
852
|
+
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,6 +1,28 @@
|
|
|
1
|
-
import { $ as SchemaBuilderOptions, T as HttpError, dt as UserContext, m as CrudSchemas, o as CacheAdapter, pt as ValidationResult, x as FieldPreset } from "./types-
|
|
1
|
+
import { $ as SchemaBuilderOptions, T as HttpError, dt as UserContext, m as CrudSchemas, o as CacheAdapter, pt as ValidationResult, x as FieldPreset } from "./types-BlCwDszq.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,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,4 +1,4 @@
|
|
|
1
|
-
import { A as KeysetPaginationOptions, I as OffsetPaginationOptions, L as OffsetPaginationResult, i as AnyDocument, j as KeysetPaginationResult, n as AggregatePaginationResult, t as AggregatePaginationOptions, z as PaginationConfig } from "../types-
|
|
1
|
+
import { A as KeysetPaginationOptions, I as OffsetPaginationOptions, L as OffsetPaginationResult, i as AnyDocument, j as KeysetPaginationResult, n as AggregatePaginationResult, t as AggregatePaginationOptions, z as PaginationConfig } from "../types-BlCwDszq.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-PLyDhrO7.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-DxqiHv-E.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-Ow6EUIoo.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 };
|