@classytic/mongokit 3.3.2 → 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 +543 -543
- package/dist/index.mjs +25 -100
- 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",
|
|
@@ -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
|
}
|
|
@@ -525,7 +452,7 @@ var QueryParser = class {
|
|
|
525
452
|
if (opts.match && typeof opts.match === "object") option.match = this._convertPopulateMatch(opts.match);
|
|
526
453
|
if (opts.limit !== void 0) {
|
|
527
454
|
const limit = parseInt(String(opts.limit), 10);
|
|
528
|
-
if (!isNaN(limit) && limit > 0) {
|
|
455
|
+
if (!Number.isNaN(limit) && limit > 0) {
|
|
529
456
|
option.options = option.options || {};
|
|
530
457
|
option.options.limit = limit;
|
|
531
458
|
}
|
|
@@ -539,7 +466,7 @@ var QueryParser = class {
|
|
|
539
466
|
}
|
|
540
467
|
if (opts.skip !== void 0) {
|
|
541
468
|
const skip = parseInt(String(opts.skip), 10);
|
|
542
|
-
if (!isNaN(skip) && skip >= 0) {
|
|
469
|
+
if (!Number.isNaN(skip) && skip >= 0) {
|
|
543
470
|
option.options = option.options || {};
|
|
544
471
|
option.options.skip = skip;
|
|
545
472
|
}
|
|
@@ -603,7 +530,7 @@ var QueryParser = class {
|
|
|
603
530
|
}
|
|
604
531
|
if (operatorMatch) {
|
|
605
532
|
const [, , operator] = operatorMatch;
|
|
606
|
-
if (this.dangerousOperators.includes(
|
|
533
|
+
if (this.dangerousOperators.includes(`$${operator}`)) {
|
|
607
534
|
warn(`[mongokit] Blocked dangerous operator: ${operator}`);
|
|
608
535
|
continue;
|
|
609
536
|
}
|
|
@@ -662,7 +589,7 @@ var QueryParser = class {
|
|
|
662
589
|
"size"
|
|
663
590
|
].includes(op)) {
|
|
664
591
|
processedValue = parseFloat(String(value));
|
|
665
|
-
if (isNaN(processedValue)) return;
|
|
592
|
+
if (Number.isNaN(processedValue)) return;
|
|
666
593
|
} else if (op === "in" || op === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
667
594
|
else processedValue = this._convertValue(value);
|
|
668
595
|
if (typeof filters[field] !== "object" || filters[field] === null || Array.isArray(filters[field])) filters[field] = {};
|
|
@@ -699,7 +626,7 @@ var QueryParser = class {
|
|
|
699
626
|
"size"
|
|
700
627
|
].includes(operator)) {
|
|
701
628
|
processedValue = parseFloat(String(value));
|
|
702
|
-
if (isNaN(processedValue)) continue;
|
|
629
|
+
if (Number.isNaN(processedValue)) continue;
|
|
703
630
|
} else if (operator === "in" || operator === "nin") processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
704
631
|
else if (operator === "like" || operator === "contains" || operator === "regex") {
|
|
705
632
|
const safeRegex = this._createSafeRegex(value);
|
|
@@ -741,7 +668,7 @@ var QueryParser = class {
|
|
|
741
668
|
}
|
|
742
669
|
_toMongoOperator(operator) {
|
|
743
670
|
const op = operator.toLowerCase();
|
|
744
|
-
return op.startsWith("$") ? op :
|
|
671
|
+
return op.startsWith("$") ? op : `$${op}`;
|
|
745
672
|
}
|
|
746
673
|
_createSafeRegex(pattern, flags = "i") {
|
|
747
674
|
if (pattern === null || pattern === void 0) return null;
|
|
@@ -890,22 +817,21 @@ var QueryParser = class {
|
|
|
890
817
|
const fromDate = from ? new Date(from) : void 0;
|
|
891
818
|
const toDate = to ? new Date(to) : void 0;
|
|
892
819
|
const range = {};
|
|
893
|
-
if (fromDate && !isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
894
|
-
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;
|
|
895
822
|
output[key] = range;
|
|
896
823
|
}
|
|
897
824
|
return output;
|
|
898
825
|
}
|
|
899
826
|
_pluralize(str) {
|
|
900
|
-
if (str.endsWith("y")) return str.slice(0, -1)
|
|
827
|
+
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
901
828
|
if (str.endsWith("s")) return str;
|
|
902
|
-
return str
|
|
829
|
+
return `${str}s`;
|
|
903
830
|
}
|
|
904
831
|
_capitalize(str) {
|
|
905
832
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
906
833
|
}
|
|
907
834
|
};
|
|
908
|
-
|
|
909
835
|
//#endregion
|
|
910
836
|
//#region src/index.ts
|
|
911
837
|
/**
|
|
@@ -922,6 +848,5 @@ function createRepository(Model, plugins = [], paginationConfig = {}, options =
|
|
|
922
848
|
return new Repository(Model, plugins, paginationConfig, options);
|
|
923
849
|
}
|
|
924
850
|
var src_default = Repository;
|
|
925
|
-
|
|
926
851
|
//#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 };
|
|
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 };
|