@opra/mongodb 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/cjs/index.js +7 -0
- package/cjs/mongo-adapter.js +109 -0
- package/cjs/mongo-collection-resource.js +103 -0
- package/cjs/mongo-entity-service.js +179 -0
- package/cjs/mongo-singleton-resource.js +63 -0
- package/cjs/package.json +3 -0
- package/cjs/transform-filter.js +96 -0
- package/cjs/transform-key-values.js +14 -0
- package/cjs/transform-patch.js +30 -0
- package/cjs/transform-projection.js +52 -0
- package/cjs/transform-sort.js +18 -0
- package/esm/index.js +7 -0
- package/esm/mongo-adapter.js +109 -0
- package/esm/mongo-collection-resource.js +103 -0
- package/esm/mongo-entity-service.js +179 -0
- package/esm/mongo-singleton-resource.js +63 -0
- package/esm/transform-filter.js +96 -0
- package/esm/transform-key-values.js +14 -0
- package/esm/transform-patch.js +30 -0
- package/esm/transform-projection.js +52 -0
- package/esm/transform-sort.js +18 -0
- package/package.json +67 -0
- package/types/index.d.ts +4 -0
- package/types/mongo-adapter.d.ts +14 -0
- package/types/mongo-collection-resource.d.ts +15 -0
- package/types/mongo-entity-service.d.ts +30 -0
- package/types/mongo-singleton-resource.d.ts +12 -0
- package/types/transform-filter.d.ts +2 -0
- package/types/transform-key-values.d.ts +3 -0
- package/types/transform-patch.d.ts +1 -0
- package/types/transform-projection.d.ts +9 -0
- package/types/transform-sort.d.ts +2 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._transformExclusionProjection = exports._transformInclusionProjection = void 0;
|
|
4
|
+
const common_1 = require("@opra/common");
|
|
5
|
+
function transformProjection(dataType, args) {
|
|
6
|
+
const out = {};
|
|
7
|
+
// omitExclusiveFields(dataType, out);
|
|
8
|
+
const pick = args.pick && (0, common_1.pathToObjectTree)(args.include ? [...args.pick, ...args.include] : args.pick);
|
|
9
|
+
const include = !args.pick && args.include && (0, common_1.pathToObjectTree)(args.include);
|
|
10
|
+
const omit = args.omit && (0, common_1.pathToObjectTree)(args.omit);
|
|
11
|
+
if (pick || include) {
|
|
12
|
+
_transformInclusionProjection(dataType, out, pick, include, omit);
|
|
13
|
+
}
|
|
14
|
+
else
|
|
15
|
+
_transformExclusionProjection(dataType, out, omit, !omit);
|
|
16
|
+
return Object.keys(out).length ? out : undefined;
|
|
17
|
+
}
|
|
18
|
+
exports.default = transformProjection;
|
|
19
|
+
function _transformInclusionProjection(dataType, target, pick, include, omit, defaultFields) {
|
|
20
|
+
defaultFields = defaultFields ?? !pick;
|
|
21
|
+
let n;
|
|
22
|
+
for (const [k, f] of dataType.fields.entries()) {
|
|
23
|
+
if (omit?.[k] === true)
|
|
24
|
+
continue;
|
|
25
|
+
n = (defaultFields && !f.exclusive) ||
|
|
26
|
+
pick === true || pick?.[k] || include === true || include?.[k];
|
|
27
|
+
if (n) {
|
|
28
|
+
if (f.type instanceof common_1.ComplexType && (typeof n === 'object' || typeof omit?.[k] === 'object')) {
|
|
29
|
+
target[k] = {};
|
|
30
|
+
_transformInclusionProjection(f.type, target[k], pick?.[k] || include?.[k], undefined, omit?.[k], defaultFields);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
target[k] = 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports._transformInclusionProjection = _transformInclusionProjection;
|
|
38
|
+
function _transformExclusionProjection(dataType, target, omit, omitExclusiveFields) {
|
|
39
|
+
let n;
|
|
40
|
+
for (const [k, f] of dataType.fields.entries()) {
|
|
41
|
+
n = omit?.[k] || (omitExclusiveFields && f.exclusive);
|
|
42
|
+
if (n) {
|
|
43
|
+
if (f.type instanceof common_1.ComplexType && typeof n === 'object') {
|
|
44
|
+
target[k] = {};
|
|
45
|
+
_transformExclusionProjection(f.type, target[k], omit?.[k], omitExclusiveFields);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
target[k] = 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports._transformExclusionProjection = _transformExclusionProjection;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function transformSort(sort) {
|
|
4
|
+
if (!(sort && sort.length))
|
|
5
|
+
return;
|
|
6
|
+
const out = {};
|
|
7
|
+
if (sort)
|
|
8
|
+
sort.forEach(k => {
|
|
9
|
+
if (k.startsWith('-'))
|
|
10
|
+
out[k.substring(1)] = -1;
|
|
11
|
+
else if (k.startsWith('+'))
|
|
12
|
+
out[k.substring(1)] = 1;
|
|
13
|
+
else
|
|
14
|
+
out[k] = 1;
|
|
15
|
+
});
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
exports.default = transformSort;
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./mongo-adapter.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./mongo-collection-resource.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./mongo-entity-service.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./mongo-singleton-resource.js"), exports);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoAdapter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lodash_isnil_1 = tslib_1.__importDefault(require("lodash.isnil"));
|
|
6
|
+
const lodash_omitby_1 = tslib_1.__importDefault(require("lodash.omitby"));
|
|
7
|
+
const common_1 = require("@opra/common");
|
|
8
|
+
const transform_filter_js_1 = tslib_1.__importDefault(require("./transform-filter.js"));
|
|
9
|
+
const transform_key_values_js_1 = tslib_1.__importDefault(require("./transform-key-values.js"));
|
|
10
|
+
const transform_patch_js_1 = tslib_1.__importDefault(require("./transform-patch.js"));
|
|
11
|
+
const transform_projection_js_1 = tslib_1.__importDefault(require("./transform-projection.js"));
|
|
12
|
+
const transform_sort_js_1 = tslib_1.__importDefault(require("./transform-sort.js"));
|
|
13
|
+
var MongoAdapter;
|
|
14
|
+
(function (MongoAdapter) {
|
|
15
|
+
MongoAdapter.transformFilter = transform_filter_js_1.default;
|
|
16
|
+
MongoAdapter.transformKeyValues = transform_key_values_js_1.default;
|
|
17
|
+
MongoAdapter.transformPatch = transform_patch_js_1.default;
|
|
18
|
+
MongoAdapter.transformProjection = transform_projection_js_1.default;
|
|
19
|
+
MongoAdapter.transformSort = transform_sort_js_1.default;
|
|
20
|
+
function transformRequest(request) {
|
|
21
|
+
const { resource } = request;
|
|
22
|
+
if (resource instanceof common_1.Collection || resource instanceof common_1.Singleton) {
|
|
23
|
+
const { args, operation } = request;
|
|
24
|
+
let options = {};
|
|
25
|
+
let filter;
|
|
26
|
+
if (operation === 'create' || operation === 'update' ||
|
|
27
|
+
operation === 'get' || operation === 'findMany') {
|
|
28
|
+
options.projection = MongoAdapter.transformProjection(resource.type, args);
|
|
29
|
+
}
|
|
30
|
+
if (resource instanceof common_1.Collection &&
|
|
31
|
+
(operation === 'delete' || operation === 'get' || operation === 'update')) {
|
|
32
|
+
filter = MongoAdapter.transformKeyValues(resource, args.key);
|
|
33
|
+
}
|
|
34
|
+
if (args.filter) {
|
|
35
|
+
const f = MongoAdapter.transformFilter(args.filter);
|
|
36
|
+
filter = filter ? { $and: [filter, f] } : f;
|
|
37
|
+
}
|
|
38
|
+
if (operation === 'findMany') {
|
|
39
|
+
options.sort = args.sort?.length ? args.sort : undefined;
|
|
40
|
+
options.limit = args.limit;
|
|
41
|
+
options.skip = args.skip;
|
|
42
|
+
options.distinct = args.distinct;
|
|
43
|
+
options.count = args.count;
|
|
44
|
+
}
|
|
45
|
+
options = (0, lodash_omitby_1.default)(options, lodash_isnil_1.default);
|
|
46
|
+
switch (operation) {
|
|
47
|
+
case 'create': {
|
|
48
|
+
return {
|
|
49
|
+
method: 'insertOne',
|
|
50
|
+
data: args.data,
|
|
51
|
+
options,
|
|
52
|
+
args: [args.data, options]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
case 'delete':
|
|
56
|
+
case 'deleteMany': {
|
|
57
|
+
return {
|
|
58
|
+
method: (operation === 'delete' ? 'deleteOne' : 'deleteMany'),
|
|
59
|
+
filter,
|
|
60
|
+
options,
|
|
61
|
+
args: [filter, options]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
case 'get': {
|
|
65
|
+
return {
|
|
66
|
+
method: 'findOne',
|
|
67
|
+
filter,
|
|
68
|
+
options,
|
|
69
|
+
args: [filter, options]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
case 'findMany': {
|
|
73
|
+
const out = {
|
|
74
|
+
method: 'find',
|
|
75
|
+
filter,
|
|
76
|
+
options,
|
|
77
|
+
args: [filter, options]
|
|
78
|
+
};
|
|
79
|
+
if (args.count)
|
|
80
|
+
out.count = args.count;
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
case 'update': {
|
|
84
|
+
const update = MongoAdapter.transformPatch(args.data);
|
|
85
|
+
filter = filter || {};
|
|
86
|
+
return {
|
|
87
|
+
method: 'updateOne',
|
|
88
|
+
filter,
|
|
89
|
+
update,
|
|
90
|
+
options,
|
|
91
|
+
args: [filter, update, options]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
case 'updateMany': {
|
|
95
|
+
const update = MongoAdapter.transformPatch(args.data);
|
|
96
|
+
return {
|
|
97
|
+
method: 'updateMany',
|
|
98
|
+
filter,
|
|
99
|
+
update,
|
|
100
|
+
options,
|
|
101
|
+
args: [filter, update, options]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw new TypeError(`Unimplemented request kind (${request.resourceKind}.${request.operation})`);
|
|
107
|
+
}
|
|
108
|
+
MongoAdapter.transformRequest = transformRequest;
|
|
109
|
+
})(MongoAdapter = exports.MongoAdapter || (exports.MongoAdapter = {}));
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoCollectionResource = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@opra/common");
|
|
6
|
+
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
7
|
+
class MongoCollectionResource {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.defaultLimit = 100;
|
|
10
|
+
}
|
|
11
|
+
async create(ctx) {
|
|
12
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
13
|
+
const service = await this.getService(ctx);
|
|
14
|
+
return service.insertOne(prepared.data, prepared.options);
|
|
15
|
+
}
|
|
16
|
+
async delete(ctx) {
|
|
17
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
18
|
+
const service = await this.getService(ctx);
|
|
19
|
+
return service.deleteOne(prepared.filter, prepared.options);
|
|
20
|
+
}
|
|
21
|
+
async deleteMany(ctx) {
|
|
22
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
23
|
+
const service = await this.getService(ctx);
|
|
24
|
+
return service.deleteMany(prepared.filter, prepared.options);
|
|
25
|
+
}
|
|
26
|
+
async get(ctx) {
|
|
27
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
28
|
+
const service = await this.getService(ctx);
|
|
29
|
+
const out = await service.findOne(prepared.filter, prepared.options);
|
|
30
|
+
if (!out)
|
|
31
|
+
throw new common_1.ResourceNotFoundError(service.collectionName, prepared.filter._id);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
async update(ctx) {
|
|
35
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
36
|
+
const service = await this.getService(ctx);
|
|
37
|
+
const out = await service.updateOne(prepared.filter, prepared.update, prepared.options);
|
|
38
|
+
if (!out)
|
|
39
|
+
throw new common_1.ResourceNotFoundError(service.collectionName, prepared.filter._id);
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
async updateMany(ctx) {
|
|
43
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
44
|
+
const service = await this.getService(ctx);
|
|
45
|
+
return service.updateMany(prepared.filter, prepared.update, prepared.options);
|
|
46
|
+
}
|
|
47
|
+
async search(ctx) {
|
|
48
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
49
|
+
const service = await this.getService(ctx);
|
|
50
|
+
if (prepared.count) {
|
|
51
|
+
const [items, count] = await Promise.all([
|
|
52
|
+
service.find(prepared.filter, prepared.options),
|
|
53
|
+
service.count(prepared.filter, prepared.options)
|
|
54
|
+
]);
|
|
55
|
+
ctx.response.count = count;
|
|
56
|
+
return items;
|
|
57
|
+
}
|
|
58
|
+
return service.find(prepared.filter, prepared.options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
tslib_1.__decorate([
|
|
62
|
+
common_1.Collection.Create(),
|
|
63
|
+
tslib_1.__metadata("design:type", Function),
|
|
64
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
65
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
66
|
+
], MongoCollectionResource.prototype, "create", null);
|
|
67
|
+
tslib_1.__decorate([
|
|
68
|
+
common_1.Collection.Delete(),
|
|
69
|
+
tslib_1.__metadata("design:type", Function),
|
|
70
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
71
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
72
|
+
], MongoCollectionResource.prototype, "delete", null);
|
|
73
|
+
tslib_1.__decorate([
|
|
74
|
+
common_1.Collection.DeleteMany(),
|
|
75
|
+
tslib_1.__metadata("design:type", Function),
|
|
76
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
77
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
78
|
+
], MongoCollectionResource.prototype, "deleteMany", null);
|
|
79
|
+
tslib_1.__decorate([
|
|
80
|
+
common_1.Collection.Get(),
|
|
81
|
+
tslib_1.__metadata("design:type", Function),
|
|
82
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
83
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
84
|
+
], MongoCollectionResource.prototype, "get", null);
|
|
85
|
+
tslib_1.__decorate([
|
|
86
|
+
common_1.Collection.Update(),
|
|
87
|
+
tslib_1.__metadata("design:type", Function),
|
|
88
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
89
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
90
|
+
], MongoCollectionResource.prototype, "update", null);
|
|
91
|
+
tslib_1.__decorate([
|
|
92
|
+
common_1.Collection.UpdateMany(),
|
|
93
|
+
tslib_1.__metadata("design:type", Function),
|
|
94
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
95
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
96
|
+
], MongoCollectionResource.prototype, "updateMany", null);
|
|
97
|
+
tslib_1.__decorate([
|
|
98
|
+
common_1.Collection.FindMany(),
|
|
99
|
+
tslib_1.__metadata("design:type", Function),
|
|
100
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
101
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
102
|
+
], MongoCollectionResource.prototype, "search", null);
|
|
103
|
+
exports.MongoCollectionResource = MongoCollectionResource;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoEntityService = void 0;
|
|
4
|
+
class MongoEntityService {
|
|
5
|
+
constructor(collectionName, options) {
|
|
6
|
+
this.collectionName = collectionName;
|
|
7
|
+
this.db = options?.db;
|
|
8
|
+
this.defaultLimit = options?.defaultLimit || 10;
|
|
9
|
+
}
|
|
10
|
+
async count(filter, options) {
|
|
11
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
12
|
+
options = {
|
|
13
|
+
...options,
|
|
14
|
+
session: options?.session || this.session
|
|
15
|
+
};
|
|
16
|
+
try {
|
|
17
|
+
return await collection.count(filter, options) || 0;
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
await this._onError(e);
|
|
21
|
+
throw e;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async deleteOne(filter, options) {
|
|
25
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
26
|
+
options = {
|
|
27
|
+
...options,
|
|
28
|
+
session: options?.session || this.session
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
const r = await collection.deleteOne(filter, options);
|
|
32
|
+
return r.deletedCount;
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
await this._onError(e);
|
|
36
|
+
throw e;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async deleteMany(filter, options) {
|
|
40
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
41
|
+
options = {
|
|
42
|
+
...options,
|
|
43
|
+
session: options?.session || this.session
|
|
44
|
+
};
|
|
45
|
+
try {
|
|
46
|
+
const r = await collection.deleteMany(filter, options);
|
|
47
|
+
return r.deletedCount;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
await this._onError(e);
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async findOne(filter, options) {
|
|
55
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
56
|
+
options = {
|
|
57
|
+
...options,
|
|
58
|
+
session: options?.session || this.session
|
|
59
|
+
};
|
|
60
|
+
let out;
|
|
61
|
+
try {
|
|
62
|
+
out = await collection.findOne(filter, options);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
await this._onError(e);
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
if (this.onTransformRow)
|
|
69
|
+
out = this.onTransformRow(out);
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
async find(filter, options) {
|
|
73
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
74
|
+
options = {
|
|
75
|
+
...options,
|
|
76
|
+
limit: options?.limit || this.defaultLimit,
|
|
77
|
+
session: options?.session || this.session
|
|
78
|
+
};
|
|
79
|
+
const out = [];
|
|
80
|
+
try {
|
|
81
|
+
const cursor = collection.find(filter, options);
|
|
82
|
+
let row;
|
|
83
|
+
while (row = await cursor.next()) {
|
|
84
|
+
if (this.onTransformRow)
|
|
85
|
+
row = this.onTransformRow(row);
|
|
86
|
+
out.push(row);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
await this._onError(e);
|
|
91
|
+
throw e;
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
async insertOne(doc, options) {
|
|
96
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
97
|
+
let out;
|
|
98
|
+
options = {
|
|
99
|
+
...options,
|
|
100
|
+
session: options?.session || this.session
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
const r = await collection.insertOne(doc, options);
|
|
104
|
+
if (r.insertedId)
|
|
105
|
+
out = await collection.findOne({ _id: r.insertedId }, options);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
await this._onError(e);
|
|
109
|
+
throw e;
|
|
110
|
+
}
|
|
111
|
+
if (this.onTransformRow)
|
|
112
|
+
out = this.onTransformRow(out);
|
|
113
|
+
if (!out)
|
|
114
|
+
throw new Error('"insertOne" operation returned no result!');
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
async updateOne(filter, doc, options) {
|
|
118
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
119
|
+
let out;
|
|
120
|
+
options = {
|
|
121
|
+
...options,
|
|
122
|
+
session: options?.session || this.session
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
const r = await collection.updateOne(filter, doc, options);
|
|
126
|
+
if (r.matchedCount)
|
|
127
|
+
out = await collection.findOne((r.upsertedId ? { _id: r.upsertedId } : filter), options);
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
await this._onError(e);
|
|
131
|
+
throw e;
|
|
132
|
+
}
|
|
133
|
+
if (this.onTransformRow)
|
|
134
|
+
out = this.onTransformRow(out);
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
async updateMany(filter, doc, options) {
|
|
138
|
+
const collection = (await this.getDatabase()).collection(this.collectionName);
|
|
139
|
+
options = {
|
|
140
|
+
...options,
|
|
141
|
+
session: options?.session || this.session,
|
|
142
|
+
upsert: false
|
|
143
|
+
};
|
|
144
|
+
try {
|
|
145
|
+
const r = await collection.updateMany(filter, doc, options);
|
|
146
|
+
return r.matchedCount;
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
await this._onError(e);
|
|
150
|
+
throw e;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
with(context, db, session) {
|
|
154
|
+
if (this.context === context && this.db === db && this.session === session)
|
|
155
|
+
return this;
|
|
156
|
+
const instance = { context };
|
|
157
|
+
// Should reset session if db changed
|
|
158
|
+
if (db) {
|
|
159
|
+
instance.db = db;
|
|
160
|
+
instance.session = session;
|
|
161
|
+
}
|
|
162
|
+
if (session)
|
|
163
|
+
instance.session = session;
|
|
164
|
+
Object.setPrototypeOf(instance, this);
|
|
165
|
+
return instance;
|
|
166
|
+
}
|
|
167
|
+
async _onError(error) {
|
|
168
|
+
if (this.onError)
|
|
169
|
+
await this.onError(error);
|
|
170
|
+
}
|
|
171
|
+
getDatabase() {
|
|
172
|
+
if (!this.context)
|
|
173
|
+
throw new Error(`Context not set!`);
|
|
174
|
+
if (!this.db)
|
|
175
|
+
throw new Error(`Database not set!`);
|
|
176
|
+
return this.db;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.MongoEntityService = MongoEntityService;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoSingletonResource = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@opra/common");
|
|
6
|
+
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
7
|
+
class MongoSingletonResource {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.defaultLimit = 100;
|
|
10
|
+
}
|
|
11
|
+
async create(ctx) {
|
|
12
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
13
|
+
const service = await this.getService(ctx);
|
|
14
|
+
await service.deleteMany();
|
|
15
|
+
return service.insertOne(prepared.data, prepared.options);
|
|
16
|
+
}
|
|
17
|
+
async delete(ctx) {
|
|
18
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
19
|
+
const service = await this.getService(ctx);
|
|
20
|
+
return service.deleteOne(prepared.filter, prepared.options);
|
|
21
|
+
}
|
|
22
|
+
async get(ctx) {
|
|
23
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
24
|
+
const service = await this.getService(ctx);
|
|
25
|
+
const out = await service.findOne(prepared.filter, prepared.options);
|
|
26
|
+
if (!out)
|
|
27
|
+
throw new common_1.ResourceNotFoundError(service.collectionName);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
async update(ctx) {
|
|
31
|
+
const prepared = mongo_adapter_js_1.MongoAdapter.transformRequest(ctx.request);
|
|
32
|
+
const service = await this.getService(ctx);
|
|
33
|
+
const out = await service.updateOne(prepared.filter, prepared.update, prepared.options);
|
|
34
|
+
if (!out)
|
|
35
|
+
throw new common_1.ResourceNotFoundError(service.collectionName, prepared.filter._id);
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
tslib_1.__decorate([
|
|
40
|
+
common_1.Singleton.Create(),
|
|
41
|
+
tslib_1.__metadata("design:type", Function),
|
|
42
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
43
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
44
|
+
], MongoSingletonResource.prototype, "create", null);
|
|
45
|
+
tslib_1.__decorate([
|
|
46
|
+
common_1.Singleton.Delete(),
|
|
47
|
+
tslib_1.__metadata("design:type", Function),
|
|
48
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
49
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
50
|
+
], MongoSingletonResource.prototype, "delete", null);
|
|
51
|
+
tslib_1.__decorate([
|
|
52
|
+
common_1.Singleton.Get(),
|
|
53
|
+
tslib_1.__metadata("design:type", Function),
|
|
54
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
55
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
56
|
+
], MongoSingletonResource.prototype, "get", null);
|
|
57
|
+
tslib_1.__decorate([
|
|
58
|
+
common_1.Singleton.Update(),
|
|
59
|
+
tslib_1.__metadata("design:type", Function),
|
|
60
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
61
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
62
|
+
], MongoSingletonResource.prototype, "update", null);
|
|
63
|
+
exports.MongoSingletonResource = MongoSingletonResource;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const common_1 = require("@opra/common");
|
|
4
|
+
function transformFilter(str) {
|
|
5
|
+
const ast = typeof str === 'string' ? (0, common_1.parseFilter)(str) : str;
|
|
6
|
+
if (!ast)
|
|
7
|
+
return;
|
|
8
|
+
if (ast instanceof common_1.ComparisonExpression) {
|
|
9
|
+
const left = ast.left instanceof common_1.QualifiedIdentifier
|
|
10
|
+
? ast.left.value
|
|
11
|
+
: transformFilter(ast.left);
|
|
12
|
+
const right = transformFilter(ast.right);
|
|
13
|
+
switch (ast.op) {
|
|
14
|
+
case '=':
|
|
15
|
+
return { [left]: right };
|
|
16
|
+
case '!=':
|
|
17
|
+
return { [left]: { $ne: right } };
|
|
18
|
+
case '>':
|
|
19
|
+
return { [left]: { $gt: right } };
|
|
20
|
+
case '>=':
|
|
21
|
+
return { [left]: { $gte: right } };
|
|
22
|
+
case '<':
|
|
23
|
+
return { [left]: { $lt: right } };
|
|
24
|
+
case '<=':
|
|
25
|
+
return { [left]: { $lte: right } };
|
|
26
|
+
case 'in':
|
|
27
|
+
return { [left]: { $in: Array.isArray(right) ? right : [right] } };
|
|
28
|
+
case '!in':
|
|
29
|
+
return { [left]: { $nin: Array.isArray(right) ? right : [right] } };
|
|
30
|
+
case 'like':
|
|
31
|
+
return {
|
|
32
|
+
[left]: {
|
|
33
|
+
$text: {
|
|
34
|
+
$search: '\\"' + right.replace(/\\"/, '"') + '\\"',
|
|
35
|
+
$caseSensitive: true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
case 'ilike':
|
|
40
|
+
return {
|
|
41
|
+
[left]: {
|
|
42
|
+
$text: {
|
|
43
|
+
$search: '\\"' + right.replace(/\\"/, '"') + '\\"'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
case '!like':
|
|
48
|
+
return {
|
|
49
|
+
[left]: {
|
|
50
|
+
$not: {
|
|
51
|
+
$text: {
|
|
52
|
+
$search: '\\"' + right.replace(/\\"/, '"') + '\\"',
|
|
53
|
+
$caseSensitive: true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
case '!ilike':
|
|
59
|
+
return {
|
|
60
|
+
[left]: {
|
|
61
|
+
$not: {
|
|
62
|
+
$text: {
|
|
63
|
+
$search: '\\"' + right.replace(/\\"/, '"') + '\\"'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(`ComparisonExpression operator (${ast.op}) not implemented yet`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (ast instanceof common_1.QualifiedIdentifier) {
|
|
73
|
+
return ast.value;
|
|
74
|
+
}
|
|
75
|
+
if (ast instanceof common_1.NumberLiteral ||
|
|
76
|
+
ast instanceof common_1.StringLiteral ||
|
|
77
|
+
ast instanceof common_1.BooleanLiteral ||
|
|
78
|
+
ast instanceof common_1.NullLiteral ||
|
|
79
|
+
ast instanceof common_1.DateLiteral ||
|
|
80
|
+
ast instanceof common_1.TimeLiteral) {
|
|
81
|
+
return ast.value;
|
|
82
|
+
}
|
|
83
|
+
if (ast instanceof common_1.ArrayExpression) {
|
|
84
|
+
return ast.items.map(transformFilter);
|
|
85
|
+
}
|
|
86
|
+
if (ast instanceof common_1.LogicalExpression) {
|
|
87
|
+
if (ast.op === 'or')
|
|
88
|
+
return { $or: ast.items.map(transformFilter) };
|
|
89
|
+
return { $and: ast.items.map(transformFilter) };
|
|
90
|
+
}
|
|
91
|
+
if (ast instanceof common_1.ParenthesesExpression) {
|
|
92
|
+
return transformFilter(ast.expression);
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`${ast.type} is not implemented yet`);
|
|
95
|
+
}
|
|
96
|
+
exports.default = transformFilter;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function transformKeyValues(resource, keyValues) {
|
|
4
|
+
const { primaryKey } = resource;
|
|
5
|
+
if (primaryKey.length > 1) {
|
|
6
|
+
const query = {};
|
|
7
|
+
primaryKey.forEach((k, i) => {
|
|
8
|
+
query[k] = typeof keyValues === 'object' ? keyValues[k] : keyValues[i];
|
|
9
|
+
});
|
|
10
|
+
return query;
|
|
11
|
+
}
|
|
12
|
+
return { [primaryKey[0]]: keyValues };
|
|
13
|
+
}
|
|
14
|
+
exports.default = transformKeyValues;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function transformPatch(doc) {
|
|
4
|
+
const trg = {};
|
|
5
|
+
_transformPatch(doc, trg);
|
|
6
|
+
return trg;
|
|
7
|
+
}
|
|
8
|
+
exports.default = transformPatch;
|
|
9
|
+
function _transformPatch(src, trg = {}, path = '') {
|
|
10
|
+
let fieldName;
|
|
11
|
+
for (const [k, v] of Object.entries(src)) {
|
|
12
|
+
fieldName = k.startsWith('*') ? k.substring(1) : k;
|
|
13
|
+
const key = path ? path + '.' + fieldName : fieldName;
|
|
14
|
+
if (v == null) {
|
|
15
|
+
trg.$unset = trg.$unset || {};
|
|
16
|
+
trg.$unset[key] = '';
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (v && typeof v === 'object') {
|
|
20
|
+
// If field name starts with "*", do "replace" operation except "merge"
|
|
21
|
+
if (!k.startsWith('*')) {
|
|
22
|
+
_transformPatch(v, trg, key);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
trg.$set = trg.$set || {};
|
|
27
|
+
trg.$set[key] = v;
|
|
28
|
+
}
|
|
29
|
+
return trg;
|
|
30
|
+
}
|