alchemymvc 1.3.6 → 1.3.7

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.
@@ -290,16 +290,18 @@ Alchemy.setMethod(function group(name, id, callback) {
290
290
  /**
291
291
  * Print a segment
292
292
  *
293
- * @author Jelle De Loecker <jelle@develry.be>
293
+ * @author Jelle De Loecker <jelle@elevenways.be>
294
294
  * @since 0.5.0
295
- * @version 1.1.5
295
+ * @version 1.3.7
296
296
  *
297
297
  * @param {String|Object} options
298
298
  * @param {Object} data
299
+ *
300
+ * @return {HePlaceholder}
299
301
  */
300
302
  Alchemy.setMethod(function segment(options, data) {
301
303
 
302
- var that = this;
304
+ const that = this;
303
305
 
304
306
  if (typeof options == 'string') {
305
307
  options = {
@@ -307,10 +309,14 @@ Alchemy.setMethod(function segment(options, data) {
307
309
  };
308
310
  }
309
311
 
310
- let start = Date.now();
312
+ let print_placeholder = options.print;
313
+
314
+ if (print_placeholder == null) {
315
+ print_placeholder = true;
316
+ }
311
317
 
312
318
  // Prints a placeholder
313
- this.view.async(function doAsync(next) {
319
+ return this.view.async(function doAsync(next) {
314
320
 
315
321
  var conduit,
316
322
  route;
@@ -354,7 +360,7 @@ Alchemy.setMethod(function segment(options, data) {
354
360
 
355
361
  next(null, block);
356
362
  });
357
- });
363
+ }, {print: print_placeholder});
358
364
  });
359
365
 
360
366
  /**
@@ -223,7 +223,7 @@ Router.setMethod(function applyDirective(element, name, options) {
223
223
  *
224
224
  * @author Jelle De Loecker <jelle@elevenways.be>
225
225
  * @since 0.2.0
226
- * @version 1.3.6
226
+ * @version 1.3.7
227
227
  *
228
228
  * @param {String} name
229
229
  * @param {Boolean} socket_route Look in the socket routes
@@ -288,22 +288,17 @@ Router.setMethod(function routeConfig(name, socket_route) {
288
288
  if (routes[section] != null && routes[section][name] != null) {
289
289
  let route = routes[section][name];
290
290
 
291
- let result = {
292
- section : section,
293
- name : name
294
- };
291
+ let result;
295
292
 
296
293
  if (socket_route) {
297
- result.socket_route = true;
294
+ result = {
295
+ section : section,
296
+ name : name,
297
+ socket_route : true,
298
+ };
298
299
  } else {
300
+ result = Object.create(route);
299
301
  result.socket_route = false;
300
- result.paths = route.paths;
301
- result.breadcrumb = route.breadcrumb;
302
- result.has_breadcrumb_assignments = route.has_breadcrumb_assignments;
303
- result.keys = route.keys;
304
- result.methods = route.methods;
305
- result.permission = route.permission;
306
- result.has_permission_assignments = route.has_permission_assignments;
307
302
  }
308
303
 
309
304
  let router_options;
@@ -329,9 +324,9 @@ Router.setMethod(function routeConfig(name, socket_route) {
329
324
  /**
330
325
  * Return the plain url for the given url name & parameters object
331
326
  *
332
- * @author Jelle De Loecker <jelle@develry.be>
327
+ * @author Jelle De Loecker <jelle@elevenways.be>
333
328
  * @since 0.2.0
334
- * @version 1.3.0
329
+ * @version 1.3.7
335
330
  *
336
331
  * @param {String} name
337
332
  * @param {Object} parameters
@@ -392,6 +387,33 @@ Router.setMethod(function routeUrl(name, parameters, options) {
392
387
  return '#url_config_' + name + '_notfound';
393
388
  }
394
389
 
390
+ if (config.param_definitions) {
391
+
392
+ let documents = {},
393
+ definition,
394
+ key;
395
+
396
+ for (key in config.param_definitions) {
397
+ definition = config.param_definitions[key];
398
+
399
+ // If this definition has a specific model name,
400
+ // try to get it from the parameters (and also remove it from there)
401
+ if (definition.type_class_name) {
402
+ if (!documents[definition.type_class_name]) {
403
+ documents[definition.type_class_name] = parameters[definition.type_class_name];
404
+
405
+ if (documents[definition.type_class_name]) {
406
+ delete parameters[definition.type_class_name];
407
+ }
408
+ }
409
+ }
410
+
411
+ if (!parameters[definition.name] && documents[definition.type_class_name]) {
412
+ parameters[definition.name] = documents[definition.type_class_name][definition.type_field_name];
413
+ }
414
+ }
415
+ }
416
+
395
417
  // Remove [brackets]
396
418
  url = url.replace(/\[.*?\]/g, '');
397
419
  url = url.assign(parameters, true, RURL.encodeUriQuery);
@@ -717,7 +739,7 @@ Router.setMethod(function updateLanguageSwitcher(element, variables) {
717
739
  *
718
740
  * @author Jelle De Loecker <jelle@elevenways.be>
719
741
  * @since 1.2.5
720
- * @version 1.3.0
742
+ * @version 1.3.7
721
743
  *
722
744
  * @param {String} prefix The prefix to use
723
745
  * @param {Object} variables
@@ -762,6 +784,8 @@ Router.setMethod(function translateCurrentRoute(prefix, variables) {
762
784
 
763
785
  // Add the get queries
764
786
  if (info.url && info.url.search) {
787
+ let key;
788
+
765
789
  for (key in info.url.query) {
766
790
 
767
791
  if (key == 'hajax' || key == 'h_diversion' || key == 'htop') {
@@ -33,4 +33,24 @@ BooleanField.setDatatype('boolean');
33
33
  */
34
34
  BooleanField.setMethod(function cast(value) {
35
35
  return Boolean(value);
36
- });
36
+ });
37
+
38
+ /**
39
+ * See if the given vlaue is considered not-empty for this field
40
+ *
41
+ * @author Jelle De Loecker <jelle@elevenways.be>
42
+ * @since 1.3.7
43
+ * @version 1.3.7
44
+ *
45
+ * @param {Mixed} value
46
+ *
47
+ * @return {Boolean}
48
+ */
49
+ BooleanField.setMethod(function valueHasContent(value) {
50
+
51
+ if (value === undefined) {
52
+ return false;
53
+ }
54
+
55
+ return true;
56
+ });
@@ -89,13 +89,11 @@ SchemaField.setProperty(function requires_translating() {
89
89
  /**
90
90
  * Get the subschema of this field
91
91
  *
92
- * @constructor
93
- *
94
- * @author Jelle De Loecker <jelle@develry.be>
92
+ * @author Jelle De Loecker <jelle@elevenways.be>
95
93
  * @since 0.2.0
96
- * @version 1.3.1
94
+ * @version 1.3.7
97
95
  *
98
- * @param {Object} record
96
+ * @param {Object} record This *should* be the schema context (might not be the root)
99
97
  * @param {String} some_path Some path to a field in the wanted schema
100
98
  *
101
99
  * @return {Schema}
@@ -1078,6 +1078,36 @@ Field.setMethod(function getRules() {
1078
1078
  return result;
1079
1079
  });
1080
1080
 
1081
+ /**
1082
+ * See if the given vlaue is considered not-empty for this field
1083
+ *
1084
+ * @author Jelle De Loecker <jelle@elevenways.be>
1085
+ * @since 1.3.7
1086
+ * @version 1.3.7
1087
+ *
1088
+ * @param {Mixed} value
1089
+ *
1090
+ * @return {Boolean}
1091
+ */
1092
+ Field.setMethod(function valueHasContent(value) {
1093
+
1094
+ if (value == null) {
1095
+ return false;
1096
+ }
1097
+
1098
+ if (value === '') {
1099
+ return false;
1100
+ }
1101
+
1102
+ if (Array.isArray(value)) {
1103
+ if (value.length === 0) {
1104
+ return false;
1105
+ }
1106
+ }
1107
+
1108
+ return true;
1109
+ });
1110
+
1081
1111
  /**
1082
1112
  * Translate the given value
1083
1113
  *
@@ -310,7 +310,7 @@ Model.prepareProperty('datasource', function datasource() {
310
310
  * @type {Object}
311
311
  */
312
312
  Model.prepareProperty('sort', function sort() {
313
- return {created: 1};
313
+ return {[this.primary_key]: -1};
314
314
  });
315
315
 
316
316
  /**
@@ -5,7 +5,7 @@ const PathDefinition = Classes.Alchemy.PathDefinition;
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@elevenways.be>
7
7
  * @since 1.3.0
8
- * @version 1.3.0
8
+ * @version 1.3.7
9
9
  */
10
10
  const PathParamDefinition = Function.inherits('Alchemy.Base', function PathParamDefinition(config) {
11
11
 
@@ -41,6 +41,9 @@ const PathParamDefinition = Function.inherits('Alchemy.Base', function PathParam
41
41
  // The optional type class constructor
42
42
  this.type_class_constructor = null;
43
43
 
44
+ // Is this a model type?
45
+ this.is_model_type = false;
46
+
44
47
  // Has all the config been parsed?
45
48
  this.is_parsed = false;
46
49
  });
@@ -79,6 +82,30 @@ PathParamDefinition.setStatic(function from(input) {
79
82
  return new this(input);
80
83
  });
81
84
 
85
+ /**
86
+ * Get the model constructor
87
+ *
88
+ * @author Jelle De Loecker <jelle@elevenways.be>
89
+ * @since 1.3.7
90
+ * @version 1.3.7
91
+ */
92
+ PathParamDefinition.enforceProperty(function model_constructor(new_value) {
93
+
94
+ if (!this.is_parsed) {
95
+ this.parseTypeDefinition();
96
+ }
97
+
98
+ if (!new_value) {
99
+ const constructor = this.type_class_constructor;
100
+
101
+ if (constructor && this.is_model_type) {
102
+ new_value = constructor;
103
+ }
104
+ }
105
+
106
+ return new_value;
107
+ });
108
+
82
109
  /**
83
110
  * Parse the type definition
84
111
  *
@@ -131,7 +158,14 @@ PathParamDefinition.setMethod(function parseTypeDefinition() {
131
158
  this.type_field_name = field_name;
132
159
 
133
160
  const Model = Classes.Alchemy.Model || Classes.Alchemy.Client.Model;
134
- this.type_class_constructor = Object.path(Model, class_name) || Object.path(Classes.Alchemy, class_name) || Object.path(Classes, class_name);
161
+
162
+ this.type_class_constructor = Object.path(Model, class_name);
163
+
164
+ if (this.type_class_constructor) {
165
+ this.is_model_type = true;
166
+ } else {
167
+ this.type_class_constructor = Object.path(Classes.Alchemy, class_name) || Object.path(Classes, class_name);
168
+ }
135
169
  }
136
170
  });
137
171
 
@@ -129,6 +129,116 @@ Route.setProperty(function has_type_class_checks() {
129
129
  return result;
130
130
  });
131
131
 
132
+ /**
133
+ * Routes with parameters can have schemas
134
+ *
135
+ * @author Jelle De Loecker <jelle@elevenways.be>
136
+ * @since 1.3.7
137
+ * @version 1.3.7
138
+ *
139
+ * @return {Schema}
140
+ */
141
+ Route.enforceProperty(function schema(new_value) {
142
+
143
+ if (new_value) {
144
+ return new_value;
145
+ }
146
+
147
+ if (!this.has_path_assignments) {
148
+ return false;
149
+ }
150
+
151
+ let added_models = {},
152
+ added_fields = {},
153
+ prefix,
154
+ param,
155
+ model_constructor,
156
+ definition;
157
+
158
+ new_value = alchemy.createSchema();
159
+
160
+ for (prefix in this.paths) {
161
+ definition = this.paths[prefix];
162
+
163
+ if (!definition?.param_definitions?.length) {
164
+ continue;
165
+ }
166
+
167
+ for (param of definition.param_definitions) {
168
+ model_constructor = param.model_constructor;
169
+
170
+ if (model_constructor) {
171
+
172
+ if (added_models[model_constructor.name]) {
173
+ continue;
174
+ }
175
+
176
+ if (added_fields[param.name]) {
177
+ continue;
178
+ }
179
+
180
+ added_models[model_constructor.name] = true;
181
+
182
+ try {
183
+ new_value.belongsTo(model_constructor.name);
184
+ } catch (err) {
185
+ // Ignored
186
+ alchemy.distinctProblem('route-schema-' + this.name, 'Route schema error', {error: err});
187
+ }
188
+ } else {
189
+ new_value.addField(param.name, 'String');
190
+ added_fields[param.name] = true;
191
+ }
192
+ }
193
+ }
194
+
195
+ return new_value;
196
+ });
197
+
198
+ /**
199
+ * Get all the param definitions
200
+ *
201
+ * @author Jelle De Loecker <jelle@elevenways.be>
202
+ * @since 1.3.7
203
+ * @version 1.3.7
204
+ *
205
+ * @return {Object}
206
+ */
207
+ Route.enforceProperty(function param_definitions(new_value) {
208
+
209
+ if (new_value) {
210
+ return new_value;
211
+ }
212
+
213
+ let prefix,
214
+ param,
215
+ key,
216
+ definition;
217
+
218
+ new_value = {};
219
+
220
+ for (prefix in this.paths) {
221
+ definition = this.paths[prefix];
222
+
223
+ if (!definition.param_definitions?.length) {
224
+ continue;
225
+ }
226
+
227
+ for (param of definition.param_definitions) {
228
+ key = prefix + '_' + param.name;
229
+
230
+ new_value[key] = {
231
+ name : param.name,
232
+ type_class_name : param.type_class_name,
233
+ type_field_name : param.type_field_name,
234
+ is_model_type : param.is_model_type,
235
+ };
236
+ }
237
+ }
238
+
239
+ return new_value;
240
+ });
241
+
132
242
  /**
133
243
  * Set the breadcrumb for this route
134
244
  *
@@ -1163,7 +1163,7 @@ RouterClass.setMethod(function getOptions(result) {
1163
1163
  *
1164
1164
  * @author Jelle De Loecker <jelle@elevenways.be>
1165
1165
  * @since 0.2.0
1166
- * @version 1.3.0
1166
+ * @version 1.3.7
1167
1167
  *
1168
1168
  * @param {Object} result Optional object to store sectioned results in
1169
1169
  *
@@ -1212,6 +1212,8 @@ RouterClass.setMethod(function getRoutes(result) {
1212
1212
  has_permission_assignments : route.has_permission_assignments || undefined,
1213
1213
  title : route.title,
1214
1214
  visible_location : route.visible_location,
1215
+ schema : route.schema,
1216
+ param_definitions : route.param_definitions,
1215
1217
  };
1216
1218
  }
1217
1219
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemymvc",
3
3
  "description": "MVC framework for Node.js",
4
- "version": "1.3.6",
4
+ "version": "1.3.7",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",