npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pylonts/mock

v1.1.5

Published

TypeScript 语义化测试数据生成器。提供带业务规则的随机数据生成函数,而非纯随机字符串。

Readme

@pylonts/mock — Mock Data Generators

TypeScript 语义化测试数据生成器。提供带业务规则的随机数据生成函数,而非纯随机字符串。

Philosophy

三级精度

| 级别 | 含义 | 例子 | |------|------|------| | 合法 | 格式正确,能通过基本校验 | mockNumbers(6) → "834102" | | 合理 | 业务规则下有意义 | mockPhone() → "13812345678"(手机号段正确) | | 可关联 | 跨实体 ID 一致,可组成有效请求 | mockMerchantId() → "M12345678"(兼容 DB 主键) |

本库保证所有生成器至少达到 合理 级别。纯随机字符串(mockAbc / mockNumbers)作为基础构件暴露给调用方自行组合。

语义生成器 ≠ 纯随机

纯随机:               Math.random().toString(36).slice(2, 8)
语义生成器:            mockPhone()            → "13812345678"  (合规号段)
                       mockIdCard()           → "110101199001011234"  (通过校验位)
                       mockBankCard()         → "6222021234567890"  (真实 BIN 前缀)
                       mockCompanyName()      → "深圳市创新科技有限公司"  (真实地名+行业用字)

什么字段该进库

进入 @pylonts/mock 的唯一前提:生成正确值需要非平凡的业务领域规则。

| 字段 | 规则 | 进库? | |------|------|--------| | phone | 号段前缀选择(13x/15x/17x/18x/19x) | ✅ 已有 | | idCard | 地区码+日期+顺序码+校验位算法 | ✅ 已有 | | bankCard | 真实 BIN 前缀 + Luhn 校验 | ✅ 已有 | | companyName | 真实地名+字号+行业后缀 | ✅ 已有 | | amt | 两位小数,正数,单位元 | ✅ 已有 | | rate | 四位小数以内,范围 0.001-0.030 | ✅ 已有 | | name | 姓氏库+频次统计 | ✅ 已有 | | datetime | 就是一段有效日期 | ❌ new Date() 即可 | | description | 无规则,纯填充 | ❌ mockChinese() 即可 |

反例:datetime 不该进库

// ❌ 错误做法:试图用 mockInteger 组合 datetime
const mockDatetime = () => {
  const y = mockInteger(2024, 2026);
  const m = String(mockInteger(1, 12)).padStart(2, '0');
  const d = String(mockInteger(1, 28)).padStart(2, '0');
  const hh = String(mockInteger(0, 23)).padStart(2, '0');
  const mm = String(mockInteger(0, 59)).padStart(2, '0');
  const ss = String(mockInteger(0, 59)).padStart(2, '0');
  return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
};

各段独立随机,导致日期不存在(2025-02-29、2024-04-31),固定 1-28 又丢失了合法日期。

正确做法:项目层一行 new Date(),不需进库。

// ✅ 项目层单行搞定
const now = new Date();
const paidAt = new Date(now.getTime() - mockInteger(3600000, 86400000)); // 1-24小时前

生成器准入规则

对于确定要进库的生成器,必须满足:输出永远符合所属数据类型的全部业务规则,而不是仅仅符合正则。

| 维度 | 规则 | 反例 | |------|------|------| | 手机号 | 号段合规(移动/联通/电信可识别),11 位 | Numbers(11) → 号段可能为 "000" | | 身份证 | 18 位,地区码+日期+顺序码+校验位全部正确 | Numbers(18) → 校验位大概率错误 | | 银行卡 | 使用真实 BIN 前缀,通过 Luhn 校验 | Numbers(16) → BIN 不存在,Luhn 不通过 | | 金额 | 两位小数,正数,单位元 | Number() → 可能为 3.14159 | | 费率 | 四位小数以内,范围 0.001-0.030 | Math.random() → 可能为 0.5 | | 公司名 | 真实地名+字号+行业后缀 | Chinese(8) → "鞷閏鬻龘有限公司" |

组合优先,新增其次

能用现有生成器组合出的语义,暂不新增生成器,接入方在外层组合即可:

VERIFY_CODE    = mockNumbers(6)                 ✅ 直接复用
RECON_PERIOD   = `2026-${pad(mockInteger(1,12))}`  ✅ 表达式组合
USCC           = mockAbcUpper(1) + mockNumbers(17) ⚠️ 暂代,需校验位时再升级

判断标准:当同一个组合逻辑出现在 2 个以上消费方时,就应该收归库内实现。

