添加骨架代码
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. 可用英雄列表
|
||||
1. Method: GET
|
||||
2. URI: /api/:accountid/heros
|
||||
2. URI: /api/:accountid
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
| heroid | 帐号id |
|
||||
|
||||
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"
|
||||
},
|
||||
"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