提交 a6fd672b 作者: 刘贵生

init

上级
流水线 #88840 已失败 于阶段
in 1 分 8 秒
node_modules
\ No newline at end of file
## 拉取代码
```
git clone git@git.allhome.com.cn:color-z/node_template.git
```
## 初始化依赖
```
cd node_tempalte
npm install
```
## 编译ts文件
```
npm run ts
```
## 启动项目
```
npm start
```
## 模板介绍
- config 一些配置信息,例如项目端口号,数据库账号,eureka注册地址等
- controller 路由层,采用swagger修饰器编写,[详情查看](https://www.npmjs.com/package/koa-swagger-decorator)
- dao dao层 一些数据操作
- db 数据库连接
- eureka eureka注册
- middleware 中间件
- model 数据库模型,表头约束
- service 业务代码
- swagger swagger注册
- types ts类型声明
- util 工具类
- app.ts 服务启动文件
\ No newline at end of file
git pull origin master
echo 拉取代码成功
git add .
git commit -m "提交代码"
git pull origin master
echo 已成功推送代码
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "node-ts",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"ts": "tsc --watch",
"start": "nodemon build/app.js",
"test": "echo \"Error: no test specified\" && exit 1",
"shell": "sh bash.sh"
},
"author": "",
"license": "ISC",
"dependencies": {
"eureka-js-client": "4.4.2",
"koa": "^2.11.0",
"koa-body": "^4.1.3",
"koa-swagger-decorator": "^1.6.4",
"mongoose": "^5.9.16",
"nodemon": "^2.0.4",
"os": "^0.1.1",
"ts-node": "^9.0.0",
"typescript": "^4.0.3"
},
"devDependencies": {
"@types/eureka-js-client": "^4.5.2",
"@types/koa": "^2.11.3",
"@types/mongoose": "^5.7.21",
"@types/nodemon": "^1.19.0"
}
}
import Koa from "koa";
import router from "./swagger/index";
import koaBody from "koa-body";
import { projectConfig } from "./config/config";
import { MongoDb } from "./db/mongo";
import { rest } from "./middleware/rest";
import { EurekaService } from "./eureka/index";
let eurekaService = new EurekaService()
let app = new Koa();
let { host, database, port } = projectConfig.db;
let mongoDb = new MongoDb(host, port, database);
const start = async () => {
await mongoDb.link();
await eurekaService.start()
app.use(koaBody());
app.use(rest())
app.use(router.routes());
app.listen(projectConfig.port);
}
start()
/**
* @name 项目配置目录
* @author liuguisheng
* @version 2020-05-29 14:47:48 星期五
*/
class ProjectConfig {
public readonly port: string = "3000"
public readonly db = {
database: "test",
username: "",
password: "",
host: "mongodb://127.0.0.1",
port: "27017"
}
public readonly eureka = {
host: "http://192.168.10.200",
port: "1025",
servicePath: "eureka/apps/",
username: "admin",
password: "admin",
serviceName: "LGSServer"
}
}
const projectConfig = new ProjectConfig();
export {
projectConfig
}
\ No newline at end of file
import { request, summary,Context, query, params, path, body, description, tags } from "koa-swagger-decorator";
import { Test } from "../service/index";
let test = new Test();
const tag = tags(['测试']);
export default class Text {
@request('get', '/getData')
@summary('测试')
@tag
static async getData ( ctx: Context ) {
ctx.body = await test.getList()
}
@request('post', '/postData')
@summary('测试')
@body({
aaa: {type: "string"},
bbb: {type: "string"}
})
@tag
static async postData ( ctx: Context ) {
console.log(ctx.request.body)
ctx.body = {aaa: 111, bbb: 222}
}
}
\ No newline at end of file
import { TEST_MODEL, TEST_DOC } from "../model/test";
import { Document, DocumentQuery, FilterQuery } from 'mongoose'
export class TestDb {
async insertData ( row: object ): Promise<TEST_DOC> {
let condition: FilterQuery<TEST_DOC> = {};
let res = await TEST_MODEL.findOne(condition).exec();
let data: TEST_DOC = res?.toObject()
return data;
}
}
\ No newline at end of file
import mongoose from "mongoose";
/**
* @name mongo数据库连接
* @description
* @param { String } host 主机地址
* @param { String } port 端口号
* @param { String } database 数据库名称
* @author liuguisheng
* @version 2020-05-29 14:45:19 星期五
*/
export class MongoDb {
host: string;
port: string;
database: string;
constructor ( host: string, port: string, database: string ) {
this.host = host;
this.port = port;
this.database = database;
}
/**
* @name 开始连接
* @author liuguisheng
* @version 2020-05-29 14:46:22 星期五
*/
async link () {
// 获取数据库配置
let { host, port, database } = this;
// 拼接数据库连接地址
let url: string = `${host}:${port}/${database}`;
// 必要的配置字段
let config: object = {
useNewUrlParser: true,
useUnifiedTopology: true
};
// 开始连接
try {
await mongoose.connect(url,config);
console.log("mongo连接成功");
}catch {
console.log("mongo连接失败");
}
}
}
\ No newline at end of file
import Eureka from "eureka-js-client";
import { projectConfig } from "../config/config";
import { getIp4 } from "../util/utils";
import { Context } from "koa-swagger-decorator";
// 获取eureka配置信息
const {
host,
port,
servicePath,
username,
password,
serviceName
} = projectConfig.eureka;
// 获取ip4
const IP4 = getIp4();
// eureka集群地址
const EUREKA_URL = `${host}:${port}/${servicePath}`;
let Eurekas: any = Eureka
// eurake客户端
export const CLIENT = new Eurekas({
instance: {
instanceId: `${IP4}:${port}`,
app: serviceName,
hostName: IP4,
ipAddr: IP4,
vipAddress: serviceName,
port: { '$': port, '@enabled': true },
statusPageUrl: `http://${IP4}:${port}/info`,
healthCheckUrl: `http://${IP4}:${port}/health`,
dataCenterInfo: {
'@class': 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo',
name: 'MyOwn',
}
},
eureka: {
serviceUrls: {
default: [
EUREKA_URL
]
}
},
requestMiddleware: ( requestOpts: any, done: Function ) => {
requestOpts.auth = {
user: username,
password
};
done(requestOpts);
}
})
/**
* @name eureka服务
* @author liuguisheng
* @version 2020-05-29 16:57:14 星期五
*/
export class EurekaService {
// 是否开启eureka服务
started: boolean = false;
/**
* @name 启动eureka
* @author liuguisheng
* @version 2020-05-29 16:58:27 星期五
*/
start () {
return new Promise((res, rej) => {
CLIENT.start( (err: any) => {
if ( err ) {
console.log(`eureka注册失败${err.message}`)
rej(err);
}
this.started = true;
console.log(`eureka注册成功`);
res();
})
})
}
/**
* @name 获取客户端状态信息
* @author liuguisheng
* @version 2020-05-29 17:05:30 星期五
*/
getStatusInfo () {
return async ( ctx: Context, next: Function ) => {
if ( ctx.path.startsWith('/info')) {
return ctx.body = {
name: serviceName,
status: 'up'
}
}
await next();
}
}
/**
* @name 获取客户端健康信息
* @author liuguisheng
* @version 2020-05-29 17:16:20 星期五
*/
getHealthInfo () {
return async ( ctx: Context, next: Function ) => {
if ( ctx.path.startsWith('/health')) {
return ctx.body = {
description: ' service for liuguisheng',
status: 'up'
}
}
await next();
}
}
/**
* @name 获取微服务
* @author liuguisheng
* @version 2020-05-29 17:19:04 星期五
*/
getInstance ( appId: string) {
let instances = CLIENT.getInstancesByAppId(appId);
return instances.map( (item: any) => {
let { ipAddr, port } = item;
return `http://${ipAddr}:${port['$']}`
})
}
}
import { Context } from "koa-swagger-decorator";
const ERRORLIST: Map<string, object> = new Map([
['SERVICE_ERROR',{ status: 500, message: "服务器错误"}],
['T_ERROR',{ status: 10002, message: "技术出错了,请联系技术人员"}],
['DATA_ERROR',{ status: 400, message: "数据错误"}],
])
/**
* @name rest错误返回中间件
* @author liuguisheng
* @version 2020-05-29 14:43:30 星期五
*/
export const rest = function () {
return async (ctx: Context, next: Function) =>{
try {
// 请求成功返回查询数据
await next();
ctx.body = {
status: "200",
message: "成功",
result: ctx.body
}
} catch (err) {
// 捕获异常,从定义的错误列表中查找错误信息返回
let {status, message } = ERRORLIST.get(err.message) as any;
ctx.body = {
status,
message
}
}
}
}
\ No newline at end of file
import mongoose, { Document } from "mongoose";
export interface TEST_DOC extends Document {
name: string,
age: number
}
const TEST_SCHEMA = new mongoose.Schema({
name: { type: String },
age: { type: Number },
email: { type: String },
time: { type: Date, default: Date.now }
})
export const TEST_MODEL = mongoose.model('text_model', TEST_SCHEMA)
\ No newline at end of file
import { TestDb } from '../dao/index'
export class Test {
private readonly dao: TestDb = new TestDb();
constructor() {
}
getList () {
return '请求成功'
}
async insertData () {
let res = await this.dao.insertData({});
res.name
res.age
return res.name;
}
}
\ No newline at end of file
import { SwaggerRouter } from "koa-swagger-decorator";
import path from 'path';
const swaggerRouter = new SwaggerRouter();
swaggerRouter.swagger({
title:'日志',
description: '日志后台接口',
varsion: 'v1.0.0',
swaggerHtmlEndpoint: '/index.html',
swaggerJsonEndpoint: '/swagger-json',
swaggerOptions: {
secrityDefinitions: {
ApiKeyAuth: {
type: 'apiKey',
in: 'header',
name: 'QianJia'
}
}
},
swaggerConfiguration: {
display: {
defaultModelsExpandDepth: 4,
defaultModelExpandDepth: 3,
docExpansion: 'list',
defaultModelRendering: 'model'
}
}
});
swaggerRouter.mapDir(path.resolve(__dirname, '../controller'));
export default swaggerRouter;
\ No newline at end of file
/**
* @name 全局类型声明
* @author liuguisheng
* @version 2020-05-29 16:13:56 星期五
*/
declare module "os";
class ErrorHandle extends Error {
static list: Map<number, string> = new Map();
constructor ( code: number, message: string) {
super(message);
}
}
class Errors {
static errorList: Map<number, string> = new Map([
[1000, "成功"],
[4004, "未找到"],
[5000, "服务器错误"],
])
getError () {
return
}
}
/**
* @name 获取当前服务器ip4
* @author liuguisheng
* @version 2020-05-29 16:19:46 星期五
*/
import os from "os";
export const getIp4 = function () {
let interfaces = os.networkInterfaces();
for( let devName in interfaces ) {
let iface: any = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}  
}
}
\ No newline at end of file
{
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": [
"./src/**/*"
],
"exclude": [
"./node_modules"
]
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论