Architecture

src/
├── index.ts              # re-export all generators
├── types.ts              # type aliases for generator signatures
├── generators/
│   ├── name.ts           # mockName, mockChinese
│   ├── phone.ts          # mockPhone
│   ├── finance.ts        # mockAmt, mockRate, mockUnionpayId
│   ├── company.ts        # mockCompanyName, mockAddress, mockCompanyInfo
│   ├── id.ts             # mockMerchantId, mockOrderId, mockSeq
│   ├── identity.ts       # mockIdCard, mockBankCard
│   └── random.ts         # mockAbc, mockAbcUpper, mockAbc123, mockNumbers, mockInteger, mockBirthday

分层

random.ts          ── 基础构件(纯随机字符串/数字,所有其他生成器的基石)
name.ts/phone.ts   ── 业务基础(有业务规则的单一数据类型)
company.ts         ── 复合业务(组合多个基础生成器,返回结构化数据)
id.ts              ── 实体 ID(有唯一性要求的生成器)
identity.ts        ── 合规数据(有校验位/BIN 算法的生成器)

生成器契约

所有生成器遵循统一签名:(...args?) => T,无状态(mockSeq 除外,它有自增计数器)。

// 无参数
type PhoneGenerator = (operator?: Operator) => string;

// 可选参数约束范围
type AmountGenerator = (min?: number, max?: number) => string;

// 固定返回
type RateGenerator = () => string;

Usage

import {
  mockName, mockPhone, mockAmt, mockRate,
  mockCompanyName, mockAddress,
  mockMerchantId, mockOrderId, mockSeq,
  mockIdCard, mockBankCard,
  mockAbc, mockNumbers, mockInteger, mockBirthday,
} from '@pylonts/mock';

// 基本用法
mockName();                  // "张伟"
mockName('female');          // "李娜"
mockPhone();                 // "13812345678"
mockPhone('unicom');         // "18612345678"
mockAmt(10, 100);            // "58.50"
mockRate();                  // "0.006"
mockMerchantId();            // "M1234567890123"

Extending

原则

  1. 先组合,再新增:mockNumbers(6) 可以满足的场景,不写 mockVerifyCode()
  2. 合理是底线:新增生成器必须保证输出符合业务规则(如手机号对号段、身份证对校验位)
  3. 无状态优先:除 mockSeq 外,生成器不应有副作用或内部状态

方式 A:组合现有生成器(推荐)

在项目层组合,不修改本库。项目自定义 mock 分两步:定义 descriptor 工厂 + 注册 resolver。

// schema/_mock.ts — project-level descriptor factories
import type { MockDescriptor } from '@pylonts/dsl';
import { mockNumbers, mockInteger, mockCompanyName, mockName, mockAbc123 } from '@pylonts/mock';

export const verifyCode = (): MockDescriptor => ({ fn: 'verifyCode' });
export const period = (): MockDescriptor => ({ fn: 'period' });
export const advertColor = (): MockDescriptor => ({ fn: 'advertColor' });
export const storeName = (): MockDescriptor => ({ fn: 'storeName' });
export const couponName = (): MockDescriptor => ({ fn: 'couponName' });
// test setup — register resolvers
import { createBuiltinRegistry } from '@pylonts/mock';
import { verifyCode, period, advertColor, storeName, couponName } from './schema/_mock';

const reg = createBuiltinRegistry();
reg.register('verifyCode', () => () => mockNumbers(6));
reg.register('period', () => () => `2026-${String(mockInteger(1, 12)).padStart(2, '0')}`);
reg.register('advertColor', () => () => `#${mockAbc123(6).toUpperCase()}`);
reg.register('storeName', () => () => `${mockName(1)}路店`);
reg.register('couponName', () => () => `${mockCompanyName()}专属套餐`);

// resolve
reg.resolve(verifyCode());  // → "483921"

方式 B:新增基础生成器

当组合无法满足业务规则时(如 USCC 有校验位算法):

  1. 在 src/generators/ 下新建文件或追加到现有文件
  2. 遵循 (...args?) => T 签名
  3. 在 types.ts 添加类型别名(可选,仅当签名是新的模式时)
  4. 在 index.ts 添加 re-export
// src/generators/finance.ts
export function mockUscc(): string {
  const prefix = '91';  // 深圳地区代码
  const body = mockNumbers(8);
  const checkDigit = calculateCheckDigit(prefix + body);
  return prefix + body + checkDigit;
}

方式 C:业务派生

基于本库生成器,产出带业务上下文的复合数据,也分 descriptor 工厂和 resolver 注册两步:

