@classytic/mongokit 1.0.2 → 2.0.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.
Files changed (87) hide show
  1. package/README.md +562 -155
  2. package/package.json +17 -10
  3. package/src/Repository.js +296 -225
  4. package/src/actions/aggregate.js +266 -191
  5. package/src/actions/create.js +47 -47
  6. package/src/actions/delete.js +88 -88
  7. package/src/actions/index.js +11 -11
  8. package/src/actions/read.js +176 -144
  9. package/src/actions/update.js +144 -144
  10. package/src/hooks/lifecycle.js +146 -146
  11. package/src/index.js +71 -60
  12. package/src/pagination/PaginationEngine.js +348 -0
  13. package/src/pagination/utils/cursor.js +119 -0
  14. package/src/pagination/utils/filter.js +42 -0
  15. package/src/pagination/utils/limits.js +82 -0
  16. package/src/pagination/utils/sort.js +101 -0
  17. package/src/plugins/aggregate-helpers.plugin.js +71 -71
  18. package/src/plugins/audit-log.plugin.js +60 -60
  19. package/src/plugins/batch-operations.plugin.js +66 -66
  20. package/src/plugins/field-filter.plugin.js +27 -27
  21. package/src/plugins/index.js +19 -19
  22. package/src/plugins/method-registry.plugin.js +140 -140
  23. package/src/plugins/mongo-operations.plugin.js +317 -313
  24. package/src/plugins/soft-delete.plugin.js +46 -46
  25. package/src/plugins/subdocument.plugin.js +66 -66
  26. package/src/plugins/timestamp.plugin.js +19 -19
  27. package/src/plugins/validation-chain.plugin.js +145 -145
  28. package/src/types.d.ts +87 -0
  29. package/src/utils/error.js +12 -0
  30. package/src/utils/field-selection.js +156 -156
  31. package/src/utils/index.js +12 -12
  32. package/types/Repository.d.ts +95 -0
  33. package/types/Repository.d.ts.map +1 -0
  34. package/types/actions/aggregate.d.ts +112 -0
  35. package/types/actions/aggregate.d.ts.map +1 -0
  36. package/types/actions/create.d.ts +21 -0
  37. package/types/actions/create.d.ts.map +1 -0
  38. package/types/actions/delete.d.ts +37 -0
  39. package/types/actions/delete.d.ts.map +1 -0
  40. package/types/actions/index.d.ts +6 -121
  41. package/types/actions/index.d.ts.map +1 -0
  42. package/types/actions/read.d.ts +135 -0
  43. package/types/actions/read.d.ts.map +1 -0
  44. package/types/actions/update.d.ts +58 -0
  45. package/types/actions/update.d.ts.map +1 -0
  46. package/types/hooks/lifecycle.d.ts +44 -0
  47. package/types/hooks/lifecycle.d.ts.map +1 -0
  48. package/types/index.d.ts +25 -104
  49. package/types/index.d.ts.map +1 -0
  50. package/types/pagination/PaginationEngine.d.ts +386 -0
  51. package/types/pagination/PaginationEngine.d.ts.map +1 -0
  52. package/types/pagination/utils/cursor.d.ts +40 -0
  53. package/types/pagination/utils/cursor.d.ts.map +1 -0
  54. package/types/pagination/utils/filter.d.ts +28 -0
  55. package/types/pagination/utils/filter.d.ts.map +1 -0
  56. package/types/pagination/utils/limits.d.ts +64 -0
  57. package/types/pagination/utils/limits.d.ts.map +1 -0
  58. package/types/pagination/utils/sort.d.ts +41 -0
  59. package/types/pagination/utils/sort.d.ts.map +1 -0
  60. package/types/plugins/aggregate-helpers.plugin.d.ts +6 -0
  61. package/types/plugins/aggregate-helpers.plugin.d.ts.map +1 -0
  62. package/types/plugins/audit-log.plugin.d.ts +6 -0
  63. package/types/plugins/audit-log.plugin.d.ts.map +1 -0
  64. package/types/plugins/batch-operations.plugin.d.ts +6 -0
  65. package/types/plugins/batch-operations.plugin.d.ts.map +1 -0
  66. package/types/plugins/field-filter.plugin.d.ts +6 -0
  67. package/types/plugins/field-filter.plugin.d.ts.map +1 -0
  68. package/types/plugins/index.d.ts +11 -88
  69. package/types/plugins/index.d.ts.map +1 -0
  70. package/types/plugins/method-registry.plugin.d.ts +3 -0
  71. package/types/plugins/method-registry.plugin.d.ts.map +1 -0
  72. package/types/plugins/mongo-operations.plugin.d.ts +4 -0
  73. package/types/plugins/mongo-operations.plugin.d.ts.map +1 -0
  74. package/types/plugins/soft-delete.plugin.d.ts +6 -0
  75. package/types/plugins/soft-delete.plugin.d.ts.map +1 -0
  76. package/types/plugins/subdocument.plugin.d.ts +6 -0
  77. package/types/plugins/subdocument.plugin.d.ts.map +1 -0
  78. package/types/plugins/timestamp.plugin.d.ts +6 -0
  79. package/types/plugins/timestamp.plugin.d.ts.map +1 -0
  80. package/types/plugins/validation-chain.plugin.d.ts +31 -0
  81. package/types/plugins/validation-chain.plugin.d.ts.map +1 -0
  82. package/types/utils/error.d.ts +11 -0
  83. package/types/utils/error.d.ts.map +1 -0
  84. package/types/utils/field-selection.d.ts +9 -0
  85. package/types/utils/field-selection.d.ts.map +1 -0
  86. package/types/utils/index.d.ts +2 -24
  87. package/types/utils/index.d.ts.map +1 -0
