Skip to content

Commit

Permalink
feat: 加入多种推断正则,去推测可能的mock类型
Browse files Browse the repository at this point in the history
  • Loading branch information
limengke123 committed Jul 1, 2019
1 parent a627216 commit bf32a5a
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 23 deletions.
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,41 @@

### 默认 mock 类型

| 类型 | 默认值 `mock`| 解释 | 实例 |
| 类型 | 默认值 `mock`| 解释 | 示例 |
| --- | --- | --- | --- |
| string | @csentence | 一般字符串 | "白高长正深常究厂影常小际么知影证。" |
| number | @integer(1, 10000) | 一般数字 | 729 |
| boolean | @boolean | 布尔值 | true |
| array.length | @integer(0, 50) | 数组的长度 | 38 |
| // | @datetime | 符合正则的时间类型 | "2014-02-18 20:33:40" |
| `string` | `@csentence` | 一般字符串 | "白高长正深常究厂影常小际么知影证。" |
| `number` | `@integer(1, 10000)` | 一般数字 | 729 |
| `boolean` | `@boolean` | 布尔值 | `true` |
| `array.length` | `@integer(0, 50)` | 数组的长度 | 38 |
| `/\w*(?:[dD]ate)|(?:[tT]ime)\w*/` | @datetime | 符合正则的时间类型 | "2014-02-18 20:33:40" |
| `/\w*[iI]d$/` | `@increment` | 符合正则的 `id`,保证 `id` 不重复 | "2014-02-18 20:33:40" |
| `/\w*[Nn]ame$/` | `@cname` | name |
| `/^province(?:Name)?$/` | `@province` | 省份 |
| `/^city(?:Name)?$/` | `@city` | 城市 |
| `/\w*[pP]ics?|\w*[pP]ictures?|\w*[iI]mgs?|\w*[iI]mages?/` | `@image` | 图片 |
| `/\w*[cC]ode$/` | `@string("lower", 5)` | code |
| `/\w*[pP]hone(?:Number)?/` | `{"regexp": "\\d{11}"}` | 手机号 |

### 常用 mock 类型

默认的 `mock` 类型不可能在所有场景都能很好使用,这里列举常用的 `mock` 类型:

| mock | 解释 | 返回示例 |
| --- | --- | --- |
| `@pick(["a", "e", "i", "o", "u"])` | 在一个枚举值中随机挑选一个值,常用语**状态**之类的字段 | `e` |
| `@region` | 返回一个区域 | 华北 |
| `@province` | 返回一个省份 | 河北省 |
| `@city` | 返回一个城市 | 菏泽市 |
| `@city(true)` | 返回一个带省份的城市 | 浙江省 宁波市 |
| `@county` | 返回一个区、县 | 长宁区 |
| `@city(true)` | 返回完整的区县 | 北京 北京市 海淀区 |
| `@email` | 返回随机邮箱 | [email protected] |
| `@url` | 返回随机 `url` 地址 | "http://nscgpruo.su/plfjwr" |
| `@cname` | 返回随机中文姓名 | 康艳 |
| `@cword( pool?, min?, max? )` | 返回限定的随机长度的随机中文字符 | 在院门 |
| `@cparagraph( min?, max? )` | 返回限定的随机长度的中文段落 | 构标号住石见关包往再声亲严证千度真。五增上已每法流确京北改开总农圆。如群省志然料且史好比物质达低长天门。第里中型研装果其内等土调号了存机见七。查已问回江员求子育属世式土党速。|
| `@image( size?, background?, foreground?, format?, text? )` | 返回一个图片地址 | "http://dummyimage.com/200x100/FF6600" |
| `@id` | 生成一个身份证号 | 360000201905197112 |

### 覆盖默认 mock 数据

Expand Down
2 changes: 1 addition & 1 deletion example/data.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/schema.json

Large diffs are not rendered by default.

44 changes: 38 additions & 6 deletions src/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import {Result} from "range-parser";

