New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

astroboy

Package Overview
Dependencies
Maintainers
2
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

astroboy - npm Package Compare versions

Comparing version 1.1.0-beta.16 to 1.1.0

.prettierrc

87

app/extends/application.js

@@ -1,43 +0,50 @@

"use strict";
/**
* 扩展 Koa Application 对象
*/
const assert = require("assert");
const appExtends = {
getConfig(key) {
if (!key) {
return this.config;
}
else {
let keys = key.split('.');
let result = this.config;
let item;
while ((item = keys.shift())) {
result = result[item];
}
return result;
}
},
getServiceClass(packageName, serviceName) {
assert(packageName, 'Package name cannot be empty!');
assert(serviceName, 'Service name cannot be empty!');
if (this.services && this.services[packageName] && this.services[packageName][serviceName]) {
return this.services[packageName][serviceName];
}
else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
getLib(packageName, libName) {
assert(packageName, 'Package name cannot be empty!');
assert(libName, 'Lib name cannot be empty!');
if (this.libs && this.libs[packageName] && this.libs[packageName][libName]) {
return this.libs[packageName][libName];
}
else {
throw new Error(`Lib ${packageName} ${libName} is not found.`);
}
},
};
module.exports = appExtends;
//# sourceMappingURL=application.js.map
const assert = require('assert');
module.exports = {
/**
* 获取配置信息,参数 key 可以是点分隔符隔开的字符串,例如 foo.bar
* @param {String} key 配置 key
*/
getConfig(key) {
if (!key) {
return this.config;
} else {
let keys = key.split('.');
let result = this.config;
let item;
while (item = keys.shift()) {
result = result[item];
}
return result;
}
},
/**
* 获取 Service 类
* @param {String} packageName 包名
* @param {String} serviceName 服务名
*/
getServiceClass(packageName, serviceName) {
assert(packageName, 'Package name cannot be empty!');
assert(serviceName, 'Service name cannot be empty!');
if (this.services && this.services[packageName] && this.services[packageName][serviceName]) {
return this.services[packageName][serviceName];
} else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
getLib(packageName, libName) {
assert(packageName, 'Package name cannot be empty!');
assert(libName, 'Lib name cannot be empty!');
if (this.libs && this.libs[packageName] && this.libs[packageName][libName]) {
return this.libs[packageName][libName];
} else {
throw new Error(`Lib ${packageName} ${libName} is not found.`);
}
}
};

@@ -1,70 +0,91 @@

"use strict";
/**
* 扩展 Koa Context 对象
*/
const assert = require("assert");
const ctxExtends = {
getConfig(...args) {
return this.app.getConfig(...args);
},
getServiceClass(...args) {
return this.app.getServiceClass(...args);
},
getService(packageName, serviceName) {
assert(packageName, 'Package name cannot be empty!');
assert(serviceName, 'Service name cannot be empty!');
if (this.app.services && this.app.services[packageName] && this.app.services[packageName][serviceName]) {
const ServiceClass = this.app.services[packageName][serviceName];
return new ServiceClass(this);
}
else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
async callService(service, method, ...args) {
const keys = service.split('/');
let packageName = undefined;
let serviceName = undefined;
if (keys.length === 2) {
packageName = keys[0];
serviceName = keys[1];
}
else if (keys.length === 1) {
packageName = this.app.ROOT_NAME;
serviceName = keys[0];
}
if (this.app.services && this.app.services[packageName] && this.app.services[packageName][serviceName]) {
const ServiceClass = this.app.services[packageName][serviceName];
const service = new ServiceClass(this);
if (service[method]) {
return await service[method](...args);
}
else {
throw new Error(`method name ${method} is not found.`);
}
}
else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
invokeServiceMethod(pkgName, serviceName, methodName, ...args) {
if (this.app.services && this.app.services[pkgName] && this.app.services[pkgName][serviceName]) {
const ServiceClass = this.app.services[pkgName][serviceName];
const service = new ServiceClass(this);
if (service[methodName]) {
return service[methodName](...args);
}
else {
throw new Error(`method name ${methodName} is not found.`);
}
}
else {
throw new Error(`Service ${pkgName} ${serviceName} is not found.`);
}
},
getLib(...args) {
return this.app.getLib(...args);
},
};
module.exports = ctxExtends;
//# sourceMappingURL=context.js.map
const assert = require('assert');
module.exports = {
getConfig(...args) {
return this.app.getConfig(...args);
},
getServiceClass(...args) {
return this.app.getServiceClass(...args);
},
/**
* 获取一个 Service 类实例
* @param {String} packageName 包名
* @param {String} serviceName 服务名
*/
getService(packageName, serviceName) {
assert(packageName, 'Package name cannot be empty!');
assert(serviceName, 'Service name cannot be empty!');
if (this.app.services && this.app.services[packageName] && this.app.services[packageName][serviceName]) {
const ServiceClass = this.app.services[packageName][serviceName];
return new ServiceClass(this);
} else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
/**
* 调用服务
* @param {String} service 服务名
* @param {String} method 方法名
* @param {Object} args 参数
*/
async callService(service, method, ...args) {
const keys = service.split('/');
let packageName,
serviceName;
if (keys.length === 2) {
packageName = keys[0];
serviceName = keys[1];
} else if (keys.length === 1) {
packageName = this.app.ROOT_NAME;
serviceName = keys[0];
}
if (this.app.services &&
this.app.services[packageName] &&
this.app.services[packageName][serviceName]) {
const ServiceClass = this.app.services[packageName][serviceName];
const service = new ServiceClass(this);
if (service[method]) {
return await service[method](...args);
} else {
throw new Error(`method name ${method} is not found.`);
}
} else {
throw new Error(`Service ${packageName} ${serviceName} is not found.`);
}
},
/**
* 调用服务(定义支持)
* @param {String} pkgName 包名
* @param {String} serviceName 服务名
* @param {String} methodName 方法名
* @param {Object} args 参数
*/
async invokeServiceMethod(pkgName, serviceName, methodName, ...args) {
if (this.app.services &&
this.app.services[pkgName] &&
this.app.services[pkgName][serviceName]) {
const ServiceClass = this.app.services[pkgName][serviceName];
const service = new ServiceClass(this);
if (service[methodName]) {
return await service[methodName](...args);
} else {
throw new Error(`method name ${methodName} is not found.`);
}
} else {
throw new Error(`Service ${pkgName} ${serviceName} is not found.`);
}
},
getLib(...args) {
return this.app.getLib(...args);
}
};

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -7,69 +6,68 @@ * 配置加载器加载顺序

const NODE_ENV = process.env.NODE_ENV;
const defaultLoaderConfig = {
AstroboyPkgLoader: {
priority: 10,
module.exports = {
AstroboyPkgLoader: {
priority: 10,
},
AstroboyExtendLoader: {
priority: 15,
options: {
applicationPattern: `/app/extends/application.${SUPPORT_EXT}`,
contextPattern: [`/app/extends/context/*.${SUPPORT_EXT}`, `/app/extends/context.${SUPPORT_EXT}`],
requestPattern: `/app/extends/request.${SUPPORT_EXT}`,
responsePattern: `/app/extends/response.${SUPPORT_EXT}`,
controllerPattern: `/app/extends/controller.${SUPPORT_EXT}`,
},
AstroboyExtendLoader: {
priority: 15,
options: {
applicationPattern: `/app/extends/application.${SUPPORT_EXT}`,
contextPattern: [`/app/extends/context/*.${SUPPORT_EXT}`, `/app/extends/context.${SUPPORT_EXT}`],
requestPattern: `/app/extends/request.${SUPPORT_EXT}`,
responsePattern: `/app/extends/response.${SUPPORT_EXT}`,
controllerPattern: `/app/extends/controller.${SUPPORT_EXT}`,
},
},
AstroboyConfigLoader: {
priority: 20,
options: {
// 注意:为了控制配置合并顺序,不要这么写 `/config/config.(default|${NODE_ENV}).js`
pattern: ['/config/config.default.js', `/config/config.${NODE_ENV}.js`],
},
AstroboyConfigLoader: {
priority: 20,
options: {
// 注意:为了控制配置合并顺序,不要这么写 `/config/config.(default|${NODE_ENV}).js`
pattern: [`/config/config.default.${SUPPORT_EXT}`, `/config/config.${NODE_ENV}.${SUPPORT_EXT}`],
},
},
AstroboyMiddlewareLoader: {
priority: 25,
options: {
pattern: `/app/middlewares/*.${SUPPORT_EXT}`,
// 注意:为了控制配置合并顺序,不要这么写 `/config/config.(default|${NODE_ENV}).js`
configPattern: ['/config/middleware.default.js', `/config/middleware.${NODE_ENV}.js`],
},
AstroboyMiddlewareLoader: {
priority: 25,
options: {
pattern: `/app/middlewares/*.${SUPPORT_EXT}`,
// 注意:为了控制配置合并顺序,不要这么写 `/config/config.(default|${NODE_ENV}).js`
configPattern: [`/config/middleware.default.${SUPPORT_EXT}`, `/config/middleware.${NODE_ENV}.${SUPPORT_EXT}`],
},
},
AstroboyLibLoader: {
priority: 30,
options: {
pattern: `/app/lib/*.${SUPPORT_EXT}`,
},
AstroboyLibLoader: {
priority: 30,
options: {
pattern: `/app/lib/*.${SUPPORT_EXT}`,
},
},
AstroboyBootLoader: {
priority: 35,
options: {
pattern: `/boot.${SUPPORT_EXT}`,
},
AstroboyBootLoader: {
priority: 35,
options: {
pattern: `/boot.${SUPPORT_EXT}`,
},
},
AstroboyControllerLoader: {
priority: 40,
options: {
pattern: `/app/controllers/**/*.${SUPPORT_EXT}`,
},
AstroboyControllerLoader: {
priority: 40,
options: {
pattern: `/app/controllers/**/*.${SUPPORT_EXT}`,
},
},
AstroboyServiceLoader: {
priority: 45,
options: {
pattern: `/app/services/**/*.${SUPPORT_EXT}`,
},
AstroboyServiceLoader: {
priority: 45,
options: {
pattern: `/app/services/**/*.${SUPPORT_EXT}`,
},
},
AstroboyRouterLoader: {
priority: 50,
options: {
pattern: `/app/routers/**/*.${SUPPORT_EXT}`,
},
AstroboyRouterLoader: {
priority: 50,
options: {
pattern: `/app/routers/**/*.${SUPPORT_EXT}`,
},
},
AstroboyVersionFileLoader: {
priority: 55,
options: {
pattern: '/config/version*.json',
},
AstroboyVersionFileLoader: {
priority: 55,
options: {
pattern: '/config/version*.json',
},
},
},
};
module.exports = defaultLoaderConfig;
//# sourceMappingURL=loader.default.js.map

@@ -1,29 +0,33 @@

"use strict";
const path = require("path");
/**
* 默认插件配置文件
*/
const defaultPluginConfig = {
'astroboy-body': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-body'),
},
'astroboy-router': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-router'),
},
'astroboy-security': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-security'),
},
'astroboy-static': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-static'),
},
'astroboy-view': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-view'),
},
};
module.exports = defaultPluginConfig;
//# sourceMappingURL=plugin.default.js.map
const path = require('path');
module.exports = {
'astroboy-body': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-body')
},
'astroboy-router': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-router')
},
'astroboy-security': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-security')
},
'astroboy-static': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-static')
},
'astroboy-view': {
enable: true,
path: path.resolve(__dirname, '../plugins/astroboy-view')
},
};

@@ -1,72 +0,58 @@

"use strict";
const chalk_1 = require("chalk");
const path = require("path");
const Koa = require("koa");
const events_1 = require("events");
const CoreLoader_1 = require("./CoreLoader");
const BaseClass_1 = require("./base/BaseClass");
/**
* ## Astroboy Framework
*
* @author Big Mogician
* @class Astroboy
* @extends {EventEmitter}
* @template DEFINE Framework Definition, defalut is `IAstroboyFrameworkDefine`.
*/
class Astroboy extends events_1.EventEmitter {
constructor(options = {}) {
super();
options.NODE_ENV =
process.env.APPLICATION_STANDARD_ENV || process.env.NODE_ENV || options.NODE_ENV || 'development';
options.NODE_PORT = process.env.NODE_PORT || options.NODE_PORT || '8201';
options.ROOT_PATH = options.ROOT_PATH || process.cwd();
this.options = options;
this.init();
this.start();
}
get [Symbol.for('BASE_DIR')]() {
return path.join(__dirname, '..');
}
init() {
this.app = new Koa();
this.app.env = this.options.NODE_ENV;
this.app.NODE_ENV = this.options.NODE_ENV;
this.app.ROOT_PATH = this.options.ROOT_PATH;
this.app.ROOT_NAME = path.basename(this.options.ROOT_PATH);
this.loader = new CoreLoader_1.CoreLoader({
astroboy: this,
app: this.app,
const EventEmitter = require('events');
const path = require('path');
const chalk = require('chalk');
const Koa = require('koa');
const CoreLoader = require('./CoreLoader');
class Astroboy extends EventEmitter {
get [Symbol.for('BASE_DIR')]() {
return path.join(__dirname, '..');
}
constructor(options = {}) {
super();
options.NODE_ENV =
process.env.APPLICATION_STANDARD_ENV || process.env.NODE_ENV || options.NODE_ENV || 'development';
options.NODE_PORT = process.env.NODE_PORT || options.NODE_PORT || '8201';
options.ROOT_PATH = options.ROOT_PATH || process.cwd();
this.options = options;
this.init();
this.start();
}
init() {
this.app = new Koa();
this.app.env = this.options.NODE_ENV;
this.app.NODE_ENV = this.options.NODE_ENV;
this.app.ROOT_PATH = this.options.ROOT_PATH;
this.app.ROOT_NAME = path.basename(this.options.ROOT_PATH);
this.loader = new CoreLoader({
astroboy: this,
app: this.app,
});
}
start() {
this.app.listen(this.options.NODE_PORT, () => {
console.log(chalk.green('应用启动成功'));
console.log(chalk.green(`访问地址:${chalk.blue('http://127.0.0.1:' + this.options.NODE_PORT)}`));
this.emit('start', this.app);
});
this.app.on('error', (err, ctx) => {
this.emit('error', err, ctx);
});
// 添加默认的 error 事件监听器
setTimeout(() => {
if (this.listenerCount('error') === 0) {
this.on('error', (err, ctx) => {
console.log('[default error callback]');
console.log(err);
});
}
start() {
this.app.listen(this.options.NODE_PORT, () => {
console.log(chalk_1.default.green('应用启动成功'));
console.log(chalk_1.default.green(`访问地址:${chalk_1.default.blue('http://127.0.0.1:' + this.options.NODE_PORT)}`));
this.emit('start', this.app);
});
this.app.on('error', (err, ctx) => {
this.emit('error', err, ctx);
});
// 添加默认的 error 事件监听器
setTimeout(() => {
if (this.listenerCount('error') === 0) {
this.on('error', (err, ctx) => {
console.log('[default error callback]');
console.log(err);
});
}
}, 3000);
}
}
}, 3000);
}
}
(function (Astroboy) {
/** ### Astroboy Base Class */
Astroboy.BaseClass = BaseClass_1.BaseClass;
/** ### Astroboy Controller Base */
Astroboy.Controller = BaseClass_1.BaseClass;
/** ### Astroboy Service Base */
Astroboy.Service = BaseClass_1.BaseClass;
/** ### Astroboy <Helper&Utils> Base */
Astroboy.Helper = BaseClass_1.BaseClass;
})(Astroboy || (Astroboy = {}));
module.exports = Astroboy;
//# sourceMappingURL=Astroboy.js.map

@@ -1,41 +0,39 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* ## Astroboy Base Class
* - `ctx` Context 请求上下文对象
* - `app` Koa Application 实例对象
* - `config` 应用配置对象
*
* @author Big Mogician
* @export
* @class BaseClass
* @implements {IAstroboyCtxExtends<DEFINE>}
* @template DEFINE Framework Definition, default is `IAstroboyFrameworkDefine`
* ctx Context 请求上下文对象
* app Koa Application 实例对象
* config 应用配置对象
*/
class BaseClass {
constructor(ctx) {
this.ctx = ctx;
this.app = (ctx && ctx.app);
this.config = (ctx && ctx.app && ctx.app.config);
}
getConfig(...args) {
return this.ctx.getConfig(...args);
}
getLib(...args) {
return this.ctx.getLib(...args);
}
getServiceClass(...args) {
return this.ctx.getServiceClass(...args);
}
getService(...args) {
return this.ctx.getService(...args);
}
callService(...args) {
return this.ctx.callService(...args);
}
invokeServiceMethod(...args) {
return this.ctx.invokeServiceMethod(...args);
}
constructor(ctx) {
this.ctx = ctx;
this.app = ctx && ctx.app;
this.config = ctx && ctx.app && ctx.app.config;
}
getConfig(...args) {
return this.ctx.getConfig(...args);
}
getServiceClass(...args) {
return this.ctx.getServiceClass(...args);
}
getService(...args) {
return this.ctx.getService(...args);
}
callService(...args) {
return this.ctx.callService(...args);
}
invokeServiceMethod(...args) {
return this.ctx.invokeServiceMethod(...args);
}
getLib(...args) {
return this.ctx.getLib(...args);
}
}
exports.BaseClass = BaseClass;
//# sourceMappingURL=BaseClass.js.map
module.exports = BaseClass;

@@ -1,293 +0,211 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-ignore no types matched
const pathMatching = require("path-matching");
const path = require("path");
const lodash = require("lodash");
const util_1 = require("./lib/util");
const Loader_1 = require("./Loader");
/**
* ## Core Loader
* - decide how to build application.
*
* @author Big Mogician
* @export
* @class CoreLoader
* @extends {Loader<F, A>}
* @template F
* @template A
*/
class CoreLoader extends Loader_1.Loader {
constructor(options = {}) {
super(options);
this.options = options || {};
this.astroboy = this.options.astroboy;
this.app = this.options.app || this.app;
this.NODE_ENV = this.app.NODE_ENV || 'development';
this.patterns = Object.assign({}, this.defaultPatterns);
this.init();
const path = require('path');
const lodash = require('lodash');
const pathMatching = require('path-matching');
const Util = require('./lib/util');
const Loader = require('./Loader');
class CoreLoader extends Loader {
get defaultPatterns() {
return {
loaderPattern: `/loader/*.(js|ts)`,
pluginPattern: `/config/plugin.(default|${this.NODE_ENV}).js`,
loaderConfigPattern: `/config/loader.(default|${this.NODE_ENV}).js`,
};
}
constructor(options = {}) {
super(options);
this.options = options;
this.astroboy = this.options.astroboy;
this.app = this.options.app;
this.NODE_ENV = this.app.NODE_ENV;
this.patterns = Object.assign({}, this.defaultPatterns);
this.init();
}
init() {
this.loadCoreDirs(this.app.ROOT_PATH);
this.loadPluginConfig();
this.loadFullDirs();
this.loadLoaderQueue();
this.loadLoaders();
this.runLoaders();
this.useMiddlewares();
}
// 加载核心目录,包括 app、framework,但不包括 plugin
loadCoreDirs(baseDir) {
let coreDirs = [
{
baseDir: baseDir,
type: 'app',
name: path.basename(baseDir),
},
];
let proto = this.astroboy;
while (proto) {
proto = Object.getPrototypeOf(proto);
if (proto) {
const newBaseDir = proto[Symbol.for('BASE_DIR')];
if (newBaseDir) {
coreDirs.push({
baseDir: newBaseDir,
type: 'framework',
name: path.basename(newBaseDir),
});
}
}
}
get defaultPatterns() {
return {
loaderPattern: `/loader/*.(js|ts)`,
pluginPattern: `/config/plugin.(default|${this.NODE_ENV}).(js|ts)`,
loaderConfigPattern: `/config/loader.(default|${this.NODE_ENV}).(js|ts)`,
};
}
/**
* ### `init` hook
*
* @virtual
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
init() {
this.loadCoreDirs(this.app.ROOT_PATH);
this.loadPluginConfig();
this.loadFullDirs();
this.loadLoaderQueue();
this.loadLoaders();
this.runLoaders();
this.useMiddlewares();
}
/**
* ### `load` hook
*
* @virtual
* @author Big Mogician
* @memberof CoreLoader
*/
load() { }
/**
* ### 加载核心目录,包括 app、framework,但不包括 plugin
*
* @author Big Mogician
* @protected
* @param {string} baseDir
* @memberof CoreLoader
*/
loadCoreDirs(baseDir) {
const coreDirs = [
{
baseDir: baseDir,
type: 'app',
name: path.basename(baseDir),
},
];
let proto = this.astroboy;
while (proto) {
proto = Object.getPrototypeOf(proto);
if (proto) {
const newBaseDir = proto[Symbol.for('BASE_DIR')];
if (newBaseDir) {
coreDirs.push({
baseDir: newBaseDir,
type: 'framework',
name: path.basename(newBaseDir),
});
}
}
this.coreDirs = coreDirs.reverse();
Util.outputJsonSync(`${this.app.ROOT_PATH}/run/coreDirs.json`, this.coreDirs);
}
// 获取插件配置
loadPluginConfig() {
let pluginConfig = {};
this.coreDirs.forEach(item => {
this.globDir(item.baseDir, this.patterns.pluginPattern, entries => {
pluginConfig = entries.reduce((a, b) => {
let content = require(b);
return lodash.merge(a, content);
}, pluginConfig);
});
});
this.pluginConfig = pluginConfig;
Util.outputJsonSync(`${this.app.ROOT_PATH}/run/pluginConfig.json`, pluginConfig);
}
// 获取遍历目录
loadFullDirs() {
let dirs = [];
this.coreDirs.forEach(item => {
dirs = dirs.concat(this.getPluginDirs(item.baseDir).reverse());
dirs.push(item);
});
this.dirs = dirs;
Util.outputJsonSync(`${this.app.ROOT_PATH}/run/dirs.json`, dirs);
}
// 获取需要遍历的插件目录
getPluginDirs(baseDir) {
const config = this.getPluginConfig(baseDir);
let ret = [];
if (lodash.isPlainObject(config)) {
for (let name in config) {
if (this.pluginConfig[name].enable) {
const baseDir = this.getPluginPath(config[name]);
ret.push({
baseDir: baseDir,
type: 'plugin',
name: path.basename(baseDir),
});
}
this.coreDirs = coreDirs.reverse();
util_1.outputJsonSync(`${this.app.ROOT_PATH}/run/coreDirs.json`, this.coreDirs);
}
}
/**
* ### 获取插件配置
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
loadPluginConfig() {
let pluginConfig = {};
this.coreDirs.forEach(item => {
this.globDir(item.baseDir, this.patterns.pluginPattern, entries => {
pluginConfig = entries.reduce((a, b) => {
const content = require(b);
return lodash.merge(a, content);
}, pluginConfig);
});
return ret;
}
getPluginConfig(baseDir) {
let config = {};
this.globDir(baseDir, this.patterns.pluginPattern, entries => {
config = entries.reduce((a, b) => {
return lodash.merge(a, require(b));
}, {});
});
return config;
}
// 获取加载器执行队列
loadLoaderQueue() {
let loaderConfig = {};
this.globDirs(this.patterns.loaderConfigPattern, entries => {
loaderConfig = entries.reduce((previousValue, currentValue) => {
return lodash.merge(previousValue, require(currentValue));
}, loaderConfig);
});
let queue = [];
Object.keys(loaderConfig).forEach(item => {
queue.push(
Object.assign(
{
priority: 300,
name: item,
},
loaderConfig[item]
)
);
});
queue = queue.sort((a, b) => {
return a.priority - b.priority;
});
this.loaderQueue = queue;
}
// 获取加载器
loadLoaders() {
let loaders = {};
this.globDirs(this.patterns.loaderPattern, entries => {
entries.forEach(entry => {
const key = this.resolveExtensions(path.basename(entry));
loaders[key] = require(entry);
});
});
this.loaders = loaders;
}
// 执行加载器
runLoaders() {
const app = this.app;
const loaders = this.loaders;
this.loaderQueue.forEach(item => {
if (loaders[item.name]) {
const loader = new loaders[item.name]({
dirs: this.dirs,
config: item.options,
app,
});
this.pluginConfig = pluginConfig;
util_1.outputJsonSync(`${this.app.ROOT_PATH}/run/pluginConfig.json`, pluginConfig);
}
/**
* ### 获取遍历目录
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
loadFullDirs() {
let dirs = [];
this.coreDirs.forEach(item => {
dirs = dirs.concat(this.getPluginDirs(item.baseDir).reverse());
dirs.push(item);
});
this.dirs = dirs;
util_1.outputJsonSync(`${this.app.ROOT_PATH}/run/dirs.json`, dirs);
}
/**
* ### 获取需要遍历的插件目录
*
* @author Big Mogician
* @protected
* @param {string} baseDir
* @returns
* @memberof CoreLoader
*/
getPluginDirs(baseDir) {
const config = this.getPluginConfig(baseDir);
const ret = [];
if (lodash.isPlainObject(config)) {
for (let name in config) {
if (this.pluginConfig[name].enable) {
const baseDir = this.getPluginPath(config[name]);
ret.push({
baseDir: baseDir,
type: 'plugin',
name: path.basename(baseDir),
});
}
}
if (!(loader instanceof Loader)) {
throw new Error(`Loader ${item.name} must extend Loader.`);
}
return ret;
}
/**
* ### 获取需要遍历的插件配置
*
* @author Big Mogician
* @protected
* @param {string} baseDir
* @returns
* @memberof CoreLoader
*/
getPluginConfig(baseDir) {
let config = {};
this.globDir(baseDir, this.patterns.pluginPattern, entries => {
config = entries.reduce((a, b) => {
return lodash.merge(a, require(b));
}, {});
});
return config;
}
/**
* ### 获取加载器执行队列
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
loadLoaderQueue() {
let loaderConfig = {};
this.globDirs(this.patterns.loaderConfigPattern, entries => {
loaderConfig = entries.reduce((previousValue, currentValue) => {
return lodash.merge(previousValue, require(currentValue));
}, loaderConfig);
});
let queue = [];
Object.keys(loaderConfig).forEach(item => {
queue.push(Object.assign({
priority: 300,
name: item,
}, loaderConfig[item]));
});
queue = queue.sort((a, b) => {
return a.priority - b.priority;
});
this.loaderQueue = queue;
}
/**
* ### 获取加载器
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
loadLoaders() {
let loaders = {};
this.globDirs(this.patterns.loaderPattern, entries => {
entries.forEach(entry => {
const key = this.resolveExtensions(path.basename(entry));
loaders[key] = require(entry);
});
});
this.loaders = loaders;
}
/**
* ### 执行加载器
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
runLoaders() {
const app = this.app;
const loaders = this.loaders;
this.loaderQueue.forEach(item => {
if (loaders[item.name]) {
const loader = new loaders[item.name]({
dirs: this.dirs,
config: item.options,
app,
});
if (!(loader instanceof Loader_1.Loader)) {
throw new Error(`Loader ${item.name} must extend Loader.`);
}
loader.load();
}
else {
throw new Error(`Loader ${item.name} is not found.`);
}
});
}
/**
* ### Use Middlewares
*
* @author Big Mogician
* @protected
* @memberof CoreLoader
*/
useMiddlewares() {
const app = this.app;
const middlewares = app.middlewares;
app.middlewareQueue.forEach(item => {
if (middlewares[item.name]) {
let fn = middlewares[item.name](item.options, app);
fn = this.wrapMiddleware(fn, item);
if (fn) {
app.use(fn);
}
}
else {
throw new Error(`middleware ${item.name} is not found.`);
}
});
}
/**
* ### Wrap Middlewares
*
* @author Big Mogician
* @protected
* @param {NormalizedMiddleware} middleware
* @param {IPriority} options
* @returns
* @memberof CoreLoader
*/
wrapMiddleware(middleware, options) {
const match = pathMatching(options);
let fn = async function (ctx, next) {
if (match(ctx)) {
await middleware(ctx, next);
}
else {
await next();
}
};
fn._name = `wrap-${middleware.name || middleware._name}`;
return fn;
}
loader.load();
} else {
throw new Error(`Loader ${item.name} is not found.`);
}
});
}
useMiddlewares() {
const app = this.app;
const middlewares = app.middlewares;
app.middlewareQueue.forEach(item => {
if (middlewares[item.name]) {
let fn = middlewares[item.name](item.options, app);
fn = this.wrapMiddleware(fn, item);
if (fn) {
app.use(fn);
}
} else {
throw new Error(`middleware ${item.name} is not found.`);
}
});
}
wrapMiddleware(middleware, options) {
const match = pathMatching(options);
let fn = async function(ctx, next) {
if (match(ctx)) {
await middleware(ctx, next);
} else {
await next();
}
};
fn._name = `wrap-${middleware.name || middleware._name}`;
return fn;
}
}
exports.CoreLoader = CoreLoader;
//# sourceMappingURL=CoreLoader.js.map
module.exports = CoreLoader;

@@ -1,21 +0,14 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs-extra");
/**
* ### 输出内容到文件
*
* @author Big Mogician
* @export
* @param {string} file
* @param {*} data
* @param {*} [options={}]
*/
function outputJsonSync(file, data, options = {}) {
options = Object.assign({
const fs = require('fs-extra');
module.exports = {
outputJsonSync(file, data, options = {}) {
options = Object.assign(
{
spaces: 2,
EOL: '\r\n',
}, options);
},
options
);
fs.outputJsonSync(file, data, options);
}
exports.outputJsonSync = outputJsonSync;
//# sourceMappingURL=util.js.map
},
};

@@ -1,105 +0,53 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const glob = require("fast-glob");
const path = require("path");
const TYPING_FILE_EXTS = '.d.ts';
'use strict';
const glob = require('fast-glob');
const path = require('path');
const APP_EXTENSIONS = ['js', 'ts'];
/**
* ### Check the file is typing file or not.
*
* @author Big Mogician
* @param {EntryItem} entry
* @returns
*/
function fileIsNotTypingFile(entry) {
return typeof entry === 'string' ? !entry.endsWith(TYPING_FILE_EXTS) : !entry.path.endsWith(TYPING_FILE_EXTS);
}
/**
* ### Base Loader
*
* @author Big Mogician
* @export
* @abstract
* @class Loader
* @template F
* @template A
*/
class Loader {
constructor(options = {}) {
this.dirs = options.dirs || [];
this.config = options.config || {};
this.app = options.app || {};
constructor(options = {}) {
this.dirs = options.dirs;
this.config = options.config;
this.app = options.app;
}
load() {}
resolveExtensions(path, resolveDevide = false) {
let newPath = path;
APP_EXTENSIONS.forEach(ext => (newPath = newPath.replace(`.${ext}`, '')));
return resolveDevide ? newPath.replace(/\//g, '.') : newPath;
}
globDirs(patterns, callback) {
this.dirs.forEach(item => {
this.globDir(item.baseDir, patterns, callback);
});
}
globDir(baseDir, patterns, callback) {
let newPatterns;
if (typeof patterns === 'string') {
newPatterns = [`${baseDir}${patterns}`];
} else if (Array.isArray(patterns)) {
newPatterns = patterns.map(pattern => {
return `${baseDir}${pattern}`;
});
}
/**
* ### Resolve Extensions
*
* @author Big Mogician
* @protected
* @param {string} path
* @param {boolean} [resolveDevide=false]
* @returns
* @memberof Loader
*/
resolveExtensions(path, resolveDevide = false) {
let newPath = path;
APP_EXTENSIONS.forEach(ext => (newPath = newPath.replace(`.${ext}`, '')));
return resolveDevide ? newPath.replace(/\//g, '.') : newPath;
const entries = glob.sync(newPatterns, { dot: true });
callback(entries.filter(i => !i.includes('.d.ts')));
}
// 获取插件的根目录
// 要求插件的入口文件必须放在插件根目录
getPluginPath(plugin) {
if (plugin.path) {
return plugin.path;
}
/**
* ### Get Dirs
*
* @author Big Mogician
* @protected
* @param {(string | string[])} patterns
* @param {(files: EntryItem[]) => void} callback
* @memberof Loader
*/
globDirs(patterns, callback) {
this.dirs.forEach(item => {
this.globDir(item.baseDir, patterns, callback);
});
}
/**
* ### Resolve Dir
*
* @author Big Mogician
* @protected
* @param {string} baseDir
* @param {(string | string[])} patterns
* @param {(files: EntryItem[]) => void} callback
* @memberof Loader
*/
globDir(baseDir, patterns, callback) {
let newPatterns = [];
if (typeof patterns === 'string') {
newPatterns = [`${baseDir}${patterns}`];
}
else if (Array.isArray(patterns)) {
newPatterns = patterns.map(pattern => {
return `${baseDir}${pattern}`;
});
}
const entries = glob.sync(newPatterns, { dot: true });
callback(entries.filter(fileIsNotTypingFile));
}
/**
* ### 获取插件的根目录
* - 要求插件的入口文件必须放在插件根目录
*
* @author Big Mogician
* @protected
* @param {IPluginEntry} plugin
* @returns
* @memberof Loader
*/
getPluginPath(plugin) {
if (plugin.path) {
return plugin.path;
}
const name = plugin.package || plugin.name;
const entryFile = require.resolve(name);
return path.dirname(entryFile);
}
const name = plugin.package || plugin.name;
const entryFile = require.resolve(name);
return path.dirname(entryFile);
}
}
exports.Loader = Loader;
//# sourceMappingURL=Loader.js.map
module.exports = Loader;

@@ -1,4 +0,9 @@

"use strict";
const Astroboy = require("./core/Astroboy");
const Astroboy = require('./core/Astroboy');
const BaseClass = require('./core/base/BaseClass');
module.exports = Astroboy;
//# sourceMappingURL=index.js.map
module.exports.BaseClass = BaseClass;
module.exports.Controller = BaseClass;
module.exports.Service = BaseClass;
module.exports.Helper = BaseClass;

@@ -1,17 +0,18 @@

"use strict";
const assert = require("assert");
const lodash = require("lodash");
const Loader_1 = require("../core/Loader");
class AstroboyBootLoader extends Loader_1.Loader {
load() {
this.globDirs(this.config.pattern || [], entries => {
entries.forEach(entry => {
const boot = require(entry);
assert(lodash.isFunction(boot), `${entry} must return a function.`);
boot(this.app);
});
});
}
'use strict';
const lodash = require('lodash');
const assert = require('assert');
const Loader = require('../core/Loader');
class AstroboyBootLoader extends Loader {
load() {
this.globDirs(this.config.pattern, entries => {
entries.forEach(entry => {
let boot = require(entry);
assert(lodash.isFunction(boot), `${entry} must return a function.`);
boot(this.app);
});
});
}
}
module.exports = AstroboyBootLoader;
//# sourceMappingURL=AstroboyBootLoader.js.map

@@ -1,27 +0,27 @@

"use strict";
const lodash = require("lodash");
const Loader_1 = require("../core/Loader");
const util_1 = require("../core/lib/util");
class AstroboyConfigLoader extends Loader_1.Loader {
load() {
let config = {};
this.globDirs(this.config.pattern || [], entries => {
config = entries.reduce((a, b) => {
let content = require(b);
// 配置文件支持两种写法:
// 1、返回一个 function,执行改方法返回一个对象
// 2、普通 JS 对象
if (lodash.isFunction(content)) {
return lodash.merge(a, content(this.app));
}
else if (lodash.isPlainObject(content)) {
return lodash.merge(a, content);
}
}, config);
});
this.app.config = config;
util_1.outputJsonSync(`${this.app.ROOT_PATH}/run/config.json`, config);
}
'use strict';
const lodash = require('lodash');
const Loader = require('../core/Loader');
const Util = require('../core/lib/util');
class AstroboyConfigLoader extends Loader {
load() {
let config = {};
this.globDirs(this.config.pattern, entries => {
config = entries.reduce((a, b) => {
let content = require(b);
// 配置文件支持两种写法:
// 1、返回一个 function,执行改方法返回一个对象
// 2、普通 JS 对象
if (lodash.isFunction(content)) {
return lodash.merge(a, content(this.app));
} else if (lodash.isPlainObject(content)) {
return lodash.merge(a, content);
}
}, config);
});
this.app.config = config;
Util.outputJsonSync(`${this.app.ROOT_PATH}/run/config.json`, config);
}
}
module.exports = AstroboyConfigLoader;
//# sourceMappingURL=AstroboyConfigLoader.js.map

@@ -1,21 +0,22 @@

"use strict";
const glob = require("fast-glob");
const Loader_1 = require("../core/Loader");
class AstroboyControllerLoader extends Loader_1.Loader {
load() {
const app = this.app;
let controllers = {};
const entries = glob.sync([`${app.ROOT_PATH}${this.config.pattern}`], {
dot: true,
});
entries
.filter(i => !i.includes('.d.ts'))
.forEach(entry => {
const key = this.resolveExtensions(entry.split('controllers/')[1], true);
controllers[key] = require(entry);
});
app.controllers = controllers;
}
'use strict';
const glob = require('fast-glob');
const Loader = require('../core/Loader');
class AstroboyControllerLoader extends Loader {
load() {
const app = this.app;
let controllers = {};
const entries = glob.sync([`${app.ROOT_PATH}${this.config.pattern}`], {
dot: true,
});
entries
.filter(i => !i.includes('.d.ts'))
.forEach(entry => {
const key = this.resolveExtensions(entry.split('controllers/')[1], true);
controllers[key] = require(entry);
});
app.controllers = controllers;
}
}
module.exports = AstroboyControllerLoader;
//# sourceMappingURL=AstroboyControllerLoader.js.map

@@ -1,4 +0,2 @@

"use strict";
const Loader_1 = require("../core/Loader");
const BaseClass_1 = require("../core/base/BaseClass");
'use strict';
const requestProto = require('koa/lib/request');

@@ -9,37 +7,44 @@ const responseProto = require('koa/lib/response');

const completeAssign = require('complete-assign');
class AstroboyExtendLoader extends Loader_1.Loader {
load() {
// application extend
this.globDirs(this.config.applicationPattern || [], entries => {
entries.forEach(entry => {
completeAssign(applicationProto, require(entry));
});
});
// context extend
this.globDirs(this.config.contextPattern || [], entries => {
entries.forEach(entry => {
completeAssign(contextProto, require(entry));
});
});
// request extend
this.globDirs(this.config.requestPattern || [], entries => {
entries.forEach(entry => {
completeAssign(requestProto, require(entry));
});
});
// response extend
this.globDirs(this.config.responsePattern || [], entries => {
entries.forEach(entry => {
completeAssign(responseProto, require(entry));
});
});
// controller extend
this.globDirs(this.config.controllerPattern || [], entries => {
entries.forEach(entry => {
completeAssign(BaseClass_1.BaseClass.prototype, require(entry));
});
});
}
const Loader = require('../core/Loader');
const baseClassProto = require('../core/base/BaseClass').prototype;
class AstroboyExtendLoader extends Loader {
load() {
// application extend
this.globDirs(this.config.applicationPattern, entries => {
entries.forEach(entry => {
completeAssign(applicationProto, require(entry));
});
});
// context extend
this.globDirs(this.config.contextPattern, entries => {
entries.forEach(entry => {
completeAssign(contextProto, require(entry));
});
});
// request extend
this.globDirs(this.config.requestPattern, entries => {
entries.forEach(entry => {
completeAssign(requestProto, require(entry));
});
});
// response extend
this.globDirs(this.config.responsePattern, entries => {
entries.forEach(entry => {
completeAssign(responseProto, require(entry));
});
});
// controller extend
this.globDirs(this.config.controllerPattern, entries => {
entries.forEach(entry => {
completeAssign(baseClassProto, require(entry));
});
});
}
}
module.exports = AstroboyExtendLoader;
//# sourceMappingURL=AstroboyExtendLoader.js.map

@@ -1,28 +0,29 @@

"use strict";
const fs = require("fs");
const Loader_1 = require("../core/Loader");
class AstroboyLibLoader extends Loader_1.Loader {
load() {
let libs = {};
this.dirs.forEach(item => {
const indexFile = `${item.baseDir}/app/lib/index.js`;
if (fs.existsSync(indexFile)) {
libs[item.name] = require(indexFile);
}
else {
this.globDir(item.baseDir, this.config.pattern || [], entries => {
if (entries.length > 0) {
libs[item.name] = {};
entries.forEach(entry => {
const key = this.resolveExtensions(entry.split('lib/')[1], true);
libs[item.name][key] = require(entry);
});
}
});
}
'use strict';
const fs = require('fs');
const Loader = require('../core/Loader');
class AstroboyLibLoader extends Loader {
load() {
let libs = {};
this.dirs.forEach(item => {
const indexFile = `${item.baseDir}/app/lib/index.js`;
if (fs.existsSync(indexFile)) {
libs[item.name] = require(indexFile);
} else {
this.globDir(item.baseDir, this.config.pattern, entries => {
if (entries.length > 0) {
libs[item.name] = {};
entries.forEach(entry => {
const key = this.resolveExtensions(entry.split('lib/')[1], true);
libs[item.name][key] = require(entry);
});
}
});
this.app.libs = libs;
}
}
});
this.app.libs = libs;
}
}
module.exports = AstroboyLibLoader;
//# sourceMappingURL=AstroboyLibLoader.js.map

@@ -1,45 +0,53 @@

"use strict";
const path = require("path");
const lodash = require("lodash");
const Loader_1 = require("../core/Loader");
const util_1 = require("../core/lib/util");
class AstroboyMiddlewareLoader extends Loader_1.Loader {
load() {
// 加载中间件配置
let middlewareConfig = {};
this.globDirs(this.config.configPattern || [], entries => {
entries.forEach(entry => {
middlewareConfig = lodash.merge(middlewareConfig, require(entry));
});
});
this.app.middlewareConfig = middlewareConfig;
// 加载中间件
let middlewares = {};
this.globDirs(this.config.pattern || [], entries => {
entries.forEach(entry => {
const key = this.resolveExtensions(path.basename(entry));
middlewares[key] = require(entry);
});
});
this.app.middlewares = middlewares;
// 生成中间件加载顺序
let middlewareQueue = [];
Object.keys(middlewareConfig).forEach(item => {
middlewareQueue.push(Object.assign({
priority: 300,
name: item,
}, middlewareConfig[item]));
});
middlewareQueue = middlewareQueue
.filter(item => {
return item.enable === true;
})
.sort((a, b) => {
return a.priority - b.priority;
});
this.app.middlewareQueue = middlewareQueue;
util_1.outputJsonSync(`${this.app.ROOT_PATH}/run/middlewares.json`, middlewareQueue);
}
'use strict';
const path = require('path');
const lodash = require('lodash');
const Loader = require('../core/Loader');
const Util = require('../core/lib/util');
class AstroboyMiddlewareLoader extends Loader {
load() {
// 加载中间件配置
let middlewareConfig = {};
this.globDirs(this.config.configPattern, entries => {
entries.forEach(entry => {
middlewareConfig = lodash.merge(middlewareConfig, require(entry));
});
});
this.app.middlewareConfig = middlewareConfig;
// 加载中间件
let middlewares = {};
this.globDirs(this.config.pattern, entries => {
entries.forEach(entry => {
const key = this.resolveExtensions(path.basename(entry));
middlewares[key] = require(entry);
});
});
this.app.middlewares = middlewares;
// 生成中间件加载顺序
let middlewareQueue = [];
Object.keys(middlewareConfig).forEach(item => {
middlewareQueue.push(
Object.assign(
{
priority: 300,
name: item,
},
middlewareConfig[item]
)
);
});
middlewareQueue = middlewareQueue
.filter(item => {
return item.enable === true;
})
.sort((a, b) => {
return a.priority - b.priority;
});
this.app.middlewareQueue = middlewareQueue;
Util.outputJsonSync(`${this.app.ROOT_PATH}/run/middlewares.json`, middlewareQueue);
}
}
module.exports = AstroboyMiddlewareLoader;
//# sourceMappingURL=AstroboyMiddlewareLoader.js.map

@@ -1,14 +0,16 @@

"use strict";
const path = require("path");
const fs = require("fs");
const Loader_1 = require("../core/Loader");
class AstroboyPkgLoader extends Loader_1.Loader {
load() {
const pkgPath = path.resolve(__dirname, '../package.json');
if (fs.existsSync(pkgPath)) {
this.app.pkg = require(pkgPath);
}
'use strict';
const path = require('path');
const fs = require('fs');
const Loader = require('../core/Loader');
class AstroboyPkgLoader extends Loader {
load() {
const pkgPath = path.resolve(__dirname, '../package.json');
if (fs.existsSync(pkgPath)) {
this.app.pkg = require(pkgPath);
}
}
}
module.exports = AstroboyPkgLoader;
//# sourceMappingURL=AstroboyPkgLoader.js.map

@@ -1,42 +0,42 @@

"use strict";
const fs = require("fs-extra");
const glob = require("fast-glob");
// @ts-ignore typings missing
const methods = require("methods");
const Loader_1 = require("../core/Loader");
class AstroboyRouterLoader extends Loader_1.Loader {
load() {
let routers = [];
const indexFile = `${this.app.ROOT_PATH}/app/routers/index.js`;
if (fs.existsSync(indexFile)) {
routers = require(indexFile);
}
else {
const entries = glob.sync([`${this.app.ROOT_PATH}${this.config.pattern}`], {
dot: true,
});
entries.forEach(entry => {
routers = routers.concat(require(entry));
});
}
const controllers = this.app.controllers;
let newRouters = [];
routers.forEach(router => {
// 如果第一个参数不是 routerName,则添加空参数名
if (methods.indexOf(router[0].toLowerCase()) > -1) {
router.unshift('');
}
newRouters.push({
name: router[0],
verb: router[1].toLowerCase(),
path: Array.isArray(router[2]) ? router[2] : [router[2]],
controller: controllers[router[3]],
methods: Array.isArray(router[4]) ? router[4] : [router[4]],
controllerName: router[3],
});
});
this.app.routers = newRouters;
'use strict';
const fs = require('fs-extra');
const glob = require('fast-glob');
const methods = require('methods');
const Loader = require('../core/Loader');
class AstroboyRouterLoader extends Loader {
load() {
let routers = [];
const indexFile = `${this.app.ROOT_PATH}/app/routers/index.js`;
if (fs.existsSync(indexFile)) {
routers = require(indexFile);
} else {
const entries = glob.sync([`${this.app.ROOT_PATH}${this.config.pattern}`], {
dot: true,
});
entries.forEach(entry => {
routers = routers.concat(require(entry));
});
}
const controllers = this.app.controllers;
let newRouters = [];
routers.forEach(router => {
// 如果第一个参数不是 routerName,则添加空参数名
if (methods.indexOf(router[0].toLowerCase()) > -1) {
router.unshift('');
}
newRouters.push({
name: router[0],
verb: router[1].toLowerCase(),
path: Array.isArray(router[2]) ? router[2] : [router[2]],
controller: controllers[router[3]],
methods: Array.isArray(router[4]) ? router[4] : [router[4]],
controllerName: router[3],
});
});
this.app.routers = newRouters;
}
}
module.exports = AstroboyRouterLoader;
//# sourceMappingURL=AstroboyRouterLoader.js.map

@@ -1,28 +0,28 @@

"use strict";
const fs = require("fs-extra");
const Loader_1 = require("../core/Loader");
class AstroboyServiceLoader extends Loader_1.Loader {
load() {
let services = {};
this.dirs.forEach(item => {
const indexFile = `${item.baseDir}/app/services/index.js`;
if (fs.existsSync(indexFile)) {
services[item.name] = require(indexFile);
}
else {
this.globDir(item.baseDir, this.config.pattern || [], entries => {
if (entries.length > 0) {
services[item.name] = {};
entries.forEach(entry => {
const key = this.resolveExtensions(entry.split('services/')[1], true);
services[item.name][key] = require(entry);
});
}
});
}
'use strict';
const fs = require('fs-extra');
const Loader = require('../core/Loader');
class AstroboyServiceLoader extends Loader {
load() {
let services = {};
this.dirs.forEach(item => {
const indexFile = `${item.baseDir}/app/services/index.js`;
if (fs.existsSync(indexFile)) {
services[item.name] = require(indexFile);
} else {
this.globDir(item.baseDir, this.config.pattern, entries => {
if (entries.length > 0) {
services[item.name] = {};
entries.forEach(entry => {
const key = this.resolveExtensions(entry.split('services/')[1], true);
services[item.name][key] = require(entry);
});
}
});
this.app.services = services;
}
}
});
this.app.services = services;
}
}
module.exports = AstroboyServiceLoader;
//# sourceMappingURL=AstroboyServiceLoader.js.map

@@ -1,21 +0,24 @@

"use strict";
const glob = require("fast-glob");
const path = require("path");
const Loader_1 = require("../core/Loader");
class AstroboyVersionFileLoader extends Loader_1.Loader {
load() {
let versionMap = {};
this.dirs.forEach(item => {
const entries = glob.sync([`${item.baseDir}${this.config.pattern}`], {
dot: true,
});
entries.forEach(entry => {
const key = path.basename(entry, '.json');
versionMap[key] = require(entry);
});
});
this.app.versionMap = versionMap;
}
'use strict';
const glob = require('fast-glob');
const path = require('path');
const Loader = require('../core/Loader');
class AstroboyVersionFileLoader extends Loader {
load() {
let versionMap = {};
this.dirs.forEach(item => {
const entries = glob.sync([`${item.baseDir}${this.config.pattern}`], {
dot: true,
});
entries.forEach(entry => {
const key = path.basename(entry, '.json');
versionMap[key] = require(entry);
});
});
this.app.versionMap = versionMap;
}
}
module.exports = AstroboyVersionFileLoader;
//# sourceMappingURL=AstroboyVersionFileLoader.js.map
{
"name": "astroboy",
"version": "1.1.0-beta.16",
"version": "1.1.0",
"description": "Astroboy(阿童木)is a Nodejs SFB(Separation of Front and Back ends) framework, built on koa2.",
"main": "index.js",
"types": "index.d.ts",
"scripts": {

@@ -21,5 +20,2 @@ "release": "sh release.sh",

"dependencies": {
"@types/fs-extra": "^5.1.0",
"@types/koa": "^2.0.46",
"@types/lodash": "^4.14.123",
"chalk": "2.4.0",

@@ -39,8 +35,8 @@ "complete-assign": "0.0.2",

"path-to-regexp": "2.2.1",
"tslib": "1.9.3",
"xss": "0.3.7"
},
"devDependencies": {
"vuepress": "^1.0.0-alpha.42"
"@types/koa": "^2.0.46",
"vuepress": "^1.0.3"
}
}

@@ -1,14 +0,11 @@

"use strict";
/**
* 请求体解析中间件
*/
const koaBody = require("koa-body");
// @ts-ignore typings missed
const bodyParser = require("koa-bodyparser");
const factory = (options, app) => {
const fn = options.parser === 'koa-bodyparser' ? bodyParser(options) : koaBody(options);
fn._name = 'body';
return fn;
};
module.exports = factory;
//# sourceMappingURL=astroboy-body.js.map
const koaBody = require('koa-body');
const bodyParser = require('koa-bodyparser');
module.exports = (options, app) => {
let fn = options.parser === 'koa-bodyparser' ? bodyParser(options) : koaBody(options);
fn._name = 'body';
return fn;
};

@@ -1,20 +0,18 @@

"use strict";
const path = require("path");
const config = {
'astroboy-body': {
priority: 15,
enable: true,
options: {
formidable: {
uploadDir: path.resolve('/tmp'),
},
multipart: true,
jsonLimit: '3mb',
formLimit: '3mb',
textLimit: '3mb',
strict: false,
},
},
};
module.exports = config;
//# sourceMappingURL=middleware.default.js.map
const path = require('path');
module.exports = {
'astroboy-body': {
priority: 15,
enable: true,
options: {
formidable: {
uploadDir: path.resolve('/tmp')
},
multipart: true,
jsonLimit: '3mb',
formLimit: '3mb',
textLimit: '3mb',
strict: false
}
}
};

@@ -1,58 +0,57 @@

"use strict";
/**
* 框架路由中间件
*/
const lodash = require("lodash");
// @ts-ignore typings missed
const KoaRouter = require("koa-router");
const compose = require("koa-compose");
const factory = function (options = {}, app) {
const koaRouter = new KoaRouter();
app.routers.forEach((router) => {
const ControllerClass = router.controller;
if (ControllerClass) {
if (lodash.isFunction(ControllerClass)) {
for (let i = 0; i < router.methods.length; i++) {
if (!ControllerClass.prototype[router.methods[i]]) {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, method:${router.methods[i]} is not found.`);
}
const lodash = require('lodash');
const KoaRouter = require('koa-router');
const compose = require('koa-compose');
module.exports = function (options = {}, app) {
const koaRouter = new KoaRouter();
app.routers.forEach(router => {
const ControllerClass = router.controller;
if (ControllerClass) {
if (lodash.isFunction(ControllerClass)) {
for (let i = 0; i < router.methods.length; i++) {
if (!ControllerClass.prototype[router.methods[i]]) {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, method:${router.methods[i]} is not found.`);
}
}
router.path.forEach(item => {
koaRouter[router.verb](router.name, item, async function (ctx, next) {
const controller = new ControllerClass(ctx);
// init 是 Controller 类初始化后调用的一个方法
if (ControllerClass.prototype.init) {
await controller['init']();
}
if (ctx.status !== 301 && ctx.status !== 302) {
for (let i = 0; i < router.methods.length; i++) {
let method = router.methods[i];
const beforeMethod = 'before' + method.slice(0, 1).toUpperCase() + method.slice(1);
if (ControllerClass.prototype[beforeMethod]) {
await controller[beforeMethod]();
}
router.path.forEach((item) => {
koaRouter[router.verb](router.name, item, async function (ctx, next) {
const controller = new ControllerClass(ctx);
// init 是 Controller 类初始化后调用的一个方法
if (ControllerClass.prototype.init) {
await controller['init']();
}
if (ctx.status !== 301 && ctx.status !== 302) {
for (let i = 0; i < router.methods.length; i++) {
let method = router.methods[i];
const beforeMethod = 'before' + method.slice(0, 1).toUpperCase() + method.slice(1);
if (ControllerClass.prototype[beforeMethod]) {
await controller[beforeMethod]();
}
if (ctx.status !== 301 && ctx.status !== 302 && !ctx.body) {
await controller[method](ctx, next);
}
else {
break;
}
}
}
});
});
if (ctx.status !== 301 && ctx.status !== 302 && !ctx.body) {
await controller[method](ctx, next);
} else {
break;
}
}
}
else {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, controllerName:${router.controllerName} is not a function.`);
}
}
else {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, controllerName:${router.controllerName} is undefined.`);
}
});
let fn = compose([koaRouter.routes(), koaRouter.allowedMethods()]);
fn._name = 'astroboy-router';
return fn;
};
module.exports = factory;
//# sourceMappingURL=astroboy-router.js.map
});
});
} else {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, controllerName:${router.controllerName} is not a function.`);
}
} else {
throw new Error(`注册路由失败,verb:${router.verb} path:${router.path}, controllerName:${router.controllerName} is undefined.`);
}
});
let fn = compose([
koaRouter.routes(),
koaRouter.allowedMethods()
]);
fn._name = 'astroboy-router';
return fn;
};

@@ -1,8 +0,7 @@

"use strict";
const config = {
'astroboy-router': {
enable: true,
},
};
module.exports = config;
//# sourceMappingURL=middleware.default.js.map
module.exports = {
'astroboy-router': {
enable: true
}
};

@@ -1,6 +0,6 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
var assert = require('assert');
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const length = Buffer.byteLength(chars);
const length = Buffer.byteLength(chars)
/**

@@ -11,10 +11,11 @@ * 生成一个长度为 len 的字符串

function randomString(len = 10) {
assert(typeof len === 'number' && len >= 0, 'the length of the random string must be a number!');
var str = '';
for (var i = 0; i < len; i++) {
str += chars[Math.floor(length * Math.random())];
}
return str;
assert(typeof len === 'number' && len >= 0, 'the length of the random string must be a number!')
var str = ''
for (var i = 0; i < len; i++) {
str += chars[Math.floor(length * Math.random())];
}
return str
}
exports.randomString = randomString;
//# sourceMappingURL=randomString.js.map
module.exports = randomString;

@@ -1,45 +0,56 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const crypto = require("crypto");
const randomString_1 = require("./randomString");
const crypto = require('crypto');
const randomString = require('./randomString');
class Token {
get defaultOptions() {
return {
saltLength: 10,
secretLength: 18,
};
get defaultOptions() {
return {
saltLength: 10,
secretLength: 18
};
}
constructor(options = {}) {
this.options = Object.assign({}, this.defaultOptions, options);
this.saltLength = this.options.saltLength;
this.secretLength = this.options.secretLength;
}
secretSync() {
return randomString(this.secretLength);
}
create(secret) {
const salt = randomString(this.saltLength);
return this.tokenize(secret, salt);
}
tokenize(secret, salt) {
const hash = crypto
.createHash('sha1')
.update(secret, 'utf-8')
.digest('base64');
return salt + '-' + hash;
}
verify(secret, token) {
if (!secret || !token ||
typeof secret !== 'string' ||
typeof token !== 'string') {
return false;
}
constructor(options = {}) {
this.options = Object.assign({}, this.defaultOptions, options);
this.saltLength = this.options.saltLength;
this.secretLength = this.options.secretLength;
const index = token.indexOf('-');
if (index === -1) {
return false;
}
secretSync() {
return randomString_1.randomString(this.secretLength);
}
create(secret) {
const salt = randomString_1.randomString(this.saltLength);
return this.tokenize(secret, salt);
}
tokenize(secret, salt) {
const hash = crypto
.createHash('sha1')
.update(secret, 'utf8')
.digest('base64');
return salt + '-' + hash;
}
verify(secret, token) {
if (!secret || !token || typeof secret !== 'string' || typeof token !== 'string') {
return false;
}
const index = token.indexOf('-');
if (index === -1) {
return false;
}
const salt = token.substr(0, index);
const expected = this.tokenize(secret, salt);
return expected === token;
}
const salt = token.substr(0, index);
const expected = this.tokenize(secret, salt);
return expected === token;
}
}
exports.Token = Token;
//# sourceMappingURL=token.js.map
module.exports = Token;

@@ -1,9 +0,7 @@

"use strict";
/**
* Content-Security-Policy
* https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy__by_cnvoid
*
*
* Content-Security-Policy-Report-Only
* https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
*/
//# sourceMappingURL=astroboy-security-csp.js.map
*/

@@ -1,51 +0,56 @@

"use strict";
/**
* CSRF
*/
const token_1 = require("../lib/token");
const Token = require('../lib/token');
class CsrfError extends Error {
constructor(code, msg) {
super(`code: ${code}, msg: ${msg}`);
this.errorContent = {
code,
msg,
};
this.errorType = 'CsrfError';
constructor(code, msg) {
super(`code: ${code}, msg: ${msg}`);
this.errorContent = {
code,
msg
};
this.errorType = 'CsrfError';
}
}
module.exports = function (options = {}, app) {
let token = new Token({
saltLength: options.saltLength,
secretLength: options.secretLength
});
return async function csrf(ctx, next) {
if (options.excluded.indexOf(ctx.method) === -1 &&
options.env.indexOf(process.env.NODE_ENV) > -1) {
const csrfSecret = ctx.cookies.get(options.csrfSecretName);
const csrfToken = ctx.header[options.csrfTokenName];
// token 或 secret 不存在
if (!csrfSecret || !csrfToken) {
throw new CsrfError(1000, 'CSRF Token Not Found!');
}
// token 校验失败
if (!token.verify(csrfSecret, csrfToken)) {
throw new CsrfError(1001, 'CSRF token Invalid!');
}
}
}
const factory = function (options = {}, app) {
let token = new token_1.Token({
saltLength: options.saltLength,
secretLength: options.secretLength,
});
return async function csrf(ctx, next) {
if ((options.excluded || []).indexOf(ctx.method) === -1 &&
(options.env || []).indexOf(process.env.NODE_ENV) > -1) {
const csrfSecret = ctx.cookies.get(options.csrfSecretName);
const csrfToken = ctx.header[options.csrfTokenName];
// token 或 secret 不存在
if (!csrfSecret || !csrfToken) {
throw new CsrfError(1000, 'CSRF Token Not Found!');
}
// token 校验失败
if (!token.verify(csrfSecret, csrfToken)) {
throw new CsrfError(1001, 'CSRF token Invalid!');
}
}
await next();
// 如果返回 HTML 格式数据,则生成
if (ctx.response.is('text/html')) {
const secret = token.secretSync();
const newToken = token.create(secret);
ctx.cookies.set(options.csrfSecretName, secret, {
maxAge: options.maxAge,
});
ctx.cookies.set(options.csrfTokenName, newToken, {
maxAge: options.maxAge,
httpOnly: false,
});
}
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-csrf.js.map
await next();
// 如果返回 HTML 格式数据,则生成
if (ctx.response.is('text/html')) {
const secret = token.secretSync();
const newToken = token.create(secret);
ctx.cookies.set(options.csrfSecretName, secret, {
maxAge: options.maxAge
});
ctx.cookies.set(options.csrfTokenName, newToken, {
maxAge: options.maxAge,
httpOnly: false
});
}
};
};

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -6,9 +5,7 @@ * X-Content-Type-Options

*/
const factory = function (options = 'nosniff', app) {
return async function cto(ctx, next) {
ctx.set('X-Content-Type-Options', options);
await next();
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-cto.js.map
module.exports = function(options = 'nosniff', app) {
return async function cto(ctx, next) {
ctx.set('X-Content-Type-Options', options);
await next();
};
};

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -9,9 +8,7 @@ * X-Frame-Options

*/
const factory = function (options = 'SAMEORIGIN', app) {
return async function frameOptions(ctx, next) {
ctx.set('X-Frame-Options', options);
await next();
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-frameOptions.js.map
module.exports = function(options = 'SAMEORIGIN', app) {
return async function frameOptions(ctx, next) {
ctx.set('X-Frame-Options', options);
await next();
};
};

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -6,24 +5,25 @@ * Strict-Transport-Security

*/
const assert = require("assert");
const factory = function (options, app) {
if (typeof options === 'number') {
options = {
maxAge: options,
};
const assert = require('assert');
module.exports = function(options, app) {
if (typeof options === 'number') {
options = {
maxAge: options
}
options = options || {};
assert(typeof options.maxAge === 'number', 'options.maxAge should be a number');
let value = 'max-age=' + options.maxAge;
if (options.includeSubDomains) {
value += '; includeSubDomains';
}
if (options.preload) {
value += '; preload';
}
return async function hsts(ctx, next) {
ctx.set('Strict-Transport-Security', value);
await next();
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-hsts.js.map
}
options = options || {};
assert(typeof options.maxAge === 'number', 'options.maxAge should be a number');
let value = 'max-age=' + options.maxAge;
if (options.includeSubDomains) {
value += '; includeSubDomains';
}
if (options.preload) {
value += '; preload';
}
return async function hsts(ctx, next) {
ctx.set('Strict-Transport-Security', value);
await next();
}
};

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -7,18 +6,18 @@ * P3P - Platform for Privacy Preferences Project

*/
const assert = require("assert");
const factory = function (options, app) {
if (typeof options === 'string') {
options = {
value: options,
};
}
options = options || {};
options.value = options.value || 'p3p';
assert(typeof options.value === 'string', 'options.value should be a string');
return async function p3p(ctx, next) {
ctx.set('P3P', options.value);
await next();
const assert = require('assert');
module.exports = function(options, app) {
if (typeof options === 'string') {
options = {
value: options
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-p3p.js.map
}
options = options || {};
options.value = options.value || 'p3p';
assert(typeof options.value === 'string', 'options.value should be a string');
return async function p3p(ctx, next) {
ctx.set('P3P', options.value);
await next();
};
};

@@ -1,35 +0,38 @@

"use strict";
const lodash = require("lodash");
const xss = require("xss");
const factory = (options, app) => {
const myxss = new xss.FilterXSS(options);
const deepXss = function (value, deep = true) {
let res;
if (Array.isArray(value) && value.length > 0) {
res = [];
const lodash = require('lodash');
const xss = require('xss');
module.exports = (options, app) => {
const myxss = new xss.FilterXSS(options);
const deepXss = function(value, deep = true) {
let res;
if (Array.isArray(value) && value.length > 0) {
res = [];
} else if (lodash.isPlainObject(value) && Object.keys(value).length > 0) {
res = {};
} else {
if (typeof value === 'string') {
return myxss.process(value.trim());
}
return value;
}
return lodash.reduce(
value,
(result, val, key) => {
if (deep) {
val = deepXss(val);
}
else if (lodash.isPlainObject(value) && Object.keys(value).length > 0) {
res = {};
}
else {
if (typeof value === 'string') {
return myxss.process(value.trim());
}
return value;
}
return lodash.reduce(value, (result, val, key) => {
if (deep) {
val = deepXss(val);
}
result[key] = val;
return result;
}, res);
};
return async function xss(ctx, next) {
ctx.query = deepXss(ctx.query);
ctx.request.body = deepXss(ctx.request.body);
await next();
};
result[key] = val;
return result;
},
res
);
};
return async function xss(ctx, next) {
ctx.query = deepXss(ctx.query);
ctx.request.body = deepXss(ctx.request.body);
await next();
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-xss.js.map

@@ -1,2 +0,1 @@

"use strict";
/**

@@ -9,9 +8,7 @@ * X-XSS-Protection: 0 禁止XSS过滤。

*/
const factory = function (options = '1; mode=block', app) {
return async function xssProtection(ctx, next) {
ctx.set('X-XSS-Protection', options);
await next();
};
};
module.exports = factory;
//# sourceMappingURL=astroboy-security-xssProtection.js.map
module.exports = function(options = '1; mode=block', app) {
return async function xssProtection(ctx, next) {
ctx.set('X-XSS-Protection', options);
await next();
};
};

@@ -1,45 +0,47 @@

"use strict";
const config = {
'astroboy-security-csrf': {
priority: 2,
enable: false,
options: {
env: ['prod'],
excluded: ['GET', 'HEAD', 'OPTIONS'],
csrfSecretName: 'csrf_secret',
csrfTokenName: 'csrf_token',
saltLength: 10,
secretLength: 18,
maxAge: 3 * 3600 * 1000,
},
module.exports = {
'astroboy-security-csrf': {
priority: 2,
enable: false,
options: {
env: ['prod'],
excluded: ['GET', 'HEAD', 'OPTIONS'],
csrfSecretName: 'csrf_secret',
csrfTokenName: 'csrf_token',
saltLength: 10,
secretLength: 18,
maxAge: 3 * 3600 * 1000,
},
'astroboy-security-cto': {
priority: 10,
enable: true,
options: 'nosniff',
},
'astroboy-security-cto': {
priority: 10,
enable: true,
options: 'nosniff',
},
'astroboy-security-frameOptions': {
priority: 10,
enable: true,
options: 'SAMEORIGIN',
},
'astroboy-security-hsts': {
priority: 10,
enable: true,
options: {
maxAge: 365 * 24 * 3600,
},
'astroboy-security-frameOptions': {
priority: 10,
enable: true,
options: 'SAMEORIGIN',
},
'astroboy-security-hsts': {
priority: 10,
enable: true,
options: {
maxAge: 365 * 24 * 3600,
},
},
'astroboy-security-xss': {
enable: true,
priority: 20,
options: {},
},
'astroboy-security-xssProtection': {
priority: 10,
enable: true,
options: '1; mode=block',
},
},
'astroboy-security-xss': {
enable: true,
priority: 20,
options: {},
},
'astroboy-security-xssProtection': {
priority: 10,
enable: true,
options: '1; mode=block',
},
};
module.exports = config;
//# sourceMappingURL=middleware.default.js.map

@@ -1,13 +0,10 @@

"use strict";
/**
* https://github.com/koajs/static
*/
// @ts-ignore typings missed
const staticM = require("koa-static");
const factory = function (options, app) {
let fn = staticM(options.root, options);
fn._name = 'static';
return fn;
};
module.exports = factory;
//# sourceMappingURL=astroboy-static.js.map
const staticM = require('koa-static');
module.exports = function (options, app) {
let fn = staticM(options.root, options);
fn._name = 'static';
return fn;
};

@@ -1,13 +0,13 @@

"use strict";
const path = require("path");
const config = {
'astroboy-static': {
priority: 3,
enable: true,
options: {
root: path.resolve('/tmp/static'),
},
},
};
module.exports = config;
//# sourceMappingURL=middleware.default.js.map
const path = require('path');
module.exports = {
'astroboy-static': {
priority: 3,
enable: true,
options: {
root: path.resolve('/tmp/static')
}
}
}

@@ -1,8 +0,7 @@

"use strict";
const config = {
'astroboy-static': {
enable: false,
},
};
module.exports = config;
//# sourceMappingURL=middleware.prod.js.map
module.exports = {
'astroboy-static': {
enable: false
}
};

@@ -1,13 +0,13 @@

"use strict";
const ViewManager_1 = require("../lib/ViewManager");
const ViewManager = require('../lib/ViewManager');
const VIEW = Symbol('Application#view');
const app = {
get view() {
if (!this[VIEW]) {
this[VIEW] = new ViewManager_1.ViewManager(this);
}
return this[VIEW];
},
};
module.exports = app;
//# sourceMappingURL=application.js.map
module.exports = {
get view() {
if (!this[VIEW]) {
this[VIEW] = new ViewManager(this);
}
return this[VIEW];
}
};

@@ -1,24 +0,39 @@

"use strict";
const ContextView_1 = require("../lib/ContextView");
const ContextView = require('../lib/ContextView');
const VIEW = Symbol('Context#view');
const ctx = {
get view() {
if (!this[VIEW]) {
this[VIEW] = new ContextView_1.ContextView(this);
}
return this[VIEW];
},
render(...args) {
return this.renderView(...args).then((body) => {
this.body = body;
});
},
renderView(...args) {
return this.view.render(...args);
},
renderString(...args) {
return this.view.render(...args);
},
};
module.exports = ctx;
//# sourceMappingURL=context.js.map
module.exports = {
get view() {
if (!this[VIEW]) {
this[VIEW] = new ContextView(this);
}
return this[VIEW];
},
/**
* Render a file, then set to body, the parameter is same as {@link @ContextView#render}
* @return {Promise} result
*/
render(...args) {
return this.renderView(...args).then(body => {
this.body = body;
});
},
/**
* Render a file, same as {@link @ContextView#render}
* @return {Promise} result
*/
renderView(...args) {
return this.view.render(...args);
},
/**
* Render template string, same as {@link @ContextView#renderString}
* @return {Promise} result
*/
renderString(...args) {
return this.view.renderString(...args); // NOTE: 不存在这个方法
},
}

@@ -1,48 +0,57 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const assert = require("assert");
const path = require('path');
const assert = require('assert');
const RENDER = Symbol.for('contextView#render');
const RENDER_STRING = Symbol.for('contextView#renderString');
const GET_VIEW_ENGINE = Symbol.for('contextView#getViewEngine');
class ContextView {
constructor(ctx) {
this.ctx = ctx;
this.app = this.ctx.app;
this.viewManager = this.app.view;
this.config = this.app.view.config;
constructor(ctx) {
this.ctx = ctx;
this.app = this.ctx.app;
this.viewManager = this.app.view;
this.config = this.app.view.config;
}
render(...args) {
return this[RENDER](...args);
}
async [RENDER](name, state = {}, options = {}) {
const filename = await this.viewManager.resolve(name);
// get the name of view engine,
// if viewEngine is specified in options, don't match extension
let viewEngineName = options.viewEngine;
if (!viewEngineName) {
const ext = path.extname(filename);
viewEngineName = this.viewManager.extMap.get(ext);
}
render(...args) {
return this[RENDER](...args);
// use the default view engine that is configured if no matching above
if (!viewEngineName) {
viewEngineName = this.config.defaultViewEngine;
}
async [RENDER](name, state = {}, options = {}) {
const filename = await this.viewManager.resolve(name);
// get the name of view engine,
// if viewEngine is specified in options, don't match extension
let viewEngineName = options.viewEngine;
if (!viewEngineName) {
const ext = path.extname(filename);
viewEngineName = this.viewManager.extMap.get(ext);
}
// use the default view engine that is configured if no matching above
if (!viewEngineName) {
viewEngineName = this.config.defaultViewEngine;
}
assert(viewEngineName, `Can't find viewEngine for ${filename}`);
// get view engine and render
const view = this[GET_VIEW_ENGINE](viewEngineName);
return await view.render(filename, state, options);
}
[GET_VIEW_ENGINE](name) {
const ViewEngine = this.viewManager.get(name);
assert(ViewEngine, `Can't find ViewEngine "${name}"`);
// use view engine to render
const engine = new ViewEngine(this.ctx);
// wrap render and renderString to support both async function and generator function
// if (engine.render) engine.render = this.app.toAsyncFunction(engine.render);
// if (engine.renderString) engine.renderString = this.app.toAsyncFunction(engine.renderString);
return engine;
}
assert(viewEngineName, `Can't find viewEngine for ${filename}`);
// get view engine and render
const view = this[GET_VIEW_ENGINE](viewEngineName);
return await view.render(filename, state, options);
}
[GET_VIEW_ENGINE](name) {
const ViewEngine = this.viewManager.get(name);
assert(ViewEngine, `Can't find ViewEngine "${name}"`);
// use view engine to render
const engine = new ViewEngine(this.ctx);
// wrap render and renderString to support both async function and generator function
// if (engine.render) engine.render = this.app.toAsyncFunction(engine.render);
// if (engine.renderString) engine.renderString = this.app.toAsyncFunction(engine.renderString);
return engine;
}
}
exports.ContextView = ContextView;
//# sourceMappingURL=ContextView.js.map
module.exports = ContextView;

@@ -1,69 +0,79 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const path = require("path");
const fs = require("fs-extra");
const assert = require('assert');
const path = require('path');
const fs = require('fs-extra');
class ViewManager extends Map {
/**
* @param {Application} app - application instance
*/
constructor(app) {
super();
this.config = app.config.view;
if (typeof this.config.root === 'string') {
this.config.root = [this.config.root];
}
this.extMap = new Map();
this.fileMap = new Map();
for (const ext of Object.keys(this.config.mapping)) {
this.extMap.set(ext, this.config.mapping[ext]);
}
/**
* @param {Application} app - application instance
*/
constructor(app) {
super();
this.config = app.config.view;
if (typeof this.config.root === 'string') {
this.config.root = [this.config.root];
}
/**
* This method can register view engine.
*
* You can define a view engine class contains two method, `render` and `renderString`
*
* ```js
* class View {
* render() {}
* renderString() {}
* }
* ```
* @param {String} name - the name of view engine
* @param {Object} viewEngine - the class of view engine
*/
use(name, viewEngine) {
assert(name, 'name is required');
assert(!this.has(name), `${name} has been registered`);
assert(viewEngine, 'viewEngine is required');
assert(viewEngine.prototype.render, 'viewEngine should implement `render` method');
assert(viewEngine.prototype.renderString, 'viewEngine should implement `renderString` method');
this.set(name, viewEngine);
this.extMap = new Map();
this.fileMap = new Map();
for (const ext of Object.keys(this.config.mapping)) {
this.extMap.set(ext, this.config.mapping[ext]);
}
async resolve(name) {
const config = this.config;
// check cache
let filename = this.fileMap.get(name);
if (config.cache && filename) {
return filename;
}
// try find it with default extension
filename = this.resolvePath([name, name + config.defaultExtension], config.root);
// set cache
this.fileMap.set(name, filename);
return filename;
}
/**
* This method can register view engine.
*
* You can define a view engine class contains two method, `render` and `renderString`
*
* ```js
* class View {
* render() {}
* renderString() {}
* }
* ```
* @param {String} name - the name of view engine
* @param {Object} viewEngine - the class of view engine
*/
use(name, viewEngine) {
assert(name, 'name is required');
assert(!this.has(name), `${name} has been registered`);
assert(viewEngine, 'viewEngine is required');
assert(viewEngine.prototype.render, 'viewEngine should implement `render` method');
assert(viewEngine.prototype.renderString, 'viewEngine should implement `renderString` method');
this.set(name, viewEngine);
}
async resolve(name) {
const config = this.config;
// check cache
let filename = this.fileMap.get(name);
if (config.cache && filename) {
return filename;
}
resolvePath(names, root) {
for (const name of names) {
for (const dir of root) {
const filename = path.resolve(dir, name);
if (fs.existsSync(filename)) {
return filename;
}
}
// try find it with default extension
filename = this.resolvePath([name, name + config.defaultExtension], config.root);
// set cache
this.fileMap.set(name, filename);
return filename;
}
resolvePath(names, root) {
for (const name of names) {
for (const dir of root) {
const filename = path.resolve(dir, name);
if (fs.existsSync(filename)) {
return filename;
}
}
}
}
}
exports.ViewManager = ViewManager;
//# sourceMappingURL=ViewManager.js.map
module.exports = ViewManager;

@@ -1,15 +0,15 @@

"use strict";
const path = require("path");
const config = app => {
return {
view: {
root: path.join(app.ROOT_PATH, 'app/views'),
cache: true,
defaultExtension: '.html',
defaultViewEngine: '',
mapping: {},
},
};
};
module.exports = config;
//# sourceMappingURL=config.default.js.map
const path = require('path');
module.exports = app => {
return {
view: {
root: path.join(app.ROOT_PATH, 'app/views'),
cache: true,
defaultExtension: '.html',
defaultViewEngine: '',
mapping: {}
}
}
}

@@ -1,8 +0,7 @@

"use strict";
const config = {
view: {
cache: false,
},
};
module.exports = config;
//# sourceMappingURL=config.development.js.map
module.exports = {
view: {
cache: false
}
}
# Astroboy
Astroboy(阿童木)is a Nodejs SFB(Separation of Front and Back ends) framework, built on koa2.
[![npm version](https://badge.fury.io/js/astroboy.svg)](https://badge.fury.io/js/astroboy)
## Install
```zsh
yarn add astroboy
```
## Run app with node
### 1. Compile project
```zsh
tsc && cp config app/config
```
### 2. Start app.js
```zsh
cd dist && node app/app.js
```
## Run app with ts-node
### 1. install ts-node and typescript
```zsh
yarn add typescript ts-node
```
### 2. Start app
```zsh
npx ts-node app/app.ts
```
## Run app in development mode
- use [astroboy-cli](https://www.npmjs.com/package/astroboy-cli) for js or js/ts hybrid project
- use [@exoskeleton/cli](https://www.npmjs.com/package/@exoskeleton/cli) for typescript-only project
## More details
> For more details, please refer to [https://astroboy-lab.github.io/astroboy](https://astroboy-lab.github.io/astroboy)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc