UNPKG

mm_os

Version:

这是超级美眉服务端框架,用于快速构建应用程序。

220 lines (210 loc) 5.2 kB
const fs = require("fs"); const send = require('koa-send'); const conf = require('mm_config'); const Item = require('mm_machine').Item; /** * Plugin插件驱动类 * @extends {Item} * @class */ class Drive extends Item { /** * 构造函数 * @param {String} dir 当前目录 * @param {Object} config 配置 * @constructor */ constructor(dir) { super(dir, __dirname); this.default_file = "./static.json"; // 更新并重载 this.mode = 3; /* 通用项 */ // 配置参数 this.config = { // 名称, 由中英文和下“_”组成, 用于修改或卸载 例如: demo "name": "", // 状态 0未启用,1启用 "state": 1, // 标题 "title": "", // 应用名 "app": "", // 插件 "plugin": "", // 物理根目录 "root": "", // 路由根路径 "path": "/", // 首页 "index": "index.html", // 重定向 "redirect": true, // 缓存保留10分钟 "maxAge": 1000 * 60 * 10, // 是否保持不变 "immutable": true, // 是否启用brotli压缩 "brotli": true, // 是否启用gizp压缩 "gzip": true, // 允许访问的拓展名 "extensions": null, // 处理函数 "func_file": "", // 执行函数名 "func_name": "", // 是否将ES6转换AMD "convert_amd": true }; } } /** * 发送文件函数 */ Drive.prototype.send = send; /** * 加载配置对象前 * @param {Object} config 配置对象 */ Drive.prototype.set_config = function(config) { if (config) { if (config.maxAge) { config.maxAge *= 1000; } } this.config = conf(Object.assign({}, this.config, config || {}), this.filename); this.run_mode(this.config.convert_amd); }; /** * 执行前 * @param {Object} ctx http请求上下文 * @param {Object} path 文件路径 */ Drive.prototype.before = async function(ctx, path) {}; /** * 执行 * @param {Object} ctx http请求上下文 * @param {Object} path 文件路径 * @return {Boolean} 成功发送返回true,失败返回false */ Drive.prototype.main = async function(ctx, path) { return send(ctx, path, this.config); }; /** * 执行后 * @param {Object} ctx http请求上下文 * @param {Object} path 文件路径 */ Drive.prototype.after = async function(ctx, path) {}; /** * 切换运行模式 * @param {Boolean} convert_amd 是否将ES6转换AMD */ Drive.prototype.run_mode = async function(convert_amd) { var cg = this.config; if (convert_amd) { this.main = async function main(ctx, path) { if (path.endsWith('.vue') || path.endsWith('.js')) { var file = ("." + path).fullname(this.dir); var code; var str = file.loadText(); try { if (str && str.indexOf('@/') !== -1) { var arr = ctx.request.href.split('/'); var word = arr[0] + "//" + arr[2] + "/"; str = str.replaceAll('@/', word); } code = $.es6_to_amd(str); } catch (e) { throw e } if (code) { if (path.endsWith('.js')) { ctx.response.type = "application/javascript; charset=utf-8"; } else { ctx.response.type = "text/html; charset=utf-8"; } ctx.body = code; var age = cg.maxAge; if (age) { if (cg.immutable) { ctx.set('Cache-Control', 'max-age=' + (age / 1000) + ",immutable"); } else { ctx.set('Cache-Control', 'max-age=' + (age / 1000)); } } return file; } } else { return send(ctx, path, cg); } } } else { this.main = async function(ctx, path) { return send(ctx, path, cg); } } return null; }; /** * 执行静态文件 * @param {Object} ctx Http请求上下文 * @param {Object} path 路由路径 * @param {Object} next 跳过当前函数 * @return {String} 执行成功返回文件路径 */ Drive.prototype.run = async function(ctx, path, next) { var done; var cg = this.config; var ph = cg.path; try { if (path.startWith(ph)) { var p = path.replace(ph, ''); if (p.indexOf('.') !== -1) { this.before(ctx, p); try { done = await this.main(ctx, p); this.after(ctx, p, done); } catch (err) { if (err.status !== 404) { throw err; } } } else { done = ' '; if (ctx.status === 404) { var file; // 取到物理路径 var root = this.dir; var dir = p.fullname(root); if (!p) { file = dir + '/' + cg.index; } else if (p.endWith('/')) { file = dir + cg.index; } else { file = dir + '.html'; } if (file.hasFile()) { p = file.replace(root, ''); this.before(ctx, p); done = await this.main(ctx, p); this.after(ctx, p, done); } else if (cg.redirect) { var file = root + '/index.html'; if (file.hasFile()) { p = '/index.html'; this.before(ctx, p); done = await this.main(ctx, p); this.after(ctx, p, done); } } } } } } catch (err) { $.log.error("静态文件执行错误", this.config.name, err); } return done; }; module.exports = Drive;