@cocreate/mongodb 1.10.6 → 1.12.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/CHANGELOG.md CHANGED
@@ -1,3 +1,33 @@
1
+ # [1.12.0](https://github.com/CoCreate-app/CoCreate-mongodb/compare/v1.11.0...v1.12.0) (2023-11-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * $storage, $database, $array are arrays ([9cda13a](https://github.com/CoCreate-app/CoCreate-mongodb/commit/9cda13ad88eff2639da6b1c5a60dc901a54d0518))
7
+ * meta name typo ([c7c8e1d](https://github.com/CoCreate-app/CoCreate-mongodb/commit/c7c8e1d7182f5992a5a1567e2ff7edf678cefbde))
8
+ * update date queries ([3f8103d](https://github.com/CoCreate-app/CoCreate-mongodb/commit/3f8103db89f0037f566e930928742a20825e24cd))
9
+ * update method names ([936254d](https://github.com/CoCreate-app/CoCreate-mongodb/commit/936254d850536e55daaaf2d7862930a3068e8aee))
10
+
11
+
12
+ ### Features
13
+
14
+ * merge data[types] with same _id for type objects and name for all other types ([1da51a8](https://github.com/CoCreate-app/CoCreate-mongodb/commit/1da51a8c0600ecbe84af41fcc5c77f1949d36c60))
15
+
16
+ # [1.11.0](https://github.com/CoCreate-app/CoCreate-mongodb/compare/v1.10.6...v1.11.0) (2023-11-03)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * favicon.ico path ([5e54a37](https://github.com/CoCreate-app/CoCreate-mongodb/commit/5e54a371dcbebc7364d401570c3f0cbeb3f0db31))
22
+ * update dependencies to the lates versions ([2a4dc62](https://github.com/CoCreate-app/CoCreate-mongodb/commit/2a4dc6263067c3c1cc4571d623aa8530a83708d1))
23
+ * update method to use object.update etc ([1e9e7b8](https://github.com/CoCreate-app/CoCreate-mongodb/commit/1e9e7b8e81d7512ec546cdbcbc381851477f8271))
24
+
25
+
26
+ ### Features
27
+
28
+ * morph data[type] so the object can be synced across multiple storage, database, arra ([8d29c0a](https://github.com/CoCreate-app/CoCreate-mongodb/commit/8d29c0a7cc160654e04e0e6266f82906e772f57f))
29
+ * read.object will compare modified.on and update db ([b8b2c74](https://github.com/CoCreate-app/CoCreate-mongodb/commit/b8b2c74e2abbf568eda14c1328961781395d7c5c))
30
+
1
31
  ## [1.10.6](https://github.com/CoCreate-app/CoCreate-mongodb/compare/v1.10.5...v1.10.6) (2023-10-25)
2
32
 
3
33
 
package/demo/index.html CHANGED
@@ -6,9 +6,9 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
7
  <link
8
8
  rel="icon"
9
- href="https://cdn.cocreate.app/favicon.ico"
10
- type="image/ico"
11
- sizes="16x16" />
9
+ type="image/png"
10
+ sizes="32x32"
11
+ href="../assets/favicon.ico" />
12
12
  <title>mongodb | CoCreateJS</title>
13
13
  </head>
14
14
 
package/docs/index.html CHANGED
@@ -11,10 +11,10 @@
11
11
  sizes="32x32"
12
12
  href="https://cocreate.app/images/favicon.ico" />
13
13
  <meta
14
- key="description"
14
+ name="description"
15
15
  content="A simple HTML5 and pure javascript component. Easy configuration using data-attributes and highly styleable." />
16
16
  <meta
17
- key="keywords"
17
+ name="keywords"
18
18
  content="helper classes, utility classes, css framework, css library, inline style classes" />
19
19
  <meta name="robots" content="index,follow" />
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/mongodb",
3
- "version": "1.10.6",
3
+ "version": "1.12.0",
4
4
  "description": "A simple mongodb component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "mongodb",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "main": "./src/index.js",
47
47
  "dependencies": {
48
- "@cocreate/utils": "^1.26.1",
48
+ "@cocreate/utils": "^1.26.2",
49
49
  "mongodb": "^4.12.1"
50
50
  }
51
51
  }
package/src/index.js CHANGED
@@ -1,40 +1,41 @@
1
1
  const { MongoClient, ObjectId } = require('mongodb');
2
2
  const { dotNotationToObject, queryData, searchData, sortData, isValidDate } = require('@cocreate/utils')
3
3
  const clients = new Map()
4
-
4
+ const organizations = {}
5
5
 
6
6
  async function dbClient(data) {
7
7
  if (data.storageUrl) {
8
- let client = clients.get(data.storageUrl)
9
- if (!client && !clients.has(data.storageUrl)) {
10
- try {
11
- clients.set(data.storageUrl, client)
12
- client = await MongoClient.connect(data.storageUrl, { useNewUrlParser: true, useUnifiedTopology: true });
13
- clients.set(data.storageUrl, client)
14
- } catch (error) {
15
- console.error(`${data.organization_id}: storageName ${data.storageName} failed to connect to mongodb`)
16
- errorHandler(data, error)
17
- return { status: false }
18
- }
8
+ if (!organizations[data.organization_id])
9
+ organizations[data.organization_id] = {}
10
+ try {
11
+ if (!organizations[data.organization_id][data.storageUrl])
12
+ organizations[data.organization_id][data.storageUrl] = MongoClient.connect(data.storageUrl, { useNewUrlParser: true, useUnifiedTopology: true })
13
+
14
+ organizations[data.organization_id][data.storageUrl] = await organizations[data.organization_id][data.storageUrl]
15
+ return organizations[data.organization_id][data.storageUrl]
16
+
17
+ } catch (error) {
18
+ console.error(`${data.organization_id}: storageName ${data.storageName} failed to connect to mongodb`)
19
+ errorHandler(data, error)
20
+ return { status: false }
19
21
  }
20
- return client
21
22
  }
23
+
24
+ errorHandler(data, 'missing StorageUrl')
22
25
  return
23
26
  }
24
27
 
25
28
  function send(data) {
26
- let [method, type] = data.method.split('.')
27
- // let action = data.method.replace(/\.([a-z])/g, (_, match) => match.toUpperCase());
28
-
29
+ let [type, method] = data.method.split('.')
29
30
  if (type === 'database')
30
- return database(method + type.charAt(0).toUpperCase() + type.slice(1), data)
31
+ return database(method, data)
31
32
  if (type === 'array')
32
- return array(method + type.charAt(0).toUpperCase() + type.slice(1), data)
33
+ return array(method, data)
33
34
  if (type === 'object')
34
- return object(method + type.charAt(0).toUpperCase() + type.slice(1), data)
35
+ return object(method, data)
35
36
  }
36
37
 
37
- function database(action, data) {
38
+ function database(method, data) {
38
39
  return new Promise(async (resolve, reject) => {
39
40
  let type = 'database'
40
41
  let databaseArray = []
@@ -45,7 +46,7 @@ function database(action, data) {
45
46
  const client = await dbClient(data)
46
47
  if (!client || client.status === false)
47
48
  return data
48
- if (action == 'readDatabase') {
49
+ if (method == 'read') {
49
50
  const db = client.db().admin();
50
51
  // TODO: support if a database name is defined then return the database details and stats
51
52
  // else apply filter and return dbs for which each should have stats and details
@@ -70,7 +71,7 @@ function database(action, data) {
70
71
  resolve(createData(data, databaseArray, type))
71
72
  })
72
73
  }
73
- if (action == 'deleteDatabase') {
74
+ if (method == 'delete') {
74
75
  const db = client.db(data.database);
75
76
  db.dropDatabase().then(restult => {
76
77
  dataTransferedIn += getBytes(restult)
@@ -79,7 +80,7 @@ function database(action, data) {
79
80
  }
80
81
  } catch (error) {
81
82
  errorHandler(data, error)
82
- console.log(action, 'error', error);
83
+ console.log(method, 'error', error);
83
84
  resolve(data);
84
85
  }
85
86
 
@@ -88,7 +89,7 @@ function database(action, data) {
88
89
  });
89
90
  }
90
91
 
91
- function array(action, data) {
92
+ function array(method, data) {
92
93
  return new Promise(async (resolve, reject) => {
93
94
  let type = 'array'
94
95
  let arrayArray = [];
@@ -111,7 +112,7 @@ function array(action, data) {
111
112
  for (let database of databases) {
112
113
  const db = client.db(database);
113
114
 
114
- if (action == 'readCollection') {
115
+ if (method == 'read') {
115
116
 
116
117
  let { query, sort } = await createFilter(data);
117
118
 
@@ -141,7 +142,7 @@ function array(action, data) {
141
142
  } else {
142
143
  let arrays
143
144
  let value
144
- if (action == 'updateCollection')
145
+ if (method == 'update')
145
146
  arrays = Object.entries(data.array)
146
147
  else
147
148
  arrays = data.array;
@@ -152,7 +153,7 @@ function array(action, data) {
152
153
  let arraysLength = arrays.length
153
154
  for (let array of arrays) {
154
155
 
155
- if (action == 'createCollection') {
156
+ if (method == 'create') {
156
157
  dataTransferedOut += getBytes(array)
157
158
  db.createCollection(array, function (error, result) {
158
159
  if (error)
@@ -173,13 +174,13 @@ function array(action, data) {
173
174
  }
174
175
  })
175
176
  } else {
176
- if (action == 'updateCollection') {
177
+ if (method == 'update') {
177
178
  [array, value] = array
178
179
  }
179
180
 
180
181
  const arrayObj = db.collection(array);
181
182
 
182
- if (action == 'updateCollection') {
183
+ if (method == 'update') {
183
184
  dataTransferedOut += getBytes(result)
184
185
  arrayObj.rename(value, function (error, result) {
185
186
  if (error)
@@ -201,7 +202,7 @@ function array(action, data) {
201
202
  })
202
203
  }
203
204
 
204
- if (action == 'deleteCollection') {
205
+ if (method == 'delete') {
205
206
  arrayObj.drop(function (error, result) {
206
207
  if (error)
207
208
  errorHandler(data, error, database, array)
@@ -231,7 +232,7 @@ function array(action, data) {
231
232
 
232
233
  } catch (error) {
233
234
  errorHandler(data, error)
234
- console.log(action, 'error', error);
235
+ console.log(method, 'error', error);
235
236
  resolve(data);
236
237
  }
237
238
  }, (error) => {
@@ -239,10 +240,11 @@ function array(action, data) {
239
240
  });
240
241
  }
241
242
 
242
- function object(action, data) {
243
+ function object(method, data) {
243
244
  return new Promise(async (resolve, reject) => {
244
245
  try {
245
246
  const client = await dbClient(data)
247
+
246
248
  if (!client || client.status === false)
247
249
  return data
248
250
 
@@ -251,13 +253,8 @@ function object(action, data) {
251
253
  let type = 'object'
252
254
  let documents = [];
253
255
 
254
- if (data.request)
255
- data[type] = data.request
256
-
257
256
  if (!data['timeStamp'])
258
- data['timeStamp'] = new Date()
259
- else
260
- data['timeStamp'] = new Date(data['timeStamp'])
257
+ data['timeStamp'] = new Date().toISOString();
261
258
 
262
259
  let databases = data.database;
263
260
  if (!Array.isArray(databases))
@@ -281,22 +278,29 @@ function object(action, data) {
281
278
  let isFilter
282
279
  if (data.$filter)
283
280
  isFilter = true
284
- if (isFilter && !data[type].length)
285
- data[type] = [{}]
281
+ if ((isFilter && !data[type].length) || data.isFilter)
282
+ data[type].splice(0, 0, { isFilter: 'isEmptyObjectFilter' });
286
283
 
287
284
  let filter = await createFilter(data, arrayObj);
288
285
 
289
286
  let projections = {}, projection = {}, update = {}, options = {}
290
287
 
291
- if (action === 'updateObject')
288
+ if (method === 'update')
292
289
  createUpdate(update, options, data, true)
293
290
 
294
291
  for (let i = 0; i < data[type].length; i++) {
292
+ let $storage = data[type][i].$storage || []
293
+ let $database = data[type][i].$database || []
294
+ let $array = data[type][i].$array || []
295
+ $storage.push(data.storageName)
296
+ $database.push(database)
297
+ $array.push(array)
298
+
295
299
  delete data[type][i].$storage
296
300
  delete data[type][i].$database
297
301
  delete data[type][i].$array
298
302
 
299
- if (action !== 'createObject' && data[type][i].$filter) {
303
+ if (method !== 'create' && data[type][i].$filter) {
300
304
  isFilter = true
301
305
  reference['$filter'] = data[type][i].$filter
302
306
  filter = await createFilter({ $filter: data[type][i].$filter }, arrayObj)
@@ -304,25 +308,29 @@ function object(action, data) {
304
308
 
305
309
  let { query, sort, index, limit } = filter
306
310
 
307
- if (action === 'createObject') {
311
+ if (method === 'create') {
308
312
  data[type][i] = replaceArray(data[type][i])
309
313
  data[type][i] = dotNotationToObject(data[type][i])
310
314
  data[type][i]['organization_id'] = data['organization_id'];
311
- data[type][i]['created'] = { on: data.timeStamp, by: data.user_id || data.clientId }
312
- } else if (action === 'readObject') {
315
+ data[type][i]['created'] = { on: new Date(data.timeStamp), by: data.user_id || data.clientId }
316
+ } else if (method === 'read') {
313
317
  projection = createProjection(data[type][i])
314
- } else if (action === 'updateObject') {
315
- data[type][i].modified = { on: data.timeStamp, by: data.user_id || data.clientId }
318
+ } else if (method === 'update') {
319
+ if (!data[type][i].modified)
320
+ data[type][i].modified = { on: new Date(data.timeStamp), by: data.user_id || data.clientId }
321
+ else
322
+ data[type][i].modified.on = new Date(data[type][i].modified.on)
323
+
316
324
  data[type][i].organization_id = data.organization_id
317
325
  createUpdate(update, options, data[type][i])
318
326
  }
319
327
 
320
- if (data[type][i]._id || action === 'createObject') {
321
- if (action !== 'createObject') {
328
+ if (data[type][i]._id || method === 'create') {
329
+ if (method !== 'create') {
322
330
  try {
323
331
  query._id = new ObjectId(data[type][i]._id);
324
332
  } catch (error) {
325
- if (action === 'updateObject' && options.upsert) {
333
+ if (method === 'update' && options.upsert) {
326
334
  data[type][i]._id = ObjectId()
327
335
  query._id = data[type][i]._id;
328
336
  } else {
@@ -337,7 +345,7 @@ function object(action, data) {
337
345
  dataTransferedOut += getBytes({ query, update, projection, options })
338
346
 
339
347
  let result
340
- if (action === 'createObject') {
348
+ if (method === 'create') {
341
349
  if (data[type][i]._id) {
342
350
  try {
343
351
  data[type][i]._id = new ObjectId(data[type][i]._id);
@@ -348,21 +356,38 @@ function object(action, data) {
348
356
  result = await arrayObj.insertOne(data[type][i]);
349
357
  // TODO: type error occuring when pushing the item pushes but throws an error
350
358
  data[type][i]._id = result.insertedId.toString()
351
- documents.push({ ...data[type][i], ...reference })
352
- } else if (action === 'readObject') {
359
+ // documents.push({ ...data[type][i], ...reference })
360
+ } else if (method === 'read') {
353
361
  result = await arrayObj.findOne(query, projection);
354
362
  result._id = result._id.toString()
355
- documents.push({ ...result, ...reference })
356
- } else if (action === 'updateObject') {
363
+
364
+ if (data[type][i].$storage && data[type][i].modified && data[type][i].modified.on) {
365
+ if (!result) {
366
+ result = await arrayObj.insertOne(data[type][i]);
367
+ data[type][i]._id = result.insertedId.toString()
368
+ } else if (result && new Date(data[type][i].modified.on) > new Date(result.modified.on)) {
369
+ data[type][i] = { ...result, ...data[type][i] }
370
+ createUpdate(update, options, data[type][i])
371
+ result = await arrayObj.updateOne(query, update, options);
372
+ } else
373
+ data[type][i] = { ...data[type][i], ...result }
374
+ } else
375
+ data[type][i] = { ...data[type][i], ...result }
376
+ } else if (method === 'update') {
357
377
  result = await arrayObj.updateOne(query, update, options);
358
378
 
359
379
  // TODO: handle upsert false and id does not exist
360
380
  data[type][i]._id = query._id.toString()
361
- documents.push({ ...data[type][i], ...reference })
362
- } else if (action === 'deleteObject') {
381
+ // documents.push({ ...data[type][i], ...reference })
382
+ } else if (method === 'delete') {
363
383
  result = await arrayObj.deleteOne(query);
364
- documents.push({ ...reference, _id: data[type][i]._id })
384
+ // documents.push({ ...reference, _id: data[type][i]._id })
365
385
  }
386
+
387
+ data[type][i].$storage = $storage
388
+ data[type][i].$database = $database
389
+ data[type][i].$array = $array
390
+
366
391
  dataTransferedIn += getBytes(result)
367
392
 
368
393
  } catch (error) {
@@ -370,16 +395,14 @@ function object(action, data) {
370
395
  }
371
396
  } else if (isFilter) {
372
397
  try {
373
- if (action === 'readObject')
398
+ if (method === 'read')
374
399
  projection = { ...projections, ...projection }
375
400
 
376
- delete query._id
377
-
378
401
  dataTransferedOut += getBytes({ query, projection, sort, index, limit })
379
- let document = ''
380
402
 
403
+ let document = ''
381
404
  const cursor = arrayObj.find(query, projection).sort(sort).skip(index).limit(limit);
382
- if (!(await cursor.hasNext()) && action === 'updateObject' && data.upsert)
405
+ if (!(await cursor.hasNext()) && method === 'update' && data.upsert)
383
406
  document = { _id: ObjectId(data[type][i]._id) }
384
407
 
385
408
  while (await cursor.hasNext() || document) {
@@ -394,13 +417,28 @@ function object(action, data) {
394
417
  continue;
395
418
  }
396
419
 
397
- if (action === 'readObject') {
398
- documents.push({ ...document, ...reference, _id: document._id.toString() })
420
+ if (method === 'read') {
421
+ document._id = document._id.toString()
422
+ let object = data[type].find(obj => obj._id && obj._id.toString() === document._id.toString())
423
+ if (object) {
424
+ if (object.$storage && object.modified && object.modified.on) {
425
+ if (document && new Date(object.modified.on) > new Date(document.modified.on)) {
426
+ object = { ...document, ...object }
427
+ createUpdate(update, options, object)
428
+ document = await arrayObj.updateOne(query, update, options);
429
+ dataTransferedIn += getBytes(document)
430
+ } else
431
+ documents.push({ ...document, ...reference })
432
+ } else
433
+ documents.push({ ...document, ...reference })
434
+
435
+ } else
436
+ documents.push({ ...document, ...reference })
399
437
  } else {
400
438
  dataTransferedOut += getBytes({ _id: document._id, update, options })
401
439
 
402
440
  let result
403
- if (action === 'updateObject') {
441
+ if (method === 'update') {
404
442
  if (options.returnNewDocument) {
405
443
  let object = await arrayObj.findOneAndUpdate({ _id: document._id }, update, options);
406
444
  for (let key of Object.keys(object)) {
@@ -415,13 +453,13 @@ function object(action, data) {
415
453
  } else
416
454
  result = await arrayObj.updateOne({ _id: document._id }, update, options);
417
455
  // TODO: if update.$push or update.$each read document with projection to get index and update the keys [] to include index
418
- } else if (action === 'deleteObject') {
456
+ } else if (method === 'delete') {
419
457
  result = await arrayObj.deleteOne({ _id: document._id });
420
458
  }
421
459
 
422
460
  dataTransferedIn += getBytes(result)
423
461
  documents.push({ ...data[type][i], ...reference, _id: document._id.toString() })
424
- data[type].push({ ...data[type][i], ...reference, _id: document._id.toString() })
462
+ // data[type].push({ ...data[type][i], ...reference, _id: document._id.toString() })
425
463
 
426
464
  }
427
465
  document = ''
@@ -433,7 +471,7 @@ function object(action, data) {
433
471
  }
434
472
  }
435
473
 
436
- // if (action === 'createObject') {
474
+ // if (method === 'create') {
437
475
  // try {
438
476
  // dataTransferedOut += getBytes(data[type])
439
477
  // const result = await arrayObj.insertMany(data[type]);
@@ -449,13 +487,12 @@ function object(action, data) {
449
487
 
450
488
  }
451
489
  }
452
-
453
490
  data = createData(data, documents, type, dataTransferedIn, dataTransferedOut)
454
491
  resolve(data)
455
492
 
456
493
  } catch (error) {
457
494
  errorHandler(data, error)
458
- console.log(action, 'error', error);
495
+ console.log(method, 'error', error);
459
496
  resolve(data);
460
497
  }
461
498
  }, (error) => {
@@ -473,7 +510,9 @@ function createUpdate(update, options, data, isGlobal) {
473
510
  Object.keys(data).forEach(key => {
474
511
  if (isGlobal && !key.startsWith('$') || key === '_id')
475
512
  return
476
- data[key] = isValidDate(data[key])
513
+
514
+ if (isValidDate(data[key]))
515
+ data[key] = new Date(data[key])
477
516
 
478
517
  let operator
479
518
  if (key.endsWith(']')) {
@@ -622,7 +661,8 @@ function createQuery(queries) {
622
661
  continue
623
662
  }
624
663
 
625
- item.value = isValidDate(item.value)
664
+ if (isValidDate(item.value))
665
+ item.value = new Date(item.value)
626
666
 
627
667
  let key = item.key;
628
668
  if (!query[key]) {
@@ -732,15 +772,31 @@ function createData(data, array, type, dataTransferedIn, dataTransferedOut) {
732
772
  });
733
773
  }
734
774
 
735
- if (!data.request)
736
- data.request = data[type] || {}
737
-
738
- data[type] = array
775
+ if (data[type] && data[type][0] && data[type][0].isFilter === 'isEmptyObjectFilter') {
776
+ data[type].shift()
777
+ data.isFilter = true
778
+ }
739
779
 
740
- if (data.returnLog) {
741
- if (!data.log)
742
- data.log = []
743
- data.log.push(...data[type])
780
+ // if (!data.request)
781
+ // data.request = data[type] || {}
782
+
783
+ let key = '_id'
784
+ if (type !== 'object')
785
+ key = 'name'
786
+ for (let i = 0; i < array.length; i++) {
787
+ const matchIndex = data[type].findIndex((item) => item[key] === array[i][key]);
788
+ if (matchIndex !== -1) {
789
+ data[type][matchIndex].$storage.push(array[i].$storage)
790
+ delete array[i].$storage
791
+ data[type][matchIndex].$database.push(array[i].$database)
792
+ delete array[i].$database
793
+ data[type][matchIndex].$array.push(array[i].$array)
794
+ delete array[i].$array
795
+
796
+ // TODO: compare dates and merge and and updates to keep all synced and up to date
797
+ data[type][matchIndex] = { ...data[type][matchIndex], ...array[i] };
798
+ } else
799
+ data[type].push(array[i])
744
800
  }
745
801
 
746
802
  return data