alchemymvc 1.2.8 → 1.3.1
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/lib/app/behaviour/sluggable_behaviour.js +4 -2
- package/lib/app/conduit/http_conduit.js +7 -2
- package/lib/app/conduit/loopback_conduit.js +2 -2
- package/lib/app/conduit/socket_conduit.js +20 -5
- package/lib/app/controller/alchemy_info_controller.js +4 -8
- package/lib/app/helper/backed_map.js +2 -2
- package/lib/app/helper/router_helper.js +98 -24
- package/lib/app/helper_controller/controller.js +45 -30
- package/lib/app/helper_datasource/00-nosql_datasource.js +44 -10
- package/lib/app/helper_field/enum_field.js +4 -4
- package/lib/app/helper_field/schema_field.js +50 -36
- package/lib/app/helper_model/document.js +81 -46
- package/lib/app/helper_model/field_set.js +11 -0
- package/lib/app/helper_model/model.js +107 -53
- package/lib/app/helper_validator/00_validator.js +38 -6
- package/lib/app/helper_validator/not_empty_validator.js +1 -3
- package/lib/app/routes.js +7 -1
- package/lib/bootstrap.js +1 -0
- package/lib/class/conduit.js +438 -290
- package/lib/class/controller.js +18 -15
- package/lib/class/datasource.js +19 -8
- package/lib/class/document.js +3 -3
- package/lib/class/field.js +34 -3
- package/lib/class/inode.js +27 -0
- package/lib/class/inode_file.js +204 -4
- package/lib/class/migration.js +2 -1
- package/lib/class/model.js +16 -5
- package/lib/class/path_definition.js +76 -120
- package/lib/class/path_param_definition.js +202 -0
- package/lib/class/postponement.js +573 -0
- package/lib/class/route.js +193 -33
- package/lib/class/router.js +22 -4
- package/lib/class/schema.js +47 -11
- package/lib/class/schema_client.js +65 -35
- package/lib/class/session.js +138 -12
- package/lib/class/sitemap.js +341 -0
- package/lib/core/base.js +13 -3
- package/lib/core/client_alchemy.js +78 -7
- package/lib/core/client_base.js +16 -10
- package/lib/core/middleware.js +56 -45
- package/lib/init/alchemy.js +124 -11
- package/lib/init/constants.js +11 -0
- package/lib/init/functions.js +163 -86
- package/lib/stages.js +18 -3
- package/package.json +6 -6
|
@@ -79,6 +79,12 @@ Schema.setStatic(function unDry(value, custom_method, whenDone) {
|
|
|
79
79
|
Schema.setDeprecatedProperty('modelName', 'model_name');
|
|
80
80
|
Schema.setDeprecatedProperty('modelClass', 'model_class');
|
|
81
81
|
Schema.setDeprecatedProperty('modelInstance', 'model_instance');
|
|
82
|
+
Schema.setDeprecatedProperty('hasTranslations', 'has_translations');
|
|
83
|
+
Schema.setDeprecatedProperty('hasAlternates', 'has_alternates');
|
|
84
|
+
Schema.setDeprecatedProperty('translatableFields', 'translatable_fields');
|
|
85
|
+
Schema.setDeprecatedProperty('indexFields', 'index_fields');
|
|
86
|
+
Schema.setDeprecatedProperty('enumValues', 'enum_values');
|
|
87
|
+
Schema.setDeprecatedProperty('hasBehaviours', 'has_behaviours');
|
|
82
88
|
|
|
83
89
|
/**
|
|
84
90
|
* Set a reference to itself
|
|
@@ -128,17 +134,34 @@ Schema.setProperty(function field_count() {
|
|
|
128
134
|
return result;
|
|
129
135
|
});
|
|
130
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Does this schema have translatable fields?
|
|
139
|
+
*
|
|
140
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
141
|
+
* @since 1.3.0
|
|
142
|
+
* @version 1.3.0
|
|
143
|
+
*
|
|
144
|
+
* @type {Boolean}
|
|
145
|
+
*/
|
|
146
|
+
Schema.setProperty(function has_translatable_fields() {
|
|
147
|
+
return this.has_translations;
|
|
148
|
+
});
|
|
149
|
+
|
|
131
150
|
/**
|
|
132
151
|
* Clone for JSON-Dry (JSON.clone())
|
|
133
152
|
*
|
|
134
153
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
135
154
|
* @since 1.1.3
|
|
136
|
-
* @version 1.1
|
|
155
|
+
* @version 1.3.1
|
|
137
156
|
*
|
|
138
157
|
* @return {Object}
|
|
139
158
|
*/
|
|
140
|
-
Schema.setMethod(function dryClone() {
|
|
141
|
-
|
|
159
|
+
Schema.setMethod(function dryClone(wm, custom_method) {
|
|
160
|
+
|
|
161
|
+
let obj = JSON.toDryObject(this),
|
|
162
|
+
cloned = JSON.undry(obj);
|
|
163
|
+
|
|
164
|
+
return cloned;
|
|
142
165
|
});
|
|
143
166
|
|
|
144
167
|
/**
|
|
@@ -147,16 +170,12 @@ Schema.setMethod(function dryClone() {
|
|
|
147
170
|
*
|
|
148
171
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
149
172
|
* @since 1.1.3
|
|
150
|
-
* @version 1.1
|
|
173
|
+
* @version 1.3.1
|
|
151
174
|
*
|
|
152
175
|
* @return {Object}
|
|
153
176
|
*/
|
|
154
177
|
Schema.setMethod(function clone() {
|
|
155
|
-
|
|
156
|
-
let obj = JSON.toDryObject(this),
|
|
157
|
-
cloned = JSON.undry(obj);
|
|
158
|
-
|
|
159
|
-
return cloned;
|
|
178
|
+
return this.dryClone();
|
|
160
179
|
});
|
|
161
180
|
|
|
162
181
|
/**
|
|
@@ -164,21 +183,31 @@ Schema.setMethod(function clone() {
|
|
|
164
183
|
*
|
|
165
184
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
166
185
|
* @since 1.1.0
|
|
167
|
-
* @version 1.1
|
|
186
|
+
* @version 1.3.1
|
|
168
187
|
*
|
|
169
188
|
* @return {Object}
|
|
170
189
|
*/
|
|
171
190
|
Schema.setMethod(function toDry() {
|
|
172
191
|
|
|
173
|
-
|
|
192
|
+
const value = {
|
|
174
193
|
name : this.name,
|
|
175
194
|
associations : this.associations,
|
|
176
195
|
fields : [],
|
|
177
|
-
rules :
|
|
196
|
+
rules : new Deck(),
|
|
178
197
|
};
|
|
179
198
|
|
|
180
|
-
|
|
181
|
-
|
|
199
|
+
let rule_dict = this.rules.getDict();
|
|
200
|
+
|
|
201
|
+
// Only add rules that are manually added to the schema,
|
|
202
|
+
// not ones defined by the field (else we would revive the rules double)
|
|
203
|
+
for (let key in rule_dict) {
|
|
204
|
+
let entry = rule_dict[key];
|
|
205
|
+
|
|
206
|
+
if (entry.options?.from_field) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
value.rules.set(key, entry);
|
|
182
211
|
}
|
|
183
212
|
|
|
184
213
|
if (this.model_name) {
|
|
@@ -191,24 +220,25 @@ Schema.setMethod(function toDry() {
|
|
|
191
220
|
|
|
192
221
|
value.options = this.options;
|
|
193
222
|
|
|
223
|
+
let result = {value};
|
|
224
|
+
|
|
194
225
|
// Get the sorted fields
|
|
195
|
-
let
|
|
196
|
-
fields = this.getSorted(false),
|
|
226
|
+
let fields = this.getSorted(false),
|
|
197
227
|
field,
|
|
198
228
|
i;
|
|
199
|
-
|
|
229
|
+
|
|
200
230
|
for (i = 0; i < fields.length; i++) {
|
|
201
231
|
field = fields[i];
|
|
202
232
|
|
|
203
233
|
value.fields.push({
|
|
204
234
|
name : field.name,
|
|
205
|
-
options : field.
|
|
235
|
+
options : field.getOptionsForDrying(),
|
|
206
236
|
class_name : field.constructor.name,
|
|
207
237
|
namespace : field.constructor.namespace,
|
|
208
238
|
});
|
|
209
239
|
}
|
|
210
240
|
|
|
211
|
-
return
|
|
241
|
+
return result;
|
|
212
242
|
});
|
|
213
243
|
|
|
214
244
|
/**
|
|
@@ -216,7 +246,7 @@ Schema.setMethod(function toDry() {
|
|
|
216
246
|
*
|
|
217
247
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
218
248
|
* @since 1.1.0
|
|
219
|
-
* @version 1.
|
|
249
|
+
* @version 1.3.0
|
|
220
250
|
*/
|
|
221
251
|
Schema.setMethod(function init() {
|
|
222
252
|
this.associations = {};
|
|
@@ -225,19 +255,19 @@ Schema.setMethod(function init() {
|
|
|
225
255
|
this.indexes = {};
|
|
226
256
|
|
|
227
257
|
// All fields belonging to an index group
|
|
228
|
-
this.
|
|
258
|
+
this.index_fields = {};
|
|
229
259
|
|
|
230
260
|
// All translatable fields
|
|
231
|
-
this.
|
|
261
|
+
this.translatable_fields = {};
|
|
232
262
|
|
|
233
263
|
// Amount of translatable fields
|
|
234
|
-
this.
|
|
264
|
+
this.has_translations = 0;
|
|
235
265
|
|
|
236
266
|
// Amount of alternate indexes
|
|
237
|
-
this.
|
|
267
|
+
this.has_alternates = 0;
|
|
238
268
|
|
|
239
269
|
// Enum values
|
|
240
|
-
this.
|
|
270
|
+
this.enum_values = {};
|
|
241
271
|
|
|
242
272
|
// Attached behaviours
|
|
243
273
|
this.behaviours = {};
|
|
@@ -249,7 +279,7 @@ Schema.setMethod(function init() {
|
|
|
249
279
|
this.rules = new Deck();
|
|
250
280
|
|
|
251
281
|
// Behaviour count
|
|
252
|
-
this.
|
|
282
|
+
this.has_behaviours = 0;
|
|
253
283
|
});
|
|
254
284
|
|
|
255
285
|
/**
|
|
@@ -448,9 +478,9 @@ Schema.setMethod(function getPrivateFields() {
|
|
|
448
478
|
/**
|
|
449
479
|
* Add a field to this schema
|
|
450
480
|
*
|
|
451
|
-
* @author Jelle De Loecker <jelle@
|
|
481
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
452
482
|
* @since 0.2.0
|
|
453
|
-
* @version 1.
|
|
483
|
+
* @version 1.3.0
|
|
454
484
|
*
|
|
455
485
|
* @param {String} name
|
|
456
486
|
* @param {String} type
|
|
@@ -510,8 +540,8 @@ Schema.setMethod(function addField(name, type, options) {
|
|
|
510
540
|
field = new FieldClass(this, name, options);
|
|
511
541
|
|
|
512
542
|
if (field.requires_translating) {
|
|
513
|
-
this.
|
|
514
|
-
this.
|
|
543
|
+
this.has_translations++;
|
|
544
|
+
this.translatable_fields[name] = field;
|
|
515
545
|
}
|
|
516
546
|
|
|
517
547
|
this.set(name, field);
|
|
@@ -521,12 +551,12 @@ Schema.setMethod(function addField(name, type, options) {
|
|
|
521
551
|
i;
|
|
522
552
|
|
|
523
553
|
for (i = 0; i < rules.length; i++) {
|
|
524
|
-
this.addRule(rules[i], [name]);
|
|
554
|
+
this.addRule(rules[i], {from_field: true, fields: [name]});
|
|
525
555
|
}
|
|
526
556
|
}
|
|
527
557
|
|
|
528
558
|
if (options.required) {
|
|
529
|
-
this.addRule('not_empty', [name]);
|
|
559
|
+
this.addRule('not_empty', {from_field: true, fields: [name]});
|
|
530
560
|
}
|
|
531
561
|
|
|
532
562
|
return field;
|
|
@@ -706,7 +736,7 @@ Schema.setMethod(function getFieldNames() {
|
|
|
706
736
|
*
|
|
707
737
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
708
738
|
* @since 0.2.0
|
|
709
|
-
* @version 1.
|
|
739
|
+
* @version 1.3.0
|
|
710
740
|
*
|
|
711
741
|
* @param {String|FieldType} _field
|
|
712
742
|
* @param {Object} options
|
|
@@ -772,7 +802,7 @@ Schema.setMethod(function addIndex(_field, _options) {
|
|
|
772
802
|
// it needs the 'alternate' property in order to be used
|
|
773
803
|
// as an alternate method of updating without _id
|
|
774
804
|
if (options.alternate) {
|
|
775
|
-
this.
|
|
805
|
+
this.has_alternates++;
|
|
776
806
|
}
|
|
777
807
|
|
|
778
808
|
that.getDatasource().done(function gotDs(err, datasource) {
|
|
@@ -799,7 +829,7 @@ Schema.setMethod(function addIndex(_field, _options) {
|
|
|
799
829
|
|
|
800
830
|
// Store the field order in the index groups
|
|
801
831
|
that.indexes[options.name].fields[path] = options.order;
|
|
802
|
-
that.
|
|
832
|
+
that.index_fields[path] = options;
|
|
803
833
|
|
|
804
834
|
datasource.ensureIndex(that.model_class, that.indexes[options.name], function ensuredIndex(err, result) {
|
|
805
835
|
|
package/lib/class/session.js
CHANGED
|
@@ -5,7 +5,7 @@ var data_listeners = alchemy.shared('data_binding_listeners');
|
|
|
5
5
|
*
|
|
6
6
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
7
7
|
* @since 0.2.0
|
|
8
|
-
* @version 1.1
|
|
8
|
+
* @version 1.3.1
|
|
9
9
|
*
|
|
10
10
|
* @param {Conduit} conduit The initializing conduit
|
|
11
11
|
*/
|
|
@@ -36,10 +36,19 @@ var Session = Function.inherits('Alchemy.Base', function ClientSession(conduit)
|
|
|
36
36
|
this.data_listener_ids = {};
|
|
37
37
|
|
|
38
38
|
// Postponed requests
|
|
39
|
-
this.
|
|
39
|
+
this.postponements = new Classes.Develry.Cache();
|
|
40
|
+
|
|
41
|
+
// Postponed requests are invalidated after 3 hours
|
|
42
|
+
this.postponements.max_age = 3 * 60 * 60 * 1000;
|
|
43
|
+
|
|
44
|
+
// Time spent in the queue
|
|
45
|
+
this.queued_time = 0;
|
|
40
46
|
|
|
41
|
-
//
|
|
42
|
-
this.
|
|
47
|
+
// Any postponements that have happened already
|
|
48
|
+
this.postponement_counter = 0;
|
|
49
|
+
|
|
50
|
+
// The amount of renders that have happened during this session
|
|
51
|
+
this.render_counter = 0;
|
|
43
52
|
|
|
44
53
|
// Increment the alchemy session count
|
|
45
54
|
alchemy.session_count++;
|
|
@@ -103,6 +112,56 @@ Session.setProperty(function idle_time() {
|
|
|
103
112
|
return result;
|
|
104
113
|
});
|
|
105
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Is this an active session?
|
|
117
|
+
* When no activity happens for 5 minutes, the session becomes inactive.
|
|
118
|
+
*
|
|
119
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
120
|
+
* @since 1.3.1
|
|
121
|
+
* @version 1.3.1
|
|
122
|
+
*
|
|
123
|
+
* @type {Boolean}
|
|
124
|
+
*/
|
|
125
|
+
Session.setProperty(function is_active() {
|
|
126
|
+
|
|
127
|
+
if (this.idle_time < 5 * 60 * 1000) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return false;
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Add the amount of time this client has been in the queue
|
|
136
|
+
*
|
|
137
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
138
|
+
* @since 1.3.1
|
|
139
|
+
* @version 1.3.1
|
|
140
|
+
*
|
|
141
|
+
* @return {Boolean}
|
|
142
|
+
*/
|
|
143
|
+
Session.setMethod(function addFinishedQueueDuration(ms) {
|
|
144
|
+
this.queued_time += ms;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Has this client already been in the queue?
|
|
149
|
+
*
|
|
150
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
151
|
+
* @since 1.3.1
|
|
152
|
+
* @version 1.3.1
|
|
153
|
+
*
|
|
154
|
+
* @return {Boolean}
|
|
155
|
+
*/
|
|
156
|
+
Session.setMethod(function hasAlreadyQueued() {
|
|
157
|
+
|
|
158
|
+
if (this.queued_time > 0) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return false;
|
|
163
|
+
});
|
|
164
|
+
|
|
106
165
|
/**
|
|
107
166
|
* Register a conduit
|
|
108
167
|
*
|
|
@@ -134,21 +193,84 @@ Session.setMethod(function createMenuItem(conduit) {
|
|
|
134
193
|
/**
|
|
135
194
|
* Postpone the result
|
|
136
195
|
*
|
|
137
|
-
* @author Jelle De Loecker <jelle@
|
|
196
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
138
197
|
* @since 0.2.0
|
|
139
|
-
* @version
|
|
198
|
+
* @version 1.3.1
|
|
140
199
|
*
|
|
141
200
|
* @param {Conduit} conduit The conduit to postpone
|
|
201
|
+
* @param {Object} options
|
|
142
202
|
*
|
|
143
|
-
* @return {
|
|
203
|
+
* @return {Alchemy.Conduit.Postponement} The postponement
|
|
204
|
+
*/
|
|
205
|
+
Session.setMethod(function postpone(conduit, options) {
|
|
206
|
+
|
|
207
|
+
let id = Crypto.uid();
|
|
208
|
+
|
|
209
|
+
let postponement = new Classes.Alchemy.Conduit.Postponement(conduit, id, options);
|
|
210
|
+
|
|
211
|
+
this.postponements.set(id, postponement);
|
|
212
|
+
|
|
213
|
+
this.postponement_counter++;
|
|
214
|
+
|
|
215
|
+
return postponement;
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Increment the render count
|
|
220
|
+
*
|
|
221
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
222
|
+
* @since 1.3.1
|
|
223
|
+
* @version 1.3.1
|
|
224
|
+
*
|
|
225
|
+
* @return {Number} The amount of renders
|
|
144
226
|
*/
|
|
145
|
-
Session.setMethod(function
|
|
227
|
+
Session.setMethod(function incrementRenderCount() {
|
|
228
|
+
return ++this.render_counter;
|
|
229
|
+
});
|
|
146
230
|
|
|
147
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Get a postponement by its id
|
|
233
|
+
*
|
|
234
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
235
|
+
* @since 1.3.1
|
|
236
|
+
* @version 1.3.1
|
|
237
|
+
*
|
|
238
|
+
* @param {String} id The postponement id
|
|
239
|
+
*
|
|
240
|
+
* @return {Alchemy.Conduit.Postponement} The postponement
|
|
241
|
+
*/
|
|
242
|
+
Session.setMethod(function getPostponement(id) {
|
|
243
|
+
return this.postponements.get(id);
|
|
244
|
+
});
|
|
148
245
|
|
|
149
|
-
|
|
246
|
+
/**
|
|
247
|
+
* See if a postponement already exists for the given conduit
|
|
248
|
+
*
|
|
249
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
250
|
+
* @since 1.3.1
|
|
251
|
+
* @version 1.3.1
|
|
252
|
+
*
|
|
253
|
+
* @param {Conduit} conduit
|
|
254
|
+
*
|
|
255
|
+
* @return {Alchemy.Conduit.Postponement} The postponement
|
|
256
|
+
*/
|
|
257
|
+
Session.setMethod(function getExistingPostponement(conduit) {
|
|
258
|
+
|
|
259
|
+
if (!this.postponement_counter) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (!this.postponements.length) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
150
266
|
|
|
151
|
-
|
|
267
|
+
let postponement;
|
|
268
|
+
|
|
269
|
+
for (postponement of this.postponements) {
|
|
270
|
+
if (postponement.original_path === conduit.path) {
|
|
271
|
+
return postponement;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
152
274
|
});
|
|
153
275
|
|
|
154
276
|
/**
|
|
@@ -156,7 +278,7 @@ Session.setMethod(function postpone(conduit) {
|
|
|
156
278
|
*
|
|
157
279
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
158
280
|
* @since 0.2.0
|
|
159
|
-
* @version 1.1
|
|
281
|
+
* @version 1.3.1
|
|
160
282
|
*
|
|
161
283
|
* @param {Boolean} expired True if removed because time ran out
|
|
162
284
|
*/
|
|
@@ -180,6 +302,10 @@ Session.setMethod(function removed(expired) {
|
|
|
180
302
|
this.menu_item.remove();
|
|
181
303
|
}
|
|
182
304
|
|
|
305
|
+
for (let postponement of this.postponements) {
|
|
306
|
+
postponement.expire();
|
|
307
|
+
}
|
|
308
|
+
|
|
183
309
|
this.emit('removed', expired);
|
|
184
310
|
});
|
|
185
311
|
|