angie-orm
Version:
A Feature-Complete Database Relationship Manager Designed for NodeJS
142 lines (125 loc) • 4.61 kB
JavaScript
/**
* @module Angie.js
* @author Joe Groseclose <@benderTheCrime>
* @date 8/23/2015
*/
// System Modules
import util from 'util';
import {blue} from 'chalk';
import $LogProvider from 'angie-log';
// Angie ORM Modules
import BaseModel from './models/BaseModel';
import * as $$FieldProvider from './models/$Fields';
import {
$$InvalidModelConfigError
} from './util/$ExceptionsProvider';
// Setup the app or inherit the app from the `global` Namespace
const p = process;
let app;
if (global.app) {
app = global.app;
} else {
app = global.app = {
services: {},
$$registry: {},
$$register(c, name, obj) {
// `component` and `app.component` should always be defined
if (name && obj) {
this.$$registry[ name ] = 'Models';
this.Models[ name ] = obj;
} else {
$LogProvider.warn(
'Invalid name or object called on app.$register'
);
}
return this;
},
$$load() {
const fs = require('fs');
// Do not call load twice
if (this.$$loaded === true) {
return new Promise((r) => { r(); });
}
let me = this;
return new Promise(function(resolve) {
let files = [];
// Find ALL the files
try {
files = files.concat(fs.readdirSync(
`${p.cwd()}/src`
).map((v) => `${p.cwd()}/src/${v}`));
} catch(e) {}
try {
files = files.concat(fs.readdirSync(
`${p.cwd()}/src/Models`
).map((v) => `${p.cwd()}/src/Models/${v}`));
} catch(e) {}
try {
files = files.concat(fs.readdirSync(
`${p.cwd()}/src/models`
).map((v) => `${p.cwd()}/src/models/${v}`));
} catch(e) {}
// Make sure the files are js/es6 files, then try to load them
files.filter(
(v) => [ 'js', 'es6' ].indexOf(v.split('.').pop()) > -1
).forEach(function(v) {
try {
require(v);
$LogProvider.info(`Successfully loaded file ${blue(v)}`);
} catch(e) {
$LogProvider.error(e);
}
});
// Set the app in a loaded state
me.$$loaded = true;
resolve();
});
},
$$loaded: false
};
app.$Fields = $$FieldProvider;
app.services.$Log = $LogProvider;
app.$$registry.$Log = 'services';
}
app.services.$Fields = $$FieldProvider;
app.$$registry.$Fields = 'services';
app.Models = {};
/**
* @desc Creates an Angie ORM Model provider. The second parameter
* of the Model function must be an object or a function/class which returns an
* object, with properties defining the Model itself (name, fields, etc). Note
* that the first bound paramter to the second argument will always be $Fields
* if the second argument is a function.
* @since 0.0.1
* @access public
* @param {string} name The name of the constant being created
* @param {function|object} obj The Model value, returns Models params.
*/
app.Model = function Model(name, Obj = {}) {
let model = typeof Obj === 'function' ?
new Obj($$FieldProvider) :
typeof Obj === 'object' ? Obj : undefined;
model.name = model.name || name;
let instance = new BaseModel(model.name);
// Mock extend obj onto the instance
if (typeof model === 'object') {
instance = util._extend(instance, model);
} else {
throw new $$InvalidModelConfigError(name);
}
this.$$register('Models', model.name, instance);
// We need to account for whether this Model creates a m2m reference and
// create the reverse
for (let key in model) {
let field = model[ key ];
if (field.type && field.type === 'ManyToManyField') {
this.Models[ field.rel ][ field.name ] =
new $$FieldProvider.ManyToManyField(field.name, {
crossReferenceTableId: field.crossReferenceTableId,
crossReferenceTable: field.crossReferenceTable,
name: field.rel
});
}
}
return this;
};