cmsmon
Version:
342 lines (312 loc) • 9.41 kB
JavaScript
;
const _ = require('lodash');
global['_'] = _;
const JsonFn = require('json-fn');
global['JsonFn'] = JsonFn;
const express = require('express');
const _app = express();
const router = express.Router();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const restify = require('express-restify-mongoose');
const Q = require('q');
const session = require('express-session');
const Reflect = require('harmony-reflect');
require('generator-bind').polyfill();
const jade = require('jade');
const NodeCache = require("node-cache");
const fs = require('fs');
const cache = new NodeCache({useClones: false, stdTTL: 20 * 60});
const ngcompile = require('../lib/ng.compile');
const Path = require('path');
const deasync = require('deasync');
const co = require('co');
const request = require('request');
const server = require('http').Server(_app);
const _io = require('socket.io')(server);
var download = function (uri, filename, callback) {
request.head(uri, function (err, res, body) {
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
const app = new Proxy(_app, {
get(target, key) {
if (['get', 'post', 'put', 'patch', 'delete'].indexOf(key) !== -1) {
return function () {
if (arguments[1] && arguments[1].constructor && arguments[1].constructor.name === 'GeneratorFunction') {
const cb = arguments[1];
const callback = function (req, res) {
/*Q.onerror = onerror.bind(onerror, req, res);
Q.spawn(cb.bind(this, ...arguments));*/
co(cb.bind(this, ...arguments)).then(() => {
}, onerror.bind(onerror, req, res));
};
arguments[1] = callback;
}
target[key](...arguments);
};
}
return target[key];
}
});
let io = new Proxy(_io, {
get(target, key) {
if (key === 'on') {
return function () {
const _fn = arguments[1];
if (_fn && _fn.constructor) {
const fn = function (socket) {
const _on = socket.on;
socket.on = function (path, cb) {
if (cb && cb.constructor && cb.constructor.name === 'GeneratorFunction') {
const callback = function (msg) {
try {
let json = JsonFn.parse(msg, true);
co(cb.bind(this, json)).then(() => {
}, e => {
console.warn(e);
});
} catch (e) {
co(cb.bind(this, msg)).then(() => {
}, e => {
console.warn(e);
});
}
};
_on.bind(socket)(path, callback);
} else {
_on.bind(socket)(path, cb);
}
}
const _emit = socket.emit;
socket.emit = function (name, result) {
console.time("send");
if (typeof result === 'string') {
_emit.bind(socket)(name, result);
} else {
_emit.bind(socket)(name, JsonFn.stringify(result));
}
}
_fn.bind(this)(socket);
}
arguments[1] = fn;
target[key](...arguments);
}
};
}
return target[key];
}
});
app.use(session({
secret: 'best cms system',
resave: false, saveUninitialized: true,
cookie: {maxAge: 2628000000},
expires: 30 * 24 * 60 * 60 * 1000
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(require('method-override')());
const CMS_KEY = Symbol("CMS");
const menu = {
top: '51px',
bodyPaddingTop: '51px',
inverse: false
}
const WebType = {APPLICATION: 'APPLICATION', WEB: 'WEB'};
// todo : use class for cms
const cms = {
io,
readFile,
download,
compile,
compiler,
/**
* type: NodeCache
* format: `${prefix}:path`
* prefix can be 'file', 'jade', 'static'...
* e.g. : 'file:/base/index.json'
*/
cache,
clearCache,
/**
* contain all important data
*/
data: {
// ng environment filter
basePath: '',
baseUrlPath: '',
ngEn: [],
errors: {},
handlers: [],
baseTemplatePath: '',
security: true,
/**
* array from page formatter
* format: [{name,path}]
* e.g. [{path:'page/main.jade', name:'main page'}]
*/
pageFormatter: [],
/**
* array from category , use to group elements
* format: [Object]
* e.g. [{Type:{Clothes:'',Food:''}}]
*/
categories: {},
online: {
menu,
autoOpenAdmin: false
},
webtype: WebType.WEB
},
filters: {
element: [],
/*
element's type : function ($, content){}
*/
page: [],
/**
* fn (schema,name)
*/
schema: [],
/**
* cms.filters.form[name](Form => {})
*/
form: {},
/**
* array of function (function(field,{key,label}) {})
*/
field: [],
fn: {},
serverFn: {}
},
utils: {},
express,
ews: null,
app,
mongoose,
routers: {},
restify,
Types: {},
getPath: p => p,
use: fn => fn(cms),
listen,
Q,
serverFn: {},
fn: {},
Enum: {
Load: {NOT: 'NOT', LOADING: 'LOADING', LOADED: 'LOADED'},
Mode: {
ADMIN: 'ADMIN',
NORMAL: 'NORMAL'
},
WebType
},
get instance() {
return global[CMS_KEY];
},
set menu(menu) {
_.assign(this.data.online.menu, menu);
},
async,
getModel: function (type) {
return this.Types[type].Model;
}
}
global[CMS_KEY] = cms;
ngcompile.prototype.onEnvReady(() => {
cms.ng = new ngcompile([
{name: 'ui.bootstrap', path: 'node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js'}
], null, null, (ng) => {
cms.data.ngEn.forEach(fn => fn(ng));
});
});
function onerror(req, res, e) {
if (e.handler) return e.handler(req, res);
cms.data.handlers.forEach(handler => handler(req, res, e));
}
/**
*
* @param mongoose
* @param app
* @returns cms;
*/
module.exports = cms;
function listen() {
cms.use(require('./form'));
cms.use(require('./query'));
cms.use(require('./angular_resolve'));
cms.use(require('./types'));
cms.use(require('./types.builder'));
//cms.use(require('./wrapper'));
cms.use(require('./container'));
if (cms.data.security) cms.use(require('./user'));
cms.use(require('./admin'));
cms.use(require('./category'));
cms.use(require('./element.filter'));
cms.use(require('./error.handler'));
cms.use(require('./utils'));
cms.use(require('./serverFn'));
cms.use(require('./config'));
_.each(cms.routers, r => app.use(r));
//app.listen(...arguments);
server.listen(...arguments);
}
/**
*
* @param path
* @param [options]
* @param {Function} options.compiler
* @returns {Choice|Undefined}
*/
function compile(path, options = {}) {
const _compiler = options.compiler;
let fn = cms.cache.get(`template:${path}`);
if (!fn) {
fn = _compiler ? _compiler(path) : compiler(path);
cms.cache.set(`template:${path}`, fn);
}
return fn;
}
function compiler(path) {
if (path.split('\.').pop() === 'jade') {
return jade.compileFile(path);
}
try {
return function () {
return this.content;
}.bind({content: fs.readFileSync(path, 'utf8')})
} catch (e) {
}
}
/**
* use to readFile first from cache
* @param path
* @returns {Choice|Undefined}
*/
function readFile(path) {
let result = cms.cache.get(`file:${path}`);
if (!result) {
result = fs.readFileSync(path, 'utf8');
cms.cache.set(`file:${path}`, result);
}
return result;
}
function clearCache() {
cms.cache.del(cms.cache.keys());
}
function async(fn) {
function _async(fn, _this) {
let result = false, done = false;
co(fn.bind(_this)).then((_result) => {
result = _result;
done = true;
}, () => done = true);
deasync.loopWhile(() => !done);
return result;
}
return function () {
return _async(fn, this);
}
}