@lobb-js/core 0.13.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/package.json +48 -0
- package/src/Lobb.ts +150 -0
- package/src/LobbError.ts +105 -0
- package/src/TypesGenerator.ts +11 -0
- package/src/api/WebServer.ts +126 -0
- package/src/api/collections/CollectionControllers.ts +485 -0
- package/src/api/collections/CollectionService.ts +162 -0
- package/src/api/collections/collectionRoutes.ts +105 -0
- package/src/api/collections/collectionStore.ts +647 -0
- package/src/api/collections/transactions.ts +166 -0
- package/src/api/collections/utils.ts +73 -0
- package/src/api/errorHandler.ts +73 -0
- package/src/api/events/index.ts +129 -0
- package/src/api/meta/route.ts +66 -0
- package/src/api/meta/service.ts +163 -0
- package/src/api/middlewares.ts +71 -0
- package/src/api/openApiRoute.ts +1017 -0
- package/src/api/schema/SchemaService.ts +71 -0
- package/src/api/schema/schemaRoutes.ts +13 -0
- package/src/config/ConfigManager.ts +252 -0
- package/src/config/validations.ts +49 -0
- package/src/coreCollections/collectionsCollection.ts +56 -0
- package/src/coreCollections/index.ts +14 -0
- package/src/coreCollections/migrationsCollection.ts +36 -0
- package/src/coreCollections/queryCollection.ts +26 -0
- package/src/coreCollections/workflowsCollection.ts +73 -0
- package/src/coreDbSetup/index.ts +72 -0
- package/src/coreMigrations/index.ts +3 -0
- package/src/database/DatabaseService.ts +44 -0
- package/src/database/DatabaseSyncManager.ts +173 -0
- package/src/database/MigrationsManager.ts +95 -0
- package/src/database/drivers/MongoDriver.ts +750 -0
- package/src/database/drivers/pgDriver/PGDriver.ts +655 -0
- package/src/database/drivers/pgDriver/QueryBuilder.ts +474 -0
- package/src/database/drivers/pgDriver/utils.ts +6 -0
- package/src/events/EventSystem.ts +191 -0
- package/src/events/coreEvents/index.ts +218 -0
- package/src/events/studioEvents/index.ts +32 -0
- package/src/extension/ExtensionSystem.ts +236 -0
- package/src/extension/dashboardRoute.ts +35 -0
- package/src/fields/ArrayField.ts +33 -0
- package/src/fields/BoolField.ts +34 -0
- package/src/fields/DateField.ts +13 -0
- package/src/fields/DateTimeField.ts +13 -0
- package/src/fields/DecimalField.ts +13 -0
- package/src/fields/FieldUtils.ts +56 -0
- package/src/fields/FloatField.ts +13 -0
- package/src/fields/IntegerField.ts +13 -0
- package/src/fields/LongField.ts +13 -0
- package/src/fields/ObjectField.ts +15 -0
- package/src/fields/StringField.ts +13 -0
- package/src/fields/TextField.ts +13 -0
- package/src/fields/TimeField.ts +13 -0
- package/src/index.ts +53 -0
- package/src/studio/Studio.ts +108 -0
- package/src/types/CollectionControllers.ts +15 -0
- package/src/types/DatabaseDriver.ts +115 -0
- package/src/types/Extension.ts +46 -0
- package/src/types/Field.ts +29 -0
- package/src/types/apiSchema.ts +12 -0
- package/src/types/collectionServiceSchema.ts +18 -0
- package/src/types/config/collectionFields.ts +85 -0
- package/src/types/config/collectionsConfig.ts +50 -0
- package/src/types/config/config.ts +66 -0
- package/src/types/config/relations.ts +17 -0
- package/src/types/filterSchema.ts +88 -0
- package/src/types/index.ts +38 -0
- package/src/types/migrations.ts +12 -0
- package/src/types/websockets.ts +34 -0
- package/src/types/workflows/processors.ts +1 -0
- package/src/utils/lockCollectionToObject.ts +204 -0
- package/src/utils/utils.ts +310 -0
- package/src/workflows/WorkflowSystem.ts +182 -0
- package/src/workflows/coreWorkflows/collectionsTable/index.ts +118 -0
- package/src/workflows/coreWorkflows/index.ts +18 -0
- package/src/workflows/coreWorkflows/processors/postOperationsWorkflows.ts +46 -0
- package/src/workflows/coreWorkflows/processors/preOperationsWorkflows.ts +27 -0
- package/src/workflows/coreWorkflows/processors/processorForDB.ts +13 -0
- package/src/workflows/coreWorkflows/processors/processors/processor.ts +23 -0
- package/src/workflows/coreWorkflows/processors/processors/processorsFunctions.ts +47 -0
- package/src/workflows/coreWorkflows/processors/utils.ts +102 -0
- package/src/workflows/coreWorkflows/processors/validator/validator.ts +19 -0
- package/src/workflows/coreWorkflows/processors/validator/validatorsFunction.ts +52 -0
- package/src/workflows/coreWorkflows/queryCoreWorkflows.ts +31 -0
- package/src/workflows/coreWorkflows/utilsCoreWorkflows.ts +40 -0
- package/src/workflows/coreWorkflows/workflowsCollection/workflowsCollectionWorkflows.ts +101 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
// import type {
|
|
2
|
+
// Db,
|
|
3
|
+
// Document,
|
|
4
|
+
// Filter,
|
|
5
|
+
// IndexDescription,
|
|
6
|
+
// IndexSpecification,
|
|
7
|
+
// } from "mongodb";
|
|
8
|
+
// import type { FindAllParamsOutput } from "../../types/index.ts";
|
|
9
|
+
// import type { Entry } from "../../types/index.ts";
|
|
10
|
+
// import type {
|
|
11
|
+
// CollectionConfig,
|
|
12
|
+
// CollectionField,
|
|
13
|
+
// CollectionFields,
|
|
14
|
+
// CollectionIndex,
|
|
15
|
+
// CollectionIndexes,
|
|
16
|
+
// CollectionIndexFields,
|
|
17
|
+
// CollectionsConfig,
|
|
18
|
+
// } from "../../types/index.ts";
|
|
19
|
+
|
|
20
|
+
// import { MongoClient, MongoServerError, ObjectId } from "mongodb";
|
|
21
|
+
// import { DatabaseDriver } from "../../types/index.ts";
|
|
22
|
+
// import { BSON, Decimal128, Double, Long } from "mongodb";
|
|
23
|
+
// import { omit } from "jsr:@opentf/std@0.12.0";
|
|
24
|
+
// import _ from "lodash";
|
|
25
|
+
// import escapeStringRegexp from "escape-string-regexp";
|
|
26
|
+
// import { LobbError } from "../../../LobbError.ts";
|
|
27
|
+
// import { Lobb } from "../../../Lobb.ts";
|
|
28
|
+
|
|
29
|
+
// export class MongoDriver extends DatabaseDriver {
|
|
30
|
+
// protected connection!: MongoClient;
|
|
31
|
+
// protected db!: Db;
|
|
32
|
+
|
|
33
|
+
// public async createConnection() {
|
|
34
|
+
// const url =
|
|
35
|
+
// `mongodb://${this.databaseConfig.host}:${this.databaseConfig.port}`;
|
|
36
|
+
// const client = new MongoClient(url, {
|
|
37
|
+
// auth: {
|
|
38
|
+
// username: this.databaseConfig.username,
|
|
39
|
+
// password: this.databaseConfig.password,
|
|
40
|
+
// },
|
|
41
|
+
// });
|
|
42
|
+
// this.connection = await client.connect();
|
|
43
|
+
// this.db = this.connection.db(this.databaseConfig.database);
|
|
44
|
+
// }
|
|
45
|
+
|
|
46
|
+
// public async close() {
|
|
47
|
+
// await this.connection.close();
|
|
48
|
+
// }
|
|
49
|
+
|
|
50
|
+
// public async raw(func: (db: Db) => void) {
|
|
51
|
+
// return await func(this.db);
|
|
52
|
+
// }
|
|
53
|
+
|
|
54
|
+
// public async dropDatabase() {
|
|
55
|
+
// await this.db.dropDatabase();
|
|
56
|
+
// }
|
|
57
|
+
|
|
58
|
+
// public async createCollection(
|
|
59
|
+
// collectionName: string,
|
|
60
|
+
// collectionConfig: CollectionConfig,
|
|
61
|
+
// ) {
|
|
62
|
+
// const properties: any = {};
|
|
63
|
+
|
|
64
|
+
// for (
|
|
65
|
+
// const [fieldName, fieldConfig] of Object.entries(collectionConfig.fields)
|
|
66
|
+
// ) {
|
|
67
|
+
// if (fieldName === "id") {
|
|
68
|
+
// continue;
|
|
69
|
+
// }
|
|
70
|
+
// properties[fieldName] = {
|
|
71
|
+
// bsonType: [this.getMongoDBFieldType(fieldConfig.type), "null"],
|
|
72
|
+
// };
|
|
73
|
+
// }
|
|
74
|
+
|
|
75
|
+
// await this.db.createCollection(collectionName, {
|
|
76
|
+
// validator: {
|
|
77
|
+
// "$jsonSchema": {
|
|
78
|
+
// "bsonType": "object",
|
|
79
|
+
// "properties": properties,
|
|
80
|
+
// },
|
|
81
|
+
// },
|
|
82
|
+
// validationLevel: "strict",
|
|
83
|
+
// validationAction: "error",
|
|
84
|
+
// });
|
|
85
|
+
|
|
86
|
+
// // creating the indexes
|
|
87
|
+
// for (
|
|
88
|
+
// const [indexName, value] of Object.entries(
|
|
89
|
+
// collectionConfig.indexes as any,
|
|
90
|
+
// )
|
|
91
|
+
// ) {
|
|
92
|
+
// await this.createIndex(
|
|
93
|
+
// collectionName,
|
|
94
|
+
// indexName,
|
|
95
|
+
// value as any,
|
|
96
|
+
// );
|
|
97
|
+
// }
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
// public async dropCollection(collectionName: string) {
|
|
101
|
+
// await this.db.dropCollection(collectionName);
|
|
102
|
+
// }
|
|
103
|
+
|
|
104
|
+
// public async addField(
|
|
105
|
+
// collectionName: string,
|
|
106
|
+
// fieldName: string,
|
|
107
|
+
// field: CollectionField,
|
|
108
|
+
// ): Promise<void> {
|
|
109
|
+
// const collectionInfo = await this.getCollectionInfo(collectionName) as any;
|
|
110
|
+
// const newValidator = collectionInfo.options.validator;
|
|
111
|
+
// newValidator.$jsonSchema.properties[fieldName] = {
|
|
112
|
+
// bsonType: [this.getMongoDBFieldType(field.type), "null"],
|
|
113
|
+
// };
|
|
114
|
+
// await this.db.command({
|
|
115
|
+
// collMod: collectionName,
|
|
116
|
+
// validator: newValidator,
|
|
117
|
+
// validationLevel: "strict",
|
|
118
|
+
// validationAction: "error",
|
|
119
|
+
// });
|
|
120
|
+
// }
|
|
121
|
+
|
|
122
|
+
// public async removeField(
|
|
123
|
+
// collectionName: string,
|
|
124
|
+
// fieldName: string,
|
|
125
|
+
// ): Promise<void> {
|
|
126
|
+
// const collectionInfo = await this.getCollectionInfo(collectionName) as any;
|
|
127
|
+
// const newValidator = collectionInfo.options.validator;
|
|
128
|
+
// delete newValidator.$jsonSchema.properties[fieldName];
|
|
129
|
+
// await this.db.command({
|
|
130
|
+
// collMod: collectionName,
|
|
131
|
+
// validator: newValidator,
|
|
132
|
+
// validationLevel: "strict",
|
|
133
|
+
// validationAction: "error",
|
|
134
|
+
// });
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// private async getCollectionInfo(collectionName: string) {
|
|
138
|
+
// const collections = await this.db.listCollections().toArray();
|
|
139
|
+
// for (let index = 0; index < collections.length; index++) {
|
|
140
|
+
// const collection = collections[index];
|
|
141
|
+
// if (collection.name === collectionName) {
|
|
142
|
+
// return collection;
|
|
143
|
+
// }
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// throw new LobbError({
|
|
147
|
+
// code: "INTERNAL_SERVER_ERROR",
|
|
148
|
+
// message:
|
|
149
|
+
// `Counldn't find the requested (${collectionName}) collection info`,
|
|
150
|
+
// });
|
|
151
|
+
// }
|
|
152
|
+
|
|
153
|
+
// public async getDbSchema(): Promise<CollectionsConfig> {
|
|
154
|
+
// const dbSchema: CollectionsConfig = {};
|
|
155
|
+
// const dbCollections = await this.db.listCollections().toArray();
|
|
156
|
+
|
|
157
|
+
// for (let index = 0; index < dbCollections.length; index++) {
|
|
158
|
+
// const collection: any = dbCollections[index];
|
|
159
|
+
// const fields = collection.options.validator?.$jsonSchema.properties;
|
|
160
|
+
// if (fields) {
|
|
161
|
+
// const fieldsConfig: CollectionFields = {
|
|
162
|
+
// id: {
|
|
163
|
+
// type: "integer",
|
|
164
|
+
// },
|
|
165
|
+
// };
|
|
166
|
+
// for (const [fieldName, value] of Object.entries(fields)) {
|
|
167
|
+
// const fieldValue = value as any;
|
|
168
|
+
// fieldsConfig[fieldName] = {
|
|
169
|
+
// type: this.getCollectionFieldType(fieldValue.bsonType[0]),
|
|
170
|
+
// };
|
|
171
|
+
// }
|
|
172
|
+
|
|
173
|
+
// dbSchema[collection.name] = {
|
|
174
|
+
// indexes: await this.getIndexes(collection.name),
|
|
175
|
+
// fields: fieldsConfig,
|
|
176
|
+
// };
|
|
177
|
+
// }
|
|
178
|
+
// }
|
|
179
|
+
|
|
180
|
+
// return dbSchema;
|
|
181
|
+
// }
|
|
182
|
+
|
|
183
|
+
// public async adaptFilter(
|
|
184
|
+
// filter: any,
|
|
185
|
+
// collectionName: string,
|
|
186
|
+
// ): Promise<Filter<Document>> {
|
|
187
|
+
// const fieldNames = Lobb.instance.configManager.getFieldNames(
|
|
188
|
+
// collectionName,
|
|
189
|
+
// );
|
|
190
|
+
// filter = _.cloneDeepWith(
|
|
191
|
+
// filter,
|
|
192
|
+
// (value: any, _key: string) => {
|
|
193
|
+
// const group: any = {};
|
|
194
|
+
// group.$and = [];
|
|
195
|
+
// for (let index = 0; index < fieldNames.length; index++) {
|
|
196
|
+
// const fieldName = fieldNames[index];
|
|
197
|
+
// const innerGroup: any = {};
|
|
198
|
+
// innerGroup.$and = [];
|
|
199
|
+
// if (value[fieldName]) {
|
|
200
|
+
// if (value[fieldName].$contains) {
|
|
201
|
+
// innerGroup.$and.push({
|
|
202
|
+
// [fieldName]: {
|
|
203
|
+
// $regex: escapeStringRegexp(value[fieldName].$contains),
|
|
204
|
+
// },
|
|
205
|
+
// });
|
|
206
|
+
// }
|
|
207
|
+
|
|
208
|
+
// if (value[fieldName].$icontains) {
|
|
209
|
+
// innerGroup.$and.push({
|
|
210
|
+
// [fieldName]: {
|
|
211
|
+
// $regex: escapeStringRegexp(value[fieldName].$icontains),
|
|
212
|
+
// $options: "i",
|
|
213
|
+
// },
|
|
214
|
+
// });
|
|
215
|
+
// }
|
|
216
|
+
|
|
217
|
+
// if (value[fieldName].$ncontains) {
|
|
218
|
+
// innerGroup.$and.push({
|
|
219
|
+
// [fieldName]: {
|
|
220
|
+
// $not: {
|
|
221
|
+
// $regex: escapeStringRegexp(value[fieldName].$ncontains),
|
|
222
|
+
// },
|
|
223
|
+
// },
|
|
224
|
+
// });
|
|
225
|
+
// }
|
|
226
|
+
|
|
227
|
+
// if (value[fieldName].$incontains) {
|
|
228
|
+
// innerGroup.$and.push({
|
|
229
|
+
// [fieldName]: {
|
|
230
|
+
// $not: {
|
|
231
|
+
// $regex: escapeStringRegexp(value[fieldName].$incontains),
|
|
232
|
+
// $options: "i",
|
|
233
|
+
// },
|
|
234
|
+
// },
|
|
235
|
+
// });
|
|
236
|
+
// }
|
|
237
|
+
|
|
238
|
+
// if (value[fieldName].$starts_with) {
|
|
239
|
+
// innerGroup.$and.push({
|
|
240
|
+
// [fieldName]: {
|
|
241
|
+
// $regex: `^${
|
|
242
|
+
// escapeStringRegexp(value[fieldName].$starts_with)
|
|
243
|
+
// }`,
|
|
244
|
+
// },
|
|
245
|
+
// });
|
|
246
|
+
// }
|
|
247
|
+
|
|
248
|
+
// if (value[fieldName].$istarts_with) {
|
|
249
|
+
// innerGroup.$and.push({
|
|
250
|
+
// [fieldName]: {
|
|
251
|
+
// $regex: `^${
|
|
252
|
+
// escapeStringRegexp(value[fieldName].$istarts_with)
|
|
253
|
+
// }`,
|
|
254
|
+
// $options: "i",
|
|
255
|
+
// },
|
|
256
|
+
// });
|
|
257
|
+
// }
|
|
258
|
+
|
|
259
|
+
// if (value[fieldName].$nstarts_with) {
|
|
260
|
+
// innerGroup.$and.push({
|
|
261
|
+
// [fieldName]: {
|
|
262
|
+
// $not: {
|
|
263
|
+
// $regex: `^${
|
|
264
|
+
// escapeStringRegexp(value[fieldName].$nstarts_with)
|
|
265
|
+
// }`,
|
|
266
|
+
// },
|
|
267
|
+
// },
|
|
268
|
+
// });
|
|
269
|
+
// }
|
|
270
|
+
|
|
271
|
+
// if (value[fieldName].$instarts_with) {
|
|
272
|
+
// innerGroup.$and.push({
|
|
273
|
+
// [fieldName]: {
|
|
274
|
+
// $not: {
|
|
275
|
+
// $regex: `^${
|
|
276
|
+
// escapeStringRegexp(value[fieldName].$instarts_with)
|
|
277
|
+
// }`,
|
|
278
|
+
// $options: "i",
|
|
279
|
+
// },
|
|
280
|
+
// },
|
|
281
|
+
// });
|
|
282
|
+
// }
|
|
283
|
+
|
|
284
|
+
// if (value[fieldName].$ends_with) {
|
|
285
|
+
// innerGroup.$and.push({
|
|
286
|
+
// [fieldName]: {
|
|
287
|
+
// $regex: `${escapeStringRegexp(value[fieldName].$ends_with)}$`,
|
|
288
|
+
// },
|
|
289
|
+
// });
|
|
290
|
+
// }
|
|
291
|
+
|
|
292
|
+
// if (value[fieldName].$iends_with) {
|
|
293
|
+
// innerGroup.$and.push({
|
|
294
|
+
// [fieldName]: {
|
|
295
|
+
// $regex: `${
|
|
296
|
+
// escapeStringRegexp(value[fieldName].$iends_with)
|
|
297
|
+
// }$`,
|
|
298
|
+
// $options: "i",
|
|
299
|
+
// },
|
|
300
|
+
// });
|
|
301
|
+
// }
|
|
302
|
+
|
|
303
|
+
// if (value[fieldName].$nends_with) {
|
|
304
|
+
// innerGroup.$and.push({
|
|
305
|
+
// [fieldName]: {
|
|
306
|
+
// $not: {
|
|
307
|
+
// $regex: `${
|
|
308
|
+
// escapeStringRegexp(value[fieldName].$nends_with)
|
|
309
|
+
// }$`,
|
|
310
|
+
// },
|
|
311
|
+
// },
|
|
312
|
+
// });
|
|
313
|
+
// }
|
|
314
|
+
|
|
315
|
+
// if (value[fieldName].$inends_with) {
|
|
316
|
+
// innerGroup.$and.push({
|
|
317
|
+
// [fieldName]: {
|
|
318
|
+
// $not: {
|
|
319
|
+
// $regex: `${
|
|
320
|
+
// escapeStringRegexp(value[fieldName].$inends_with)
|
|
321
|
+
// }$`,
|
|
322
|
+
// $options: "i",
|
|
323
|
+
// },
|
|
324
|
+
// },
|
|
325
|
+
// });
|
|
326
|
+
// }
|
|
327
|
+
|
|
328
|
+
// if (value[fieldName].$between) {
|
|
329
|
+
// innerGroup.$and.push({
|
|
330
|
+
// [fieldName]: {
|
|
331
|
+
// $gte: value[fieldName].$between[0],
|
|
332
|
+
// $lte: value[fieldName].$between[1],
|
|
333
|
+
// },
|
|
334
|
+
// });
|
|
335
|
+
// }
|
|
336
|
+
|
|
337
|
+
// if (value[fieldName].$nbetween) {
|
|
338
|
+
// innerGroup.$and.push({
|
|
339
|
+
// [fieldName]: {
|
|
340
|
+
// $not: {
|
|
341
|
+
// $gte: value[fieldName].$nbetween[0],
|
|
342
|
+
// $lte: value[fieldName].$nbetween[1],
|
|
343
|
+
// },
|
|
344
|
+
// },
|
|
345
|
+
// });
|
|
346
|
+
// }
|
|
347
|
+
|
|
348
|
+
// if (innerGroup.$and.length) {
|
|
349
|
+
// group.$and.push(innerGroup);
|
|
350
|
+
// }
|
|
351
|
+
// }
|
|
352
|
+
// }
|
|
353
|
+
|
|
354
|
+
// if (group.$and.length) {
|
|
355
|
+
// return group;
|
|
356
|
+
// }
|
|
357
|
+
// },
|
|
358
|
+
// );
|
|
359
|
+
|
|
360
|
+
// filter = this.renameIdKeys(filter);
|
|
361
|
+
|
|
362
|
+
// return filter;
|
|
363
|
+
// }
|
|
364
|
+
|
|
365
|
+
// ////////////////////////
|
|
366
|
+
// // Indexes Operations //
|
|
367
|
+
// ////////////////////////
|
|
368
|
+
// public async createIndex(
|
|
369
|
+
// collectionName: string,
|
|
370
|
+
// indexName: string,
|
|
371
|
+
// indexInfo: CollectionIndex,
|
|
372
|
+
// ) {
|
|
373
|
+
// const collection = this.db.collection(collectionName);
|
|
374
|
+
|
|
375
|
+
// const fields: IndexSpecification = {};
|
|
376
|
+
// for (const fieldName in indexInfo.fields) {
|
|
377
|
+
// const field = indexInfo.fields[fieldName];
|
|
378
|
+
// fields[fieldName] = field.order === "asc" ? 1 : -1;
|
|
379
|
+
// }
|
|
380
|
+
|
|
381
|
+
// try {
|
|
382
|
+
// await collection.createIndex(fields, {
|
|
383
|
+
// unique: indexInfo.unique,
|
|
384
|
+
// name: indexName,
|
|
385
|
+
// });
|
|
386
|
+
// } catch (error) {
|
|
387
|
+
// if (error instanceof MongoServerError) {
|
|
388
|
+
// if (
|
|
389
|
+
// error.errmsg.includes("Index already exists with a different name")
|
|
390
|
+
// ) {
|
|
391
|
+
// const existingIndexName = error.errmsg.split(": ")[1];
|
|
392
|
+
// await collection.dropIndex(existingIndexName);
|
|
393
|
+
// await this.createIndex(collectionName, indexName, indexInfo);
|
|
394
|
+
// } else {
|
|
395
|
+
// throw error;
|
|
396
|
+
// }
|
|
397
|
+
// } else {
|
|
398
|
+
// throw error;
|
|
399
|
+
// }
|
|
400
|
+
// }
|
|
401
|
+
// }
|
|
402
|
+
|
|
403
|
+
// public async dropIndex(collectionName: string, indexName: string) {
|
|
404
|
+
// const collection = this.db.collection(collectionName);
|
|
405
|
+
// await collection.dropIndex(indexName);
|
|
406
|
+
// }
|
|
407
|
+
|
|
408
|
+
// public async getIndexes(collectionName: string): Promise<CollectionIndexes> {
|
|
409
|
+
// const collection = this.db.collection(collectionName);
|
|
410
|
+
// const indexes: IndexDescription[] = await collection.indexes();
|
|
411
|
+
// const collectionIndexes: CollectionIndexes = {};
|
|
412
|
+
|
|
413
|
+
// for (let index = 0; index < indexes.length; index++) {
|
|
414
|
+
// const indexObject = indexes[index];
|
|
415
|
+
// // dont return the default indexes that are created automatically when a
|
|
416
|
+
// // collection is created
|
|
417
|
+
// const defaultIndexesNames = ["_id_"];
|
|
418
|
+
// if (indexObject.name && !defaultIndexesNames.includes(indexObject.name)) {
|
|
419
|
+
// const fields: CollectionIndexFields = {};
|
|
420
|
+
// for (const [fieldName, order] of Object.entries(indexObject.key)) {
|
|
421
|
+
// fields[fieldName] = {
|
|
422
|
+
// order: order === 1 ? "asc" : "desc",
|
|
423
|
+
// };
|
|
424
|
+
// }
|
|
425
|
+
// collectionIndexes[indexObject.name] = {
|
|
426
|
+
// unique: indexObject.unique ?? false,
|
|
427
|
+
// fields,
|
|
428
|
+
// };
|
|
429
|
+
// }
|
|
430
|
+
// }
|
|
431
|
+
|
|
432
|
+
// return collectionIndexes;
|
|
433
|
+
// }
|
|
434
|
+
|
|
435
|
+
// /////////////////////
|
|
436
|
+
// // CRUD OPERATIONS //
|
|
437
|
+
// /////////////////////
|
|
438
|
+
// public async findAll(collectionName: string, params: FindAllParamsOutput) {
|
|
439
|
+
// const collection = this.db.collection(collectionName);
|
|
440
|
+
// const pipeline = this.findAllParamsToPipeline(params);
|
|
441
|
+
// const data = await collection.aggregate(pipeline).toArray();
|
|
442
|
+
// return this.adaptToReturnFormatManyDocuments(data, params);
|
|
443
|
+
// }
|
|
444
|
+
|
|
445
|
+
// public async findOne(collectionName: string, filter: any) {
|
|
446
|
+
// const collection = this.db.collection(collectionName);
|
|
447
|
+
// const data = await collection.findOne(filter);
|
|
448
|
+
// if (data) {
|
|
449
|
+
// return this.adaptToReturnFormatOneDocuments(data);
|
|
450
|
+
// }
|
|
451
|
+
// return data;
|
|
452
|
+
// }
|
|
453
|
+
|
|
454
|
+
// public async createOne(collectionName: string, data: any) {
|
|
455
|
+
// const collection = this.db.collection(collectionName);
|
|
456
|
+
// try {
|
|
457
|
+
// delete data.id;
|
|
458
|
+
// const result = await collection.insertOne(data);
|
|
459
|
+
// delete data._id;
|
|
460
|
+
// return {
|
|
461
|
+
// id: result.insertedId,
|
|
462
|
+
// ...data,
|
|
463
|
+
// };
|
|
464
|
+
// } catch (error) {
|
|
465
|
+
// console.error(`(Driver Error): ${error}`);
|
|
466
|
+
// if (error instanceof MongoServerError) {
|
|
467
|
+
// if (error.code === 11000) {
|
|
468
|
+
// throw new LobbError({
|
|
469
|
+
// code: "CONFLICT",
|
|
470
|
+
// message:
|
|
471
|
+
// `One or more fields violate the uniqueness constraint in the (${collectionName}) collection.`,
|
|
472
|
+
// });
|
|
473
|
+
// }
|
|
474
|
+
|
|
475
|
+
// throw error;
|
|
476
|
+
// }
|
|
477
|
+
// throw error;
|
|
478
|
+
// }
|
|
479
|
+
// }
|
|
480
|
+
|
|
481
|
+
// public async updateOne(
|
|
482
|
+
// collectionName: string,
|
|
483
|
+
// filter: any,
|
|
484
|
+
// data: any,
|
|
485
|
+
// ) {
|
|
486
|
+
// const collection = this.db.collection(collectionName);
|
|
487
|
+
// const entry = await collection.findOneAndUpdate(filter, {
|
|
488
|
+
// $set: data,
|
|
489
|
+
// }, {
|
|
490
|
+
// returnDocument: "after",
|
|
491
|
+
// });
|
|
492
|
+
// if (entry) {
|
|
493
|
+
// return this.adaptToReturnFormatOneDocuments(entry);
|
|
494
|
+
// }
|
|
495
|
+
// return entry;
|
|
496
|
+
// }
|
|
497
|
+
|
|
498
|
+
// public async deleteOne(
|
|
499
|
+
// collectionName: string,
|
|
500
|
+
// filter: any,
|
|
501
|
+
// ) {
|
|
502
|
+
// const collection = this.db.collection(collectionName);
|
|
503
|
+
// const entry = await collection.findOneAndDelete(filter);
|
|
504
|
+
// if (entry) {
|
|
505
|
+
// return this.adaptToReturnFormatOneDocuments(entry);
|
|
506
|
+
// }
|
|
507
|
+
// return entry;
|
|
508
|
+
// }
|
|
509
|
+
|
|
510
|
+
// public async deleteMany(
|
|
511
|
+
// collectionName: string,
|
|
512
|
+
// filter?: any,
|
|
513
|
+
// ) {
|
|
514
|
+
// const collection = this.db.collection(collectionName);
|
|
515
|
+
// const entry = await collection.deleteMany();
|
|
516
|
+
// return {
|
|
517
|
+
// affectedCount: entry.deletedCount,
|
|
518
|
+
// };
|
|
519
|
+
// }
|
|
520
|
+
|
|
521
|
+
// public async updateMany(
|
|
522
|
+
// collectionName: string,
|
|
523
|
+
// data: any,
|
|
524
|
+
// filter?: any,
|
|
525
|
+
// ) {
|
|
526
|
+
// const collection = this.db.collection(collectionName);
|
|
527
|
+
// const entry = await collection.updateMany(filter, {
|
|
528
|
+
// $set: data,
|
|
529
|
+
// });
|
|
530
|
+
// return {
|
|
531
|
+
// affectedCount: entry.modifiedCount,
|
|
532
|
+
// };
|
|
533
|
+
// }
|
|
534
|
+
|
|
535
|
+
// public async createMany(
|
|
536
|
+
// collectionName: string,
|
|
537
|
+
// data: any,
|
|
538
|
+
// ) {
|
|
539
|
+
// const collection = this.db.collection(collectionName);
|
|
540
|
+
// const entry = await collection.insertMany(data);
|
|
541
|
+
// return {
|
|
542
|
+
// affectedCount: entry.insertedCount,
|
|
543
|
+
// };
|
|
544
|
+
// }
|
|
545
|
+
|
|
546
|
+
// /////////////////////
|
|
547
|
+
// // META OPERATIONS //
|
|
548
|
+
// /////////////////////
|
|
549
|
+
// public async getTotalCount(
|
|
550
|
+
// collectionName: string,
|
|
551
|
+
// filter: any,
|
|
552
|
+
// ) {
|
|
553
|
+
// const collection = this.db.collection(collectionName);
|
|
554
|
+
// return await collection.countDocuments(filter);
|
|
555
|
+
// }
|
|
556
|
+
|
|
557
|
+
// ////////////////////
|
|
558
|
+
// // HELPER METHODS //
|
|
559
|
+
// ////////////////////
|
|
560
|
+
// private adaptToReturnFormatManyDocuments(
|
|
561
|
+
// data: Document[],
|
|
562
|
+
// params: FindAllParamsOutput,
|
|
563
|
+
// ): Entry[] {
|
|
564
|
+
// // renaming the _id property to id
|
|
565
|
+
// data = data.map((obj) => {
|
|
566
|
+
// delete obj.id;
|
|
567
|
+
// const { _id, ...rest } = obj;
|
|
568
|
+
// return { id: _id, ...rest };
|
|
569
|
+
// });
|
|
570
|
+
|
|
571
|
+
// // remove the id if it wasn't selected by the user
|
|
572
|
+
// const idExist = params.fields === "*" || params.fields.includes("id");
|
|
573
|
+
// if (!idExist) {
|
|
574
|
+
// data = data.map((element) => {
|
|
575
|
+
// return omit(element, ["id"]);
|
|
576
|
+
// });
|
|
577
|
+
// }
|
|
578
|
+
|
|
579
|
+
// return data as Entry[];
|
|
580
|
+
// }
|
|
581
|
+
|
|
582
|
+
// private adaptToReturnFormatOneDocuments(data: Document): Entry {
|
|
583
|
+
// delete data.id;
|
|
584
|
+
// const { _id, ...rest } = data;
|
|
585
|
+
// return { id: _id, ...rest };
|
|
586
|
+
// }
|
|
587
|
+
|
|
588
|
+
// private findAllParamsToPipeline(params: FindAllParamsOutput): Document[] {
|
|
589
|
+
// const pipelines: Document[] = [];
|
|
590
|
+
|
|
591
|
+
// // sort
|
|
592
|
+
// if (params.sort) {
|
|
593
|
+
// const document: Document = {};
|
|
594
|
+
// document["$sort"] = {};
|
|
595
|
+
// const sorts = params.sort.split(",").map((fieldNames: any) =>
|
|
596
|
+
// fieldNames.trim()
|
|
597
|
+
// );
|
|
598
|
+
// for (let index = 0; index < sorts.length; index++) {
|
|
599
|
+
// const sort = sorts[index];
|
|
600
|
+
// if (sort[0] === "-") {
|
|
601
|
+
// document["$sort"][sort.substring(1)] = -1;
|
|
602
|
+
// } else {
|
|
603
|
+
// document["$sort"][sort] = 1;
|
|
604
|
+
// }
|
|
605
|
+
// }
|
|
606
|
+
// pipelines.push(document);
|
|
607
|
+
// }
|
|
608
|
+
|
|
609
|
+
// // page
|
|
610
|
+
// let offset = params.offset;
|
|
611
|
+
// if (params.page) {
|
|
612
|
+
// offset = (params.page - 1) * params.limit;
|
|
613
|
+
// }
|
|
614
|
+
|
|
615
|
+
// // offset
|
|
616
|
+
// const sortDocument: Document = {};
|
|
617
|
+
// sortDocument["$skip"] = offset;
|
|
618
|
+
// pipelines.push(sortDocument);
|
|
619
|
+
|
|
620
|
+
// // limit
|
|
621
|
+
// const limitDocument: Document = {};
|
|
622
|
+
// limitDocument["$limit"] = params.limit;
|
|
623
|
+
// pipelines.push(limitDocument);
|
|
624
|
+
|
|
625
|
+
// // adding normal and auth filters
|
|
626
|
+
// const document: Document = {};
|
|
627
|
+
// if (params.filter) {
|
|
628
|
+
// document["$match"] = {};
|
|
629
|
+
// document["$match"]["$and"] = [];
|
|
630
|
+
// document["$match"]["$and"].push(params.filter);
|
|
631
|
+
// }
|
|
632
|
+
// if (Object.keys(document).length) {
|
|
633
|
+
// pipelines.push(document);
|
|
634
|
+
// }
|
|
635
|
+
|
|
636
|
+
// // fields
|
|
637
|
+
// if (params.fields !== "*") {
|
|
638
|
+
// const document: Document = {};
|
|
639
|
+
// document["$project"] = {};
|
|
640
|
+
// const fields = Array.isArray(params.fields)
|
|
641
|
+
// ? params.fields
|
|
642
|
+
// : params.fields.split(",");
|
|
643
|
+
// for (let index = 0; index < fields.length; index++) {
|
|
644
|
+
// const fieldName = fields[index].trim();
|
|
645
|
+
// document["$project"][fieldName] = 1;
|
|
646
|
+
// }
|
|
647
|
+
// pipelines.push(document);
|
|
648
|
+
// }
|
|
649
|
+
|
|
650
|
+
// return pipelines;
|
|
651
|
+
// }
|
|
652
|
+
|
|
653
|
+
// private renameIdKeys(value: any) {
|
|
654
|
+
// return _.cloneDeepWith(value, (val: any, key: any) => {
|
|
655
|
+
// if (val && val.id) {
|
|
656
|
+
// val._id = val.id;
|
|
657
|
+
// delete val.id;
|
|
658
|
+
// return val;
|
|
659
|
+
// }
|
|
660
|
+
// });
|
|
661
|
+
// }
|
|
662
|
+
|
|
663
|
+
// private getMongoDBFieldType(type: any) {
|
|
664
|
+
// const typeMapping: any = {
|
|
665
|
+
// id: "objectId",
|
|
666
|
+
// string: "string",
|
|
667
|
+
// bool: "bool",
|
|
668
|
+
// date: "date",
|
|
669
|
+
// integer: "int",
|
|
670
|
+
// long: "long",
|
|
671
|
+
// float: "double",
|
|
672
|
+
// decimal: "decimal",
|
|
673
|
+
// };
|
|
674
|
+
|
|
675
|
+
// if (!typeMapping[type]) {
|
|
676
|
+
// throw new LobbError({
|
|
677
|
+
// code: "INTERNAL_SERVER_ERROR",
|
|
678
|
+
// message: "Couldn't find an equivelant mongodb type",
|
|
679
|
+
// });
|
|
680
|
+
// }
|
|
681
|
+
|
|
682
|
+
// return typeMapping[type];
|
|
683
|
+
// }
|
|
684
|
+
|
|
685
|
+
// private getCollectionFieldType(mongoDBType: string): any {
|
|
686
|
+
// const typeMapping: Record<string, any> = {
|
|
687
|
+
// objectId: "integer",
|
|
688
|
+
// string: "string",
|
|
689
|
+
// bool: "bool",
|
|
690
|
+
// date: "date",
|
|
691
|
+
// int: "integer",
|
|
692
|
+
// long: "long",
|
|
693
|
+
// double: "float",
|
|
694
|
+
// decimal: "decimal",
|
|
695
|
+
// };
|
|
696
|
+
|
|
697
|
+
// if (!typeMapping[mongoDBType]) {
|
|
698
|
+
// throw new LobbError({
|
|
699
|
+
// code: "INTERNAL_SERVER_ERROR",
|
|
700
|
+
// message: "Couldn't find an equivalent CollectionFieldType",
|
|
701
|
+
// });
|
|
702
|
+
// }
|
|
703
|
+
|
|
704
|
+
// return typeMapping[mongoDBType];
|
|
705
|
+
// }
|
|
706
|
+
|
|
707
|
+
// ///////////////////////////////////////////////////////////
|
|
708
|
+
// // parse some types of data to be compatible with the db //
|
|
709
|
+
// ///////////////////////////////////////////////////////////
|
|
710
|
+
// public override encodeFieldValue(fieldType: string, value: any) {
|
|
711
|
+
// if (fieldType === "id") {
|
|
712
|
+
// if (typeof value === "object" && ObjectId.isValid(value)) {
|
|
713
|
+
// return value;
|
|
714
|
+
// }
|
|
715
|
+
|
|
716
|
+
// return ObjectId.createFromHexString(value);
|
|
717
|
+
// } else if (fieldType === "decimal") {
|
|
718
|
+
// return new Decimal128(value);
|
|
719
|
+
// } else if (fieldType === "float") {
|
|
720
|
+
// const double = new Double(value);
|
|
721
|
+
// if (isNaN(double.value)) {
|
|
722
|
+
// throw new LobbError({
|
|
723
|
+
// code: "INTERNAL_SERVER_ERROR",
|
|
724
|
+
// message: `this Value (${value}) is not a valid float`,
|
|
725
|
+
// });
|
|
726
|
+
// }
|
|
727
|
+
// return double;
|
|
728
|
+
// } else if (fieldType === "long") {
|
|
729
|
+
// return new Long(value);
|
|
730
|
+
// }
|
|
731
|
+
|
|
732
|
+
// return value;
|
|
733
|
+
// }
|
|
734
|
+
|
|
735
|
+
// public override decodeFieldValue(fieldType: string, value: any) {
|
|
736
|
+
// if (fieldType === "id") {
|
|
737
|
+
// return value.toHexString();
|
|
738
|
+
// } else if (fieldType === "date") {
|
|
739
|
+
// return value.toISOString();
|
|
740
|
+
// } else if (fieldType === "decimal") {
|
|
741
|
+
// return value.toString();
|
|
742
|
+
// } else if (fieldType === "float") {
|
|
743
|
+
// return value.toString();
|
|
744
|
+
// } else if (fieldType === "long") {
|
|
745
|
+
// return value.toString();
|
|
746
|
+
// }
|
|
747
|
+
|
|
748
|
+
// return value;
|
|
749
|
+
// }
|
|
750
|
+
// }
|