@classytic/mongokit 2.0.0 → 2.1.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 +221 -7
- package/dist/actions/index.cjs +479 -0
- package/dist/actions/index.cjs.map +1 -0
- package/dist/actions/index.d.cts +3 -0
- package/dist/actions/index.d.ts +3 -0
- package/dist/actions/index.js +473 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/index-BfVJZF-3.d.cts +337 -0
- package/dist/index-CgOJ2pqz.d.ts +337 -0
- package/dist/index.cjs +2142 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +239 -0
- package/dist/index.d.ts +239 -0
- package/dist/index.js +2108 -0
- package/dist/index.js.map +1 -0
- package/dist/memory-cache-DG2oSSbx.d.ts +142 -0
- package/dist/memory-cache-DqfFfKes.d.cts +142 -0
- package/dist/pagination/PaginationEngine.cjs +375 -0
- package/dist/pagination/PaginationEngine.cjs.map +1 -0
- package/dist/pagination/PaginationEngine.d.cts +117 -0
- package/dist/pagination/PaginationEngine.d.ts +117 -0
- package/dist/pagination/PaginationEngine.js +369 -0
- package/dist/pagination/PaginationEngine.js.map +1 -0
- package/dist/plugins/index.cjs +874 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.cts +275 -0
- package/dist/plugins/index.d.ts +275 -0
- package/dist/plugins/index.js +857 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/types-Nxhmi1aI.d.cts +510 -0
- package/dist/types-Nxhmi1aI.d.ts +510 -0
- package/dist/utils/index.cjs +667 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +189 -0
- package/dist/utils/index.d.ts +189 -0
- package/dist/utils/index.js +643 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +44 -21
- package/src/Repository.js +0 -296
- package/src/actions/aggregate.js +0 -266
- package/src/actions/create.js +0 -59
- package/src/actions/delete.js +0 -88
- package/src/actions/index.js +0 -11
- package/src/actions/read.js +0 -188
- package/src/actions/update.js +0 -176
- package/src/hooks/lifecycle.js +0 -146
- package/src/index.js +0 -71
- package/src/pagination/PaginationEngine.js +0 -348
- package/src/pagination/utils/cursor.js +0 -119
- package/src/pagination/utils/filter.js +0 -42
- package/src/pagination/utils/limits.js +0 -82
- package/src/pagination/utils/sort.js +0 -101
- package/src/plugins/aggregate-helpers.plugin.js +0 -71
- package/src/plugins/audit-log.plugin.js +0 -60
- package/src/plugins/batch-operations.plugin.js +0 -66
- package/src/plugins/field-filter.plugin.js +0 -27
- package/src/plugins/index.js +0 -19
- package/src/plugins/method-registry.plugin.js +0 -140
- package/src/plugins/mongo-operations.plugin.js +0 -317
- package/src/plugins/soft-delete.plugin.js +0 -46
- package/src/plugins/subdocument.plugin.js +0 -66
- package/src/plugins/timestamp.plugin.js +0 -19
- package/src/plugins/validation-chain.plugin.js +0 -145
- package/src/types.d.ts +0 -87
- package/src/utils/error.js +0 -12
- package/src/utils/field-selection.js +0 -156
- package/src/utils/index.js +0 -12
- package/types/Repository.d.ts +0 -95
- package/types/Repository.d.ts.map +0 -1
- package/types/actions/aggregate.d.ts +0 -112
- package/types/actions/aggregate.d.ts.map +0 -1
- package/types/actions/create.d.ts +0 -21
- package/types/actions/create.d.ts.map +0 -1
- package/types/actions/delete.d.ts +0 -37
- package/types/actions/delete.d.ts.map +0 -1
- package/types/actions/index.d.ts +0 -6
- package/types/actions/index.d.ts.map +0 -1
- package/types/actions/read.d.ts +0 -135
- package/types/actions/read.d.ts.map +0 -1
- package/types/actions/update.d.ts +0 -58
- package/types/actions/update.d.ts.map +0 -1
- package/types/hooks/lifecycle.d.ts +0 -44
- package/types/hooks/lifecycle.d.ts.map +0 -1
- package/types/index.d.ts +0 -25
- package/types/index.d.ts.map +0 -1
- package/types/pagination/PaginationEngine.d.ts +0 -386
- package/types/pagination/PaginationEngine.d.ts.map +0 -1
- package/types/pagination/utils/cursor.d.ts +0 -40
- package/types/pagination/utils/cursor.d.ts.map +0 -1
- package/types/pagination/utils/filter.d.ts +0 -28
- package/types/pagination/utils/filter.d.ts.map +0 -1
- package/types/pagination/utils/limits.d.ts +0 -64
- package/types/pagination/utils/limits.d.ts.map +0 -1
- package/types/pagination/utils/sort.d.ts +0 -41
- package/types/pagination/utils/sort.d.ts.map +0 -1
- package/types/plugins/aggregate-helpers.plugin.d.ts +0 -6
- package/types/plugins/aggregate-helpers.plugin.d.ts.map +0 -1
- package/types/plugins/audit-log.plugin.d.ts +0 -6
- package/types/plugins/audit-log.plugin.d.ts.map +0 -1
- package/types/plugins/batch-operations.plugin.d.ts +0 -6
- package/types/plugins/batch-operations.plugin.d.ts.map +0 -1
- package/types/plugins/field-filter.plugin.d.ts +0 -6
- package/types/plugins/field-filter.plugin.d.ts.map +0 -1
- package/types/plugins/index.d.ts +0 -11
- package/types/plugins/index.d.ts.map +0 -1
- package/types/plugins/method-registry.plugin.d.ts +0 -3
- package/types/plugins/method-registry.plugin.d.ts.map +0 -1
- package/types/plugins/mongo-operations.plugin.d.ts +0 -4
- package/types/plugins/mongo-operations.plugin.d.ts.map +0 -1
- package/types/plugins/soft-delete.plugin.d.ts +0 -6
- package/types/plugins/soft-delete.plugin.d.ts.map +0 -1
- package/types/plugins/subdocument.plugin.d.ts +0 -6
- package/types/plugins/subdocument.plugin.d.ts.map +0 -1
- package/types/plugins/timestamp.plugin.d.ts +0 -6
- package/types/plugins/timestamp.plugin.d.ts.map +0 -1
- package/types/plugins/validation-chain.plugin.d.ts +0 -31
- package/types/plugins/validation-chain.plugin.d.ts.map +0 -1
- package/types/utils/error.d.ts +0 -11
- package/types/utils/error.d.ts.map +0 -1
- package/types/utils/field-selection.d.ts +0 -9
- package/types/utils/field-selection.d.ts.map +0 -1
- package/types/utils/index.d.ts +0 -2
- package/types/utils/index.d.ts.map +0 -1
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/actions/create.ts
|
|
10
|
+
var create_exports = {};
|
|
11
|
+
__export(create_exports, {
|
|
12
|
+
create: () => create,
|
|
13
|
+
createDefault: () => createDefault,
|
|
14
|
+
createMany: () => createMany,
|
|
15
|
+
upsert: () => upsert
|
|
16
|
+
});
|
|
17
|
+
async function create(Model, data, options = {}) {
|
|
18
|
+
const document = new Model(data);
|
|
19
|
+
await document.save({ session: options.session });
|
|
20
|
+
return document;
|
|
21
|
+
}
|
|
22
|
+
async function createMany(Model, dataArray, options = {}) {
|
|
23
|
+
return Model.insertMany(dataArray, {
|
|
24
|
+
session: options.session,
|
|
25
|
+
ordered: options.ordered !== false
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function createDefault(Model, overrides = {}, options = {}) {
|
|
29
|
+
const defaults = {};
|
|
30
|
+
Model.schema.eachPath((path, schemaType) => {
|
|
31
|
+
const schemaOptions = schemaType.options;
|
|
32
|
+
if (schemaOptions.default !== void 0 && path !== "_id") {
|
|
33
|
+
defaults[path] = typeof schemaOptions.default === "function" ? schemaOptions.default() : schemaOptions.default;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return create(Model, { ...defaults, ...overrides }, options);
|
|
37
|
+
}
|
|
38
|
+
async function upsert(Model, query, data, options = {}) {
|
|
39
|
+
return Model.findOneAndUpdate(
|
|
40
|
+
query,
|
|
41
|
+
{ $setOnInsert: data },
|
|
42
|
+
{
|
|
43
|
+
upsert: true,
|
|
44
|
+
new: true,
|
|
45
|
+
runValidators: true,
|
|
46
|
+
session: options.session,
|
|
47
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/actions/read.ts
|
|
53
|
+
var read_exports = {};
|
|
54
|
+
__export(read_exports, {
|
|
55
|
+
count: () => count,
|
|
56
|
+
exists: () => exists,
|
|
57
|
+
getAll: () => getAll,
|
|
58
|
+
getById: () => getById,
|
|
59
|
+
getByQuery: () => getByQuery,
|
|
60
|
+
getOrCreate: () => getOrCreate,
|
|
61
|
+
tryGetByQuery: () => tryGetByQuery
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// src/utils/error.ts
|
|
65
|
+
function createError(status, message) {
|
|
66
|
+
const error = new Error(message);
|
|
67
|
+
error.status = status;
|
|
68
|
+
return error;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/actions/read.ts
|
|
72
|
+
function parsePopulate(populate) {
|
|
73
|
+
if (!populate) return [];
|
|
74
|
+
if (typeof populate === "string") {
|
|
75
|
+
return populate.split(",").map((p) => p.trim());
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(populate)) {
|
|
78
|
+
return populate.map((p) => typeof p === "string" ? p.trim() : p);
|
|
79
|
+
}
|
|
80
|
+
return [populate];
|
|
81
|
+
}
|
|
82
|
+
async function getById(Model, id, options = {}) {
|
|
83
|
+
const query = options.query ? Model.findOne({ _id: id, ...options.query }) : Model.findById(id);
|
|
84
|
+
if (options.select) query.select(options.select);
|
|
85
|
+
if (options.populate) query.populate(parsePopulate(options.populate));
|
|
86
|
+
if (options.lean) query.lean();
|
|
87
|
+
if (options.session) query.session(options.session);
|
|
88
|
+
const document = await query.exec();
|
|
89
|
+
if (!document && options.throwOnNotFound !== false) {
|
|
90
|
+
throw createError(404, "Document not found");
|
|
91
|
+
}
|
|
92
|
+
return document;
|
|
93
|
+
}
|
|
94
|
+
async function getByQuery(Model, query, options = {}) {
|
|
95
|
+
const mongoQuery = Model.findOne(query);
|
|
96
|
+
if (options.select) mongoQuery.select(options.select);
|
|
97
|
+
if (options.populate) mongoQuery.populate(parsePopulate(options.populate));
|
|
98
|
+
if (options.lean) mongoQuery.lean();
|
|
99
|
+
if (options.session) mongoQuery.session(options.session);
|
|
100
|
+
const document = await mongoQuery.exec();
|
|
101
|
+
if (!document && options.throwOnNotFound !== false) {
|
|
102
|
+
throw createError(404, "Document not found");
|
|
103
|
+
}
|
|
104
|
+
return document;
|
|
105
|
+
}
|
|
106
|
+
async function tryGetByQuery(Model, query, options = {}) {
|
|
107
|
+
return getByQuery(Model, query, { ...options, throwOnNotFound: false });
|
|
108
|
+
}
|
|
109
|
+
async function getAll(Model, query = {}, options = {}) {
|
|
110
|
+
let mongoQuery = Model.find(query);
|
|
111
|
+
if (options.select) mongoQuery = mongoQuery.select(options.select);
|
|
112
|
+
if (options.populate) mongoQuery = mongoQuery.populate(parsePopulate(options.populate));
|
|
113
|
+
if (options.sort) mongoQuery = mongoQuery.sort(options.sort);
|
|
114
|
+
if (options.limit) mongoQuery = mongoQuery.limit(options.limit);
|
|
115
|
+
if (options.skip) mongoQuery = mongoQuery.skip(options.skip);
|
|
116
|
+
mongoQuery = mongoQuery.lean(options.lean !== false);
|
|
117
|
+
if (options.session) mongoQuery = mongoQuery.session(options.session);
|
|
118
|
+
return mongoQuery.exec();
|
|
119
|
+
}
|
|
120
|
+
async function getOrCreate(Model, query, createData, options = {}) {
|
|
121
|
+
return Model.findOneAndUpdate(
|
|
122
|
+
query,
|
|
123
|
+
{ $setOnInsert: createData },
|
|
124
|
+
{
|
|
125
|
+
upsert: true,
|
|
126
|
+
new: true,
|
|
127
|
+
runValidators: true,
|
|
128
|
+
session: options.session,
|
|
129
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
async function count(Model, query = {}, options = {}) {
|
|
134
|
+
return Model.countDocuments(query).session(options.session ?? null);
|
|
135
|
+
}
|
|
136
|
+
async function exists(Model, query, options = {}) {
|
|
137
|
+
return Model.exists(query).session(options.session ?? null);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/actions/update.ts
|
|
141
|
+
var update_exports = {};
|
|
142
|
+
__export(update_exports, {
|
|
143
|
+
increment: () => increment,
|
|
144
|
+
pullFromArray: () => pullFromArray,
|
|
145
|
+
pushToArray: () => pushToArray,
|
|
146
|
+
update: () => update,
|
|
147
|
+
updateByQuery: () => updateByQuery,
|
|
148
|
+
updateMany: () => updateMany,
|
|
149
|
+
updateWithConstraints: () => updateWithConstraints,
|
|
150
|
+
updateWithValidation: () => updateWithValidation
|
|
151
|
+
});
|
|
152
|
+
function parsePopulate2(populate) {
|
|
153
|
+
if (!populate) return [];
|
|
154
|
+
if (typeof populate === "string") {
|
|
155
|
+
return populate.split(",").map((p) => p.trim());
|
|
156
|
+
}
|
|
157
|
+
if (Array.isArray(populate)) {
|
|
158
|
+
return populate.map((p) => typeof p === "string" ? p.trim() : p);
|
|
159
|
+
}
|
|
160
|
+
return [populate];
|
|
161
|
+
}
|
|
162
|
+
async function update(Model, id, data, options = {}) {
|
|
163
|
+
const document = await Model.findByIdAndUpdate(id, data, {
|
|
164
|
+
new: true,
|
|
165
|
+
runValidators: true,
|
|
166
|
+
session: options.session,
|
|
167
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
168
|
+
}).select(options.select || "").populate(parsePopulate2(options.populate)).lean(options.lean ?? false);
|
|
169
|
+
if (!document) {
|
|
170
|
+
throw createError(404, "Document not found");
|
|
171
|
+
}
|
|
172
|
+
return document;
|
|
173
|
+
}
|
|
174
|
+
async function updateWithConstraints(Model, id, data, constraints = {}, options = {}) {
|
|
175
|
+
const query = { _id: id, ...constraints };
|
|
176
|
+
const document = await Model.findOneAndUpdate(query, data, {
|
|
177
|
+
new: true,
|
|
178
|
+
runValidators: true,
|
|
179
|
+
session: options.session,
|
|
180
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
181
|
+
}).select(options.select || "").populate(parsePopulate2(options.populate)).lean(options.lean ?? false);
|
|
182
|
+
return document;
|
|
183
|
+
}
|
|
184
|
+
async function updateWithValidation(Model, id, data, validationOptions = {}, options = {}) {
|
|
185
|
+
const { buildConstraints, validateUpdate } = validationOptions;
|
|
186
|
+
if (buildConstraints) {
|
|
187
|
+
const constraints = buildConstraints(data);
|
|
188
|
+
const document = await updateWithConstraints(Model, id, data, constraints, options);
|
|
189
|
+
if (document) {
|
|
190
|
+
return { success: true, data: document };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const existing = await Model.findById(id).select(options.select || "").lean();
|
|
194
|
+
if (!existing) {
|
|
195
|
+
return {
|
|
196
|
+
success: false,
|
|
197
|
+
error: {
|
|
198
|
+
code: 404,
|
|
199
|
+
message: "Document not found"
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (validateUpdate) {
|
|
204
|
+
const validation = validateUpdate(existing, data);
|
|
205
|
+
if (!validation.valid) {
|
|
206
|
+
return {
|
|
207
|
+
success: false,
|
|
208
|
+
error: {
|
|
209
|
+
code: 403,
|
|
210
|
+
message: validation.message || "Update not allowed",
|
|
211
|
+
violations: validation.violations
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const updated = await update(Model, id, data, options);
|
|
217
|
+
return { success: true, data: updated };
|
|
218
|
+
}
|
|
219
|
+
async function updateMany(Model, query, data, options = {}) {
|
|
220
|
+
const result = await Model.updateMany(query, data, {
|
|
221
|
+
runValidators: true,
|
|
222
|
+
session: options.session,
|
|
223
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
matchedCount: result.matchedCount,
|
|
227
|
+
modifiedCount: result.modifiedCount
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
async function updateByQuery(Model, query, data, options = {}) {
|
|
231
|
+
const document = await Model.findOneAndUpdate(query, data, {
|
|
232
|
+
new: true,
|
|
233
|
+
runValidators: true,
|
|
234
|
+
session: options.session,
|
|
235
|
+
...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
|
|
236
|
+
}).select(options.select || "").populate(parsePopulate2(options.populate)).lean(options.lean ?? false);
|
|
237
|
+
if (!document && options.throwOnNotFound !== false) {
|
|
238
|
+
throw createError(404, "Document not found");
|
|
239
|
+
}
|
|
240
|
+
return document;
|
|
241
|
+
}
|
|
242
|
+
async function increment(Model, id, field, value = 1, options = {}) {
|
|
243
|
+
return update(Model, id, { $inc: { [field]: value } }, options);
|
|
244
|
+
}
|
|
245
|
+
async function pushToArray(Model, id, field, value, options = {}) {
|
|
246
|
+
return update(Model, id, { $push: { [field]: value } }, options);
|
|
247
|
+
}
|
|
248
|
+
async function pullFromArray(Model, id, field, value, options = {}) {
|
|
249
|
+
return update(Model, id, { $pull: { [field]: value } }, options);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/actions/delete.ts
|
|
253
|
+
var delete_exports = {};
|
|
254
|
+
__export(delete_exports, {
|
|
255
|
+
deleteById: () => deleteById,
|
|
256
|
+
deleteByQuery: () => deleteByQuery,
|
|
257
|
+
deleteMany: () => deleteMany,
|
|
258
|
+
restore: () => restore,
|
|
259
|
+
softDelete: () => softDelete
|
|
260
|
+
});
|
|
261
|
+
async function deleteById(Model, id, options = {}) {
|
|
262
|
+
const document = await Model.findByIdAndDelete(id).session(options.session ?? null);
|
|
263
|
+
if (!document) {
|
|
264
|
+
throw createError(404, "Document not found");
|
|
265
|
+
}
|
|
266
|
+
return { success: true, message: "Deleted successfully" };
|
|
267
|
+
}
|
|
268
|
+
async function deleteMany(Model, query, options = {}) {
|
|
269
|
+
const result = await Model.deleteMany(query).session(options.session ?? null);
|
|
270
|
+
return {
|
|
271
|
+
success: true,
|
|
272
|
+
count: result.deletedCount,
|
|
273
|
+
message: "Deleted successfully"
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
async function deleteByQuery(Model, query, options = {}) {
|
|
277
|
+
const document = await Model.findOneAndDelete(query).session(options.session ?? null);
|
|
278
|
+
if (!document && options.throwOnNotFound !== false) {
|
|
279
|
+
throw createError(404, "Document not found");
|
|
280
|
+
}
|
|
281
|
+
return { success: true, message: "Deleted successfully" };
|
|
282
|
+
}
|
|
283
|
+
async function softDelete(Model, id, options = {}) {
|
|
284
|
+
const document = await Model.findByIdAndUpdate(
|
|
285
|
+
id,
|
|
286
|
+
{
|
|
287
|
+
deleted: true,
|
|
288
|
+
deletedAt: /* @__PURE__ */ new Date(),
|
|
289
|
+
deletedBy: options.userId
|
|
290
|
+
},
|
|
291
|
+
{ new: true, session: options.session }
|
|
292
|
+
);
|
|
293
|
+
if (!document) {
|
|
294
|
+
throw createError(404, "Document not found");
|
|
295
|
+
}
|
|
296
|
+
return { success: true, message: "Soft deleted successfully" };
|
|
297
|
+
}
|
|
298
|
+
async function restore(Model, id, options = {}) {
|
|
299
|
+
const document = await Model.findByIdAndUpdate(
|
|
300
|
+
id,
|
|
301
|
+
{
|
|
302
|
+
deleted: false,
|
|
303
|
+
deletedAt: null,
|
|
304
|
+
deletedBy: null
|
|
305
|
+
},
|
|
306
|
+
{ new: true, session: options.session }
|
|
307
|
+
);
|
|
308
|
+
if (!document) {
|
|
309
|
+
throw createError(404, "Document not found");
|
|
310
|
+
}
|
|
311
|
+
return { success: true, message: "Restored successfully" };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/actions/aggregate.ts
|
|
315
|
+
var aggregate_exports = {};
|
|
316
|
+
__export(aggregate_exports, {
|
|
317
|
+
aggregate: () => aggregate,
|
|
318
|
+
aggregatePaginate: () => aggregatePaginate,
|
|
319
|
+
average: () => average,
|
|
320
|
+
countBy: () => countBy,
|
|
321
|
+
distinct: () => distinct,
|
|
322
|
+
facet: () => facet,
|
|
323
|
+
groupBy: () => groupBy,
|
|
324
|
+
lookup: () => lookup,
|
|
325
|
+
minMax: () => minMax,
|
|
326
|
+
sum: () => sum,
|
|
327
|
+
unwind: () => unwind
|
|
328
|
+
});
|
|
329
|
+
async function aggregate(Model, pipeline, options = {}) {
|
|
330
|
+
const aggregation = Model.aggregate(pipeline);
|
|
331
|
+
if (options.session) {
|
|
332
|
+
aggregation.session(options.session);
|
|
333
|
+
}
|
|
334
|
+
return aggregation.exec();
|
|
335
|
+
}
|
|
336
|
+
async function aggregatePaginate(Model, pipeline, options = {}) {
|
|
337
|
+
const page = parseInt(String(options.page || 1), 10);
|
|
338
|
+
const limit = parseInt(String(options.limit || 10), 10);
|
|
339
|
+
const skip = (page - 1) * limit;
|
|
340
|
+
const SAFE_LIMIT = 1e3;
|
|
341
|
+
if (limit > SAFE_LIMIT) {
|
|
342
|
+
console.warn(
|
|
343
|
+
`[mongokit] Large aggregation limit (${limit}). $facet results must be <16MB. Consider using Repository.aggregatePaginate() for safer handling of large datasets.`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
const facetPipeline = [
|
|
347
|
+
...pipeline,
|
|
348
|
+
{
|
|
349
|
+
$facet: {
|
|
350
|
+
docs: [{ $skip: skip }, { $limit: limit }],
|
|
351
|
+
total: [{ $count: "count" }]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
];
|
|
355
|
+
const aggregation = Model.aggregate(facetPipeline);
|
|
356
|
+
if (options.session) {
|
|
357
|
+
aggregation.session(options.session);
|
|
358
|
+
}
|
|
359
|
+
const [result] = await aggregation.exec();
|
|
360
|
+
const docs = result.docs || [];
|
|
361
|
+
const total = result.total[0]?.count || 0;
|
|
362
|
+
const pages = Math.ceil(total / limit);
|
|
363
|
+
return {
|
|
364
|
+
docs,
|
|
365
|
+
total,
|
|
366
|
+
page,
|
|
367
|
+
limit,
|
|
368
|
+
pages,
|
|
369
|
+
hasNext: page < pages,
|
|
370
|
+
hasPrev: page > 1
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
async function groupBy(Model, field, options = {}) {
|
|
374
|
+
const pipeline = [
|
|
375
|
+
{ $group: { _id: `$${field}`, count: { $sum: 1 } } },
|
|
376
|
+
{ $sort: { count: -1 } }
|
|
377
|
+
];
|
|
378
|
+
if (options.limit) {
|
|
379
|
+
pipeline.push({ $limit: options.limit });
|
|
380
|
+
}
|
|
381
|
+
return aggregate(Model, pipeline, options);
|
|
382
|
+
}
|
|
383
|
+
async function countBy(Model, field, query = {}, options = {}) {
|
|
384
|
+
const pipeline = [];
|
|
385
|
+
if (Object.keys(query).length > 0) {
|
|
386
|
+
pipeline.push({ $match: query });
|
|
387
|
+
}
|
|
388
|
+
pipeline.push(
|
|
389
|
+
{ $group: { _id: `$${field}`, count: { $sum: 1 } } },
|
|
390
|
+
{ $sort: { count: -1 } }
|
|
391
|
+
);
|
|
392
|
+
return aggregate(Model, pipeline, options);
|
|
393
|
+
}
|
|
394
|
+
async function lookup(Model, lookupOptions) {
|
|
395
|
+
const { from, localField, foreignField, as, pipeline = [], query = {}, options = {} } = lookupOptions;
|
|
396
|
+
const aggPipeline = [];
|
|
397
|
+
if (Object.keys(query).length > 0) {
|
|
398
|
+
aggPipeline.push({ $match: query });
|
|
399
|
+
}
|
|
400
|
+
aggPipeline.push({
|
|
401
|
+
$lookup: {
|
|
402
|
+
from,
|
|
403
|
+
localField,
|
|
404
|
+
foreignField,
|
|
405
|
+
as,
|
|
406
|
+
...pipeline.length > 0 ? { pipeline } : {}
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
return aggregate(Model, aggPipeline, options);
|
|
410
|
+
}
|
|
411
|
+
async function unwind(Model, field, options = {}) {
|
|
412
|
+
const pipeline = [
|
|
413
|
+
{
|
|
414
|
+
$unwind: {
|
|
415
|
+
path: `$${field}`,
|
|
416
|
+
preserveNullAndEmptyArrays: options.preserveEmpty !== false
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
];
|
|
420
|
+
return aggregate(Model, pipeline, { session: options.session });
|
|
421
|
+
}
|
|
422
|
+
async function facet(Model, facets, options = {}) {
|
|
423
|
+
const pipeline = [{ $facet: facets }];
|
|
424
|
+
return aggregate(Model, pipeline, options);
|
|
425
|
+
}
|
|
426
|
+
async function distinct(Model, field, query = {}, options = {}) {
|
|
427
|
+
return Model.distinct(field, query).session(options.session ?? null);
|
|
428
|
+
}
|
|
429
|
+
async function sum(Model, field, query = {}, options = {}) {
|
|
430
|
+
const pipeline = [];
|
|
431
|
+
if (Object.keys(query).length > 0) {
|
|
432
|
+
pipeline.push({ $match: query });
|
|
433
|
+
}
|
|
434
|
+
pipeline.push({
|
|
435
|
+
$group: {
|
|
436
|
+
_id: null,
|
|
437
|
+
total: { $sum: `$${field}` }
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
const result = await aggregate(Model, pipeline, options);
|
|
441
|
+
return result[0]?.total || 0;
|
|
442
|
+
}
|
|
443
|
+
async function average(Model, field, query = {}, options = {}) {
|
|
444
|
+
const pipeline = [];
|
|
445
|
+
if (Object.keys(query).length > 0) {
|
|
446
|
+
pipeline.push({ $match: query });
|
|
447
|
+
}
|
|
448
|
+
pipeline.push({
|
|
449
|
+
$group: {
|
|
450
|
+
_id: null,
|
|
451
|
+
average: { $avg: `$${field}` }
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
const result = await aggregate(Model, pipeline, options);
|
|
455
|
+
return result[0]?.average || 0;
|
|
456
|
+
}
|
|
457
|
+
async function minMax(Model, field, query = {}, options = {}) {
|
|
458
|
+
const pipeline = [];
|
|
459
|
+
if (Object.keys(query).length > 0) {
|
|
460
|
+
pipeline.push({ $match: query });
|
|
461
|
+
}
|
|
462
|
+
pipeline.push({
|
|
463
|
+
$group: {
|
|
464
|
+
_id: null,
|
|
465
|
+
min: { $min: `$${field}` },
|
|
466
|
+
max: { $max: `$${field}` }
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
const result = await aggregate(Model, pipeline, options);
|
|
470
|
+
return result[0] || { min: null, max: null };
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
exports.aggregate = aggregate_exports;
|
|
474
|
+
exports.create = create_exports;
|
|
475
|
+
exports.deleteActions = delete_exports;
|
|
476
|
+
exports.read = read_exports;
|
|
477
|
+
exports.update = update_exports;
|
|
478
|
+
//# sourceMappingURL=index.cjs.map
|
|
479
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/actions/create.ts","../../src/actions/read.ts","../../src/utils/error.ts","../../src/actions/update.ts","../../src/actions/delete.ts","../../src/actions/aggregate.ts"],"names":["parsePopulate"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Create Actions\r\n * Pure functions for document creation\r\n */\r\n\r\nimport type { Model, ClientSession, SchemaType } from 'mongoose';\r\nimport type { CreateOptions, AnyDocument } from '../types.js';\r\n\r\n/**\r\n * Create single document\r\n */\r\nexport async function create<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n data: Record<string, unknown>,\r\n options: CreateOptions = {}\r\n): Promise<TDoc> {\r\n const document = new Model(data);\r\n await document.save({ session: options.session });\r\n return document as TDoc;\r\n}\r\n\r\n/**\r\n * Create multiple documents\r\n */\r\nexport async function createMany<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n dataArray: Record<string, unknown>[],\r\n options: CreateOptions = {}\r\n): Promise<TDoc[]> {\r\n return Model.insertMany(dataArray, {\r\n session: options.session,\r\n ordered: options.ordered !== false,\r\n }) as Promise<TDoc[]>;\r\n}\r\n\r\n/**\r\n * Create with defaults (useful for initialization)\r\n */\r\nexport async function createDefault<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n overrides: Record<string, unknown> = {},\r\n options: CreateOptions = {}\r\n): Promise<TDoc> {\r\n const defaults: Record<string, unknown> = {};\r\n\r\n // Extract defaults from schema\r\n Model.schema.eachPath((path: string, schemaType: SchemaType) => {\r\n const schemaOptions = schemaType.options as { default?: unknown };\r\n if (schemaOptions.default !== undefined && path !== '_id') {\r\n defaults[path] = typeof schemaOptions.default === 'function'\r\n ? schemaOptions.default()\r\n : schemaOptions.default;\r\n }\r\n });\r\n\r\n return create(Model, { ...defaults, ...overrides }, options);\r\n}\r\n\r\n/**\r\n * Upsert (create or update)\r\n */\r\nexport async function upsert<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown>,\r\n data: Record<string, unknown>,\r\n options: { session?: ClientSession; updatePipeline?: boolean } = {}\r\n): Promise<TDoc | null> {\r\n return Model.findOneAndUpdate(\r\n query,\r\n { $setOnInsert: data },\r\n {\r\n upsert: true,\r\n new: true,\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n }\r\n );\r\n}\r\n","/**\r\n * Read Actions\r\n * Pure functions for document retrieval\r\n */\r\n\r\nimport type { Model, ClientSession, PopulateOptions } from 'mongoose';\r\nimport { createError } from '../utils/error.js';\r\nimport type { AnyDocument, SelectSpec, PopulateSpec, SortSpec, OperationOptions } from '../types.js';\r\n\r\n/**\r\n * Parse populate specification into consistent format\r\n */\r\nfunction parsePopulate(populate: PopulateSpec | undefined): (string | PopulateOptions)[] {\r\n if (!populate) return [];\r\n if (typeof populate === 'string') {\r\n return populate.split(',').map(p => p.trim());\r\n }\r\n if (Array.isArray(populate)) {\r\n return populate.map(p => typeof p === 'string' ? p.trim() : p);\r\n }\r\n return [populate];\r\n}\r\n\r\n/**\r\n * Get document by ID\r\n *\r\n * @param Model - Mongoose model\r\n * @param id - Document ID\r\n * @param options - Query options\r\n * @returns Document or null\r\n * @throws Error if document not found and throwOnNotFound is true\r\n */\r\nexport async function getById<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n options: OperationOptions = {}\r\n): Promise<TDoc | null> {\r\n // If additional query filters are provided (e.g., soft delete filter), use findOne\r\n const query = options.query\r\n ? Model.findOne({ _id: id, ...options.query })\r\n : Model.findById(id);\r\n\r\n if (options.select) query.select(options.select);\r\n if (options.populate) query.populate(parsePopulate(options.populate));\r\n if (options.lean) query.lean();\r\n if (options.session) query.session(options.session);\r\n\r\n const document = await query.exec();\r\n if (!document && options.throwOnNotFound !== false) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return document;\r\n}\r\n\r\n/**\r\n * Get document by query\r\n *\r\n * @param Model - Mongoose model\r\n * @param query - MongoDB query\r\n * @param options - Query options\r\n * @returns Document or null\r\n * @throws Error if document not found and throwOnNotFound is true\r\n */\r\nexport async function getByQuery<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown>,\r\n options: OperationOptions = {}\r\n): Promise<TDoc | null> {\r\n const mongoQuery = Model.findOne(query);\r\n\r\n if (options.select) mongoQuery.select(options.select);\r\n if (options.populate) mongoQuery.populate(parsePopulate(options.populate));\r\n if (options.lean) mongoQuery.lean();\r\n if (options.session) mongoQuery.session(options.session);\r\n\r\n const document = await mongoQuery.exec();\r\n if (!document && options.throwOnNotFound !== false) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return document;\r\n}\r\n\r\n/**\r\n * Get document by query without throwing (returns null if not found)\r\n */\r\nexport async function tryGetByQuery<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown>,\r\n options: Omit<OperationOptions, 'throwOnNotFound'> = {}\r\n): Promise<TDoc | null> {\r\n return getByQuery(Model, query, { ...options, throwOnNotFound: false });\r\n}\r\n\r\n/**\r\n * Get all documents (basic query without pagination)\r\n * For pagination, use Repository.paginate() or Repository.stream()\r\n */\r\nexport async function getAll<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown> = {},\r\n options: {\r\n select?: SelectSpec;\r\n populate?: PopulateSpec;\r\n sort?: SortSpec;\r\n limit?: number;\r\n skip?: number;\r\n lean?: boolean;\r\n session?: ClientSession;\r\n } = {}\r\n): Promise<TDoc[]> {\r\n let mongoQuery = Model.find(query);\r\n\r\n if (options.select) mongoQuery = mongoQuery.select(options.select);\r\n if (options.populate) mongoQuery = mongoQuery.populate(parsePopulate(options.populate));\r\n if (options.sort) mongoQuery = mongoQuery.sort(options.sort);\r\n if (options.limit) mongoQuery = mongoQuery.limit(options.limit);\r\n if (options.skip) mongoQuery = mongoQuery.skip(options.skip);\r\n\r\n mongoQuery = mongoQuery.lean(options.lean !== false);\r\n if (options.session) mongoQuery = mongoQuery.session(options.session);\r\n\r\n return mongoQuery.exec() as Promise<TDoc[]>;\r\n}\r\n\r\n/**\r\n * Get or create document (upsert)\r\n */\r\nexport async function getOrCreate<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown>,\r\n createData: Record<string, unknown>,\r\n options: { session?: ClientSession; updatePipeline?: boolean } = {}\r\n): Promise<TDoc | null> {\r\n return Model.findOneAndUpdate(\r\n query,\r\n { $setOnInsert: createData },\r\n {\r\n upsert: true,\r\n new: true,\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Count documents matching query\r\n */\r\nexport async function count(\r\n Model: Model<any>,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<number> {\r\n return Model.countDocuments(query).session(options.session ?? null);\r\n}\r\n\r\n/**\r\n * Check if document exists\r\n */\r\nexport async function exists(\r\n Model: Model<any>,\r\n query: Record<string, unknown>,\r\n options: { session?: ClientSession } = {}\r\n): Promise<{ _id: unknown } | null> {\r\n return Model.exists(query).session(options.session ?? null);\r\n}\r\n","/**\r\n * Error Utilities\r\n * \r\n * HTTP-compatible error creation for repository operations\r\n */\r\n\r\nimport type { HttpError } from '../types.js';\r\n\r\n/**\r\n * Creates an error with HTTP status code\r\n *\r\n * @param status - HTTP status code\r\n * @param message - Error message\r\n * @returns Error with status property\r\n * \r\n * @example\r\n * throw createError(404, 'Document not found');\r\n * throw createError(400, 'Invalid input');\r\n * throw createError(403, 'Access denied');\r\n */\r\nexport function createError(status: number, message: string): HttpError {\r\n const error = new Error(message) as HttpError;\r\n error.status = status;\r\n return error;\r\n}\r\n","/**\r\n * Update Actions\r\n * Pure functions for document updates with optimizations\r\n */\r\n\r\nimport type { Model, ClientSession, PopulateOptions } from 'mongoose';\r\nimport { createError } from '../utils/error.js';\r\nimport type { AnyDocument, UpdateOptions, UpdateManyResult, UpdateWithValidationResult } from '../types.js';\r\n\r\n/**\r\n * Parse populate specification into consistent format\r\n */\r\nfunction parsePopulate(populate: unknown): (string | PopulateOptions)[] {\r\n if (!populate) return [];\r\n if (typeof populate === 'string') {\r\n return populate.split(',').map(p => p.trim());\r\n }\r\n if (Array.isArray(populate)) {\r\n return populate.map(p => typeof p === 'string' ? p.trim() : p as PopulateOptions);\r\n }\r\n return [populate as PopulateOptions];\r\n}\r\n\r\n/**\r\n * Update by ID\r\n */\r\nexport async function update<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n data: Record<string, unknown>,\r\n options: UpdateOptions = {}\r\n): Promise<TDoc> {\r\n const document = await Model.findByIdAndUpdate(id, data, {\r\n new: true,\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n })\r\n .select(options.select || '')\r\n .populate(parsePopulate(options.populate))\r\n .lean(options.lean ?? false);\r\n\r\n if (!document) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return document as TDoc;\r\n}\r\n\r\n/**\r\n * Update with query constraints (optimized)\r\n * Returns null if constraints not met (not an error)\r\n */\r\nexport async function updateWithConstraints<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n data: Record<string, unknown>,\r\n constraints: Record<string, unknown> = {},\r\n options: UpdateOptions = {}\r\n): Promise<TDoc | null> {\r\n const query = { _id: id, ...constraints };\r\n\r\n const document = await Model.findOneAndUpdate(query, data, {\r\n new: true,\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n })\r\n .select(options.select || '')\r\n .populate(parsePopulate(options.populate))\r\n .lean(options.lean ?? false);\r\n\r\n return document as TDoc | null;\r\n}\r\n\r\n/**\r\n * Validation options for smart update\r\n */\r\ninterface ValidationOptions {\r\n buildConstraints?: (data: Record<string, unknown>) => Record<string, unknown>;\r\n validateUpdate?: (\r\n existing: Record<string, unknown>,\r\n data: Record<string, unknown>\r\n ) => { valid: boolean; message?: string; violations?: Array<{ field: string; reason: string }> };\r\n}\r\n\r\n/**\r\n * Update with validation (smart optimization)\r\n * 1-query on success, 2-queries for detailed errors\r\n */\r\nexport async function updateWithValidation<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n data: Record<string, unknown>,\r\n validationOptions: ValidationOptions = {},\r\n options: UpdateOptions = {}\r\n): Promise<UpdateWithValidationResult<TDoc>> {\r\n const { buildConstraints, validateUpdate } = validationOptions;\r\n\r\n // Try optimized update with constraints\r\n if (buildConstraints) {\r\n const constraints = buildConstraints(data);\r\n const document = await updateWithConstraints(Model, id, data, constraints, options);\r\n\r\n if (document) {\r\n return { success: true, data: document };\r\n }\r\n }\r\n\r\n // Fetch for validation\r\n const existing = await Model.findById(id).select(options.select || '').lean();\r\n\r\n if (!existing) {\r\n return {\r\n success: false,\r\n error: {\r\n code: 404,\r\n message: 'Document not found',\r\n },\r\n };\r\n }\r\n\r\n // Run custom validation\r\n if (validateUpdate) {\r\n const validation = validateUpdate(existing as Record<string, unknown>, data);\r\n if (!validation.valid) {\r\n return {\r\n success: false,\r\n error: {\r\n code: 403,\r\n message: validation.message || 'Update not allowed',\r\n violations: validation.violations,\r\n },\r\n };\r\n }\r\n }\r\n\r\n // Validation passed - perform update\r\n const updated = await update(Model, id, data, options);\r\n return { success: true, data: updated };\r\n}\r\n\r\n/**\r\n * Update many documents\r\n */\r\nexport async function updateMany(\r\n Model: Model<unknown>,\r\n query: Record<string, unknown>,\r\n data: Record<string, unknown>,\r\n options: { session?: ClientSession; updatePipeline?: boolean } = {}\r\n): Promise<UpdateManyResult> {\r\n const result = await Model.updateMany(query, data, {\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n });\r\n\r\n return {\r\n matchedCount: result.matchedCount,\r\n modifiedCount: result.modifiedCount,\r\n };\r\n}\r\n\r\n/**\r\n * Update by query\r\n */\r\nexport async function updateByQuery<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n query: Record<string, unknown>,\r\n data: Record<string, unknown>,\r\n options: UpdateOptions = {}\r\n): Promise<TDoc | null> {\r\n const document = await Model.findOneAndUpdate(query, data, {\r\n new: true,\r\n runValidators: true,\r\n session: options.session,\r\n ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),\r\n })\r\n .select(options.select || '')\r\n .populate(parsePopulate(options.populate))\r\n .lean(options.lean ?? false);\r\n\r\n if (!document && options.throwOnNotFound !== false) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return document as TDoc | null;\r\n}\r\n\r\n/**\r\n * Increment field\r\n */\r\nexport async function increment<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n field: string,\r\n value: number = 1,\r\n options: UpdateOptions = {}\r\n): Promise<TDoc> {\r\n return update(Model, id, { $inc: { [field]: value } }, options);\r\n}\r\n\r\n/**\r\n * Push to array\r\n */\r\nexport async function pushToArray<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n field: string,\r\n value: unknown,\r\n options: UpdateOptions = {}\r\n): Promise<TDoc> {\r\n return update(Model, id, { $push: { [field]: value } }, options);\r\n}\r\n\r\n/**\r\n * Pull from array\r\n */\r\nexport async function pullFromArray<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n field: string,\r\n value: unknown,\r\n options: UpdateOptions = {}\r\n): Promise<TDoc> {\r\n return update(Model, id, { $pull: { [field]: value } }, options);\r\n}\r\n","/**\r\n * Delete Actions\r\n * Pure functions for document deletion\r\n */\r\n\r\nimport type { Model, ClientSession } from 'mongoose';\r\nimport { createError } from '../utils/error.js';\r\nimport type { DeleteResult, AnyDocument } from '../types.js';\r\n\r\n/**\r\n * Delete by ID\r\n */\r\nexport async function deleteById(\r\n Model: Model<any>,\r\n id: string,\r\n options: { session?: ClientSession } = {}\r\n): Promise<DeleteResult> {\r\n const document = await Model.findByIdAndDelete(id).session(options.session ?? null);\r\n\r\n if (!document) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return { success: true, message: 'Deleted successfully' };\r\n}\r\n\r\n/**\r\n * Delete many documents\r\n */\r\nexport async function deleteMany(\r\n Model: Model<any>,\r\n query: Record<string, unknown>,\r\n options: { session?: ClientSession } = {}\r\n): Promise<DeleteResult> {\r\n const result = await Model.deleteMany(query).session(options.session ?? null);\r\n\r\n return {\r\n success: true,\r\n count: result.deletedCount,\r\n message: 'Deleted successfully',\r\n };\r\n}\r\n\r\n/**\r\n * Delete by query\r\n */\r\nexport async function deleteByQuery(\r\n Model: Model<any>,\r\n query: Record<string, unknown>,\r\n options: { session?: ClientSession; throwOnNotFound?: boolean } = {}\r\n): Promise<DeleteResult> {\r\n const document = await Model.findOneAndDelete(query).session(options.session ?? null);\r\n\r\n if (!document && options.throwOnNotFound !== false) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return { success: true, message: 'Deleted successfully' };\r\n}\r\n\r\n/**\r\n * Soft delete (set deleted flag)\r\n */\r\nexport async function softDelete<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n options: { session?: ClientSession; userId?: string } = {}\r\n): Promise<DeleteResult> {\r\n const document = await Model.findByIdAndUpdate(\r\n id,\r\n {\r\n deleted: true,\r\n deletedAt: new Date(),\r\n deletedBy: options.userId,\r\n },\r\n { new: true, session: options.session }\r\n );\r\n\r\n if (!document) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return { success: true, message: 'Soft deleted successfully' };\r\n}\r\n\r\n/**\r\n * Restore soft deleted document\r\n */\r\nexport async function restore<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n id: string,\r\n options: { session?: ClientSession } = {}\r\n): Promise<DeleteResult> {\r\n const document = await Model.findByIdAndUpdate(\r\n id,\r\n {\r\n deleted: false,\r\n deletedAt: null,\r\n deletedBy: null,\r\n },\r\n { new: true, session: options.session }\r\n );\r\n\r\n if (!document) {\r\n throw createError(404, 'Document not found');\r\n }\r\n\r\n return { success: true, message: 'Restored successfully' };\r\n}\r\n","/**\r\n * Aggregate Actions\r\n * MongoDB aggregation pipeline operations\r\n */\r\n\r\nimport type { Model, ClientSession, PipelineStage } from 'mongoose';\r\nimport type { AnyDocument, LookupOptions, GroupResult, MinMaxResult } from '../types.js';\r\n\r\n/**\r\n * Execute aggregation pipeline\r\n */\r\nexport async function aggregate<TResult = unknown>(\r\n Model: Model<any>,\r\n pipeline: PipelineStage[],\r\n options: { session?: ClientSession } = {}\r\n): Promise<TResult[]> {\r\n const aggregation = Model.aggregate(pipeline);\r\n\r\n if (options.session) {\r\n aggregation.session(options.session);\r\n }\r\n\r\n return aggregation.exec() as Promise<TResult[]>;\r\n}\r\n\r\n/**\r\n * Aggregate with pagination using native MongoDB $facet\r\n * WARNING: $facet results must be <16MB. For larger results (limit >1000),\r\n * consider using Repository.aggregatePaginate() or splitting into separate queries.\r\n */\r\nexport async function aggregatePaginate<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n pipeline: PipelineStage[],\r\n options: { page?: number; limit?: number; session?: ClientSession } = {}\r\n): Promise<{\r\n docs: TDoc[];\r\n total: number;\r\n page: number;\r\n limit: number;\r\n pages: number;\r\n hasNext: boolean;\r\n hasPrev: boolean;\r\n}> {\r\n const page = parseInt(String(options.page || 1), 10);\r\n const limit = parseInt(String(options.limit || 10), 10);\r\n const skip = (page - 1) * limit;\r\n\r\n // 16MB MongoDB document size limit safety check\r\n const SAFE_LIMIT = 1000;\r\n if (limit > SAFE_LIMIT) {\r\n console.warn(\r\n `[mongokit] Large aggregation limit (${limit}). $facet results must be <16MB. ` +\r\n `Consider using Repository.aggregatePaginate() for safer handling of large datasets.`\r\n );\r\n }\r\n\r\n const facetPipeline: PipelineStage[] = [\r\n ...pipeline,\r\n {\r\n $facet: {\r\n docs: [{ $skip: skip }, { $limit: limit }],\r\n total: [{ $count: 'count' }],\r\n },\r\n },\r\n ];\r\n\r\n const aggregation = Model.aggregate(facetPipeline);\r\n if (options.session) {\r\n aggregation.session(options.session);\r\n }\r\n\r\n const [result] = await aggregation.exec() as [{ docs: TDoc[]; total: { count: number }[] }];\r\n const docs = result.docs || [];\r\n const total = result.total[0]?.count || 0;\r\n const pages = Math.ceil(total / limit);\r\n\r\n return {\r\n docs,\r\n total,\r\n page,\r\n limit,\r\n pages,\r\n hasNext: page < pages,\r\n hasPrev: page > 1,\r\n };\r\n}\r\n\r\n/**\r\n * Group documents by field value\r\n */\r\nexport async function groupBy(\r\n Model: Model<any>,\r\n field: string,\r\n options: { limit?: number; session?: ClientSession } = {}\r\n): Promise<GroupResult[]> {\r\n const pipeline: PipelineStage[] = [\r\n { $group: { _id: `$${field}`, count: { $sum: 1 } } },\r\n { $sort: { count: -1 } },\r\n ];\r\n\r\n if (options.limit) {\r\n pipeline.push({ $limit: options.limit });\r\n }\r\n\r\n return aggregate(Model, pipeline, options);\r\n}\r\n\r\n/**\r\n * Count by field values\r\n */\r\nexport async function countBy(\r\n Model: Model<any>,\r\n field: string,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<GroupResult[]> {\r\n const pipeline: PipelineStage[] = [];\r\n\r\n if (Object.keys(query).length > 0) {\r\n pipeline.push({ $match: query });\r\n }\r\n\r\n pipeline.push(\r\n { $group: { _id: `$${field}`, count: { $sum: 1 } } },\r\n { $sort: { count: -1 } }\r\n );\r\n\r\n return aggregate(Model, pipeline, options);\r\n}\r\n\r\n/**\r\n * Lookup (join) with another collection\r\n */\r\nexport async function lookup<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n lookupOptions: LookupOptions\r\n): Promise<TDoc[]> {\r\n const { from, localField, foreignField, as, pipeline = [], query = {}, options = {} } = lookupOptions;\r\n\r\n const aggPipeline: PipelineStage[] = [];\r\n\r\n if (Object.keys(query).length > 0) {\r\n aggPipeline.push({ $match: query });\r\n }\r\n\r\n aggPipeline.push({\r\n $lookup: {\r\n from,\r\n localField,\r\n foreignField,\r\n as,\r\n ...(pipeline.length > 0 ? { pipeline: pipeline as any } : {}),\r\n },\r\n } as any);\r\n\r\n return aggregate(Model, aggPipeline, options);\r\n}\r\n\r\n/**\r\n * Unwind array field\r\n */\r\nexport async function unwind<TDoc = AnyDocument>(\r\n Model: Model<TDoc>,\r\n field: string,\r\n options: { preserveEmpty?: boolean; session?: ClientSession } = {}\r\n): Promise<TDoc[]> {\r\n const pipeline: PipelineStage[] = [\r\n {\r\n $unwind: {\r\n path: `$${field}`,\r\n preserveNullAndEmptyArrays: options.preserveEmpty !== false,\r\n },\r\n },\r\n ];\r\n\r\n return aggregate(Model, pipeline, { session: options.session });\r\n}\r\n\r\n/**\r\n * Facet search (multiple aggregations in one query)\r\n */\r\nexport async function facet<TResult = Record<string, unknown[]>>(\r\n Model: Model<any>,\r\n facets: Record<string, PipelineStage[]>,\r\n options: { session?: ClientSession } = {}\r\n): Promise<TResult[]> {\r\n const pipeline: PipelineStage[] = [{ $facet: facets as any } as any];\r\n\r\n return aggregate(Model, pipeline, options);\r\n}\r\n\r\n/**\r\n * Get distinct values\r\n */\r\nexport async function distinct<T = unknown>(\r\n Model: Model<any>,\r\n field: string,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<T[]> {\r\n return Model.distinct(field, query).session(options.session ?? null) as Promise<T[]>;\r\n}\r\n\r\n/**\r\n * Calculate sum\r\n */\r\nexport async function sum(\r\n Model: Model<any>,\r\n field: string,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<number> {\r\n const pipeline: PipelineStage[] = [];\r\n\r\n if (Object.keys(query).length > 0) {\r\n pipeline.push({ $match: query });\r\n }\r\n\r\n pipeline.push({\r\n $group: {\r\n _id: null,\r\n total: { $sum: `$${field}` },\r\n },\r\n });\r\n\r\n const result = await aggregate<{ total: number }>(Model, pipeline, options);\r\n return result[0]?.total || 0;\r\n}\r\n\r\n/**\r\n * Calculate average\r\n */\r\nexport async function average(\r\n Model: Model<any>,\r\n field: string,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<number> {\r\n const pipeline: PipelineStage[] = [];\r\n\r\n if (Object.keys(query).length > 0) {\r\n pipeline.push({ $match: query });\r\n }\r\n\r\n pipeline.push({\r\n $group: {\r\n _id: null,\r\n average: { $avg: `$${field}` },\r\n },\r\n });\r\n\r\n const result = await aggregate<{ average: number }>(Model, pipeline, options);\r\n return result[0]?.average || 0;\r\n}\r\n\r\n/**\r\n * Min/Max\r\n */\r\nexport async function minMax(\r\n Model: Model<any>,\r\n field: string,\r\n query: Record<string, unknown> = {},\r\n options: { session?: ClientSession } = {}\r\n): Promise<MinMaxResult> {\r\n const pipeline: PipelineStage[] = [];\r\n\r\n if (Object.keys(query).length > 0) {\r\n pipeline.push({ $match: query });\r\n }\r\n\r\n pipeline.push({\r\n $group: {\r\n _id: null,\r\n min: { $min: `$${field}` },\r\n max: { $max: `$${field}` },\r\n },\r\n });\r\n\r\n const result = await aggregate<MinMaxResult>(Model, pipeline, options);\r\n return result[0] || { min: null, max: null };\r\n}\r\n"]}
|