@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
|
@@ -1,29 +1,90 @@
|
|
|
1
|
-
import { F as ObjectId, G as PopulateSpec, H as Plugin, L as OffsetPaginationResult, M as Logger, Y as RepositoryInstance, at as SortSpec, c as CacheOptions, et as SelectSpec, ft as ValidationChainOptions, l as CacheStats, mt as ValidatorDefinition, nt as SoftDeleteOptions, q as RepositoryContext, u as CascadeOptions, x as FieldPreset } from "./types-
|
|
1
|
+
import { F as ObjectId, G as PopulateSpec, H as Plugin, L as OffsetPaginationResult, M as Logger, Y as RepositoryInstance, at as SortSpec, c as CacheOptions, et as SelectSpec, ft as ValidationChainOptions, l as CacheStats, mt as ValidatorDefinition, nt as SoftDeleteOptions, q as RepositoryContext, u as CascadeOptions, x as FieldPreset } from "./types-BlCwDszq.mjs";
|
|
2
2
|
import mongoose, { ClientSession } from "mongoose";
|
|
3
3
|
|
|
4
|
-
//#region src/plugins/
|
|
4
|
+
//#region src/plugins/aggregate-helpers.plugin.d.ts
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Aggregate helpers plugin
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
|
-
* const
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* };
|
|
9
|
+
* const repo = new Repository(Model, [
|
|
10
|
+
* methodRegistryPlugin(),
|
|
11
|
+
* aggregateHelpersPlugin(),
|
|
12
|
+
* ]);
|
|
14
13
|
*
|
|
15
|
-
* const
|
|
14
|
+
* const groups = await repo.groupBy('category');
|
|
15
|
+
* const total = await repo.sum('amount', { status: 'completed' });
|
|
16
16
|
*/
|
|
17
|
-
declare function
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/plugins/timestamp.plugin.d.ts
|
|
17
|
+
declare function aggregateHelpersPlugin(): Plugin;
|
|
20
18
|
/**
|
|
21
|
-
*
|
|
19
|
+
* Type interface for repositories using aggregateHelpersPlugin
|
|
22
20
|
*
|
|
23
21
|
* @example
|
|
24
|
-
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { Repository, methodRegistryPlugin, aggregateHelpersPlugin } from '@classytic/mongokit';
|
|
24
|
+
* import type { AggregateHelpersMethods } from '@classytic/mongokit';
|
|
25
|
+
*
|
|
26
|
+
* class OrderRepo extends Repository<IOrder> {}
|
|
27
|
+
*
|
|
28
|
+
* type OrderRepoWithAggregates = OrderRepo & AggregateHelpersMethods;
|
|
29
|
+
*
|
|
30
|
+
* const repo = new OrderRepo(OrderModel, [
|
|
31
|
+
* methodRegistryPlugin(),
|
|
32
|
+
* aggregateHelpersPlugin(),
|
|
33
|
+
* ]) as OrderRepoWithAggregates;
|
|
34
|
+
*
|
|
35
|
+
* // TypeScript autocomplete works!
|
|
36
|
+
* const groups = await repo.groupBy('status');
|
|
37
|
+
* const total = await repo.sum('amount', { status: 'completed' });
|
|
38
|
+
* const avg = await repo.average('amount');
|
|
39
|
+
* ```
|
|
25
40
|
*/
|
|
26
|
-
|
|
41
|
+
interface AggregateHelpersMethods {
|
|
42
|
+
/**
|
|
43
|
+
* Group documents by field value and count occurrences
|
|
44
|
+
* @param field - Field to group by
|
|
45
|
+
* @param options - Operation options
|
|
46
|
+
* @returns Array of groups with _id and count
|
|
47
|
+
*/
|
|
48
|
+
groupBy(field: string, options?: {
|
|
49
|
+
limit?: number;
|
|
50
|
+
session?: unknown;
|
|
51
|
+
}): Promise<Array<{
|
|
52
|
+
_id: unknown;
|
|
53
|
+
count: number;
|
|
54
|
+
}>>;
|
|
55
|
+
/**
|
|
56
|
+
* Calculate sum of field values
|
|
57
|
+
* @param field - Field to sum
|
|
58
|
+
* @param query - Filter query
|
|
59
|
+
* @param options - Operation options
|
|
60
|
+
* @returns Sum of field values
|
|
61
|
+
*/
|
|
62
|
+
sum(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
63
|
+
/**
|
|
64
|
+
* Calculate average of field values
|
|
65
|
+
* @param field - Field to average
|
|
66
|
+
* @param query - Filter query
|
|
67
|
+
* @param options - Operation options
|
|
68
|
+
* @returns Average of field values
|
|
69
|
+
*/
|
|
70
|
+
average(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
71
|
+
/**
|
|
72
|
+
* Get minimum field value
|
|
73
|
+
* @param field - Field to get minimum from
|
|
74
|
+
* @param query - Filter query
|
|
75
|
+
* @param options - Operation options
|
|
76
|
+
* @returns Minimum field value
|
|
77
|
+
*/
|
|
78
|
+
min(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
79
|
+
/**
|
|
80
|
+
* Get maximum field value
|
|
81
|
+
* @param field - Field to get maximum from
|
|
82
|
+
* @param query - Filter query
|
|
83
|
+
* @param options - Operation options
|
|
84
|
+
* @returns Maximum field value
|
|
85
|
+
*/
|
|
86
|
+
max(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
87
|
+
}
|
|
27
88
|
//#endregion
|
|
28
89
|
//#region src/plugins/audit-log.plugin.d.ts
|
|
29
90
|
/**
|
|
@@ -34,688 +95,711 @@ declare function timestampPlugin(): Plugin;
|
|
|
34
95
|
*/
|
|
35
96
|
declare function auditLogPlugin(logger: Logger): Plugin;
|
|
36
97
|
//#endregion
|
|
37
|
-
//#region src/plugins/
|
|
98
|
+
//#region src/plugins/audit-trail.plugin.d.ts
|
|
99
|
+
interface AuditTrailOptions {
|
|
100
|
+
/** Operations to track (default: ['create', 'update', 'delete']) */
|
|
101
|
+
operations?: AuditOperation[];
|
|
102
|
+
/** Store field-level before/after diff on updates (default: true) */
|
|
103
|
+
trackChanges?: boolean;
|
|
104
|
+
/** Store full document snapshot on create (default: false — can be heavy) */
|
|
105
|
+
trackDocument?: boolean;
|
|
106
|
+
/** Auto-purge after N days via MongoDB TTL index (default: undefined — keep forever) */
|
|
107
|
+
ttlDays?: number;
|
|
108
|
+
/** MongoDB collection name (default: 'audit_trails') */
|
|
109
|
+
collectionName?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Extract custom metadata from the repository context.
|
|
112
|
+
* Returned object is stored on the audit entry as `metadata`.
|
|
113
|
+
*/
|
|
114
|
+
metadata?: (context: RepositoryContext) => Record<string, unknown>;
|
|
115
|
+
/**
|
|
116
|
+
* Fields to exclude from change tracking (e.g., passwords, tokens).
|
|
117
|
+
* These fields are redacted in the `changes` diff.
|
|
118
|
+
*/
|
|
119
|
+
excludeFields?: string[];
|
|
120
|
+
}
|
|
121
|
+
type AuditOperation = 'create' | 'update' | 'delete';
|
|
122
|
+
interface AuditEntry {
|
|
123
|
+
model: string;
|
|
124
|
+
operation: AuditOperation;
|
|
125
|
+
documentId: unknown;
|
|
126
|
+
userId?: unknown;
|
|
127
|
+
orgId?: unknown;
|
|
128
|
+
changes?: Record<string, {
|
|
129
|
+
from: unknown;
|
|
130
|
+
to: unknown;
|
|
131
|
+
}>;
|
|
132
|
+
document?: Record<string, unknown>;
|
|
133
|
+
metadata?: Record<string, unknown>;
|
|
134
|
+
timestamp: Date;
|
|
135
|
+
}
|
|
136
|
+
declare function auditTrailPlugin(options?: AuditTrailOptions): Plugin;
|
|
137
|
+
interface AuditQueryOptions {
|
|
138
|
+
model?: string;
|
|
139
|
+
documentId?: string | ObjectId;
|
|
140
|
+
userId?: string | ObjectId;
|
|
141
|
+
orgId?: string | ObjectId;
|
|
142
|
+
operation?: AuditOperation;
|
|
143
|
+
from?: Date;
|
|
144
|
+
to?: Date;
|
|
145
|
+
page?: number;
|
|
146
|
+
limit?: number;
|
|
147
|
+
}
|
|
148
|
+
interface AuditQueryResult {
|
|
149
|
+
docs: AuditEntry[];
|
|
150
|
+
page: number;
|
|
151
|
+
limit: number;
|
|
152
|
+
total: number;
|
|
153
|
+
pages: number;
|
|
154
|
+
hasNext: boolean;
|
|
155
|
+
hasPrev: boolean;
|
|
156
|
+
}
|
|
38
157
|
/**
|
|
39
|
-
*
|
|
158
|
+
* Standalone audit trail query utility.
|
|
159
|
+
* Use this to query audits across all models — e.g., admin dashboards, audit APIs.
|
|
40
160
|
*
|
|
41
|
-
* @example
|
|
161
|
+
* @example
|
|
42
162
|
* ```typescript
|
|
43
|
-
*
|
|
44
|
-
* softDeletePlugin({ deletedField: 'deletedAt' })
|
|
45
|
-
* ]);
|
|
46
|
-
*
|
|
47
|
-
* // Delete (soft)
|
|
48
|
-
* await repo.delete(id);
|
|
49
|
-
*
|
|
50
|
-
* // Restore
|
|
51
|
-
* await repo.restore(id);
|
|
52
|
-
*
|
|
53
|
-
* // Get deleted documents
|
|
54
|
-
* await repo.getDeleted({ page: 1, limit: 20 });
|
|
55
|
-
* ```
|
|
163
|
+
* import { AuditTrailQuery } from '@classytic/mongokit';
|
|
56
164
|
*
|
|
57
|
-
*
|
|
58
|
-
* ```typescript
|
|
59
|
-
* // Schema: { deletedAt: { type: Date, default: null } }
|
|
60
|
-
* const repo = new Repository(Model, [
|
|
61
|
-
* softDeletePlugin({
|
|
62
|
-
* deletedField: 'deletedAt',
|
|
63
|
-
* filterMode: 'null', // default - works with default: null
|
|
64
|
-
* })
|
|
65
|
-
* ]);
|
|
66
|
-
* ```
|
|
165
|
+
* const auditQuery = new AuditTrailQuery(); // defaults to 'audit_trails' collection
|
|
67
166
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* const repo = new Repository(Model, [
|
|
71
|
-
* softDeletePlugin({
|
|
72
|
-
* deletedField: 'deletedAt',
|
|
73
|
-
* ttlDays: 30, // Auto-delete after 30 days
|
|
74
|
-
* })
|
|
75
|
-
* ]);
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
declare function softDeletePlugin(options?: SoftDeleteOptions): Plugin;
|
|
79
|
-
/**
|
|
80
|
-
* TypeScript interface for soft delete plugin methods
|
|
167
|
+
* // All audits for an org
|
|
168
|
+
* const orgAudits = await auditQuery.query({ orgId: '...' });
|
|
81
169
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
170
|
+
* // All updates by a user
|
|
171
|
+
* const userUpdates = await auditQuery.query({
|
|
172
|
+
* userId: '...',
|
|
173
|
+
* operation: 'update',
|
|
174
|
+
* });
|
|
85
175
|
*
|
|
86
|
-
*
|
|
176
|
+
* // All audits for a specific document
|
|
177
|
+
* const docHistory = await auditQuery.query({
|
|
178
|
+
* model: 'Job',
|
|
179
|
+
* documentId: '...',
|
|
180
|
+
* });
|
|
87
181
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
182
|
+
* // Date range
|
|
183
|
+
* const recent = await auditQuery.query({
|
|
184
|
+
* from: new Date('2025-01-01'),
|
|
185
|
+
* to: new Date(),
|
|
186
|
+
* page: 1,
|
|
187
|
+
* limit: 50,
|
|
188
|
+
* });
|
|
92
189
|
*
|
|
93
|
-
* //
|
|
94
|
-
*
|
|
95
|
-
* const
|
|
190
|
+
* // Direct model access for custom queries
|
|
191
|
+
* const model = auditQuery.getModel();
|
|
192
|
+
* const count = await model.countDocuments({ operation: 'delete' });
|
|
96
193
|
* ```
|
|
97
194
|
*/
|
|
98
|
-
|
|
195
|
+
declare class AuditTrailQuery {
|
|
196
|
+
private model;
|
|
197
|
+
constructor(collectionName?: string, ttlDays?: number);
|
|
99
198
|
/**
|
|
100
|
-
*
|
|
101
|
-
* @param id - Document ID to restore
|
|
102
|
-
* @param options - Optional restore options
|
|
103
|
-
* @returns Restored document
|
|
199
|
+
* Get the underlying Mongoose model for custom queries
|
|
104
200
|
*/
|
|
105
|
-
|
|
106
|
-
session?: ClientSession;
|
|
107
|
-
}): Promise<TDoc>;
|
|
201
|
+
getModel(): mongoose.Model<AuditEntry>;
|
|
108
202
|
/**
|
|
109
|
-
*
|
|
110
|
-
* @param params - Query parameters (filters, sort, pagination)
|
|
111
|
-
* @param options - Query options (select, populate, lean, session)
|
|
112
|
-
* @returns Paginated result of deleted documents
|
|
203
|
+
* Query audit entries with filters and pagination
|
|
113
204
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
205
|
+
query(options?: AuditQueryOptions): Promise<AuditQueryResult>;
|
|
206
|
+
/**
|
|
207
|
+
* Get audit trail for a specific document
|
|
208
|
+
*/
|
|
209
|
+
getDocumentTrail(model: string, documentId: string | ObjectId, options?: {
|
|
117
210
|
page?: number;
|
|
118
211
|
limit?: number;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
212
|
+
operation?: AuditOperation;
|
|
213
|
+
}): Promise<AuditQueryResult>;
|
|
214
|
+
/**
|
|
215
|
+
* Get all audits for a user
|
|
216
|
+
*/
|
|
217
|
+
getUserTrail(userId: string | ObjectId, options?: {
|
|
218
|
+
page?: number;
|
|
219
|
+
limit?: number;
|
|
220
|
+
operation?: AuditOperation;
|
|
221
|
+
orgId?: string | ObjectId;
|
|
222
|
+
}): Promise<AuditQueryResult>;
|
|
223
|
+
/**
|
|
224
|
+
* Get all audits for an organization
|
|
225
|
+
*/
|
|
226
|
+
getOrgTrail(orgId: string | ObjectId, options?: {
|
|
227
|
+
page?: number;
|
|
228
|
+
limit?: number;
|
|
229
|
+
operation?: AuditOperation;
|
|
230
|
+
model?: string;
|
|
231
|
+
}): Promise<AuditQueryResult>;
|
|
125
232
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
233
|
+
interface AuditTrailMethods {
|
|
234
|
+
/**
|
|
235
|
+
* Get paginated audit trail for a document
|
|
236
|
+
*/
|
|
237
|
+
getAuditTrail(documentId: string | ObjectId, options?: {
|
|
238
|
+
page?: number;
|
|
239
|
+
limit?: number;
|
|
240
|
+
operation?: AuditOperation;
|
|
241
|
+
}): Promise<AuditQueryResult>;
|
|
135
242
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Method registry plugin that enables dynamic method registration
|
|
138
|
-
*/
|
|
139
|
-
declare function methodRegistryPlugin(): Plugin;
|
|
140
243
|
//#endregion
|
|
141
|
-
//#region src/plugins/
|
|
142
|
-
type OperationType = 'create' | 'createMany' | 'update' | 'delete';
|
|
244
|
+
//#region src/plugins/batch-operations.plugin.d.ts
|
|
143
245
|
/**
|
|
144
|
-
*
|
|
246
|
+
* Batch operations plugin
|
|
145
247
|
*
|
|
146
248
|
* @example
|
|
147
249
|
* const repo = new Repository(Model, [
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* uniqueField('email', 'Email already exists'),
|
|
151
|
-
* blockIf('no-delete-admin', ['delete'], ctx => ctx.data?.role === 'admin', 'Cannot delete admin'),
|
|
152
|
-
* ])
|
|
250
|
+
* methodRegistryPlugin(),
|
|
251
|
+
* batchOperationsPlugin(),
|
|
153
252
|
* ]);
|
|
154
|
-
*/
|
|
155
|
-
declare function validationChainPlugin(validators?: ValidatorDefinition[], options?: ValidationChainOptions): Plugin;
|
|
156
|
-
/**
|
|
157
|
-
* Block operation if condition is true
|
|
158
253
|
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*/
|
|
162
|
-
declare function blockIf(name: string, operations: OperationType[], condition: (context: RepositoryContext) => boolean, errorMessage: string): ValidatorDefinition;
|
|
163
|
-
/**
|
|
164
|
-
* Require a field to be present
|
|
165
|
-
*/
|
|
166
|
-
declare function requireField(field: string, operations?: OperationType[]): ValidatorDefinition;
|
|
167
|
-
/**
|
|
168
|
-
* Auto-inject a value if not present
|
|
169
|
-
*/
|
|
170
|
-
declare function autoInject(field: string, getter: (context: RepositoryContext) => unknown, operations?: OperationType[]): ValidatorDefinition;
|
|
171
|
-
/**
|
|
172
|
-
* Make a field immutable (cannot be updated)
|
|
173
|
-
*/
|
|
174
|
-
declare function immutableField(field: string): ValidatorDefinition;
|
|
175
|
-
/**
|
|
176
|
-
* Ensure field value is unique
|
|
254
|
+
* await repo.updateMany({ status: 'pending' }, { status: 'active' });
|
|
255
|
+
* await repo.deleteMany({ status: 'deleted' });
|
|
177
256
|
*/
|
|
178
|
-
declare function
|
|
179
|
-
//#endregion
|
|
180
|
-
//#region src/plugins/mongo-operations.plugin.d.ts
|
|
257
|
+
declare function batchOperationsPlugin(): Plugin;
|
|
181
258
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* Adds MongoDB-specific atomic operations to repositories:
|
|
185
|
-
* - upsert: Create or update document
|
|
186
|
-
* - increment/decrement: Atomic numeric operations
|
|
187
|
-
* - pushToArray/pullFromArray/addToSet: Array operations
|
|
188
|
-
* - setField/unsetField/renameField: Field operations
|
|
189
|
-
* - multiplyField: Multiply numeric field
|
|
190
|
-
* - setMin/setMax: Conditional min/max updates
|
|
191
|
-
*
|
|
192
|
-
* @example Basic usage (no TypeScript autocomplete)
|
|
193
|
-
* ```typescript
|
|
194
|
-
* const repo = new Repository(ProductModel, [
|
|
195
|
-
* methodRegistryPlugin(),
|
|
196
|
-
* mongoOperationsPlugin(),
|
|
197
|
-
* ]);
|
|
198
|
-
*
|
|
199
|
-
* // Works at runtime but TypeScript doesn't know about these methods
|
|
200
|
-
* await (repo as any).increment(productId, 'views', 1);
|
|
201
|
-
* await (repo as any).pushToArray(productId, 'tags', 'featured');
|
|
202
|
-
* ```
|
|
259
|
+
* Type interface for repositories using batchOperationsPlugin
|
|
203
260
|
*
|
|
204
|
-
* @example
|
|
261
|
+
* @example
|
|
205
262
|
* ```typescript
|
|
206
|
-
* import { Repository,
|
|
207
|
-
* import type {
|
|
263
|
+
* import { Repository, methodRegistryPlugin, batchOperationsPlugin } from '@classytic/mongokit';
|
|
264
|
+
* import type { BatchOperationsMethods } from '@classytic/mongokit';
|
|
208
265
|
*
|
|
209
|
-
* class ProductRepo extends Repository<IProduct> {
|
|
210
|
-
* // Add your custom methods here
|
|
211
|
-
* }
|
|
266
|
+
* class ProductRepo extends Repository<IProduct> {}
|
|
212
267
|
*
|
|
213
|
-
*
|
|
214
|
-
* type ProductRepoWithPlugins = ProductRepo & MongoOperationsMethods<IProduct>;
|
|
268
|
+
* type ProductRepoWithBatch = ProductRepo & BatchOperationsMethods;
|
|
215
269
|
*
|
|
216
270
|
* const repo = new ProductRepo(ProductModel, [
|
|
217
271
|
* methodRegistryPlugin(),
|
|
218
|
-
*
|
|
219
|
-
* ]) as
|
|
272
|
+
* batchOperationsPlugin(),
|
|
273
|
+
* ]) as ProductRepoWithBatch;
|
|
220
274
|
*
|
|
221
|
-
* //
|
|
222
|
-
* await repo.
|
|
223
|
-
* await repo.
|
|
224
|
-
* await repo.pushToArray(productId, 'tags', 'featured');
|
|
275
|
+
* // TypeScript autocomplete works!
|
|
276
|
+
* await repo.updateMany({ status: 'pending' }, { status: 'active' });
|
|
277
|
+
* await repo.deleteMany({ status: 'archived' });
|
|
225
278
|
* ```
|
|
226
279
|
*/
|
|
227
|
-
|
|
280
|
+
/** Bulk write result */
|
|
281
|
+
interface BulkWriteResult {
|
|
282
|
+
ok: number;
|
|
283
|
+
insertedCount: number;
|
|
284
|
+
upsertedCount: number;
|
|
285
|
+
matchedCount: number;
|
|
286
|
+
modifiedCount: number;
|
|
287
|
+
deletedCount: number;
|
|
288
|
+
insertedIds: Record<number, unknown>;
|
|
289
|
+
upsertedIds: Record<number, unknown>;
|
|
290
|
+
}
|
|
291
|
+
interface BatchOperationsMethods {
|
|
292
|
+
/**
|
|
293
|
+
* Update multiple documents matching the query
|
|
294
|
+
* @param query - Query to match documents
|
|
295
|
+
* @param data - Update data
|
|
296
|
+
* @param options - Operation options
|
|
297
|
+
* @returns Update result with matchedCount, modifiedCount, etc.
|
|
298
|
+
*/
|
|
299
|
+
updateMany(query: Record<string, unknown>, data: Record<string, unknown>, options?: {
|
|
300
|
+
session?: ClientSession;
|
|
301
|
+
updatePipeline?: boolean;
|
|
302
|
+
}): Promise<{
|
|
303
|
+
acknowledged: boolean;
|
|
304
|
+
matchedCount: number;
|
|
305
|
+
modifiedCount: number;
|
|
306
|
+
upsertedCount: number;
|
|
307
|
+
upsertedId: unknown;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Delete multiple documents matching the query
|
|
311
|
+
* @param query - Query to match documents
|
|
312
|
+
* @param options - Operation options
|
|
313
|
+
* @returns Delete result with deletedCount
|
|
314
|
+
*/
|
|
315
|
+
deleteMany(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<{
|
|
316
|
+
acknowledged: boolean;
|
|
317
|
+
deletedCount: number;
|
|
318
|
+
}>;
|
|
319
|
+
/**
|
|
320
|
+
* Execute heterogeneous bulk write operations in a single database call.
|
|
321
|
+
* Supports insertOne, updateOne, updateMany, deleteOne, deleteMany, replaceOne.
|
|
322
|
+
*
|
|
323
|
+
* @param operations - Array of bulk write operations
|
|
324
|
+
* @param options - Options (session, ordered)
|
|
325
|
+
* @returns Bulk write result with counts per operation type
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* const result = await repo.bulkWrite([
|
|
329
|
+
* { insertOne: { document: { name: 'Item', price: 10 } } },
|
|
330
|
+
* { updateOne: { filter: { _id: id }, update: { $inc: { views: 1 } } } },
|
|
331
|
+
* { deleteOne: { filter: { _id: oldId } } },
|
|
332
|
+
* ]);
|
|
333
|
+
* console.log(result.insertedCount, result.modifiedCount, result.deletedCount);
|
|
334
|
+
*/
|
|
335
|
+
bulkWrite(operations: Record<string, unknown>[], options?: {
|
|
336
|
+
session?: ClientSession;
|
|
337
|
+
ordered?: boolean;
|
|
338
|
+
}): Promise<BulkWriteResult>;
|
|
339
|
+
}
|
|
340
|
+
//#endregion
|
|
341
|
+
//#region src/plugins/cache.plugin.d.ts
|
|
228
342
|
/**
|
|
229
|
-
*
|
|
343
|
+
* Cache plugin factory
|
|
230
344
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
345
|
+
* @param options - Cache configuration
|
|
346
|
+
* @returns Plugin instance
|
|
347
|
+
*/
|
|
348
|
+
declare function cachePlugin(options: CacheOptions): Plugin;
|
|
349
|
+
/**
|
|
350
|
+
* TypeScript interface for cache plugin methods
|
|
233
351
|
*
|
|
234
352
|
* @example
|
|
235
353
|
* ```typescript
|
|
236
|
-
* import {
|
|
237
|
-
* import type { MongoOperationsMethods } from '@classytic/mongokit';
|
|
238
|
-
*
|
|
239
|
-
* // Without type safety (base is flexible)
|
|
240
|
-
* class ProductRepo extends Repository<IProduct> {
|
|
241
|
-
* // Can add anything - fully flexible
|
|
242
|
-
* }
|
|
354
|
+
* import type { CacheMethods } from '@classytic/mongokit';
|
|
243
355
|
*
|
|
244
|
-
*
|
|
245
|
-
* class ProductRepo extends Repository<IProduct> implements MongoOperationsMethods<IProduct> {
|
|
246
|
-
* // TypeScript knows about upsert, increment, decrement, etc.
|
|
247
|
-
* }
|
|
356
|
+
* type ProductRepoWithCache = ProductRepo & CacheMethods;
|
|
248
357
|
*
|
|
249
|
-
* const
|
|
358
|
+
* const productRepo = new ProductRepo(ProductModel, [
|
|
250
359
|
* methodRegistryPlugin(),
|
|
251
|
-
*
|
|
252
|
-
* ]);
|
|
360
|
+
* cachePlugin({ adapter: redisAdapter, ttl: 60 }),
|
|
361
|
+
* ]) as ProductRepoWithCache;
|
|
253
362
|
*
|
|
254
|
-
* //
|
|
255
|
-
* await
|
|
256
|
-
* await
|
|
363
|
+
* // TypeScript autocomplete for cache methods
|
|
364
|
+
* await productRepo.invalidateCache(productId);
|
|
365
|
+
* await productRepo.invalidateListCache();
|
|
366
|
+
* await productRepo.invalidateAllCache();
|
|
367
|
+
* const stats = productRepo.getCacheStats();
|
|
368
|
+
* productRepo.resetCacheStats();
|
|
257
369
|
* ```
|
|
258
370
|
*/
|
|
259
|
-
interface
|
|
371
|
+
interface CacheMethods {
|
|
260
372
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* @param
|
|
264
|
-
* @param options - Operation options (session, etc.)
|
|
265
|
-
* @returns Created or updated document
|
|
373
|
+
* Invalidate cache for a specific document
|
|
374
|
+
* Use when document was updated outside this service
|
|
375
|
+
* @param id - Document ID to invalidate
|
|
266
376
|
*/
|
|
267
|
-
|
|
377
|
+
invalidateCache(id: string): Promise<void>;
|
|
268
378
|
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* @param field - Field name to increment
|
|
272
|
-
* @param value - Value to increment by (default: 1)
|
|
273
|
-
* @param options - Operation options (session, etc.)
|
|
274
|
-
* @returns Updated document
|
|
379
|
+
* Invalidate all list caches for this model
|
|
380
|
+
* Use when bulk changes happened outside this service
|
|
275
381
|
*/
|
|
276
|
-
|
|
382
|
+
invalidateListCache(): Promise<void>;
|
|
277
383
|
/**
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* @param field - Field name to decrement
|
|
281
|
-
* @param value - Value to decrement by (default: 1)
|
|
282
|
-
* @param options - Operation options (session, etc.)
|
|
283
|
-
* @returns Updated document
|
|
284
|
-
*/
|
|
285
|
-
decrement(id: string | ObjectId, field: string, value?: number, options?: Record<string, unknown>): Promise<TDoc>;
|
|
286
|
-
/**
|
|
287
|
-
* Push value to array field
|
|
288
|
-
* @param id - Document ID
|
|
289
|
-
* @param field - Array field name
|
|
290
|
-
* @param value - Value to push
|
|
291
|
-
* @param options - Operation options (session, etc.)
|
|
292
|
-
* @returns Updated document
|
|
293
|
-
*/
|
|
294
|
-
pushToArray(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
295
|
-
/**
|
|
296
|
-
* Remove value from array field
|
|
297
|
-
* @param id - Document ID
|
|
298
|
-
* @param field - Array field name
|
|
299
|
-
* @param value - Value to remove
|
|
300
|
-
* @param options - Operation options (session, etc.)
|
|
301
|
-
* @returns Updated document
|
|
302
|
-
*/
|
|
303
|
-
pullFromArray(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
304
|
-
/**
|
|
305
|
-
* Add value to array only if not already present (unique)
|
|
306
|
-
* @param id - Document ID
|
|
307
|
-
* @param field - Array field name
|
|
308
|
-
* @param value - Value to add
|
|
309
|
-
* @param options - Operation options (session, etc.)
|
|
310
|
-
* @returns Updated document
|
|
311
|
-
*/
|
|
312
|
-
addToSet(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
313
|
-
/**
|
|
314
|
-
* Set field value (alias for update with $set)
|
|
315
|
-
* @param id - Document ID
|
|
316
|
-
* @param field - Field name
|
|
317
|
-
* @param value - Value to set
|
|
318
|
-
* @param options - Operation options (session, etc.)
|
|
319
|
-
* @returns Updated document
|
|
320
|
-
*/
|
|
321
|
-
setField(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
322
|
-
/**
|
|
323
|
-
* Unset (remove) field from document
|
|
324
|
-
* @param id - Document ID
|
|
325
|
-
* @param fields - Field name or array of field names to remove
|
|
326
|
-
* @param options - Operation options (session, etc.)
|
|
327
|
-
* @returns Updated document
|
|
328
|
-
*/
|
|
329
|
-
unsetField(id: string | ObjectId, fields: string | string[], options?: Record<string, unknown>): Promise<TDoc>;
|
|
330
|
-
/**
|
|
331
|
-
* Rename field in document
|
|
332
|
-
* @param id - Document ID
|
|
333
|
-
* @param oldName - Current field name
|
|
334
|
-
* @param newName - New field name
|
|
335
|
-
* @param options - Operation options (session, etc.)
|
|
336
|
-
* @returns Updated document
|
|
337
|
-
*/
|
|
338
|
-
renameField(id: string | ObjectId, oldName: string, newName: string, options?: Record<string, unknown>): Promise<TDoc>;
|
|
339
|
-
/**
|
|
340
|
-
* Multiply numeric field by value
|
|
341
|
-
* @param id - Document ID
|
|
342
|
-
* @param field - Field name
|
|
343
|
-
* @param multiplier - Multiplier value
|
|
344
|
-
* @param options - Operation options (session, etc.)
|
|
345
|
-
* @returns Updated document
|
|
346
|
-
*/
|
|
347
|
-
multiplyField(id: string | ObjectId, field: string, multiplier: number, options?: Record<string, unknown>): Promise<TDoc>;
|
|
348
|
-
/**
|
|
349
|
-
* Set field to minimum value (only if current value is greater)
|
|
350
|
-
* @param id - Document ID
|
|
351
|
-
* @param field - Field name
|
|
352
|
-
* @param value - Minimum value
|
|
353
|
-
* @param options - Operation options (session, etc.)
|
|
354
|
-
* @returns Updated document
|
|
384
|
+
* Invalidate ALL cache entries for this model
|
|
385
|
+
* Nuclear option - use sparingly
|
|
355
386
|
*/
|
|
356
|
-
|
|
387
|
+
invalidateAllCache(): Promise<void>;
|
|
357
388
|
/**
|
|
358
|
-
*
|
|
359
|
-
* @
|
|
360
|
-
* @param field - Field name
|
|
361
|
-
* @param value - Maximum value
|
|
362
|
-
* @param options - Operation options (session, etc.)
|
|
363
|
-
* @returns Updated document
|
|
389
|
+
* Get cache statistics for monitoring
|
|
390
|
+
* @returns Cache statistics (hits, misses, sets, invalidations)
|
|
364
391
|
*/
|
|
365
|
-
|
|
392
|
+
getCacheStats(): CacheStats;
|
|
366
393
|
/**
|
|
367
|
-
*
|
|
368
|
-
* Combines $inc, $set, $push, $pull, $addToSet, $unset, $setOnInsert, etc.
|
|
369
|
-
*
|
|
370
|
-
* @param id - Document ID
|
|
371
|
-
* @param operators - MongoDB update operators (e.g. { $inc: { views: 1 }, $set: { lastViewed: new Date() } })
|
|
372
|
-
* @param options - Operation options (session, arrayFilters, etc.)
|
|
373
|
-
* @returns Updated document
|
|
374
|
-
*
|
|
375
|
-
* @example
|
|
376
|
-
* await repo.atomicUpdate(postId, {
|
|
377
|
-
* $inc: { reactionCount: -1 },
|
|
378
|
-
* $set: { lastActiveAt: new Date() },
|
|
379
|
-
* $push: { history: { action: 'unreact', at: new Date() } }
|
|
380
|
-
* });
|
|
394
|
+
* Reset cache statistics
|
|
381
395
|
*/
|
|
382
|
-
|
|
396
|
+
resetCacheStats(): void;
|
|
383
397
|
}
|
|
384
398
|
//#endregion
|
|
385
|
-
//#region src/plugins/
|
|
399
|
+
//#region src/plugins/cascade.plugin.d.ts
|
|
386
400
|
/**
|
|
387
|
-
*
|
|
401
|
+
* Cascade delete plugin
|
|
402
|
+
*
|
|
403
|
+
* Deletes related documents after the parent document is deleted.
|
|
404
|
+
* Works with both hard delete and soft delete scenarios.
|
|
405
|
+
*
|
|
406
|
+
* @param options - Cascade configuration
|
|
407
|
+
* @returns Plugin
|
|
408
|
+
*/
|
|
409
|
+
declare function cascadePlugin(options: CascadeOptions): Plugin;
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/plugins/custom-id.plugin.d.ts
|
|
412
|
+
/**
|
|
413
|
+
* Generator function that produces a unique ID.
|
|
414
|
+
* Receives the full repository context for conditional logic.
|
|
415
|
+
*/
|
|
416
|
+
type IdGenerator = (context: RepositoryContext) => string | Promise<string>;
|
|
417
|
+
interface CustomIdOptions {
|
|
418
|
+
/** Field to store the custom ID (default: 'customId') */
|
|
419
|
+
field?: string;
|
|
420
|
+
/** Function to generate the ID. Can be async. */
|
|
421
|
+
generator: IdGenerator;
|
|
422
|
+
/** Only generate if the field is missing/empty (default: true) */
|
|
423
|
+
generateOnlyIfEmpty?: boolean;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Atomically increment and return the next sequence value for a given key.
|
|
427
|
+
* Uses `findOneAndUpdate` with `upsert` + `$inc` — fully atomic even under
|
|
428
|
+
* heavy concurrency.
|
|
429
|
+
*
|
|
430
|
+
* @param counterKey - Unique key identifying this counter (e.g., "Invoice" or "Invoice:2026-02")
|
|
431
|
+
* @param increment - Value to increment by (default: 1)
|
|
432
|
+
* @returns The next sequence number (after increment)
|
|
388
433
|
*
|
|
389
434
|
* @example
|
|
390
|
-
* const
|
|
391
|
-
*
|
|
392
|
-
* batchOperationsPlugin(),
|
|
393
|
-
* ]);
|
|
435
|
+
* const seq = await getNextSequence('invoices');
|
|
436
|
+
* // First call → 1, second → 2, ...
|
|
394
437
|
*
|
|
395
|
-
*
|
|
396
|
-
* await
|
|
438
|
+
* @example Batch increment for createMany
|
|
439
|
+
* const startSeq = await getNextSequence('invoices', 5);
|
|
440
|
+
* // If current was 10, returns 15 (you use 11, 12, 13, 14, 15)
|
|
397
441
|
*/
|
|
398
|
-
declare function
|
|
442
|
+
declare function getNextSequence(counterKey: string, increment?: number, connection?: mongoose.Connection): Promise<number>;
|
|
443
|
+
interface SequentialIdOptions {
|
|
444
|
+
/** Prefix string (e.g., 'INV', 'ORD') */
|
|
445
|
+
prefix: string;
|
|
446
|
+
/** Mongoose model — used to derive the counter key from model name */
|
|
447
|
+
model: mongoose.Model<any>;
|
|
448
|
+
/** Number of digits to pad to (default: 4 → "0001") */
|
|
449
|
+
padding?: number;
|
|
450
|
+
/** Separator between prefix and number (default: '-') */
|
|
451
|
+
separator?: string;
|
|
452
|
+
/** Custom counter key override (default: model.modelName) */
|
|
453
|
+
counterKey?: string;
|
|
454
|
+
}
|
|
399
455
|
/**
|
|
400
|
-
*
|
|
456
|
+
* Generator: Simple sequential counter.
|
|
457
|
+
* Produces IDs like `INV-0001`, `INV-0002`, etc.
|
|
458
|
+
*
|
|
459
|
+
* Uses atomic MongoDB counters — safe under concurrency.
|
|
401
460
|
*
|
|
402
461
|
* @example
|
|
403
462
|
* ```typescript
|
|
404
|
-
*
|
|
405
|
-
*
|
|
463
|
+
* customIdPlugin({
|
|
464
|
+
* field: 'invoiceNumber',
|
|
465
|
+
* generator: sequentialId({ prefix: 'INV', model: InvoiceModel }),
|
|
466
|
+
* })
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
declare function sequentialId(options: SequentialIdOptions): IdGenerator;
|
|
470
|
+
interface DateSequentialIdOptions {
|
|
471
|
+
/** Prefix string (e.g., 'BILL', 'INV') */
|
|
472
|
+
prefix: string;
|
|
473
|
+
/** Mongoose model — used to derive the counter key */
|
|
474
|
+
model: mongoose.Model<any>;
|
|
475
|
+
/**
|
|
476
|
+
* Partition granularity — counter resets each period.
|
|
477
|
+
* - 'yearly' → BILL-2026-0001, resets every January
|
|
478
|
+
* - 'monthly' → BILL-2026-02-0001, resets every month
|
|
479
|
+
* - 'daily' → BILL-2026-02-20-0001, resets every day
|
|
480
|
+
*/
|
|
481
|
+
partition?: 'yearly' | 'monthly' | 'daily';
|
|
482
|
+
/** Number of digits to pad to (default: 4) */
|
|
483
|
+
padding?: number;
|
|
484
|
+
/** Separator (default: '-') */
|
|
485
|
+
separator?: string;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Generator: Date-partitioned sequential counter.
|
|
489
|
+
* Counter resets per period — great for invoice/bill numbering.
|
|
406
490
|
*
|
|
407
|
-
*
|
|
491
|
+
* Produces IDs like:
|
|
492
|
+
* - yearly: `BILL-2026-0001`
|
|
493
|
+
* - monthly: `BILL-2026-02-0001`
|
|
494
|
+
* - daily: `BILL-2026-02-20-0001`
|
|
408
495
|
*
|
|
409
|
-
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* customIdPlugin({
|
|
499
|
+
* field: 'billNumber',
|
|
500
|
+
* generator: dateSequentialId({
|
|
501
|
+
* prefix: 'BILL',
|
|
502
|
+
* model: BillModel,
|
|
503
|
+
* partition: 'monthly',
|
|
504
|
+
* }),
|
|
505
|
+
* })
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
declare function dateSequentialId(options: DateSequentialIdOptions): IdGenerator;
|
|
509
|
+
interface PrefixedIdOptions {
|
|
510
|
+
/** Prefix string (e.g., 'USR', 'TXN') */
|
|
511
|
+
prefix: string;
|
|
512
|
+
/** Separator (default: '_') */
|
|
513
|
+
separator?: string;
|
|
514
|
+
/** Length of the random suffix (default: 12) */
|
|
515
|
+
length?: number;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Generator: Prefix + random alphanumeric suffix.
|
|
519
|
+
* Does NOT require a database round-trip — purely in-memory.
|
|
410
520
|
*
|
|
411
|
-
*
|
|
412
|
-
* methodRegistryPlugin(),
|
|
413
|
-
* batchOperationsPlugin(),
|
|
414
|
-
* ]) as ProductRepoWithBatch;
|
|
521
|
+
* Produces IDs like: `USR_a7b3xk9m2p1q`
|
|
415
522
|
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
523
|
+
* Good for: user-facing IDs where ordering doesn't matter.
|
|
524
|
+
* Not suitable for sequential numbering.
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```typescript
|
|
528
|
+
* customIdPlugin({
|
|
529
|
+
* field: 'publicId',
|
|
530
|
+
* generator: prefixedId({ prefix: 'USR', length: 10 }),
|
|
531
|
+
* })
|
|
419
532
|
* ```
|
|
420
533
|
*/
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
* @param options - Operation options
|
|
454
|
-
* @returns Delete result with deletedCount
|
|
455
|
-
*/
|
|
456
|
-
deleteMany(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<{
|
|
457
|
-
acknowledged: boolean;
|
|
458
|
-
deletedCount: number;
|
|
459
|
-
}>;
|
|
460
|
-
/**
|
|
461
|
-
* Execute heterogeneous bulk write operations in a single database call.
|
|
462
|
-
* Supports insertOne, updateOne, updateMany, deleteOne, deleteMany, replaceOne.
|
|
463
|
-
*
|
|
464
|
-
* @param operations - Array of bulk write operations
|
|
465
|
-
* @param options - Options (session, ordered)
|
|
466
|
-
* @returns Bulk write result with counts per operation type
|
|
467
|
-
*
|
|
468
|
-
* @example
|
|
469
|
-
* const result = await repo.bulkWrite([
|
|
470
|
-
* { insertOne: { document: { name: 'Item', price: 10 } } },
|
|
471
|
-
* { updateOne: { filter: { _id: id }, update: { $inc: { views: 1 } } } },
|
|
472
|
-
* { deleteOne: { filter: { _id: oldId } } },
|
|
473
|
-
* ]);
|
|
474
|
-
* console.log(result.insertedCount, result.modifiedCount, result.deletedCount);
|
|
475
|
-
*/
|
|
476
|
-
bulkWrite(operations: Record<string, unknown>[], options?: {
|
|
477
|
-
session?: ClientSession;
|
|
478
|
-
ordered?: boolean;
|
|
479
|
-
}): Promise<BulkWriteResult>;
|
|
534
|
+
declare function prefixedId(options: PrefixedIdOptions): IdGenerator;
|
|
535
|
+
/**
|
|
536
|
+
* Custom ID plugin — injects generated IDs into documents before creation.
|
|
537
|
+
*
|
|
538
|
+
* @param options - Configuration for ID generation
|
|
539
|
+
* @returns Plugin instance
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```typescript
|
|
543
|
+
* import { Repository, customIdPlugin, sequentialId } from '@classytic/mongokit';
|
|
544
|
+
*
|
|
545
|
+
* const invoiceRepo = new Repository(InvoiceModel, [
|
|
546
|
+
* customIdPlugin({
|
|
547
|
+
* field: 'invoiceNumber',
|
|
548
|
+
* generator: sequentialId({ prefix: 'INV', model: InvoiceModel }),
|
|
549
|
+
* }),
|
|
550
|
+
* ]);
|
|
551
|
+
*
|
|
552
|
+
* const inv = await invoiceRepo.create({ amount: 100 });
|
|
553
|
+
* console.log(inv.invoiceNumber); // "INV-0001"
|
|
554
|
+
* ```
|
|
555
|
+
*/
|
|
556
|
+
declare function customIdPlugin(options: CustomIdOptions): Plugin;
|
|
557
|
+
//#endregion
|
|
558
|
+
//#region src/plugins/elastic.plugin.d.ts
|
|
559
|
+
interface ElasticSearchOptions {
|
|
560
|
+
/** Elasticsearch or OpenSearch client instance */
|
|
561
|
+
client: any;
|
|
562
|
+
/** Index name to perform search against */
|
|
563
|
+
index: string;
|
|
564
|
+
/** Field to extract MongoDB ID from the indexed document (default: '_id') */
|
|
565
|
+
idField?: string;
|
|
480
566
|
}
|
|
567
|
+
declare function elasticSearchPlugin(options: ElasticSearchOptions): Plugin;
|
|
481
568
|
//#endregion
|
|
482
|
-
//#region src/plugins/
|
|
569
|
+
//#region src/plugins/field-filter.plugin.d.ts
|
|
483
570
|
/**
|
|
484
|
-
*
|
|
571
|
+
* Field filter plugin that restricts fields based on user context
|
|
485
572
|
*
|
|
486
573
|
* @example
|
|
487
|
-
* const
|
|
574
|
+
* const fieldPreset = {
|
|
575
|
+
* public: ['id', 'name'],
|
|
576
|
+
* authenticated: ['email'],
|
|
577
|
+
* admin: ['createdAt', 'internalNotes']
|
|
578
|
+
* };
|
|
579
|
+
*
|
|
580
|
+
* const repo = new Repository(Model, [fieldFilterPlugin(fieldPreset)]);
|
|
581
|
+
*/
|
|
582
|
+
declare function fieldFilterPlugin(fieldPreset: FieldPreset): Plugin;
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region src/plugins/method-registry.plugin.d.ts
|
|
585
|
+
/**
|
|
586
|
+
* Extended repository interface with method registry
|
|
587
|
+
*/
|
|
588
|
+
interface MethodRegistryRepository extends RepositoryInstance {
|
|
589
|
+
registerMethod(name: string, fn: Function): void;
|
|
590
|
+
hasMethod(name: string): boolean;
|
|
591
|
+
getRegisteredMethods(): string[];
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Method registry plugin that enables dynamic method registration
|
|
595
|
+
*/
|
|
596
|
+
declare function methodRegistryPlugin(): Plugin;
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/plugins/mongo-operations.plugin.d.ts
|
|
599
|
+
/**
|
|
600
|
+
* MongoDB operations plugin
|
|
601
|
+
*
|
|
602
|
+
* Adds MongoDB-specific atomic operations to repositories:
|
|
603
|
+
* - upsert: Create or update document
|
|
604
|
+
* - increment/decrement: Atomic numeric operations
|
|
605
|
+
* - pushToArray/pullFromArray/addToSet: Array operations
|
|
606
|
+
* - setField/unsetField/renameField: Field operations
|
|
607
|
+
* - multiplyField: Multiply numeric field
|
|
608
|
+
* - setMin/setMax: Conditional min/max updates
|
|
609
|
+
*
|
|
610
|
+
* @example Basic usage (no TypeScript autocomplete)
|
|
611
|
+
* ```typescript
|
|
612
|
+
* const repo = new Repository(ProductModel, [
|
|
488
613
|
* methodRegistryPlugin(),
|
|
489
|
-
*
|
|
614
|
+
* mongoOperationsPlugin(),
|
|
490
615
|
* ]);
|
|
491
616
|
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Type interface for repositories using aggregateHelpersPlugin
|
|
617
|
+
* // Works at runtime but TypeScript doesn't know about these methods
|
|
618
|
+
* await (repo as any).increment(productId, 'views', 1);
|
|
619
|
+
* await (repo as any).pushToArray(productId, 'tags', 'featured');
|
|
620
|
+
* ```
|
|
498
621
|
*
|
|
499
|
-
* @example
|
|
622
|
+
* @example With TypeScript type safety (recommended)
|
|
500
623
|
* ```typescript
|
|
501
|
-
* import { Repository,
|
|
502
|
-
* import type {
|
|
624
|
+
* import { Repository, mongoOperationsPlugin, methodRegistryPlugin } from '@classytic/mongokit';
|
|
625
|
+
* import type { MongoOperationsMethods } from '@classytic/mongokit';
|
|
503
626
|
*
|
|
504
|
-
* class
|
|
627
|
+
* class ProductRepo extends Repository<IProduct> {
|
|
628
|
+
* // Add your custom methods here
|
|
629
|
+
* }
|
|
505
630
|
*
|
|
506
|
-
* type
|
|
631
|
+
* // Create with type assertion to get autocomplete for plugin methods
|
|
632
|
+
* type ProductRepoWithPlugins = ProductRepo & MongoOperationsMethods<IProduct>;
|
|
507
633
|
*
|
|
508
|
-
* const repo = new
|
|
634
|
+
* const repo = new ProductRepo(ProductModel, [
|
|
509
635
|
* methodRegistryPlugin(),
|
|
510
|
-
*
|
|
511
|
-
* ]) as
|
|
636
|
+
* mongoOperationsPlugin(),
|
|
637
|
+
* ]) as ProductRepoWithPlugins;
|
|
512
638
|
*
|
|
513
|
-
* // TypeScript autocomplete
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
639
|
+
* // Now TypeScript provides autocomplete and type checking!
|
|
640
|
+
* await repo.increment(productId, 'views', 1);
|
|
641
|
+
* await repo.upsert({ sku: 'ABC' }, { name: 'Product', price: 99 });
|
|
642
|
+
* await repo.pushToArray(productId, 'tags', 'featured');
|
|
517
643
|
* ```
|
|
518
644
|
*/
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* Group documents by field value and count occurrences
|
|
522
|
-
* @param field - Field to group by
|
|
523
|
-
* @param options - Operation options
|
|
524
|
-
* @returns Array of groups with _id and count
|
|
525
|
-
*/
|
|
526
|
-
groupBy(field: string, options?: {
|
|
527
|
-
limit?: number;
|
|
528
|
-
session?: unknown;
|
|
529
|
-
}): Promise<Array<{
|
|
530
|
-
_id: unknown;
|
|
531
|
-
count: number;
|
|
532
|
-
}>>;
|
|
533
|
-
/**
|
|
534
|
-
* Calculate sum of field values
|
|
535
|
-
* @param field - Field to sum
|
|
536
|
-
* @param query - Filter query
|
|
537
|
-
* @param options - Operation options
|
|
538
|
-
* @returns Sum of field values
|
|
539
|
-
*/
|
|
540
|
-
sum(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
541
|
-
/**
|
|
542
|
-
* Calculate average of field values
|
|
543
|
-
* @param field - Field to average
|
|
544
|
-
* @param query - Filter query
|
|
545
|
-
* @param options - Operation options
|
|
546
|
-
* @returns Average of field values
|
|
547
|
-
*/
|
|
548
|
-
average(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
549
|
-
/**
|
|
550
|
-
* Get minimum field value
|
|
551
|
-
* @param field - Field to get minimum from
|
|
552
|
-
* @param query - Filter query
|
|
553
|
-
* @param options - Operation options
|
|
554
|
-
* @returns Minimum field value
|
|
555
|
-
*/
|
|
556
|
-
min(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
557
|
-
/**
|
|
558
|
-
* Get maximum field value
|
|
559
|
-
* @param field - Field to get maximum from
|
|
560
|
-
* @param query - Filter query
|
|
561
|
-
* @param options - Operation options
|
|
562
|
-
* @returns Maximum field value
|
|
563
|
-
*/
|
|
564
|
-
max(field: string, query?: Record<string, unknown>, options?: Record<string, unknown>): Promise<number>;
|
|
565
|
-
}
|
|
566
|
-
//#endregion
|
|
567
|
-
//#region src/plugins/subdocument.plugin.d.ts
|
|
645
|
+
declare function mongoOperationsPlugin(): Plugin;
|
|
568
646
|
/**
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
* @example
|
|
572
|
-
* const repo = new Repository(Model, [
|
|
573
|
-
* methodRegistryPlugin(),
|
|
574
|
-
* subdocumentPlugin(),
|
|
575
|
-
* ]);
|
|
647
|
+
* Type interface for repositories using mongoOperationsPlugin
|
|
576
648
|
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
*/
|
|
580
|
-
declare function subdocumentPlugin(): Plugin;
|
|
581
|
-
/**
|
|
582
|
-
* Type interface for repositories using subdocumentPlugin
|
|
649
|
+
* Use this interface to get TypeScript autocomplete and type safety
|
|
650
|
+
* for the methods added by mongoOperationsPlugin.
|
|
583
651
|
*
|
|
584
652
|
* @example
|
|
585
653
|
* ```typescript
|
|
586
|
-
* import { Repository,
|
|
587
|
-
* import type {
|
|
654
|
+
* import { Repository, mongoOperationsPlugin, methodRegistryPlugin } from '@classytic/mongokit';
|
|
655
|
+
* import type { MongoOperationsMethods } from '@classytic/mongokit';
|
|
588
656
|
*
|
|
589
|
-
*
|
|
657
|
+
* // Without type safety (base is flexible)
|
|
658
|
+
* class ProductRepo extends Repository<IProduct> {
|
|
659
|
+
* // Can add anything - fully flexible
|
|
660
|
+
* }
|
|
590
661
|
*
|
|
591
|
-
* type
|
|
662
|
+
* // With type safety for plugin methods
|
|
663
|
+
* class ProductRepo extends Repository<IProduct> implements MongoOperationsMethods<IProduct> {
|
|
664
|
+
* // TypeScript knows about upsert, increment, decrement, etc.
|
|
665
|
+
* }
|
|
592
666
|
*
|
|
593
|
-
* const repo = new
|
|
667
|
+
* const repo = new ProductRepo(ProductModel, [
|
|
594
668
|
* methodRegistryPlugin(),
|
|
595
|
-
*
|
|
596
|
-
* ])
|
|
669
|
+
* mongoOperationsPlugin(),
|
|
670
|
+
* ]);
|
|
597
671
|
*
|
|
598
|
-
* // TypeScript autocomplete
|
|
599
|
-
* await repo.
|
|
600
|
-
* await repo.
|
|
601
|
-
* await repo.deleteSubdocument(orderId, 'items', itemId);
|
|
672
|
+
* // Now TypeScript provides autocomplete and type checking
|
|
673
|
+
* await repo.increment(productId, 'views', 1);
|
|
674
|
+
* await repo.upsert({ sku: 'ABC' }, { name: 'Product' });
|
|
602
675
|
* ```
|
|
603
676
|
*/
|
|
604
|
-
interface
|
|
677
|
+
interface MongoOperationsMethods<TDoc> {
|
|
605
678
|
/**
|
|
606
|
-
*
|
|
607
|
-
* @param
|
|
608
|
-
* @param
|
|
609
|
-
* @param
|
|
610
|
-
* @
|
|
611
|
-
* @returns Updated parent document
|
|
679
|
+
* Update existing document or insert new one
|
|
680
|
+
* @param query - Query to find document
|
|
681
|
+
* @param data - Data to update or insert
|
|
682
|
+
* @param options - Operation options (session, etc.)
|
|
683
|
+
* @returns Created or updated document
|
|
612
684
|
*/
|
|
613
|
-
|
|
685
|
+
upsert(query: Record<string, unknown>, data: Record<string, unknown>, options?: Record<string, unknown>): Promise<TDoc>;
|
|
614
686
|
/**
|
|
615
|
-
*
|
|
616
|
-
* @param
|
|
617
|
-
* @param
|
|
618
|
-
* @param
|
|
619
|
-
* @param options - Operation options
|
|
620
|
-
* @returns
|
|
687
|
+
* Atomically increment numeric field
|
|
688
|
+
* @param id - Document ID
|
|
689
|
+
* @param field - Field name to increment
|
|
690
|
+
* @param value - Value to increment by (default: 1)
|
|
691
|
+
* @param options - Operation options (session, etc.)
|
|
692
|
+
* @returns Updated document
|
|
621
693
|
*/
|
|
622
|
-
|
|
623
|
-
lean?: boolean;
|
|
624
|
-
session?: unknown;
|
|
625
|
-
}): Promise<Record<string, unknown>>;
|
|
694
|
+
increment(id: string | ObjectId, field: string, value?: number, options?: Record<string, unknown>): Promise<TDoc>;
|
|
626
695
|
/**
|
|
627
|
-
*
|
|
628
|
-
* @param
|
|
629
|
-
* @param
|
|
630
|
-
* @param
|
|
631
|
-
* @param
|
|
632
|
-
* @
|
|
633
|
-
* @returns Updated parent document
|
|
696
|
+
* Atomically decrement numeric field
|
|
697
|
+
* @param id - Document ID
|
|
698
|
+
* @param field - Field name to decrement
|
|
699
|
+
* @param value - Value to decrement by (default: 1)
|
|
700
|
+
* @param options - Operation options (session, etc.)
|
|
701
|
+
* @returns Updated document
|
|
634
702
|
*/
|
|
635
|
-
|
|
636
|
-
session?: unknown;
|
|
637
|
-
}): Promise<TDoc>;
|
|
703
|
+
decrement(id: string | ObjectId, field: string, value?: number, options?: Record<string, unknown>): Promise<TDoc>;
|
|
638
704
|
/**
|
|
639
|
-
*
|
|
640
|
-
* @param
|
|
641
|
-
* @param
|
|
642
|
-
* @param
|
|
643
|
-
* @param options - Operation options
|
|
644
|
-
* @returns Updated
|
|
705
|
+
* Push value to array field
|
|
706
|
+
* @param id - Document ID
|
|
707
|
+
* @param field - Array field name
|
|
708
|
+
* @param value - Value to push
|
|
709
|
+
* @param options - Operation options (session, etc.)
|
|
710
|
+
* @returns Updated document
|
|
645
711
|
*/
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
* await productRepo.invalidateAllCache();
|
|
675
|
-
* const stats = productRepo.getCacheStats();
|
|
676
|
-
* productRepo.resetCacheStats();
|
|
677
|
-
* ```
|
|
678
|
-
*/
|
|
679
|
-
interface CacheMethods {
|
|
712
|
+
pushToArray(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
713
|
+
/**
|
|
714
|
+
* Remove value from array field
|
|
715
|
+
* @param id - Document ID
|
|
716
|
+
* @param field - Array field name
|
|
717
|
+
* @param value - Value to remove
|
|
718
|
+
* @param options - Operation options (session, etc.)
|
|
719
|
+
* @returns Updated document
|
|
720
|
+
*/
|
|
721
|
+
pullFromArray(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
722
|
+
/**
|
|
723
|
+
* Add value to array only if not already present (unique)
|
|
724
|
+
* @param id - Document ID
|
|
725
|
+
* @param field - Array field name
|
|
726
|
+
* @param value - Value to add
|
|
727
|
+
* @param options - Operation options (session, etc.)
|
|
728
|
+
* @returns Updated document
|
|
729
|
+
*/
|
|
730
|
+
addToSet(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
731
|
+
/**
|
|
732
|
+
* Set field value (alias for update with $set)
|
|
733
|
+
* @param id - Document ID
|
|
734
|
+
* @param field - Field name
|
|
735
|
+
* @param value - Value to set
|
|
736
|
+
* @param options - Operation options (session, etc.)
|
|
737
|
+
* @returns Updated document
|
|
738
|
+
*/
|
|
739
|
+
setField(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
680
740
|
/**
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
* @param
|
|
741
|
+
* Unset (remove) field from document
|
|
742
|
+
* @param id - Document ID
|
|
743
|
+
* @param fields - Field name or array of field names to remove
|
|
744
|
+
* @param options - Operation options (session, etc.)
|
|
745
|
+
* @returns Updated document
|
|
684
746
|
*/
|
|
685
|
-
|
|
747
|
+
unsetField(id: string | ObjectId, fields: string | string[], options?: Record<string, unknown>): Promise<TDoc>;
|
|
686
748
|
/**
|
|
687
|
-
*
|
|
688
|
-
*
|
|
749
|
+
* Rename field in document
|
|
750
|
+
* @param id - Document ID
|
|
751
|
+
* @param oldName - Current field name
|
|
752
|
+
* @param newName - New field name
|
|
753
|
+
* @param options - Operation options (session, etc.)
|
|
754
|
+
* @returns Updated document
|
|
689
755
|
*/
|
|
690
|
-
|
|
756
|
+
renameField(id: string | ObjectId, oldName: string, newName: string, options?: Record<string, unknown>): Promise<TDoc>;
|
|
691
757
|
/**
|
|
692
|
-
*
|
|
693
|
-
*
|
|
758
|
+
* Multiply numeric field by value
|
|
759
|
+
* @param id - Document ID
|
|
760
|
+
* @param field - Field name
|
|
761
|
+
* @param multiplier - Multiplier value
|
|
762
|
+
* @param options - Operation options (session, etc.)
|
|
763
|
+
* @returns Updated document
|
|
694
764
|
*/
|
|
695
|
-
|
|
765
|
+
multiplyField(id: string | ObjectId, field: string, multiplier: number, options?: Record<string, unknown>): Promise<TDoc>;
|
|
696
766
|
/**
|
|
697
|
-
*
|
|
698
|
-
* @
|
|
767
|
+
* Set field to minimum value (only if current value is greater)
|
|
768
|
+
* @param id - Document ID
|
|
769
|
+
* @param field - Field name
|
|
770
|
+
* @param value - Minimum value
|
|
771
|
+
* @param options - Operation options (session, etc.)
|
|
772
|
+
* @returns Updated document
|
|
699
773
|
*/
|
|
700
|
-
|
|
774
|
+
setMin(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
701
775
|
/**
|
|
702
|
-
*
|
|
776
|
+
* Set field to maximum value (only if current value is less)
|
|
777
|
+
* @param id - Document ID
|
|
778
|
+
* @param field - Field name
|
|
779
|
+
* @param value - Maximum value
|
|
780
|
+
* @param options - Operation options (session, etc.)
|
|
781
|
+
* @returns Updated document
|
|
703
782
|
*/
|
|
704
|
-
|
|
783
|
+
setMax(id: string | ObjectId, field: string, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
784
|
+
/**
|
|
785
|
+
* Atomic update with multiple MongoDB operators in a single call.
|
|
786
|
+
* Combines $inc, $set, $push, $pull, $addToSet, $unset, $setOnInsert, etc.
|
|
787
|
+
*
|
|
788
|
+
* @param id - Document ID
|
|
789
|
+
* @param operators - MongoDB update operators (e.g. { $inc: { views: 1 }, $set: { lastViewed: new Date() } })
|
|
790
|
+
* @param options - Operation options (session, arrayFilters, etc.)
|
|
791
|
+
* @returns Updated document
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* await repo.atomicUpdate(postId, {
|
|
795
|
+
* $inc: { reactionCount: -1 },
|
|
796
|
+
* $set: { lastActiveAt: new Date() },
|
|
797
|
+
* $push: { history: { action: 'unreact', at: new Date() } }
|
|
798
|
+
* });
|
|
799
|
+
*/
|
|
800
|
+
atomicUpdate(id: string | ObjectId, operators: Record<string, Record<string, unknown>>, options?: Record<string, unknown>): Promise<TDoc>;
|
|
705
801
|
}
|
|
706
802
|
//#endregion
|
|
707
|
-
//#region src/plugins/cascade.plugin.d.ts
|
|
708
|
-
/**
|
|
709
|
-
* Cascade delete plugin
|
|
710
|
-
*
|
|
711
|
-
* Deletes related documents after the parent document is deleted.
|
|
712
|
-
* Works with both hard delete and soft delete scenarios.
|
|
713
|
-
*
|
|
714
|
-
* @param options - Cascade configuration
|
|
715
|
-
* @returns Plugin
|
|
716
|
-
*/
|
|
717
|
-
declare function cascadePlugin(options: CascadeOptions): Plugin;
|
|
718
|
-
//#endregion
|
|
719
803
|
//#region src/plugins/multi-tenant.plugin.d.ts
|
|
720
804
|
interface MultiTenantOptions {
|
|
721
805
|
/** Field name used for tenant isolation (default: 'organizationId') */
|
|
@@ -780,308 +864,224 @@ interface ObservabilityOptions {
|
|
|
780
864
|
}
|
|
781
865
|
declare function observabilityPlugin(options: ObservabilityOptions): Plugin;
|
|
782
866
|
//#endregion
|
|
783
|
-
//#region src/plugins/
|
|
784
|
-
interface AuditTrailOptions {
|
|
785
|
-
/** Operations to track (default: ['create', 'update', 'delete']) */
|
|
786
|
-
operations?: AuditOperation[];
|
|
787
|
-
/** Store field-level before/after diff on updates (default: true) */
|
|
788
|
-
trackChanges?: boolean;
|
|
789
|
-
/** Store full document snapshot on create (default: false — can be heavy) */
|
|
790
|
-
trackDocument?: boolean;
|
|
791
|
-
/** Auto-purge after N days via MongoDB TTL index (default: undefined — keep forever) */
|
|
792
|
-
ttlDays?: number;
|
|
793
|
-
/** MongoDB collection name (default: 'audit_trails') */
|
|
794
|
-
collectionName?: string;
|
|
795
|
-
/**
|
|
796
|
-
* Extract custom metadata from the repository context.
|
|
797
|
-
* Returned object is stored on the audit entry as `metadata`.
|
|
798
|
-
*/
|
|
799
|
-
metadata?: (context: RepositoryContext) => Record<string, unknown>;
|
|
800
|
-
/**
|
|
801
|
-
* Fields to exclude from change tracking (e.g., passwords, tokens).
|
|
802
|
-
* These fields are redacted in the `changes` diff.
|
|
803
|
-
*/
|
|
804
|
-
excludeFields?: string[];
|
|
805
|
-
}
|
|
806
|
-
type AuditOperation = 'create' | 'update' | 'delete';
|
|
807
|
-
interface AuditEntry {
|
|
808
|
-
model: string;
|
|
809
|
-
operation: AuditOperation;
|
|
810
|
-
documentId: unknown;
|
|
811
|
-
userId?: unknown;
|
|
812
|
-
orgId?: unknown;
|
|
813
|
-
changes?: Record<string, {
|
|
814
|
-
from: unknown;
|
|
815
|
-
to: unknown;
|
|
816
|
-
}>;
|
|
817
|
-
document?: Record<string, unknown>;
|
|
818
|
-
metadata?: Record<string, unknown>;
|
|
819
|
-
timestamp: Date;
|
|
820
|
-
}
|
|
821
|
-
declare function auditTrailPlugin(options?: AuditTrailOptions): Plugin;
|
|
822
|
-
interface AuditQueryOptions {
|
|
823
|
-
model?: string;
|
|
824
|
-
documentId?: string | ObjectId;
|
|
825
|
-
userId?: string | ObjectId;
|
|
826
|
-
orgId?: string | ObjectId;
|
|
827
|
-
operation?: AuditOperation;
|
|
828
|
-
from?: Date;
|
|
829
|
-
to?: Date;
|
|
830
|
-
page?: number;
|
|
831
|
-
limit?: number;
|
|
832
|
-
}
|
|
833
|
-
interface AuditQueryResult {
|
|
834
|
-
docs: AuditEntry[];
|
|
835
|
-
page: number;
|
|
836
|
-
limit: number;
|
|
837
|
-
total: number;
|
|
838
|
-
pages: number;
|
|
839
|
-
hasNext: boolean;
|
|
840
|
-
hasPrev: boolean;
|
|
841
|
-
}
|
|
867
|
+
//#region src/plugins/soft-delete.plugin.d.ts
|
|
842
868
|
/**
|
|
843
|
-
*
|
|
844
|
-
* Use this to query audits across all models — e.g., admin dashboards, audit APIs.
|
|
869
|
+
* Soft delete plugin
|
|
845
870
|
*
|
|
846
|
-
* @example
|
|
871
|
+
* @example Basic usage
|
|
847
872
|
* ```typescript
|
|
848
|
-
*
|
|
873
|
+
* const repo = new Repository(Model, [
|
|
874
|
+
* softDeletePlugin({ deletedField: 'deletedAt' })
|
|
875
|
+
* ]);
|
|
849
876
|
*
|
|
850
|
-
*
|
|
877
|
+
* // Delete (soft)
|
|
878
|
+
* await repo.delete(id);
|
|
851
879
|
*
|
|
852
|
-
* //
|
|
853
|
-
*
|
|
880
|
+
* // Restore
|
|
881
|
+
* await repo.restore(id);
|
|
854
882
|
*
|
|
855
|
-
* //
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
* operation: 'update',
|
|
859
|
-
* });
|
|
883
|
+
* // Get deleted documents
|
|
884
|
+
* await repo.getDeleted({ page: 1, limit: 20 });
|
|
885
|
+
* ```
|
|
860
886
|
*
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
887
|
+
* @example With null filter mode (for schemas with default: null)
|
|
888
|
+
* ```typescript
|
|
889
|
+
* // Schema: { deletedAt: { type: Date, default: null } }
|
|
890
|
+
* const repo = new Repository(Model, [
|
|
891
|
+
* softDeletePlugin({
|
|
892
|
+
* deletedField: 'deletedAt',
|
|
893
|
+
* filterMode: 'null', // default - works with default: null
|
|
894
|
+
* })
|
|
895
|
+
* ]);
|
|
896
|
+
* ```
|
|
866
897
|
*
|
|
867
|
-
*
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
*
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*
|
|
898
|
+
* @example With TTL for auto-cleanup
|
|
899
|
+
* ```typescript
|
|
900
|
+
* const repo = new Repository(Model, [
|
|
901
|
+
* softDeletePlugin({
|
|
902
|
+
* deletedField: 'deletedAt',
|
|
903
|
+
* ttlDays: 30, // Auto-delete after 30 days
|
|
904
|
+
* })
|
|
905
|
+
* ]);
|
|
906
|
+
* ```
|
|
907
|
+
*/
|
|
908
|
+
declare function softDeletePlugin(options?: SoftDeleteOptions): Plugin;
|
|
909
|
+
/**
|
|
910
|
+
* TypeScript interface for soft delete plugin methods
|
|
874
911
|
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
*
|
|
912
|
+
* @example
|
|
913
|
+
* ```typescript
|
|
914
|
+
* import type { SoftDeleteMethods } from '@classytic/mongokit';
|
|
915
|
+
*
|
|
916
|
+
* type UserRepoWithSoftDelete = UserRepo & SoftDeleteMethods<IUser>;
|
|
917
|
+
*
|
|
918
|
+
* const userRepo = new UserRepo(UserModel, [
|
|
919
|
+
* methodRegistryPlugin(),
|
|
920
|
+
* softDeletePlugin({ deletedField: 'deletedAt' }),
|
|
921
|
+
* ]) as UserRepoWithSoftDelete;
|
|
922
|
+
*
|
|
923
|
+
* // TypeScript autocomplete for soft delete methods
|
|
924
|
+
* await userRepo.restore(userId);
|
|
925
|
+
* const deleted = await userRepo.getDeleted({ page: 1, limit: 20 });
|
|
878
926
|
* ```
|
|
879
927
|
*/
|
|
880
|
-
|
|
881
|
-
private model;
|
|
882
|
-
constructor(collectionName?: string, ttlDays?: number);
|
|
883
|
-
/**
|
|
884
|
-
* Get the underlying Mongoose model for custom queries
|
|
885
|
-
*/
|
|
886
|
-
getModel(): mongoose.Model<AuditEntry>;
|
|
887
|
-
/**
|
|
888
|
-
* Query audit entries with filters and pagination
|
|
889
|
-
*/
|
|
890
|
-
query(options?: AuditQueryOptions): Promise<AuditQueryResult>;
|
|
891
|
-
/**
|
|
892
|
-
* Get audit trail for a specific document
|
|
893
|
-
*/
|
|
894
|
-
getDocumentTrail(model: string, documentId: string | ObjectId, options?: {
|
|
895
|
-
page?: number;
|
|
896
|
-
limit?: number;
|
|
897
|
-
operation?: AuditOperation;
|
|
898
|
-
}): Promise<AuditQueryResult>;
|
|
899
|
-
/**
|
|
900
|
-
* Get all audits for a user
|
|
901
|
-
*/
|
|
902
|
-
getUserTrail(userId: string | ObjectId, options?: {
|
|
903
|
-
page?: number;
|
|
904
|
-
limit?: number;
|
|
905
|
-
operation?: AuditOperation;
|
|
906
|
-
orgId?: string | ObjectId;
|
|
907
|
-
}): Promise<AuditQueryResult>;
|
|
928
|
+
interface SoftDeleteMethods<TDoc> {
|
|
908
929
|
/**
|
|
909
|
-
*
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
}): Promise<
|
|
917
|
-
}
|
|
918
|
-
interface AuditTrailMethods {
|
|
930
|
+
* Restore a soft-deleted document
|
|
931
|
+
* @param id - Document ID to restore
|
|
932
|
+
* @param options - Optional restore options
|
|
933
|
+
* @returns Restored document
|
|
934
|
+
*/
|
|
935
|
+
restore(id: string | ObjectId, options?: {
|
|
936
|
+
session?: ClientSession;
|
|
937
|
+
}): Promise<TDoc>;
|
|
919
938
|
/**
|
|
920
|
-
* Get paginated
|
|
939
|
+
* Get paginated list of soft-deleted documents
|
|
940
|
+
* @param params - Query parameters (filters, sort, pagination)
|
|
941
|
+
* @param options - Query options (select, populate, lean, session)
|
|
942
|
+
* @returns Paginated result of deleted documents
|
|
921
943
|
*/
|
|
922
|
-
|
|
944
|
+
getDeleted(params?: {
|
|
945
|
+
filters?: Record<string, unknown>;
|
|
946
|
+
sort?: SortSpec | string;
|
|
923
947
|
page?: number;
|
|
924
948
|
limit?: number;
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
/** Elasticsearch or OpenSearch client instance */
|
|
932
|
-
client: any;
|
|
933
|
-
/** Index name to perform search against */
|
|
934
|
-
index: string;
|
|
935
|
-
/** Field to extract MongoDB ID from the indexed document (default: '_id') */
|
|
936
|
-
idField?: string;
|
|
949
|
+
}, options?: {
|
|
950
|
+
select?: SelectSpec;
|
|
951
|
+
populate?: PopulateSpec;
|
|
952
|
+
lean?: boolean;
|
|
953
|
+
session?: ClientSession;
|
|
954
|
+
}): Promise<OffsetPaginationResult<TDoc>>;
|
|
937
955
|
}
|
|
938
|
-
declare function elasticSearchPlugin(options: ElasticSearchOptions): Plugin;
|
|
939
956
|
//#endregion
|
|
940
|
-
//#region src/plugins/
|
|
941
|
-
/**
|
|
942
|
-
* Generator function that produces a unique ID.
|
|
943
|
-
* Receives the full repository context for conditional logic.
|
|
944
|
-
*/
|
|
945
|
-
type IdGenerator = (context: RepositoryContext) => string | Promise<string>;
|
|
946
|
-
interface CustomIdOptions {
|
|
947
|
-
/** Field to store the custom ID (default: 'customId') */
|
|
948
|
-
field?: string;
|
|
949
|
-
/** Function to generate the ID. Can be async. */
|
|
950
|
-
generator: IdGenerator;
|
|
951
|
-
/** Only generate if the field is missing/empty (default: true) */
|
|
952
|
-
generateOnlyIfEmpty?: boolean;
|
|
953
|
-
}
|
|
957
|
+
//#region src/plugins/subdocument.plugin.d.ts
|
|
954
958
|
/**
|
|
955
|
-
*
|
|
956
|
-
* Uses `findOneAndUpdate` with `upsert` + `$inc` — fully atomic even under
|
|
957
|
-
* heavy concurrency.
|
|
958
|
-
*
|
|
959
|
-
* @param counterKey - Unique key identifying this counter (e.g., "Invoice" or "Invoice:2026-02")
|
|
960
|
-
* @param increment - Value to increment by (default: 1)
|
|
961
|
-
* @returns The next sequence number (after increment)
|
|
959
|
+
* Subdocument plugin for managing nested arrays
|
|
962
960
|
*
|
|
963
961
|
* @example
|
|
964
|
-
* const
|
|
965
|
-
*
|
|
962
|
+
* const repo = new Repository(Model, [
|
|
963
|
+
* methodRegistryPlugin(),
|
|
964
|
+
* subdocumentPlugin(),
|
|
965
|
+
* ]);
|
|
966
966
|
*
|
|
967
|
-
*
|
|
968
|
-
*
|
|
969
|
-
* // If current was 10, returns 15 (you use 11, 12, 13, 14, 15)
|
|
967
|
+
* await repo.addSubdocument(parentId, 'items', { name: 'Item 1' });
|
|
968
|
+
* await repo.updateSubdocument(parentId, 'items', itemId, { name: 'Updated Item' });
|
|
970
969
|
*/
|
|
971
|
-
declare function
|
|
972
|
-
interface SequentialIdOptions {
|
|
973
|
-
/** Prefix string (e.g., 'INV', 'ORD') */
|
|
974
|
-
prefix: string;
|
|
975
|
-
/** Mongoose model — used to derive the counter key from model name */
|
|
976
|
-
model: mongoose.Model<any>;
|
|
977
|
-
/** Number of digits to pad to (default: 4 → "0001") */
|
|
978
|
-
padding?: number;
|
|
979
|
-
/** Separator between prefix and number (default: '-') */
|
|
980
|
-
separator?: string;
|
|
981
|
-
/** Custom counter key override (default: model.modelName) */
|
|
982
|
-
counterKey?: string;
|
|
983
|
-
}
|
|
970
|
+
declare function subdocumentPlugin(): Plugin;
|
|
984
971
|
/**
|
|
985
|
-
*
|
|
986
|
-
* Produces IDs like `INV-0001`, `INV-0002`, etc.
|
|
987
|
-
*
|
|
988
|
-
* Uses atomic MongoDB counters — safe under concurrency.
|
|
972
|
+
* Type interface for repositories using subdocumentPlugin
|
|
989
973
|
*
|
|
990
974
|
* @example
|
|
991
975
|
* ```typescript
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
-
*
|
|
995
|
-
* }
|
|
976
|
+
* import { Repository, methodRegistryPlugin, subdocumentPlugin } from '@classytic/mongokit';
|
|
977
|
+
* import type { SubdocumentMethods } from '@classytic/mongokit';
|
|
978
|
+
*
|
|
979
|
+
* class OrderRepo extends Repository<IOrder> {}
|
|
980
|
+
*
|
|
981
|
+
* type OrderRepoWithSubdocs = OrderRepo & SubdocumentMethods<IOrder>;
|
|
982
|
+
*
|
|
983
|
+
* const repo = new OrderRepo(OrderModel, [
|
|
984
|
+
* methodRegistryPlugin(),
|
|
985
|
+
* subdocumentPlugin(),
|
|
986
|
+
* ]) as OrderRepoWithSubdocs;
|
|
987
|
+
*
|
|
988
|
+
* // TypeScript autocomplete works!
|
|
989
|
+
* await repo.addSubdocument(orderId, 'items', { productId: '123', quantity: 2 });
|
|
990
|
+
* await repo.updateSubdocument(orderId, 'items', itemId, { quantity: 5 });
|
|
991
|
+
* await repo.deleteSubdocument(orderId, 'items', itemId);
|
|
996
992
|
* ```
|
|
997
993
|
*/
|
|
998
|
-
|
|
999
|
-
interface DateSequentialIdOptions {
|
|
1000
|
-
/** Prefix string (e.g., 'BILL', 'INV') */
|
|
1001
|
-
prefix: string;
|
|
1002
|
-
/** Mongoose model — used to derive the counter key */
|
|
1003
|
-
model: mongoose.Model<any>;
|
|
994
|
+
interface SubdocumentMethods<TDoc> {
|
|
1004
995
|
/**
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
* -
|
|
1008
|
-
*
|
|
996
|
+
* Add subdocument to array field
|
|
997
|
+
* @param parentId - Parent document ID
|
|
998
|
+
* @param arrayPath - Path to array field (e.g., 'items', 'addresses')
|
|
999
|
+
* @param subData - Subdocument data
|
|
1000
|
+
* @param options - Operation options
|
|
1001
|
+
* @returns Updated parent document
|
|
1009
1002
|
*/
|
|
1010
|
-
|
|
1011
|
-
/**
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1003
|
+
addSubdocument(parentId: string | ObjectId, arrayPath: string, subData: Record<string, unknown>, options?: Record<string, unknown>): Promise<TDoc>;
|
|
1004
|
+
/**
|
|
1005
|
+
* Get subdocument from array field
|
|
1006
|
+
* @param parentId - Parent document ID
|
|
1007
|
+
* @param arrayPath - Path to array field
|
|
1008
|
+
* @param subId - Subdocument ID
|
|
1009
|
+
* @param options - Operation options
|
|
1010
|
+
* @returns Subdocument
|
|
1011
|
+
*/
|
|
1012
|
+
getSubdocument(parentId: string | ObjectId, arrayPath: string, subId: string | ObjectId, options?: {
|
|
1013
|
+
lean?: boolean;
|
|
1014
|
+
session?: unknown;
|
|
1015
|
+
}): Promise<Record<string, unknown>>;
|
|
1016
|
+
/**
|
|
1017
|
+
* Update subdocument in array field
|
|
1018
|
+
* @param parentId - Parent document ID
|
|
1019
|
+
* @param arrayPath - Path to array field
|
|
1020
|
+
* @param subId - Subdocument ID
|
|
1021
|
+
* @param updateData - Update data
|
|
1022
|
+
* @param options - Operation options
|
|
1023
|
+
* @returns Updated parent document
|
|
1024
|
+
*/
|
|
1025
|
+
updateSubdocument(parentId: string | ObjectId, arrayPath: string, subId: string | ObjectId, updateData: Record<string, unknown>, options?: {
|
|
1026
|
+
session?: unknown;
|
|
1027
|
+
}): Promise<TDoc>;
|
|
1028
|
+
/**
|
|
1029
|
+
* Delete subdocument from array field
|
|
1030
|
+
* @param parentId - Parent document ID
|
|
1031
|
+
* @param arrayPath - Path to array field
|
|
1032
|
+
* @param subId - Subdocument ID
|
|
1033
|
+
* @param options - Operation options
|
|
1034
|
+
* @returns Updated parent document
|
|
1035
|
+
*/
|
|
1036
|
+
deleteSubdocument(parentId: string | ObjectId, arrayPath: string, subId: string | ObjectId, options?: Record<string, unknown>): Promise<TDoc>;
|
|
1015
1037
|
}
|
|
1038
|
+
//#endregion
|
|
1039
|
+
//#region src/plugins/timestamp.plugin.d.ts
|
|
1016
1040
|
/**
|
|
1017
|
-
*
|
|
1018
|
-
* Counter resets per period — great for invoice/bill numbering.
|
|
1019
|
-
*
|
|
1020
|
-
* Produces IDs like:
|
|
1021
|
-
* - yearly: `BILL-2026-0001`
|
|
1022
|
-
* - monthly: `BILL-2026-02-0001`
|
|
1023
|
-
* - daily: `BILL-2026-02-20-0001`
|
|
1041
|
+
* Timestamp plugin that auto-injects timestamps
|
|
1024
1042
|
*
|
|
1025
1043
|
* @example
|
|
1026
|
-
*
|
|
1027
|
-
* customIdPlugin({
|
|
1028
|
-
* field: 'billNumber',
|
|
1029
|
-
* generator: dateSequentialId({
|
|
1030
|
-
* prefix: 'BILL',
|
|
1031
|
-
* model: BillModel,
|
|
1032
|
-
* partition: 'monthly',
|
|
1033
|
-
* }),
|
|
1034
|
-
* })
|
|
1035
|
-
* ```
|
|
1044
|
+
* const repo = new Repository(Model, [timestampPlugin()]);
|
|
1036
1045
|
*/
|
|
1037
|
-
declare function
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
/** Separator (default: '_') */
|
|
1042
|
-
separator?: string;
|
|
1043
|
-
/** Length of the random suffix (default: 12) */
|
|
1044
|
-
length?: number;
|
|
1045
|
-
}
|
|
1046
|
+
declare function timestampPlugin(): Plugin;
|
|
1047
|
+
//#endregion
|
|
1048
|
+
//#region src/plugins/validation-chain.plugin.d.ts
|
|
1049
|
+
type OperationType = 'create' | 'createMany' | 'update' | 'delete';
|
|
1046
1050
|
/**
|
|
1047
|
-
*
|
|
1048
|
-
* Does NOT require a database round-trip — purely in-memory.
|
|
1049
|
-
*
|
|
1050
|
-
* Produces IDs like: `USR_a7b3xk9m2p1q`
|
|
1051
|
-
*
|
|
1052
|
-
* Good for: user-facing IDs where ordering doesn't matter.
|
|
1053
|
-
* Not suitable for sequential numbering.
|
|
1051
|
+
* Validation chain plugin
|
|
1054
1052
|
*
|
|
1055
1053
|
* @example
|
|
1056
|
-
*
|
|
1057
|
-
*
|
|
1058
|
-
*
|
|
1059
|
-
*
|
|
1060
|
-
*
|
|
1061
|
-
*
|
|
1054
|
+
* const repo = new Repository(Model, [
|
|
1055
|
+
* validationChainPlugin([
|
|
1056
|
+
* requireField('email'),
|
|
1057
|
+
* uniqueField('email', 'Email already exists'),
|
|
1058
|
+
* blockIf('no-delete-admin', ['delete'], ctx => ctx.data?.role === 'admin', 'Cannot delete admin'),
|
|
1059
|
+
* ])
|
|
1060
|
+
* ]);
|
|
1062
1061
|
*/
|
|
1063
|
-
declare function
|
|
1062
|
+
declare function validationChainPlugin(validators?: ValidatorDefinition[], options?: ValidationChainOptions): Plugin;
|
|
1064
1063
|
/**
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
1067
|
-
* @param options - Configuration for ID generation
|
|
1068
|
-
* @returns Plugin instance
|
|
1064
|
+
* Block operation if condition is true
|
|
1069
1065
|
*
|
|
1070
1066
|
* @example
|
|
1071
|
-
*
|
|
1072
|
-
* import { Repository, customIdPlugin, sequentialId } from '@classytic/mongokit';
|
|
1073
|
-
*
|
|
1074
|
-
* const invoiceRepo = new Repository(InvoiceModel, [
|
|
1075
|
-
* customIdPlugin({
|
|
1076
|
-
* field: 'invoiceNumber',
|
|
1077
|
-
* generator: sequentialId({ prefix: 'INV', model: InvoiceModel }),
|
|
1078
|
-
* }),
|
|
1079
|
-
* ]);
|
|
1080
|
-
*
|
|
1081
|
-
* const inv = await invoiceRepo.create({ amount: 100 });
|
|
1082
|
-
* console.log(inv.invoiceNumber); // "INV-0001"
|
|
1083
|
-
* ```
|
|
1067
|
+
* blockIf('block-library', ['delete'], ctx => ctx.data?.managed, 'Cannot delete managed records')
|
|
1084
1068
|
*/
|
|
1085
|
-
declare function
|
|
1069
|
+
declare function blockIf(name: string, operations: OperationType[], condition: (context: RepositoryContext) => boolean, errorMessage: string): ValidatorDefinition;
|
|
1070
|
+
/**
|
|
1071
|
+
* Require a field to be present
|
|
1072
|
+
*/
|
|
1073
|
+
declare function requireField(field: string, operations?: OperationType[]): ValidatorDefinition;
|
|
1074
|
+
/**
|
|
1075
|
+
* Auto-inject a value if not present
|
|
1076
|
+
*/
|
|
1077
|
+
declare function autoInject(field: string, getter: (context: RepositoryContext) => unknown, operations?: OperationType[]): ValidatorDefinition;
|
|
1078
|
+
/**
|
|
1079
|
+
* Make a field immutable (cannot be updated)
|
|
1080
|
+
*/
|
|
1081
|
+
declare function immutableField(field: string): ValidatorDefinition;
|
|
1082
|
+
/**
|
|
1083
|
+
* Ensure field value is unique
|
|
1084
|
+
*/
|
|
1085
|
+
declare function uniqueField(field: string, errorMessage?: string): ValidatorDefinition;
|
|
1086
1086
|
//#endregion
|
|
1087
|
-
export {
|
|
1087
|
+
export { dateSequentialId as A, AuditEntry as B, elasticSearchPlugin as C, PrefixedIdOptions as D, IdGenerator as E, CacheMethods as F, AuditTrailOptions as G, AuditQueryOptions as H, cachePlugin as I, auditLogPlugin as J, AuditTrailQuery as K, BatchOperationsMethods as L, prefixedId as M, sequentialId as N, SequentialIdOptions as O, cascadePlugin as P, BulkWriteResult as R, ElasticSearchOptions as S, DateSequentialIdOptions as T, AuditQueryResult as U, AuditOperation as V, AuditTrailMethods as W, aggregateHelpersPlugin as X, AggregateHelpersMethods as Y, MongoOperationsMethods as _, uniqueField as a, methodRegistryPlugin as b, SubdocumentMethods as c, softDeletePlugin as d, ObservabilityOptions as f, multiTenantPlugin as g, MultiTenantOptions as h, requireField as i, getNextSequence as j, customIdPlugin as k, subdocumentPlugin as l, observabilityPlugin as m, blockIf as n, validationChainPlugin as o, OperationMetric as p, auditTrailPlugin as q, immutableField as r, timestampPlugin as s, autoInject as t, SoftDeleteMethods as u, mongoOperationsPlugin as v, CustomIdOptions as w, fieldFilterPlugin as x, MethodRegistryRepository as y, batchOperationsPlugin as z };
|