alchemymvc 1.3.19 → 1.3.21
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 +0 -0
- package/lib/app/datasource/mongo_datasource.js +94 -1
- package/lib/app/element/time_ago.js +0 -0
- package/lib/app/helper/alchemy_helper.js +8 -4
- package/lib/app/helper_controller/controller.js +1 -0
- package/lib/app/helper_datasource/00-nosql_datasource.js +0 -0
- package/lib/app/helper_field/{date_field.js → 11-date_field.js} +1 -3
- package/lib/app/helper_field/15-local_temporal_field.js +100 -0
- package/lib/app/helper_field/20-decimal_field.js +105 -0
- package/lib/app/helper_field/big_int_field.js +7 -13
- package/lib/app/helper_field/fixed_decimal_field.js +44 -0
- package/lib/app/helper_field/local_date_field.js +39 -0
- package/lib/app/helper_field/local_date_time_field.js +39 -0
- package/lib/app/helper_field/local_time_field.js +39 -0
- package/lib/app/helper_field/mixed_field.js +73 -0
- package/lib/app/helper_field/schema_field.js +121 -35
- package/lib/app/helper_model/criteria.js +13 -0
- package/lib/app/helper_model/document.js +229 -0
- package/lib/app/helper_model/field_set.js +0 -0
- package/lib/app/helper_model/model.js +91 -18
- package/lib/app/model/alchemy_task_history_model.js +0 -0
- package/lib/bootstrap.js +0 -0
- package/lib/class/conduit.js +2 -2
- package/lib/class/datasource.js +80 -0
- package/lib/class/document.js +27 -0
- package/lib/class/field.js +110 -0
- package/lib/class/inode_file.js +0 -0
- package/lib/class/model.js +50 -28
- package/lib/class/path_evaluator.js +16 -9
- package/lib/class/route.js +4 -1
- package/lib/class/router.js +4 -2
- package/lib/class/schema_client.js +163 -20
- package/lib/class/session.js +0 -0
- package/lib/class/task.js +48 -2
- package/lib/class/task_service.js +37 -8
- package/lib/core/base.js +19 -4
- package/lib/core/client_alchemy.js +84 -1
- package/lib/core/middleware.js +27 -7
- package/lib/init/alchemy.js +4 -1
- package/lib/init/constants.js +23 -0
- package/lib/init/requirements.js +0 -0
- package/package.json +3 -3
|
@@ -110,7 +110,7 @@ SchemaField.setProperty(function requires_translating() {
|
|
|
110
110
|
*
|
|
111
111
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
112
112
|
* @since 0.2.0
|
|
113
|
-
* @version 1.3.
|
|
113
|
+
* @version 1.3.21
|
|
114
114
|
*
|
|
115
115
|
* @param {Object} record This *should* be the schema context (might not be the root)
|
|
116
116
|
* @param {String} some_path Some path to a field in the wanted schema
|
|
@@ -124,56 +124,131 @@ SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
|
124
124
|
// If schema is a string,
|
|
125
125
|
// it needs to be extracted from another field's value
|
|
126
126
|
if (typeof schema == 'string') {
|
|
127
|
+
schema = this.resolveSchemaPath(this.schema, record, some_path, schema);
|
|
128
|
+
}
|
|
127
129
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
return schema;
|
|
131
|
+
});
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Get the subschema of a given schema
|
|
135
|
+
*
|
|
136
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
137
|
+
* @since 1.3.21
|
|
138
|
+
* @version 1.3.21
|
|
139
|
+
*
|
|
140
|
+
* @param {Schema} context_schema The schema context (probably the schema this field is in)
|
|
141
|
+
* @param {Object} record This *should* be the schema context (might not be the root)
|
|
142
|
+
* @param {String} some_path Some path to a field in the wanted schema
|
|
143
|
+
* @param {String} schema The schema path to resolve
|
|
144
|
+
*
|
|
145
|
+
* @return {Schema}
|
|
146
|
+
*/
|
|
147
|
+
SchemaField.setMethod(function resolveSchemaPath(context_schema, record, field_path, schema_path) {
|
|
133
148
|
|
|
134
|
-
|
|
135
|
-
|
|
149
|
+
if (typeof schema_path != 'string') {
|
|
150
|
+
return schema_path;
|
|
151
|
+
}
|
|
136
152
|
|
|
137
|
-
|
|
138
|
-
let field = this.schema.getField(external_field_name);
|
|
153
|
+
let schema;
|
|
139
154
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
155
|
+
// When there are 2 pieces, the second piece is the property name
|
|
156
|
+
let pieces = schema_path.split('.');
|
|
144
157
|
|
|
145
|
-
|
|
146
|
-
|
|
158
|
+
// The first piece is the external field name
|
|
159
|
+
let external_field_name = pieces.shift();
|
|
147
160
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
161
|
+
// The rest of the pieces is the property path
|
|
162
|
+
let property_name = pieces.join('.') || 'schema';
|
|
151
163
|
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
// Get that other field by its name
|
|
165
|
+
let field = context_schema.getField(external_field_name);
|
|
154
166
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
if (!field) {
|
|
168
|
+
let association = context_schema.getAssociation(external_field_name);
|
|
169
|
+
return this.getSubschemaFromAssociation(record, property_name, association);
|
|
170
|
+
}
|
|
159
171
|
|
|
160
|
-
|
|
161
|
-
|
|
172
|
+
if (!field) {
|
|
173
|
+
console.error('Failed to get subschema', external_field_name, 'of', context_schema, field_path);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
162
176
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
// Get the values that field can have (probably an enum)
|
|
178
|
+
let values = field.getValues();
|
|
179
|
+
|
|
180
|
+
if (values == null) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Now get the actual external value from the record
|
|
185
|
+
let record_value = field.getRecordValue(record);
|
|
186
|
+
|
|
187
|
+
// I'm not sure if this will help
|
|
188
|
+
if (record_value == null) {
|
|
189
|
+
record_value = field.getRecordValue(record, field_path);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Get the correct field value
|
|
193
|
+
let enum_value = values.get(record_value);
|
|
194
|
+
|
|
195
|
+
if (!enum_value) {
|
|
196
|
+
schema = null;
|
|
197
|
+
} else if (enum_value.schema) {
|
|
198
|
+
schema = enum_value.schema;
|
|
199
|
+
} else if (enum_value.value) {
|
|
200
|
+
schema = enum_value.value[property_name] || enum_value.value.schema;
|
|
201
|
+
} else {
|
|
202
|
+
console.log('Could not find', schema_path, 'in', record, 'enum values:', enum_value, 'of field', field)
|
|
172
203
|
}
|
|
173
204
|
|
|
174
205
|
return schema;
|
|
175
206
|
});
|
|
176
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Get the subschema via an association
|
|
210
|
+
* @TODO: Work in progress!
|
|
211
|
+
*
|
|
212
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
213
|
+
* @since 0.2.0
|
|
214
|
+
* @version 1.3.21
|
|
215
|
+
*
|
|
216
|
+
* @param {Object} record This *should* be the schema context (might not be the root)
|
|
217
|
+
* @param {String} path The path inside the associated schema
|
|
218
|
+
* @param {Object} association The association object
|
|
219
|
+
*
|
|
220
|
+
* @return {Schema} Response might be a promise
|
|
221
|
+
*/
|
|
222
|
+
SchemaField.setMethod(function getSubschemaFromAssociation(record, path, association) {
|
|
223
|
+
|
|
224
|
+
let local_value = record[association.options.local_key];
|
|
225
|
+
|
|
226
|
+
if (!local_value) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const associated_model = alchemy.getModel(association.model_name);
|
|
231
|
+
|
|
232
|
+
if (!associated_model) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return Pledge.Swift.execute(async () => {
|
|
237
|
+
|
|
238
|
+
let result = await associated_model.findByValues({
|
|
239
|
+
[association.options.foreign_key]: local_value,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (!result) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let found_schema = this.resolveSchemaPath(associated_model.schema, result, path, path);
|
|
247
|
+
|
|
248
|
+
return found_schema;
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
177
252
|
/**
|
|
178
253
|
* Cast all the subschema values using their _toDatasource method
|
|
179
254
|
*
|
|
@@ -414,6 +489,17 @@ SchemaField.setMethod(function _toAppFromValue(query, options, value, callback)
|
|
|
414
489
|
record = {
|
|
415
490
|
[this.schema.name] : options.parent_value
|
|
416
491
|
};
|
|
492
|
+
} else if (options._root_data) {
|
|
493
|
+
|
|
494
|
+
let root_data = options._root_data;
|
|
495
|
+
|
|
496
|
+
if (root_data[this.schema.name]) {
|
|
497
|
+
root_data = root_data[this.schema.name];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
record = {
|
|
501
|
+
[this.schema.name] : root_data
|
|
502
|
+
};
|
|
417
503
|
} else {
|
|
418
504
|
record = {
|
|
419
505
|
[this.schema.name] : {
|
|
@@ -1116,6 +1116,19 @@ Criteria.setMethod(function and(value) {
|
|
|
1116
1116
|
return this._applyGroup('and');
|
|
1117
1117
|
});
|
|
1118
1118
|
|
|
1119
|
+
/**
|
|
1120
|
+
* Alias for `ne`: Not equals check
|
|
1121
|
+
*
|
|
1122
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1123
|
+
* @since 1.3.21
|
|
1124
|
+
* @version 1.3.2
|
|
1125
|
+
*
|
|
1126
|
+
* @param {*} value
|
|
1127
|
+
*/
|
|
1128
|
+
Criteria.setMethod(function notEquals(value) {
|
|
1129
|
+
return this.ne(value);
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1119
1132
|
Criteria.addValueExpression('equals');
|
|
1120
1133
|
Criteria.addValueExpression('gte');
|
|
1121
1134
|
Criteria.addValueExpression('gt');
|
|
@@ -131,6 +131,32 @@ Document.setStatic(function setMethod(key, method, on_server) {
|
|
|
131
131
|
return Blast.Collection.Function.setMethod(this, key, method);
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Set a getter for this computed field
|
|
136
|
+
*
|
|
137
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
138
|
+
* @since 1.3.21
|
|
139
|
+
* @version 1.3.21
|
|
140
|
+
*
|
|
141
|
+
* @param {String} name Name of the property
|
|
142
|
+
* @param {Boolean} on_server Also set on the server implementation
|
|
143
|
+
*/
|
|
144
|
+
Document.setStatic(function setComputedFieldGetter(name, on_server) {
|
|
145
|
+
this.setProperty(name, function getComputedFieldValue() {
|
|
146
|
+
this.recomputeFieldIfNecessary(name);
|
|
147
|
+
return this.$main[name];
|
|
148
|
+
}, function setComputedFieldValue(value) {
|
|
149
|
+
|
|
150
|
+
const field = this.$model.schema.getField(name);
|
|
151
|
+
|
|
152
|
+
if (field?.options?.allow_manual_set) {
|
|
153
|
+
return this.$main[name] = value;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.error('Can not set computed field "' + name + '" to', value);
|
|
157
|
+
}, on_server);
|
|
158
|
+
});
|
|
159
|
+
|
|
134
160
|
/**
|
|
135
161
|
* Set a getter for this field
|
|
136
162
|
*
|
|
@@ -858,6 +884,209 @@ Document.setMethod(function setValues(values) {
|
|
|
858
884
|
|
|
859
885
|
});
|
|
860
886
|
|
|
887
|
+
/**
|
|
888
|
+
* Recompute the given field if required
|
|
889
|
+
*
|
|
890
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
891
|
+
* @since 1.3.21
|
|
892
|
+
* @version 1.3.21
|
|
893
|
+
*
|
|
894
|
+
* @param {string|Alchemy.Field} name
|
|
895
|
+
* @param {boolean} force
|
|
896
|
+
*
|
|
897
|
+
* @return {Pledge|undefined}
|
|
898
|
+
*/
|
|
899
|
+
Document.setMethod(function recomputeFieldIfNecessary(name, force = false) {
|
|
900
|
+
|
|
901
|
+
const field = this.$model.schema.getField(name),
|
|
902
|
+
original = this.$main[name];
|
|
903
|
+
|
|
904
|
+
if (!field) {
|
|
905
|
+
return original;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
let options = field.options;
|
|
909
|
+
|
|
910
|
+
if (!options.compute_method) {
|
|
911
|
+
return original;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
let required_field_count = options.required_fields?.length || 0,
|
|
915
|
+
optional_field_count = options.optional_fields?.length || 0;
|
|
916
|
+
|
|
917
|
+
if (!force && original == null) {
|
|
918
|
+
// If the value is null, it hasn't been computed yet
|
|
919
|
+
// and we need to compute it
|
|
920
|
+
force = true;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (!force) {
|
|
924
|
+
let has_changed = false;
|
|
925
|
+
|
|
926
|
+
if (required_field_count) {
|
|
927
|
+
for (let required_field of options.required_fields) {
|
|
928
|
+
if (this.hasChanged(required_field)) {
|
|
929
|
+
has_changed = true;
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
if (!has_changed && optional_field_count) {
|
|
936
|
+
for (let optional_field of options.optional_fields) {
|
|
937
|
+
if (this.hasChanged(optional_field)) {
|
|
938
|
+
has_changed = true;
|
|
939
|
+
break;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
if (!has_changed) {
|
|
945
|
+
return original;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// Make sure the required fields are set
|
|
950
|
+
if (required_field_count) {
|
|
951
|
+
let has_value = true;
|
|
952
|
+
|
|
953
|
+
for (let required_field of options.required_fields) {
|
|
954
|
+
if (this[required_field] == null) {
|
|
955
|
+
has_value = false;
|
|
956
|
+
break;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
if (!has_value) {
|
|
961
|
+
// If not all required field values are set,
|
|
962
|
+
// the result will also be undefined
|
|
963
|
+
return this._setComputedFieldValue(name, undefined);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
let compute_method = options.compute_method;
|
|
968
|
+
|
|
969
|
+
if (typeof compute_method == 'string') {
|
|
970
|
+
let fnc = this[compute_method];
|
|
971
|
+
|
|
972
|
+
if (typeof fnc == 'function') {
|
|
973
|
+
compute_method = fnc;
|
|
974
|
+
} else {
|
|
975
|
+
// Handle special cases in the browser
|
|
976
|
+
compute_method = alchemy.getCustomHandler('recompute_field');
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (!compute_method) {
|
|
981
|
+
return original;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
let result = compute_method.call(this, this, field);
|
|
985
|
+
|
|
986
|
+
return this._setComputedFieldValue(name, result);
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Set a computed field to a specific value
|
|
991
|
+
*
|
|
992
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
993
|
+
* @since 1.3.21
|
|
994
|
+
* @version 1.3.21
|
|
995
|
+
*
|
|
996
|
+
* @param {string|Alchemy.Field} name
|
|
997
|
+
* @param {*} value
|
|
998
|
+
*
|
|
999
|
+
* @return {Pledge|undefined}
|
|
1000
|
+
*/
|
|
1001
|
+
Document.setMethod(function _setComputedFieldValue(name, value) {
|
|
1002
|
+
|
|
1003
|
+
const field = this.$model.schema.getField(name);
|
|
1004
|
+
|
|
1005
|
+
if (value == null && field?.options?.allow_manual_set) {
|
|
1006
|
+
return this.$main[name];
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
if (Pledge.isThenable(value)) {
|
|
1010
|
+
value.then(value => {
|
|
1011
|
+
this.$main[name] = value;
|
|
1012
|
+
});
|
|
1013
|
+
} else {
|
|
1014
|
+
this.$main[name] = value;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return value;
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Recompute values of computed fields.
|
|
1022
|
+
* This might be async. If it is, a pledge will be returned.
|
|
1023
|
+
*
|
|
1024
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1025
|
+
* @since 1.3.21
|
|
1026
|
+
* @version 1.3.21
|
|
1027
|
+
*
|
|
1028
|
+
* @return {Pledge|undefined}
|
|
1029
|
+
*/
|
|
1030
|
+
Document.setMethod(function recomputeValues() {
|
|
1031
|
+
|
|
1032
|
+
const schema = this.$model.schema;
|
|
1033
|
+
|
|
1034
|
+
if (!schema.has_computed_fields) {
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
let promises = [];
|
|
1039
|
+
|
|
1040
|
+
for (let key in schema.computed_fields) {
|
|
1041
|
+
let field = schema.computed_fields[key];
|
|
1042
|
+
let options = field.options;
|
|
1043
|
+
|
|
1044
|
+
// Make sure the required fields are set
|
|
1045
|
+
if (options.required_fields?.length) {
|
|
1046
|
+
let has_value = true;
|
|
1047
|
+
|
|
1048
|
+
for (let required_field of options.required_fields) {
|
|
1049
|
+
if (this[required_field] == null) {
|
|
1050
|
+
has_value = false;
|
|
1051
|
+
break;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (!has_value) {
|
|
1056
|
+
// If not all required field values are set,
|
|
1057
|
+
// the result will also be undefined
|
|
1058
|
+
this._setComputedFieldValue(key, undefined);
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
let compute_method = options.compute_method;
|
|
1064
|
+
|
|
1065
|
+
if (typeof compute_method == 'string') {
|
|
1066
|
+
let fnc = this[compute_method];
|
|
1067
|
+
|
|
1068
|
+
if (typeof fnc == 'function') {
|
|
1069
|
+
compute_method = fnc;
|
|
1070
|
+
} else {
|
|
1071
|
+
// Handle special cases in the browser
|
|
1072
|
+
compute_method = alchemy.getCustomHandler('recompute_field');
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
if (!compute_method) {
|
|
1077
|
+
continue;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
let result = compute_method.call(this, this, field);
|
|
1081
|
+
|
|
1082
|
+
this._setComputedFieldValue(key, result);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
if (promises.length) {
|
|
1086
|
+
return Pledge.all(promises);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
|
|
861
1090
|
/**
|
|
862
1091
|
* Get the clean options
|
|
863
1092
|
*
|
|
File without changes
|
|
@@ -629,7 +629,7 @@ Model.setMethod(function getAliasModel(alias) {
|
|
|
629
629
|
*
|
|
630
630
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
631
631
|
* @since 0.0.1
|
|
632
|
-
* @version 1.3.
|
|
632
|
+
* @version 1.3.21
|
|
633
633
|
*
|
|
634
634
|
* @param {String} type The type of find (first, all)
|
|
635
635
|
* @param {Criteria} criteria The criteria object
|
|
@@ -797,6 +797,27 @@ Model.setMethod(function find(type, criteria, callback) {
|
|
|
797
797
|
next();
|
|
798
798
|
}
|
|
799
799
|
});
|
|
800
|
+
}, function recomputeAfterFind(next) {
|
|
801
|
+
|
|
802
|
+
if (!that.schema.has_recompute_after_find || criteria.options.document === false) {
|
|
803
|
+
return next();
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
let tasks = [];
|
|
807
|
+
|
|
808
|
+
for (let document of records) {
|
|
809
|
+
tasks.push((next) => {
|
|
810
|
+
let promise = document.recomputeValues();
|
|
811
|
+
|
|
812
|
+
if (!promise) {
|
|
813
|
+
return next();
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
Pledge.done(promise, next);
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
Function.parallel(8, tasks, next);
|
|
800
821
|
}, function done(err) {
|
|
801
822
|
|
|
802
823
|
var i;
|
|
@@ -1626,7 +1647,7 @@ Hawkejs.Model = Model;
|
|
|
1626
1647
|
*
|
|
1627
1648
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1628
1649
|
* @since 0.0.1
|
|
1629
|
-
* @version 1.
|
|
1650
|
+
* @version 1.3.20
|
|
1630
1651
|
*
|
|
1631
1652
|
* @param {Document} document
|
|
1632
1653
|
* @param {Object} options
|
|
@@ -1675,9 +1696,9 @@ Model.setMethod(function saveRecord(document, options, callback) {
|
|
|
1675
1696
|
creating = options.create || doc.$pk == null;
|
|
1676
1697
|
next();
|
|
1677
1698
|
});
|
|
1678
|
-
}, function
|
|
1699
|
+
}, function doBeforeNormalize(next) {
|
|
1679
1700
|
// @TODO: make "beforeSave" only use promises
|
|
1680
|
-
that.callOrNext('
|
|
1701
|
+
that.callOrNext('beforeNormalize', [document, options], next);
|
|
1681
1702
|
}, function emitSavingEvent(next) {
|
|
1682
1703
|
// @TODO: Should this be able to stop the saving without throwing an error?
|
|
1683
1704
|
that.issueEvent('saving', [document, options, creating], next);
|
|
@@ -1771,28 +1792,42 @@ Model.setMethod(function compose(data, options) {
|
|
|
1771
1792
|
/**
|
|
1772
1793
|
* Create a record in the database
|
|
1773
1794
|
*
|
|
1774
|
-
* @author Jelle De Loecker <jelle@
|
|
1795
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1775
1796
|
* @since 0.2.0
|
|
1776
|
-
* @version 1.3.
|
|
1797
|
+
* @version 1.3.21
|
|
1777
1798
|
*
|
|
1778
|
-
* @param {
|
|
1799
|
+
* @param {Document} document
|
|
1779
1800
|
* @param {Object} options
|
|
1780
1801
|
* @param {Function} callback
|
|
1781
1802
|
*/
|
|
1782
|
-
Model.setMethod(function createRecord(
|
|
1803
|
+
Model.setMethod(function createRecord(document, options, callback) {
|
|
1783
1804
|
|
|
1784
1805
|
const that = this;
|
|
1785
1806
|
|
|
1786
1807
|
// Normalize & clone the data, set default values, ...
|
|
1787
|
-
data = this.compose(
|
|
1808
|
+
let data = this.compose(document, options);
|
|
1809
|
+
|
|
1810
|
+
document = createDocumentForSaving(this, document, data);
|
|
1788
1811
|
|
|
1789
|
-
Function.series(function
|
|
1812
|
+
Function.series(function recompute(next) {
|
|
1813
|
+
let result = document.recomputeValues();
|
|
1814
|
+
|
|
1815
|
+
if (result) {
|
|
1816
|
+
result.done(next);
|
|
1817
|
+
} else {
|
|
1818
|
+
next();
|
|
1819
|
+
}
|
|
1820
|
+
}, function doBeforeValidate(next) {
|
|
1821
|
+
that.callOrNext('beforeValidate', [document, options], next);
|
|
1822
|
+
}, function validate(next) {
|
|
1790
1823
|
|
|
1791
1824
|
if (options.validate === false || !that.schema) {
|
|
1792
1825
|
return next();
|
|
1793
1826
|
}
|
|
1794
1827
|
|
|
1795
|
-
Pledge.done(that.schema.validate(
|
|
1828
|
+
Pledge.done(that.schema.validate(document), next);
|
|
1829
|
+
}, function doBeforeSave(next) {
|
|
1830
|
+
that.callOrNext('beforeSave', [document, options], next);
|
|
1796
1831
|
}, function done(err) {
|
|
1797
1832
|
|
|
1798
1833
|
if (err) {
|
|
@@ -1816,32 +1851,70 @@ Model.setMethod(function createRecord(data, options, callback) {
|
|
|
1816
1851
|
})
|
|
1817
1852
|
});
|
|
1818
1853
|
|
|
1854
|
+
/**
|
|
1855
|
+
* Create a document used for saving
|
|
1856
|
+
*
|
|
1857
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1858
|
+
* @since 1.3.21
|
|
1859
|
+
* @version 1.3.21
|
|
1860
|
+
*
|
|
1861
|
+
* @param {Model} model
|
|
1862
|
+
* @param {Document|Object} original_input
|
|
1863
|
+
* @param {Object} data
|
|
1864
|
+
*/
|
|
1865
|
+
function createDocumentForSaving(model, original_input, data) {
|
|
1866
|
+
|
|
1867
|
+
// Turn it into a new document
|
|
1868
|
+
let document = model.createDocument(data);
|
|
1869
|
+
|
|
1870
|
+
if (original_input?.$attributes.original_record) {
|
|
1871
|
+
document.$attributes.original_record = original_input.$attributes.original_record;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
return document;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1819
1877
|
/**
|
|
1820
1878
|
* Update a record in the database
|
|
1821
1879
|
*
|
|
1822
|
-
* @author Jelle De Loecker <jelle@
|
|
1880
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1823
1881
|
* @since 0.2.0
|
|
1824
|
-
* @version 1.3.
|
|
1882
|
+
* @version 1.3.21
|
|
1825
1883
|
*
|
|
1826
|
-
* @param {
|
|
1884
|
+
* @param {Document} document
|
|
1827
1885
|
* @param {Object} options
|
|
1828
1886
|
* @param {Function} callback
|
|
1829
1887
|
*/
|
|
1830
|
-
Model.setMethod(function updateRecord(
|
|
1888
|
+
Model.setMethod(function updateRecord(document, options, callback) {
|
|
1831
1889
|
|
|
1832
1890
|
const that = this;
|
|
1833
1891
|
|
|
1834
1892
|
// Normalize the data, but no default values should be set (skip non present items)
|
|
1835
|
-
data = this.compose(
|
|
1893
|
+
let data = this.compose(document, Object.assign({update: true}, options));
|
|
1894
|
+
|
|
1895
|
+
// Turn it into a new document
|
|
1896
|
+
document = createDocumentForSaving(this, document, data);
|
|
1897
|
+
|
|
1898
|
+
Function.series(function recompute(next) {
|
|
1899
|
+
let result = document.recomputeValues();
|
|
1836
1900
|
|
|
1837
|
-
|
|
1901
|
+
if (result) {
|
|
1902
|
+
result.done(next);
|
|
1903
|
+
} else {
|
|
1904
|
+
next();
|
|
1905
|
+
}
|
|
1906
|
+
}, function doBeforeValidate(next) {
|
|
1907
|
+
that.callOrNext('beforeValidate', [document, options], next);
|
|
1908
|
+
}, function validate(next) {
|
|
1838
1909
|
|
|
1839
1910
|
if (options.validate === false || !that.schema) {
|
|
1840
1911
|
return next();
|
|
1841
1912
|
}
|
|
1842
1913
|
|
|
1843
|
-
Pledge.done(that.schema.validate(
|
|
1914
|
+
Pledge.done(that.schema.validate(document), next);
|
|
1844
1915
|
|
|
1916
|
+
}, function doBeforeSave(next) {
|
|
1917
|
+
that.callOrNext('beforeSave', [document, options], next);
|
|
1845
1918
|
}, function done(err) {
|
|
1846
1919
|
|
|
1847
1920
|
if (err) {
|
|
File without changes
|
package/lib/bootstrap.js
CHANGED
|
File without changes
|
package/lib/class/conduit.js
CHANGED
|
@@ -1578,7 +1578,7 @@ Conduit.setMethod(function redirect(status, options) {
|
|
|
1578
1578
|
*
|
|
1579
1579
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1580
1580
|
* @since 0.2.0
|
|
1581
|
-
* @version 1.3.
|
|
1581
|
+
* @version 1.3.21
|
|
1582
1582
|
*
|
|
1583
1583
|
* @param {Nulber} status Response statuscode
|
|
1584
1584
|
* @param {Error} message Optional error to send
|
|
@@ -1613,7 +1613,7 @@ Conduit.setMethod(function error(status, message, print_error) {
|
|
|
1613
1613
|
if (alchemy.settings.environment == 'dev') {
|
|
1614
1614
|
print_dev = true;
|
|
1615
1615
|
|
|
1616
|
-
if (is_400 && this.original_path.indexOf('.js.map') > -1) {
|
|
1616
|
+
if (is_400 && this.original_path && this.original_path.indexOf('.js.map') > -1) {
|
|
1617
1617
|
print_dev = false;
|
|
1618
1618
|
print_error = false;
|
|
1619
1619
|
}
|