@classytic/mongokit 1.0.1 → 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 +564 -157
  2. package/package.json +20 -12
  3. package/src/Repository.js +296 -225
  4. package/src/actions/aggregate.js +266 -191
  5. package/src/actions/create.js +59 -58
  6. package/src/actions/delete.js +88 -88
  7. package/src/actions/index.js +11 -11
  8. package/src/actions/read.js +188 -155
  9. package/src/actions/update.js +176 -172
  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 -113
  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 -96
  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
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @typedef {Object} PaginationConfig
3
+ * @property {number} defaultLimit - Default limit value
4
+ * @property {number} maxLimit - Maximum allowed limit
5
+ * @property {number} maxPage - Maximum allowed page number
6
+ */
7
+
8
+ /**
9
+ * Validates and sanitizes limit value
10
+ * Parses strings to numbers and prevents NaN bugs
11
+ *
12
+ * @param {number|string} limit - Requested limit
13
+ * @param {PaginationConfig} config - Pagination configuration
14
+ * @returns {number} Sanitized limit between 1 and maxLimit
15
+ */
16
+ export function validateLimit(limit, config) {
17
+ const parsed = Number(limit);
18
+
19
+ if (!Number.isFinite(parsed) || parsed < 1) {
20
+ return config.defaultLimit || 10;
21
+ }
22
+
23
+ return Math.min(Math.floor(parsed), config.maxLimit);
24
+ }
25
+
26
+ /**
27
+ * Validates and sanitizes page number
28
+ * Parses strings to numbers and prevents NaN bugs
29
+ *
30
+ * @param {number|string} page - Requested page (1-indexed)
31
+ * @param {PaginationConfig} config - Pagination configuration
32
+ * @returns {number} Sanitized page number >= 1
33
+ * @throws {Error} If page exceeds maxPage
34
+ */
35
+ export function validatePage(page, config) {
36
+ const parsed = Number(page);
37
+
38
+ if (!Number.isFinite(parsed) || parsed < 1) {
39
+ return 1;
40
+ }
41
+
42
+ const sanitized = Math.floor(parsed);
43
+
44
+ if (sanitized > config.maxPage) {
45
+ throw new Error(`Page ${sanitized} exceeds maximum ${config.maxPage}`);
46
+ }
47
+
48
+ return sanitized;
49
+ }
50
+
51
+ /**
52
+ * Checks if page number should trigger deep pagination warning
53
+ *
54
+ * @param {number} page - Current page number
55
+ * @param {number} threshold - Warning threshold
56
+ * @returns {boolean} True if warning should be shown
57
+ */
58
+ export function shouldWarnDeepPagination(page, threshold) {
59
+ return page > threshold;
60
+ }
61
+
62
+ /**
63
+ * Calculates number of documents to skip for offset pagination
64
+ *
65
+ * @param {number} page - Page number (1-indexed)
66
+ * @param {number} limit - Documents per page
67
+ * @returns {number} Number of documents to skip
68
+ */
69
+ export function calculateSkip(page, limit) {
70
+ return (page - 1) * limit;
71
+ }
72
+
73
+ /**
74
+ * Calculates total number of pages
75
+ *
76
+ * @param {number} total - Total document count
77
+ * @param {number} limit - Documents per page
78
+ * @returns {number} Total number of pages
79
+ */
80
+ export function calculateTotalPages(total, limit) {
81
+ return Math.ceil(total / limit);
82
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Normalizes sort object to ensure stable key order
3
+ * Primary fields first, _id last (not alphabetical)
4
+ *
5
+ * @param {Record<string, 1|-1>} sort - Sort specification
6
+ * @returns {Record<string, 1|-1>} Normalized sort with stable key order
7
+ */
8
+ export function normalizeSort(sort) {
9
+ /** @type {Record<string, 1|-1>} */
10
+ const normalized = {};
11
+
12
+ Object.keys(sort).forEach(key => {
13
+ if (key !== '_id') normalized[key] = sort[key];
14
+ });
15
+
16
+ if (sort._id !== undefined) {
17
+ normalized._id = sort._id;
18
+ }
19
+
20
+ return normalized;
21
+ }
22
+
23
+ /**
24
+ * Validates and normalizes sort for keyset pagination
25
+ * Auto-adds _id tie-breaker if needed
26
+ * Ensures _id direction matches primary field
27
+ *
28
+ * @param {Record<string, 1|-1>} sort - Sort specification
29
+ * @returns {Record<string, 1|-1>} Validated and normalized sort
30
+ * @throws {Error} If sort is invalid for keyset pagination
31
+ */
32
+ export function validateKeysetSort(sort) {
33
+ const keys = Object.keys(sort);
34
+
35
+ if (keys.length === 1 && keys[0] !== '_id') {
36
+ const field = keys[0];
37
+ const direction = sort[field];
38
+ return normalizeSort({ [field]: direction, _id: direction });
39
+ }
40
+
41
+ if (keys.length === 1 && keys[0] === '_id') {
42
+ return normalizeSort(sort);
43
+ }
44
+
45
+ if (keys.length === 2) {
46
+ if (!keys.includes('_id')) {
47
+ throw new Error('Keyset pagination requires _id as tie-breaker');
48
+ }
49
+
50
+ const primaryField = keys.find(k => k !== '_id');
51
+ const primaryDirection = sort[primaryField];
52
+ const idDirection = sort._id;
53
+
54
+ if (primaryDirection !== idDirection) {
55
+ throw new Error('_id direction must match primary field direction');
56
+ }
57
+
58
+ return normalizeSort(sort);
59
+ }
60
+
61
+ throw new Error('Keyset pagination only supports single field + _id');
62
+ }
63
+
64
+ /**
65
+ * Inverts sort directions (1 becomes -1, -1 becomes 1)
66
+ *
67
+ * @param {Record<string, 1|-1>} sort - Sort specification
68
+ * @returns {Record<string, 1|-1>} Inverted sort
69
+ */
70
+ export function invertSort(sort) {
71
+ /** @type {Record<string, 1|-1>} */
72
+ const inverted = {};
73
+
74
+ Object.keys(sort).forEach(key => {
75
+ inverted[key] = sort[key] === 1 ? -1 : 1;
76
+ });
77
+
78
+ return inverted;
79
+ }
80
+
81
+ /**
82
+ * Extracts primary sort field (first non-_id field)
83
+ *
84
+ * @param {Record<string, 1|-1>} sort - Sort specification
85
+ * @returns {string} Primary field name
86
+ */
87
+ export function getPrimaryField(sort) {
88
+ const keys = Object.keys(sort);
89
+ return keys.find(k => k !== '_id') || '_id';
90
+ }
91
+
92
+ /**
93
+ * Gets sort direction for a specific field
94
+ *
95
+ * @param {Record<string, 1|-1>} sort - Sort specification
96
+ * @param {string} field - Field name
97
+ * @returns {1|-1|undefined} Sort direction
98
+ */
99
+ export function getDirection(sort, field) {
100
+ return sort[field];
101
+ }
@@ -1,71 +1,71 @@
1
- /**
2
- * Aggregate Helpers Plugin
3
- * Adds common aggregation helper methods
4
- */
5
-
6
- export const aggregateHelpersPlugin = () => ({
7
- name: 'aggregate-helpers',
8
-
9
- apply(repo) {
10
- if (!repo.registerMethod) {
11
- throw new Error('aggregateHelpersPlugin requires methodRegistryPlugin');
12
- }
13
-
14
- /**
15
- * Group by field
16
- */
17
- repo.registerMethod('groupBy', async function (field, options = {}) {
18
- const pipeline = [
19
- { $group: { _id: `$${field}`, count: { $sum: 1 } } },
20
- { $sort: { count: -1 } }
21
- ];
22
-
23
- if (options.limit) {
24
- pipeline.push({ $limit: options.limit });
25
- }
26
-
27
- return this.aggregate(pipeline, options);
28
- });
29
-
30
- // Helper: Generic aggregation operation
31
- const aggregateOperation = async function (field, operator, resultKey, query = {}, options = {}) {
32
- const pipeline = [
33
- { $match: query },
34
- { $group: { _id: null, [resultKey]: { [operator]: `$${field}` } } }
35
- ];
36
-
37
- const result = await this.aggregate(pipeline, options);
38
- return result[0]?.[resultKey] || 0;
39
- };
40
-
41
- /**
42
- * Sum field values
43
- */
44
- repo.registerMethod('sum', async function (field, query = {}, options = {}) {
45
- return aggregateOperation.call(this, field, '$sum', 'total', query, options);
46
- });
47
-
48
- /**
49
- * Average field values
50
- */
51
- repo.registerMethod('average', async function (field, query = {}, options = {}) {
52
- return aggregateOperation.call(this, field, '$avg', 'avg', query, options);
53
- });
54
-
55
- /**
56
- * Get minimum value
57
- */
58
- repo.registerMethod('min', async function (field, query = {}, options = {}) {
59
- return aggregateOperation.call(this, field, '$min', 'min', query, options);
60
- });
61
-
62
- /**
63
- * Get maximum value
64
- */
65
- repo.registerMethod('max', async function (field, query = {}, options = {}) {
66
- return aggregateOperation.call(this, field, '$max', 'max', query, options);
67
- });
68
- }
69
- });
70
-
71
- export default aggregateHelpersPlugin;
1
+ /**
2
+ * Aggregate Helpers Plugin
3
+ * Adds common aggregation helper methods
4
+ */
5
+
6
+ export const aggregateHelpersPlugin = () => ({
7
+ name: 'aggregate-helpers',
8
+
9
+ apply(repo) {
10
+ if (!repo.registerMethod) {
11
+ throw new Error('aggregateHelpersPlugin requires methodRegistryPlugin');
12
+ }
13
+
14
+ /**
15
+ * Group by field
16
+ */
17
+ repo.registerMethod('groupBy', async function (field, options = {}) {
18
+ const pipeline = [
19
+ { $group: { _id: `$${field}`, count: { $sum: 1 } } },
20
+ { $sort: { count: -1 } }
21
+ ];
22
+
23
+ if (options.limit) {
24
+ pipeline.push(/** @type {any} */({ $limit: options.limit }));
25
+ }
26
+
27
+ return this.aggregate(pipeline, options);
28
+ });
29
+
30
+ // Helper: Generic aggregation operation
31
+ const aggregateOperation = async function (field, operator, resultKey, query = {}, options = {}) {
32
+ const pipeline = [
33
+ { $match: query },
34
+ { $group: { _id: null, [resultKey]: { [operator]: `$${field}` } } }
35
+ ];
36
+
37
+ const result = await this.aggregate(pipeline, options);
38
+ return result[0]?.[resultKey] || 0;
39
+ };
40
+
41
+ /**
42
+ * Sum field values
43
+ */
44
+ repo.registerMethod('sum', async function (field, query = {}, options = {}) {
45
+ return aggregateOperation.call(this, field, '$sum', 'total', query, options);
46
+ });
47
+
48
+ /**
49
+ * Average field values
50
+ */
51
+ repo.registerMethod('average', async function (field, query = {}, options = {}) {
52
+ return aggregateOperation.call(this, field, '$avg', 'avg', query, options);
53
+ });
54
+
55
+ /**
56
+ * Get minimum value
57
+ */
58
+ repo.registerMethod('min', async function (field, query = {}, options = {}) {
59
+ return aggregateOperation.call(this, field, '$min', 'min', query, options);
60
+ });
61
+
62
+ /**
63
+ * Get maximum value
64
+ */
65
+ repo.registerMethod('max', async function (field, query = {}, options = {}) {
66
+ return aggregateOperation.call(this, field, '$max', 'max', query, options);
67
+ });
68
+ }
69
+ });
70
+
71
+ export default aggregateHelpersPlugin;
@@ -1,60 +1,60 @@
1
- export const auditLogPlugin = (logger) => ({
2
- name: 'auditLog',
3
-
4
- apply(repo) {
5
- repo.on('after:create', ({ context, result }) => {
6
- logger?.info?.('Document created', {
7
- model: context.model || repo.model,
8
- id: result._id,
9
- userId: context.user?._id || context.user?.id,
10
- organizationId: context.organizationId,
11
- });
12
- });
13
-
14
- repo.on('after:update', ({ context, result }) => {
15
- logger?.info?.('Document updated', {
16
- model: context.model || repo.model,
17
- id: context.id || result._id,
18
- userId: context.user?._id || context.user?.id,
19
- organizationId: context.organizationId,
20
- });
21
- });
22
-
23
- repo.on('after:delete', ({ context, result }) => {
24
- logger?.info?.('Document deleted', {
25
- model: context.model || repo.model,
26
- id: context.id,
27
- userId: context.user?._id || context.user?.id,
28
- organizationId: context.organizationId,
29
- });
30
- });
31
-
32
- repo.on('error:create', ({ context, error }) => {
33
- logger?.error?.('Create failed', {
34
- model: context.model || repo.model,
35
- error: error.message,
36
- userId: context.user?._id || context.user?.id,
37
- });
38
- });
39
-
40
- repo.on('error:update', ({ context, error }) => {
41
- logger?.error?.('Update failed', {
42
- model: context.model || repo.model,
43
- id: context.id,
44
- error: error.message,
45
- userId: context.user?._id || context.user?.id,
46
- });
47
- });
48
-
49
- repo.on('error:delete', ({ context, error }) => {
50
- logger?.error?.('Delete failed', {
51
- model: context.model || repo.model,
52
- id: context.id,
53
- error: error.message,
54
- userId: context.user?._id || context.user?.id,
55
- });
56
- });
57
- },
58
- });
59
-
60
- export default auditLogPlugin;
1
+ export const auditLogPlugin = (logger) => ({
2
+ name: 'auditLog',
3
+
4
+ apply(repo) {
5
+ repo.on('after:create', ({ context, result }) => {
6
+ logger?.info?.('Document created', {
7
+ model: context.model || repo.model,
8
+ id: result._id,
9
+ userId: context.user?._id || context.user?.id,
10
+ organizationId: context.organizationId,
11
+ });
12
+ });
13
+
14
+ repo.on('after:update', ({ context, result }) => {
15
+ logger?.info?.('Document updated', {
16
+ model: context.model || repo.model,
17
+ id: context.id || result._id,
18
+ userId: context.user?._id || context.user?.id,
19
+ organizationId: context.organizationId,
20
+ });
21
+ });
22
+
23
+ repo.on('after:delete', ({ context, result }) => {
24
+ logger?.info?.('Document deleted', {
25
+ model: context.model || repo.model,
26
+ id: context.id,
27
+ userId: context.user?._id || context.user?.id,
28
+ organizationId: context.organizationId,
29
+ });
30
+ });
31
+
32
+ repo.on('error:create', ({ context, error }) => {
33
+ logger?.error?.('Create failed', {
34
+ model: context.model || repo.model,
35
+ error: error.message,
36
+ userId: context.user?._id || context.user?.id,
37
+ });
38
+ });
39
+
40
+ repo.on('error:update', ({ context, error }) => {
41
+ logger?.error?.('Update failed', {
42
+ model: context.model || repo.model,
43
+ id: context.id,
44
+ error: error.message,
45
+ userId: context.user?._id || context.user?.id,
46
+ });
47
+ });
48
+
49
+ repo.on('error:delete', ({ context, error }) => {
50
+ logger?.error?.('Delete failed', {
51
+ model: context.model || repo.model,
52
+ id: context.id,
53
+ error: error.message,
54
+ userId: context.user?._id || context.user?.id,
55
+ });
56
+ });
57
+ },
58
+ });
59
+
60
+ export default auditLogPlugin;
@@ -1,66 +1,66 @@
1
- /**
2
- * Batch Operations Plugin
3
- * Adds bulk update/delete operations with proper event emission
4
- */
5
-
6
- export const batchOperationsPlugin = () => ({
7
- name: 'batch-operations',
8
-
9
- apply(repo) {
10
- if (!repo.registerMethod) {
11
- throw new Error('batchOperationsPlugin requires methodRegistryPlugin');
12
- }
13
-
14
- /**
15
- * Update multiple documents
16
- * @param {Object} query - MongoDB query to match documents
17
- * @param {Object} data - Update data
18
- * @param {Object} options - Additional options (session, context)
19
- * @returns {Promise<Object>} MongoDB update result
20
- */
21
- repo.registerMethod('updateMany', async function (query, data, options = {}) {
22
- const context = await this._buildContext('updateMany', { query, data, options });
23
-
24
- try {
25
- this.emit('before:updateMany', context);
26
-
27
- const result = await this.Model.updateMany(query, data, {
28
- runValidators: true,
29
- session: options.session,
30
- }).exec();
31
-
32
- this.emit('after:updateMany', { context, result });
33
- return result;
34
- } catch (error) {
35
- this.emit('error:updateMany', { context, error });
36
- throw this._handleError(error);
37
- }
38
- });
39
-
40
- /**
41
- * Delete multiple documents
42
- * @param {Object} query - MongoDB query to match documents
43
- * @param {Object} options - Additional options (session, context)
44
- * @returns {Promise<Object>} MongoDB delete result
45
- */
46
- repo.registerMethod('deleteMany', async function (query, options = {}) {
47
- const context = await this._buildContext('deleteMany', { query, options });
48
-
49
- try {
50
- this.emit('before:deleteMany', context);
51
-
52
- const result = await this.Model.deleteMany(query, {
53
- session: options.session,
54
- }).exec();
55
-
56
- this.emit('after:deleteMany', { context, result });
57
- return result;
58
- } catch (error) {
59
- this.emit('error:deleteMany', { context, error });
60
- throw this._handleError(error);
61
- }
62
- });
63
- }
64
- });
65
-
66
- export default batchOperationsPlugin;
1
+ /**
2
+ * Batch Operations Plugin
3
+ * Adds bulk update/delete operations with proper event emission
4
+ */
5
+
6
+ export const batchOperationsPlugin = () => ({
7
+ name: 'batch-operations',
8
+
9
+ apply(repo) {
10
+ if (!repo.registerMethod) {
11
+ throw new Error('batchOperationsPlugin requires methodRegistryPlugin');
12
+ }
13
+
14
+ /**
15
+ * Update multiple documents
16
+ * @param {Object} query - MongoDB query to match documents
17
+ * @param {Object} data - Update data
18
+ * @param {Object} options - Additional options (session, context)
19
+ * @returns {Promise<Object>} MongoDB update result
20
+ */
21
+ repo.registerMethod('updateMany', async function (query, data, options = {}) {
22
+ const context = await this._buildContext('updateMany', { query, data, options });
23
+
24
+ try {
25
+ this.emit('before:updateMany', context);
26
+
27
+ const result = await this.Model.updateMany(query, data, {
28
+ runValidators: true,
29
+ session: options.session,
30
+ }).exec();
31
+
32
+ this.emit('after:updateMany', { context, result });
33
+ return result;
34
+ } catch (error) {
35
+ this.emit('error:updateMany', { context, error });
36
+ throw this._handleError(error);
37
+ }
38
+ });
39
+
40
+ /**
41
+ * Delete multiple documents
42
+ * @param {Object} query - MongoDB query to match documents
43
+ * @param {Object} options - Additional options (session, context)
44
+ * @returns {Promise<Object>} MongoDB delete result
45
+ */
46
+ repo.registerMethod('deleteMany', async function (query, options = {}) {
47
+ const context = await this._buildContext('deleteMany', { query, options });
48
+
49
+ try {
50
+ this.emit('before:deleteMany', context);
51
+
52
+ const result = await this.Model.deleteMany(query, {
53
+ session: options.session,
54
+ }).exec();
55
+
56
+ this.emit('after:deleteMany', { context, result });
57
+ return result;
58
+ } catch (error) {
59
+ this.emit('error:deleteMany', { context, error });
60
+ throw this._handleError(error);
61
+ }
62
+ });
63
+ }
64
+ });
65
+
66
+ export default batchOperationsPlugin;
@@ -1,27 +1,27 @@
1
- import { getFieldsForUser } from '../utils/field-selection.js';
2
-
3
- export const fieldFilterPlugin = (fieldPreset) => ({
4
- name: 'fieldFilter',
5
-
6
- apply(repo) {
7
- const applyFieldFiltering = (context) => {
8
- if (!fieldPreset) return;
9
-
10
- const user = context.context?.user || context.user;
11
- const fields = getFieldsForUser(user, fieldPreset);
12
- const presetSelect = fields.join(' ');
13
-
14
- if (context.select) {
15
- context.select = `${presetSelect} ${context.select}`;
16
- } else {
17
- context.select = presetSelect;
18
- }
19
- };
20
-
21
- repo.on('before:getAll', applyFieldFiltering);
22
- repo.on('before:getById', applyFieldFiltering);
23
- repo.on('before:getByQuery', applyFieldFiltering);
24
- },
25
- });
26
-
27
- export default fieldFilterPlugin;
1
+ import { getFieldsForUser } from '../utils/field-selection.js';
2
+
3
+ export const fieldFilterPlugin = (fieldPreset) => ({
4
+ name: 'fieldFilter',
5
+
6
+ apply(repo) {
7
+ const applyFieldFiltering = (context) => {
8
+ if (!fieldPreset) return;
9
+
10
+ const user = context.context?.user || context.user;
11
+ const fields = getFieldsForUser(user, fieldPreset);
12
+ const presetSelect = fields.join(' ');
13
+
14
+ if (context.select) {
15
+ context.select = `${presetSelect} ${context.select}`;
16
+ } else {
17
+ context.select = presetSelect;
18
+ }
19
+ };
20
+
21
+ repo.on('before:getAll', applyFieldFiltering);
22
+ repo.on('before:getById', applyFieldFiltering);
23
+ repo.on('before:getByQuery', applyFieldFiltering);
24
+ },
25
+ });
26
+
27
+ export default fieldFilterPlugin;
@@ -1,19 +1,19 @@
1
- // Core plugins
2
- export { fieldFilterPlugin } from './field-filter.plugin.js';
3
- export { timestampPlugin } from './timestamp.plugin.js';
4
- export { auditLogPlugin } from './audit-log.plugin.js';
5
- export { softDeletePlugin } from './soft-delete.plugin.js';
6
- export { methodRegistryPlugin } from './method-registry.plugin.js';
7
- export {
8
- validationChainPlugin,
9
- blockIf,
10
- requireField,
11
- autoInject,
12
- immutableField,
13
- uniqueField,
14
- } from './validation-chain.plugin.js';
15
- export { mongoOperationsPlugin } from './mongo-operations.plugin.js';
16
- export { batchOperationsPlugin } from './batch-operations.plugin.js';
17
- export { aggregateHelpersPlugin } from './aggregate-helpers.plugin.js';
18
- export { subdocumentPlugin } from './subdocument.plugin.js';
19
-
1
+ // Core plugins
2
+ export { fieldFilterPlugin } from './field-filter.plugin.js';
3
+ export { timestampPlugin } from './timestamp.plugin.js';
4
+ export { auditLogPlugin } from './audit-log.plugin.js';
5
+ export { softDeletePlugin } from './soft-delete.plugin.js';
6
+ export { methodRegistryPlugin } from './method-registry.plugin.js';
7
+ export {
8
+ validationChainPlugin,
9
+ blockIf,
10
+ requireField,
11
+ autoInject,
12
+ immutableField,
13
+ uniqueField,
14
+ } from './validation-chain.plugin.js';
15
+ export { mongoOperationsPlugin } from './mongo-operations.plugin.js';
16
+ export { batchOperationsPlugin } from './batch-operations.plugin.js';
17
+ export { aggregateHelpersPlugin } from './aggregate-helpers.plugin.js';
18
+ export { subdocumentPlugin } from './subdocument.plugin.js';
19
+