Skip to content

Commit

Permalink
♻️ Add namespace support to models
Browse files Browse the repository at this point in the history
  • Loading branch information
skerit committed Jan 29, 2024
1 parent 56565cf commit 66810cb
Show file tree
Hide file tree
Showing 24 changed files with 342 additions and 300 deletions.
14 changes: 10 additions & 4 deletions lib/app/helper_field/schema_field.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ SchemaField.setMethod(function _toDatasourceFromValue(value, holder, datasource,
*
* @author Jelle De Loecker <[email protected]>
* @since 0.2.0
* @version 1.3.16
* @version 1.4.0
*
* @param {Mixed} value
* @param {Function} callback
Expand All @@ -388,15 +388,21 @@ SchemaField.setMethod(function _toApp(query, options, value, callback) {
});
}

Function.parallel(tasks, (err, result) => {
Pledge.Swift.all(tasks).done((err, result) => {

if (err) {
return callback(err);
}

callback(null, this.cast(result));
});
try {
result = this.cast(result)
} catch (err) {
callback(err);
return;
}

callback(null, result);
});
});

/**
Expand Down
42 changes: 25 additions & 17 deletions lib/app/helper_model/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if (Blast.isBrowser) {
key;

for (config of hawkejs.scene.exposed.model_info) {
DocClass = Document.getDocumentClass(config.name);
DocClass = Document.getDocumentClass(config.model_name);

for (key in config.schema.dict) {
DocClass.setFieldGetter(key);
Expand Down Expand Up @@ -240,35 +240,43 @@ Document.setStatic(function getClassForUndry(class_name) {
*
* @author Jelle De Loecker <[email protected]>
* @since 1.0.0
* @version 1.3.1
* @version 1.4.0
*
* @param {Object|string} model
* @param {Function|Object|string} model_param
*/
Document.setStatic(function getDocumentClass(model) {
Document.setStatic(function getDocumentClass(model_param) {

if (!model) {
if (!model_param) {
throw new Error('Can not get Hawkejs.Document class for non-existing model');
}

let model_name;
let model = typeof model_param == 'function' ? model_param : alchemy.getModel(model_param, false);

if (typeof model == 'function') {
model_name = model.name;
} else if (typeof model == 'string') {
model_name = model;
} else {
model_name = model.model_name;
if (!model) {
throw new Error('There is no model named "' + model_param + '"');
}

// Construct the name of the document class
let document_name = model_name;
if (model.is_namespace) {
return;
}

if (class_cache.has(document_name)) {
return class_cache.get(document_name);
let model_name = model.model_name;

if (class_cache.has(model_name)) {
return class_cache.get(model_name);
}

// Construct the name of the document class constructor
let document_name = model.name;

// Construct the path to this class
let doc_path = 'Alchemy.Client.Document.' + document_name;
let doc_path = 'Alchemy.Client.Document.';

if (model.model_namespace) {
doc_path += model.model_namespace + '.';
}

doc_path += document_name;

// Get the class
let DocClass = Object.path(Blast.Classes, doc_path);
Expand Down
2 changes: 1 addition & 1 deletion lib/app/helper_model/field_set.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const FieldSet = Fn.inherits('Alchemy.Base', 'Alchemy.Criteria', function FieldS
this.name = name;

if (typeof model == 'function') {
model = model.name;
model = model.model_name;
}

this.model = model;
Expand Down
120 changes: 82 additions & 38 deletions lib/app/helper_model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (Blast.isBrowser) {
for (config of hawkejs.scene.exposed.model_info) {
// First get or create the client-side Model class,
// then set some extra configuration coming from the server-side
Model.getClass(config.name).setModelConfig(config);
Model.getClass(config.model_name).setModelConfig(config);
}
});
}
Expand All @@ -36,12 +36,44 @@ const Model = Function.inherits('Alchemy.Client.Base', 'Alchemy.Client.Model', f
*
* @author Jelle De Loecker <[email protected]>
* @since 1.1.0
* @version 1.1.0
* @version 1.4.0
*/
Model.constitute(function setModelName() {
this.model_name = this.name;
this.setProperty('model_name', this.model_name);
this.table = this.model_name.tableize();
Model.postInherit(function setModelName() {

let base_name = this.name;
let model_name = base_name;
let table_prefix = this.table_prefix;
let namespace = this.namespace;

if (namespace.startsWith('Alchemy.Model.') || namespace == 'Alchemy.Model') {
namespace = namespace.slice(14);
} else if (namespace.startsWith('Alchemy.Client.Model.') || namespace == 'Alchemy.Client.Model') {
namespace = namespace.slice(21);
}

this.setStatic('model_namespace', namespace, false);

let ns = namespace.replaceAll('.', '_');

if (!table_prefix && ns) {
table_prefix = ns.tableize();
}

if (ns) {
model_name = ns + '_' + model_name;
}

// The simple name of the model
this.model_name = model_name;
this.setProperty('model_name', model_name);

let table_name = base_name.tableize();

if (table_prefix) {
table_name = table_prefix + '_' + table_name;
}

this.table = table_name;
});

/**
Expand Down Expand Up @@ -221,23 +253,34 @@ Model.prepareStaticProperty('Document', function getDocumentClass() {
*
* @author Jelle De Loecker <[email protected]>
* @since 1.0.0
* @version 1.3.1
* @version 1.4.0
*
* @param {string} model_name
* @param {boolean} allow_create
* @param {string} parent
*/
Model.setStatic(function getClass(model_name, allow_create, parent) {

if (class_cache.has(model_name)) {
return class_cache.get(model_name);
let cache_key = model_name;

if (class_cache.has(cache_key)) {
return class_cache.get(cache_key);
}

// Get the model path as an array
let model_path = Blast.parseClassPath(model_name);

// Ensure it is the correct model_name
model_name = model_path.join('_');

// Construct the name of the class
let class_name = model_name;
let class_name = model_path.last();

// Construct the path to this class
let class_path = 'Alchemy.Client.Model.' + class_name;
// The root path
const root_path = 'Alchemy.Client.Model';

// Construct the expected path to this class
let class_path = root_path + '.' + model_path.join('.');

// Get the class
let ModelClass = Object.path(Blast.Classes, class_path);
Expand All @@ -247,39 +290,39 @@ Model.setStatic(function getClass(model_name, allow_create, parent) {
}

if (ModelClass == null && allow_create) {
let config;

let namespace = root_path,
config;

if (model_path.length > 1) {
namespace += '.' + model_path.slice(0, -1).join('.');
}

let model_constructor = Function.create(class_name, function ModelConstructor(record, options) {
ModelConstructor.wrapper.super.call(this, record, options);
});

// @TODO: inherit from parents
let parent_path = 'Alchemy.Client.Model';

if (Blast.isBrowser) {
// No longer needed
} else if (Blast.isNode) {
config = alchemy.getModel(model_name, false);

if (config && config.super) {
config = {
parent : config.super.name,
primary_key : config.prototype.primary_key,
display_field : config.prototype.display_field,
};
if (parent) {
let parent_model_path = Blast.parseClassPath(parent);
parent = root_path + '.' + parent_model_path.join('.');
} else {
parent = root_path;
}
}

if (config && config.parent) {
parent = config.parent;
}
} else if (Blast.isNode) {
let server_class = alchemy.getModel(model_name, false);

if (parent) {
getClass(parent);
parent_path += '.' + parent;
parent = getClass(server_class.super.model_name);

config = {
primary_key : server_class.prototype.primary_key,
display_field : server_class.prototype.display_field,
};
}

ModelClass = Function.inherits(parent_path, model_constructor);
ModelClass = Function.inherits(parent, namespace, model_constructor);

ModelClass.setProperty('$model_name', model_name);

Expand All @@ -298,7 +341,7 @@ Model.setStatic(function getClass(model_name, allow_create, parent) {
}
}

class_cache.set(model_name, ModelClass);
class_cache.set(cache_key, ModelClass);

return ModelClass;
});
Expand Down Expand Up @@ -1560,7 +1603,8 @@ Model.setMethod(function hasServerAction(action) {
*/
Model.setProperty(function model_info() {

let name = this.constructor.name,
let class_name = this.constructor.name,
model_name = this.constructor.model_name,
data;

if (Blast.isBrowser) {
Expand All @@ -1573,17 +1617,17 @@ Model.setProperty(function model_info() {
let config;

for (config of hawkejs.scene.exposed.model_info) {
if (config.name === name) {
if (config.model_name === model_name) {
data = config;
break;
}
}
} else {

let MainClass = Blast.Classes.Alchemy.Model[name];
let MainClass = Blast.Classes.Alchemy.Model.Model.get(model_name, false);

if (!MainClass) {
throw new Error('Unable to find main class for "' + name + '", unable to get client config!');
throw new Error('Unable to find main class for "' + model_name + '", unable to get client config!');
}

data = MainClass.getClientConfig();
Expand Down
27 changes: 27 additions & 0 deletions lib/app/model/05-system_model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* The base System model class.
* Models meant for the Alchemy system.
*
* @author Jelle De Loecker <[email protected]>
* @since 1.4.0
* @version 1.4.0
*/
const System = Function.inherits('Alchemy.Model.App', 'Alchemy.Model.System', 'System');

/**
* Mark this class as being abstract
*
* @author Jelle De Loecker <[email protected]>
* @since 1.4.0
* @version 1.4.0
*/
System.makeAbstractClass();

/**
* Use the `alchemy` prefix for the table name
*
* @author Jelle De Loecker <[email protected]>
* @since 1.4.0
* @version 1.4.0
*/
System.setTablePrefix('alchemy');
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @since 1.2.0
* @version 1.2.0
*/
const AlchemyMigration = Function.inherits('Alchemy.Model.App', 'AlchemyMigration');
const Migration = Function.inherits('Alchemy.Model.System', 'Migration');

/**
* Constitute the class wide schema
Expand All @@ -16,7 +16,7 @@ const AlchemyMigration = Function.inherits('Alchemy.Model.App', 'AlchemyMigratio
* @since 1.2.0
* @version 1.2.0
*/
AlchemyMigration.constitute(function addTaskFields() {
Migration.constitute(function addTaskFields() {

// The name of the migration
this.addField('name', 'String');
Expand Down
Loading

0 comments on commit 66810cb

Please sign in to comment.