alchemymvc 1.3.0 → 1.3.2
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/conduit/http_conduit.js +7 -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 +16 -7
- package/lib/app/helper_field/schema_field.js +44 -30
- package/lib/app/helper_model/document.js +40 -36
- package/lib/app/helper_model/model.js +72 -43
- 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/class/conduit.js +207 -46
- package/lib/class/controller.js +18 -15
- package/lib/class/datasource.js +14 -7
- package/lib/class/field.js +21 -3
- package/lib/class/migration.js +2 -1
- package/lib/class/model.js +12 -1
- package/lib/class/postponement.js +593 -0
- package/lib/class/route.js +18 -2
- package/lib/class/router.js +6 -2
- package/lib/class/schema.js +36 -0
- package/lib/class/schema_client.js +16 -19
- package/lib/class/session.js +138 -12
- package/lib/core/base.js +7 -1
- package/lib/core/client_alchemy.js +3 -1
- package/lib/core/client_base.js +7 -2
- package/lib/init/alchemy.js +150 -2
- package/lib/init/functions.js +30 -4
- package/lib/init/requirements.js +4 -2
- package/lib/stages.js +18 -3
- package/package.json +4 -4
|
@@ -105,9 +105,9 @@ HttpConduit.enforceProperty(function fingerprint() {
|
|
|
105
105
|
/**
|
|
106
106
|
* Init
|
|
107
107
|
*
|
|
108
|
-
* @author Jelle De Loecker <jelle@
|
|
108
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
109
109
|
* @since 0.3.3
|
|
110
|
-
* @version 1.
|
|
110
|
+
* @version 1.3.1
|
|
111
111
|
*
|
|
112
112
|
* @param {IncomingMessage} req
|
|
113
113
|
* @param {ServerResponse} res
|
|
@@ -139,6 +139,11 @@ HttpConduit.setMethod(async function initHttp(req, res, router) {
|
|
|
139
139
|
|
|
140
140
|
this.debugMark(false);
|
|
141
141
|
|
|
142
|
+
if (this.shouldBePostponed()) {
|
|
143
|
+
this.postponeAndQueue();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
142
147
|
// Call the middleware, which will call the handler afterwards
|
|
143
148
|
this.callMiddleware();
|
|
144
149
|
});
|
|
@@ -102,19 +102,34 @@ var SocketConduit = Function.inherits('Alchemy.Conduit', function Socket(socket,
|
|
|
102
102
|
/**
|
|
103
103
|
* Return the client IP address
|
|
104
104
|
*
|
|
105
|
-
* @author Jelle De Loecker <jelle@
|
|
105
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
106
106
|
* @since 0.2.1
|
|
107
|
-
* @version
|
|
107
|
+
* @version 1.3.1
|
|
108
108
|
*/
|
|
109
109
|
SocketConduit.setProperty(function ip() {
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
let handshake = this.socket?.handshake;
|
|
112
112
|
|
|
113
|
-
if (!
|
|
113
|
+
if (!handshake) {
|
|
114
114
|
return null;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
if (handshake.headers) {
|
|
118
|
+
let forwarded_for = handshake.headers['x-forwarded-for'] || handshake.headers['x-real-ip'];
|
|
119
|
+
|
|
120
|
+
if (forwarded_for) {
|
|
121
|
+
|
|
122
|
+
// Forwarded for can contain multiple ip addresses,
|
|
123
|
+
// return the first one
|
|
124
|
+
if (forwarded_for.indexOf(',') > -1) {
|
|
125
|
+
forwarded_for = forwarded_for.before(',');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return forwarded_for;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return handshake.address || null;
|
|
118
133
|
});
|
|
119
134
|
|
|
120
135
|
/**
|
|
@@ -130,20 +130,16 @@ Info.setAction(async function appcache(conduit) {
|
|
|
130
130
|
*
|
|
131
131
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
132
132
|
* @since 1.1.0
|
|
133
|
-
* @version 1.1
|
|
133
|
+
* @version 1.3.1
|
|
134
134
|
*/
|
|
135
135
|
Info.setAction(function postponed(conduit, id) {
|
|
136
136
|
|
|
137
137
|
var session = conduit.getSession(),
|
|
138
|
-
|
|
138
|
+
postponement = session.getPostponement(id);
|
|
139
139
|
|
|
140
|
-
if (!
|
|
140
|
+
if (!postponement) {
|
|
141
141
|
return conduit.notFound();
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
postponed_conduit._end(...postponed_conduit._end_arguments);
|
|
147
|
-
|
|
148
|
-
session.postponed.remove(id);
|
|
144
|
+
postponement.handleRequest(conduit);
|
|
149
145
|
});
|
|
@@ -77,12 +77,12 @@ Backed.enforceProperty(function backing(new_value, old_value) {
|
|
|
77
77
|
*
|
|
78
78
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
79
79
|
* @since 1.2.1
|
|
80
|
-
* @version 1.
|
|
80
|
+
* @version 1.3.1
|
|
81
81
|
*
|
|
82
82
|
* @return {Backed}
|
|
83
83
|
*/
|
|
84
84
|
Backed.setMethod(function clone() {
|
|
85
|
-
let result = new
|
|
85
|
+
let result = new this.constructor(this.backing);
|
|
86
86
|
result.local = new Map(this.local);
|
|
87
87
|
return result;
|
|
88
88
|
});
|
|
@@ -86,9 +86,9 @@ Router.setMethod(function isLocalUrl(url) {
|
|
|
86
86
|
/**
|
|
87
87
|
* Apply directive to an element
|
|
88
88
|
*
|
|
89
|
-
* @author Jelle De Loecker <jelle@
|
|
89
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
90
90
|
* @since 1.1.0
|
|
91
|
-
* @version 1.
|
|
91
|
+
* @version 1.3.1
|
|
92
92
|
*
|
|
93
93
|
* @param {Element} element The element to apply to
|
|
94
94
|
* @param {String} name The route name
|
|
@@ -120,14 +120,23 @@ Router.setMethod(function applyDirective(element, name, options) {
|
|
|
120
120
|
if (config.keys && config.keys.length) {
|
|
121
121
|
|
|
122
122
|
let key,
|
|
123
|
-
val
|
|
124
|
-
i;
|
|
123
|
+
val;
|
|
125
124
|
|
|
126
|
-
for (
|
|
127
|
-
key = config.keys[i];
|
|
125
|
+
for (key of config.keys) {
|
|
128
126
|
|
|
129
127
|
if (params[key] == null) {
|
|
130
|
-
|
|
128
|
+
|
|
129
|
+
val = element['route_' + key];
|
|
130
|
+
|
|
131
|
+
if (val == null) {
|
|
132
|
+
let variables = element[Hawkejs.VARIABLES];
|
|
133
|
+
|
|
134
|
+
if (variables) {
|
|
135
|
+
val = variables[key];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (val == null) {
|
|
131
140
|
val = element[key];
|
|
132
141
|
}
|
|
133
142
|
|
|
@@ -93,7 +93,7 @@ SchemaField.setProperty(function requires_translating() {
|
|
|
93
93
|
*
|
|
94
94
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
95
95
|
* @since 0.2.0
|
|
96
|
-
* @version 1.
|
|
96
|
+
* @version 1.3.1
|
|
97
97
|
*
|
|
98
98
|
* @param {Object} record
|
|
99
99
|
* @param {String} some_path Some path to a field in the wanted schema
|
|
@@ -102,29 +102,23 @@ SchemaField.setProperty(function requires_translating() {
|
|
|
102
102
|
*/
|
|
103
103
|
SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
external_field_name,
|
|
107
|
-
property_name,
|
|
108
|
-
record_value,
|
|
109
|
-
pieces,
|
|
110
|
-
field,
|
|
111
|
-
name;
|
|
105
|
+
let schema = this.options.schema;
|
|
112
106
|
|
|
113
107
|
// If schema is a string,
|
|
114
108
|
// it needs to be extracted from another field's value
|
|
115
109
|
if (typeof schema == 'string') {
|
|
116
110
|
|
|
117
111
|
// When there are 2 pieces, the second piece is the property name
|
|
118
|
-
pieces = schema.split('.');
|
|
112
|
+
let pieces = schema.split('.');
|
|
119
113
|
|
|
120
114
|
// The first piece is the external field name
|
|
121
|
-
external_field_name = pieces[0];
|
|
115
|
+
let external_field_name = pieces[0];
|
|
122
116
|
|
|
123
117
|
// The second piece is the property name
|
|
124
|
-
property_name = pieces[1] || 'schema';
|
|
118
|
+
let property_name = pieces[1] || 'schema';
|
|
125
119
|
|
|
126
120
|
// Get that other field by its name
|
|
127
|
-
field = this.schema.getField(external_field_name);
|
|
121
|
+
let field = this.schema.getField(external_field_name);
|
|
128
122
|
|
|
129
123
|
if (!field) {
|
|
130
124
|
console.error('Failed to get subschema', external_field_name, 'of', this.schema, some_path);
|
|
@@ -139,7 +133,7 @@ SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
|
139
133
|
}
|
|
140
134
|
|
|
141
135
|
// Now get the actual external value from the record
|
|
142
|
-
record_value = field.getRecordValue(record);
|
|
136
|
+
let record_value = field.getRecordValue(record);
|
|
143
137
|
|
|
144
138
|
// I'm not sure if this will help
|
|
145
139
|
if (record_value == null) {
|
|
@@ -155,6 +149,8 @@ SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
|
155
149
|
schema = enum_value.schema;
|
|
156
150
|
} else if (enum_value.value) {
|
|
157
151
|
schema = enum_value.value[property_name] || enum_value.value.schema;
|
|
152
|
+
} else {
|
|
153
|
+
console.log('Could not find', schema, 'in', record, 'enum values:', enum_value, 'of field', field)
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
|
|
@@ -166,7 +162,7 @@ SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
|
166
162
|
*
|
|
167
163
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
168
164
|
* @since 0.2.0
|
|
169
|
-
* @version
|
|
165
|
+
* @version 1.3.1
|
|
170
166
|
*
|
|
171
167
|
* @param {Object} value Value of field, an object in this case
|
|
172
168
|
* @param {Object} data The data object containing `value`
|
|
@@ -174,18 +170,21 @@ SchemaField.setMethod(function getSubschema(record, some_path) {
|
|
|
174
170
|
*
|
|
175
171
|
* @return {Object}
|
|
176
172
|
*/
|
|
177
|
-
SchemaField.setMethod(function _toDatasource(value,
|
|
173
|
+
SchemaField.setMethod(function _toDatasource(value, holder, datasource, callback) {
|
|
178
174
|
|
|
179
175
|
var that = this,
|
|
180
176
|
sub_schema,
|
|
181
177
|
record,
|
|
182
178
|
model,
|
|
183
179
|
temp;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
180
|
+
|
|
181
|
+
if (this.schema.name) {
|
|
182
|
+
record = {
|
|
183
|
+
[this.schema.name] : holder,
|
|
184
|
+
};
|
|
185
|
+
} else {
|
|
186
|
+
record = holder;
|
|
187
|
+
}
|
|
189
188
|
|
|
190
189
|
sub_schema = this.getSubschema(record);
|
|
191
190
|
|
|
@@ -217,7 +216,7 @@ SchemaField.setMethod(function _toDatasource(value, data, datasource, callback)
|
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
// Add the newly found data
|
|
220
|
-
temp = Object.assign({},
|
|
219
|
+
temp = Object.assign({}, holder);
|
|
221
220
|
record = {};
|
|
222
221
|
record[that.schema.name] = temp;
|
|
223
222
|
|
|
@@ -240,7 +239,7 @@ SchemaField.setMethod(function _toDatasource(value, data, datasource, callback)
|
|
|
240
239
|
});
|
|
241
240
|
|
|
242
241
|
/**
|
|
243
|
-
*
|
|
242
|
+
* Turn datasource data into app data
|
|
244
243
|
*
|
|
245
244
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
246
245
|
* @since 0.2.0
|
|
@@ -323,11 +322,19 @@ SchemaField.setMethod(function _toApp(query, options, value, callback) {
|
|
|
323
322
|
return;
|
|
324
323
|
}
|
|
325
324
|
|
|
326
|
-
|
|
327
|
-
let record = {};
|
|
325
|
+
let record;
|
|
328
326
|
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
if (options.parent_value) {
|
|
328
|
+
record = {
|
|
329
|
+
[this.schema.name] : options.parent_value
|
|
330
|
+
};
|
|
331
|
+
} else {
|
|
332
|
+
record = {
|
|
333
|
+
[this.schema.name] : {
|
|
334
|
+
[this.name] : value,
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
331
338
|
|
|
332
339
|
let sub_schema = this.getSubschema(record);
|
|
333
340
|
|
|
@@ -335,13 +342,20 @@ SchemaField.setMethod(function _toApp(query, options, value, callback) {
|
|
|
335
342
|
if (sub_schema) {
|
|
336
343
|
let tasks = {};
|
|
337
344
|
|
|
338
|
-
Object.each(value,
|
|
345
|
+
Object.each(value, (field_value, field_name) => {
|
|
339
346
|
|
|
340
|
-
|
|
347
|
+
let field = sub_schema.get(field_name);
|
|
341
348
|
|
|
342
349
|
if (field != null) {
|
|
343
|
-
|
|
344
|
-
|
|
350
|
+
|
|
351
|
+
let sub_options = {
|
|
352
|
+
_root_data: options._root_data,
|
|
353
|
+
parent_field_schema_name: this.name,
|
|
354
|
+
parent_value : value,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
tasks[field_name] = (next) => {
|
|
358
|
+
field.toApp({}, sub_options, field_value, next);
|
|
345
359
|
};
|
|
346
360
|
}
|
|
347
361
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
let class_cache = new Map(),
|
|
2
2
|
cache_stores_in_progress,
|
|
3
3
|
did_check = Symbol('did_check');
|
|
4
4
|
|
|
@@ -7,16 +7,11 @@ if (Blast.isBrowser) {
|
|
|
7
7
|
|
|
8
8
|
Blast.once('hawkejs_init', function gotScene(hawkejs, variables, settings, renderer) {
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
model_info = hawkejs.scene.exposed.model_info;
|
|
16
|
-
|
|
17
|
-
for (model_name in model_info) {
|
|
18
|
-
config = model_info[model_name];
|
|
19
|
-
DocClass = Document.getDocumentClass(model_name);
|
|
10
|
+
let DocClass,
|
|
11
|
+
config;
|
|
12
|
+
|
|
13
|
+
for (config of hawkejs.scene.exposed.model_info) {
|
|
14
|
+
DocClass = Document.getDocumentClass(config.name);
|
|
20
15
|
|
|
21
16
|
for (key in config.schema.dict) {
|
|
22
17
|
DocClass.setFieldGetter(key);
|
|
@@ -218,25 +213,18 @@ Document.setStatic(function getClassForUndry(class_name) {
|
|
|
218
213
|
*
|
|
219
214
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
220
215
|
* @since 1.0.0
|
|
221
|
-
* @version 1.1
|
|
216
|
+
* @version 1.3.1
|
|
222
217
|
*
|
|
223
218
|
* @param {Object|String} model
|
|
224
219
|
*/
|
|
225
220
|
Document.setStatic(function getDocumentClass(model) {
|
|
226
221
|
|
|
227
|
-
var doc_constructor,
|
|
228
|
-
document_name,
|
|
229
|
-
parent_path,
|
|
230
|
-
model_name,
|
|
231
|
-
DocClass,
|
|
232
|
-
doc_path,
|
|
233
|
-
config,
|
|
234
|
-
key;
|
|
235
|
-
|
|
236
222
|
if (!model) {
|
|
237
223
|
throw new Error('Can not get Hawkejs.Document class for non-existing model');
|
|
238
224
|
}
|
|
239
225
|
|
|
226
|
+
let model_name;
|
|
227
|
+
|
|
240
228
|
if (typeof model == 'function') {
|
|
241
229
|
model_name = model.name;
|
|
242
230
|
} else if (typeof model == 'string') {
|
|
@@ -246,26 +234,32 @@ Document.setStatic(function getDocumentClass(model) {
|
|
|
246
234
|
}
|
|
247
235
|
|
|
248
236
|
// Construct the name of the document class
|
|
249
|
-
document_name = model_name;
|
|
237
|
+
let document_name = model_name;
|
|
238
|
+
|
|
239
|
+
if (class_cache.has(document_name)) {
|
|
240
|
+
return class_cache.get(document_name);
|
|
241
|
+
}
|
|
250
242
|
|
|
251
243
|
// Construct the path to this class
|
|
252
|
-
doc_path = 'Alchemy.Client.Document.' + document_name;
|
|
244
|
+
let doc_path = 'Alchemy.Client.Document.' + document_name;
|
|
253
245
|
|
|
254
246
|
// Get the class
|
|
255
|
-
DocClass = Object.path(Blast.Classes, doc_path);
|
|
247
|
+
let DocClass = Object.path(Blast.Classes, doc_path);
|
|
256
248
|
|
|
257
249
|
if (DocClass == null) {
|
|
258
|
-
doc_constructor = Function.create(document_name, function DocumentConstructor(record, options) {
|
|
250
|
+
let doc_constructor = Function.create(document_name, function DocumentConstructor(record, options) {
|
|
259
251
|
DocumentConstructor.wrapper.super.call(this, record, options);
|
|
260
252
|
});
|
|
261
253
|
|
|
262
|
-
|
|
263
|
-
|
|
254
|
+
let parent,
|
|
255
|
+
config;
|
|
256
|
+
|
|
257
|
+
if (Blast.isBrowser) {
|
|
264
258
|
|
|
265
|
-
|
|
259
|
+
let model = Blast.Classes.Alchemy.Client.Model.Model.getClass(model_name);
|
|
266
260
|
|
|
267
|
-
if (
|
|
268
|
-
|
|
261
|
+
if (model && model.super) {
|
|
262
|
+
parent = model.super.name;
|
|
269
263
|
}
|
|
270
264
|
} else if (Blast.isNode) {
|
|
271
265
|
config = alchemy.getModel(model_name, false);
|
|
@@ -277,13 +271,17 @@ Document.setStatic(function getDocumentClass(model) {
|
|
|
277
271
|
}
|
|
278
272
|
}
|
|
279
273
|
|
|
280
|
-
parent_path = 'Alchemy.Client.Document';
|
|
274
|
+
let parent_path = 'Alchemy.Client.Document';
|
|
281
275
|
|
|
282
276
|
if (config && config.parent) {
|
|
277
|
+
parent = config.parent;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (parent && parent != 'Model') {
|
|
283
281
|
// Make sure the parent class exists
|
|
284
|
-
getDocumentClass(
|
|
282
|
+
getDocumentClass(parent);
|
|
285
283
|
|
|
286
|
-
parent_path += '.' +
|
|
284
|
+
parent_path += '.' + parent;
|
|
287
285
|
}
|
|
288
286
|
|
|
289
287
|
DocClass = Function.inherits(parent_path, doc_constructor);
|
|
@@ -297,6 +295,8 @@ Document.setStatic(function getDocumentClass(model) {
|
|
|
297
295
|
DocClass.Model = Blast.Classes.Hawkejs.Model.getClass(model_name);
|
|
298
296
|
}
|
|
299
297
|
|
|
298
|
+
class_cache.set(document_name, DocClass);
|
|
299
|
+
|
|
300
300
|
return DocClass;
|
|
301
301
|
});
|
|
302
302
|
|
|
@@ -1068,12 +1068,16 @@ Document.setMethod(function informDatasource(options, callback) {
|
|
|
1068
1068
|
/**
|
|
1069
1069
|
* Store the current data as the original record
|
|
1070
1070
|
*
|
|
1071
|
-
* @author Jelle De Loecker <jelle@
|
|
1071
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1072
1072
|
* @since 1.0.4
|
|
1073
|
-
* @version 1.
|
|
1073
|
+
* @version 1.3.1
|
|
1074
1074
|
*/
|
|
1075
1075
|
Document.setMethod(function storeCurrentDataAsOriginalRecord() {
|
|
1076
|
-
|
|
1076
|
+
try {
|
|
1077
|
+
this.$attributes.original_record = JSON.clone(this.$main);
|
|
1078
|
+
} catch (err) {
|
|
1079
|
+
alchemy.distinctProblem('store_current_data_error', err.message, {error: err});
|
|
1080
|
+
}
|
|
1077
1081
|
});
|
|
1078
1082
|
|
|
1079
1083
|
/**
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
let class_cache = new Map(),
|
|
2
|
+
fallback_datasource,
|
|
3
3
|
TABLE = Symbol('table');
|
|
4
4
|
|
|
5
5
|
if (Blast.isBrowser) {
|
|
6
6
|
Blast.once('hawkejs_init', function gotScene(hawkejs, variables, settings, view) {
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
model_name,
|
|
10
|
-
config,
|
|
11
|
-
key;
|
|
12
|
-
|
|
13
|
-
model_info = hawkejs.scene.exposed.model_info;
|
|
8
|
+
let config;
|
|
14
9
|
|
|
15
|
-
for (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
config.
|
|
10
|
+
for (config of hawkejs.scene.exposed.model_info) {
|
|
11
|
+
// First get or create the client-side Model class,
|
|
12
|
+
// then set some extra configuration coming from the server-side
|
|
13
|
+
Model.getClass(config.name).setModelConfig(config);
|
|
19
14
|
}
|
|
20
15
|
});
|
|
21
16
|
}
|
|
@@ -90,6 +85,30 @@ Model.setStatic(function hasServerAction(action) {
|
|
|
90
85
|
return !!config;
|
|
91
86
|
});
|
|
92
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Set the Model configuration
|
|
90
|
+
*
|
|
91
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
92
|
+
* @since 1.3.1
|
|
93
|
+
* @version 1.3.1
|
|
94
|
+
*
|
|
95
|
+
* @param {Object} config
|
|
96
|
+
*/
|
|
97
|
+
Model.setStatic(function setModelConfig(config) {
|
|
98
|
+
|
|
99
|
+
let model_name = this.model_name;
|
|
100
|
+
|
|
101
|
+
config.schema.setModel(model_name);
|
|
102
|
+
|
|
103
|
+
if (!this.prototype.hasOwnProperty('primary_key')) {
|
|
104
|
+
this.setProperty('primary_key', config.primary_key);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!this.prototype.hasOwnProperty('display_field')) {
|
|
108
|
+
this.setProperty('display_field', config.display_field);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
93
112
|
/**
|
|
94
113
|
* Table name to use in the database.
|
|
95
114
|
* False if no table should be used.
|
|
@@ -201,50 +220,43 @@ Model.prepareStaticProperty('Document', function getDocumentClass() {
|
|
|
201
220
|
*
|
|
202
221
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
203
222
|
* @since 1.0.0
|
|
204
|
-
* @version 1.
|
|
223
|
+
* @version 1.3.1
|
|
205
224
|
*
|
|
206
225
|
* @param {String} model_name
|
|
207
226
|
* @param {Boolean} allow_create
|
|
227
|
+
* @param {String} parent
|
|
208
228
|
*/
|
|
209
|
-
Model.setStatic(function getClass(model_name, allow_create ) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
class_path,
|
|
215
|
-
ModelClass,
|
|
216
|
-
config,
|
|
217
|
-
key;
|
|
229
|
+
Model.setStatic(function getClass(model_name, allow_create, parent) {
|
|
230
|
+
|
|
231
|
+
if (class_cache.has(model_name)) {
|
|
232
|
+
return class_cache.get(model_name);
|
|
233
|
+
}
|
|
218
234
|
|
|
219
235
|
// Construct the name of the class
|
|
220
|
-
class_name = model_name;
|
|
236
|
+
let class_name = model_name;
|
|
221
237
|
|
|
222
238
|
// Construct the path to this class
|
|
223
|
-
class_path = 'Alchemy.Client.Model.' + class_name;
|
|
239
|
+
let class_path = 'Alchemy.Client.Model.' + class_name;
|
|
224
240
|
|
|
225
241
|
// Get the class
|
|
226
|
-
ModelClass = Object.path(Blast.Classes, class_path);
|
|
242
|
+
let ModelClass = Object.path(Blast.Classes, class_path);
|
|
227
243
|
|
|
228
244
|
if (allow_create == null) {
|
|
229
245
|
allow_create = true;
|
|
230
246
|
}
|
|
231
247
|
|
|
232
248
|
if (ModelClass == null && allow_create) {
|
|
233
|
-
|
|
249
|
+
let config;
|
|
250
|
+
|
|
251
|
+
let model_constructor = Function.create(class_name, function ModelConstructor(record, options) {
|
|
234
252
|
ModelConstructor.wrapper.super.call(this, record, options);
|
|
235
253
|
});
|
|
236
254
|
|
|
237
255
|
// @TODO: inherit from parents
|
|
238
|
-
parent_path = 'Alchemy.Client.Model';
|
|
239
|
-
|
|
240
|
-
if (Blast.isBrowser && window._hawkejs_static_expose) {
|
|
241
|
-
let exposed = window._hawkejs_static_expose;
|
|
242
|
-
|
|
243
|
-
config = exposed.model_info;
|
|
256
|
+
let parent_path = 'Alchemy.Client.Model';
|
|
244
257
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
258
|
+
if (Blast.isBrowser) {
|
|
259
|
+
// No longer needed
|
|
248
260
|
} else if (Blast.isNode) {
|
|
249
261
|
config = alchemy.getModel(model_name, false);
|
|
250
262
|
|
|
@@ -258,8 +270,12 @@ Model.setStatic(function getClass(model_name, allow_create ) {
|
|
|
258
270
|
}
|
|
259
271
|
|
|
260
272
|
if (config && config.parent) {
|
|
261
|
-
|
|
262
|
-
|
|
273
|
+
parent = config.parent;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (parent) {
|
|
277
|
+
getClass(parent);
|
|
278
|
+
parent_path += '.' + parent;
|
|
263
279
|
}
|
|
264
280
|
|
|
265
281
|
ModelClass = Function.inherits(parent_path, model_constructor);
|
|
@@ -281,6 +297,8 @@ Model.setStatic(function getClass(model_name, allow_create ) {
|
|
|
281
297
|
}
|
|
282
298
|
}
|
|
283
299
|
|
|
300
|
+
class_cache.set(model_name, ModelClass);
|
|
301
|
+
|
|
284
302
|
return ModelClass;
|
|
285
303
|
});
|
|
286
304
|
|
|
@@ -1502,11 +1520,14 @@ Model.setProperty(function model_info() {
|
|
|
1502
1520
|
return {};
|
|
1503
1521
|
}
|
|
1504
1522
|
|
|
1505
|
-
|
|
1506
|
-
hawkejs.scene.exposed.model_info[name] = {};
|
|
1507
|
-
}
|
|
1523
|
+
let config;
|
|
1508
1524
|
|
|
1509
|
-
|
|
1525
|
+
for (config of hawkejs.scene.exposed.model_info) {
|
|
1526
|
+
if (config.name === name) {
|
|
1527
|
+
data = config;
|
|
1528
|
+
break;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1510
1531
|
} else {
|
|
1511
1532
|
|
|
1512
1533
|
let MainClass = Blast.Classes.Alchemy.Model[name];
|
|
@@ -1724,7 +1745,7 @@ Model.setMethod(function compose(data, options) {
|
|
|
1724
1745
|
*
|
|
1725
1746
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1726
1747
|
* @since 0.2.0
|
|
1727
|
-
* @version 1.
|
|
1748
|
+
* @version 1.3.1
|
|
1728
1749
|
*
|
|
1729
1750
|
* @param {Object} data The record data to check
|
|
1730
1751
|
* @param {Object} options
|
|
@@ -1750,6 +1771,10 @@ Model.setMethod(function createRecord(data, options, callback) {
|
|
|
1750
1771
|
return callback(err);
|
|
1751
1772
|
}
|
|
1752
1773
|
|
|
1774
|
+
if (!that.datasource) {
|
|
1775
|
+
return callback(new Error('Model "' + that.model_name + '" has no datasource'));
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1753
1778
|
that.datasource.create(that, data, options, function afterCreate(err, result) {
|
|
1754
1779
|
|
|
1755
1780
|
if (err != null) {
|
|
@@ -1768,7 +1793,7 @@ Model.setMethod(function createRecord(data, options, callback) {
|
|
|
1768
1793
|
*
|
|
1769
1794
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1770
1795
|
* @since 0.2.0
|
|
1771
|
-
* @version 1.
|
|
1796
|
+
* @version 1.3.1
|
|
1772
1797
|
*
|
|
1773
1798
|
* @param {Object} data The record data to check
|
|
1774
1799
|
* @param {Object} options
|
|
@@ -1795,6 +1820,10 @@ Model.setMethod(function updateRecord(data, options, callback) {
|
|
|
1795
1820
|
return callback(err);
|
|
1796
1821
|
}
|
|
1797
1822
|
|
|
1823
|
+
if (!that.datasource) {
|
|
1824
|
+
return callback(new Error('Model "' + that.model_name + '" has no datasource'));
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1798
1827
|
that.datasource.update(that, data, options, function afterUpdate(err, result) {
|
|
1799
1828
|
|
|
1800
1829
|
if (err != null) {
|