// swagger文档的解析正则
const leftBrace: RegExp = /\s*(.*)\s*{\s*/g
const rightBrace: RegExp = /.*}.*/g
const bodyReg: RegExp = /^\s*(\w+)\s*\(([\[\]\w]+),?\s*(\w+)?\):?(.+)?/g
const arrReg: RegExp = /array\[(\w+)]$/g
const timeReg: RegExp = /\w*(?:[dD]ate)|(?:[tT]ime)\w*/g
const idReg: RegExp = /\w*[iI]d$/g
// 字段修饰正则,去推测字段名对应的 mock 类型
const timeReg: RegExp = /\w*(?:[dD]ate)|(?:[tT]ime)\w*/
const idReg: RegExp = /\w*[iI]d$/
const userNameReg: RegExp = /\w*[nN]ame$/
const provinceReg: RegExp = /^province(?:Name)?$/
const cityReg: RegExp = /^city(?:Name)?$/
const picReg: RegExp = /\w*[pP]ics?|\w*[pP]ictures?|\w*[iI]mgs?|\w*[iI]mages?/
const codeReg: RegExp = /\w*[cC]ode$/
const phoneReg: RegExp = /\w*[pP]hone(?:Number)?/

const RESULT = 'Result'
const DATA = 'data'
Expand All @@ -26,7 +34,7 @@ export interface Ischema {
optional?: boolean,
comment?: string,
generics?: string,
mock?: string,
mock?: string | {regexp: string},
data?: any
}

Expand Down Expand Up @@ -56,6 +64,9 @@ export class Resolver {
optional,
}
if (mock) {
if (typeof mock !== "string") {
console.log(mock)
}
accu[name].mock = mock
}
if (transformType === 'array') {
Expand All @@ -66,8 +77,8 @@ export class Resolver {
})
}

static getType (type: string, name?: string): {transformType: string, generics?: string, mock?: string} {
let result: {transformType:string, generics?: string, mock?: string} = {transformType: type}
static getType (type: string, name?: string): {transformType: string, generics?: string, mock?: string | {regexp: string} } {
let result: {transformType:string, generics?: string, mock?: string | {regexp: string}} = {transformType: type}
if (arrReg.test(type)) {
return {
transformType: 'array',
Expand Down Expand Up @@ -96,13 +107,34 @@ export class Resolver {
return result
}

static handleStringMock (name: string = ''): string {
static handleStringMock (name: string = ''): string | {regexp: string} {
if (timeReg.test(name)) {
return '@datetime'
}
if (idReg.test(name)) {
return '@increment'
}
if (provinceReg.test(name)) {
return '@province'
}
if (cityReg.test(name)) {
return '@city'
}
if (picReg.test(name)) {
return '@image'
}
if (codeReg.test(name)) {
return '@string("lower", 8)'
}
if (phoneReg.test(name)) {
// json 不支持正则表达式,这里给他转换成字符串
return {
regexp: '\\d{11}'
}
}
if (userNameReg.test(name)) {
return '@cname'
}
return '@csentence'
}

Expand Down
24 changes: 15 additions & 9 deletions src/tasks/generateData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,19 @@ function parse<T, K extends keyof T>(root: T, source: any): Map<string, Ischema>
if (!generics) {
throw new Error('数组类型缺少泛型 generics')
}
const length = Mock.mock(mock)
const length = getMockData(mock)
if (source[generics]) {
// 其他类型的值
accu[currentKey] = new Array(length).fill(0).map(() => parse(source[generics], source))
} else {
// 基本类型的值
const { mock } = Resolver.getType(generics)
accu[currentKey] = new Array(length).fill(0).map(() => Mock.mock(mock))
// 基本类型的值,把数组的名字传进去,拿到匹配的mock
const { mock } = Resolver.getType(generics, currentKey as string)
accu[currentKey] = new Array(length).fill(0).map(() => getMockData(mock))
}
} else {
if (mock) {
// 一般类型
if (type === 'string') {
// 有可能是数字类型的,需要专程字符串
accu[currentKey] = '' + Mock.mock(mock)
}
accu[currentKey] = Mock.mock(mock)
accu[currentKey] = getMockData(mock)
} else {
// 复合类型
accu[currentKey] = parse(source[type || ''], source)
Expand All @@ -70,3 +66,13 @@ function parse<T, K extends keyof T>(root: T, source: any): Map<string, Ischema>
}, result)
}

const getMockData = (mock: any): any => {
// 获取mock的值
if (typeof mock !== 'string') {
const regexp = new RegExp(mock.regexp)
return Mock.mock({regexp}).regexp
} else {
return Mock.mock(mock)
}
}

0 comments on commit bf32a5a

Please sign in to comment.