139 lines
3.9 KiB
JavaScript
139 lines
3.9 KiB
JavaScript
var fs = require('fs')
|
|
, DataSource = require('./datasource').DataSource;
|
|
|
|
// Built-in data types
|
|
var builtinTypes = {
|
|
'string': String,
|
|
'number': Number,
|
|
'date': Date,
|
|
'buffer': Buffer,
|
|
'binary': Buffer,
|
|
'boolean': Boolean,
|
|
'any': DataSource.Any,
|
|
'array': Array
|
|
}
|
|
|
|
/**
|
|
* Resolve the type string to be a function, for example, 'String' to String
|
|
* @param type The type string, such as 'number', 'Number', 'boolean', or 'String'. It's case insensitive
|
|
* @returns {Function} if the type is resolved
|
|
*/
|
|
function getSchemaType(type) {
|
|
if (!type) {
|
|
return type;
|
|
}
|
|
if (Array.isArray(type) && type.length > 0) {
|
|
// For array types, the first item should be the type string
|
|
var itemType = getSchemaType(type[0]);
|
|
if (typeof itemType === 'function') {
|
|
return [itemType];
|
|
}
|
|
else return itemType; // Not resolved, return the type string
|
|
}
|
|
if (typeof type === 'string') {
|
|
var schemaType = builtinTypes[type.toLowerCase()];
|
|
if (schemaType) {
|
|
return schemaType;
|
|
} else {
|
|
return type;
|
|
}
|
|
} else if (type.constructor.name == 'Object') {
|
|
// We also support the syntax {type: 'string', ...}
|
|
if (type.type) {
|
|
return getSchemaType(type.type);
|
|
} else {
|
|
throw new Error('Missing type property');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build a schema
|
|
* @param name The name of the schema
|
|
* @param properties The properties of the schema
|
|
* @param associations An array of associations between models
|
|
* @returns {*}
|
|
*/
|
|
function buildSchema(name, properties, associations) {
|
|
for (var p in properties) {
|
|
// console.log(name + "." + p + ": " + properties[p]);
|
|
var type = getSchemaType(properties[p]);
|
|
if (typeof type === 'string') {
|
|
// console.log('Association: ' + type);
|
|
associations.push({
|
|
source: name,
|
|
target: type,
|
|
relation: Array.isArray(properties[p]) ? 'hasMany' : 'belongsTo',
|
|
as: p
|
|
});
|
|
delete properties[p];
|
|
} else {
|
|
properties[p] = type;
|
|
}
|
|
}
|
|
return properties;
|
|
}
|
|
|
|
|
|
/**
|
|
* Load ADL schemas from a json doc
|
|
* @param schemaFile The schema json file
|
|
* @returns A map of schemas keyed by name
|
|
*/
|
|
function loadSchemasSync(schemaFile, dataSource) {
|
|
// Set up the data source
|
|
if(!dataSource) {
|
|
dataSource = new DataSource('memory');
|
|
}
|
|
|
|
// Read the schema JSON file
|
|
var schemas = JSON.parse(fs.readFileSync(schemaFile));
|
|
|
|
return parseSchemas(dataSource, schemas);
|
|
|
|
}
|
|
|
|
function parseSchemas(dataSource, schemas) {
|
|
var models = {};
|
|
|
|
if (Array.isArray(schemas)) {
|
|
// An array already
|
|
} else if (schemas.properties && schemas.name) {
|
|
// Only one item
|
|
schemas = [schemas];
|
|
} else {
|
|
// Anonymous schema
|
|
schemas = [
|
|
{
|
|
name: 'Anonymous',
|
|
properties: schemas
|
|
}
|
|
];
|
|
}
|
|
|
|
var associations = [];
|
|
for (var s in schemas) {
|
|
var name = schemas[s].name;
|
|
// console.log('Loading ' + name);
|
|
var jdbSchema = buildSchema(name, schemas[s].properties, associations);
|
|
// console.dir(jdbSchema);
|
|
var model = dataSource.define(name, jdbSchema);
|
|
console.dir(model);
|
|
models[name.toLowerCase()] = model;
|
|
}
|
|
|
|
// Connect the models based on the associations
|
|
for (var i = 0; i < associations.length; i++) {
|
|
var association = associations[i];
|
|
var sourceModel = models[association.source.toLowerCase()];
|
|
var targetModel = models[association.target.toLowerCase()];
|
|
if (sourceModel && targetModel) {
|
|
sourceModel[association.relation](targetModel, {as: association.as});
|
|
}
|
|
}
|
|
return models;
|
|
}
|
|
|
|
exports.loadSchemasSync = loadSchemasSync;
|
|
exports.parseSchemas = parseSchemas;
|