Skip to content

Commit

Permalink
feat:update
Browse files Browse the repository at this point in the history
  • Loading branch information
linzb93 committed Sep 18, 2024
1 parent b3f96e7 commit d12860a
Show file tree
Hide file tree
Showing 39 changed files with 592 additions and 287 deletions.
13 changes: 13 additions & 0 deletions packages/mock/__tests__/address.test.ts
Original file line number Diff line number Diff line change
@@ -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();
});
});
53 changes: 39 additions & 14 deletions packages/mock/__tests__/core.test.ts
Original file line number Diff line number Diff line change
@@ -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}$/);
});
});
103 changes: 69 additions & 34 deletions packages/mock/lib/core/index.ts
Original file line number Diff line number Diff line change
@@ -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<T> = { [K in keyof T]: string | number | boolean };

export default function <T extends Record<string, any>>(
template: T
): Result<T> {
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<T>);
}

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<T extends { [K in keyof T]: string }>(obj: T): T {
// 这里可以添加一些转换逻辑,但最终返回的是相同的对象
return obj;
}

// 示例调用
const inputObject = {
name: "Kimi",
age: "30",
country: "Moon",
};

const outputObject = transformObject(inputObject);
15 changes: 12 additions & 3 deletions packages/mock/lib/core/use.ts
Original file line number Diff line number Diff line change
@@ -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;
}
20 changes: 20 additions & 0 deletions packages/mock/lib/index.ts
Original file line number Diff line number Diff line change
@@ -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 };
94 changes: 53 additions & 41 deletions packages/mock/lib/random/address/city.ts
Original file line number Diff line number Diff line change
@@ -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;
},
};
Loading

0 comments on commit d12860a

Please sign in to comment.