@opra/mongodb 1.2.3 → 1.3.1
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/cjs/{mongo-adapter.js → adapter/mongo-adapter.js} +4 -6
- package/cjs/adapter/mongo-patch-generator.js +165 -0
- package/cjs/index.js +7 -6
- package/cjs/{mongo-collection-service.js → services/mongo-collection-service.js} +1 -1
- package/cjs/{mongo-entity-service.js → services/mongo-entity-service.js} +16 -7
- package/cjs/{mongo-nested-service.js → services/mongo-nested-service.js} +10 -3
- package/cjs/{mongo-service.js → services/mongo-service.js} +4 -2
- package/cjs/{mongo-singleton-service.js → services/mongo-singleton-service.js} +1 -1
- package/esm/{mongo-adapter.js → adapter/mongo-adapter.js} +4 -6
- package/esm/adapter/mongo-patch-generator.js +161 -0
- package/esm/index.js +7 -6
- package/esm/{mongo-collection-service.js → services/mongo-collection-service.js} +1 -1
- package/esm/{mongo-entity-service.js → services/mongo-entity-service.js} +16 -7
- package/esm/{mongo-nested-service.js → services/mongo-nested-service.js} +10 -3
- package/esm/{mongo-service.js → services/mongo-service.js} +4 -2
- package/esm/{mongo-singleton-service.js → services/mongo-singleton-service.js} +1 -1
- package/package.json +4 -4
- package/types/{mongo-adapter.d.ts → adapter/mongo-adapter.d.ts} +4 -6
- package/types/adapter/mongo-patch-generator.d.ts +25 -0
- package/types/{adapter-utils → adapter}/prepare-filter.d.ts +1 -1
- package/types/index.d.cts +7 -6
- package/types/index.d.ts +7 -6
- package/types/{mongo-collection-service.d.ts → services/mongo-collection-service.d.ts} +1 -1
- package/types/{mongo-entity-service.d.ts → services/mongo-entity-service.d.ts} +1 -0
- package/types/{mongo-nested-service.d.ts → services/mongo-nested-service.d.ts} +2 -2
- package/types/{mongo-service.d.ts → services/mongo-service.d.ts} +1 -1
- package/types/{mongo-singleton-service.d.ts → services/mongo-singleton-service.d.ts} +1 -1
- package/cjs/adapter-utils/prepare-patch.js +0 -37
- package/esm/adapter-utils/prepare-patch.js +0 -34
- package/types/adapter-utils/prepare-patch.d.ts +0 -3
- /package/cjs/{adapter-utils → adapter}/prepare-filter.js +0 -0
- /package/cjs/{adapter-utils → adapter}/prepare-key-values.js +0 -0
- /package/cjs/{adapter-utils → adapter}/prepare-projection.js +0 -0
- /package/cjs/{adapter-utils → adapter}/prepare-sort.js +0 -0
- /package/esm/{adapter-utils → adapter}/prepare-filter.js +0 -0
- /package/esm/{adapter-utils → adapter}/prepare-key-values.js +0 -0
- /package/esm/{adapter-utils → adapter}/prepare-projection.js +0 -0
- /package/esm/{adapter-utils → adapter}/prepare-sort.js +0 -0
- /package/types/{adapter-utils → adapter}/prepare-key-values.d.ts +0 -0
- /package/types/{adapter-utils → adapter}/prepare-projection.d.ts +0 -0
- /package/types/{adapter-utils → adapter}/prepare-sort.d.ts +0 -0
|
@@ -2,16 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MongoAdapter = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const prepare_filter_js_1 = tslib_1.__importDefault(require("./
|
|
6
|
-
const prepare_key_values_js_1 = tslib_1.__importDefault(require("./
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const prepare_sort_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-sort.js"));
|
|
5
|
+
const prepare_filter_js_1 = tslib_1.__importDefault(require("./prepare-filter.js"));
|
|
6
|
+
const prepare_key_values_js_1 = tslib_1.__importDefault(require("./prepare-key-values.js"));
|
|
7
|
+
const prepare_projection_js_1 = tslib_1.__importDefault(require("./prepare-projection.js"));
|
|
8
|
+
const prepare_sort_js_1 = tslib_1.__importDefault(require("./prepare-sort.js"));
|
|
10
9
|
var MongoAdapter;
|
|
11
10
|
(function (MongoAdapter) {
|
|
12
11
|
MongoAdapter.prepareFilter = prepare_filter_js_1.default;
|
|
13
12
|
MongoAdapter.prepareKeyValues = prepare_key_values_js_1.default;
|
|
14
|
-
MongoAdapter.preparePatch = prepare_patch_js_1.default;
|
|
15
13
|
MongoAdapter.prepareProjection = prepare_projection_js_1.default;
|
|
16
14
|
MongoAdapter.prepareSort = prepare_sort_js_1.default;
|
|
17
15
|
async function parseRequest(context) {
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoPatchGenerator = void 0;
|
|
4
|
+
const common_1 = require("@opra/common");
|
|
5
|
+
const FIELD_NAME_PATTERN = /^([-><*:])?(.+)$/;
|
|
6
|
+
class MongoPatchGenerator {
|
|
7
|
+
generatePatch(dataType, doc, options) {
|
|
8
|
+
const ctx = {};
|
|
9
|
+
this._processComplexType(ctx, dataType, options?.currentPath || '', doc);
|
|
10
|
+
const update = {};
|
|
11
|
+
if (ctx.$pull)
|
|
12
|
+
update.$pull = ctx.$pull;
|
|
13
|
+
if (ctx.$unset)
|
|
14
|
+
update.$unset = ctx.$unset;
|
|
15
|
+
if (ctx.$set)
|
|
16
|
+
update.$set = ctx.$set;
|
|
17
|
+
if (ctx.$push)
|
|
18
|
+
update.$push = ctx.$push;
|
|
19
|
+
return {
|
|
20
|
+
update,
|
|
21
|
+
arrayFilters: ctx.arrayFilters,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
_processComplexType(ctx, dataType, path, input) {
|
|
25
|
+
if (input.$add) {
|
|
26
|
+
this._processAdd(ctx, dataType, path, input.$add);
|
|
27
|
+
}
|
|
28
|
+
if (input.$remove) {
|
|
29
|
+
this._processRemove(ctx, dataType, path, input.$remove);
|
|
30
|
+
}
|
|
31
|
+
const keys = Object.keys(input);
|
|
32
|
+
const pathDot = path + (path ? '.' : '');
|
|
33
|
+
let field;
|
|
34
|
+
let key;
|
|
35
|
+
let value;
|
|
36
|
+
let keyField;
|
|
37
|
+
let keyValue;
|
|
38
|
+
let arrayIndex = 0;
|
|
39
|
+
let arrayFilterName = '';
|
|
40
|
+
for (key of keys) {
|
|
41
|
+
const m = FIELD_NAME_PATTERN.exec(key);
|
|
42
|
+
if (!m)
|
|
43
|
+
continue;
|
|
44
|
+
key = m[2];
|
|
45
|
+
value = input[key];
|
|
46
|
+
field = dataType.fields.get(key);
|
|
47
|
+
if (!field) {
|
|
48
|
+
if (dataType.additionalFields === true) {
|
|
49
|
+
if (value === null) {
|
|
50
|
+
ctx.$unset = ctx.$unset || {};
|
|
51
|
+
ctx.$unset[pathDot + key] = 1;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
ctx.$set = ctx.$set || {};
|
|
55
|
+
ctx.$set[pathDot + key] = value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (field.readonly)
|
|
61
|
+
continue;
|
|
62
|
+
if (value === null) {
|
|
63
|
+
ctx.$unset = ctx.$unset || {};
|
|
64
|
+
ctx.$unset[pathDot + field.name] = 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (field.type instanceof common_1.ComplexType) {
|
|
68
|
+
if (!value)
|
|
69
|
+
continue;
|
|
70
|
+
if (field.isArray) {
|
|
71
|
+
if (!value.length)
|
|
72
|
+
continue;
|
|
73
|
+
keyField = field.keyField || field.type.keyField;
|
|
74
|
+
if (keyField) {
|
|
75
|
+
for (let v of value) {
|
|
76
|
+
/** Increase arrayIndex and determine a new name for array filter */
|
|
77
|
+
arrayFilterName = 'f' + String(++arrayIndex);
|
|
78
|
+
/** Extract key value from object */
|
|
79
|
+
keyValue = v[keyField];
|
|
80
|
+
if (keyValue == null)
|
|
81
|
+
continue;
|
|
82
|
+
v = { ...v };
|
|
83
|
+
/** Remove key field from object */
|
|
84
|
+
delete v[keyField];
|
|
85
|
+
/** Add array filter */
|
|
86
|
+
ctx.arrayFilters = ctx.arrayFilters || {};
|
|
87
|
+
ctx.arrayFilters[`${arrayFilterName}.${keyField}`] = keyValue;
|
|
88
|
+
/** Process each object in array */
|
|
89
|
+
this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!(typeof value === 'object'))
|
|
95
|
+
continue;
|
|
96
|
+
/** Process nested object */
|
|
97
|
+
this._processComplexType(ctx, field.type, pathDot + field.name, value);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
ctx.$set = ctx.$set || {};
|
|
101
|
+
ctx.$set[pathDot + field.name] = value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
_processAdd(ctx, dataType, path, input) {
|
|
105
|
+
let field;
|
|
106
|
+
let key;
|
|
107
|
+
let value;
|
|
108
|
+
const pathDot = path + (path ? '.' : '');
|
|
109
|
+
const keys = Object.keys(input);
|
|
110
|
+
let keyField;
|
|
111
|
+
for (key of keys) {
|
|
112
|
+
value = input[key];
|
|
113
|
+
field = dataType.fields.get(key);
|
|
114
|
+
if (!(field && field.isArray))
|
|
115
|
+
continue;
|
|
116
|
+
ctx.$push = ctx.$push || {};
|
|
117
|
+
if (field.type instanceof common_1.ComplexType) {
|
|
118
|
+
keyField = field.keyField || field.type.keyField;
|
|
119
|
+
if (keyField) {
|
|
120
|
+
if (Array.isArray(value)) {
|
|
121
|
+
value.forEach(v => {
|
|
122
|
+
if (!v[keyField]) {
|
|
123
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
ctx.$push[pathDot + key] = { $each: value };
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (!value[keyField]) {
|
|
130
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
|
|
131
|
+
}
|
|
132
|
+
ctx.$push[pathDot + key] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
_processRemove(ctx, dataType, path, input) {
|
|
141
|
+
let field;
|
|
142
|
+
let key;
|
|
143
|
+
let value;
|
|
144
|
+
const pathDot = path + (path ? '.' : '');
|
|
145
|
+
const keys = Object.keys(input);
|
|
146
|
+
let keyField;
|
|
147
|
+
for (key of keys) {
|
|
148
|
+
value = input[key];
|
|
149
|
+
field = dataType.fields.get(key);
|
|
150
|
+
if (!(field && field.isArray))
|
|
151
|
+
continue;
|
|
152
|
+
ctx.$pull = ctx.$pull || {};
|
|
153
|
+
if (field.type instanceof common_1.ComplexType) {
|
|
154
|
+
keyField = field.keyField || field.type.keyField;
|
|
155
|
+
if (!keyField)
|
|
156
|
+
continue;
|
|
157
|
+
ctx.$pull[pathDot + key] = { $elemMatch: { [keyField]: Array.isArray(value) ? { $in: value } : value } };
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
ctx.$pull[pathDot + key] = Array.isArray(value) ? { $in: value } : value;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.MongoPatchGenerator = MongoPatchGenerator;
|
package/cjs/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
tslib_1.__exportStar(require("./mongo-adapter.js"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./mongo-
|
|
6
|
-
tslib_1.__exportStar(require("./mongo-
|
|
7
|
-
tslib_1.__exportStar(require("./mongo-
|
|
8
|
-
tslib_1.__exportStar(require("./mongo-service.js"), exports);
|
|
9
|
-
tslib_1.__exportStar(require("./mongo-
|
|
4
|
+
tslib_1.__exportStar(require("./adapter/mongo-adapter.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./adapter/mongo-patch-generator.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./services/mongo-collection-service.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./services/mongo-entity-service.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./services/mongo-nested-service.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./services/mongo-service.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./services/mongo-singleton-service.js"), exports);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MongoCollectionService = void 0;
|
|
4
4
|
const common_1 = require("@opra/common");
|
|
5
|
-
const mongo_adapter_js_1 = require("
|
|
5
|
+
const mongo_adapter_js_1 = require("../adapter/mongo-adapter.js");
|
|
6
6
|
const mongo_entity_service_js_1 = require("./mongo-entity-service.js");
|
|
7
7
|
/**
|
|
8
8
|
* @class MongoCollectionService
|
|
@@ -4,7 +4,8 @@ exports.MongoEntityService = void 0;
|
|
|
4
4
|
const objects_1 = require("@jsopen/objects");
|
|
5
5
|
const common_1 = require("@opra/common");
|
|
6
6
|
const valgen_1 = require("valgen");
|
|
7
|
-
const mongo_adapter_js_1 = require("
|
|
7
|
+
const mongo_adapter_js_1 = require("../adapter/mongo-adapter.js");
|
|
8
|
+
const mongo_patch_generator_js_1 = require("../adapter/mongo-patch-generator.js");
|
|
8
9
|
const mongo_service_js_1 = require("./mongo-service.js");
|
|
9
10
|
/**
|
|
10
11
|
* @class MongoEntityService
|
|
@@ -390,12 +391,20 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
390
391
|
if (input && inputRaw) {
|
|
391
392
|
throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
|
|
392
393
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
394
|
+
if (inputRaw)
|
|
395
|
+
return inputRaw;
|
|
396
|
+
const inputCodec = this._getInputCodec('update');
|
|
397
|
+
const doc = inputCodec(input);
|
|
398
|
+
delete doc._id;
|
|
399
|
+
return this._generatePatch(command, doc);
|
|
400
|
+
}
|
|
401
|
+
_generatePatch(command, doc) {
|
|
402
|
+
const patchGenerator = new mongo_patch_generator_js_1.MongoPatchGenerator();
|
|
403
|
+
const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc);
|
|
404
|
+
command.options = command.options || {};
|
|
405
|
+
if (arrayFilters) {
|
|
406
|
+
command.options.arrayFilters = command.options.arrayFilters || [];
|
|
407
|
+
command.options.arrayFilters.push(arrayFilters);
|
|
399
408
|
}
|
|
400
409
|
return update;
|
|
401
410
|
}
|
|
@@ -4,7 +4,8 @@ exports.MongoNestedService = void 0;
|
|
|
4
4
|
const objects_1 = require("@jsopen/objects");
|
|
5
5
|
const common_1 = require("@opra/common");
|
|
6
6
|
const valgen_1 = require("valgen");
|
|
7
|
-
const mongo_adapter_js_1 = require("
|
|
7
|
+
const mongo_adapter_js_1 = require("../adapter/mongo-adapter.js");
|
|
8
|
+
const mongo_patch_generator_js_1 = require("../adapter/mongo-patch-generator.js");
|
|
8
9
|
const mongo_service_js_1 = require("./mongo-service.js");
|
|
9
10
|
/**
|
|
10
11
|
* A class that provides methods to perform operations on an array field in a MongoDB collection.
|
|
@@ -687,9 +688,15 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
687
688
|
const elemMatch = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter], { fieldPrefix: 'elem.' });
|
|
688
689
|
options.arrayFilters = [elemMatch];
|
|
689
690
|
}
|
|
690
|
-
const
|
|
691
|
-
|
|
691
|
+
const patchGenerator = new mongo_patch_generator_js_1.MongoPatchGenerator();
|
|
692
|
+
const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc, {
|
|
693
|
+
currentPath: this.fieldName + (options?.filter ? '.$[elem]' : '.$[]'),
|
|
692
694
|
});
|
|
695
|
+
command.options = command.options || {};
|
|
696
|
+
if (arrayFilters) {
|
|
697
|
+
command.options.arrayFilters = command.options.arrayFilters || [];
|
|
698
|
+
command.options.arrayFilters.push(arrayFilters);
|
|
699
|
+
}
|
|
693
700
|
// Count matching items, we will use this as result
|
|
694
701
|
const count = await this._count({
|
|
695
702
|
crud: 'read',
|
|
@@ -4,7 +4,7 @@ exports.MongoService = void 0;
|
|
|
4
4
|
const common_1 = require("@opra/common");
|
|
5
5
|
const core_1 = require("@opra/core");
|
|
6
6
|
const mongodb_1 = require("mongodb");
|
|
7
|
-
const mongo_adapter_js_1 = require("
|
|
7
|
+
const mongo_adapter_js_1 = require("../adapter/mongo-adapter.js");
|
|
8
8
|
const transactionKey = Symbol.for('transaction');
|
|
9
9
|
/**
|
|
10
10
|
* Class representing a MongoDB service for interacting with a collection.
|
|
@@ -232,8 +232,10 @@ class MongoService extends core_1.ServiceBase {
|
|
|
232
232
|
if (validator)
|
|
233
233
|
return validator;
|
|
234
234
|
const options = { projection: '*' };
|
|
235
|
-
if (operation === 'update')
|
|
235
|
+
if (operation === 'update') {
|
|
236
236
|
options.partial = 'deep';
|
|
237
|
+
options.allowPatchOperators = true;
|
|
238
|
+
}
|
|
237
239
|
const dataType = this.dataType;
|
|
238
240
|
validator = dataType.generateCodec('decode', options);
|
|
239
241
|
this._inputCodecs[operation] = validator;
|
|
@@ -4,7 +4,7 @@ exports.MongoSingletonService = void 0;
|
|
|
4
4
|
const objects_1 = require("@jsopen/objects");
|
|
5
5
|
const common_1 = require("@opra/common");
|
|
6
6
|
const mongodb_1 = require("mongodb");
|
|
7
|
-
const mongo_adapter_js_1 = require("
|
|
7
|
+
const mongo_adapter_js_1 = require("../adapter/mongo-adapter.js");
|
|
8
8
|
const mongo_entity_service_js_1 = require("./mongo-entity-service.js");
|
|
9
9
|
/**
|
|
10
10
|
* A class that provides access to a MongoDB collection, with support for singleton document operations.
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import _prepareFilter from './
|
|
2
|
-
import _prepareKeyValues from './
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import _prepareSort from './adapter-utils/prepare-sort.js';
|
|
1
|
+
import _prepareFilter from './prepare-filter.js';
|
|
2
|
+
import _prepareKeyValues from './prepare-key-values.js';
|
|
3
|
+
import _prepareProjection from './prepare-projection.js';
|
|
4
|
+
import _prepareSort from './prepare-sort.js';
|
|
6
5
|
export var MongoAdapter;
|
|
7
6
|
(function (MongoAdapter) {
|
|
8
7
|
MongoAdapter.prepareFilter = _prepareFilter;
|
|
9
8
|
MongoAdapter.prepareKeyValues = _prepareKeyValues;
|
|
10
|
-
MongoAdapter.preparePatch = _preparePatch;
|
|
11
9
|
MongoAdapter.prepareProjection = _prepareProjection;
|
|
12
10
|
MongoAdapter.prepareSort = _prepareSort;
|
|
13
11
|
async function parseRequest(context) {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ComplexType } from '@opra/common';
|
|
2
|
+
const FIELD_NAME_PATTERN = /^([-><*:])?(.+)$/;
|
|
3
|
+
export class MongoPatchGenerator {
|
|
4
|
+
generatePatch(dataType, doc, options) {
|
|
5
|
+
const ctx = {};
|
|
6
|
+
this._processComplexType(ctx, dataType, options?.currentPath || '', doc);
|
|
7
|
+
const update = {};
|
|
8
|
+
if (ctx.$pull)
|
|
9
|
+
update.$pull = ctx.$pull;
|
|
10
|
+
if (ctx.$unset)
|
|
11
|
+
update.$unset = ctx.$unset;
|
|
12
|
+
if (ctx.$set)
|
|
13
|
+
update.$set = ctx.$set;
|
|
14
|
+
if (ctx.$push)
|
|
15
|
+
update.$push = ctx.$push;
|
|
16
|
+
return {
|
|
17
|
+
update,
|
|
18
|
+
arrayFilters: ctx.arrayFilters,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
_processComplexType(ctx, dataType, path, input) {
|
|
22
|
+
if (input.$add) {
|
|
23
|
+
this._processAdd(ctx, dataType, path, input.$add);
|
|
24
|
+
}
|
|
25
|
+
if (input.$remove) {
|
|
26
|
+
this._processRemove(ctx, dataType, path, input.$remove);
|
|
27
|
+
}
|
|
28
|
+
const keys = Object.keys(input);
|
|
29
|
+
const pathDot = path + (path ? '.' : '');
|
|
30
|
+
let field;
|
|
31
|
+
let key;
|
|
32
|
+
let value;
|
|
33
|
+
let keyField;
|
|
34
|
+
let keyValue;
|
|
35
|
+
let arrayIndex = 0;
|
|
36
|
+
let arrayFilterName = '';
|
|
37
|
+
for (key of keys) {
|
|
38
|
+
const m = FIELD_NAME_PATTERN.exec(key);
|
|
39
|
+
if (!m)
|
|
40
|
+
continue;
|
|
41
|
+
key = m[2];
|
|
42
|
+
value = input[key];
|
|
43
|
+
field = dataType.fields.get(key);
|
|
44
|
+
if (!field) {
|
|
45
|
+
if (dataType.additionalFields === true) {
|
|
46
|
+
if (value === null) {
|
|
47
|
+
ctx.$unset = ctx.$unset || {};
|
|
48
|
+
ctx.$unset[pathDot + key] = 1;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
ctx.$set = ctx.$set || {};
|
|
52
|
+
ctx.$set[pathDot + key] = value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (field.readonly)
|
|
58
|
+
continue;
|
|
59
|
+
if (value === null) {
|
|
60
|
+
ctx.$unset = ctx.$unset || {};
|
|
61
|
+
ctx.$unset[pathDot + field.name] = 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (field.type instanceof ComplexType) {
|
|
65
|
+
if (!value)
|
|
66
|
+
continue;
|
|
67
|
+
if (field.isArray) {
|
|
68
|
+
if (!value.length)
|
|
69
|
+
continue;
|
|
70
|
+
keyField = field.keyField || field.type.keyField;
|
|
71
|
+
if (keyField) {
|
|
72
|
+
for (let v of value) {
|
|
73
|
+
/** Increase arrayIndex and determine a new name for array filter */
|
|
74
|
+
arrayFilterName = 'f' + String(++arrayIndex);
|
|
75
|
+
/** Extract key value from object */
|
|
76
|
+
keyValue = v[keyField];
|
|
77
|
+
if (keyValue == null)
|
|
78
|
+
continue;
|
|
79
|
+
v = { ...v };
|
|
80
|
+
/** Remove key field from object */
|
|
81
|
+
delete v[keyField];
|
|
82
|
+
/** Add array filter */
|
|
83
|
+
ctx.arrayFilters = ctx.arrayFilters || {};
|
|
84
|
+
ctx.arrayFilters[`${arrayFilterName}.${keyField}`] = keyValue;
|
|
85
|
+
/** Process each object in array */
|
|
86
|
+
this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!(typeof value === 'object'))
|
|
92
|
+
continue;
|
|
93
|
+
/** Process nested object */
|
|
94
|
+
this._processComplexType(ctx, field.type, pathDot + field.name, value);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
ctx.$set = ctx.$set || {};
|
|
98
|
+
ctx.$set[pathDot + field.name] = value;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
_processAdd(ctx, dataType, path, input) {
|
|
102
|
+
let field;
|
|
103
|
+
let key;
|
|
104
|
+
let value;
|
|
105
|
+
const pathDot = path + (path ? '.' : '');
|
|
106
|
+
const keys = Object.keys(input);
|
|
107
|
+
let keyField;
|
|
108
|
+
for (key of keys) {
|
|
109
|
+
value = input[key];
|
|
110
|
+
field = dataType.fields.get(key);
|
|
111
|
+
if (!(field && field.isArray))
|
|
112
|
+
continue;
|
|
113
|
+
ctx.$push = ctx.$push || {};
|
|
114
|
+
if (field.type instanceof ComplexType) {
|
|
115
|
+
keyField = field.keyField || field.type.keyField;
|
|
116
|
+
if (keyField) {
|
|
117
|
+
if (Array.isArray(value)) {
|
|
118
|
+
value.forEach(v => {
|
|
119
|
+
if (!v[keyField]) {
|
|
120
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
ctx.$push[pathDot + key] = { $each: value };
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
if (!value[keyField]) {
|
|
127
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
|
|
128
|
+
}
|
|
129
|
+
ctx.$push[pathDot + key] = value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
_processRemove(ctx, dataType, path, input) {
|
|
138
|
+
let field;
|
|
139
|
+
let key;
|
|
140
|
+
let value;
|
|
141
|
+
const pathDot = path + (path ? '.' : '');
|
|
142
|
+
const keys = Object.keys(input);
|
|
143
|
+
let keyField;
|
|
144
|
+
for (key of keys) {
|
|
145
|
+
value = input[key];
|
|
146
|
+
field = dataType.fields.get(key);
|
|
147
|
+
if (!(field && field.isArray))
|
|
148
|
+
continue;
|
|
149
|
+
ctx.$pull = ctx.$pull || {};
|
|
150
|
+
if (field.type instanceof ComplexType) {
|
|
151
|
+
keyField = field.keyField || field.type.keyField;
|
|
152
|
+
if (!keyField)
|
|
153
|
+
continue;
|
|
154
|
+
ctx.$pull[pathDot + key] = { $elemMatch: { [keyField]: Array.isArray(value) ? { $in: value } : value } };
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
ctx.$pull[pathDot + key] = Array.isArray(value) ? { $in: value } : value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export * from './mongo-adapter.js';
|
|
2
|
-
export * from './mongo-
|
|
3
|
-
export * from './mongo-
|
|
4
|
-
export * from './mongo-
|
|
5
|
-
export * from './mongo-service.js';
|
|
6
|
-
export * from './mongo-
|
|
1
|
+
export * from './adapter/mongo-adapter.js';
|
|
2
|
+
export * from './adapter/mongo-patch-generator.js';
|
|
3
|
+
export * from './services/mongo-collection-service.js';
|
|
4
|
+
export * from './services/mongo-entity-service.js';
|
|
5
|
+
export * from './services/mongo-nested-service.js';
|
|
6
|
+
export * from './services/mongo-service.js';
|
|
7
|
+
export * from './services/mongo-singleton-service.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResourceNotAvailableError } from '@opra/common';
|
|
2
|
-
import { MongoAdapter } from '
|
|
2
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
3
3
|
import { MongoEntityService } from './mongo-entity-service.js';
|
|
4
4
|
/**
|
|
5
5
|
* @class MongoCollectionService
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { omit } from '@jsopen/objects';
|
|
2
2
|
import { InternalServerError } from '@opra/common';
|
|
3
3
|
import { isNotNullish } from 'valgen';
|
|
4
|
-
import { MongoAdapter } from '
|
|
4
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
5
|
+
import { MongoPatchGenerator } from '../adapter/mongo-patch-generator.js';
|
|
5
6
|
import { MongoService } from './mongo-service.js';
|
|
6
7
|
/**
|
|
7
8
|
* @class MongoEntityService
|
|
@@ -387,12 +388,20 @@ export class MongoEntityService extends MongoService {
|
|
|
387
388
|
if (input && inputRaw) {
|
|
388
389
|
throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
|
|
389
390
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
391
|
+
if (inputRaw)
|
|
392
|
+
return inputRaw;
|
|
393
|
+
const inputCodec = this._getInputCodec('update');
|
|
394
|
+
const doc = inputCodec(input);
|
|
395
|
+
delete doc._id;
|
|
396
|
+
return this._generatePatch(command, doc);
|
|
397
|
+
}
|
|
398
|
+
_generatePatch(command, doc) {
|
|
399
|
+
const patchGenerator = new MongoPatchGenerator();
|
|
400
|
+
const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc);
|
|
401
|
+
command.options = command.options || {};
|
|
402
|
+
if (arrayFilters) {
|
|
403
|
+
command.options.arrayFilters = command.options.arrayFilters || [];
|
|
404
|
+
command.options.arrayFilters.push(arrayFilters);
|
|
396
405
|
}
|
|
397
406
|
return update;
|
|
398
407
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { omit } from '@jsopen/objects';
|
|
2
2
|
import { ComplexType, NotAcceptableError, ResourceNotAvailableError } from '@opra/common';
|
|
3
3
|
import { isNotNullish } from 'valgen';
|
|
4
|
-
import { MongoAdapter } from '
|
|
4
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
5
|
+
import { MongoPatchGenerator } from '../adapter/mongo-patch-generator.js';
|
|
5
6
|
import { MongoService } from './mongo-service.js';
|
|
6
7
|
/**
|
|
7
8
|
* A class that provides methods to perform operations on an array field in a MongoDB collection.
|
|
@@ -684,9 +685,15 @@ export class MongoNestedService extends MongoService {
|
|
|
684
685
|
const elemMatch = MongoAdapter.prepareFilter([options?.filter], { fieldPrefix: 'elem.' });
|
|
685
686
|
options.arrayFilters = [elemMatch];
|
|
686
687
|
}
|
|
687
|
-
const
|
|
688
|
-
|
|
688
|
+
const patchGenerator = new MongoPatchGenerator();
|
|
689
|
+
const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc, {
|
|
690
|
+
currentPath: this.fieldName + (options?.filter ? '.$[elem]' : '.$[]'),
|
|
689
691
|
});
|
|
692
|
+
command.options = command.options || {};
|
|
693
|
+
if (arrayFilters) {
|
|
694
|
+
command.options.arrayFilters = command.options.arrayFilters || [];
|
|
695
|
+
command.options.arrayFilters.push(arrayFilters);
|
|
696
|
+
}
|
|
690
697
|
// Count matching items, we will use this as result
|
|
691
698
|
const count = await this._count({
|
|
692
699
|
crud: 'read',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DATATYPE_METADATA } from '@opra/common';
|
|
2
2
|
import { ServiceBase } from '@opra/core';
|
|
3
3
|
import { ObjectId } from 'mongodb';
|
|
4
|
-
import { MongoAdapter } from '
|
|
4
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
5
5
|
const transactionKey = Symbol.for('transaction');
|
|
6
6
|
/**
|
|
7
7
|
* Class representing a MongoDB service for interacting with a collection.
|
|
@@ -229,8 +229,10 @@ export class MongoService extends ServiceBase {
|
|
|
229
229
|
if (validator)
|
|
230
230
|
return validator;
|
|
231
231
|
const options = { projection: '*' };
|
|
232
|
-
if (operation === 'update')
|
|
232
|
+
if (operation === 'update') {
|
|
233
233
|
options.partial = 'deep';
|
|
234
|
+
options.allowPatchOperators = true;
|
|
235
|
+
}
|
|
234
236
|
const dataType = this.dataType;
|
|
235
237
|
validator = dataType.generateCodec('decode', options);
|
|
236
238
|
this._inputCodecs[operation] = validator;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { omit } from '@jsopen/objects';
|
|
2
2
|
import { ResourceNotAvailableError } from '@opra/common';
|
|
3
3
|
import { ObjectId } from 'mongodb';
|
|
4
|
-
import { MongoAdapter } from '
|
|
4
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
5
5
|
import { MongoEntityService } from './mongo-entity-service.js';
|
|
6
6
|
/**
|
|
7
7
|
* A class that provides access to a MongoDB collection, with support for singleton document operations.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/mongodb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Opra MongoDB adapter package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"valgen": "^5.12.0"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@opra/common": "^1.
|
|
14
|
-
"@opra/core": "^1.
|
|
15
|
-
"@opra/http": "^1.
|
|
13
|
+
"@opra/common": "^1.3.1",
|
|
14
|
+
"@opra/core": "^1.3.1",
|
|
15
|
+
"@opra/http": "^1.3.1",
|
|
16
16
|
"mongodb": ">= 6.0.0"
|
|
17
17
|
},
|
|
18
18
|
"type": "module",
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { OpraFilter } from '@opra/common';
|
|
2
2
|
import type { ExecutionContext } from '@opra/core';
|
|
3
3
|
import mongodb, { ObjectId } from 'mongodb';
|
|
4
|
-
import _prepareFilter from './
|
|
5
|
-
import _prepareKeyValues from './
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import _prepareSort from './adapter-utils/prepare-sort.js';
|
|
4
|
+
import _prepareFilter from './prepare-filter.js';
|
|
5
|
+
import _prepareKeyValues from './prepare-key-values.js';
|
|
6
|
+
import _prepareProjection from './prepare-projection.js';
|
|
7
|
+
import _prepareSort from './prepare-sort.js';
|
|
9
8
|
export declare namespace MongoAdapter {
|
|
10
9
|
type AnyId = string | number | ObjectId;
|
|
11
10
|
type FilterInput<T = any> = OpraFilter.Expression | mongodb.Filter<T> | string | undefined;
|
|
12
11
|
const prepareFilter: typeof _prepareFilter;
|
|
13
12
|
const prepareKeyValues: typeof _prepareKeyValues;
|
|
14
|
-
const preparePatch: typeof _preparePatch;
|
|
15
13
|
const prepareProjection: typeof _prepareProjection;
|
|
16
14
|
const prepareSort: typeof _prepareSort;
|
|
17
15
|
interface TransformedRequest {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ComplexType } from '@opra/common';
|
|
2
|
+
import type { UpdateFilter } from 'mongodb';
|
|
3
|
+
import type { PatchDTO } from 'ts-gems';
|
|
4
|
+
interface Context {
|
|
5
|
+
$set?: Record<string, any>;
|
|
6
|
+
$unset?: Record<string, any>;
|
|
7
|
+
$push?: Record<string, any>;
|
|
8
|
+
$pull?: Record<string, any>;
|
|
9
|
+
arrayFilters?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
export declare class MongoPatchGenerator {
|
|
12
|
+
generatePatch<T extends object>(dataType: ComplexType, doc: PatchDTO<T>, options?: MongoPatchGenerator.Options): {
|
|
13
|
+
update: UpdateFilter<T>;
|
|
14
|
+
arrayFilters?: Record<string, any>;
|
|
15
|
+
};
|
|
16
|
+
protected _processComplexType(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
17
|
+
protected _processAdd(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
18
|
+
protected _processRemove(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
19
|
+
}
|
|
20
|
+
export declare namespace MongoPatchGenerator {
|
|
21
|
+
interface Options {
|
|
22
|
+
currentPath?: string;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {};
|
package/types/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export * from './mongo-adapter.js';
|
|
2
|
-
export * from './mongo-
|
|
3
|
-
export * from './mongo-
|
|
4
|
-
export * from './mongo-
|
|
5
|
-
export * from './mongo-service.js';
|
|
6
|
-
export * from './mongo-
|
|
1
|
+
export * from './adapter/mongo-adapter.js';
|
|
2
|
+
export * from './adapter/mongo-patch-generator.js';
|
|
3
|
+
export * from './services/mongo-collection-service.js';
|
|
4
|
+
export * from './services/mongo-entity-service.js';
|
|
5
|
+
export * from './services/mongo-nested-service.js';
|
|
6
|
+
export * from './services/mongo-service.js';
|
|
7
|
+
export * from './services/mongo-singleton-service.js';
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export * from './mongo-adapter.js';
|
|
2
|
-
export * from './mongo-
|
|
3
|
-
export * from './mongo-
|
|
4
|
-
export * from './mongo-
|
|
5
|
-
export * from './mongo-service.js';
|
|
6
|
-
export * from './mongo-
|
|
1
|
+
export * from './adapter/mongo-adapter.js';
|
|
2
|
+
export * from './adapter/mongo-patch-generator.js';
|
|
3
|
+
export * from './services/mongo-collection-service.js';
|
|
4
|
+
export * from './services/mongo-entity-service.js';
|
|
5
|
+
export * from './services/mongo-nested-service.js';
|
|
6
|
+
export * from './services/mongo-service.js';
|
|
7
|
+
export * from './services/mongo-singleton-service.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import mongodb, { type UpdateFilter } from 'mongodb';
|
|
2
2
|
import type { PartialDTO, PatchDTO, RequiredSome, Type } from 'ts-gems';
|
|
3
|
-
import { MongoAdapter } from '
|
|
3
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
4
4
|
import { MongoEntityService } from './mongo-entity-service.js';
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
@@ -187,6 +187,7 @@ export declare class MongoEntityService<T extends mongodb.Document> extends Mong
|
|
|
187
187
|
*/
|
|
188
188
|
protected _replace(command: MongoEntityService.ReplaceCommand<T>): Promise<PartialDTO<T> | undefined>;
|
|
189
189
|
protected _prepareUpdate(command: MongoEntityService.UpdateOneCommand<T> | MongoEntityService.UpdateManyCommand<T>): UpdateFilter<T>;
|
|
190
|
+
protected _generatePatch(command: MongoEntityService.UpdateOneCommand<T> | MongoEntityService.UpdateManyCommand<T>, doc: any): mongodb.UpdateFilter<T>;
|
|
190
191
|
protected _executeCommand(command: MongoEntityService.CommandInfo, commandFn: () => any): Promise<any>;
|
|
191
192
|
protected _beforeCreate(command: MongoEntityService.CreateCommand<T>): Promise<void>;
|
|
192
193
|
protected _beforeDelete(command: MongoEntityService.DeleteCommand<T>): Promise<void>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ComplexType } from '@opra/common';
|
|
2
2
|
import mongodb from 'mongodb';
|
|
3
3
|
import type { DTO, PartialDTO, PatchDTO, RequiredSome, StrictOmit, Type } from 'ts-gems';
|
|
4
|
-
import { MongoAdapter } from '
|
|
5
|
-
import type { MongoEntityService } from './mongo-entity-service';
|
|
4
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
5
|
+
import type { MongoEntityService } from './mongo-entity-service.js';
|
|
6
6
|
import { MongoService } from './mongo-service.js';
|
|
7
7
|
/**
|
|
8
8
|
*
|
|
@@ -3,7 +3,7 @@ import { ExecutionContext, ServiceBase } from '@opra/core';
|
|
|
3
3
|
import mongodb, { ClientSession, type Document, type TransactionOptions } from 'mongodb';
|
|
4
4
|
import type { Nullish, StrictOmit, Type } from 'ts-gems';
|
|
5
5
|
import type { IsObject } from 'valgen';
|
|
6
|
-
import { MongoAdapter } from '
|
|
6
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
7
7
|
/**
|
|
8
8
|
* The namespace for the MongoService.
|
|
9
9
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import mongodb, { type UpdateFilter } from 'mongodb';
|
|
2
2
|
import type { PartialDTO, PatchDTO, RequiredSome, Type } from 'ts-gems';
|
|
3
|
-
import { MongoAdapter } from '
|
|
3
|
+
import { MongoAdapter } from '../adapter/mongo-adapter.js';
|
|
4
4
|
import { MongoEntityService } from './mongo-entity-service.js';
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = preparePatch;
|
|
4
|
-
const objects_1 = require("@jsopen/objects");
|
|
5
|
-
function preparePatch(doc, options, target) {
|
|
6
|
-
target = target || {};
|
|
7
|
-
_preparePatch(doc, target, '', options);
|
|
8
|
-
target.$set = target.$set || {};
|
|
9
|
-
return target;
|
|
10
|
-
}
|
|
11
|
-
function _preparePatch(src, trg, path, options) {
|
|
12
|
-
let f;
|
|
13
|
-
let key;
|
|
14
|
-
let field;
|
|
15
|
-
trg = trg || {};
|
|
16
|
-
const fieldPrefix = options?.fieldPrefix;
|
|
17
|
-
for (const [k, v] of Object.entries(src)) {
|
|
18
|
-
f = k.startsWith('*') ? k.substring(1) : k;
|
|
19
|
-
key = path ? path + '.' + f : f;
|
|
20
|
-
field = (fieldPrefix ? fieldPrefix : '') + key;
|
|
21
|
-
if (v == null) {
|
|
22
|
-
trg.$unset = trg.$unset || {};
|
|
23
|
-
trg.$unset[field] = '';
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
if (v && typeof v === 'object' && !(0, objects_1.isBuiltIn)(v)) {
|
|
27
|
-
// If field name starts with "*", do "replace" operation except "merge"
|
|
28
|
-
if (!k.startsWith('*')) {
|
|
29
|
-
_preparePatch(v, trg, key);
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
trg.$set = trg.$set || {};
|
|
34
|
-
trg.$set[field] = v;
|
|
35
|
-
}
|
|
36
|
-
return trg;
|
|
37
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { isBuiltIn } from '@jsopen/objects';
|
|
2
|
-
export default function preparePatch(doc, options, target) {
|
|
3
|
-
target = target || {};
|
|
4
|
-
_preparePatch(doc, target, '', options);
|
|
5
|
-
target.$set = target.$set || {};
|
|
6
|
-
return target;
|
|
7
|
-
}
|
|
8
|
-
function _preparePatch(src, trg, path, options) {
|
|
9
|
-
let f;
|
|
10
|
-
let key;
|
|
11
|
-
let field;
|
|
12
|
-
trg = trg || {};
|
|
13
|
-
const fieldPrefix = options?.fieldPrefix;
|
|
14
|
-
for (const [k, v] of Object.entries(src)) {
|
|
15
|
-
f = k.startsWith('*') ? k.substring(1) : k;
|
|
16
|
-
key = path ? path + '.' + f : f;
|
|
17
|
-
field = (fieldPrefix ? fieldPrefix : '') + key;
|
|
18
|
-
if (v == null) {
|
|
19
|
-
trg.$unset = trg.$unset || {};
|
|
20
|
-
trg.$unset[field] = '';
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
if (v && typeof v === 'object' && !isBuiltIn(v)) {
|
|
24
|
-
// If field name starts with "*", do "replace" operation except "merge"
|
|
25
|
-
if (!k.startsWith('*')) {
|
|
26
|
-
_preparePatch(v, trg, key);
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
trg.$set = trg.$set || {};
|
|
31
|
-
trg.$set[field] = v;
|
|
32
|
-
}
|
|
33
|
-
return trg;
|
|
34
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|