Comparing version 1.0.2 to 2.0.0
@@ -1,13 +0,30 @@ | ||
var koa = require('koa'); | ||
var mvc = require('lark-mvc') | ||
var app = koa(); | ||
app.use(mvc.middleware({ | ||
'path': './models' | ||
})) | ||
.use(function *(next){ | ||
yield next; | ||
this.body = this.pageServices.demo.render() + | ||
this.pageServices.newlist.render() | ||
}) | ||
/** | ||
* Lark-mvc example raw use with Koa | ||
**/ | ||
'use strict'; | ||
import _debug from 'debug'; | ||
import Koa from 'koa'; | ||
import MVC from '..'; | ||
const debug = _debug('lark-mvc'); | ||
const app = new Koa(); | ||
debug("Example: create an instance of MVC, and save it"); | ||
const access = new MVC('models').saveInstance().access(); | ||
debug("Example: prepare koa app"); | ||
app.use(async (ctx, next) => { | ||
debug("Example: page.foo.execute without ctx"); | ||
try { | ||
ctx.body = await access.page.foo.execute(); | ||
} | ||
catch (e) { | ||
console.log(e.stack); | ||
} | ||
}); | ||
app.listen(3000); | ||
debug("Example: load!"); |
176
index.js
@@ -1,102 +0,108 @@ | ||
var path = require('path'); | ||
var rd = require('rd'); | ||
var layerproxy = require("./lib/layerproxy") | ||
/** | ||
* @param options | ||
* @param options.path {string} It locate to models, where files will automate load if its filetype is js. | ||
*/ | ||
* Lark-mvc | ||
**/ | ||
'use strict'; | ||
var larkMVC = function(options, lark){ | ||
if (!options || !options.path) { | ||
var _path = 'models' | ||
}else{ | ||
var _path = options.path | ||
} | ||
if (process.mainModule) { | ||
_path = path.join(path.dirname(process.mainModule.filename), _path); | ||
} | ||
if (_path[_path.length - 1] !== '/') { | ||
_path += '/'; | ||
} | ||
rd.eachFileFilterSync(_path, /\.js$/, function (file) { | ||
if (0 !== file.indexOf(_path)) { | ||
throw new Error("File path " + file + " not expected, should be under " + _path); | ||
} | ||
var filename = path.basename(file) | ||
if (filename && filename[0] === '.') { | ||
return; | ||
} | ||
var relativePath = file.slice(_path.length); | ||
var _pathsplit = relativePath.split('/'); | ||
if (_pathsplit.length <= 1) { | ||
throw new Error('Invalid model path : ' + _path); | ||
} | ||
var filename = _pathsplit[_pathsplit.length - 1]; | ||
_pathsplit[_pathsplit.length - 1] = path.basename(filename, path.extname(filename)); | ||
import _debug from 'debug'; | ||
import path from 'path'; | ||
import savable from 'save-instance'; | ||
import Layer from './lib/layer'; | ||
import Service from './lib/service'; | ||
import defaultConfig from './conf/default'; | ||
var modelproxy = createModel(layerproxy, _pathsplit, null, options); | ||
if (!modelproxy) { | ||
return; | ||
} | ||
const debug = _debug("lark-mvc"); | ||
var model; | ||
try { | ||
model = require(file); | ||
class MVC extends Layer { | ||
constructor (modelPath, options = defaultConfig) { | ||
debug("MVC: constructing"); | ||
if (!modelPath || 'string' !== typeof modelPath) { | ||
modelPath = 'models'; | ||
} | ||
catch (e) { | ||
console.log('Lark-MVC loading model ' + file + ' failed, skip...'); | ||
return; | ||
if (!path.isAbsolute(modelPath)) { | ||
modelPath = path.join(path.dirname(process.mainModule.filename), modelPath); | ||
} | ||
if (model instanceof Function) { | ||
return model(layerproxy, lark); | ||
super({}); | ||
debug("MVC: loading models"); | ||
this._layers = {}; | ||
const entrylayers = {}; | ||
for (const layername in options) { | ||
const dirname = path.join(modelPath, options[layername].path || ''); | ||
debug("MVC: layer " + layername + ", path is " + dirname); | ||
for (const _layername in this._layers) { | ||
const layer = this._layers[_layername]; | ||
const layerPath = layer.path; | ||
if (!layerPath) { | ||
continue; | ||
} | ||
if (layerPath.indexOf(dirname) === 0 || dirname.indexOf(layerPath) === 0) { | ||
throw new Error("Can not add layer with path " + dirname + ", conflict with " + layerPath); | ||
} | ||
} | ||
debug("MVC: creating layer " + layername); | ||
this._layers[layername] = new Layer(this); | ||
entrylayers[layername] = this._layers[layername]; | ||
debug("MVC: loading directory " + dirname); | ||
this._layers[layername].load(dirname); | ||
} | ||
else if (model instanceof Object && !Array.isArray(model)) { | ||
for (var property in model) { | ||
if (!!modelproxy[property]) { | ||
throw new Error('Property ' + property + ' in mvc.xxx in use!'); | ||
debug("MVC: add access to each layer"); | ||
for (const layername in options) { | ||
debug("MVC: adding access layers to " + layername); | ||
const layer = this._layers[layername]; | ||
let accessList = options[layername].access; | ||
if (!Array.isArray(accessList)) { | ||
accessList = [accessList]; | ||
} | ||
for (const accessLayername of accessList) { | ||
if ('string' !== typeof accessLayername) { | ||
continue; | ||
} | ||
modelproxy[property] = model[property]; | ||
debug("MVC: adding access layer " + accessLayername + " to " + layername); | ||
layer.addAccessLayer(accessLayername, this._layers[accessLayername]); | ||
delete entrylayers[accessLayername]; | ||
} | ||
} | ||
}); | ||
return function*(next) { | ||
this.pageServices = layerproxy.pageServices | ||
yield next | ||
}; | ||
} | ||
function createModel (layerproxy, _pathsplit, type, options) { | ||
var type = type || _pathsplit.shift(); | ||
if (options && options.ignore) { | ||
if (!Array.isArray(options.ignore)) { | ||
options.ignore = [options.ignore]; | ||
debug("MVC: adding entry access layers"); | ||
for (const layername in entrylayers) { | ||
debug("MVC: adding access layer " + layername + " to entry layer"); | ||
const layer = this._layers[layername]; | ||
this.addAccessLayer(layername, layer); | ||
} | ||
for (var i = 0; i < options.ignore.length; i++) { | ||
var ignore = options.ignore[i]; | ||
if (_pathsplit.indexOf(ignore) >=0) { | ||
return; | ||
} | ||
access () { | ||
return this._accessWithPath(); | ||
} | ||
_accessWithPath (modulePath) { | ||
debug("MVC: access"); | ||
this._accessed = this._accessed || {}; | ||
modulePath = modulePath || this._currentModulePath || null; | ||
debug("MVC: caller is " + modulePath); | ||
if (!modulePath) { | ||
return super.access(); | ||
} | ||
if (this._accessed[modulePath]) { | ||
debug("MVC: using cache"); | ||
return this._accessed[modulePath]; | ||
} | ||
for (const layername in this._layers) { | ||
const layer = this._layers[layername]; | ||
const dirname = layer.path; | ||
if (!dirname) { | ||
continue; | ||
} | ||
if (modulePath.indexOf(dirname) === 0) { | ||
debug("MVC: layer found"); | ||
this._accessed[modulePath] = layer.access(); | ||
return layer.access(); | ||
} | ||
} | ||
debug("MVC: no layer found, use entry layer"); | ||
return super.access(); | ||
} | ||
var name = _pathsplit.join('/'); | ||
switch (type) { | ||
case 'dao' : | ||
type = 'daoService'; | ||
break; | ||
case 'dataServices' : | ||
type = 'dataService'; | ||
break; | ||
case 'pageServices' : | ||
type = 'pageService'; | ||
break; | ||
default : | ||
throw new Error('Unknown model type ' + type); | ||
createService () { | ||
return new Service(this, this._currentModulePath); | ||
} | ||
return layerproxy[type].create(name); | ||
} | ||
savable(MVC); | ||
var output = layerproxy; | ||
output.middleware = larkMVC | ||
module.exports = output | ||
debug("MVC: load"); | ||
export default MVC; |
{ | ||
"name": "lark-mvc", | ||
"version": "1.0.2", | ||
"description": "MVC for building web server with lark.js", | ||
"main": "index.js", | ||
"directories": { | ||
"example": "examples", | ||
"test": "test" | ||
}, | ||
"scripts": { | ||
"test": "NODE_ENV=test ./node_modules/.bin/mocha --harmony --require should test/" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/larkjs/lark-mvc.git" | ||
}, | ||
"keywords": [ | ||
"lark.js", | ||
"koa" | ||
], | ||
"author": { | ||
"name": "lark.js Team" | ||
}, | ||
"license": "FreeBSD", | ||
"bugs": { | ||
"url": "https://github.com/larkjs/lark-mvc/issues" | ||
}, | ||
"dependencies": { | ||
"rd": "~0.0.2" | ||
}, | ||
"devDependencies": { | ||
"mocha": "^2.0.1", | ||
"should": "^4.4.1", | ||
"supertest": "^0.15.0" | ||
}, | ||
"homepage": "https://www.npmjs.com/package/lark-mvc", | ||
"readme": "MVC for building web server using lark.js\n\n [![NPM version][npm-image]][npm-url]\n [![build status][travis-image]][travis-url]\n\n## Features:\n\n * Seperate bussiness codes into `pageService`, `dataService` and `dao`, which accord to `MVC` concept. (`C`in `MVC` implements in `lark-router`).\n * Make calling rules between MVC layers.\n * Support hook between MVC layers.\n\n## Install:\n\n```\nnpm install lark-mvc\n```\n\n## Example:\n\nFirst of all, import web server and this module in the app. \n\n```\nvar larkMVC = require('lark-mvc')\nvar app = require('lark')\napp.use(larkMVC()) \napp.run(3000)\n```\n\nSecondely, write `pageService` layer to implement `V` in MVC, which generates html codes by rendering tempalate and data.\n\n```\nvar pageService = require('lark-mvc').pageService\nvar demo = pageService.create('demo')\ndemo.render = function(){\n var res = ''\n co(function *(){\n var categroy = yield this.dataService.demo.getArticles(this.params.id)\n var articles = yield this.dataService.demo.getArticles(categroy)\n var data = {\n 'categroy': categroy,\n 'articles': articles\n }\n res = yield this.render('demo.html', data)\n })\n return res\n})\nmodule.exports = demo\n```\n\nThirdly, write `dataService` layer to implement `M` in MVC, which collects data from database and passes them to `pageService`.\n\n```\nvar dataService = require('lark-mvc').dataService\nvar demo = dataService.create('demo')\ndemo.getData = * function(){\n // get data by dao\n articles = {}\n co (function *(){\n var articles = yeild this.dao.demo.get(this.request.id);\n if articles\n })\n return articles\n}\n\nmodule.exports = demo\n```\n\nForthly, write `dao` layer, which is a wrapper of accessing database.\n\n```\nvar dao = require('lark-mvc').dataService\nvar demo = dao.create('dao')\ndemo.getData = * function(){\n db = redis.conn()\n data = db.get('test-key')\n return data\n}\nmodule.exports = demo\n```\n\nWe have all done here. And then, run the app to see the results.\n\n```\nnode --harmony app.js\n```\n\n<hr>\n\n一个支持MVC模式的中间件\n\n## 功能:\n\n * MVC 分层逻辑\n * app中只能相邻层调用,不允许跨层调用\n * hook功能支持:支持hook功能,在跨层调用前后,发送相应事件,添加自定义逻辑。\n\n## 示例:\n\n在 bootstrap 中启用本模块\n\n```\nvar larkMVC = require('lark-mvc')\nvar app = require('lark')\napp.use(larkMVC()) // lark 默认是支持本模块的,本行代码可以删除\n```\n\ncontroller层在 lark-router中实现\nview 层在template 模板目录里\nmodel 层又分3层: pageService, dataService, dao, 功能如下:\n\n * pageService 负责页面数据逻辑, 被action调用,调用dataService\n * dataService 负责业务数据逻辑,被pageService调用,调用dao\n * dao 负责数据库相关业务逻辑\n\npageService 样例:\n\n```\nvar pageService = require('lark-mvc').pageService\nvar demo = pageService.create('demo')\ndemo.render = function(){\n var res = ''\n co(function *(){\n var categroy = yield this.dataService.demo.getArticles(this.params.id)\n var articles = yield this.dataService.demo.getArticles(categroy)\n var data = {\n 'categroy': categroy,\n 'articles': articles\n }\n res = yield this.render('demo.html', data)\n })\n return res\n})\nmodule.exports = demo\n```\n\naction 层调\n\n```\nthis.pageService.demo.render() [ok]\nthis.dataService.demo.getArticles() [no]\n```\n\ndataService 样例:\n\n```\nvar dataService = require('lark-mvc').dataService\nvar demo = dataService.create('demo')\ndemo.getData = * function(){\n // get data by dao\n articles = {}\n co (function *(){\n var articles = yeild this.dao.demo.get(this.request.id);\n if articles\n })\n return articles\n}\n\nmodule.exports = demo\n```\n\ndao 样例:\n\n```\nvar dao = require('lark-mvc').dataService\nvar demo = dao.create('dao')\ndemo.getData = * function(){\n db = redis.conn()\n data = db.get('test-key')\n return data\n}\nmodule.exports = demo\n```\n\n层之间hook样例:\n\n```\npageSerice.on('beferDataService', function(params){\n validate(params)\n})\n```\n\n[npm-image]: https://img.shields.io/npm/v/lark-mvc.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/lark-mvc\n\n[travis-image]: https://img.shields.io/travis/larkjs/lark-mvc/master.svg?style=flat-square\n[travis-url]: https://travis-ci.org/larkjs/lark-mvc\n", | ||
"readmeFilename": "README.md" | ||
"name": "lark-mvc", | ||
"version": "2.0.0", | ||
"description": "MVC for building web server with lark.js", | ||
"main": ".easy", | ||
"directories": { | ||
"example": "examples", | ||
"test": "test" | ||
}, | ||
"scripts": { | ||
"test": "cd .easy && rm -rf node_modules && ln -s ../node_modules node_modules && NODE_ENV=test ./node_modules/.bin/mocha --harmony --require should test/" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/larkjs/lark-mvc.git" | ||
}, | ||
"keywords": [ | ||
"lark.js", | ||
"lark", | ||
"koa" | ||
], | ||
"author": { | ||
"name": "lark.js Team" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/larkjs/lark-mvc/issues" | ||
}, | ||
"dependencies": { | ||
"chalk": "^1.1.1", | ||
"readdir": "0.0.13", | ||
"save-instance": "0.0.3" | ||
}, | ||
"devDependencies": { | ||
"easy-babel": "^1.0.1", | ||
"koa": "^2.0.0-alpha.3", | ||
"mocha": "^2.0.1", | ||
"should": "^4.4.1", | ||
"supertest": "^0.15.0" | ||
}, | ||
"homepage": "https://www.npmjs.com/package/lark-mvc", | ||
"readmeFilename": "README.md", | ||
"engines": { | ||
"node": ">=4.0.0" | ||
}, | ||
"easy": { | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "NODE_ENV=test ./node_modules/.bin/mocha --harmony --require should test/" | ||
} | ||
} | ||
} |
175
README.md
@@ -8,5 +8,5 @@ MVC for building web server using lark.js | ||
* Seperate bussiness codes into `pageService`, `dataService` and `dao`, which accord to `MVC` concept. (`C`in `MVC` implements in `lark-router`). | ||
* Seperate bussiness codes into layers such as `pageServices`, `dataServices` and `daoServices`, which accord to `MVC` concept. (`C`in `MVC` implements in `lark-router`). | ||
* Make calling rules between MVC layers. | ||
* Support hook between MVC layers. | ||
* Support hook between MVC layers (not implemented yet). | ||
@@ -24,161 +24,66 @@ ## Install: | ||
``` | ||
var larkMVC = require('lark-mvc') | ||
var app = require('lark') | ||
app.use(larkMVC()) | ||
import mvc from 'lark-mvc/middleware'; | ||
import KOA from 'koa'; // koa2.x | ||
const app = new Koa(); | ||
app.use(mvc()) | ||
app.run(3000) | ||
``` | ||
Secondely, write `pageService` layer to implement `V` in MVC, which generates html codes by rendering tempalate and data. | ||
Secondely, write `pageServices` layer to implement `V` in MVC, which generates html codes by rendering tempalate and data. | ||
``` | ||
var pageService = require('lark-mvc').pageService | ||
var demo = pageService.create('demo') | ||
demo.render = function(){ | ||
var res = '' | ||
co(function *(){ | ||
var categroy = yield this.dataService.demo.getArticles(this.params.id) | ||
var articles = yield this.dataService.demo.getArticles(categroy) | ||
var data = { | ||
import MVC from 'lark-mvc'; | ||
const service = MVC.getInstance().createService(); | ||
const access = service.access(); | ||
service.render = async (ctx) => { | ||
let res = ''; | ||
let categroy = await access.data.demo.getArticles(ctx.params.id); | ||
let articles = await access.data.demo.getArticles(categroy); | ||
let data = { | ||
'categroy': categroy, | ||
'articles': articles | ||
} | ||
res = yield this.render('demo.html', data) | ||
}) | ||
return res | ||
}; | ||
res = await ctx.render('demo.html', data); | ||
return res; | ||
}) | ||
module.exports = demo | ||
export default service; | ||
``` | ||
Thirdly, write `dataService` layer to implement `M` in MVC, which collects data from database and passes them to `pageService`. | ||
Thirdly, write `dataServices` layer to implement `M` in MVC, which collects data from database and passes them to `pageServices`. | ||
``` | ||
var dataService = require('lark-mvc').dataService | ||
var demo = dataService.create('demo') | ||
demo.getData = * function(){ | ||
import MVC from 'lark-mvc'; | ||
const service = MVC.getInstance().createService(); | ||
const access = service.access(); | ||
service.getData = async (ctx) => { | ||
// get data by dao | ||
articles = {} | ||
co (function *(){ | ||
var articles = yeild this.dao.demo.get(this.request.id); | ||
if articles | ||
}) | ||
let articles = {} | ||
articles = await access.dao.demo.get(ctx.request.id); | ||
return articles | ||
} | ||
module.exports = demo | ||
export default service; | ||
``` | ||
Forthly, write `dao` layer, which is a wrapper of accessing database. | ||
Forthly, write `daoServices` layer, which is a wrapper of accessing database. | ||
``` | ||
var dao = require('lark-mvc').dataService | ||
var demo = dao.create('dao') | ||
demo.getData = * function(){ | ||
db = redis.conn() | ||
data = db.get('test-key') | ||
return data | ||
} | ||
module.exports = demo | ||
``` | ||
import MVC from 'lark-mvc'; | ||
const service = MVC.getInstance().createService(); | ||
const access = service.access(); | ||
We have all done here. And then, run the app to see the results. | ||
``` | ||
node --harmony app.js | ||
``` | ||
<hr> | ||
一个支持MVC模式的中间件 | ||
## 功能: | ||
* MVC 分层逻辑 | ||
* app中只能相邻层调用,不允许跨层调用 | ||
* hook功能支持:支持hook功能,在跨层调用前后,发送相应事件,添加自定义逻辑。 | ||
## 示例: | ||
在 bootstrap 中启用本模块 | ||
``` | ||
var larkMVC = require('lark-mvc') | ||
var app = require('lark') | ||
app.use(larkMVC()) // lark 默认是支持本模块的,本行代码可以删除 | ||
``` | ||
controller层在 lark-router中实现 | ||
view 层在template 模板目录里 | ||
model 层又分3层: pageService, dataService, dao, 功能如下: | ||
* pageService 负责页面数据逻辑, 被action调用,调用dataService | ||
* dataService 负责业务数据逻辑,被pageService调用,调用dao | ||
* dao 负责数据库相关业务逻辑 | ||
pageService 样例: | ||
``` | ||
var pageService = require('lark-mvc').pageService | ||
var demo = pageService.create('demo') | ||
demo.render = function(){ | ||
var res = '' | ||
co(function *(){ | ||
var categroy = yield this.dataService.demo.getArticles(this.params.id) | ||
var articles = yield this.dataService.demo.getArticles(categroy) | ||
var data = { | ||
'categroy': categroy, | ||
'articles': articles | ||
} | ||
res = yield this.render('demo.html', data) | ||
}) | ||
return res | ||
}) | ||
module.exports = demo | ||
``` | ||
action 层调 | ||
``` | ||
this.pageService.demo.render() [ok] | ||
this.dataService.demo.getArticles() [no] | ||
``` | ||
dataService 样例: | ||
``` | ||
var dataService = require('lark-mvc').dataService | ||
var demo = dataService.create('demo') | ||
demo.getData = * function(){ | ||
// get data by dao | ||
articles = {} | ||
co (function *(){ | ||
var articles = yeild this.dao.demo.get(this.request.id); | ||
if articles | ||
}) | ||
return articles | ||
service.getData = async (ctx) => { | ||
db = redis.conn(); | ||
data = await db.get('test-key'); | ||
return data; | ||
} | ||
module.exports = demo | ||
export default service; | ||
``` | ||
dao 样例: | ||
We have all done here. And then, run the app to see the results. | ||
(Remember to compile with babel before running it) | ||
``` | ||
var dao = require('lark-mvc').dataService | ||
var demo = dao.create('dao') | ||
demo.getData = * function(){ | ||
db = redis.conn() | ||
data = db.get('test-key') | ||
return data | ||
} | ||
module.exports = demo | ||
``` | ||
层之间hook样例: | ||
``` | ||
pageSerice.on('beferDataService', function(params){ | ||
validate(params) | ||
}) | ||
``` | ||
[npm-image]: https://img.shields.io/npm/v/lark-mvc.svg?style=flat-square | ||
@@ -185,0 +90,0 @@ [npm-url]: https://npmjs.org/package/lark-mvc |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
54766
48
0
1211
3
5
92
8
+ Addedchalk@^1.1.1
+ Addedreaddir@0.0.13
+ Addedsave-instance@0.0.3
+ Addedansi-regex@2.1.1(transitive)
+ Addedansi-styles@2.2.1(transitive)
+ Addedchalk@1.1.3(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedhas-ansi@2.0.0(transitive)
+ Addedq@1.0.1(transitive)
+ Addedreaddir@0.0.13(transitive)
+ Addedsave-instance@0.0.3(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedsupports-color@2.0.0(transitive)
- Removedrd@~0.0.2
- Removedrd@0.0.2(transitive)