@@ -1,156 +1,156 @@
1
- /**
2
- * Field Selection Utilities
3
- *
4
- * Provides explicit, performant field filtering using Mongoose projections.
5
- *
6
- * Philosophy:
7
- * - Explicit is better than implicit
8
- * - Filter at DB level (10x faster than in-memory)
9
- * - Progressive disclosure (show more fields as trust increases)
10
- *
11
- * Usage:
12
- * ```javascript
13
- * // For Mongoose queries (PREFERRED - 90% of cases)
14
- * const projection = getMongooseProjection(request.user, fieldPresets.gymPlans);
15
- * const plans = await GymPlan.find().select(projection).lean();
16
- *
17
- * // For complex data (10% of cases - aggregations, multiple sources)
18
- * const filtered = filterResponseData(complexData, fieldPresets.gymPlans, request.user);
19
- * ```
20
- */
21
-
22
- /**
23
- * Get allowed fields for a user based on their context
24
- *
25
- * @param {Object} user - User object from request.user (or null for public)
26
- * @param {Object} preset - Field preset configuration
27
- * @param {string[]} preset.public - Fields visible to everyone
28
- * @param {string[]} preset.authenticated - Additional fields for authenticated users
29
- * @param {string[]} preset.admin - Additional fields for admins
30
- * @returns {string[]} Array of allowed field names
31
- */
32
- export const getFieldsForUser = (user, preset) => {
33
- if (!preset) {
34
- throw new Error('Field preset is required');
35
- }
36
-
37
- // Start with public fields
38
- let fields = [...(preset.public || [])];
39
-
40
- // Add authenticated fields if user is logged in
41
- if (user) {
42
- fields.push(...(preset.authenticated || []));
43
-
44
- // Add admin fields if user is admin/superadmin
45
- const roles = Array.isArray(user.roles) ? user.roles : (user.roles ? [user.roles] : []);
46
- if (roles.includes('admin') || roles.includes('superadmin')) {
47
- fields.push(...(preset.admin || []));
48
- }
49
- }
50
-
51
- // Remove duplicates
52
- return [...new Set(fields)];
53
- };
54
-
55
- /**
56
- * Get Mongoose projection string for query .select()
57
- *
58
- * @param {Object} user - User object from request.user
59
- * @param {Object} preset - Field preset configuration
60
- * @returns {string} Space-separated field names for Mongoose .select()
61
- *
62
- * @example
63
- * const projection = getMongooseProjection(request.user, fieldPresets.gymPlans);
64
- * const plans = await GymPlan.find({ organizationId }).select(projection).lean();
65
- */
66
- export const getMongooseProjection = (user, preset) => {
67
- const fields = getFieldsForUser(user, preset);
68
- return fields.join(' ');
69
- };
70
-
71
- /**
72
- * Filter response data to include only allowed fields
73
- *
74
- * Use this for complex responses where Mongoose projections aren't applicable:
75
- * - Aggregation pipeline results
76
- * - Data from multiple sources
77
- * - Custom computed fields
78
- *
79
- * For simple DB queries, prefer getMongooseProjection() (10x faster)
80
- *
81
- * @param {Object|Array} data - Data to filter
82
- * @param {Object} preset - Field preset configuration
83
- * @param {Object} user - User object from request.user
84
- * @returns {Object|Array} Filtered data
85
- *
86
- * @example
87
- * const stats = await calculateComplexStats();
88
- * const filtered = filterResponseData(stats, fieldPresets.dashboard, request.user);
89
- * return reply.send(filtered);
90
- */
91
- export const filterResponseData = (data, preset, user = null) => {
92
- const allowedFields = getFieldsForUser(user, preset);
93
-
94
- // Handle arrays
95
- if (Array.isArray(data)) {
96
- return data.map(item => filterObject(item, allowedFields));
97
- }
98
-
99
- // Handle single object
100
- return filterObject(data, allowedFields);
101
- };
102
-
103
- /**
104
- * Filter a single object to include only allowed fields
105
- *
106
- * @private
107
- * @param {Object} obj - Object to filter
108
- * @param {string[]} allowedFields - Array of allowed field names
109
- * @returns {Object} Filtered object
110
- */
111
- const filterObject = (obj, allowedFields) => {
112
- if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
113
- return obj;
114
- }
115
-
116
- const filtered = {};
117
-
118
- for (const field of allowedFields) {
119
- if (field in obj) {
120
- filtered[field] = obj[field];
121
- }
122
- }
123
-
124
- return filtered;
125
- };
126
-
127
- /**
128
- * Helper to create field presets (module-level)
129
- *
130
- * Each module should define its own field preset in its own directory.
131
- * This keeps modules independent and self-contained.
132
- *
133
- * @param {Object} config - Field configuration
134
- * @returns {Object} Field preset
135
- *
136
- * @example
137
- * // In modules/gym-plan/gym-plan.fields.js
138
- * import { createFieldPreset } from '#common/utils/field-selection.js';
139
- *
140
- * export const gymPlanFieldPreset = createFieldPreset({
141
- * public: ['id', 'name', 'price'],
142
- * authenticated: ['features', 'description'],
143
- * admin: ['createdAt', 'updatedAt', 'internalNotes']
144
- * });
145
- *
146
- * // Then in controller:
147
- * import { gymPlanFieldPreset } from './gym-plan.fields.js';
148
- * super(gymPlanRepository, { fieldPreset: gymPlanFieldPreset });
149
- */
150
- export const createFieldPreset = (config) => {
151
- return {
152
- public: config.public || [],
153
- authenticated: config.authenticated || [],
154
- admin: config.admin || [],
155
- };
156
- };
1
+ /**
2
+ * Field Selection Utilities
3
+ *
4
+ * Provides explicit, performant field filtering using Mongoose projections.
5
+ *
6
+ * Philosophy:
7
+ * - Explicit is better than implicit
8
+ * - Filter at DB level (10x faster than in-memory)
9
+ * - Progressive disclosure (show more fields as trust increases)
10
+ *
11
+ * Usage:
12
+ * ```javascript
13
+ * // For Mongoose queries (PREFERRED - 90% of cases)
14
+ * const projection = getMongooseProjection(request.user, fieldPresets.gymPlans);
15
+ * const plans = await GymPlan.find().select(projection).lean();
16
+ *
17
+ * // For complex data (10% of cases - aggregations, multiple sources)
18
+ * const filtered = filterResponseData(complexData, fieldPresets.gymPlans, request.user);
19
+ * ```
20
+ */
21
+
22
+ /**
23
+ * Get allowed fields for a user based on their context
24
+ *
25
+ * @param {Object} user - User object from request.user (or null for public)
26
+ * @param {Object} preset - Field preset configuration
27
+ * @param {string[]} preset.public - Fields visible to everyone
28
+ * @param {string[]} preset.authenticated - Additional fields for authenticated users
29
+ * @param {string[]} preset.admin - Additional fields for admins
30
+ * @returns {string[]} Array of allowed field names
31
+ */
32
+ export const getFieldsForUser = (user, preset) => {
33
+ if (!preset) {
34
+ throw new Error('Field preset is required');
35
+ }
36
+
37
+ // Start with public fields
38
+ let fields = [...(preset.public || [])];
39
+
40
+ // Add authenticated fields if user is logged in
41
+ if (user) {
42
+ fields.push(...(preset.authenticated || []));
43
+
44
+ // Add admin fields if user is admin/superadmin
45
+ const roles = Array.isArray(user.roles) ? user.roles : (user.roles ? [user.roles] : []);
46
+ if (roles.includes('admin') || roles.includes('superadmin')) {
47
+ fields.push(...(preset.admin || []));
48
+ }
49
+ }
50
+
51
+ // Remove duplicates
52
+ return [...new Set(fields)];
53
+ };
54
+
55
+ /**
56
+ * Get Mongoose projection string for query .select()
57
+ *
58
+ * @param {Object} user - User object from request.user
59
+ * @param {Object} preset - Field preset configuration
60
+ * @returns {string} Space-separated field names for Mongoose .select()
61
+ *
62
+ * @example
63
+ * const projection = getMongooseProjection(request.user, fieldPresets.gymPlans);
64
+ * const plans = await GymPlan.find({ organizationId }).select(projection).lean();
65
+ */
66
+ export const getMongooseProjection = (user, preset) => {
67
+ const fields = getFieldsForUser(user, preset);
68
+ return fields.join(' ');
69
+ };
70
+
71
+ /**
72
+ * Filter response data to include only allowed fields
73
+ *
74
+ * Use this for complex responses where Mongoose projections aren't applicable:
75
+ * - Aggregation pipeline results
76
+ * - Data from multiple sources
77
+ * - Custom computed fields
78
+ *
79
+ * For simple DB queries, prefer getMongooseProjection() (10x faster)
80
+ *
81
+ * @param {Object|Array} data - Data to filter
82
+ * @param {Object} preset - Field preset configuration
83
+ * @param {Object} user - User object from request.user
84
+ * @returns {Object|Array} Filtered data
85
+ *
86
+ * @example
87
+ * const stats = await calculateComplexStats();
88
+ * const filtered = filterResponseData(stats, fieldPresets.dashboard, request.user);
89
+ * return reply.send(filtered);
90
+ */
91
+ export const filterResponseData = (data, preset, user = null) => {
92
+ const allowedFields = getFieldsForUser(user, preset);
93
+
94
+ // Handle arrays
95
+ if (Array.isArray(data)) {
96
+ return data.map(item => filterObject(item, allowedFields));
97
+ }
98
+
99
+ // Handle single object
100
+ return filterObject(data, allowedFields);
101
+ };
102
+
103
+ /**
104
+ * Filter a single object to include only allowed fields
105
+ *
106
+ * @private
107
+ * @param {Object} obj - Object to filter
108
+ * @param {string[]} allowedFields - Array of allowed field names
109
+ * @returns {Object} Filtered object
110
+ */
111
+ const filterObject = (obj, allowedFields) => {
112
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
113
+ return obj;
114
+ }
115
+
116
+ const filtered = {};
117
+
118
+ for (const field of allowedFields) {
119
+ if (field in obj) {
120
+ filtered[field] = obj[field];
121
+ }
122
+ }
123
+
124
+ return filtered;
125
+ };
126
+
127
+ /**
128
+ * Helper to create field presets (module-level)
129
+ *
130
+ * Each module should define its own field preset in its own directory.
131
+ * This keeps modules independent and self-contained.
132
+ *
133
+ * @param {Object} config - Field configuration
134
+ * @returns {Object} Field preset
135
+ *
136
+ * @example
137
+ * // In modules/gym-plan/gym-plan.fields.js
138
+ * import { createFieldPreset } from '#common/utils/field-selection.js';
139
+ *
140
+ * export const gymPlanFieldPreset = createFieldPreset({
141
+ * public: ['id', 'name', 'price'],
142
+ * authenticated: ['features', 'description'],
143
+ * admin: ['createdAt', 'updatedAt', 'internalNotes']
144
+ * });
145
+ *
146
+ * // Then in controller:
147
+ * import { gymPlanFieldPreset } from './gym-plan.fields.js';
148
+ * super(gymPlanRepository, { fieldPreset: gymPlanFieldPreset });
149
+ */
150
+ export const createFieldPreset = (config) => {
151
+ return {
152
+ public: config.public || [],
153
+ authenticated: config.authenticated || [],
154
+ admin: config.admin || [],
155
+ };
156
+ };
@@ -1,12 +1,12 @@
1
- /**
2
- * Utility Functions for MongoKit
3
- * Reusable helpers for field selection, filtering, and more
4
- */
5
-
6
- export {
7
- getFieldsForUser,
8
- getMongooseProjection,
9
- filterResponseData,
10
- createFieldPreset,
11
- } from './field-selection.js';
12
-
1
+ /**
2
+ * Utility Functions for MongoKit
3
+ * Reusable helpers for field selection, filtering, and more
4
+ */
5
+
6
+ export {
7
+ getFieldsForUser,
8
+ getMongooseProjection,
9
+ filterResponseData,
10
+ createFieldPreset,
11
+ } from './field-selection.js';
12
+
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @typedef {import('./types.js').OffsetPaginationResult} OffsetPaginationResult
3
+ * @typedef {import('./types.js').KeysetPaginationResult} KeysetPaginationResult
4
+ * @typedef {import('./types.js').AggregatePaginationResult} AggregatePaginationResult
5
+ * @typedef {import('./types.js').ObjectId} ObjectId
6
+ */
7
+ export class Repository {
8
+ constructor(Model: any, plugins?: any[], paginationConfig?: {});
9
+ Model: any;
10
+ model: any;
11
+ _hooks: Map<any, any>;
12
+ _pagination: PaginationEngine;
13
+ use(plugin: any): this;
14
+ on(event: any, listener: any): this;
15
+ emit(event: any, data: any): void;
16
+ create(data: any, options?: {}): Promise<any>;
17
+ createMany(dataArray: any, options?: {}): Promise<any>;
18
+ getById(id: any, options?: {}): Promise<any>;
19
+ getByQuery(query: any, options?: {}): Promise<any>;
20
+ /**
21
+ * Unified pagination - auto-detects offset vs keyset based on params
22
+ *
23
+ * Auto-detection logic:
24
+ * - If params has 'cursor' or 'after' → uses keyset pagination (stream)
25
+ * - If params has 'pagination' or 'page' → uses offset pagination (paginate)
26
+ * - Else → defaults to offset pagination with page=1
27
+ *
28
+ * @param {Object} params - Query and pagination parameters
29
+ * @param {Object} [params.filters] - MongoDB query filters
30
+ * @param {string|Object} [params.sort] - Sort specification
31
+ * @param {string} [params.cursor] - Cursor token for keyset pagination
32
+ * @param {string} [params.after] - Alias for cursor
33
+ * @param {number} [params.page] - Page number for offset pagination
34
+ * @param {Object} [params.pagination] - Pagination config { page, limit }
35
+ * @param {number} [params.limit] - Documents per page
36
+ * @param {string} [params.search] - Full-text search query
37
+ * @param {Object} [options] - Additional options (select, populate, lean, session)
38
+ * @returns {Promise<OffsetPaginationResult|KeysetPaginationResult>} Discriminated union based on method
39
+ *
40
+ * @example
41
+ * // Offset pagination (page-based)
42
+ * await repo.getAll({ page: 1, limit: 50, filters: { status: 'active' } });
43
+ * await repo.getAll({ pagination: { page: 2, limit: 20 } });
44
+ *
45
+ * // Keyset pagination (cursor-based)
46
+ * await repo.getAll({ cursor: 'eyJ2Ij...', limit: 50 });
47
+ * await repo.getAll({ after: 'eyJ2Ij...', sort: { createdAt: -1 } });
48
+ *
49
+ * // Simple query (defaults to page 1)
50
+ * await repo.getAll({ filters: { status: 'active' } });
51
+ */
52
+ getAll(params?: {
53
+ filters?: any;
54
+ sort?: string | any;
55
+ cursor?: string;
56
+ after?: string;
57
+ page?: number;
58
+ pagination?: any;
59
+ limit?: number;
60
+ search?: string;
61
+ }, options?: any): Promise<OffsetPaginationResult | KeysetPaginationResult>;
62
+ getOrCreate(query: any, createData: any, options?: {}): Promise<any>;
63
+ count(query?: {}, options?: {}): Promise<number>;
64
+ exists(query: any, options?: {}): Promise<{
65
+ _id: any;
66
+ }>;
67
+ update(id: any, data: any, options?: {}): Promise<any>;
68
+ delete(id: any, options?: {}): Promise<{
69
+ success: boolean;
70
+ message: string;
71
+ }>;
72
+ aggregate(pipeline: any, options?: {}): Promise<any[]>;
73
+ /**
74
+ * Aggregate pipeline with pagination
75
+ * Best for: Complex queries, grouping, joins
76
+ *
77
+ * @param {Object} options - Aggregate pagination options
78
+ * @returns {Promise<AggregatePaginationResult>}
79
+ */
80
+ aggregatePaginate(options?: any): Promise<AggregatePaginationResult>;
81
+ distinct(field: any, query?: {}, options?: {}): Promise<any>;
82
+ withTransaction(callback: any): Promise<any>;
83
+ _executeQuery(buildQuery: any): Promise<any>;
84
+ _buildContext(operation: any, options: any): Promise<any>;
85
+ _parseSort(sort: any): any;
86
+ _parsePopulate(populate: any): any[];
87
+ _handleError(error: any): any;
88
+ }
89
+ export default Repository;
90
+ export type OffsetPaginationResult = import("./types.js").OffsetPaginationResult;
91
+ export type KeysetPaginationResult = import("./types.js").KeysetPaginationResult;
92
+ export type AggregatePaginationResult = import("./types.js").AggregatePaginationResult;
93
+ export type ObjectId = import("./types.js").ObjectId;
94
+ import { PaginationEngine } from './pagination/PaginationEngine.js';
95
+ //# sourceMappingURL=Repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Repository.d.ts","sourceRoot":"","sources":["../src/Repository.js"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH;IACE,gEAMC;IALC,WAAkB;IAClB,WAA4B;IAC5B,sBAAuB;IACvB,8BAAgE;IAIlE,uBAOC;IAED,oCAMC;IAED,kCAGC;IAED,8CAWC;IAED,uDAWC;IAED,6CAGC;IAED,mDAGC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,gBAvBG;QAAwB,OAAO;QACA,IAAI,GAA3B,MAAM,MAAO;QACG,MAAM,GAAtB,MAAM;QACU,KAAK,GAArB,MAAM;QACU,IAAI,GAApB,MAAM;QACU,UAAU;QACV,KAAK,GAArB,MAAM;QACU,MAAM,GAAtB,MAAM;KACd,kBACU,OAAO,CAAC,sBAAsB,GAAC,sBAAsB,CAAC,CAgElE;IAED,qEAEC;IAED,iDAEC;IAED;;OAEC;IAED,uDAWC;IAED;;;OAWC;IAED,uDAEC;IAED;;;;;;OAMG;IACH,kCAFa,OAAO,CAAC,yBAAyB,CAAC,CAK9C;IAED,6DAEC;IAED,6CAaC;IAED,6CAYC;IAED,0DAUC;IAED,2BAOC;IAED,qCAKC;IAED,8BAUC;CACF;;qCA3RY,OAAO,YAAY,EAAE,sBAAsB;qCAC3C,OAAO,YAAY,EAAE,sBAAsB;wCAC3C,OAAO,YAAY,EAAE,yBAAyB;uBAC9C,OAAO,YAAY,EAAE,QAAQ;iCANT,kCAAkC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Aggregate Actions
3
+ * MongoDB aggregation pipeline operations
4
+ */
5
+ /**
6
+ * @typedef {import('mongoose').Model} Model
7
+ * @typedef {import('mongoose').ClientSession} ClientSession
8
+ */
9
+ /**
10
+ * Execute aggregation pipeline
11
+ *
12
+ * @param {Model} Model - Mongoose model
13
+ * @param {any[]} pipeline - Aggregation pipeline stages
14
+ * @param {Object} [options={}] - Aggregation options
15
+ * @param {ClientSession} [options.session] - MongoDB session
16
+ * @returns {Promise<any[]>} Aggregation results
17
+ */
18
+ export function aggregate(Model: Model, pipeline: any[], options?: {
19
+ session?: ClientSession;
20
+ }): Promise<any[]>;
21
+ /**
22
+ * Aggregate with pagination using native MongoDB $facet
23
+ * WARNING: $facet results must be <16MB. For larger results (limit >1000),
24
+ * consider using Repository.aggregatePaginate() or splitting into separate queries.
25
+ *
26
+ * @param {Model} Model - Mongoose model
27
+ * @param {any[]} pipeline - Aggregation pipeline stages (before pagination)
28
+ * @param {Object} [options={}] - Pagination options
29
+ * @param {number} [options.page=1] - Page number (1-indexed)
30
+ * @param {number} [options.limit=10] - Documents per page
31
+ * @param {ClientSession} [options.session] - MongoDB session
32
+ * @returns {Promise<{docs: any[], total: number, page: number, limit: number, pages: number, hasNext: boolean, hasPrev: boolean}>} Paginated results
33
+ *
34
+ * @example
35
+ * const result = await aggregatePaginate(UserModel, [
36
+ * { $match: { status: 'active' } },
37
+ * { $group: { _id: '$category', count: { $sum: 1 } } }
38
+ * ], { page: 1, limit: 20 });
39
+ */
40
+ export function aggregatePaginate(Model: Model, pipeline: any[], options?: {
41
+ page?: number;
42
+ limit?: number;
43
+ session?: ClientSession;
44
+ }): Promise<{
45
+ docs: any[];
46
+ total: number;
47
+ page: number;
48
+ limit: number;
49
+ pages: number;
50
+ hasNext: boolean;
51
+ hasPrev: boolean;
52
+ }>;
53
+ /**
54
+ * Group documents by field value
55
+ *
56
+ * @param {Model} Model - Mongoose model
57
+ * @param {string} field - Field name to group by
58
+ * @param {Object} [options={}] - Options
59
+ * @param {number} [options.limit] - Maximum groups to return
60
+ * @param {ClientSession} [options.session] - MongoDB session
61
+ * @returns {Promise<Array<{_id: any, count: number}>>} Grouped results
62
+ */
63
+ export function groupBy(Model: Model, field: string, options?: {
64
+ limit?: number;
65
+ session?: ClientSession;
66
+ }): Promise<Array<{
67
+ _id: any;
68
+ count: number;
69
+ }>>;
70
+ /**
71
+ * Count by field values
72
+ */
73
+ export function countBy(Model: any, field: any, query?: {}, options?: {}): Promise<any[]>;
74
+ /**
75
+ * Lookup (join) with another collection
76
+ */
77
+ export function lookup(Model: any, { from, localField, foreignField, as, pipeline, query, options }: {
78
+ from: any;
79
+ localField: any;
80
+ foreignField: any;
81
+ as: any;
82
+ pipeline?: any[];
83
+ query?: {};
84
+ options?: {};
85
+ }): Promise<any[]>;
86
+ /**
87
+ * Unwind array field
88
+ */
89
+ export function unwind(Model: any, field: any, options?: {}): Promise<any[]>;
90
+ /**
91
+ * Facet search (multiple aggregations in one query)
92
+ */
93
+ export function facet(Model: any, facets: any, options?: {}): Promise<any[]>;
94
+ /**
95
+ * Get distinct values
96
+ */
97
+ export function distinct(Model: any, field: any, query?: {}, options?: {}): Promise<any>;
98
+ /**
99
+ * Calculate sum
100
+ */
101
+ export function sum(Model: any, field: any, query?: {}, options?: {}): Promise<any>;
102
+ /**
103
+ * Calculate average
104
+ */
105
+ export function average(Model: any, field: any, query?: {}, options?: {}): Promise<any>;
106
+ /**
107
+ * Min/Max
108
+ */
109
+ export function minMax(Model: any, field: any, query?: {}, options?: {}): Promise<any>;
110
+ export type Model = import("mongoose").Model<any, any, any, any, any, any, any>;
111
+ export type ClientSession = import("mongoose").ClientSession;
112
+ //# sourceMappingURL=aggregate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/actions/aggregate.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AAEH;;;;;;;;GAQG;AACH,iCANW,KAAK,YACL,GAAG,EAAE,YAEb;IAAgC,OAAO,GAA/B,aAAa;CACrB,GAAU,OAAO,CAAC,GAAG,EAAE,CAAC,CAU1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,yCAdW,KAAK,YACL,GAAG,EAAE,YAEb;IAAyB,IAAI,GAArB,MAAM;IACW,KAAK,GAAtB,MAAM;IACkB,OAAO,GAA/B,aAAa;CACrB,GAAU,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAAC,CAwDjI;AAED;;;;;;;;;GASG;AACH,+BAPW,KAAK,SACL,MAAM,YAEd;IAAyB,KAAK,GAAtB,MAAM;IACkB,OAAO,GAA/B,aAAa;CACrB,GAAU,OAAO,CAAC,KAAK,CAAC;IAAC,GAAG,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC,CAarD;AAED;;GAEG;AACH,0FAaC;AAED;;GAEG;AACH;;;;;;;;mBA0BC;AAED;;GAEG;AACH,6EAWC;AAED;;GAEG;AACH,6EAIC;AAED;;GAEG;AACH,yFAEC;AAED;;GAEG;AACH,oFAgBC;AAED;;GAEG;AACH,wFAgBC;AAED;;GAEG;AACH,uFAiBC;;4BAjQY,OAAO,UAAU,EAAE,aAAa"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Create Actions
3
+ * Pure functions for document creation
4
+ */
5
+ /**
6
+ * Create single document
7
+ */
8
+ export function create(Model: any, data: any, options?: {}): Promise<any>;
9
+ /**
10
+ * Create multiple documents
11
+ */
12
+ export function createMany(Model: any, dataArray: any, options?: {}): Promise<any>;
13
+ /**
14
+ * Create with defaults (useful for initialization)
15
+ */
16
+ export function createDefault(Model: any, overrides?: {}, options?: {}): Promise<any>;
17
+ /**
18
+ * Upsert (create or update)
19
+ */
20
+ export function upsert(Model: any, query: any, data: any, options?: {}): Promise<any>;
21
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/actions/create.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,0EAIC;AAED;;GAEG;AACH,mFAKC;AAED;;GAEG;AACH,sFAaC;AAED;;GAEG;AACH,sFAYC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Delete by ID
3
+ */
4
+ export function deleteById(Model: any, id: any, options?: {}): Promise<{
5
+ success: boolean;
6
+ message: string;
7
+ }>;
8
+ /**
9
+ * Delete many documents
10
+ */
11
+ export function deleteMany(Model: any, query: any, options?: {}): Promise<{
12
+ success: boolean;
13
+ count: any;
14
+ message: string;
15
+ }>;
16
+ /**
17
+ * Delete by query
18
+ */
19
+ export function deleteByQuery(Model: any, query: any, options?: {}): Promise<{
20
+ success: boolean;
21
+ message: string;
22
+ }>;
23
+ /**
24
+ * Soft delete (set deleted flag)
25
+ */
26
+ export function softDelete(Model: any, id: any, options?: {}): Promise<{
27
+ success: boolean;
28
+ message: string;
29
+ }>;
30
+ /**
31
+ * Restore soft deleted document
32
+ */
33
+ export function restore(Model: any, id: any, options?: {}): Promise<{
34
+ success: boolean;
35
+ message: string;
36
+ }>;
37
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/actions/delete.js"],"names":[],"mappings":"AAOA;;GAEG;AACH;;;GAQC;AAED;;GAEG;AACH;;;;GAQC;AAED;;GAEG;AACH;;;GAQC;AAED;;GAEG;AACH;;;GAgBC;AAED;;GAEG;AACH;;;GAgBC"}