@twin.org/entity-storage-connector-mongodb 0.0.2-next.9 → 0.0.3-next.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/dist/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IMongoDbEntityStorageConnectorConfig.js +4 -0
- package/dist/es/models/IMongoDbEntityStorageConnectorConfig.js.map +1 -0
- package/dist/es/models/IMongoDbEntityStorageConnectorConstructorOptions.js +2 -0
- package/dist/es/models/IMongoDbEntityStorageConnectorConstructorOptions.js.map +1 -0
- package/dist/{esm/index.mjs → es/mongoDbEntityStorageConnector.js} +99 -40
- package/dist/es/mongoDbEntityStorageConnector.js.map +1 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/IMongoDbEntityStorageConnectorConstructorOptions.d.ts +5 -1
- package/dist/types/mongoDbEntityStorageConnector.d.ts +10 -5
- package/docs/changelog.md +61 -0
- package/docs/reference/classes/MongoDbEntityStorageConnector.md +24 -10
- package/docs/reference/interfaces/IMongoDbEntityStorageConnectorConstructorOptions.md +8 -0
- package/locales/en.json +2 -5
- package/package.json +13 -10
- package/dist/cjs/index.cjs +0 -335
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./mongoDbEntityStorageConnector.js";
|
|
4
|
+
export * from "./models/IMongoDbEntityStorageConnectorConfig.js";
|
|
5
|
+
export * from "./models/IMongoDbEntityStorageConnectorConstructorOptions.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kDAAkD,CAAC;AACjE,cAAc,8DAA8D,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./mongoDbEntityStorageConnector.js\";\nexport * from \"./models/IMongoDbEntityStorageConnectorConfig.js\";\nexport * from \"./models/IMongoDbEntityStorageConnectorConstructorOptions.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IMongoDbEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IMongoDbEntityStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the MongoDb Entity Storage Connector.\n */\nexport interface IMongoDbEntityStorageConnectorConfig {\n\t/**\n\t * The host for the MongoDb instance.\n\t */\n\thost: string;\n\n\t/**\n\t * The port for the MongoDb instance.\n\t */\n\tport?: number;\n\n\t/**\n\t * The user for the MongoDb instance.\n\t */\n\tuser?: string;\n\n\t/**\n\t * The password for the MongoDb instance.\n\t */\n\tpassword?: string;\n\n\t/**\n\t * The name of the database to be used.\n\t */\n\tdatabase: string;\n\n\t/**\n\t * The name of the collection to be used.\n\t */\n\tcollection: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IMongoDbEntityStorageConnectorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IMongoDbEntityStorageConnectorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMongoDbEntityStorageConnectorConfig } from \"./IMongoDbEntityStorageConnectorConfig.js\";\n\n/**\n * The options for the MongoDb entity storage connector constructor.\n */\nexport interface IMongoDbEntityStorageConnectorConstructorOptions {\n\t/**\n\t * The schema for the entity.\n\t */\n\tentitySchema: string;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t */\n\tpartitionContextIds?: string[];\n\n\t/**\n\t * The type of logging component to use.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The configuration for the connector.\n\t */\n\tconfig: IMongoDbEntityStorageConnectorConfig;\n}\n"]}
|
|
@@ -1,27 +1,37 @@
|
|
|
1
|
-
import { Guards, ComponentFactory, BaseError, Is, GeneralError } from '@twin.org/core';
|
|
2
|
-
import { EntitySchemaFactory, EntitySchemaHelper, LogicalOperator, ComparisonOperator } from '@twin.org/entity';
|
|
3
|
-
import { MongoClient } from 'mongodb';
|
|
4
|
-
|
|
5
1
|
// Copyright 2024 IOTA Stiftung.
|
|
6
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
|
|
4
|
+
import { BaseError, ComponentFactory, GeneralError, Guards, Is, ObjectHelper } from "@twin.org/core";
|
|
5
|
+
import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, LogicalOperator } from "@twin.org/entity";
|
|
6
|
+
import { MongoClient } from "mongodb";
|
|
7
7
|
/**
|
|
8
8
|
* Class for performing entity storage operations using MongoDb.
|
|
9
9
|
*/
|
|
10
|
-
class MongoDbEntityStorageConnector {
|
|
10
|
+
export class MongoDbEntityStorageConnector {
|
|
11
|
+
/**
|
|
12
|
+
* Runtime name for the class.
|
|
13
|
+
*/
|
|
14
|
+
static CLASS_NAME = "MongoDbEntityStorageConnector";
|
|
11
15
|
/**
|
|
12
16
|
* Limit the number of entities when finding.
|
|
13
17
|
* @internal
|
|
14
18
|
*/
|
|
15
|
-
static
|
|
19
|
+
static _DEFAULT_LIMIT = 40;
|
|
16
20
|
/**
|
|
17
|
-
*
|
|
21
|
+
* Partition id field name.
|
|
22
|
+
* @internal
|
|
18
23
|
*/
|
|
19
|
-
|
|
24
|
+
static _PARTITION_KEY = "partitionId";
|
|
20
25
|
/**
|
|
21
26
|
* The schema for the entity.
|
|
22
27
|
* @internal
|
|
23
28
|
*/
|
|
24
29
|
_entitySchema;
|
|
30
|
+
/**
|
|
31
|
+
* The keys to use from the context ids to create partitions.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
_partitionContextIds;
|
|
25
35
|
/**
|
|
26
36
|
* The configuration for the connector.
|
|
27
37
|
* @internal
|
|
@@ -37,13 +47,14 @@ class MongoDbEntityStorageConnector {
|
|
|
37
47
|
* @param options The options for the connector.
|
|
38
48
|
*/
|
|
39
49
|
constructor(options) {
|
|
40
|
-
Guards.object(
|
|
41
|
-
Guards.stringValue(
|
|
42
|
-
Guards.object(
|
|
43
|
-
Guards.stringValue(
|
|
44
|
-
Guards.stringValue(
|
|
45
|
-
Guards.stringValue(
|
|
50
|
+
Guards.object(MongoDbEntityStorageConnector.CLASS_NAME, "options", options);
|
|
51
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
52
|
+
Guards.object(MongoDbEntityStorageConnector.CLASS_NAME, "options.config", options.config);
|
|
53
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "options.config.host", options.config.host);
|
|
54
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "options.config.database", options.config.database);
|
|
55
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "options.config.collection", options.config.collection);
|
|
46
56
|
this._entitySchema = EntitySchemaFactory.get(options.entitySchema);
|
|
57
|
+
this._partitionContextIds = options.partitionContextIds;
|
|
47
58
|
this._config = options.config;
|
|
48
59
|
this._client = new MongoClient(this.createConnectionConfig());
|
|
49
60
|
}
|
|
@@ -58,50 +69,57 @@ class MongoDbEntityStorageConnector {
|
|
|
58
69
|
await this._client.connect();
|
|
59
70
|
await nodeLogging?.log({
|
|
60
71
|
level: "info",
|
|
61
|
-
source:
|
|
72
|
+
source: MongoDbEntityStorageConnector.CLASS_NAME,
|
|
62
73
|
ts: Date.now(),
|
|
63
74
|
message: "databaseCreating",
|
|
64
75
|
data: {
|
|
65
|
-
|
|
76
|
+
databaseName: this._config.database
|
|
66
77
|
}
|
|
67
78
|
});
|
|
68
79
|
// Create the database if it does not exist
|
|
69
80
|
this._client.db(this._config.database);
|
|
70
81
|
await nodeLogging?.log({
|
|
71
82
|
level: "info",
|
|
72
|
-
source:
|
|
83
|
+
source: MongoDbEntityStorageConnector.CLASS_NAME,
|
|
73
84
|
ts: Date.now(),
|
|
74
85
|
message: "databaseExists",
|
|
75
86
|
data: {
|
|
76
|
-
|
|
87
|
+
databaseName: this._config.database
|
|
77
88
|
}
|
|
78
89
|
});
|
|
79
90
|
await this.getCollection();
|
|
80
91
|
await nodeLogging?.log({
|
|
81
92
|
level: "info",
|
|
82
|
-
source:
|
|
93
|
+
source: MongoDbEntityStorageConnector.CLASS_NAME,
|
|
83
94
|
ts: Date.now(),
|
|
84
95
|
message: "collectionExists",
|
|
85
96
|
data: {
|
|
86
|
-
|
|
97
|
+
collectionName: this._config.collection
|
|
87
98
|
}
|
|
88
99
|
});
|
|
89
100
|
}
|
|
90
101
|
catch (error) {
|
|
91
102
|
await nodeLogging?.log({
|
|
92
103
|
level: "error",
|
|
93
|
-
source:
|
|
104
|
+
source: MongoDbEntityStorageConnector.CLASS_NAME,
|
|
94
105
|
ts: Date.now(),
|
|
95
106
|
message: "databaseCreateFailed",
|
|
96
107
|
error: BaseError.fromError(error),
|
|
97
108
|
data: {
|
|
98
|
-
|
|
109
|
+
databaseName: this._config.database
|
|
99
110
|
}
|
|
100
111
|
});
|
|
101
112
|
return false;
|
|
102
113
|
}
|
|
103
114
|
return true;
|
|
104
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Returns the class name of the component.
|
|
118
|
+
* @returns The class name of the component.
|
|
119
|
+
*/
|
|
120
|
+
className() {
|
|
121
|
+
return MongoDbEntityStorageConnector.CLASS_NAME;
|
|
122
|
+
}
|
|
105
123
|
/**
|
|
106
124
|
* Get the schema for the entities.
|
|
107
125
|
* @returns The schema for the entities.
|
|
@@ -117,12 +135,17 @@ class MongoDbEntityStorageConnector {
|
|
|
117
135
|
* @returns The object if it can be found or undefined.
|
|
118
136
|
*/
|
|
119
137
|
async get(id, secondaryIndex, conditions) {
|
|
120
|
-
Guards.stringValue(
|
|
138
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
139
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
140
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
121
141
|
try {
|
|
122
142
|
const primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
123
143
|
const query = Is.empty(secondaryIndex)
|
|
124
144
|
? { [primaryKey.property]: id }
|
|
125
145
|
: { [secondaryIndex]: id };
|
|
146
|
+
if (Is.stringValue(partitionKey)) {
|
|
147
|
+
query[MongoDbEntityStorageConnector._PARTITION_KEY] = partitionKey;
|
|
148
|
+
}
|
|
126
149
|
if (conditions) {
|
|
127
150
|
for (const condition of conditions) {
|
|
128
151
|
query[condition.property] = condition.value;
|
|
@@ -130,10 +153,12 @@ class MongoDbEntityStorageConnector {
|
|
|
130
153
|
}
|
|
131
154
|
const collection = await this.getCollection();
|
|
132
155
|
const result = await collection.findOne(query);
|
|
156
|
+
ObjectHelper.propertyDelete(result, "_id");
|
|
157
|
+
ObjectHelper.propertyDelete(result, MongoDbEntityStorageConnector._PARTITION_KEY);
|
|
133
158
|
return result;
|
|
134
159
|
}
|
|
135
160
|
catch (err) {
|
|
136
|
-
throw new GeneralError(
|
|
161
|
+
throw new GeneralError(MongoDbEntityStorageConnector.CLASS_NAME, "getFailed", {
|
|
137
162
|
id
|
|
138
163
|
}, err);
|
|
139
164
|
}
|
|
@@ -145,22 +170,29 @@ class MongoDbEntityStorageConnector {
|
|
|
145
170
|
* @returns The id of the entity.
|
|
146
171
|
*/
|
|
147
172
|
async set(entity, conditions) {
|
|
148
|
-
Guards.object(
|
|
173
|
+
Guards.object(MongoDbEntityStorageConnector.CLASS_NAME, "entity", entity);
|
|
174
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
175
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
149
176
|
EntitySchemaHelper.validateEntity(entity, this.getSchema());
|
|
150
177
|
const primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
151
178
|
const id = entity[primaryKey.property];
|
|
152
179
|
try {
|
|
153
180
|
const filter = { [primaryKey.property]: id };
|
|
181
|
+
const finalEntity = ObjectHelper.clone(entity);
|
|
182
|
+
if (Is.stringValue(partitionKey)) {
|
|
183
|
+
filter[MongoDbEntityStorageConnector._PARTITION_KEY] = partitionKey;
|
|
184
|
+
ObjectHelper.propertySet(finalEntity, MongoDbEntityStorageConnector._PARTITION_KEY, partitionKey);
|
|
185
|
+
}
|
|
154
186
|
if (Is.arrayValue(conditions)) {
|
|
155
187
|
for (const condition of conditions) {
|
|
156
188
|
filter[condition.property] = condition.value;
|
|
157
189
|
}
|
|
158
190
|
}
|
|
159
191
|
const collection = await this.getCollection();
|
|
160
|
-
await collection.findOneAndUpdate(filter, { $set:
|
|
192
|
+
await collection.findOneAndUpdate(filter, { $set: ObjectHelper.removeEmptyProperties(finalEntity) }, { upsert: true });
|
|
161
193
|
}
|
|
162
194
|
catch (err) {
|
|
163
|
-
throw new GeneralError(
|
|
195
|
+
throw new GeneralError(MongoDbEntityStorageConnector.CLASS_NAME, "setFailed", {
|
|
164
196
|
id
|
|
165
197
|
}, err);
|
|
166
198
|
}
|
|
@@ -172,10 +204,15 @@ class MongoDbEntityStorageConnector {
|
|
|
172
204
|
* @returns Nothing.
|
|
173
205
|
*/
|
|
174
206
|
async remove(id, conditions) {
|
|
175
|
-
Guards.stringValue(
|
|
207
|
+
Guards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
208
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
209
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
176
210
|
try {
|
|
177
211
|
const primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
178
212
|
const query = { [primaryKey.property]: id };
|
|
213
|
+
if (Is.stringValue(partitionKey)) {
|
|
214
|
+
query[MongoDbEntityStorageConnector._PARTITION_KEY] = partitionKey;
|
|
215
|
+
}
|
|
179
216
|
if (conditions) {
|
|
180
217
|
for (const condition of conditions) {
|
|
181
218
|
query[condition.property] = condition.value;
|
|
@@ -185,7 +222,7 @@ class MongoDbEntityStorageConnector {
|
|
|
185
222
|
await collection.deleteOne(query);
|
|
186
223
|
}
|
|
187
224
|
catch (err) {
|
|
188
|
-
throw new GeneralError(
|
|
225
|
+
throw new GeneralError(MongoDbEntityStorageConnector.CLASS_NAME, "removeFailed", { id }, err);
|
|
189
226
|
}
|
|
190
227
|
}
|
|
191
228
|
/**
|
|
@@ -193,16 +230,32 @@ class MongoDbEntityStorageConnector {
|
|
|
193
230
|
* @param conditions The conditions to match for the entities.
|
|
194
231
|
* @param sortProperties The optional sort order.
|
|
195
232
|
* @param properties The optional properties to return, defaults to all.
|
|
196
|
-
* @param cursor The cursor to request the next
|
|
197
|
-
* @param
|
|
233
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
234
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
198
235
|
* @returns All the entities for the storage matching the conditions,
|
|
199
236
|
* and a cursor which can be used to request more entities.
|
|
200
237
|
*/
|
|
201
|
-
async query(conditions, sortProperties, properties, cursor,
|
|
202
|
-
const
|
|
238
|
+
async query(conditions, sortProperties, properties, cursor, limit) {
|
|
239
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
240
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
241
|
+
const returnSize = limit ?? MongoDbEntityStorageConnector._DEFAULT_LIMIT;
|
|
242
|
+
const finalConditions = {
|
|
243
|
+
conditions: [],
|
|
244
|
+
logicalOperator: LogicalOperator.And
|
|
245
|
+
};
|
|
246
|
+
if (Is.stringValue(partitionKey)) {
|
|
247
|
+
finalConditions.conditions.push({
|
|
248
|
+
property: MongoDbEntityStorageConnector._PARTITION_KEY,
|
|
249
|
+
comparison: ComparisonOperator.Equals,
|
|
250
|
+
value: partitionKey
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (!Is.empty(conditions)) {
|
|
254
|
+
finalConditions.conditions.push(conditions);
|
|
255
|
+
}
|
|
203
256
|
const filter = {};
|
|
204
|
-
if (conditions) {
|
|
205
|
-
this.buildQueryParameters("",
|
|
257
|
+
if (finalConditions.conditions.length > 0) {
|
|
258
|
+
this.buildQueryParameters("", finalConditions, filter);
|
|
206
259
|
}
|
|
207
260
|
const sort = new Map();
|
|
208
261
|
if (Array.isArray(sortProperties)) {
|
|
@@ -218,7 +271,7 @@ class MongoDbEntityStorageConnector {
|
|
|
218
271
|
}
|
|
219
272
|
const cursorValue = cursor ? Number(cursor) : 0;
|
|
220
273
|
const collection = await this.getCollection();
|
|
221
|
-
const
|
|
274
|
+
const entitiesResult = await collection
|
|
222
275
|
// False positive, this is not an array find call
|
|
223
276
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
224
277
|
?.find(filter, { projection })
|
|
@@ -226,8 +279,13 @@ class MongoDbEntityStorageConnector {
|
|
|
226
279
|
.skip(cursorValue)
|
|
227
280
|
.limit(returnSize)
|
|
228
281
|
.toArray();
|
|
282
|
+
const entities = entitiesResult ?? [];
|
|
283
|
+
for (const entity of entities) {
|
|
284
|
+
ObjectHelper.propertyDelete(entity, "_id");
|
|
285
|
+
ObjectHelper.propertyDelete(entity, MongoDbEntityStorageConnector._PARTITION_KEY);
|
|
286
|
+
}
|
|
229
287
|
return {
|
|
230
|
-
entities
|
|
288
|
+
entities,
|
|
231
289
|
cursor: entities?.length === returnSize ? String(cursorValue + returnSize) : undefined
|
|
232
290
|
};
|
|
233
291
|
}
|
|
@@ -324,10 +382,11 @@ class MongoDbEntityStorageConnector {
|
|
|
324
382
|
return { $in: Array.isArray(value) ? value : [value] };
|
|
325
383
|
case ComparisonOperator.Includes:
|
|
326
384
|
return { $elemMatch: { $eq: value } };
|
|
385
|
+
case ComparisonOperator.NotIncludes:
|
|
386
|
+
return { $elemMatch: { $ne: value } };
|
|
327
387
|
default:
|
|
328
|
-
throw new GeneralError(
|
|
388
|
+
throw new GeneralError(MongoDbEntityStorageConnector.CLASS_NAME, "unsupportedComparisonOperator", { comparison });
|
|
329
389
|
}
|
|
330
390
|
}
|
|
331
391
|
}
|
|
332
|
-
|
|
333
|
-
export { MongoDbEntityStorageConnector };
|
|
392
|
+
//# sourceMappingURL=mongoDbEntityStorageConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongoDbEntityStorageConnector.js","sourceRoot":"","sources":["../../src/mongoDbEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype IEntitySchema,\n\tLogicalOperator,\n\ttype SortDirection\n} from \"@twin.org/entity\";\nimport type { IEntityStorageConnector } from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type Collection, type Document, type Filter, MongoClient, type WithId } from \"mongodb\";\nimport type { IMongoDbEntityStorageConnectorConfig } from \"./models/IMongoDbEntityStorageConnectorConfig.js\";\nimport type { IMongoDbEntityStorageConnectorConstructorOptions } from \"./models/IMongoDbEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using MongoDb.\n */\nexport class MongoDbEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MongoDbEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IMongoDbEntityStorageConnectorConfig;\n\n\t/**\n\t * The MongoDb client.\n\t * @internal\n\t */\n\tprivate readonly _client: MongoClient;\n\n\t/**\n\t * Create a new instance of MongoDbEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMongoDbEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MongoDbEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMongoDbEntityStorageConnectorConfig>(\n\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.host),\n\t\t\toptions.config.host\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.database),\n\t\t\toptions.config.database\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.collection),\n\t\t\toptions.config.collection\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._config = options.config;\n\n\t\tthis._client = new MongoClient(this.createConnectionConfig());\n\t}\n\n\t/**\n\t * Initialize the MongoDb environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tawait this._client.connect();\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Create the database if it does not exist\n\t\t\tthis._client.db(this._config.database);\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tawait this.getCollection();\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"collectionExists\",\n\t\t\t\tdata: {\n\t\t\t\t\tcollectionName: this._config.collection\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MongoDbEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Get an entity from MongoDb.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());\n\t\t\tconst query: { [key: string]: unknown } = Is.empty(secondaryIndex)\n\t\t\t\t? { [primaryKey.property]: id }\n\t\t\t\t: { [secondaryIndex]: id };\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tquery[MongoDbEntityStorageConnector._PARTITION_KEY] = partitionKey;\n\t\t\t}\n\n\t\t\tif (conditions) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\tquery[condition.property as string] = condition.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst collection = await this.getCollection();\n\t\t\tconst result = await collection.findOne(query);\n\t\t\tObjectHelper.propertyDelete(result, \"_id\");\n\t\t\tObjectHelper.propertyDelete(result, MongoDbEntityStorageConnector._PARTITION_KEY);\n\t\t\treturn result as T | undefined;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MongoDbEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\n\t\tconst primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());\n\t\tconst id = entity[primaryKey.property];\n\n\t\ttry {\n\t\t\tconst filter: { [key in keyof T]?: unknown } = { [primaryKey.property]: id };\n\t\t\tconst finalEntity = ObjectHelper.clone(entity);\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tfilter[MongoDbEntityStorageConnector._PARTITION_KEY as keyof T] = partitionKey;\n\t\t\t\tObjectHelper.propertySet(\n\t\t\t\t\tfinalEntity,\n\t\t\t\t\tMongoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tpartitionKey\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\tfilter[condition.property] = condition.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst collection = await this.getCollection();\n\t\t\tawait collection.findOneAndUpdate(\n\t\t\t\tfilter,\n\t\t\t\t{ $set: ObjectHelper.removeEmptyProperties(finalEntity) as Partial<Document> },\n\t\t\t\t{ upsert: true }\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MongoDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst primaryKey = EntitySchemaHelper.getPrimaryKey(this.getSchema());\n\t\t\tconst query: { [key in keyof T]?: unknown } = { [primaryKey.property]: id };\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tquery[MongoDbEntityStorageConnector._PARTITION_KEY as keyof T] = partitionKey;\n\t\t\t}\n\n\t\t\tif (conditions) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\tquery[condition.property] = condition.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst collection = await this.getCollection();\n\t\t\tawait collection.deleteOne(query);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MongoDbEntityStorageConnector.CLASS_NAME, \"removeFailed\", { id }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst returnSize = limit ?? MongoDbEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MongoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(conditions);\n\t\t}\n\n\t\tconst filter: Filter<T> = {};\n\t\tif (finalConditions.conditions.length > 0) {\n\t\t\tthis.buildQueryParameters(\"\", finalConditions, filter);\n\t\t}\n\n\t\tconst sort = new Map<string, SortDirection>();\n\t\tif (Array.isArray(sortProperties)) {\n\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\tsort.set(sortProperty.property as string, sortProperty.sortDirection);\n\t\t\t}\n\t\t}\n\n\t\tconst projection: { [key: string]: number } = {};\n\t\tif (properties) {\n\t\t\tfor (const property of properties) {\n\t\t\t\tprojection[property as string] = 1;\n\t\t\t}\n\t\t}\n\n\t\tconst cursorValue = cursor ? Number(cursor) : 0;\n\n\t\tconst collection = await this.getCollection();\n\t\tconst entitiesResult = await collection\n\t\t\t// False positive, this is not an array find call\n\t\t\t// eslint-disable-next-line unicorn/no-array-callback-reference\n\t\t\t?.find(filter as Filter<Document>, { projection })\n\t\t\t.sort(sort)\n\t\t\t.skip(cursorValue)\n\t\t\t.limit(returnSize)\n\t\t\t.toArray();\n\n\t\tconst entities = (entitiesResult as unknown as Partial<T>[]) ?? [];\n\n\t\tfor (const entity of entities) {\n\t\t\tObjectHelper.propertyDelete(entity, \"_id\");\n\t\t\tObjectHelper.propertyDelete(entity, MongoDbEntityStorageConnector._PARTITION_KEY);\n\t\t}\n\n\t\treturn {\n\t\t\tentities,\n\t\t\tcursor: entities?.length === returnSize ? String(cursorValue + returnSize) : undefined\n\t\t};\n\t}\n\n\t/**\n\t * Drop the collection.\n\t * @returns Nothing.\n\t */\n\tpublic async collectionDrop(): Promise<void> {\n\t\ttry {\n\t\t\tconst collection = await this.getCollection();\n\t\t\tawait collection.drop();\n\t\t} catch {\n\t\t\t// Ignore errors\n\t\t}\n\t}\n\n\t/**\n\t * Create a new DB connection configuration.\n\t * @returns The MongoDb connection configuration.\n\t * @internal\n\t */\n\tprivate createConnectionConfig(): string {\n\t\tconst { host, port, user, password, database } = this._config;\n\t\tconst portPart = port ? `:${port}` : \"\";\n\t\tif (user && password) {\n\t\t\treturn `mongodb://${user}:${password}@${host}${portPart}/${database}`;\n\t\t}\n\t\treturn `mongodb://${host}${portPart}/${database}`;\n\t}\n\n\t/**\n\t * Return a Mongo DB collection.\n\t * @returns The MongoDb collection.\n\t * @internal\n\t */\n\tprivate async getCollection(): Promise<Collection> {\n\t\tconst { database, collection } = this._config;\n\t\treturn this._client.db(database).collection(collection);\n\t}\n\n\t/**\n\t * Create an MongoDB filter query.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param filter The filter query to use.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T>,\n\t\tfilter: Filter<T>\n\t): void {\n\t\tif (!condition) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tconst subConditions: Filter<T>[] = condition.conditions.map(c => {\n\t\t\t\tconst subFilter: Filter<T> = {};\n\t\t\t\tthis.buildQueryParameters(objectPath, c, subFilter);\n\t\t\t\treturn subFilter;\n\t\t\t});\n\n\t\t\tif (condition.logicalOperator === LogicalOperator.And) {\n\t\t\t\tfilter.$and = subConditions as Filter<WithId<T>>[];\n\t\t\t} else if (condition.logicalOperator === LogicalOperator.Or) {\n\t\t\t\tfilter.$or = subConditions as Filter<WithId<T>>[];\n\t\t\t} else {\n\t\t\t\tObject.assign(filter, subConditions[0]);\n\t\t\t}\n\t\t} else {\n\t\t\tconst prop = objectPath ? `${objectPath}.${condition.property}` : String(condition.property);\n\t\t\tconst comparison = this.mapComparisonOperator(condition.comparison, condition.value);\n\n\t\t\t(filter as { [key: string]: unknown })[prop] = comparison;\n\t\t}\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in MongoDB.\n\t * @param comparison The comparison operator.\n\t * @param value The value to compare.\n\t * @returns The MongoDB comparison expression.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(comparison: ComparisonOperator, value: unknown): unknown {\n\t\tswitch (comparison) {\n\t\t\tcase ComparisonOperator.Equals:\n\t\t\t\treturn value;\n\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\treturn { $ne: value };\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn { $gt: value };\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn { $lt: value };\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn { $gte: value };\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn { $lte: value };\n\t\t\tcase ComparisonOperator.In:\n\t\t\t\treturn { $in: Array.isArray(value) ? value : [value] };\n\t\t\tcase ComparisonOperator.Includes:\n\t\t\t\treturn { $elemMatch: { $eq: value } };\n\t\t\tcase ComparisonOperator.NotIncludes:\n\t\t\t\treturn { $elemMatch: { $ne: value } };\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tMongoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"unsupportedComparisonOperator\",\n\t\t\t\t\t{ comparison }\n\t\t\t\t);\n\t\t}\n\t}\n}\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./mongoDbEntityStorageConnector";
|
|
2
|
-
export * from "./models/IMongoDbEntityStorageConnectorConfig";
|
|
3
|
-
export * from "./models/IMongoDbEntityStorageConnectorConstructorOptions";
|
|
1
|
+
export * from "./mongoDbEntityStorageConnector.js";
|
|
2
|
+
export * from "./models/IMongoDbEntityStorageConnectorConfig.js";
|
|
3
|
+
export * from "./models/IMongoDbEntityStorageConnectorConstructorOptions.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IMongoDbEntityStorageConnectorConfig } from "./IMongoDbEntityStorageConnectorConfig";
|
|
1
|
+
import type { IMongoDbEntityStorageConnectorConfig } from "./IMongoDbEntityStorageConnectorConfig.js";
|
|
2
2
|
/**
|
|
3
3
|
* The options for the MongoDb entity storage connector constructor.
|
|
4
4
|
*/
|
|
@@ -7,6 +7,10 @@ export interface IMongoDbEntityStorageConnectorConstructorOptions {
|
|
|
7
7
|
* The schema for the entity.
|
|
8
8
|
*/
|
|
9
9
|
entitySchema: string;
|
|
10
|
+
/**
|
|
11
|
+
* The keys to use from the context ids to create partitions.
|
|
12
|
+
*/
|
|
13
|
+
partitionContextIds?: string[];
|
|
10
14
|
/**
|
|
11
15
|
* The type of logging component to use.
|
|
12
16
|
* @default logging
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type EntityCondition, type IEntitySchema, type SortDirection } from "@twin.org/entity";
|
|
2
2
|
import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
|
|
3
|
-
import type { IMongoDbEntityStorageConnectorConstructorOptions } from "./models/IMongoDbEntityStorageConnectorConstructorOptions";
|
|
3
|
+
import type { IMongoDbEntityStorageConnectorConstructorOptions } from "./models/IMongoDbEntityStorageConnectorConstructorOptions.js";
|
|
4
4
|
/**
|
|
5
5
|
* Class for performing entity storage operations using MongoDb.
|
|
6
6
|
*/
|
|
@@ -8,7 +8,7 @@ export declare class MongoDbEntityStorageConnector<T = unknown> implements IEnti
|
|
|
8
8
|
/**
|
|
9
9
|
* Runtime name for the class.
|
|
10
10
|
*/
|
|
11
|
-
readonly CLASS_NAME: string;
|
|
11
|
+
static readonly CLASS_NAME: string;
|
|
12
12
|
/**
|
|
13
13
|
* Create a new instance of MongoDbEntityStorageConnector.
|
|
14
14
|
* @param options The options for the connector.
|
|
@@ -20,6 +20,11 @@ export declare class MongoDbEntityStorageConnector<T = unknown> implements IEnti
|
|
|
20
20
|
* @returns A promise that resolves to a boolean indicating success.
|
|
21
21
|
*/
|
|
22
22
|
bootstrap(nodeLoggingComponentType?: string): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the class name of the component.
|
|
25
|
+
* @returns The class name of the component.
|
|
26
|
+
*/
|
|
27
|
+
className(): string;
|
|
23
28
|
/**
|
|
24
29
|
* Get the schema for the entities.
|
|
25
30
|
* @returns The schema for the entities.
|
|
@@ -61,15 +66,15 @@ export declare class MongoDbEntityStorageConnector<T = unknown> implements IEnti
|
|
|
61
66
|
* @param conditions The conditions to match for the entities.
|
|
62
67
|
* @param sortProperties The optional sort order.
|
|
63
68
|
* @param properties The optional properties to return, defaults to all.
|
|
64
|
-
* @param cursor The cursor to request the next
|
|
65
|
-
* @param
|
|
69
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
70
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
66
71
|
* @returns All the entities for the storage matching the conditions,
|
|
67
72
|
* and a cursor which can be used to request more entities.
|
|
68
73
|
*/
|
|
69
74
|
query(conditions?: EntityCondition<T>, sortProperties?: {
|
|
70
75
|
property: keyof T;
|
|
71
76
|
sortDirection: SortDirection;
|
|
72
|
-
}[], properties?: (keyof T)[], cursor?: string,
|
|
77
|
+
}[], properties?: (keyof T)[], cursor?: string, limit?: number): Promise<{
|
|
73
78
|
entities: Partial<T>[];
|
|
74
79
|
cursor?: string;
|
|
75
80
|
}>;
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# @twin.org/entity-storage-connector-mongodb - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.2](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-mongodb-v0.0.3-next.1...entity-storage-connector-mongodb-v0.0.3-next.2) (2025-11-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **entity-storage-connector-mongodb:** Synchronize repo versions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
18
|
+
|
|
19
|
+
## [0.0.3-next.1](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-mongodb-v0.0.3-next.0...entity-storage-connector-mongodb-v0.0.3-next.1) (2025-11-10)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* add context id features ([#55](https://github.com/twinfoundation/entity-storage/issues/55)) ([99c15a2](https://github.com/twinfoundation/entity-storage/commit/99c15a257539b61d9da63649ce573ebf47699fc9))
|
|
25
|
+
* add production release automation ([1eb4c8e](https://github.com/twinfoundation/entity-storage/commit/1eb4c8ee3eb099defdfc2d063ae44935276dcae8))
|
|
26
|
+
* add validate-locales ([e66ef0d](https://github.com/twinfoundation/entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
|
|
27
|
+
* eslint migration to flat config ([f033b64](https://github.com/twinfoundation/entity-storage/commit/f033b64984c0e6a8129d929c9dd816dcc1b8dab0))
|
|
28
|
+
* logging naming consistency ([f99d12d](https://github.com/twinfoundation/entity-storage/commit/f99d12dea04b6d4f2b5632ff5473e9ec7d5f9055))
|
|
29
|
+
* synchronised storage ([#44](https://github.com/twinfoundation/entity-storage/issues/44)) ([94e10e2](https://github.com/twinfoundation/entity-storage/commit/94e10e26d1feec801449dc04af7a9757ac7495ff))
|
|
30
|
+
* update dependencies ([7ccc0c4](https://github.com/twinfoundation/entity-storage/commit/7ccc0c429125d073dc60b3de6cf101abc8cc6cba))
|
|
31
|
+
* update framework core ([b59a380](https://github.com/twinfoundation/entity-storage/commit/b59a380bb7fba2b43610f69074dcdee24a4737da))
|
|
32
|
+
* use shared store mechanism ([#34](https://github.com/twinfoundation/entity-storage/issues/34)) ([68b6b71](https://github.com/twinfoundation/entity-storage/commit/68b6b71e7a96d7d016cd57bfff36775b56bf3f93))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* query params force coercion ([dd6aa87](https://github.com/twinfoundation/entity-storage/commit/dd6aa87efdfb60bab7d6756a86888863c45c51a7))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Dependencies
|
|
41
|
+
|
|
42
|
+
* The following workspace dependencies were updated
|
|
43
|
+
* dependencies
|
|
44
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
45
|
+
* devDependencies
|
|
46
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
47
|
+
|
|
48
|
+
## [0.0.2-next.10](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-mongodb-v0.0.2-next.9...entity-storage-connector-mongodb-v0.0.2-next.10) (2025-10-09)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Features
|
|
52
|
+
|
|
53
|
+
* add validate-locales ([e66ef0d](https://github.com/twinfoundation/entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
### Dependencies
|
|
57
|
+
|
|
58
|
+
* The following workspace dependencies were updated
|
|
59
|
+
* dependencies
|
|
60
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
61
|
+
* devDependencies
|
|
62
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
63
|
+
|
|
3
64
|
## [0.0.2-next.9](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-mongodb-v0.0.2-next.8...entity-storage-connector-mongodb-v0.0.2-next.9) (2025-10-02)
|
|
4
65
|
|
|
5
66
|
|
|
@@ -36,14 +36,10 @@ The options for the connector.
|
|
|
36
36
|
|
|
37
37
|
### CLASS\_NAME
|
|
38
38
|
|
|
39
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
39
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
40
40
|
|
|
41
41
|
Runtime name for the class.
|
|
42
42
|
|
|
43
|
-
#### Implementation of
|
|
44
|
-
|
|
45
|
-
`IEntityStorageConnector.CLASS_NAME`
|
|
46
|
-
|
|
47
43
|
## Methods
|
|
48
44
|
|
|
49
45
|
### bootstrap()
|
|
@@ -72,6 +68,24 @@ A promise that resolves to a boolean indicating success.
|
|
|
72
68
|
|
|
73
69
|
***
|
|
74
70
|
|
|
71
|
+
### className()
|
|
72
|
+
|
|
73
|
+
> **className**(): `string`
|
|
74
|
+
|
|
75
|
+
Returns the class name of the component.
|
|
76
|
+
|
|
77
|
+
#### Returns
|
|
78
|
+
|
|
79
|
+
`string`
|
|
80
|
+
|
|
81
|
+
The class name of the component.
|
|
82
|
+
|
|
83
|
+
#### Implementation of
|
|
84
|
+
|
|
85
|
+
`IEntityStorageConnector.className`
|
|
86
|
+
|
|
87
|
+
***
|
|
88
|
+
|
|
75
89
|
### getSchema()
|
|
76
90
|
|
|
77
91
|
> **getSchema**(): `IEntitySchema`
|
|
@@ -92,7 +106,7 @@ The schema for the entities.
|
|
|
92
106
|
|
|
93
107
|
### get()
|
|
94
108
|
|
|
95
|
-
> **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`
|
|
109
|
+
> **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`T` \| `undefined`\>
|
|
96
110
|
|
|
97
111
|
Get an entity from MongoDb.
|
|
98
112
|
|
|
@@ -118,7 +132,7 @@ The optional conditions to match for the entities.
|
|
|
118
132
|
|
|
119
133
|
#### Returns
|
|
120
134
|
|
|
121
|
-
`Promise`\<`
|
|
135
|
+
`Promise`\<`T` \| `undefined`\>
|
|
122
136
|
|
|
123
137
|
The object if it can be found or undefined.
|
|
124
138
|
|
|
@@ -194,7 +208,7 @@ Nothing.
|
|
|
194
208
|
|
|
195
209
|
### query()
|
|
196
210
|
|
|
197
|
-
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `
|
|
211
|
+
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `limit?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
|
|
198
212
|
|
|
199
213
|
Find all the entities which match the conditions.
|
|
200
214
|
|
|
@@ -222,9 +236,9 @@ The optional properties to return, defaults to all.
|
|
|
222
236
|
|
|
223
237
|
`string`
|
|
224
238
|
|
|
225
|
-
The cursor to request the next
|
|
239
|
+
The cursor to request the next chunk of entities.
|
|
226
240
|
|
|
227
|
-
#####
|
|
241
|
+
##### limit?
|
|
228
242
|
|
|
229
243
|
`number`
|
|
230
244
|
|
|
@@ -12,6 +12,14 @@ The schema for the entity.
|
|
|
12
12
|
|
|
13
13
|
***
|
|
14
14
|
|
|
15
|
+
### partitionContextIds?
|
|
16
|
+
|
|
17
|
+
> `optional` **partitionContextIds**: `string`[]
|
|
18
|
+
|
|
19
|
+
The keys to use from the context ids to create partitions.
|
|
20
|
+
|
|
21
|
+
***
|
|
22
|
+
|
|
15
23
|
### loggingComponentType?
|
|
16
24
|
|
|
17
25
|
> `optional` **loggingComponentType**: `string`
|
package/locales/en.json
CHANGED
|
@@ -11,11 +11,8 @@
|
|
|
11
11
|
"setFailed": "Unable to set entity \"{id}\"",
|
|
12
12
|
"getFailed": "Unable to get entity \"{id}\"",
|
|
13
13
|
"removeFailed": "Unable to remove entity \"{id}\"",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"conditionalNotSupported": "Conditional operator \"{operator}\" is not supported",
|
|
17
|
-
"sortSingle": "You can only sort by a single property",
|
|
18
|
-
"sortNotIndexed": "The property \"{property}\" is not indexed and cannot be used for sorting"
|
|
14
|
+
"databaseCreateFailed": "The database creation failed for \"{databaseName}\"",
|
|
15
|
+
"unsupportedComparisonOperator": "Comparison operator \"{comparison}\" is not supported"
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-mongodb",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-next.2",
|
|
4
4
|
"description": "Entity Storage connector implementation using MongoDb storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,27 +14,26 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@twin.org/context": "next",
|
|
17
18
|
"@twin.org/core": "next",
|
|
18
19
|
"@twin.org/entity": "next",
|
|
19
|
-
"@twin.org/entity-storage-models": "0.0.
|
|
20
|
+
"@twin.org/entity-storage-models": "0.0.3-next.2",
|
|
20
21
|
"@twin.org/logging-models": "next",
|
|
21
22
|
"@twin.org/nameof": "next",
|
|
22
|
-
"mongodb": "
|
|
23
|
+
"mongodb": "7.0.0"
|
|
23
24
|
},
|
|
24
|
-
"main": "./dist/
|
|
25
|
-
"module": "./dist/esm/index.mjs",
|
|
25
|
+
"main": "./dist/es/index.js",
|
|
26
26
|
"types": "./dist/types/index.d.ts",
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
29
|
"types": "./dist/types/index.d.ts",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
30
|
+
"import": "./dist/es/index.js",
|
|
31
|
+
"default": "./dist/es/index.js"
|
|
32
32
|
},
|
|
33
33
|
"./locales/*.json": "./locales/*.json"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
-
"dist/
|
|
37
|
-
"dist/esm",
|
|
36
|
+
"dist/es",
|
|
38
37
|
"dist/types",
|
|
39
38
|
"locales",
|
|
40
39
|
"docs"
|
|
@@ -53,5 +52,9 @@
|
|
|
53
52
|
"connector",
|
|
54
53
|
"adapter",
|
|
55
54
|
"integration"
|
|
56
|
-
]
|
|
55
|
+
],
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "git+https://github.com/twinfoundation/entity-storage/issues"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://twindev.org"
|
|
57
60
|
}
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var core = require('@twin.org/core');
|
|
4
|
-
var entity = require('@twin.org/entity');
|
|
5
|
-
var mongodb = require('mongodb');
|
|
6
|
-
|
|
7
|
-
// Copyright 2024 IOTA Stiftung.
|
|
8
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
9
|
-
/**
|
|
10
|
-
* Class for performing entity storage operations using MongoDb.
|
|
11
|
-
*/
|
|
12
|
-
class MongoDbEntityStorageConnector {
|
|
13
|
-
/**
|
|
14
|
-
* Limit the number of entities when finding.
|
|
15
|
-
* @internal
|
|
16
|
-
*/
|
|
17
|
-
static _PAGE_SIZE = 40;
|
|
18
|
-
/**
|
|
19
|
-
* Runtime name for the class.
|
|
20
|
-
*/
|
|
21
|
-
CLASS_NAME = "MongoDbEntityStorageConnector";
|
|
22
|
-
/**
|
|
23
|
-
* The schema for the entity.
|
|
24
|
-
* @internal
|
|
25
|
-
*/
|
|
26
|
-
_entitySchema;
|
|
27
|
-
/**
|
|
28
|
-
* The configuration for the connector.
|
|
29
|
-
* @internal
|
|
30
|
-
*/
|
|
31
|
-
_config;
|
|
32
|
-
/**
|
|
33
|
-
* The MongoDb client.
|
|
34
|
-
* @internal
|
|
35
|
-
*/
|
|
36
|
-
_client;
|
|
37
|
-
/**
|
|
38
|
-
* Create a new instance of MongoDbEntityStorageConnector.
|
|
39
|
-
* @param options The options for the connector.
|
|
40
|
-
*/
|
|
41
|
-
constructor(options) {
|
|
42
|
-
core.Guards.object(this.CLASS_NAME, "options", options);
|
|
43
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
44
|
-
core.Guards.object(this.CLASS_NAME, "options.config", options.config);
|
|
45
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.config.host", options.config.host);
|
|
46
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.config.database", options.config.database);
|
|
47
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.config.collection", options.config.collection);
|
|
48
|
-
this._entitySchema = entity.EntitySchemaFactory.get(options.entitySchema);
|
|
49
|
-
this._config = options.config;
|
|
50
|
-
this._client = new mongodb.MongoClient(this.createConnectionConfig());
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Initialize the MongoDb environment.
|
|
54
|
-
* @param nodeLoggingComponentType Optional type of the logging component.
|
|
55
|
-
* @returns A promise that resolves to a boolean indicating success.
|
|
56
|
-
*/
|
|
57
|
-
async bootstrap(nodeLoggingComponentType) {
|
|
58
|
-
const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
59
|
-
try {
|
|
60
|
-
await this._client.connect();
|
|
61
|
-
await nodeLogging?.log({
|
|
62
|
-
level: "info",
|
|
63
|
-
source: this.CLASS_NAME,
|
|
64
|
-
ts: Date.now(),
|
|
65
|
-
message: "databaseCreating",
|
|
66
|
-
data: {
|
|
67
|
-
database: this._config.database
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
// Create the database if it does not exist
|
|
71
|
-
this._client.db(this._config.database);
|
|
72
|
-
await nodeLogging?.log({
|
|
73
|
-
level: "info",
|
|
74
|
-
source: this.CLASS_NAME,
|
|
75
|
-
ts: Date.now(),
|
|
76
|
-
message: "databaseExists",
|
|
77
|
-
data: {
|
|
78
|
-
database: this._config.database
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
await this.getCollection();
|
|
82
|
-
await nodeLogging?.log({
|
|
83
|
-
level: "info",
|
|
84
|
-
source: this.CLASS_NAME,
|
|
85
|
-
ts: Date.now(),
|
|
86
|
-
message: "collectionExists",
|
|
87
|
-
data: {
|
|
88
|
-
collection: this._config.collection
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
await nodeLogging?.log({
|
|
94
|
-
level: "error",
|
|
95
|
-
source: this.CLASS_NAME,
|
|
96
|
-
ts: Date.now(),
|
|
97
|
-
message: "databaseCreateFailed",
|
|
98
|
-
error: core.BaseError.fromError(error),
|
|
99
|
-
data: {
|
|
100
|
-
database: this._config.database
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Get the schema for the entities.
|
|
109
|
-
* @returns The schema for the entities.
|
|
110
|
-
*/
|
|
111
|
-
getSchema() {
|
|
112
|
-
return this._entitySchema;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Get an entity from MongoDb.
|
|
116
|
-
* @param id The id of the entity to get, or the index value if secondaryIndex is set.
|
|
117
|
-
* @param secondaryIndex Get the item using a secondary index.
|
|
118
|
-
* @param conditions The optional conditions to match for the entities.
|
|
119
|
-
* @returns The object if it can be found or undefined.
|
|
120
|
-
*/
|
|
121
|
-
async get(id, secondaryIndex, conditions) {
|
|
122
|
-
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
123
|
-
try {
|
|
124
|
-
const primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
125
|
-
const query = core.Is.empty(secondaryIndex)
|
|
126
|
-
? { [primaryKey.property]: id }
|
|
127
|
-
: { [secondaryIndex]: id };
|
|
128
|
-
if (conditions) {
|
|
129
|
-
for (const condition of conditions) {
|
|
130
|
-
query[condition.property] = condition.value;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const collection = await this.getCollection();
|
|
134
|
-
const result = await collection.findOne(query);
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
catch (err) {
|
|
138
|
-
throw new core.GeneralError(this.CLASS_NAME, "getFailed", {
|
|
139
|
-
id
|
|
140
|
-
}, err);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Set an entity.
|
|
145
|
-
* @param entity The entity to set.
|
|
146
|
-
* @param conditions The optional conditions to match for the entities.
|
|
147
|
-
* @returns The id of the entity.
|
|
148
|
-
*/
|
|
149
|
-
async set(entity$1, conditions) {
|
|
150
|
-
core.Guards.object(this.CLASS_NAME, "entity", entity$1);
|
|
151
|
-
entity.EntitySchemaHelper.validateEntity(entity$1, this.getSchema());
|
|
152
|
-
const primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
153
|
-
const id = entity$1[primaryKey.property];
|
|
154
|
-
try {
|
|
155
|
-
const filter = { [primaryKey.property]: id };
|
|
156
|
-
if (core.Is.arrayValue(conditions)) {
|
|
157
|
-
for (const condition of conditions) {
|
|
158
|
-
filter[condition.property] = condition.value;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const collection = await this.getCollection();
|
|
162
|
-
await collection.findOneAndUpdate(filter, { $set: entity$1 }, { upsert: true });
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
throw new core.GeneralError(this.CLASS_NAME, "setFailed", {
|
|
166
|
-
id
|
|
167
|
-
}, err);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Remove the entity.
|
|
172
|
-
* @param id The id of the entity to remove.
|
|
173
|
-
* @param conditions The optional conditions to match for the entities.
|
|
174
|
-
* @returns Nothing.
|
|
175
|
-
*/
|
|
176
|
-
async remove(id, conditions) {
|
|
177
|
-
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
178
|
-
try {
|
|
179
|
-
const primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this.getSchema());
|
|
180
|
-
const query = { [primaryKey.property]: id };
|
|
181
|
-
if (conditions) {
|
|
182
|
-
for (const condition of conditions) {
|
|
183
|
-
query[condition.property] = condition.value;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const collection = await this.getCollection();
|
|
187
|
-
await collection.deleteOne(query);
|
|
188
|
-
}
|
|
189
|
-
catch (err) {
|
|
190
|
-
throw new core.GeneralError(this.CLASS_NAME, "removeFailed", { id }, err);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Find all the entities which match the conditions.
|
|
195
|
-
* @param conditions The conditions to match for the entities.
|
|
196
|
-
* @param sortProperties The optional sort order.
|
|
197
|
-
* @param properties The optional properties to return, defaults to all.
|
|
198
|
-
* @param cursor The cursor to request the next page of entities.
|
|
199
|
-
* @param pageSize The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
200
|
-
* @returns All the entities for the storage matching the conditions,
|
|
201
|
-
* and a cursor which can be used to request more entities.
|
|
202
|
-
*/
|
|
203
|
-
async query(conditions, sortProperties, properties, cursor, pageSize) {
|
|
204
|
-
const returnSize = pageSize ?? MongoDbEntityStorageConnector._PAGE_SIZE;
|
|
205
|
-
const filter = {};
|
|
206
|
-
if (conditions) {
|
|
207
|
-
this.buildQueryParameters("", conditions, filter);
|
|
208
|
-
}
|
|
209
|
-
const sort = new Map();
|
|
210
|
-
if (Array.isArray(sortProperties)) {
|
|
211
|
-
for (const sortProperty of sortProperties) {
|
|
212
|
-
sort.set(sortProperty.property, sortProperty.sortDirection);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
const projection = {};
|
|
216
|
-
if (properties) {
|
|
217
|
-
for (const property of properties) {
|
|
218
|
-
projection[property] = 1;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
const cursorValue = cursor ? Number(cursor) : 0;
|
|
222
|
-
const collection = await this.getCollection();
|
|
223
|
-
const entities = await collection
|
|
224
|
-
// False positive, this is not an array find call
|
|
225
|
-
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
226
|
-
?.find(filter, { projection })
|
|
227
|
-
.sort(sort)
|
|
228
|
-
.skip(cursorValue)
|
|
229
|
-
.limit(returnSize)
|
|
230
|
-
.toArray();
|
|
231
|
-
return {
|
|
232
|
-
entities: entities ?? [],
|
|
233
|
-
cursor: entities?.length === returnSize ? String(cursorValue + returnSize) : undefined
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Drop the collection.
|
|
238
|
-
* @returns Nothing.
|
|
239
|
-
*/
|
|
240
|
-
async collectionDrop() {
|
|
241
|
-
try {
|
|
242
|
-
const collection = await this.getCollection();
|
|
243
|
-
await collection.drop();
|
|
244
|
-
}
|
|
245
|
-
catch {
|
|
246
|
-
// Ignore errors
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Create a new DB connection configuration.
|
|
251
|
-
* @returns The MongoDb connection configuration.
|
|
252
|
-
* @internal
|
|
253
|
-
*/
|
|
254
|
-
createConnectionConfig() {
|
|
255
|
-
const { host, port, user, password, database } = this._config;
|
|
256
|
-
const portPart = port ? `:${port}` : "";
|
|
257
|
-
if (user && password) {
|
|
258
|
-
return `mongodb://${user}:${password}@${host}${portPart}/${database}`;
|
|
259
|
-
}
|
|
260
|
-
return `mongodb://${host}${portPart}/${database}`;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Return a Mongo DB collection.
|
|
264
|
-
* @returns The MongoDb collection.
|
|
265
|
-
* @internal
|
|
266
|
-
*/
|
|
267
|
-
async getCollection() {
|
|
268
|
-
const { database, collection } = this._config;
|
|
269
|
-
return this._client.db(database).collection(collection);
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Create an MongoDB filter query.
|
|
273
|
-
* @param objectPath The path for the nested object.
|
|
274
|
-
* @param condition The conditions to create the query from.
|
|
275
|
-
* @param filter The filter query to use.
|
|
276
|
-
* @internal
|
|
277
|
-
*/
|
|
278
|
-
buildQueryParameters(objectPath, condition, filter) {
|
|
279
|
-
if (!condition) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
if ("conditions" in condition) {
|
|
283
|
-
const subConditions = condition.conditions.map(c => {
|
|
284
|
-
const subFilter = {};
|
|
285
|
-
this.buildQueryParameters(objectPath, c, subFilter);
|
|
286
|
-
return subFilter;
|
|
287
|
-
});
|
|
288
|
-
if (condition.logicalOperator === entity.LogicalOperator.And) {
|
|
289
|
-
filter.$and = subConditions;
|
|
290
|
-
}
|
|
291
|
-
else if (condition.logicalOperator === entity.LogicalOperator.Or) {
|
|
292
|
-
filter.$or = subConditions;
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
Object.assign(filter, subConditions[0]);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
const prop = objectPath ? `${objectPath}.${condition.property}` : String(condition.property);
|
|
300
|
-
const comparison = this.mapComparisonOperator(condition.comparison, condition.value);
|
|
301
|
-
filter[prop] = comparison;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Map the framework comparison operators to those in MongoDB.
|
|
306
|
-
* @param comparison The comparison operator.
|
|
307
|
-
* @param value The value to compare.
|
|
308
|
-
* @returns The MongoDB comparison expression.
|
|
309
|
-
* @internal
|
|
310
|
-
*/
|
|
311
|
-
mapComparisonOperator(comparison, value) {
|
|
312
|
-
switch (comparison) {
|
|
313
|
-
case entity.ComparisonOperator.Equals:
|
|
314
|
-
return value;
|
|
315
|
-
case entity.ComparisonOperator.NotEquals:
|
|
316
|
-
return { $ne: value };
|
|
317
|
-
case entity.ComparisonOperator.GreaterThan:
|
|
318
|
-
return { $gt: value };
|
|
319
|
-
case entity.ComparisonOperator.LessThan:
|
|
320
|
-
return { $lt: value };
|
|
321
|
-
case entity.ComparisonOperator.GreaterThanOrEqual:
|
|
322
|
-
return { $gte: value };
|
|
323
|
-
case entity.ComparisonOperator.LessThanOrEqual:
|
|
324
|
-
return { $lte: value };
|
|
325
|
-
case entity.ComparisonOperator.In:
|
|
326
|
-
return { $in: Array.isArray(value) ? value : [value] };
|
|
327
|
-
case entity.ComparisonOperator.Includes:
|
|
328
|
-
return { $elemMatch: { $eq: value } };
|
|
329
|
-
default:
|
|
330
|
-
throw new core.GeneralError(this.CLASS_NAME, "unsupportedComparisonOperator", { comparison });
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
exports.MongoDbEntityStorageConnector = MongoDbEntityStorageConnector;
|