diff --git a/packages/mock/__tests__/address.test.ts b/packages/mock/__tests__/address.test.ts new file mode 100644 index 0000000..e50d029 --- /dev/null +++ b/packages/mock/__tests__/address.test.ts @@ -0,0 +1,13 @@ +import { describe, it, expect } from "vitest"; +import { mock } from "../lib"; +import { findProvince } from "../lib/random/address/testUtil"; + +describe("地址", () => { + it("省份", () => { + const obj = mock({ + from: "@province", + }); + const from = obj.from as string; + expect(findProvince(from)).toBeTruthy(); + }); +}); diff --git a/packages/mock/__tests__/core.test.ts b/packages/mock/__tests__/core.test.ts index 2e60089..037f5f7 100644 --- a/packages/mock/__tests__/core.test.ts +++ b/packages/mock/__tests__/core.test.ts @@ -1,18 +1,43 @@ import { describe, it, expect } from "vitest"; +import { mock } from "../lib"; -// const { mock } = require("@linzb93/mock"); +describe("数字", () => { + it("小于10的整数", () => { + const obj = mock({ + age: "@integer(1,10)", + }); + expect(Number.isInteger(obj.age)).toBeTruthy(); + expect(obj.age).toBeLessThan(10); + }); + it("浮点数", () => { + const obj = mock({ + money: "@float(10,140, 2, 4)", + }); + expect(Number(obj.money)).not.toBeNaN(); + expect(Number(obj.money)).not.toBe(parseInt(obj.money.toString())); + }); +}); + +describe("布尔值", () => { + it("对或错", () => { + const obj = mock({ + isStudent: "@boolean", + }); + expect(obj.isStudent === true || obj.isStudent === false).toBeTruthy(); + }); +}); -describe.todo("姓名", () => { -// const map = ["李小明", "张三", "李四", "王五"]; -// it("无筛选", () => { -// expect(map.includes(mock({ name: "@cname" }).name)).toBeTruthy(); -// }); -// it("选一个姓", () => { -// expect( -// ["李小明", "李四"].includes(mock({ name: "@cname(李)" }).name) -// ).toBeTruthy(); -// }); -// it("选一个姓,两个字的名字", () => { -// expect(mock({ name: "@cname(李,2)" })).toEqual({ name: "李四" }); -// }); +describe("字符", () => { + it("小写", () => { + const obj = mock({ + char: "@char", + }); + expect(obj.char).toMatch(/^[a-z]$/); + }); + it("字符串", () => { + const obj = mock({ + name: "@string(4,9)", + }); + expect(obj.name).toMatch(/^[a-z]{4,9}$/); + }); }); diff --git a/packages/mock/lib/core/index.ts b/packages/mock/lib/core/index.ts index 9e6c005..4cdf0d1 100644 --- a/packages/mock/lib/core/index.ts +++ b/packages/mock/lib/core/index.ts @@ -1,43 +1,78 @@ -import use, { database } from "./use"; -import cname from "../random/name/cname"; -import province from "../random/name/province"; -import city from "../random/name/city"; -import county from "../random/name/county"; +import { database } from "./use"; +import { BasicType } from "../types"; -export default function (template: any) { +function parseFunctionCall(data: string | number) { + const callString = data.toString(); + // 使用正则表达式匹配函数名称和参数(可选) + const regex = /^\s*@(\w+)\s*(?:\((.*)\))?\s*$/; + const match = callString.match(regex); + + if (!match) { + throw new Error("Invalid function call format"); + } + + // 第一个捕获组是函数名称,第二个捕获组是参数字符串(可选) + const functionName = match[1]; + let args: BasicType[] = []; + + if (match[2]) { + // 如果存在参数字符串,则处理参数 + args = match[2] + .split(",") + .map((arg) => getParams(arg.trim().replace(/['"]+/g, ""))); + } + + // 返回结果对象 + return { fn: functionName, args }; +} +type Result = { [K in keyof T]: string | number | boolean }; + +export default function >( + template: T +): Result { return Object.keys(template).reduce((obj, key) => { - // if (key.includes('|') && Array.isArray(template[key])) { - // const index = key.indexOf('|'); - // const length = Number(key.slice(index + 1)); - - // } - const matchWrap = template[key].slice(1); - const match = matchWrap.match(/^(\w+)(\((\S+)\))?$/); - if (match) { - const args = match[3] ? match[3].split(",") : []; - return { - ...obj, - [key]: database[match[1]](...getParams(args)), - }; + const value = template[key]; + if (typeof value !== "string") { + return obj; } + + const { fn, args } = parseFunctionCall(value); return { ...obj, - [key]: database[match[1]](), + [key]: database[fn](...args), }; - }, {}); + }, {} as Result); } -function getParams(args: string[]) { - return args.map((arg) => { - if (arg === "true") { - return true; - } - if (arg === "false") { - return false; - } - if (parseInt(arg) === Number(arg)) { - return Number(arg); - } - return arg; - }); +/** + * 将字符串中的boolean值和数字转换成对应类型 + * @param {string[]} arg - 待转换的参数列表 + * @returns + */ +function getParams(arg: string): BasicType { + if (arg === "true") { + return true; + } + if (arg === "false") { + return false; + } + if (!isNaN(Number(arg))) { + return Number(arg); + } + return arg; } + +/*** */ +function transformObject(obj: T): T { + // 这里可以添加一些转换逻辑,但最终返回的是相同的对象 + return obj; +} + +// 示例调用 +const inputObject = { + name: "Kimi", + age: "30", + country: "Moon", +}; + +const outputObject = transformObject(inputObject); diff --git a/packages/mock/lib/core/use.ts b/packages/mock/lib/core/use.ts index 8d8dff5..ddd461d 100644 --- a/packages/mock/lib/core/use.ts +++ b/packages/mock/lib/core/use.ts @@ -1,7 +1,16 @@ -type PluginType = (value: string, length: number) => string; +import type { BasicType } from "../types"; + +type PluginType = (...args: any[]) => BasicType; export const database: { [key: string]: PluginType; } = {}; -export default function (name: string, plugin: PluginType) { - database[name] = plugin; + +interface MockPlugin { + name: string; + serve: PluginType; +} + +export default function (plugin: MockPlugin) { + const { name, serve } = plugin; + database[name] = serve; } diff --git a/packages/mock/lib/index.ts b/packages/mock/lib/index.ts index 57643d7..2e6f782 100644 --- a/packages/mock/lib/index.ts +++ b/packages/mock/lib/index.ts @@ -1,4 +1,24 @@ import * as utils from "./shared"; import use from "./core/use"; import mock from "./core"; +import integer from "./random/basic/integer"; +import char from "./random/basic/char"; +import mockString from "./random/basic/string"; +import mockBoolean from "./random/basic/boolean"; +import float from "./random/basic/float"; +import province from "./random/address/province"; + +/** + * 基础部分 + */ +use(integer); +use(mockBoolean); +use(char); +use(mockString); +use(float); +/** + * 地址 + */ +use(province); + export { utils, use, mock }; diff --git a/packages/mock/lib/random/address/city.ts b/packages/mock/lib/random/address/city.ts index eadb6da..0b24e41 100644 --- a/packages/mock/lib/random/address/city.ts +++ b/packages/mock/lib/random/address/city.ts @@ -1,45 +1,57 @@ -import addrData from "./address_ch.json"; -import { sample } from '../../shared'; +import addrData from "./dict.json"; +import { sample } from "lodash-es"; + +type Props = keyof typeof addrData; + /** - * - * @param {Boolean | String} args 是否同时显示完整 | 指定省份下的城市 - * @returns string + * 随机获取城市名称 */ -module.exports = (...args:any[]) => { - const isFull = - (args.length === 1 && args[0] === true) || - (args.length === 2 && args[1] === true); - const prefix = typeof args[0] === "string" ? args[0] : ""; - if (prefix) { - // 匹配省份 - const provinceCode = Object.keys(addrData).find( - (code) => addrData[code] === prefix - ); - if (!provinceCode) { - // 无法匹配的就返回空字符串 - return ""; - } - const cityList = Object.keys(addrData).filter( - (code) => - code.slice(0, 2) === provinceCode.slice(0, 2) && - code.endsWith("00") && - addrData[code] !== prefix - ); - if (isFull) { - return `${prefix}${addrData[sample(cityList)]}`; - } - return addrData[sample(cityList)]; - } - const cityCodes = Object.keys(addrData).filter( - (code) => code.endsWith("00") && code.slice(2, 4) !== "00" - ); - const cityCode = sample(cityCodes); - const cityName = addrData[cityCode]; - if (isFull) { - const provinceCode = cityCode.toString().replace(/\d{4}$/, "0000"); - const provinceName = addrData[provinceCode]; - return `${provinceName}${cityName}`; - } +export default { + name: "city", + /** + * @param {boolean} showAll - 是否显示完整地址 + * @param {string} prefix - 筛选某个省、自治区、直辖市下的城市 + * @returns {string} + */ + serve: (showAll: boolean, prefix: string) => { + const cityName = ""; + // 如果prefix不为空,则搜索省份的名字,获取前2位,找到所有code前两位相同的城市。 + + // const isFull = + // (args.length === 1 && args[0] === true) || + // (args.length === 2 && args[1] === true); + // const prefix = typeof args[0] === "string" ? args[0] : ""; + // if (prefix) { + // // 匹配省份 + // const provinceCode = Object.keys(addrData).find( + // (code) => addrData[code] === prefix + // ); + // if (!provinceCode) { + // // 无法匹配的就返回空字符串 + // return ""; + // } + // const cityList = Object.keys(addrData).filter( + // (code) => + // code.slice(0, 2) === provinceCode.slice(0, 2) && + // code.endsWith("00") && + // addrData[code] !== prefix + // ); + // if (isFull) { + // return `${prefix}${addrData[sample(cityList)]}`; + // } + // return addrData[sample(cityList)]; + // } + // const cityCodes = Object.keys(addrData).filter( + // (code) => code.endsWith("00") && code.slice(2, 4) !== "00" + // ); + // const cityCode = sample(cityCodes); + // const cityName = addrData[cityCode]; + // if (isFull) { + // const provinceCode = cityCode.toString().replace(/\d{4}$/, "0000"); + // const provinceName = addrData[provinceCode]; + // return `${provinceName}${cityName}`; + // } - return cityName; + return cityName; + }, }; diff --git a/packages/mock/lib/random/address/county.ts b/packages/mock/lib/random/address/county.ts index 2e8bae9..a9d2c0a 100644 --- a/packages/mock/lib/random/address/county.ts +++ b/packages/mock/lib/random/address/county.ts @@ -1,43 +1,46 @@ -const addrData = require("./address_ch.json"); -const { sample } = require("../../utils"); +import addrData from "./dict.json"; +import { sample } from "../../shared"; /** * * @param {Boolean | String} args 是否同时显示完整 | 指定省份下的城市 * @returns string */ -module.exports = (...args) => { - const isFull = - (args.length === 1 && args[0] === true) || - (args.length === 2 && args[1] === true); - const prefix = typeof args[0] === "string" ? args[0] : ""; - if (prefix) { - // 匹配省份 - const provinceCode = Object.keys(addrData).find( - (code) => addrData[code] === prefix - ); - if (!provinceCode) { - // 无法匹配的就返回空字符串 - return ""; +export default { + name: "county", + serve: (...args) => { + const isFull = + (args.length === 1 && args[0] === true) || + (args.length === 2 && args[1] === true); + const prefix = typeof args[0] === "string" ? args[0] : ""; + if (prefix) { + // 匹配省份 + const provinceCode = Object.keys(addrData).find( + (code) => addrData[code] === prefix + ); + if (!provinceCode) { + // 无法匹配的就返回空字符串 + return ""; + } + const cityList = Object.keys(addrData).filter( + (code) => + code.slice(0, 2) === provinceCode.slice(0, 2) && !code.endsWith("00") + ); + if (isFull) { + return `${prefix}${sample(cityList)}`; + } + return sample(cityList); } - const cityList = Object.keys(addrData).filter( - (code) => - code.slice(0, 2) === provinceCode.slice(0, 2) && !code.endsWith("00") + const countyCodes = Object.keys(addrData).filter( + (code) => !code.endsWith("00") ); + const countyCode = sample(countyCodes); + const countyName = addrData[countyCode]; if (isFull) { - return `${prefix}${sample(cityList)}`; + const provinceCode = countyCode.toString().replace(/\d{4}$/, "0000"); + const cityCode = countyCode.toString().replace(/\d{2}$/, "00"); + return `${addrData[provinceCode]}${addrData[cityCode]}${countyName}`; } - return sample(cityList); - } - const countyCodes = Object.keys(addrData).filter( - (code) => !code.endsWith("00") - ); - const countyCode = sample(countyCodes); - const countyName = addrData[countyCode]; - if (isFull) { - const provinceCode = countyCode.toString().replace(/\d{4}$/, "0000"); - const cityCode = countyCode.toString().replace(/\d{2}$/, "00"); - return `${addrData[provinceCode]}${addrData[cityCode]}${countyName}`; - } - return countyName; + return countyName; + }, }; diff --git a/packages/mock/lib/random/address/address_ch.json b/packages/mock/lib/random/address/dict.json similarity index 100% rename from packages/mock/lib/random/address/address_ch.json rename to packages/mock/lib/random/address/dict.json diff --git a/packages/mock/lib/random/address/province.ts b/packages/mock/lib/random/address/province.ts index f32adda..ccbbcb6 100644 --- a/packages/mock/lib/random/address/province.ts +++ b/packages/mock/lib/random/address/province.ts @@ -1,8 +1,17 @@ -const addrData = require("./address_ch.json"); -const { sample } = require("../../utils"); -module.exports = () => { - const provinceCodes = Object.keys(addrData).filter((code) => - code.endsWith("0000") - ); - return addrData[sample(provinceCodes)]; +import addrData from "./dict.json"; +import { sample } from "lodash-es"; +import { getProvinceCodes, getCodeName } from "./shared"; + +type Props = keyof typeof addrData; + +/** + * 随机获取省份(含省、自治区、直辖市)名称 + */ +export default { + name: "province", + serve: () => { + const provinceCodes = getProvinceCodes(); + const target = sample(provinceCodes) as Props; + return getCodeName(target); + }, }; diff --git a/packages/mock/lib/random/address/shared.ts b/packages/mock/lib/random/address/shared.ts new file mode 100644 index 0000000..4339b3e --- /dev/null +++ b/packages/mock/lib/random/address/shared.ts @@ -0,0 +1,9 @@ +import addrData from "./dict.json"; + +export const getProvinceCodes = () => { + return Object.keys(addrData).filter((code) => code.endsWith("0000")); +}; + +type Props = keyof typeof addrData; + +export const getCodeName = (code: Props) => addrData[code]; diff --git a/packages/mock/lib/random/address/testUtil.ts b/packages/mock/lib/random/address/testUtil.ts new file mode 100644 index 0000000..18f8207 --- /dev/null +++ b/packages/mock/lib/random/address/testUtil.ts @@ -0,0 +1,16 @@ +import addrData from "./dict.json"; + +type Props = keyof typeof addrData; + +export function findProvince(name: string) { + if (!process.env.VITEST) { + throw new Error(`this function is only used in test mode. `); + } + const provinceCodes = Object.keys(addrData).filter((code) => + code.endsWith("0000") + ); + return !!provinceCodes.find((item) => { + const target = item as Props; + return addrData[target] === name; + }); +} diff --git a/packages/mock/lib/random/address/zip.ts b/packages/mock/lib/random/address/zip.ts index 50317f7..1264297 100644 --- a/packages/mock/lib/random/address/zip.ts +++ b/packages/mock/lib/random/address/zip.ts @@ -1,5 +1,11 @@ -const { sample } = require("../../utils"); -const addrData = require("./address_ch.json"); -module.exports = () => { - return sample(Object.keys(addrData)); +import addrData from "./dict.json"; +import { sample } from "lodash-es"; +/** + * 随机生成一个六位数邮政编码 + */ +export default { + name: "zip", + serve: () => { + return sample(Object.keys(addrData)); + }, }; diff --git a/packages/mock/lib/random/basic/boolean.ts b/packages/mock/lib/random/basic/boolean.ts index 483b0dd..bd31696 100644 --- a/packages/mock/lib/random/basic/boolean.ts +++ b/packages/mock/lib/random/basic/boolean.ts @@ -1,10 +1,13 @@ -import { sample } from "../../shared"; +import { sample } from "lodash-es"; /** * 返回true或者false * @example * '@boolean'; */ -export default () => { - return sample([true, false]); +export default { + name: "boolean", + serve: () => { + return sample([true, false]); + }, }; diff --git a/packages/mock/lib/random/basic/char.ts b/packages/mock/lib/random/basic/char.ts index 370cd09..3309f6d 100644 --- a/packages/mock/lib/random/basic/char.ts +++ b/packages/mock/lib/random/basic/char.ts @@ -5,4 +5,7 @@ import { repeat } from "../../shared"; * @example * '@char' */ -export default () => repeat(2, 1); +export default { + name: "char", + serve: () => repeat(2, 1), +}; diff --git a/packages/mock/lib/random/basic/float.ts b/packages/mock/lib/random/basic/float.ts index 6b8a06f..239906c 100644 --- a/packages/mock/lib/random/basic/float.ts +++ b/packages/mock/lib/random/basic/float.ts @@ -4,13 +4,13 @@ * @float(3, 500, 2, 5) // 整数在3~500,小数在2~5位。 * @float(5,10) // 整数在5~10,小数在1~7位。 */ -export default (min = 1, max = 1e9, dmin = 1, dmax = 7) => { - const int = min + parseInt((Math.random() * (max - min)).toString()); - let dec = parseInt( - (Math.random() * Math.pow(10, dmax)).toString() - ).toString(); - if (Number(dec) < Math.pow(10, dmin)) { - dec = "0".repeat(dmin - dec.toString().replace(/0+$/g, "").length) + dec; - } - return `${int}.${dec}`; +import integer from "./integer"; +import { repeatNumber } from "../../shared"; +export default { + name: "float", + serve: (min = 1, max = 1e9, dmin = 1, dmax = 7) => { + const int = integer.serve(min, max); + let dec = repeatNumber(dmin, dmax); + return Number(`${int}.${dec}`); + }, }; diff --git a/packages/mock/lib/random/basic/integer.ts b/packages/mock/lib/random/basic/integer.ts index b238f81..d5cec1c 100644 --- a/packages/mock/lib/random/basic/integer.ts +++ b/packages/mock/lib/random/basic/integer.ts @@ -8,19 +8,18 @@ function randomInteger(): number; function randomInteger(max: number): number; function randomInteger(min: number, max: number): number; function randomInteger(...args: any[]) { - let max = 1e10; - if (args.length === 0) { - return parseInt((Math.random() * max).toString()); - } - if (args.length === 1) { - max = Number(args[0]); - return parseInt((Math.random() * max).toString()); - } - if (args.length === 2) { - const min = Number(args[0]); - const max = Number(args[1]); - return parseInt((Math.random() * (max - min)).toString()) + min; + let max = 0; + let min = 0; + if (args.length < 2) { + max = args.length == 1 ? Number(args[0]) : 1e9; + } else { + min = Number(args[0]); + max = Number(args[1]); } + return parseInt((Math.random() * (max - min)).toString()) + min; } -export default randomInteger; +export default { + name: "integer", + serve: randomInteger, +}; diff --git a/packages/mock/lib/random/basic/string.ts b/packages/mock/lib/random/basic/string.ts index 7dc7e10..880493c 100644 --- a/packages/mock/lib/random/basic/string.ts +++ b/packages/mock/lib/random/basic/string.ts @@ -1,4 +1,7 @@ -import { repeat } from '../../shared' -export default (min = 3, max = 10) => { - return repeat(2, min, max) +import { repeatString } from "../../shared"; +export default { + name: "string", + serve: (min = 3, max = 10) => { + return repeatString(min, max); + }, }; diff --git a/packages/mock/lib/random/color/color.ts b/packages/mock/lib/random/color/color.ts index cbe623f..e827cac 100644 --- a/packages/mock/lib/random/color/color.ts +++ b/packages/mock/lib/random/color/color.ts @@ -1,9 +1,14 @@ -export default () => { - return `#${getRandom()}${getRandom()}${getRandom()}`; +import integer from "../basic/integer"; +/** + * 生成RGB格式十六进制的 + */ +export default { + name: "color", + serve: () => { + return `#${getRandom()}${getRandom()}${getRandom()}`; + }, }; function getRandom() { - const data = parseInt((Math.random() * 256).toString()); - const raw = data === 256 ? 255 : data; - return raw.toString(16); + return integer.serve(0, 255).toString(16); } diff --git a/packages/mock/lib/random/color/rgb.ts b/packages/mock/lib/random/color/rgb.ts index d907e8d..2380dde 100644 --- a/packages/mock/lib/random/color/rgb.ts +++ b/packages/mock/lib/random/color/rgb.ts @@ -1,12 +1,18 @@ -export default (useOpacity: boolean) => { - if (useOpacity === true) { - const opacity = Math.random().toFixed(2); - return `rgba(${getRandom()},${getRandom()},${getRandom()},${opacity})`; - } - return `rgb(${getRandom()},${getRandom()},${getRandom()})`; +import integer from "../basic/integer"; +/** + * 生成rgb格式的颜色,含透明度 + */ +export default { + name: "rgb", + serve: (useOpacity: boolean) => { + if (useOpacity === true) { + const opacity = (integer.serve(0, 100) / 100).toFixed(2); + return `rgba(${getRandom()},${getRandom()},${getRandom()},${opacity})`; + } + return `rgb(${getRandom()},${getRandom()},${getRandom()})`; + }, }; function getRandom() { - const data = parseInt((Math.random() * 256).toString()); - return data === 256 ? 255 : data; + return integer.serve(0, 255); } diff --git a/packages/mock/lib/random/date/date.ts b/packages/mock/lib/random/date/date.ts index 82b3e14..004ebf8 100644 --- a/packages/mock/lib/random/date/date.ts +++ b/packages/mock/lib/random/date/date.ts @@ -1,18 +1,24 @@ import dayjs from "dayjs"; -export default (...args: any[]) => { - if (args.length === 0) { - return dayjs(parseInt((Math.random() * 1e10).toString())).toDate(); - } else if (args.length === 1) { - return dayjs(parseInt((Math.random() * 1e10).toString())).format(args[0]); - } else if (args.length === 3) { - const [type, date, format] = args; +export default { + name: "date", + serve: (...args: any[]) => { + if (args.length === 0) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format( + "YYYY-MM-DD" + ); + } + if (args.length === 1) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format(args[0]); + } + const [type, date, format = "YYYY-MM-DD"] = args; if (type === "before") { const max = dayjs(date).unix(); return dayjs(parseInt((Math.random() * max).toString())).format(format); - } else if (type === "after") { + } + if (type === "after") { const max = dayjs().add(1, "y").unix(); return dayjs(parseInt((Math.random() * max).toString())).format(format); } - } + }, }; diff --git a/packages/mock/lib/random/date/datetime.ts b/packages/mock/lib/random/date/datetime.ts new file mode 100644 index 0000000..039d9c2 --- /dev/null +++ b/packages/mock/lib/random/date/datetime.ts @@ -0,0 +1,23 @@ +import dayjs from "dayjs"; + +export default { + name: "datetime", + serve: (...args: any[]) => { + if (args.length === 0) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format( + "YYYY-MM-DD HH:mm:ss" + ); + } + if (args.length === 1) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format(args[0]); + } + const [type, date, format = "YYYY-MM-DD HH:mm:ss"] = args; + if (type === "before") { + const max = dayjs(date).unix(); + return dayjs(parseInt((Math.random() * max).toString())).format(format); + } else if (type === "after") { + const max = dayjs().add(1, "y").unix(); + return dayjs(parseInt((Math.random() * max).toString())).format(format); + } + }, +}; diff --git a/packages/mock/lib/random/date/time.ts b/packages/mock/lib/random/date/time.ts new file mode 100644 index 0000000..fbcad54 --- /dev/null +++ b/packages/mock/lib/random/date/time.ts @@ -0,0 +1,24 @@ +import dayjs from "dayjs"; + +export default { + name: "time", + serve: (...args: any[]) => { + if (args.length === 0) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format( + "HH:mm:ss" + ); + } + if (args.length === 1) { + return dayjs(parseInt((Math.random() * 1e10).toString())).format(args[0]); + } + const [type, date, format = "HH:mm:ss"] = args; + if (type === "before") { + const max = dayjs(date).unix(); + return dayjs(parseInt((Math.random() * max).toString())).format(format); + } + if (type === "after") { + const max = dayjs().add(1, "y").unix(); + return dayjs(parseInt((Math.random() * max).toString())).format(format); + } + }, +}; diff --git a/packages/mock/lib/random/name/cfirst.ts b/packages/mock/lib/random/name/cfirst.ts index b87c46b..b993baf 100644 --- a/packages/mock/lib/random/name/cfirst.ts +++ b/packages/mock/lib/random/name/cfirst.ts @@ -1,12 +1,19 @@ -const { sample } = require("../../utils"); +import { sample } from "lodash-es"; +import dict from "./dict.json"; -module.exports = (length) => { - const map = require("./name.json").cfirst; - if (!length) { - return sample(map); - } - if (Number(length) === 2) { - return sample(map.filter((item) => item.length === 2)); - } - return sample(map.filter((item) => item.length === 1)); +/** + * 生成中文姓氏,可以指定姓氏长度为一个字或者两个字 + */ +export default { + name: "cfirst", + serve: (length?: number) => { + const map = dict.cfirst; + if (!length) { + return sample(map); + } + if (Number(length) === 2) { + return sample(map.filter((item) => item.length === 2)); + } + return sample(map.filter((item) => item.length === 1)); + }, }; diff --git a/packages/mock/lib/random/name/clast.ts b/packages/mock/lib/random/name/clast.ts index c185ac9..4d6b399 100644 --- a/packages/mock/lib/random/name/clast.ts +++ b/packages/mock/lib/random/name/clast.ts @@ -1,12 +1,19 @@ -const { sample } = require("../../utils"); +import { sample } from "lodash-es"; +import dict from "./dict.json"; -module.exports = (length) => { - const map = require("./name.json").clast; - if (!length) { - return sample(map); - } - if (Number(length) === 2) { - return sample(map.filter((item) => item.length === 2)); - } - return sample(map.filter((item) => item.length === 1)); +/** + * 生成中文名字,可以指定名字长度为一个字或者两个字 + */ +export default { + name: "clast", + serve: (length?: number) => { + const map = dict.clast; + if (!length) { + return sample(map); + } + if (Number(length) === 2) { + return sample(map.filter((item) => item.length === 2)); + } + return sample(map.filter((item) => item.length === 1)); + }, }; diff --git a/packages/mock/lib/random/name/cname.ts b/packages/mock/lib/random/name/cname.ts index e5e1dfe..043cb02 100644 --- a/packages/mock/lib/random/name/cname.ts +++ b/packages/mock/lib/random/name/cname.ts @@ -1,16 +1,14 @@ -const nameData = require("./name.json"); -const { sample } = require("../../utils"); -module.exports = (first, length) => { - if (first) { - if (length) { - if (length - first.length <= 0) { - return ""; - } - return `${first}${sample( - nameData.clast.filter((name) => length - first.length === name.length) - )}`; +import cfirst from "./cfirst"; +import clast from "./clast"; +/** + * 生成中文全名,可以指定姓氏 + */ +export default { + name: "cname", + serve: (first: string, length: number) => { + if (first) { + return `${first}${clast.serve(length)}`; } - return `${first}${sample(nameData.clast)}`; - } - return `${sample(nameData.cfirst)}${sample(nameData.clast)}`; + return `${cfirst.serve()}${clast.serve(length)}`; + }, }; diff --git a/packages/mock/lib/random/name/name.json b/packages/mock/lib/random/name/dict.json similarity index 100% rename from packages/mock/lib/random/name/name.json rename to packages/mock/lib/random/name/dict.json diff --git a/packages/mock/lib/random/struc/tree.ts b/packages/mock/lib/random/struc/tree.ts index 379d89a..561d683 100644 --- a/packages/mock/lib/random/struc/tree.ts +++ b/packages/mock/lib/random/struc/tree.ts @@ -1,4 +1,5 @@ /** + * 生成树形结构,格式如下: * { * "data|tree": { * "id": "", // 自定义 @@ -9,4 +10,7 @@ * * "data|tree.3" 表示最多嵌套三层,默认5层。 */ -export default () => {}; +export default { + name: "tree", + serve: () => {}, +}; diff --git a/packages/mock/lib/random/text/cparagraph.ts b/packages/mock/lib/random/text/cparagraph.ts new file mode 100644 index 0000000..675b40c --- /dev/null +++ b/packages/mock/lib/random/text/cparagraph.ts @@ -0,0 +1,9 @@ +import { sample } from "lodash-es"; +import dict from "./dict_cn.json"; +/** + * 生成中文语句(带符号的汉字集合,结尾是句号) + */ +export default { + name: "cparagraph", + serve: () => {}, +}; diff --git a/packages/mock/lib/random/text/csentence.ts b/packages/mock/lib/random/text/csentence.ts new file mode 100644 index 0000000..66284b2 --- /dev/null +++ b/packages/mock/lib/random/text/csentence.ts @@ -0,0 +1,9 @@ +import { sample } from "lodash-es"; +import dict from "./dict_cn.json"; +/** + * 生成中文语句(带符号的汉字集合,结尾是句号) + */ +export default { + name: "csentence", + serve: () => {}, +}; diff --git a/packages/mock/lib/random/text/ctitle.ts b/packages/mock/lib/random/text/ctitle.ts new file mode 100644 index 0000000..db6ffcc --- /dev/null +++ b/packages/mock/lib/random/text/ctitle.ts @@ -0,0 +1,9 @@ +import { sample } from "lodash-es"; +import dict from "./dict_cn.json"; +/** + * 生成中文标题(不带符号的汉字集合) + */ +export default { + name: "ctitle", + serve: () => {}, +}; diff --git a/packages/mock/lib/random/text/dict_cn.json b/packages/mock/lib/random/text/dict_cn.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/packages/mock/lib/random/text/dict_cn.json @@ -0,0 +1 @@ +{} diff --git a/packages/mock/lib/random/web/email.ts b/packages/mock/lib/random/web/email.ts index e070bc5..65ead50 100644 --- a/packages/mock/lib/random/web/email.ts +++ b/packages/mock/lib/random/web/email.ts @@ -1,10 +1,14 @@ -import { sample } from "../../shared"; +import { sample } from "lodash-es"; +import { repeatNumberAndString } from "../../shared"; -export default (serve: string) => { - const prefix = ""; - if (serve) { - return `${prefix}@${serve}.com`; - } - const matchServe = sample(["qq", "163", "sina", "gmail", "souhu"]); - return `${prefix}@${matchServe}.com`; +export default { + name: "email", + serve: (serve: string) => { + const prefix = repeatNumberAndString(5, 9); + if (serve) { + return `${prefix}@${serve}.com`; + } + const matchServe = sample(["qq", "163", "sina", "gmail", "souhu"]); + return `${prefix}@${matchServe}.com`; + }, }; diff --git a/packages/mock/lib/random/web/image.ts b/packages/mock/lib/random/web/image.ts index 54b6bdc..88e2a7d 100644 --- a/packages/mock/lib/random/web/image.ts +++ b/packages/mock/lib/random/web/image.ts @@ -1,3 +1,6 @@ -export default (size: string) => { - return `http://dummyimage.com/${size}`; +export default { + name: "image", + serve: (size: string) => { + return `http://dummyimage.com/${size}`; + }, }; diff --git a/packages/mock/lib/random/web/ip.ts b/packages/mock/lib/random/web/ip.ts index 9b7bce9..446edba 100644 --- a/packages/mock/lib/random/web/ip.ts +++ b/packages/mock/lib/random/web/ip.ts @@ -1,7 +1,11 @@ -export default () => { - return `${getData()}.${getData()}.${getData()}.${getData()}`; +import integer from "../basic/integer"; +export default { + name: "ip", + serve: () => { + return `${getData()}.${getData()}.${getData()}.${getData()}`; + }, }; function getData() { - return parseInt(Math.random() * 256); + return integer.serve(0, 255); } diff --git a/packages/mock/lib/random/web/mobile.ts b/packages/mock/lib/random/web/mobile.ts index 02a5c31..e7a181f 100644 --- a/packages/mock/lib/random/web/mobile.ts +++ b/packages/mock/lib/random/web/mobile.ts @@ -1,9 +1,9 @@ -import { sample } from "../../shared"; -export default () => { - const prefix = sample([13, 15, 18]); - let ret = prefix.toString(); - for (let i = 0; i < 9; i++) { - ret += parseInt(Math.random() * 10); - } - return Number(ret); +import { sample } from "lodash-es"; +import { repeatNumber } from "../../shared"; +export default { + name: "mobile", + serve: () => { + const prefix = sample([13, 15, 18]); + return Number(`${prefix}${repeatNumber(9)}`); + }, }; diff --git a/packages/mock/lib/random/web/url.ts b/packages/mock/lib/random/web/url.ts index 48140e8..0ff98cf 100644 --- a/packages/mock/lib/random/web/url.ts +++ b/packages/mock/lib/random/web/url.ts @@ -1,8 +1,11 @@ -import { sample } from "../../shared"; +import { sample } from "lodash-es"; import stringFn from "../basic/string"; -export default (useHttp: boolean) => { - const protocol = useHttp ? "http" : "https"; - const top = sample(["com", "cn", "net"]); - return `${protocol}://www.${stringFn(3, 6)}.${top}`; +export default { + name: "url", + serve: (useHttp: boolean) => { + const protocol = useHttp ? "http" : "https"; + const top = sample(["com", "cn", "net"]); + return `${protocol}://www.${stringFn.serve(3, 6)}.${top}`; + }, }; diff --git a/packages/mock/lib/shared/index.ts b/packages/mock/lib/shared/index.ts index 6b8915e..6fdde02 100644 --- a/packages/mock/lib/shared/index.ts +++ b/packages/mock/lib/shared/index.ts @@ -1,48 +1,54 @@ -// import { fill } from "lodash-es"; +import { sample } from "lodash-es"; -export const sample = (list: any[]) => { - return list[parseInt((Math.random() * list.length).toString())]; -}; +export { sample }; -const fixContinuousNumber = (num:number) => Array(num).fill('').map((_, index) => index + 1); +const letters = "abcdefghijklmnopqrstuvwxyz".split(""); +const numList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; +function getLength(min: number, max?: number) { + return !max ? min : min + parseInt((Math.random() * (max - min)).toString()); +} +/** + * 重复数字 + * @param min + * @param max + * @returns + */ +export const repeatNumber = (min = 1, max?: number) => { + const totalLength = getLength(min, max); + let output = ""; + for (let i = 0; i < totalLength; i++) { + output += sample(numList); + } + return output; +}; /** - * 重复 - * @param {number} type - 1 纯数字,2纯字母,3混合 - * @param {number} min 重复次数,如果max存在的话就是重复最小次数 - * @param {number} max 重复最大次数 - * @returns + * 重复字符 + * @param min + * @param max + * @returns */ -export const repeat = (type: 1 | 2 | 3, min: number, max?: number) => { - let ret = ""; - const numList = fixContinuousNumber(10); - const letters = "abcdefghijklmnopqrstuvwxyz"; - if (type === 1) { - if (!max) { - for (let i = 0; i < min; i++) { - ret += sample(numList); - } - return Number(ret); - } else { - const len = min + parseInt((Math.random() * (max - min)).toString()); - for (let i = min; i < len; i++) { - ret += sample(numList); - } - return Number(ret); - } +export const repeatString = (min = 1, max?: number) => { + const totalLength = getLength(min, max); + let output = ""; + for (let i = 0; i < totalLength; i++) { + output += sample(letters); } - if (type === 2) { - if (!max) { - for (let i = 0; i < min; i++) { - ret += sample(letters.split("")); - } - return Number(ret); - } else { - const len = min + parseInt((Math.random() * (max - min)).toString()); - for (let i = min; i < len; i++) { - ret += sample(letters.split("")); - } - return Number(ret); - } + return output; +}; + +/** + * 重复字符和数字 + * @param min + * @param max + * @returns + */ +export const repeatNumberAndString = (min = 1, max?: number) => { + const totalLength = getLength(min, max); + let output = ""; + const mixedList = [...numList, ...letters]; + for (let i = 0; i < totalLength; i++) { + output += sample(mixedList); } + return output; }; diff --git a/packages/mock/lib/types.d.ts b/packages/mock/lib/types.d.ts new file mode 100644 index 0000000..106c454 --- /dev/null +++ b/packages/mock/lib/types.d.ts @@ -0,0 +1,11 @@ +export interface AnyObject { + [key: string]: any; +} + +export interface NumberOrStringObject { + [key: string]: number | string; +} +export interface StringObject { + [key: string]: string; +} +export type BasicType = string | number | boolean; diff --git a/packages/mock/package.json b/packages/mock/package.json index d1fc4fc..11e9b57 100644 --- a/packages/mock/package.json +++ b/packages/mock/package.json @@ -1,6 +1,7 @@ { "name": "@linzb93/mock", "version": "0.0.1", + "type": "module", "description": "mockjs", "keywords": [ "mockjs"