{"id":14989625,"url":"https://github.com/chalk2017/koa-decorator-resolver","last_synced_at":"2026-01-05T05:03:25.550Z","repository":{"id":53776503,"uuid":"458527766","full_name":"chalk2017/koa-decorator-resolver","owner":"chalk2017","description":"koa服务端框架装饰器解决方案","archived":false,"fork":false,"pushed_at":"2022-08-25T15:21:43.000Z","size":926,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-28T23:55:17.831Z","etag":null,"topics":["decorator","koa","nodejs","orm","service"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chalk2017.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-12T13:21:06.000Z","updated_at":"2024-11-25T06:57:59.000Z","dependencies_parsed_at":"2022-09-06T17:41:43.208Z","dependency_job_id":null,"html_url":"https://github.com/chalk2017/koa-decorator-resolver","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk2017%2Fkoa-decorator-resolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk2017%2Fkoa-decorator-resolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk2017%2Fkoa-decorator-resolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk2017%2Fkoa-decorator-resolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chalk2017","download_url":"https://codeload.github.com/chalk2017/koa-decorator-resolver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244875047,"owners_count":20524591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorator","koa","nodejs","orm","service"],"created_at":"2024-09-24T14:18:40.117Z","updated_at":"2026-01-05T05:03:25.536Z","avatar_url":"https://github.com/chalk2017.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# koa-decorator-resolver :zap:\n\n\u003e **这是一个可以在koa框架中使用装饰器的解决方案**\n\n[![license:MIT](https://img.shields.io/badge/License-MIT-green)](https://www.npmjs.com/package/koa-decorator-resolver) ![version:1.3.x](https://img.shields.io/badge/version-1.3.x-blue)\n\n------------\n\n```json\n// 测试基于以下版本，取自2022/8/2最新版本\n{\n  \"dependencies\": {\n    \"@types/jest\": \"^27.4.1\",\n    \"@types/request\": \"^2.48.8\",\n    \"chalk\": \"^2.4.1\",\n    \"console-writer\": \"^1.0.0-beta.1.1\",\n    \"crypto-js\": \"^4.1.1\",\n    \"exceljs\": \"^4.3.0\",\n    \"fs-extra\": \"^10.0.0\",\n    \"jest\": \"^27.5.1\",\n    \"jest-fast-config\": \"^1.0.3\",\n    \"jest-html-reporter\": \"^3.4.2\",\n    \"koa\": \"^2.13.4\",\n    \"koa-body\": \"^5.0.0\",\n    \"koa-bodyparser\": \"^4.3.0\",\n    \"koa-decorator-resolver\": \"^1.2.5\",\n    \"koa-router\": \"^12.0.0\",\n    \"koa-send\": \"^5.0.1\",\n    \"koa-websocket\": \"^7.0.0\",\n    \"lodash\": \"^4.17.21\",\n    \"moment\": \"^2.23.0\",\n    \"mysql2\": \"^2.3.3\",\n    \"request\": \"^2.88.2\",\n    \"require-all\": \"^3.0.0\",\n    \"sequelize\": \"^6.21.3\",\n    \"sqlite\": \"^4.0.23\",\n    \"sqlite3\": \"^5.0.11\",\n    \"ts-jest\": \"^27.1.4\",\n    \"ts-node\": \"^10.9.1\",\n    \"tsconfig-paths\": \"^4.0.0\",\n    \"typescript\": \"^4.7.4\",\n    \"uuid\": \"^8.3.2\",\n    \"xlsx\": \"^0.17.4\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^10.17.44\",\n    \"chai\": \"^4.3.4\",\n    \"copy\": \"^0.3.2\",\n    \"dotenv\": \"^10.0.0\",\n    \"dotenv-cli\": \"^6.0.0\",\n    \"mocha\": \"^9.1.3\",\n    \"nodemon\": \"^2.0.15\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"nyc\": \"^15.1.0\",\n    \"ts-mocha\": \"^8.0.0\"\n  }\n}\n```\n\n------------\n- ## 目录\n- [安装](#安装)\n- [默认请求](#默认请求)\n  - [使用方法](#使用方法)\n  - [定义插件](#定义插件)\n- [使用数据库](#使用数据库)\n  - [配置数据库](#配置数据库)\n    - [创建数据库连接实例](#创建数据库连接实例)\n    - [定义表模型](#定义表模型)\n    - [定义装饰器](#定义装饰器)\n    - [调用Sequelize数据库关系模型库](#调用Sequelize数据库关系模型库)\n    - [开启事务](#开启事务)\n  - [文件配置数据库、mysql和postgres方言配置](#文件配置数据库、mysql和postgres方言配置)\n- [方法、参数一览](#方法、参数一览)\n\n### 安装\n```\n# 安装依赖\nnpm install koa-decorator-resolve \n```\n\n-----\n\n**数据库支持**\n```\n# 如果要用到mysql数据库，则需要安装驱动，如下：\nnpm install mysql2@2.x.x\n\n# 如果要用到postgres数据库，则需要安装驱动，如下：\nnpm install pg@7.x.x pg-hstore@2.x.x\n\n# 如果要用到sqlite数据库，则需要安装驱动，如下：\nnpm install sqlite@4.x.x sqlite3@5.x.x\n```\n\u003e 完全依赖于Sequelize对数据库的支持，详细参照：[https://www.sequelize.com.cn/](https://www.sequelize.com.cn/)\n\n\n### 默认请求\n\u003e 不需要定义restful，单纯的通过定义类和函数的方式自动解析成restful请求，请求的Url格式是“类名/函数名”，默认解析成的是Post，如果想要解析成Get或其他请求可以通过自定义插件的方式生成相应装饰器来解决。\n\n#### 使用方法\n- **文件: index.ts**\n```typescript\n// 这是koa工程的入口文件\nimport * as Koa from 'koa';\nimport * as Router from 'koa-router';\nimport { routeBinder } from 'koa-decorator-resolve';\nimport * as serviceModules from './serviceModules';\nconst router = new Router();\n// 把模块注册在路由上\nrouteBinder(router,serviceModules);\napp.use(router.routes());\napp.listen(8080, () =\u003e {\n    console.log('server start on 8080');\n});\n```\n- **文件: serviceModules.ts**\n```typescript\n// 这是注册在路由上的模块列表\nexport class serviceModule1 {\n    func1(data){\n        return {name:data.name + ' func1',msg:'success'}\n    }\n    func2(data){\n        return {name:data.name + ' func2',msg:'success'}\n    }\n}\nexport class serviceModule2 {\n    func3(data){\n        return {name:data.name + ' func3',msg:'success'}\n    }\n}\n```\n- **在前端发送几个请求**\n```javascript\n    // 通过“类名/函数”就可以发送出去\n    axios.post('/serviceModule1/func1',{name:'m1f1'}).then(res=\u003e{\n        console.log(res); // 结果 : {name:'m1f1 func1',msg'success'}\n    })\n    axios.post('/serviceModule2/func3',{name:'m2f3'}).then(res=\u003e{\n        console.log(res); // 结果 : {name:'m2f3 func3',msg'success'}\n    })\n```\n\n#### 定义插件\n\u003e 自定义装饰器，用来扩展一些功能\n##### 1. 定义装饰器和插件函数\n- **文件: plugins.ts**\n```typescript\n// 这个文件用于配置和注册插件\nimport {injectorBuilder,Injector,ModuleFuncArgsType} from 'koa-decorator-resolve';\n// 定义装饰器\ntype Option = {value:string}\n// Transfer是装饰器名\nexport const Transfer: Injector\u003cOption\u003e = injectorBuilder('Transfer');\n// 配置装饰器\nexport const config = {\n    Transfer: { // Transfer是装饰器名，一定要与injectorBuilder里参数中的名字一致\n        method: 'get', // 被装饰的方法反射的restful类型，默认是post，如果一个方法有多个装饰插件，则以第一个为主\n        before: { // 被装饰方法执行前，所执行的钩子方法\n            plugin: (ctx: any, option?: Option) =\u003e {\n                return {'transfer-before':option.value};\n            },\n            replaceProps: true, // 是否把钩子方法的返回值替换给被装饰方法的第一个参数\n        },\n        after: { //  被装饰方法执行结束后，所执行的钩子方法\n            plugin: (res: any, ctx: any, option?: Option) =\u003e {\n                return {'transfer-after':res}\n            },\n            replaceProps: true, // 是否把钩子方法的返回值替换给请求返回值的body\n        },\n        intercept: (func: (...args: ModuleFuncArgsType) =\u003e any, args: ModuleFuncArgsType, option?: Option) =\u003e {\n            // 拦截器钩子，如果多个装饰器定义了拦截器钩子，只生效第一个\n            return func(...args)\n        }\n    }\n}\n```\n##### 2. 注册插件\n- **文件: index.ts**\n```typescript\n// the entry of project\nimport * as Koa from 'koa';\nimport * as Router from 'koa-router';\nimport {routeBinder} from 'koa-decorator-resolve';\nimport * as serviceModules from './serviceModules';\nimport {config} from './plugins'; // 上一步定义的插件配置\nconst router = new Router();\n// 通过注册路由方法的第三个参数注册插件\nrouteBinder(router,serviceModules,config);\napp.use(router.routes());\napp.listen(8080, () =\u003e {\n    console.log('server start on 8080');\n});\n```\n##### 3. 使用装饰器\n\n- **文件: serviceModules.ts**\n```typescript\n// the restful modules\nimport {Transfer} from './plugins';\nexport class serviceModule {\n    // 用定义的装饰器直接注解方法\n    @Transfer({value:123})\n    func(data){\n        // 根据上面的逻辑，data的值 : {'transfer-before':123}\n        return 456\n    }\n    // 根据上面的逻辑，请求response的值 : {'transfer-after':456}\n}\n```\n\n### 使用数据库\n\u003e 通过装饰器注入数据库实例\n#### 配置数据库\n\n##### 创建数据库连接实例\n\u003e 首先要创建数据库连接\n- **文件: initTables.ts**\n```typescript\n// 引入sequelize的类型\nimport { STRING, INTEGER, BIGINT, DATE, TIME, DATEONLY, BOOLEAN, FLOAT, DOUBLE } from 'sequelize';\n// 引入定义函数\nimport {defineTables} from 'koa-decorator-resolve';\n// 以下是表模型的构造器\nexport const tablesStructure = {\n    ACCESS:[{\n        id: {\n          type: BIGINT,\n          primaryKey: true,\n        },\n        user_name: STRING(20),\n        role: STRING(4),\n        access: INTEGER,\n        begin_date: DATE,\n        end_date: DATE,\n    }, {version: true}],\n    USER:[{\n        user_id: {\n          type: BIGINT,\n          primaryKey: true,\n        },\n        user_name: STRING(20),\n        password: STRING(20)\n    }, {version: true}],\n}\n// 表与表的关系模型可以定义在这里，基于sequelize的关系模型定义方式\nexport const relationCallback = (tables) =\u003e {\n    tables.ACCESS.hasOne(tables.USER);\n    // ...\n}\nexport const {\n    Database, // 装饰器\n    connect // 连接函数（下面参数useAlwaysConnection=true的场合需要在入口手动调用这个函数来创建连接）\n} = new defineTables(tablesStructure, relationCallback, {\n    // 使用长连接，短连接是每次执行方法的时候连接一次，执行完释放连接\n    useAlwaysConnection: false, // 默认false\n    // // 是否使用基础配置文件(基础配置方式请查看文档最后的说明)\n    // useBaseConfig: false, // 默认true\n    // 直接传入sequelize参数， 数组内为实例化sequelize的参数，详细参数用法，请参照sequelize库\n    sequelizeArgs: [\n      \"default_db\",\n      \"root\",\n      \"root\",\n      {\n        host: \"localhost\",\n        port: 3306,\n        dialect: \"mysql\",\n      },\n    ]\n});\n```\n\n##### 调用Sequelize数据库关系模型库\n\u003e 装饰器注入DB实例\n```typescript\n// the restful modules\nimport {OrmSequelize} from 'koa-decorator-resolve';\nimport {Database,tablesStructure} from './initTables';\nexport class serviceModule extends OrmSequelize\u003ctypeof tablesStructure\u003e {\n    @Database({\n        tables: ['ACCESS','USER'],\n        relation: (tables) =\u003e {\n            // 配合tables用于动态表关联\n        }\n    })\n    async func(data){\n        return await this.db.tables.ACCESS.findAll() // 通过表模型直接操作数据库，参照Sequelize\n    }\n}\n```\n\n##### 开启事务\n\u003e 事务中，成功commit，异常rollback\n```typescript\n// the restful modules\nimport {OrmSequelize} from 'koa-decorator-resolve';\nimport {Database,tablesStructure} from './initTables';\nexport class serviceModule extends OrmSequelize\u003ctypeof tablesStructure\u003e {\n    @Sqlite({\n        useTransaction:true // 开启事务\n    })\n    async func(data){\n        return await this.db.tables.ACCESS.findAll()\n    }\n}\n```\n\n#### 文件配置数据库\n\n\u003e 通过配置文件配置数据库\n1. useBaseConfig = true 使用基本配置\n```typescript\nimport {defineTables} from 'koa-decorator-resover';\nexport const {Database,connect} = new defineTables(tablesStructure, relationCallback, {\n    // 是否使用基础配置文件\n    useBaseConfig: true, // 默认true\n    // 注意： sequelizeArgs参数不能添加，否则会优先于sequelizeArgs对数据库的配置\n});\n```\n\n```\n# 在工程根目录下的.env文件中配置当前连接到哪个数据库，每个数据库有单独的配置文件，短连接的时候支持热替换（服务运行当中替换数据库）\n[base] -- .env\n     | -- db.mysql.js\n     | -- db.postgres.js\n\n# 以下是.env文件的格式\n--------------------------------\n| # 此时加载根目录下的db.mysql.js, 如果DB_DRIVER=postgres则会加载根目录下的db.postgres.js文件\n| # DB_DRIVER=mysql\n--------------------------------\n```\n\n```javascript\n// db.mysql.js 和 db.postgres.js的配置方法\nmodule.exports = {\n    database: 'test_db',\n    username: 'test_user',\n    password: 'test_pw',\n    host: 'localhost',\n    port: 2001,\n    pool: { // 池化参数同样参照sequelize\n        max: 5,\n        min: 0,\n        acquire: 30000,\n        idle: 10000,\n    };\n}\n// db.sqlite.js文件的配置方法\nmodule.exports = {\n    path: '/etc/test.db',\n    pool: { // 池化参数同样参照sequelize\n        max: 5,\n        min: 0,\n        acquire: 30000,\n        idle: 10000,\n    };\n}\n```\n**注意：基本配置只支持mysql、postgres、sqlite**\n\n2. useBaseConfig = false 使用标准配置\n```typescript\nimport {defineTables} from 'koa-decorator-resover';\nexport const {Database,connect} = new defineTables(tablesStructure, relationCallback, {\n    // 是否使用基础配置文件\n    useBaseConfig: false, // 默认true\n    // 注意： sequelizeArgs参数不能添加，否则会优先于sequelizeArgs对数据库的配置\n});\n```\n\n```\n# 在工程根目录下只需要配置db.config.js文件\n[base] -- db.config.js\n```\n\n```javascript\n// 默认标准配置，完全sequelize参数，不需要.env\nmodule.exports = {\n  driver: \"mysql\",\n  options: {\n    mysql: [\n      \"default_db\",\n      \"root\",\n      \"root\",\n      {\n        host: \"localhost\",\n        port: 3306,\n        dialect: \"mysql\",\n      },\n    ],\n    postgres: [\n      \"default_db\",\n      \"postgres\",\n      \"password\",\n      {\n        host: \"localhost\",\n        port: 2345,\n        dialect: \"postgres\",\n      },\n    ],\n    sqlite: [\n      {\n        dialect: \"sqlite\",\n        storage: require(\"path\").resolve(\"dbfile\", \"sqlite.db\"),\n      },\n    ],\n  },\n};\n```\n**注意：标准配置参数完全准寻sequelize参数，详细参照sequelize即可**\n\n---\n\n### 方法、参数一览\n\u003e [F]方法、[D]装饰器、[C]类、[I]接口、[T]类型\n  - service.binder\n    - [F]routeBinder - 路由绑定方法\n    - [F]restfulBinder - 传统restful绑定方法（仅支持Get/Post装饰器，即将弃用）\n  - service.injector\n    - [F]servInjector - 服务注入器，注入插件，生成controller函数和method类别\n  - decorator.builder\n    - [F]injectorBuilder - 函数装饰器构建器\n    - [F]classInjectorBuilder - 类装饰器构建器\n    - [F]propsInjectorBuilder - 参数装饰器构建器\n  - decorator.factory\n    - [F]injectBind - 装饰器参数对象绑定\n    - [F]injectRemove - 装饰器参数对象解除绑定\n  - decorator.restful\n    - [D]Get - 传统restful装饰器（配合restfulBinder使用，即将启用）\n    - [D]Post - 传统restful装饰器（配合restfulBinder使用，即将启用）\n  - database.baseDefined (orm共通)\n    - [C]DefineDatabase - 定义数据库入口类\n    - [I]OrmBaseLoader - 加载器类接口\n    - [I]OrmBaseLoaderConstructor - 加载器实例化接口\n  - database.configurator（orm共通）\n    - [F]standardTransfor - 连接参数标准转换器\n    - [I]Transfor - 连接参数转换器接口\n    - [I]StandardConfigType - 配置文件内容格式接口类型\n    - [F]loadConfig - 参数读取方法\n  - database.loader.sequelize.loader\n    - [C]OrmLoader - sequelize加载器类\n    - [T]Combine - 类型继承\n    - [T]CombineAny - 类型继承，元素转换成any类型\n    - [T]CombineColumnModel - 继承Model并注入column字段的类型\n    - [T]TablesModelType - TablesStructure推断表结构\n    - [T]DefineModel - 简化sequelize.define方法\n    - [T]TablesStructureProps - 表结构callback中的参数\n    - [T]TablesStructure - 表结构定义\n    - [T]Relation - 关系函数\n    - [T]DatabaseOptions - Database装饰器参数\n    - [T]GlobalOptions - 全局参数，defineTables的第三个参数类型\n    - [T]DB - 注入的db的类型，通过this.db.获取\n    - [I]OrmSequelize - 用于Service模块db对象注入的继承类，实现this.db.tables.???自动提示，并能提示字段\n    - [I]OrmInterface - 模块接口\n    - [T]RewriteModelCtor - 解析重写Model方法类型\n    - [T]RewriteModelProps - 重写Model方法的类型\n    - [T]RewriteModelKeys - 重写Model方法名称的list\n    - [T]BaseConfigType - 配置文件内容格式接口类型\n  - database.loader.sequelize.binder\n    - [F]defineTables - 构建表实例入口方法\n        - [F]connect - 主动连接函数\n        - [D]Database - DB注入装饰器\n    - [F]baseTransfor - sequelize用的连接参数转换器\n  - type\n    - [T]PluginConfig - 装饰器插件配置结构\n    - [T]Injector - 装饰器类型声明\n    - [T]ModuleFuncType - 模块函数类型\n    - [T]ModuleFuncArgsType - 模块函数参数\n    - [T]MethodType - restful的method\n\n    ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchalk2017%2Fkoa-decorator-resolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchalk2017%2Fkoa-decorator-resolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchalk2017%2Fkoa-decorator-resolver/lists"}