添加骨架代码
This commit is contained in:
parent
6f7553fc18
commit
51947d4b73
5
config/config.json
Normal file
5
config/config.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"redis": "redis://127.0.0.1:6379/15",
|
||||||
|
"db_main": "mongodb://127.0.0.1/card-development",
|
||||||
|
"port": 2987
|
||||||
|
}
|
@ -53,12 +53,11 @@
|
|||||||
|
|
||||||
### 3. 可用英雄列表
|
### 3. 可用英雄列表
|
||||||
1. Method: GET
|
1. Method: GET
|
||||||
2. URI: /api/:accountid/heros
|
2. URI: /api/:accountid
|
||||||
|
|
||||||
| 字段 | 说明 |
|
| 字段 | 说明 |
|
||||||
| -------- | -------------------------------------- |
|
| -------- | -------------------------------------- |
|
||||||
| accountid | 帐号id |
|
| accountid | 帐号id |
|
||||||
| heroid | 帐号id |
|
|
||||||
|
|
||||||
3. Response: JSON
|
3. Response: JSON
|
||||||
|
|
||||||
|
1136
package-lock.json
generated
Normal file
1136
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@ -7,5 +7,31 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC"
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@typegoose/auto-increment": "^0.6.0",
|
||||||
|
"@typegoose/typegoose": "^7.4.6",
|
||||||
|
"bson": "^4.2.2",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"fast-rbac": "^1.3.0",
|
||||||
|
"fastify": "^3.9.2",
|
||||||
|
"fastify-cors": "^5.1.0",
|
||||||
|
"fastify-file-upload": "^3.0.0",
|
||||||
|
"fastify-formbody": "^5.0.0",
|
||||||
|
"fastify-helmet": "^5.0.3",
|
||||||
|
"fastify-jwt": "^2.2.0",
|
||||||
|
"fastify-plugin": "^3.0.0",
|
||||||
|
"mime-types": "^2.1.28",
|
||||||
|
"mongoose": "^5.11.10",
|
||||||
|
"mongoose-findorcreate": "^3.0.0",
|
||||||
|
"tracer": "^1.1.4",
|
||||||
|
"urlencode": "^1.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/debug": "^4.1.5",
|
||||||
|
"@types/mongoose": "^5.10.3",
|
||||||
|
"@types/node": "^14.14.20",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"typescript": "^4.1.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
117
src/api.server.ts
Normal file
117
src/api.server.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import fastify, {FastifyError, FastifyInstance} from 'fastify'
|
||||||
|
import helmet from 'fastify-helmet'
|
||||||
|
import { Server, IncomingMessage, ServerResponse } from 'http'
|
||||||
|
import {RouterMap} from './decorators/router';
|
||||||
|
import {mongoose} from "@typegoose/typegoose";
|
||||||
|
import logger from './logger/logger';
|
||||||
|
import {Config} from "./cfg/Config";
|
||||||
|
|
||||||
|
const zReqParserPlugin = require('./plugins/zReqParser');
|
||||||
|
|
||||||
|
const apiAuthPlugin = require('./plugins/apiauth');
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const join = require('path').join;
|
||||||
|
|
||||||
|
let config: Config = require('../config/config.json');
|
||||||
|
|
||||||
|
export class ApiServer {
|
||||||
|
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
this.server = fastify({logger: true});
|
||||||
|
this.registerPlugins();
|
||||||
|
}
|
||||||
|
private registerPlugins() {
|
||||||
|
this.server.register(require('fastify-formbody'));
|
||||||
|
this.server.register(zReqParserPlugin);
|
||||||
|
// @ts-ignore
|
||||||
|
this.server.register(
|
||||||
|
helmet,
|
||||||
|
{ hidePoweredBy: { setTo: 'PHP 4.2.0' } }
|
||||||
|
)
|
||||||
|
|
||||||
|
this.server.register(require('fastify-cors'), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerRouter() {
|
||||||
|
logger.log('register api routers');
|
||||||
|
let self = this;
|
||||||
|
for (let [controller, config] of RouterMap.decoratedRouters) {
|
||||||
|
let controllers = Array.isArray(controller) ? controller : [controller]
|
||||||
|
controllers.forEach((controller) => {
|
||||||
|
logger.info('find api router', config.method || 'all', config.path, controller.name);
|
||||||
|
// @ts-ignore
|
||||||
|
self.server[config.method || 'all'](config.path, {
|
||||||
|
preValidation: async function (request: { roles: string[]; }, reply: any, done: any) {
|
||||||
|
request.roles = config.roles;
|
||||||
|
await this.apiAuth(request, reply, done);
|
||||||
|
}
|
||||||
|
}, controller);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// this.server.register(new AccountRouter().applyAll, {prefix: 'user', logLevel: 'debug'});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 加载所有的controller
|
||||||
|
*/
|
||||||
|
initControllers() {
|
||||||
|
logger.info('Bootstrap controllers...');
|
||||||
|
const controllers = join(__dirname, 'api/controllers');
|
||||||
|
fs.readdirSync(controllers)
|
||||||
|
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
|
||||||
|
.forEach((file: any) => {
|
||||||
|
logger.log(file);
|
||||||
|
return require(join(controllers, file))});
|
||||||
|
}
|
||||||
|
async connectDB() {
|
||||||
|
const options = {useNewUrlParser: true,
|
||||||
|
poolSize: 5,
|
||||||
|
keepAlive: true,
|
||||||
|
keepAliveInitialDelay: 300000,
|
||||||
|
useUnifiedTopology: true};
|
||||||
|
const uri = config.db_main;
|
||||||
|
logger.info(`connect to ${uri} ...`);
|
||||||
|
try {
|
||||||
|
// await mongoose.createConnection(uri, options)
|
||||||
|
await mongoose.connect(uri, options)
|
||||||
|
logger.log('DB Connected');
|
||||||
|
} catch (err) {
|
||||||
|
logger.log(`DB Connection Error: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private setErrHandler() {
|
||||||
|
this.server.setNotFoundHandler(function(request: any, reply: { send: (arg0: { code: number; msg: string; }) => void; }){
|
||||||
|
reply.send({code: 404, msg: 'page not found'})
|
||||||
|
});
|
||||||
|
this.server.setErrorHandler(function (error: FastifyError, request: any, reply: { send: (arg0: { code: any; msg: any; }) => void; }) {
|
||||||
|
let statusCode = error && error.statusCode || 100;
|
||||||
|
if (statusCode >= 500) {
|
||||||
|
logger.error(error)
|
||||||
|
} else if (statusCode >= 400) {
|
||||||
|
logger.info(error)
|
||||||
|
} else {
|
||||||
|
logger.error(error)
|
||||||
|
}
|
||||||
|
reply.send({code: statusCode, msg: error ? error.message : 'unknown error'})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
public async start() {
|
||||||
|
let self = this;
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
await self.connectDB();
|
||||||
|
self.initControllers();
|
||||||
|
self.registerRouter();
|
||||||
|
self.setErrHandler();
|
||||||
|
this.server.listen({port: config.port}, (err: any, address: any) => {
|
||||||
|
if (err) {
|
||||||
|
logger.log(err)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
resolve && resolve(address);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/api.ts
Normal file
13
src/api.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import {ApiServer} from './api.server';
|
||||||
|
import logger from "./logger/logger";
|
||||||
|
|
||||||
|
class Server extends ApiServer {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
let server = new Server();
|
||||||
|
server.start().then((address) => {
|
||||||
|
logger.log(`Api Server listening at ${address}`)
|
||||||
|
})
|
5
src/cfg/Config.ts
Normal file
5
src/cfg/Config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface Config {
|
||||||
|
redis: string;
|
||||||
|
db_main: string;
|
||||||
|
port: number;
|
||||||
|
}
|
9
src/common/base.controller.ts
Normal file
9
src/common/base.controller.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import fastify = require('fastify');
|
||||||
|
|
||||||
|
class BaseController {
|
||||||
|
aotoRoute(req: fastify.FastifyRequest, res: any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export default BaseController
|
19
src/decorators/dbconn.ts
Normal file
19
src/decorators/dbconn.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {mongoose} from "@typegoose/typegoose";
|
||||||
|
import {Config} from "../cfg/Config";
|
||||||
|
/**
|
||||||
|
* 为model指定数据库连接
|
||||||
|
* @param {string} name 数据库连接名字, 在config中必须要有对应的配置, 比如main, 则必须要有 db_main
|
||||||
|
* */
|
||||||
|
let config: Config = require('../../config/config.json');
|
||||||
|
export function dbconn(name?: string) {
|
||||||
|
return (target: any) => {
|
||||||
|
name = name || 'main';
|
||||||
|
// @ts-ignore
|
||||||
|
const url = config['db_'+name];
|
||||||
|
target['db'] = mongoose.createConnection(url, {
|
||||||
|
useNewUrlParser: true,
|
||||||
|
useCreateIndex:true,
|
||||||
|
useFindAndModify: false,
|
||||||
|
useUnifiedTopology: true});
|
||||||
|
};
|
||||||
|
}
|
90
src/decorators/router.ts
Normal file
90
src/decorators/router.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import BaseController from '../common/base.controller';
|
||||||
|
|
||||||
|
export class RouterMap {
|
||||||
|
static decoratedRouters: Map<Function | Function[], {
|
||||||
|
target?: any,
|
||||||
|
method?: string,
|
||||||
|
path?: string,
|
||||||
|
roles?: string[],
|
||||||
|
permissions?: string[]
|
||||||
|
}> = new Map()
|
||||||
|
}
|
||||||
|
export function router(route?: string) {
|
||||||
|
return (target: BaseController, name: string, value: PropertyDescriptor) => {
|
||||||
|
if (!route) {
|
||||||
|
const controller = target.constructor.name
|
||||||
|
const controllerName = controller.toLowerCase().replace('.controller', '')
|
||||||
|
route = 'all ' + ['', controllerName, name].join('/')
|
||||||
|
}
|
||||||
|
const split = route.split(' ');
|
||||||
|
if (split.length > 2) {
|
||||||
|
throw new Error('路由中只允许一个空格')
|
||||||
|
}
|
||||||
|
const [method, path] = split
|
||||||
|
// @ts-ignore
|
||||||
|
const key = target[name];
|
||||||
|
let routerObj = {
|
||||||
|
target: target,
|
||||||
|
path: path,
|
||||||
|
method: method
|
||||||
|
};
|
||||||
|
if (RouterMap.decoratedRouters.has(key)) {
|
||||||
|
let objCurrent = RouterMap.decoratedRouters.get(key);
|
||||||
|
Object.assign(objCurrent, routerObj);
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], objCurrent);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], routerObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function role(roles?: string | string[]) {
|
||||||
|
return (target: BaseController, name: string, value: PropertyDescriptor) => {
|
||||||
|
let roleList: string[] = [];
|
||||||
|
if (roles) {
|
||||||
|
if (Array.isArray(roles)) {
|
||||||
|
roleList = roles;
|
||||||
|
} else {
|
||||||
|
roleList = [roles];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const key = target[name];
|
||||||
|
let roleObj = {roles: roleList};
|
||||||
|
if (RouterMap.decoratedRouters.has(key)) {
|
||||||
|
let objCurrent = RouterMap.decoratedRouters.get(key);
|
||||||
|
Object.assign(objCurrent, roleObj);
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], objCurrent);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], roleObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function permission(permissions?: string | string[]) {
|
||||||
|
return (target: BaseController, name: string, value: PropertyDescriptor) => {
|
||||||
|
let permissionList: string[] = [];
|
||||||
|
if (permissions) {
|
||||||
|
if (Array.isArray(permissions)) {
|
||||||
|
permissionList = permissions;
|
||||||
|
} else {
|
||||||
|
permissionList = [permissions];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const key = target[name];
|
||||||
|
let permissionObj = {permissions: permissionList};
|
||||||
|
if (RouterMap.decoratedRouters.has(key)) {
|
||||||
|
let objCurrent = RouterMap.decoratedRouters.get(key);
|
||||||
|
Object.assign(objCurrent, permissionObj);
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], objCurrent);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
RouterMap.decoratedRouters.set(target[name], permissionObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/logger/logger.ts
Normal file
2
src/logger/logger.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
const logger = require('tracer').colorConsole({dateformat: 'yyyy-mm-dd HH:MM:ss.L'});
|
||||||
|
export default logger
|
Loading…
x
Reference in New Issue
Block a user