// schema/_mock.ts(项目层)
import type { MockDescriptor } from '@pylonts/dsl';

export const merchantRow = (): MockDescriptor => ({ fn: 'merchantRow' });
// test setup
import { createBuiltinRegistry, mockCompanyName, mockName, mockPhone, mockAddress } from '@pylonts/mock';
import { merchantRow } from './schema/_mock';

const reg = createBuiltinRegistry();
reg.register('merchantRow', () => () => ({
  name: mockCompanyName(),
  contactName: mockName(),
  contactPhone: mockPhone(),
  bizAddress: mockAddress(),
}));

reg.resolve(merchantRow());  // → { name: '...', contactName: '...', ... }

与语义的集成

语义编码 → 生成器的映射不在本库中维护,由项目层负责:项目在 schema/_mock.ts 定义 descriptor 工厂,注册 resolver 进 MockRegistry 后按 descriptor.fn 解析:

// schema/_mock.ts(项目层)
import type { MockDescriptor } from '@pylonts/dsl';

export const merchantName = (): MockDescriptor => ({ fn: 'merchantName' });
export const bdName = (): MockDescriptor => ({ fn: 'bdName' });
export const contactPhone = (): MockDescriptor => ({ fn: 'contactPhone' });
// test setup
import { createBuiltinRegistry, mockCompanyName, mockName, mockPhone } from '@pylonts/mock';
import { merchantName, bdName, contactPhone } from './schema/_mock';

const registry = createBuiltinRegistry();
registry.register('merchantName', () => mockCompanyName);
registry.register('bdName', () => mockName);
registry.register('contactPhone', () => mockPhone);

// 之后按 descriptor.fn 解析:
registry.resolve({ fn: 'merchantName' });  // → '某某科技有限公司'
registry.resolve(merchantName());          // → 同上

当前生成器清单

名称/文本

| 方法 | 签名 | 说明 | |------|------|------| | mockName | (gender?, surnameType?) => string | 中文姓名,支持性别/单复姓 | | mockChinese | (length?) => string | 随机中文字符串(占用 GBK 空间的合法汉字,非生僻字) |

手机号

| 方法 | 签名 | 说明 | |------|------|------| | mockPhone | (operator?) => string | 11 位手机号,可选 mobile/unicom/telecom,号段合规 |

财务

| 方法 | 签名 | 说明 | |------|------|------| | mockAmt | (min?, max?) => string | 金额,如 "58.50",范围默认 1-1000,两位小数 | | mockRate | () => string | 费率,如 "0.006",范围 0.001-0.030 | | mockUnionpayId | () => string | 银联商户编号,9-12 位数字 |

公司/地址

| 方法 | 签名 | 说明 | |------|------|------| | mockCompanyName | () => string | 公司全称(城市前缀 + 字号 + 行业后缀),如 "深圳市创新科技有限公司" | | mockAddress | () => string | 中文地址,省市区 + 街道 | | mockCompanyInfo | () => [string, string, string] | [全称, 简称, 地址] 三元组,三值保持一致 |

ID/序号

| 方法 | 签名 | 说明 | |------|------|------| | mockMerchantId | () => string | 商户 ID,VARCHAR(12) 兼容,M 前缀 + 时间戳片段 + 随机后缀 | | mockOrderId | () => string | 订单 ID,ORD + 时间戳 + 随机后缀 | | mockSeq | (prefix?) => string | 自增序号,模块级计数器,每次调用 +1 |

身份信息

| 方法 | 签名 | 说明 | |------|------|------| | mockIdCard | () => string | 18 位身份证号,地区码/出生日期/顺序码/校验位全部合规 | | mockBankCard | () => string | 银行卡号,从真实 BIN 前缀数据生成,通过 Luhn 校验 |

账号/密码

| 方法 | 签名 | 说明 | |------|------|------| | mockPassword | () => string | 固定密码,返回 "123456"(descriptor fn: 'password') |

通用随机

| 方法 | 签名 | 说明 | |------|------|------| | mockAbc | (count?) => string | 小写字母,默认 5-15 位 | | mockAbcUpper | (count?) => string | 大写字母,默认 5-15 位 | | mockAbc123 | (count?) => string | 字母数字混合,默认 5-15 位 | | mockNumbers | (count?) => string | 纯数字字符串,默认 5-15 位 | | mockInteger | (min?, max?) => number | 随机整数,默认 0-100000000 | | mockBirthday | (startYear?, endYear?) => string | 生日,yyyyMMdd 格式,默认 1960-2005 |

License

MIT