UNPKG

titbit-loader

Version:
223 lines (184 loc) 8.29 kB
#!/usr/bin/env node 'use strict' let type_context = `//!!注意:以下注释是为了能够在支持jsdoc的代码编辑器中提示以及方便查阅提供,不需要可以去掉。 /** * ---------------------- ctx.ext模块具备的方法 ----------------------------- * * @typedef {object} ext * @property {function} extName(filename: string) - 解析文件扩展名。 * @property {function} makeName(filename: string) - 生成唯一文件名,默认为时间字符串+随机数:2021-01-01_12-12-23_27789.jpg,filename主要用于获取扩展名。 * @property {function} nrand(n, m) - 返回两个数之间的随机数。 * @property {function} uuid() - 返回唯一字符串用于唯一ID,支持标准的8-4-4-4-12和短字符串8-2-2-4两种模式(传递参数为true)。 * @property {function} timestr() - 默认返回年-月-日_时-分-秒,没有空格,方便保存和解析。 * @property {function} sha1(text, encoding = 'hex') * @property {function} sha256(text, encoding = 'hex') * @property {function} sha512(text, encoding = 'hex') * @property {function} sm3(text, encoding = 'hex') * @property {function} hmacsha1(text, key, encoding = 'hex') * @property {function} pipe(filename: string, reply: object) * * 更多参考:{@link https://gitee.com/daoio/titbit/wikis/helper-function} */ /** * --------------------------------- 请求上下文 ----------------------------------------- * * @typedef {object} context * @property {string} version - 协议版本,字符串类型,为'1.1' 或 '2' 或 '3'。 * @property {number} major - 协议主要版本号,1、2、3分别表示HTTP/1.1 HTTP/2 HTTP/3。 * @property {string} method - 请求类型,GET POST等HTTP请求类型,大写字母的字符串。 * @property {string} path - 具体请求的路径,比如 /x/y。 * @property {string} routepath - 实际执行请求的路由字符串,比如 /x/:id。 * @property {boolean} isUpload - 是否为上传文件请求,此时就是检测消息头content-type是否为multipart/form-data格式。 * @property {object} box - 默认为空对象,可以添加任何属性值,用来动态传递给下一层组件需要使用的信息。 * @property {object} query - url传递的参数。 * @property {object} param - 路由参数。 * @property {object} headers - 指向request.headers。 * @property {object} files - 上传文件保存的信息。 * @property {(object|string|buffer|null)} body - body请求体的数据,具体格式需要看content-type,一般为字符串或者对象,也可能是buffer。 * @property {object} request HTTP/1.1 - 就是http模块request事件的参数IncomingMessage对象,HTTP/2 指向stream对象。 * @property {object} reply - HTTP/1.1协议,指向response,HTTP/2 指向stream。 * @property {object} service - 用于依赖注入的对象,指向app.service。 * @property {function} moveFile(file: object) - 用来移动上传的文件到指定路径,file是通过getFile获取的文件对象。 * @property {function} getFile(name: string, index = 0) - 根据上传名获取上传的文件,如果index是-1表示获取整个数组。 * @property {function} sendHeader() - 发送消息头,针对http/2设计,http/1.1只是一个空函数,为了代码保持一致。 * @property {function} setHeader(key: string, value: string|array) * @property {function} send(body: string|object|buffer) - 设置要返回的body数据。 * @property {function} status(code: null | number) - 设置状态码,默认为null表示返回状态码。 * @property {ext} ext - 指向ext模块,提供了一些助手函数,具体参考wiki。 * * 更多参考:{@link https://gitee.com/daoio/titbit/blob/master/README.md#%E8%AF%B7%E6%B1%82%E4%B8%8A%E4%B8%8B%E6%96%87} */ ` let head_hint = `/********************************************************************** 提示: 表单提交或异步请求,对应于POST或PUT请求,对应函数post和put,提交的请求体数据通过 ctx.body 获取。 路由参数通过 ctx.param 获取,示例:let id = ctx.param.id url参数(?a=1&b=2)通过 ctx.query 获取,示例:let name = ctx.query.name 使用ctx.getFile(name)获取上传的文件,示例:let f = ctx.getFile('image') **********************************************************************/\n\n` function fmt_ctx_param(text) { let ctx_param = ` /** * ${text} * @param {context} ctx * @returns */ ` return ctx_param } const fs = require('fs') function makeController (name) { return `'use strict'\n\n` + head_hint + `class ${name} {\n\n` + ` constructor() {\n` + ` //param用于指定最后的路由参数,默认就是/:id\n` + ` //若要改变路由,则可以设置此属性,比如设置为/:name\n` + ` //this.param = '/:id'\n` + ` }\n\n` + ` //控制器类初始化后会执行此函数。\n` + ` //service默认是app.service,此参数通过titbit-loader初始化的initArgs选项进行控制。\n` + ` async init(service) {\n` + ` \n` + ` }\n\n` + ` //以下方法,若不需要,要去掉,避免无意义的路由。\n` + `${fmt_ctx_param('获取资源具体内容')}` + ` async get(ctx) {\n\n` + ` }\n` + `${fmt_ctx_param('创建资源')}` + ` async post(ctx) {\n\n` + ` }\n` + `${fmt_ctx_param('更新资源')}` + ` async put(ctx) {\n\n` + ` }\n` + `${fmt_ctx_param('GET请求,用于获取资源列表')}` + ` async list(ctx) {\n\n` + ` }\n` + `${fmt_ctx_param('删除资源')}` + ` async _delete(ctx) {\n\n` + ` }\n` + `}\n\nmodule.exports = ${name}\n\n` + `${type_context}` } let limitName = [ 'async', 'await', 'for', 'of', 'if', 'else', 'switch', 'function', 'delete', 'new', 'case', 'require', 'import', 'export', 'exports', 'process', 'global', 'this', 'let', 'const', 'var', 'class', 'return', 'module', 'do', 'while', 'catch', 'try', 'break', 'boolean', 'instanceof', 'typeof', 'continue', 'fetch', 'globalThis', 'queueMicrotask' ] let name_preg = /^[a-z_][a-z0-9_\-]{0,50}$/i function checkName (name) { return name_preg.test(name) } function parseNameDir (name) { let ind = name.indexOf('/') let hasJS = (name.length > 3 && name.substring(name.length-3) === '.js') if (ind > 0) { let narr = name.split('/') let real_name = narr[narr.length-1] return { dir: `/${narr[narr.length-2]}`, name: hasJS ? real_name.substring(0, real_name.length-3) : real_name } } return { dir : '', name: hasJS ? name.substring(0, name.length-3) : name } } function filterName (name) { return (limitName.indexOf(name) >= 0 ? `_${name}` : name) } let cdir = 'controller' let clist = [] //let model_name = '' for (let i = 2; i < process.argv.length; i++) { if (process.argv[i].indexOf('--cdir=') === 0) { let t = process.argv[i].substring('--cdir='.length) if (t.length > 0) { cdir = t } continue } /* if (process.argv.indexOf('--model=') === 0) { let mname = process.argv[i].substring('--model='.length) if (mname.length > 0 && (/^[a-z0-9_][a-z\-_0-9]{0,100}$/i).test(mname)) { model_name = mname } continue } */ clist.push(process.argv[i]) } try { fs.accessSync(cdir) } catch (err) { fs.mkdirSync(cdir) } let nd let cpath for (let c of clist) { nd = parseNameDir(c) if (!checkName(nd.name)) { console.error(`${nd.name} 不符合命名要求,要求字母数字,字母开头,支持连字符和下划线(- 和 _)。(the name is illegal.)`) continue } let modname = nd.name.replace(/\-+/ig, '') if (nd.dir) { try { fs.accessSync(`${cdir}${nd.dir}`) } catch (err) { fs.mkdirSync(`${cdir}${nd.dir}`) } } cpath = `${cdir}${nd.dir}/${nd.name}.js` try { fs.accessSync(cpath) console.error(`${c} 已经存在。`) continue } catch (err) {} try { fs.writeFileSync(cpath, makeController(filterName(modname)), {encoding: 'utf8'}) } catch (err) { console.error(err) } }