@opra/mongodb 1.26.2 → 1.26.4
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 +24 -1
- package/adapter/mongo-adapter.d.ts +45 -0
- package/adapter/mongo-adapter.js +23 -0
- package/adapter/mongo-patch-generator.d.ts +12 -0
- package/adapter/mongo-patch-generator.js +22 -10
- package/adapter/prepare-filter.d.ts +4 -6
- package/adapter/prepare-filter.js +4 -6
- package/adapter/prepare-key-values.d.ts +9 -0
- package/adapter/prepare-key-values.js +9 -0
- package/adapter/prepare-projection.d.ts +8 -0
- package/adapter/prepare-projection.js +13 -5
- package/adapter/prepare-sort.d.ts +6 -0
- package/adapter/prepare-sort.js +6 -0
- package/package.json +4 -4
- package/services/mongo-collection-service.d.ts +133 -84
- package/services/mongo-collection-service.js +36 -38
- package/services/mongo-entity-service.d.ts +71 -23
- package/services/mongo-entity-service.js +39 -40
- package/services/mongo-nested-service.d.ts +136 -87
- package/services/mongo-nested-service.js +62 -70
- package/services/mongo-service.d.ts +60 -34
- package/services/mongo-service.js +10 -15
- package/services/mongo-singleton-service.d.ts +49 -46
- package/services/mongo-singleton-service.js +25 -28
- package/types.d.ts +9 -3
package/README.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
1
|
# @opra/mongodb
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[![NPM Version][npm-image]][npm-url]
|
|
4
|
+
[![NPM Downloads][downloads-image]][downloads-url]
|
|
5
|
+
[![CI Tests][ci-test-image]][ci-test-url]
|
|
6
|
+
[![Test Coverage][coveralls-image]][coveralls-url]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Support
|
|
10
|
+
You can report bugs and discuss features on the [GitHub issues](https://github.com/panates/opra/issues) page.
|
|
11
|
+
|
|
12
|
+
## Node Compatibility
|
|
13
|
+
- node >= 20.x
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## License
|
|
17
|
+
Available under [MIT](LICENSE) license.
|
|
18
|
+
|
|
19
|
+
[npm-image]: https://img.shields.io/npm/v/@opra/mongodb
|
|
20
|
+
[npm-url]: https://npmjs.org/package/@opra/mongodb
|
|
21
|
+
[downloads-image]: https://img.shields.io/npm/dm/@opra/mongodb.svg
|
|
22
|
+
[downloads-url]: https://npmjs.org/package/@opra/mongodb
|
|
23
|
+
[ci-test-image]: https://github.com/panates/opra/actions/workflows/test.yml/badge.svg
|
|
24
|
+
[ci-test-url]: https://github.com/panates/opra/actions/workflows/test.yml
|
|
25
|
+
[coveralls-image]: https://coveralls.io/repos/github/panates/opra/badge.svg?branch=main
|
|
26
|
+
[coveralls-url]: https://coveralls.io/github/panates/opra?branch=main
|
|
@@ -5,18 +5,63 @@ import _prepareFilter from './prepare-filter.js';
|
|
|
5
5
|
import _prepareKeyValues from './prepare-key-values.js';
|
|
6
6
|
import _prepareProjection from './prepare-projection.js';
|
|
7
7
|
import _prepareSort from './prepare-sort.js';
|
|
8
|
+
/**
|
|
9
|
+
* MongoAdapter namespace provides types and utility functions for integrating MongoDB with Opra.
|
|
10
|
+
*/
|
|
8
11
|
export declare namespace MongoAdapter {
|
|
12
|
+
/**
|
|
13
|
+
* Represents any type of identifier that can be used in MongoDB.
|
|
14
|
+
*/
|
|
9
15
|
type AnyId = string | number | ObjectId;
|
|
16
|
+
/**
|
|
17
|
+
* Represents the input for a filter, which can be an Opra filter expression,
|
|
18
|
+
* a MongoDB filter object, a string, or undefined.
|
|
19
|
+
*/
|
|
10
20
|
type FilterInput<T = any> = OpraFilter.Expression | mongodb.Filter<T> | string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Prepares the given filter input into a MongoDB filter expression.
|
|
23
|
+
*/
|
|
11
24
|
const prepareFilter: typeof _prepareFilter;
|
|
25
|
+
/**
|
|
26
|
+
* Prepares the given key values into a MongoDB compatible format.
|
|
27
|
+
*/
|
|
12
28
|
const prepareKeyValues: typeof _prepareKeyValues;
|
|
29
|
+
/**
|
|
30
|
+
* Prepares the given projection into a MongoDB compatible format.
|
|
31
|
+
*/
|
|
13
32
|
const prepareProjection: typeof _prepareProjection;
|
|
33
|
+
/**
|
|
34
|
+
* Prepares the given sort into a MongoDB compatible format.
|
|
35
|
+
*/
|
|
14
36
|
const prepareSort: typeof _prepareSort;
|
|
37
|
+
/**
|
|
38
|
+
* Represents a request that has been transformed for MongoDB operations.
|
|
39
|
+
*/
|
|
15
40
|
interface TransformedRequest {
|
|
41
|
+
/**
|
|
42
|
+
* The operation method name.
|
|
43
|
+
*/
|
|
16
44
|
method: 'create' | 'delete' | 'deleteMany' | 'get' | 'findMany' | 'replace' | 'update' | 'updateMany';
|
|
45
|
+
/**
|
|
46
|
+
* The primary key for the operation, if applicable.
|
|
47
|
+
*/
|
|
17
48
|
key?: any;
|
|
49
|
+
/**
|
|
50
|
+
* The data object for create or update operations.
|
|
51
|
+
*/
|
|
18
52
|
data?: any;
|
|
53
|
+
/**
|
|
54
|
+
* Additional options for the MongoDB operation.
|
|
55
|
+
*/
|
|
19
56
|
options: any;
|
|
20
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Parses an execution context and transforms it into a MongoDB-compatible request.
|
|
60
|
+
*
|
|
61
|
+
* @param context - The execution context to parse.
|
|
62
|
+
* @returns A promise that resolves to the transformed request.
|
|
63
|
+
* @throws {@link TypeError} If the context transport is not 'http'.
|
|
64
|
+
* @throws {@link Error} If the operation is not compatible with MongoDB Adapter.
|
|
65
|
+
*/
|
|
21
66
|
function parseRequest(context: ExecutionContext): Promise<TransformedRequest>;
|
|
22
67
|
}
|
package/adapter/mongo-adapter.js
CHANGED
|
@@ -2,12 +2,35 @@ import _prepareFilter from './prepare-filter.js';
|
|
|
2
2
|
import _prepareKeyValues from './prepare-key-values.js';
|
|
3
3
|
import _prepareProjection from './prepare-projection.js';
|
|
4
4
|
import _prepareSort from './prepare-sort.js';
|
|
5
|
+
/**
|
|
6
|
+
* MongoAdapter namespace provides types and utility functions for integrating MongoDB with Opra.
|
|
7
|
+
*/
|
|
5
8
|
export var MongoAdapter;
|
|
6
9
|
(function (MongoAdapter) {
|
|
10
|
+
/**
|
|
11
|
+
* Prepares the given filter input into a MongoDB filter expression.
|
|
12
|
+
*/
|
|
7
13
|
MongoAdapter.prepareFilter = _prepareFilter;
|
|
14
|
+
/**
|
|
15
|
+
* Prepares the given key values into a MongoDB compatible format.
|
|
16
|
+
*/
|
|
8
17
|
MongoAdapter.prepareKeyValues = _prepareKeyValues;
|
|
18
|
+
/**
|
|
19
|
+
* Prepares the given projection into a MongoDB compatible format.
|
|
20
|
+
*/
|
|
9
21
|
MongoAdapter.prepareProjection = _prepareProjection;
|
|
22
|
+
/**
|
|
23
|
+
* Prepares the given sort into a MongoDB compatible format.
|
|
24
|
+
*/
|
|
10
25
|
MongoAdapter.prepareSort = _prepareSort;
|
|
26
|
+
/**
|
|
27
|
+
* Parses an execution context and transforms it into a MongoDB-compatible request.
|
|
28
|
+
*
|
|
29
|
+
* @param context - The execution context to parse.
|
|
30
|
+
* @returns A promise that resolves to the transformed request.
|
|
31
|
+
* @throws {@link TypeError} If the context transport is not 'http'.
|
|
32
|
+
* @throws {@link Error} If the operation is not compatible with MongoDB Adapter.
|
|
33
|
+
*/
|
|
11
34
|
async function parseRequest(context) {
|
|
12
35
|
if (context.transport !== 'http') {
|
|
13
36
|
throw new TypeError('MongoAdapter can parse only HttpContext');
|
|
@@ -9,7 +9,19 @@ interface Context {
|
|
|
9
9
|
arrayFilters?: Record<string, any>[];
|
|
10
10
|
initArrayFields?: string[];
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* MongoPatchGenerator is responsible for generating MongoDB update patches from DTO objects.
|
|
14
|
+
* It handles nested objects, array operations ($push, $pull), and field unsetting.
|
|
15
|
+
*/
|
|
12
16
|
export declare class MongoPatchGenerator {
|
|
17
|
+
/**
|
|
18
|
+
* Generates a MongoDB update patch for the given data type and document.
|
|
19
|
+
*
|
|
20
|
+
* @param dataType - The data type of the entity being updated.
|
|
21
|
+
* @param doc - The patch DTO containing the updates.
|
|
22
|
+
* @param options - Optional configuration for patch generation.
|
|
23
|
+
* @returns An object containing the MongoDB update filter, array filters, and any array fields to initialize.
|
|
24
|
+
*/
|
|
13
25
|
generatePatch<T extends object>(dataType: ComplexType, doc: PatchDTO<T>, options?: MongoPatchGenerator.Options): {
|
|
14
26
|
update: UpdateFilter<T>;
|
|
15
27
|
arrayFilters?: Record<string, any>[];
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { ComplexType } from '@opra/common';
|
|
2
2
|
const FIELD_NAME_PATTERN = /^([-><*:])?(.+)$/;
|
|
3
|
+
/**
|
|
4
|
+
* MongoPatchGenerator is responsible for generating MongoDB update patches from DTO objects.
|
|
5
|
+
* It handles nested objects, array operations ($push, $pull), and field unsetting.
|
|
6
|
+
*/
|
|
3
7
|
export class MongoPatchGenerator {
|
|
8
|
+
/**
|
|
9
|
+
* Generates a MongoDB update patch for the given data type and document.
|
|
10
|
+
*
|
|
11
|
+
* @param dataType - The data type of the entity being updated.
|
|
12
|
+
* @param doc - The patch DTO containing the updates.
|
|
13
|
+
* @param options - Optional configuration for patch generation.
|
|
14
|
+
* @returns An object containing the MongoDB update filter, array filters, and any array fields to initialize.
|
|
15
|
+
*/
|
|
4
16
|
generatePatch(dataType, doc, options) {
|
|
5
17
|
const ctx = {};
|
|
6
18
|
this._processComplexType(ctx, dataType, options?.currentPath || '', doc, options?.scope);
|
|
@@ -49,9 +61,9 @@ export class MongoPatchGenerator {
|
|
|
49
61
|
field = dataType.findField(key, scope);
|
|
50
62
|
if (field && !field.inScope(scope))
|
|
51
63
|
continue;
|
|
52
|
-
|
|
64
|
+
/* Field not found */
|
|
53
65
|
if (!field) {
|
|
54
|
-
|
|
66
|
+
/* Additional fields will be updated */
|
|
55
67
|
if (dataType.additionalFields) {
|
|
56
68
|
if (value === null) {
|
|
57
69
|
ctx.$unset = ctx.$unset || {};
|
|
@@ -61,7 +73,7 @@ export class MongoPatchGenerator {
|
|
|
61
73
|
else {
|
|
62
74
|
ctx.$set = ctx.$set || {};
|
|
63
75
|
if (dataType.additionalFields instanceof ComplexType) {
|
|
64
|
-
|
|
76
|
+
/* Process nested object */
|
|
65
77
|
if (this._processComplexType(ctx, dataType.additionalFields, pathDot + key, value, scope)) {
|
|
66
78
|
result = true;
|
|
67
79
|
}
|
|
@@ -73,7 +85,7 @@ export class MongoPatchGenerator {
|
|
|
73
85
|
}
|
|
74
86
|
continue;
|
|
75
87
|
}
|
|
76
|
-
|
|
88
|
+
/* Unset field value if null */
|
|
77
89
|
if (value === null) {
|
|
78
90
|
ctx.$unset = ctx.$unset || {};
|
|
79
91
|
ctx.$unset[pathDot + field.name] = 1;
|
|
@@ -92,19 +104,19 @@ export class MongoPatchGenerator {
|
|
|
92
104
|
keyField = field.keyField || field.type.keyField;
|
|
93
105
|
if (keyField) {
|
|
94
106
|
for (let v of value) {
|
|
95
|
-
|
|
107
|
+
/* Increase arrayIndex and determine a new name for array filter */
|
|
96
108
|
arrayFilterName = 'f' + String(++arrayIndex);
|
|
97
|
-
|
|
109
|
+
/* Extract key value from object */
|
|
98
110
|
keyValue = v[keyField];
|
|
99
111
|
if (keyValue == null)
|
|
100
112
|
continue;
|
|
101
113
|
v = { ...v };
|
|
102
|
-
|
|
114
|
+
/* Remove key field from object */
|
|
103
115
|
delete v[keyField];
|
|
104
|
-
|
|
116
|
+
/* Process each object in array */
|
|
105
117
|
if (this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v, scope)) {
|
|
106
118
|
result = true;
|
|
107
|
-
|
|
119
|
+
/* Add array filter */
|
|
108
120
|
ctx.arrayFilters = ctx.arrayFilters || [];
|
|
109
121
|
ctx.arrayFilters.unshift({
|
|
110
122
|
[`${arrayFilterName}.${keyField}`]: keyValue,
|
|
@@ -118,7 +130,7 @@ export class MongoPatchGenerator {
|
|
|
118
130
|
else {
|
|
119
131
|
if (!(typeof value === 'object'))
|
|
120
132
|
continue;
|
|
121
|
-
|
|
133
|
+
/* Process nested object */
|
|
122
134
|
if (this._processComplexType(ctx, field.type, pathDot + field.name, value, scope)) {
|
|
123
135
|
result = true;
|
|
124
136
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import mongodb from 'mongodb';
|
|
2
2
|
import type { MongoAdapter } from './mongo-adapter.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Prepares the MongoDB filter based on the provided filters and options.
|
|
5
5
|
*
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
* @returns {mongodb.Filter<any>} - The prepared MongoDB filter.
|
|
6
|
+
* @param filters - The filter(s) to be applied. Can be a single filter or an array of filters.
|
|
7
|
+
* @param options - Additional options.
|
|
8
|
+
* @returns The prepared MongoDB filter, or `undefined` if no filters are provided.
|
|
11
9
|
*/
|
|
12
10
|
export default function prepareFilter<T = any>(filters: MongoAdapter.FilterInput<T> | MongoAdapter.FilterInput<T>[], options?: {
|
|
13
11
|
fieldPrefix?: string;
|
|
@@ -10,13 +10,11 @@ const opMap = {
|
|
|
10
10
|
'!in': '$nin',
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Prepares the MongoDB filter based on the provided filters and options.
|
|
14
14
|
*
|
|
15
|
-
* @param
|
|
16
|
-
* @param
|
|
17
|
-
* @
|
|
18
|
-
*
|
|
19
|
-
* @returns {mongodb.Filter<any>} - The prepared MongoDB filter.
|
|
15
|
+
* @param filters - The filter(s) to be applied. Can be a single filter or an array of filters.
|
|
16
|
+
* @param options - Additional options.
|
|
17
|
+
* @returns The prepared MongoDB filter, or `undefined` if no filters are provided.
|
|
20
18
|
*/
|
|
21
19
|
export default function prepareFilter(filters, options) {
|
|
22
20
|
const filtersArray = Array.isArray(filters) ? filters : [filters];
|
|
@@ -1 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepares the MongoDB primary key query object from the given key values.
|
|
3
|
+
*
|
|
4
|
+
* @param keyValue - The value of the primary key, or an object containing multiple key values.
|
|
5
|
+
* @param primaryKey - An optional array of field names that form the primary key. Defaults to ['_id'].
|
|
6
|
+
* @returns A record object representing the MongoDB primary key query.
|
|
7
|
+
* @throws {@link TypeError} If a composite key is required but an object is not provided.
|
|
8
|
+
* @throws {@link Error} If a required key field is missing in the input object.
|
|
9
|
+
*/
|
|
1
10
|
export default function prepareKeyValues(keyValue: any, primaryKey?: string[]): Record<string, any>;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { isPlainObject } from '@jsopen/objects';
|
|
2
2
|
const defaultPrimaryKey = ['_id'];
|
|
3
|
+
/**
|
|
4
|
+
* Prepares the MongoDB primary key query object from the given key values.
|
|
5
|
+
*
|
|
6
|
+
* @param keyValue - The value of the primary key, or an object containing multiple key values.
|
|
7
|
+
* @param primaryKey - An optional array of field names that form the primary key. Defaults to ['_id'].
|
|
8
|
+
* @returns A record object representing the MongoDB primary key query.
|
|
9
|
+
* @throws {@link TypeError} If a composite key is required but an object is not provided.
|
|
10
|
+
* @throws {@link Error} If a required key field is missing in the input object.
|
|
11
|
+
*/
|
|
3
12
|
export default function prepareKeyValues(keyValue, primaryKey) {
|
|
4
13
|
primaryKey = primaryKey || defaultPrimaryKey;
|
|
5
14
|
const b = isPlainObject(keyValue);
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { ComplexType, FieldsProjection } from '@opra/common';
|
|
2
2
|
import mongodb, { type Document } from 'mongodb';
|
|
3
|
+
/**
|
|
4
|
+
* Prepares the MongoDB projection object based on the data type and requested projection.
|
|
5
|
+
*
|
|
6
|
+
* @param dataType - The data type of the entity.
|
|
7
|
+
* @param projection - The requested projection (string, array of strings, Document, or '*').
|
|
8
|
+
* @param scope - Optional scope for field visibility.
|
|
9
|
+
* @returns The prepared MongoDB projection document, or `undefined`.
|
|
10
|
+
*/
|
|
3
11
|
export default function prepareProjection(dataType: ComplexType, projection?: string | string[] | Document | '*', scope?: string): mongodb.Document | undefined;
|
|
4
12
|
export declare function prepare(dataType: ComplexType, target: mongodb.Document, projection?: FieldsProjection, scope?: string): void;
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { ComplexType, parseFieldsProjection, } from '@opra/common';
|
|
2
|
+
/**
|
|
3
|
+
* Prepares the MongoDB projection object based on the data type and requested projection.
|
|
4
|
+
*
|
|
5
|
+
* @param dataType - The data type of the entity.
|
|
6
|
+
* @param projection - The requested projection (string, array of strings, Document, or '*').
|
|
7
|
+
* @param scope - Optional scope for field visibility.
|
|
8
|
+
* @returns The prepared MongoDB projection document, or `undefined`.
|
|
9
|
+
*/
|
|
2
10
|
export default function prepareProjection(dataType, projection, scope) {
|
|
3
11
|
if (projection === '*')
|
|
4
12
|
return undefined;
|
|
@@ -20,18 +28,18 @@ export function prepare(dataType, target, projection, scope) {
|
|
|
20
28
|
let fieldName;
|
|
21
29
|
let field;
|
|
22
30
|
let k;
|
|
23
|
-
|
|
31
|
+
/* Add fields from data type */
|
|
24
32
|
for (field of dataType.fields(scope)) {
|
|
25
33
|
fieldName = field.name;
|
|
26
34
|
k = fieldName.toLowerCase();
|
|
27
35
|
projectionKeysSet.delete(k);
|
|
28
36
|
const p = projection?.[k];
|
|
29
37
|
if (
|
|
30
|
-
|
|
38
|
+
/* Ignore if field is omitted */
|
|
31
39
|
p?.sign === '-' ||
|
|
32
|
-
|
|
40
|
+
/* Ignore if defaultFields is false and field is not in projection */
|
|
33
41
|
(!defaultFields && !p) ||
|
|
34
|
-
|
|
42
|
+
/* Ignore if defaultFields is true and fields is exclusive */
|
|
35
43
|
(defaultFields && field.exclusive && !p)) {
|
|
36
44
|
continue;
|
|
37
45
|
}
|
|
@@ -43,7 +51,7 @@ export function prepare(dataType, target, projection, scope) {
|
|
|
43
51
|
}
|
|
44
52
|
target[fieldName] = 1;
|
|
45
53
|
}
|
|
46
|
-
|
|
54
|
+
/* Add additional fields */
|
|
47
55
|
if (dataType.additionalFields) {
|
|
48
56
|
for (k of projectionKeysSet.values()) {
|
|
49
57
|
const n = projection?.[k];
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import mongodb from 'mongodb';
|
|
2
|
+
/**
|
|
3
|
+
* Prepares the MongoDB sort object from an array of sort strings.
|
|
4
|
+
*
|
|
5
|
+
* @param sort - An array of strings representing the sort order (e.g., ['+name', '-age']).
|
|
6
|
+
* @returns The prepared MongoDB sort object, or `undefined` if no sort is provided.
|
|
7
|
+
*/
|
|
2
8
|
export default function prepareSort(sort?: string[]): mongodb.Sort | undefined;
|
package/adapter/prepare-sort.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepares the MongoDB sort object from an array of sort strings.
|
|
3
|
+
*
|
|
4
|
+
* @param sort - An array of strings representing the sort order (e.g., ['+name', '-age']).
|
|
5
|
+
* @returns The prepared MongoDB sort object, or `undefined` if no sort is provided.
|
|
6
|
+
*/
|
|
1
7
|
export default function prepareSort(sort) {
|
|
2
8
|
if (!(sort && sort.length))
|
|
3
9
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/mongodb",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.4",
|
|
4
4
|
"description": "Opra MongoDB adapter package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"valgen": "^6.0.3"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@opra/common": "^1.26.
|
|
14
|
-
"@opra/core": "^1.26.
|
|
15
|
-
"@opra/http": "^1.26.
|
|
13
|
+
"@opra/common": "^1.26.4",
|
|
14
|
+
"@opra/core": "^1.26.4",
|
|
15
|
+
"@opra/http": "^1.26.4",
|
|
16
16
|
"mongodb": "^7.0.0"
|
|
17
17
|
},
|
|
18
18
|
"exports": {
|