feat: 默认值系统

pull/635/head
bigfengyu 5 years ago
parent 08c17f9228
commit 4965cc445d

@ -1,7 +1,7 @@
# BUILDING
# BUILDING
FROM node:lts-alpine AS builder
# base on work of llitfkitfk@gmail.com
# base on work of llitfkitfk@gmail.com
LABEL maintainer="chibing.fy@alibaba-inc.com"
WORKDIR /app
@ -23,7 +23,7 @@ RUN npm run build
# RUNNING
FROM node:lts-alpine
# base on work of llitfkitfk@gmail.com
# base on work of llitfkitfk@gmail.com
LABEL maintainer="chibing.fy@alibaba-inc.com"
# use China mirror of: https://github.com/jgm/pandoc/releases/download/2.7.3/pandoc-2.7.3-linux.tar.gz
RUN wget http://q08gwzg9o.bkt.clouddn.com/pandoc-2.7.3-linux.tar.gz && \
@ -31,8 +31,8 @@ RUN wget http://q08gwzg9o.bkt.clouddn.com/pandoc-2.7.3-linux.tar.gz && \
cp pandoc-2.7.3/bin/* /usr/bin/ && \
pandoc -v && \
rm -rf pandoc-2.7.3-linux.tar.gz pandoc-2.7.3
WORKDIR /app
COPY --from=builder /app/public .
COPY --from=builder /app/dist .
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/node_modules ./node_modules

@ -143,7 +143,6 @@ npm run check
```
#### 启动开发模式的服务器 监视并在发生代码变更时自动重启
```bash
npm run dev
```

@ -0,0 +1,2 @@
ALTER TABLE `Properties`
MODIFY COLUMN `type` enum('String','Number','Boolean','Object','Array','Function','RegExp','Null') NOT NULL;

@ -0,0 +1,11 @@
ALTER TABLE repositories_collaborators
DROP COLUMN createdat ;
ALTER TABLE repositories_collaborators
DROP COLUMN updatedat ;
ALTER TABLE repositories_members
DROP COLUMN createdat ;
ALTER TABLE repositories_members
DROP COLUMN updatedat ;

@ -0,0 +1,5 @@
ALTER TABLE `properties`
ADD COLUMN `pos` INT(10) NULL DEFAULT 2;
ALTER TABLE `interfaces`
ADD COLUMN `status` INT(10) NULL DEFAULT 200;

@ -0,0 +1,2 @@
ALTER TABLE Interfaces
MODIFY COLUMN `method` VARCHAR(256) NOT NULL;

@ -0,0 +1,2 @@
ALTER TABLE `Properties`
ADD COLUMN `required` TINYINT(1) NOT NULL DEFAULT 0;

@ -0,0 +1,11 @@
CREATE TABLE `default_val` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`createdat` datetime NOT NULL COMMENT '创建时间',
`updatedat` datetime NOT NULL COMMENT '修改时间',
`name` varchar(256) NOT NULL COMMENT '名字',
`rule` varchar(512) NOT NULL COMMENT '规则',
`value` text NOT NULL COMMENT '',
`repositoryid` bigint unsigned NOT NULL COMMENT 'FK',
`deletedat` datetime NOT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET=utf8mb4 COMMENT='默认值';

@ -23,78 +23,79 @@
"dependencies": {
"@types/treeify": "^1.0.0",
"chalk": "^2.4.2",
"cross-env": "^5.2.0",
"cross-env": "^6.0.3",
"graceful": "^1.0.2",
"is-md5": "^0.0.2",
"js-beautify": "^1.10.0",
"js-beautify": "^1.10.2",
"kcors": "^2.2.2",
"koa": "^2.7.0",
"koa-body": "^4.1.0",
"koa": "^2.11.0",
"koa-body": "^4.1.1",
"koa-generic-session": "^2.0.1",
"koa-logger": "^3.2.0",
"koa-logger": "^3.2.1",
"koa-redis": "^4.0.0",
"koa-router": "^7.4.0",
"koa-send": "^5.0.0",
"koa-static": "^5.0.0",
"lodash": "^4.17.11",
"lodash": "^4.17.15",
"mariadb": "^2.1.2",
"md5": "^2.2.1",
"mockjs": "^1.0.1-beta3",
"mockjs": "1.1.0",
"moment": "^2.24.0",
"mysql": "^2.17.1",
"mysql2": "^1.6.5",
"mysql2": "^2.0.0",
"nanoid": "^2.1.6",
"node-fetch": "^2.6.0",
"node-print": "0.0.4",
"node-schedule": "^1.3.2",
"nodemailer": "^6.2.1",
"notevil": "^1.3.1",
"path-to-regexp": "^3.0.0",
"notevil": "^1.3.2",
"path-to-regexp": "^3.1.0",
"redis": "^2.8.0",
"reflect-metadata": "^0.1.13",
"request": "^2.88.0",
"request-promise": "^4.2.4",
"sequelize": "^5.10.1",
"sequelize-typescript": "^1.0.0-beta.3",
"request-promise": "^4.2.5",
"sequelize": "^5.21.2",
"sequelize-typescript": "^1.0.0",
"svg-captcha": "^1.4.0",
"treeify": "^1.1.0",
"underscore": "^1.9.1",
"urllib": "^2.34.0"
"urllib": "^2.34.1"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/chai": "^4.2.4",
"@types/kcors": "^2.2.3",
"@types/koa": "^2.0.51",
"@types/koa-generic-session": "^1.0.2",
"@types/koa-generic-session": "^1.0.3",
"@types/koa-logger": "^3.1.1",
"@types/koa-redis": "^3.0.2",
"@types/koa-router": "^7.0.40",
"@types/koa-redis": "^3.0.3",
"@types/koa-router": "^7.0.42",
"@types/koa-static": "^4.0.1",
"@types/lodash": "^4.14.132",
"@types/lodash": "^4.14.145",
"@types/md5": "^2.1.33",
"@types/mocha": "^5.2.6",
"@types/mocha": "^5.2.7",
"@types/mockjs": "^1.0.2",
"@types/nanoid": "^2.1.0",
"@types/node": "^12.0.3",
"@types/node-schedule": "^1.2.3",
"@types/nodemailer": "^6.2.0",
"@types/redis": "^2.8.13",
"@types/request": "^2.48.1",
"@types/node": "^12.12.6",
"@types/node-schedule": "^1.2.4",
"@types/nodemailer": "^6.2.2",
"@types/redis": "^2.8.14",
"@types/request": "^2.48.3",
"@types/request-promise": "^4.1.44",
"@types/sequelize": "^4.28.4",
"@types/underscore": "^1.8.18",
"babel-eslint": "^10.0.1",
"@types/sequelize": "^4.28.6",
"@types/underscore": "^1.9.3",
"babel-eslint": "^10.0.3",
"chai": "^4.2.0",
"mocha": "^6.1.4",
"nodemon": "^1.19.1",
"mocha": "^6.2.2",
"nodemon": "^1.19.4",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"pre-commit": "^1.2.2",
"rimraf": "^2.6.3",
"source-map-support": "^0.5.12",
"standard": "^12.0.1",
"rimraf": "^3.0.0",
"source-map-support": "^0.5.16",
"standard": "^14.3.1",
"supertest": "^4.0.2",
"tslint": "^5.16.0",
"typescript": "^3.5.1"
"tslint": "^5.20.1",
"typescript": "^3.7.2"
},
"pre-commit": [
"check"

@ -1,6 +1,6 @@
import { IConfigOptions } from "../types"
let config: IConfigOptions = {
const config: IConfigOptions = {
version: 'v2.8.0',
serve: {
port: (process.env.SERVE_PORT && parseInt(process.env.SERVE_PORT)) || 8080,
@ -12,17 +12,20 @@ let config: IConfigOptions = {
},
db: {
dialect: 'mysql',
host: process.env.MYSQL_URL || 'localhost',
host: process.env.MYSQL_URL ?? 'localhost',
port: (process.env.MYSQL_PORT && parseInt(process.env.MYSQL_PORT)) || 3306,
username: process.env.MYSQL_USERNAME || 'root',
password: process.env.MYSQL_PASSWD || '',
database: process.env.MYSQL_SCHEMA || 'RAP2_DELOS_APP',
username: process.env.MYSQL_USERNAME ?? 'root',
password: process.env.MYSQL_PASSWD ?? '29837DF983(*&34kfjD(*3kjf(',
database: process.env.MYSQL_SCHEMA ?? 'RAP2_DELOS_APP',
pool: {
max: 5,
min: 0,
idle: 10000,
},
logging: false,
dialectOptions: {
connectTimeout: 20000,
},
},
redis: {},
mail: {

@ -0,0 +1,27 @@
import { Table, Column, Model, AutoIncrement, PrimaryKey, ForeignKey } from 'sequelize-typescript'
import { Repository } from '../../models'
@Table({ paranoid: true, freezeTableName: false, timestamps: true, tableName: 'default_val' })
export default class DefaultVal extends Model<DefaultVal> {
@PrimaryKey
@AutoIncrement
@Column
id: number
@Column
name: string
@Column
rule: string
@Column
value: string
@ForeignKey(() => Repository)
@Column
repositoryId: number
}

@ -9,4 +9,5 @@ export { default as Repository } from './bo/repository'
export { default as User } from './bo/user'
export { default as OrganizationsMembers } from './bo/organizationsMembers'
export { default as RepositoriesCollaborators } from './bo/repositoriesCollaborators'
export { default as RepositoriesMembers } from './bo/repositoriesMembers'
export { default as RepositoriesMembers } from './bo/repositoriesMembers'
export { default as DefaultVal } from './bo/defaultVal'

@ -20,11 +20,13 @@ const sequelize = new Sequelize({
port: config.db.port,
pool: config.db.pool,
logging: config.db.logging ? logging : false,
dialectOptions: config.db.dialectOptions,
})
sequelize.addModels([__dirname + '/bo'])
sequelize.authenticate()
.then((/* err */) => {
sequelize.sync()
console.log('----------------------------------------')
console.log('DATABASE √')
console.log(' HOST %s', config.db.host)

@ -1,5 +1,5 @@
import router from './router'
import { Repository, Interface, Property } from '../models'
import { Repository, Interface, Property, DefaultVal } from '../models'
import { QueryInclude } from '../models'
import Tree from './utils/tree'
import urlUtils from './utils/url'
@ -269,10 +269,26 @@ router.all('/app/mock/:repositoryId(\\d+)/:url(.+)', async (ctx) => {
}
let interfaceId = itf.id
let properties: any = await Property.findAll({
let properties = await Property.findAll({
attributes,
where: { interfaceId, scope: 'response' },
})
// default values override
const defaultVals = await DefaultVal.findAll({ where: { repositoryId } })
const defaultValsMap: {[key: string]: DefaultVal} = {}
for (const dv of defaultVals) {
defaultValsMap[dv.name] = dv
}
for (const p of properties) {
const dv = defaultValsMap[p.name]
if (!p.value && !p.rule && dv) {
p.value = dv.value
p.rule = dv.rule
}
}
// check required
if (~['GET', 'POST'].indexOf(method)) {
let requiredProperties = await Property.findAll({
@ -310,7 +326,10 @@ router.all('/app/mock/:repositoryId(\\d+)/:url(.+)', async (ctx) => {
requestProperties = requestProperties.map((item: any) => item.toJSON())
let requestData = Tree.ArrayToTreeToTemplateToData(requestProperties)
Object.assign(requestData, { ...ctx.params, ...ctx.query, ...ctx.body })
const data = Tree.ArrayToTreeToTemplateToData(properties, requestData)
let data = Tree.ArrayToTreeToTemplateToData(properties, requestData)
if (data.__root__) {
data = data.__root__
}
ctx.type = 'json'
ctx.status = itf.status
ctx.body = JSON.stringify(data, undefined, 2)

@ -2,7 +2,7 @@
import router from './router'
import * as _ from 'underscore'
import Pagination from './utils/pagination'
import { User, Organization, Repository, Module, Interface, Property, QueryInclude, Logger } from '../models'
import { User, Organization, Repository, Module, Interface, Property, QueryInclude, Logger, DefaultVal } from '../models'
import Tree from './utils/tree'
import { AccessUtils, ACCESS_TYPE } from './utils/access'
import * as Consts from './utils/const'
@ -132,6 +132,7 @@ router.get('/repository/owned', isLoggedIn, async (ctx) => {
pagination: undefined,
}
})
router.get('/repository/joined', isLoggedIn, async (ctx) => {
let where: any = {}
let { name } = ctx.query
@ -269,6 +270,7 @@ router.post('/repository/create', isLoggedIn, async (ctx, next) => {
repositoryId: ctx.body.data.id,
})
})
router.post('/repository/update', isLoggedIn, async (ctx, next) => {
const body = Object.assign({}, ctx.request.body)
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, body.id)) {
@ -336,6 +338,7 @@ router.post('/repository/update', isLoggedIn, async (ctx, next) => {
await Logger.create({ creatorId, userId, type: 'exit', repositoryId: id })
}
})
router.post('/repository/transfer', isLoggedIn, async (ctx) => {
let { id, ownerId, organizationId } = ctx.request.body
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) {
@ -353,6 +356,7 @@ router.post('/repository/transfer', isLoggedIn, async (ctx) => {
data: result[0],
}
})
router.get('/repository/remove', isLoggedIn, async (ctx, next) => {
const id = +ctx.query.id
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, id)) {
@ -394,6 +398,7 @@ router.post('/repository/lock', isLoggedIn, async (ctx) => {
})
ctx.body = { data: result[0] }
})
router.post('/repository/unlock', async (ctx) => {
if (!ctx.session.id) {
ctx.body = { data: 0 }
@ -413,6 +418,7 @@ router.get('/module/count', async (ctx) => {
data: await Module.count(),
}
})
router.get('/module/list', async (ctx) => {
let where: any = {}
let { repositoryId, name } = ctx.query
@ -425,6 +431,7 @@ router.get('/module/list', async (ctx) => {
}),
}
})
router.get('/module/get', async (ctx) => {
ctx.body = {
data: await Module.findByPk(ctx.query.id, {
@ -432,6 +439,7 @@ router.get('/module/get', async (ctx) => {
})
}
})
router.post('/module/create', isLoggedIn, async (ctx, next) => {
let creatorId = ctx.session.id
let body = Object.assign(ctx.request.body, { creatorId })
@ -451,6 +459,7 @@ router.post('/module/create', isLoggedIn, async (ctx, next) => {
moduleId: mod.id,
})
})
router.post('/module/update', isLoggedIn, async (ctx, next) => {
const { id, name, description } = ctx.request.body
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) {
@ -478,6 +487,7 @@ router.post('/module/update', isLoggedIn, async (ctx, next) => {
moduleId: mod.id,
})
})
router.get('/module/remove', isLoggedIn, async (ctx, next) => {
let { id } = ctx.query
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) {
@ -502,6 +512,7 @@ router.get('/module/remove', isLoggedIn, async (ctx, next) => {
moduleId: mod.id,
})
})
router.post('/module/sort', isLoggedIn, async (ctx) => {
let { ids } = ctx.request.body
let counter = 1
@ -519,12 +530,12 @@ router.post('/module/sort', isLoggedIn, async (ctx) => {
}
})
//
router.get('/interface/count', async (ctx) => {
ctx.body = {
data: await Interface.count(),
}
})
router.get('/interface/list', async (ctx) => {
let where: any = {}
let { repositoryId, moduleId, name } = ctx.query
@ -542,6 +553,40 @@ router.get('/interface/list', async (ctx) => {
}),
}
})
router.get('/repository/defaultVal/get/:id', async (ctx) => {
const repositoryId: number = ctx.params.id
ctx.body = {
data: await DefaultVal.findAll({ where: { repositoryId } })
}
})
router.post('/repository/defaultVal/update/:id', async (ctx) => {
const repositoryId: number = ctx.params.id
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, repositoryId)) {
ctx.body = Consts.COMMON_ERROR_RES.ACCESS_DENY
return
}
const list = ctx.request.body.list
if (!(repositoryId > 0) || !list) {
ctx.body = Consts.COMMON_ERROR_RES.ERROR_PARAMS
return
}
await DefaultVal.destroy({
where: { repositoryId }
})
for (const item of list) {
await DefaultVal.create({
...item,
repositoryId,
})
}
ctx.body = {
isOk: true,
}
})
router.get('/interface/get', async (ctx) => {
let { id } = ctx.query
@ -555,7 +600,6 @@ router.get('/interface/get', async (ctx) => {
let itf = await Interface.findByPk(id, {
attributes: { exclude: [] },
include: [QueryInclude.Properties]
})
if (!itf) {
@ -563,6 +607,7 @@ router.get('/interface/get', async (ctx) => {
isOk: false,
errMsg: `没有找到 id 为 ${id} 的接口`
}
return
}
if (
@ -578,10 +623,20 @@ router.get('/interface/get', async (ctx) => {
const itfJSON: { [k: string]: any } = itf.toJSON()
itfJSON['treeProperties'] = Tree.ArrayToTree(itf.properties).children
let scopes = ['request', 'response']
for (let i = 0; i < scopes.length; i++) {
let properties: any = await Property.findAll({
attributes: { exclude: [] },
where: { interfaceId: itf.id, scope: scopes[i] }
})
properties = properties.map((item: any) => item.toJSON())
itfJSON[scopes[i] + 'Properties'] = Tree.ArrayToTree(properties).children
}
ctx.type = 'json'
ctx.body = Tree.stringifyWithFunctonAndRegExp({ data: itfJSON })
})
router.post('/interface/create', isLoggedIn, async (ctx, next) => {
let creatorId = ctx.session.id
let body = Object.assign(ctx.request.body, { creatorId })
@ -784,8 +839,8 @@ router.post('/interface/unlock', async (ctx) => {
// tslint:disable-next-line:no-null-keyword
lockerId: null,
}, {
where: { id }
})
where: { id }
})
ctx.body = {
data: {

@ -5,7 +5,7 @@
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "esnext",
"target": "es2019",
"removeComments": true,
"sourceMap": true,
"watch": false,

Loading…
Cancel
Save