alchemymvc 1.3.15 → 1.3.17

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.
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @author Jelle De Loecker <jelle@develry.be>
8
8
  * @since 0.1.0
9
- * @version 0.3.0
9
+ * @version 1.3.16
10
10
  */
11
11
  var Sluggable = Function.inherits('Alchemy.Behaviour', function SluggableBehaviour(model, options) {
12
12
 
@@ -19,6 +19,10 @@ var Sluggable = Function.inherits('Alchemy.Behaviour', function SluggableBehavio
19
19
  this.target_field = options.target_field;
20
20
  this.replacement = options.replacement;
21
21
 
22
+ if (!this.source_field) {
23
+ throw new Error('No source field found for sluggable behaviour in "' + this.model.model_name + '"');
24
+ }
25
+
22
26
  if (!options.unique_modifier_fields) {
23
27
  options.unique_modifier_fields = [];
24
28
  } else if (!Array.isArray(options.unique_modifier_fields)) {
@@ -132,6 +132,19 @@ SocketConduit.setProperty(function ip() {
132
132
  return handshake.address || null;
133
133
  });
134
134
 
135
+ /**
136
+ * Is this client still connected?
137
+ *
138
+ * @author Jelle De Loecker <jelle@elevenways.be>
139
+ * @since 1.3.16
140
+ * @version 1.3.16
141
+ *
142
+ * @type {Boolean}
143
+ */
144
+ SocketConduit.setProperty(function is_connected() {
145
+ return this.socket?.connected || false;
146
+ });
147
+
135
148
  /**
136
149
  * Parse the request, get information from the url
137
150
  *
@@ -5,9 +5,9 @@ var MongoClient = alchemy.use('mongodb').MongoClient;
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@develry.be>
7
7
  * @since 0.2.0
8
- * @version 1.1.0
8
+ * @version 1.3.16
9
9
  */
10
- var Mongo = Function.inherits('Alchemy.Datasource.Nosql', function Mongo(name, _options) {
10
+ const Mongo = Function.inherits('Alchemy.Datasource.Nosql', function Mongo(name, _options) {
11
11
 
12
12
  var options,
13
13
  uri;
@@ -50,12 +50,6 @@ var Mongo = Function.inherits('Alchemy.Datasource.Nosql', function Mongo(name, _
50
50
 
51
51
  // Set the connection options
52
52
  this.mongoOptions = {
53
-
54
- // Use the new url parser, because otherwise it logs a warning
55
- useNewUrlParser : true,
56
-
57
- // Enable the new unified topology layer
58
- useUnifiedTopology : true,
59
53
  };
60
54
 
61
55
  // Cache collections in here
@@ -144,7 +138,7 @@ Mongo.setMethod(function normalizeFindOptions(options) {
144
138
  *
145
139
  * @author Jelle De Loecker <jelle@develry.be>
146
140
  * @since 0.2.0
147
- * @version 1.1.0
141
+ * @version 1.3.16
148
142
  */
149
143
  Mongo.decorateMethod(Blast.Decorators.memoize({ignore_arguments: true}), function connect() {
150
144
 
@@ -160,7 +154,7 @@ Mongo.decorateMethod(Blast.Decorators.memoize({ignore_arguments: true}), functio
160
154
  pledge = new Pledge();
161
155
 
162
156
  // Create the connection to the database
163
- MongoClient.connect(that.uri, that.mongoOptions, function connected(err, client) {
157
+ Pledge.done(MongoClient.connect(that.uri, that.mongoOptions), function connected(err, client) {
164
158
 
165
159
  if (err) {
166
160
  that.connection_error = err;
@@ -186,41 +180,47 @@ Mongo.decorateMethod(Blast.Decorators.memoize({ignore_arguments: true}), functio
186
180
  *
187
181
  * @author Jelle De Loecker <jelle@develry.be>
188
182
  * @since 0.2.0
189
- * @version 0.2.0
183
+ * @version 1.3.16
190
184
  *
185
+ * @param {String} name
191
186
  * @param {Function} callback
187
+ *
188
+ * @return {Pledge<Collection>}
192
189
  */
193
190
  Mongo.setMethod(function collection(name, callback) {
194
191
 
195
- var that = this;
192
+ const pledge = new Pledge();
196
193
 
197
- if (this.collections[name]) {
198
- setImmediate(function cachedCollection() {
199
- callback(null, that.collections[name]);
200
- });
194
+ pledge.done(callback);
201
195
 
202
- return;
196
+ if (this.collections[name]) {
197
+ pledge.resolve(this.collections[name]);
198
+ return pledge;
203
199
  }
204
200
 
201
+ const that = this;
202
+
205
203
  this.connect().done(function gotConnection(err, db) {
206
204
 
207
205
  if (err) {
208
- return callback(err);
206
+ return pledge.reject(err);
209
207
  }
210
208
 
211
- that.connection.collection(name, function createdCollection(err, collection) {
209
+ Pledge.done(that.connection.collection(name), function createdCollection(err, collection) {
212
210
 
213
211
  if (err) {
214
- return callback(err);
212
+ return pledge.reject(err);
215
213
  }
216
214
 
217
215
  // Cache the collection
218
216
  that.collections[name] = collection;
219
217
 
220
218
  // Return it to the callback
221
- callback(null, collection);
219
+ pledge.resolve(collection);
222
220
  });
223
221
  });
222
+
223
+ return pledge;
224
224
  });
225
225
 
226
226
  /**
@@ -228,7 +228,7 @@ Mongo.setMethod(function collection(name, callback) {
228
228
  *
229
229
  * @author Jelle De Loecker <jelle@develry.be>
230
230
  * @since 0.2.0
231
- * @version 1.2.0
231
+ * @version 1.3.16
232
232
  */
233
233
  Mongo.setMethod(function _read(model, criteria, callback) {
234
234
 
@@ -268,11 +268,6 @@ Mongo.setMethod(function _read(model, criteria, callback) {
268
268
 
269
269
  let aggregate_options = {};
270
270
 
271
- // Limits can still be set as an option though
272
- if (options.limit) {
273
- aggregate_options.limit = options.limit;
274
- }
275
-
276
271
  Function.parallel({
277
272
  available: function getAvailable(next) {
278
273
 
@@ -286,13 +281,13 @@ Mongo.setMethod(function _read(model, criteria, callback) {
286
281
  pipeline.push({$count: 'available'});
287
282
 
288
283
  // Expensive aggregate just to get the available count...
289
- collection.aggregate(pipeline, cloned_options, function gotAggregate(err, cursor) {
284
+ Pledge.done(collection.aggregate(pipeline, cloned_options), function gotAggregate(err, cursor) {
290
285
 
291
286
  if (err) {
292
287
  return next(err);
293
288
  }
294
289
 
295
- cursor.toArray(function gotAvailableArray(err, items) {
290
+ Pledge.done(cursor.toArray(), function gotAvailableArray(err, items) {
296
291
 
297
292
  if (err) {
298
293
  return next(err);
@@ -313,13 +308,22 @@ Mongo.setMethod(function _read(model, criteria, callback) {
313
308
  });
314
309
  },
315
310
  items: function getItems(next) {
316
- collection.aggregate(compiled.pipeline, aggregate_options, function gotAggregate(err, cursor) {
311
+
312
+ let pipeline = JSON.clone(compiled.pipeline);
313
+
314
+ // Limits also have to be set in the pipeline now
315
+ // (We have to do it here, so the `available` count is correct)
316
+ if (options.limit) {
317
+ pipeline.push({$limit: options.limit});
318
+ }
319
+
320
+ Pledge.done(collection.aggregate(pipeline, aggregate_options), function gotAggregate(err, cursor) {
317
321
 
318
322
  if (err) {
319
323
  return next(err);
320
324
  }
321
325
 
322
- cursor.toArray(next);
326
+ Pledge.done(cursor.toArray(), next);
323
327
  });
324
328
  }
325
329
  }, function done(err, data) {
@@ -346,10 +350,10 @@ Mongo.setMethod(function _read(model, criteria, callback) {
346
350
  return next(null, null);
347
351
  }
348
352
 
349
- cursor.count(false, next);
353
+ Pledge.done(collection.countDocuments(compiled), next);
350
354
  },
351
355
  items: function getItems(next) {
352
- cursor.toArray(next);
356
+ Pledge.done(cursor.toArray(), next);
353
357
  }
354
358
  }, function done(err, data) {
355
359
 
@@ -369,7 +373,7 @@ Mongo.setMethod(function _read(model, criteria, callback) {
369
373
  *
370
374
  * @author Jelle De Loecker <jelle@develry.be>
371
375
  * @since 0.2.0
372
- * @version 1.3.6
376
+ * @version 1.3.16
373
377
  */
374
378
  Mongo.setMethod(function _create(model, data, options, callback) {
375
379
 
@@ -379,13 +383,7 @@ Mongo.setMethod(function _create(model, data, options, callback) {
379
383
  return callback(err);
380
384
  }
381
385
 
382
- let method = 'insert';
383
-
384
- if (typeof collection.insertOne == 'function') {
385
- method = 'insertOne';
386
- }
387
-
388
- collection[method](data, {w: 1, fullResult: true}, function afterInsert(err, result) {
386
+ Pledge.done(collection.insertOne(data, {w: 1, fullResult: true}), function afterInsert(err, result) {
389
387
 
390
388
  // Clear the cache
391
389
  model.nukeCache();
@@ -394,6 +392,7 @@ Mongo.setMethod(function _create(model, data, options, callback) {
394
392
  return callback(err, result);
395
393
  }
396
394
 
395
+ // @TODO: fix because of mongodb 6
397
396
  let write_errors = result.message?.documents?.[0]?.writeErrors;
398
397
 
399
398
  if (write_errors) {
@@ -424,7 +423,7 @@ Mongo.setMethod(function _create(model, data, options, callback) {
424
423
  *
425
424
  * @author Jelle De Loecker <jelle@develry.be>
426
425
  * @since 0.2.0
427
- * @version 1.1.0
426
+ * @version 1.3.16
428
427
  */
429
428
  Mongo.setMethod(function _update(model, data, options, callback) {
430
429
 
@@ -507,16 +506,18 @@ Mongo.setMethod(function _update(model, data, options, callback) {
507
506
  console.log('Updating with obj', id, updateObject);
508
507
  }
509
508
 
509
+ let promise;
510
+
510
511
  if (collection.findOneAndUpdate) {
511
- collection.findOneAndUpdate({_id: id}, updateObject, {upsert: true}, afterUpdate);
512
+ promise = collection.findOneAndUpdate({_id: id}, updateObject, {upsert: true});
512
513
  } else if (collection.findAndModify) {
513
- collection.findAndModify({_id: id}, [['_id', 1]], updateObject, {upsert: true}, afterUpdate);
514
+ promise = collection.findAndModify({_id: id}, [['_id', 1]], updateObject, {upsert: true});
514
515
  } else {
515
516
  // If it's not available (like nedb)
516
- collection.update({_id: ''+id}, updateObject, {upsert: true}, afterUpdate);
517
+ promise = collection.update({_id: ''+id}, updateObject, {upsert: true});
517
518
  }
518
519
 
519
- function afterUpdate(err, result) {
520
+ Pledge.done(promise, function afterUpdate(err, result) {
520
521
 
521
522
  // Clear the cache
522
523
  model.nukeCache();
@@ -526,7 +527,7 @@ Mongo.setMethod(function _update(model, data, options, callback) {
526
527
  }
527
528
 
528
529
  callback(null, Object.assign({}, data));
529
- }
530
+ });
530
531
  });
531
532
  });
532
533
 
@@ -536,7 +537,7 @@ Mongo.setMethod(function _update(model, data, options, callback) {
536
537
  * @author Kjell Keisse <kjell@codedor.be>
537
538
  * @author Jelle De Loecker <jelle@develry.be>
538
539
  * @since 0.2.0
539
- * @version 1.0.3
540
+ * @version 1.3.16
540
541
  */
541
542
  Mongo.setMethod(function _remove(model, query, options, callback) {
542
543
 
@@ -546,7 +547,7 @@ Mongo.setMethod(function _remove(model, query, options, callback) {
546
547
  return callback(err);
547
548
  }
548
549
 
549
- collection.findOneAndDelete(query, function _deleted(err, result){
550
+ Pledge.done(collection.findOneAndDelete(query), function _deleted(err, result){
550
551
 
551
552
  //clear cache
552
553
  model.nukeCache();
@@ -565,43 +566,59 @@ Mongo.setMethod(function _remove(model, query, options, callback) {
565
566
  *
566
567
  * @author Jelle De Loecker <jelle@develry.be>
567
568
  * @since 0.2.0
568
- * @version 1.1.0
569
+ * @version 1.3.17
569
570
  */
570
571
  Mongo.setMethod(function _ensureIndex(model, index, callback) {
571
572
 
572
- this.collection(model.table, function gotCollection(err, collection) {
573
-
574
- var options,
575
- obj,
576
- key;
573
+ this.collection(model.table, async function gotCollection(err, collection) {
577
574
 
578
575
  if (err != null) {
579
576
  return callback(err);
580
577
  }
581
578
 
582
- options = {
583
- name: index.options.name
579
+ let options = {
580
+ name : index.options.name,
581
+ unique : index.options.unique ? true : false,
582
+ sparse : index.options.sparse ? true : false,
584
583
  };
585
584
 
586
- if (index.options.unique) {
587
- options.unique = true;
588
- }
589
-
590
- if (index.options.sparse) {
591
- options.sparse = true;
592
- }
585
+ let index_specs;
593
586
 
594
587
  // Hack in the text indexes
595
588
  if (options.name == 'text') {
596
- obj = {};
589
+ let key;
590
+
591
+ index_specs = {};
597
592
 
598
593
  for (key in index.fields) {
599
- obj[key] = 'text';
594
+ index_specs[key] = 'text';
600
595
  }
601
-
602
- collection.createIndex(obj, options, callback);
603
596
  } else {
604
- collection.createIndex(index.fields, options, callback);
597
+ index_specs = index.fields;
605
598
  }
599
+
600
+ try {
601
+ await collection.createIndex(index_specs, options);
602
+ } catch (err) {
603
+
604
+ // Check for IndexOptionsConflict
605
+ if (err.code === 85) {
606
+
607
+ try {
608
+
609
+ // Index already exists, drop it
610
+ await collection.dropIndex(options.name);
611
+
612
+ // Try again
613
+ await collection.createIndex(index_specs, options);
614
+ } catch (second_err) {
615
+ return callback(second_err);
616
+ }
617
+ } else {
618
+ return callback(err);
619
+ }
620
+ }
621
+
622
+ callback();
606
623
  });
607
624
  });
@@ -1,3 +1,5 @@
1
+ const TIMEOUT_ID = Symbol('timeout_id');
2
+
1
3
  /**
2
4
  * The custom al-time-ago element
3
5
  *
@@ -27,8 +29,6 @@ TimeAgo.setAttribute(function date(str) {
27
29
  return this._date;
28
30
  }, function setValue(value) {
29
31
 
30
- var date;
31
-
32
32
  if (value) {
33
33
  this._date = Date.create(value);
34
34
  } else {
@@ -73,57 +73,40 @@ TimeAgo.setProperty(function value() {
73
73
  * @version 0.1.0
74
74
  */
75
75
  TimeAgo.setMethod(function connected() {
76
- this.refresh(true);
76
+ this.refresh();
77
77
  });
78
78
 
79
79
  /**
80
80
  * Refresh the content
81
81
  *
82
- * @author Jelle De Loecker <jelle@develry.be>
82
+ * @author Jelle De Loecker <jelle@elevenways.be>
83
83
  * @since 0.1.0
84
- * @version 0.1.7
85
- *
86
- * @param {Boolean} reset_timer
84
+ * @version 1.3.17
87
85
  */
88
- TimeAgo.setMethod(function refresh(reset_timer) {
86
+ TimeAgo.setMethod(function refresh() {
89
87
 
90
- let that = this,
91
- counter,
92
- timer,
93
- text = this.value,
94
- diff;
88
+ let text = this.value;
95
89
 
96
90
  if (this.textContent != text) {
97
91
  this.textContent = text;
98
92
  }
99
93
 
100
- if (!reset_timer || Blast.isNode) {
94
+ if (Blast.isNode || !this.isConnected || !this.date) {
101
95
  return;
102
96
  }
103
97
 
104
- if (this._timer) {
105
- clearInterval(this._timer);
106
- this._timer = null;
98
+ let diff = Math.abs(Date.now() - this.date),
99
+ timer;
100
+
101
+ if (diff < 1000 * 70) {
102
+ timer = 1000;
103
+ } else {
104
+ timer = 1000 * 29;
107
105
  }
108
106
 
109
- if (this.date) {
110
- diff = Math.abs(Date.now() - this.date);
111
- counter = 0;
112
-
113
- if (diff < 1000 * 29) {
114
- timer = 1000;
115
- } else {
116
- timer = 1000 * 29;
117
- }
118
-
119
- this._timer = setInterval(function doUpdate() {
120
- counter++;
121
-
122
- if (counter > 60) {
123
- that.refresh(true);
124
- } else {
125
- that.refresh();
126
- }
127
- }, timer);
107
+ if (this[TIMEOUT_ID]) {
108
+ clearTimeout(this[TIMEOUT_ID]);
128
109
  }
110
+
111
+ this[TIMEOUT_ID] = setTimeout(() => this.refresh(), timer);
129
112
  });
@@ -292,7 +292,7 @@ Alchemy.setMethod(function group(name, id, callback) {
292
292
  *
293
293
  * @author Jelle De Loecker <jelle@elevenways.be>
294
294
  * @since 0.5.0
295
- * @version 1.3.7
295
+ * @version 1.3.17
296
296
  *
297
297
  * @param {String|Object} options
298
298
  * @param {Object} data
@@ -325,7 +325,7 @@ Alchemy.setMethod(function segment(options, data) {
325
325
  conduit = that.view.server_var('conduit');
326
326
 
327
327
  if (!conduit) {
328
- return next();
328
+ return next(null, '<!-- Failed to render segment ' + options.name + ': no conduit found -->');
329
329
  }
330
330
 
331
331
  options.params = data;