@opra/mongodb 0.33.13 → 1.0.0-alpha.2
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/adapter-utils/prepare-filter.js +20 -28
- package/cjs/adapter-utils/prepare-projection.js +40 -39
- package/cjs/index.js +1 -2
- package/cjs/mongo-adapter.js +66 -1
- package/cjs/mongo-collection-service.js +72 -313
- package/cjs/mongo-entity-service.js +329 -0
- package/cjs/{mongo-array-service.js → mongo-nested-service.js} +231 -225
- package/cjs/mongo-service.js +124 -183
- package/cjs/mongo-singleton-service.js +28 -124
- package/esm/adapter-utils/prepare-filter.js +20 -28
- package/esm/adapter-utils/prepare-projection.js +39 -38
- package/esm/index.js +1 -2
- package/esm/mongo-adapter.js +66 -1
- package/esm/mongo-collection-service.js +73 -313
- package/esm/mongo-entity-service.js +324 -0
- package/esm/mongo-nested-service.js +569 -0
- package/esm/mongo-service.js +125 -184
- package/esm/mongo-singleton-service.js +29 -125
- package/package.json +9 -8
- package/types/adapter-utils/prepare-filter.d.ts +2 -3
- package/types/adapter-utils/prepare-projection.d.ts +4 -13
- package/types/index.d.ts +1 -2
- package/types/mongo-adapter.d.ts +14 -1
- package/types/mongo-collection-service.d.ts +88 -251
- package/types/mongo-entity-service.d.ts +149 -0
- package/types/mongo-nested-service.d.ts +258 -0
- package/types/mongo-service.d.ts +208 -82
- package/types/mongo-singleton-service.d.ts +39 -148
- package/cjs/types.js +0 -2
- package/esm/mongo-array-service.js +0 -563
- package/esm/types.js +0 -1
- package/types/mongo-array-service.d.ts +0 -409
- package/types/types.d.ts +0 -3
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import {
|
|
2
|
+
import { ResourceNotAvailableError } from '@opra/common';
|
|
3
3
|
import { MongoAdapter } from './mongo-adapter.js';
|
|
4
|
-
import {
|
|
4
|
+
import { MongoEntityService } from './mongo-entity-service.js';
|
|
5
5
|
/**
|
|
6
6
|
* A class that provides access to a MongoDB collection, with support for singleton document operations.
|
|
7
7
|
* @class MongoSingletonService
|
|
8
8
|
* @extends MongoService
|
|
9
9
|
* @template T - The type of document stored in the collection
|
|
10
10
|
*/
|
|
11
|
-
export class MongoSingletonService extends
|
|
11
|
+
export class MongoSingletonService extends MongoEntityService {
|
|
12
12
|
/**
|
|
13
13
|
* Constructs a new instance
|
|
14
14
|
*
|
|
@@ -18,14 +18,12 @@ export class MongoSingletonService extends MongoService {
|
|
|
18
18
|
*/
|
|
19
19
|
constructor(dataType, options) {
|
|
20
20
|
super(dataType, options);
|
|
21
|
-
this.collectionKey = this.collectionKey || options?.collectionKey || '_id';
|
|
22
21
|
this._id = this._id || options?._id || new ObjectId('655608925cad472b75fc6485');
|
|
23
|
-
this.$documentFilter = this.$documentFilter || options?.documentFilter;
|
|
24
|
-
this.$interceptor = this.$interceptor || options?.interceptor;
|
|
25
22
|
}
|
|
26
23
|
/**
|
|
27
24
|
* Asserts the existence of a resource based on the given options.
|
|
28
25
|
*
|
|
26
|
+
* @param {MongoSingletonService.ExistsOptions<T>} [options]
|
|
29
27
|
* @returns {Promise<void>} A Promise that resolves when the resource exists.
|
|
30
28
|
* @throws {ResourceNotAvailableError} If the resource does not exist.
|
|
31
29
|
*/
|
|
@@ -36,37 +34,23 @@ export class MongoSingletonService extends MongoService {
|
|
|
36
34
|
/**
|
|
37
35
|
* Creates the document in the database.
|
|
38
36
|
*
|
|
39
|
-
* @param {
|
|
37
|
+
* @param {PartialDTO<T>} input - The partial input to create the document with.
|
|
40
38
|
* @param {MongoSingletonService.CreateOptions} [options] - The options for creating the document.
|
|
41
39
|
* @return {Promise<PartialDTO<T>>} A promise that resolves to the partial output of the created document.
|
|
42
40
|
* @throws {Error} Throws an error if an unknown error occurs while creating the document.
|
|
43
41
|
*/
|
|
44
42
|
async create(input, options) {
|
|
43
|
+
input._id = this._id;
|
|
45
44
|
const info = {
|
|
46
45
|
crud: 'create',
|
|
47
46
|
method: 'create',
|
|
47
|
+
byId: false,
|
|
48
|
+
documentId: this._id,
|
|
48
49
|
input,
|
|
49
50
|
options,
|
|
50
51
|
};
|
|
51
52
|
return this._intercept(() => this._create(input, options), info);
|
|
52
53
|
}
|
|
53
|
-
async _create(input, options) {
|
|
54
|
-
const encode = this.getEncoder('create');
|
|
55
|
-
const doc = encode(input);
|
|
56
|
-
doc._id = this._id;
|
|
57
|
-
const r = await this.__insertOne(doc, options);
|
|
58
|
-
if (r.insertedId) {
|
|
59
|
-
if (!options)
|
|
60
|
-
return doc;
|
|
61
|
-
const out = await this._findOne(options);
|
|
62
|
-
if (out)
|
|
63
|
-
return out;
|
|
64
|
-
if (!out)
|
|
65
|
-
throw new ResourceNotAvailableError(this.getResourceName());
|
|
66
|
-
}
|
|
67
|
-
/* istanbul ignore next */
|
|
68
|
-
throw new InternalServerError(`Unknown error while creating document for "${this.getResourceName()}"`);
|
|
69
|
-
}
|
|
70
54
|
/**
|
|
71
55
|
* Deletes a record from the database
|
|
72
56
|
*
|
|
@@ -77,77 +61,51 @@ export class MongoSingletonService extends MongoService {
|
|
|
77
61
|
const info = {
|
|
78
62
|
crud: 'delete',
|
|
79
63
|
method: 'delete',
|
|
64
|
+
byId: true,
|
|
65
|
+
documentId: this._id,
|
|
80
66
|
options,
|
|
81
67
|
};
|
|
82
68
|
return this._intercept(async () => {
|
|
83
|
-
const filter = MongoAdapter.prepareFilter([
|
|
84
|
-
|
|
85
|
-
options?.filter
|
|
86
|
-
]);
|
|
87
|
-
return this._delete({ ...options, filter });
|
|
69
|
+
const filter = MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
|
|
70
|
+
return this._delete(this._id, { ...options, filter });
|
|
88
71
|
}, info);
|
|
89
72
|
}
|
|
90
|
-
async _delete(options) {
|
|
91
|
-
const filter = MongoAdapter.prepareFilter([
|
|
92
|
-
{ _id: this._id },
|
|
93
|
-
options?.filter
|
|
94
|
-
]);
|
|
95
|
-
const r = await this.__deleteOne(filter, options);
|
|
96
|
-
return r.deletedCount;
|
|
97
|
-
}
|
|
98
73
|
/**
|
|
99
74
|
* Checks if the document exists in the database.
|
|
100
75
|
*
|
|
101
76
|
* @return {Promise<boolean>} - A promise that resolves to a boolean value indicating if the document exists.
|
|
102
77
|
*/
|
|
103
78
|
async exists(options) {
|
|
104
|
-
return !!(await this.
|
|
79
|
+
return !!(await this.find({ ...options, projection: ['_id'], skip: undefined }));
|
|
105
80
|
}
|
|
106
81
|
/**
|
|
107
82
|
* Fetches the document if it exists. Returns undefined if not found.
|
|
108
83
|
*
|
|
109
|
-
* @param {MongoSingletonService.
|
|
84
|
+
* @param {MongoSingletonService.FindOneOptions<T>} [options] - The options for finding the document.
|
|
110
85
|
* @returns {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the found document or undefined if not found.
|
|
111
86
|
*/
|
|
112
|
-
async
|
|
87
|
+
async find(options) {
|
|
113
88
|
const info = {
|
|
114
89
|
crud: 'read',
|
|
115
90
|
method: 'findOne',
|
|
91
|
+
byId: true,
|
|
92
|
+
documentId: this._id,
|
|
116
93
|
options,
|
|
117
94
|
};
|
|
118
95
|
return this._intercept(async () => {
|
|
119
|
-
const filter = MongoAdapter.prepareFilter([
|
|
120
|
-
|
|
121
|
-
options?.filter
|
|
122
|
-
]);
|
|
123
|
-
return this._findOne({ ...options, filter });
|
|
96
|
+
const filter = MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
|
|
97
|
+
return this._findById(this._id, { ...options, filter });
|
|
124
98
|
}, info);
|
|
125
99
|
}
|
|
126
|
-
async _findOne(options) {
|
|
127
|
-
const filter = MongoAdapter.prepareFilter([
|
|
128
|
-
{ _id: this._id },
|
|
129
|
-
options?.filter
|
|
130
|
-
]);
|
|
131
|
-
const mongoOptions = {
|
|
132
|
-
...options,
|
|
133
|
-
projection: MongoAdapter.prepareProjection(this.getDataType(), options),
|
|
134
|
-
sort: undefined,
|
|
135
|
-
skip: undefined,
|
|
136
|
-
limit: undefined
|
|
137
|
-
};
|
|
138
|
-
const decoder = this.getDecoder();
|
|
139
|
-
const out = await this.__findOne(filter, mongoOptions);
|
|
140
|
-
return out ? decoder(out) : undefined;
|
|
141
|
-
}
|
|
142
100
|
/**
|
|
143
101
|
* Fetches the document from the Mongo collection service. Throws error if not found.
|
|
144
102
|
*
|
|
145
|
-
* @param {
|
|
103
|
+
* @param {MongoSingletonService.FindOneOptions<T>} options - The options to customize the query.
|
|
146
104
|
* @return {Promise<PartialDTO<T>>} - A promise that resolves to the fetched document.
|
|
147
105
|
* @throws {ResourceNotAvailableError} - If the document is not found in the collection.
|
|
148
106
|
*/
|
|
149
107
|
async get(options) {
|
|
150
|
-
const out = await this.
|
|
108
|
+
const out = await this.find(options);
|
|
151
109
|
if (!out)
|
|
152
110
|
throw new ResourceNotAvailableError(this.getResourceName());
|
|
153
111
|
return out;
|
|
@@ -164,34 +122,16 @@ export class MongoSingletonService extends MongoService {
|
|
|
164
122
|
const info = {
|
|
165
123
|
crud: 'update',
|
|
166
124
|
method: 'update',
|
|
125
|
+
byId: true,
|
|
126
|
+
documentId: this._id,
|
|
167
127
|
input,
|
|
168
128
|
options,
|
|
169
129
|
};
|
|
170
130
|
return this._intercept(async () => {
|
|
171
|
-
const filter = MongoAdapter.prepareFilter([
|
|
172
|
-
|
|
173
|
-
options?.filter
|
|
174
|
-
]);
|
|
175
|
-
return this._updateOnly(input, { ...options, filter });
|
|
131
|
+
const filter = MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
|
|
132
|
+
return this._updateOnly(this._id, input, { ...options, filter });
|
|
176
133
|
}, info);
|
|
177
134
|
}
|
|
178
|
-
async _updateOnly(input, options) {
|
|
179
|
-
const encode = this.getEncoder('update');
|
|
180
|
-
const doc = encode(input);
|
|
181
|
-
const patch = MongoAdapter.preparePatch(doc);
|
|
182
|
-
const mongoOptions = {
|
|
183
|
-
...options,
|
|
184
|
-
includeResultMetadata: false,
|
|
185
|
-
upsert: undefined,
|
|
186
|
-
projection: MongoAdapter.prepareProjection(this.getDataType(), options),
|
|
187
|
-
};
|
|
188
|
-
const filter = MongoAdapter.prepareFilter([
|
|
189
|
-
{ _id: this._id },
|
|
190
|
-
options?.filter
|
|
191
|
-
]);
|
|
192
|
-
const r = await this.__updateOne(filter, patch, mongoOptions);
|
|
193
|
-
return r.modifiedCount;
|
|
194
|
-
}
|
|
195
135
|
/**
|
|
196
136
|
* Updates a document in the MongoDB collection.
|
|
197
137
|
*
|
|
@@ -204,50 +144,14 @@ export class MongoSingletonService extends MongoService {
|
|
|
204
144
|
const info = {
|
|
205
145
|
crud: 'update',
|
|
206
146
|
method: 'update',
|
|
147
|
+
byId: true,
|
|
148
|
+
documentId: this._id,
|
|
207
149
|
input,
|
|
208
150
|
options,
|
|
209
151
|
};
|
|
210
152
|
return this._intercept(async () => {
|
|
211
|
-
const filter = MongoAdapter.prepareFilter([
|
|
212
|
-
|
|
213
|
-
options?.filter
|
|
214
|
-
]);
|
|
215
|
-
return this._update(input, { ...options, filter });
|
|
153
|
+
const filter = MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
|
|
154
|
+
return this._update(this._id, input, { ...options, filter });
|
|
216
155
|
}, info);
|
|
217
156
|
}
|
|
218
|
-
async _update(input, options) {
|
|
219
|
-
const encode = this.getEncoder('update');
|
|
220
|
-
const doc = encode(input);
|
|
221
|
-
const patch = MongoAdapter.preparePatch(doc);
|
|
222
|
-
const mongoOptions = {
|
|
223
|
-
...options,
|
|
224
|
-
includeResultMetadata: false,
|
|
225
|
-
upsert: undefined,
|
|
226
|
-
projection: MongoAdapter.prepareProjection(this.getDataType(), options),
|
|
227
|
-
};
|
|
228
|
-
const filter = MongoAdapter.prepareFilter([
|
|
229
|
-
{ _id: this._id },
|
|
230
|
-
options?.filter
|
|
231
|
-
]);
|
|
232
|
-
const decoder = this.getDecoder();
|
|
233
|
-
const out = await this.__findOneAndUpdate(filter, patch, mongoOptions);
|
|
234
|
-
return out ? decoder(out) : undefined;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Retrieves the common filter used for querying the document.
|
|
238
|
-
* This method is mostly used for security issues like securing multi-tenant applications.
|
|
239
|
-
*
|
|
240
|
-
* @protected
|
|
241
|
-
* @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
|
|
242
|
-
* that resolves to the common filter, or undefined if not available.
|
|
243
|
-
*/
|
|
244
|
-
_getDocumentFilter(args) {
|
|
245
|
-
return typeof this.$documentFilter === 'function' ?
|
|
246
|
-
this.$documentFilter(args, this) : this.$documentFilter;
|
|
247
|
-
}
|
|
248
|
-
async _intercept(callback, args) {
|
|
249
|
-
if (this.$interceptor)
|
|
250
|
-
return this.$interceptor(callback, args, this);
|
|
251
|
-
return callback();
|
|
252
|
-
}
|
|
253
157
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/mongodb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha.2",
|
|
4
4
|
"description": "Opra MongoDB adapter package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"build:esm": "tsc -b tsconfig-build-esm.json",
|
|
18
18
|
"postbuild": "cp README.md package.json ../../LICENSE ../../build/mongodb && cp ../../package.cjs.json ../../build/mongodb/cjs/package.json",
|
|
19
19
|
"lint": "eslint . --max-warnings=0",
|
|
20
|
+
"format": "prettier . --write --log-level=warn",
|
|
20
21
|
"test": "jest",
|
|
21
22
|
"cover": "jest --collect-coverage",
|
|
22
23
|
"clean": "npm run clean:src && npm run clean:dist && npm run clean:cover",
|
|
@@ -25,14 +26,14 @@
|
|
|
25
26
|
"clean:cover": "rimraf ../../coverage/mongodb"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"@faker-js/faker": "^8.4.
|
|
29
|
-
"mongodb": "^6.
|
|
30
|
-
"ts-gems": "^3.
|
|
29
|
+
"@faker-js/faker": "^8.4.1",
|
|
30
|
+
"mongodb": "^6.7.0",
|
|
31
|
+
"ts-gems": "^3.4.0"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"@opra/common": "^0.
|
|
34
|
-
"@opra/core": "^0.
|
|
35
|
-
"mongodb": ">=6.
|
|
34
|
+
"@opra/common": "^1.0.0-alpha.2",
|
|
35
|
+
"@opra/core": "^1.0.0-alpha.2",
|
|
36
|
+
"mongodb": ">= 6.0.0"
|
|
36
37
|
},
|
|
37
38
|
"type": "module",
|
|
38
39
|
"module": "./esm/index.js",
|
|
@@ -55,4 +56,4 @@
|
|
|
55
56
|
"mongodb",
|
|
56
57
|
"adapter"
|
|
57
58
|
]
|
|
58
|
-
}
|
|
59
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import mongodb from 'mongodb';
|
|
2
|
-
import {
|
|
3
|
-
export type FilterInput = (OpraFilter.Expression | mongodb.Filter<any> | string | undefined);
|
|
2
|
+
import type { MongoAdapter } from '../mongo-adapter.js';
|
|
4
3
|
/**
|
|
5
4
|
* Prepare the MongoDB filter based on the provided filters and options.
|
|
6
5
|
*
|
|
@@ -10,6 +9,6 @@ export type FilterInput = (OpraFilter.Expression | mongodb.Filter<any> | string
|
|
|
10
9
|
*
|
|
11
10
|
* @returns {mongodb.Filter<any>} - The prepared MongoDB filter.
|
|
12
11
|
*/
|
|
13
|
-
export default function prepareFilter(filters: FilterInput | FilterInput[], options?: {
|
|
12
|
+
export default function prepareFilter(filters: MongoAdapter.FilterInput | MongoAdapter.FilterInput[], options?: {
|
|
14
13
|
fieldPrefix?: string;
|
|
15
14
|
}): mongodb.Filter<any>;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import mongodb from 'mongodb';
|
|
2
|
-
import { ComplexType } from '@opra/common';
|
|
3
|
-
export default function prepareProjection(dataType: ComplexType,
|
|
4
|
-
|
|
5
|
-
omit?: string[];
|
|
6
|
-
include?: string[];
|
|
7
|
-
}): mongodb.Document | undefined;
|
|
8
|
-
export declare function _prepareProjection(dataType: ComplexType, target: mongodb.Document, options: {
|
|
9
|
-
pickActivated: boolean;
|
|
10
|
-
include?: any;
|
|
11
|
-
pick?: any;
|
|
12
|
-
omit?: any;
|
|
13
|
-
}): void;
|
|
1
|
+
import mongodb, { Document } from 'mongodb';
|
|
2
|
+
import { ComplexType, FieldsProjection } from '@opra/common';
|
|
3
|
+
export default function prepareProjection(dataType: ComplexType, projection?: string | string[] | Document): mongodb.Document | undefined;
|
|
4
|
+
export declare function prepare(dataType: ComplexType, target: mongodb.Document, projection?: FieldsProjection): void;
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from './mongo-adapter.js';
|
|
2
|
-
export * from './mongo-
|
|
2
|
+
export * from './mongo-nested-service.js';
|
|
3
3
|
export * from './mongo-collection-service.js';
|
|
4
4
|
export * from './mongo-service.js';
|
|
5
5
|
export * from './mongo-singleton-service.js';
|
|
6
|
-
export * from './types.js';
|
package/types/mongo-adapter.d.ts
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
+
import mongodb, { ClientSession, ObjectId } from 'mongodb';
|
|
2
|
+
import { OpraFilter } from '@opra/common';
|
|
3
|
+
import { HttpContext } from '@opra/core';
|
|
1
4
|
import _prepareFilter from './adapter-utils/prepare-filter.js';
|
|
2
5
|
import _prepareKeyValues from './adapter-utils/prepare-key-values.js';
|
|
3
6
|
import _preparePatch from './adapter-utils/prepare-patch.js';
|
|
4
7
|
import _prepareProjection from './adapter-utils/prepare-projection.js';
|
|
5
8
|
import _prepareSort from './adapter-utils/prepare-sort.js';
|
|
6
9
|
export declare namespace MongoAdapter {
|
|
7
|
-
|
|
10
|
+
type AnyId = string | number | ObjectId;
|
|
11
|
+
type FilterInput = OpraFilter.Expression | mongodb.Filter<any> | string | undefined;
|
|
12
|
+
type WithTransactionCallback = (session: ClientSession) => any;
|
|
8
13
|
const prepareFilter: typeof _prepareFilter;
|
|
14
|
+
const prepareKeyValues: typeof _prepareKeyValues;
|
|
9
15
|
const preparePatch: typeof _preparePatch;
|
|
10
16
|
const prepareProjection: typeof _prepareProjection;
|
|
11
17
|
const prepareSort: typeof _prepareSort;
|
|
18
|
+
interface TransformedRequest {
|
|
19
|
+
method: 'create' | 'delete' | 'deleteMany' | 'get' | 'findMany' | 'update' | 'updateMany';
|
|
20
|
+
key?: any;
|
|
21
|
+
data?: any;
|
|
22
|
+
options: any;
|
|
23
|
+
}
|
|
24
|
+
function parseRequest(context: HttpContext): Promise<TransformedRequest>;
|
|
12
25
|
}
|