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

model-reaction

v0.1.1

Published

A TypeScript model library with validation, reaction system, and batch operations

Downloads

4

Readme

model-reaction

一个强大的、类型安全的数据模型管理库,支持同步和异步数据验证、依赖反应、脏数据管理和统一错误处理。

项目简介

model-reaction 是一个用于管理应用程序数据模型的 TypeScript 库,提供以下核心功能:

  • 数据验证:支持同步和异步验证规则,支持自定义验证消息
  • 依赖反应:当指定字段变化时,自动触发相关计算和操作
  • 脏数据管理:跟踪验证失败的数据,并提供清除功能
  • 事件系统:支持订阅字段变化、验证完成和错误事件
  • 错误处理:统一的错误处理机制,支持错误类型分类和自定义错误监听
  • 类型安全:完全基于 TypeScript 构建,提供良好的类型提示

安装

# 使用 npm
npm install model-reaction

# 使用 yarn
yarn add model-reaction

基本使用

同步验证示例

import { createModel, Model, ValidationRules, ErrorType } from 'model-reaction';

// 定义模型架构
const userModel = createModel({
  name: {
    type: 'string',
    validator: [
      ValidationRules.required.withMessage('姓名不能为空'),
      // ValidationRules.minLength(2).withMessage('姓名长度不能少于2个字符')
    ],
    default: '',
  },
  age: {
    type: 'number',
    validator: [
      ValidationRules.required.withMessage('年龄不能为空'),
      ValidationRules.number.withMessage('年龄必须是数字'),
      ValidationRules.min(18).withMessage('年龄必须大于等于18岁')
    ],
    default: 18
  },
  info: {
    type: 'string',
    reaction: {
      fields: ['name', 'age'],
      computed: (values) => `My name is ${values.name} and I am ${values.age} years old.`,
      action: (values) => console.log('Info updated:', values.computed)
    },
    default: ''
  }
}, {
  debounceReactions: 100,
  asyncValidationTimeout: 5000
});

// 订阅错误事件
userModel.on('validation:error', (error) => {
  console.error(`验证错误: ${error.field} - ${error.message}`);
});

userModel.on('field:not-found', (error) => {
  console.error(`字段不存在: ${error.field}`);
});

// 设置字段值
await userModel.setField('name', 'John');
await userModel.setField('age', 30);

// 尝试设置不存在的字段
await userModel.setField('nonexistentField', 'value');

// 获取字段值
console.log('姓名:', userModel.getField('name')); // 输出: John
console.log('年龄:', userModel.getField('age')); // 输出: 30
console.log('信息:', userModel.getField('info')); // 输出: My name is John and I am 30 years old.

// 验证所有字段
const isValid = await userModel.validateAll();
console.log('验证是否通过:', isValid);
console.log('验证错误:', userModel.validationErrors);
console.log('验证摘要:', userModel.getValidationSummary());

// 获取脏数据
console.log('脏数据:', userModel.getDirtyData());

// 清除脏数据
userModel.clearDirtyData();
console.log('清除后脏数据:', userModel.getDirtyData());

异步验证示例

import { createModel, Model, ValidationRules } from 'model-reaction';

// 定义模型架构
const asyncUserModel = createModel({
  name: {
    type: 'string',
    validator: [ValidationRules.required.withMessage('用户名不能为空')],
    default: '',
  },
  username: {
    type: 'string',
    validator: [
      ValidationRules.required.withMessage('账号不能为空'),
      ValidationRules.asyncUnique(
        async (value: string): Promise<boolean> => {
          // 模拟异步检查用户名是否已存在
          return new Promise<boolean>((resolve) => {
            setTimeout(() => {
              // 假设 'admin' 已被占用
              resolve(value !== 'admin');
            }, 100);
          });
        }
      ).withMessage('用户名已存在')
    ],
    default: ''
  }
}, {
  asyncValidationTimeout: 3000
});

// 异步设置字段值
const result1 = await asyncUserModel.setField('username', 'newuser');
console.log('设置新用户名结果:', result1); // 输出: true

const result2 = await asyncUserModel.setField('username', 'admin');
console.log('设置已存在用户名结果:', result2); // 输出: false
console.log('验证错误:', asyncUserModel.validationErrors);
console.log('脏数据:', asyncUserModel.getDirtyData());

API 参考

createModel

模型管理器是库的核心类,提供以下方法:

构造函数

createModel(schema: Model, options?: ModelOptions);

方法

  • setField(field: string, value: any): Promise<boolean>: 设置单个字段值,返回验证结果
  • setFields(fields: Record<string, any>): Promise<boolean>: 批量设置字段值,返回验证结果
  • getField(field: string): any: 获取字段值
  • validateAll(): Promise<boolean>: 验证所有字段,返回整体验证结果
  • getValidationSummary(): string: 获取验证摘要信息
  • getDirtyData(): Record<string, any>: 获取验证失败的脏数据
  • clearDirtyData(): void: 清除所有脏数据
  • on(event: string, callback: (data: any) => void): void: 订阅事件
  • off(event: string, callback?: (data: any) => void): void: 取消订阅事件
  • emit(event: string, data: any): void: 触发事件

事件

  • field:change: 字段值变化时触发
  • validation:complete: 验证完成时触发
  • validation:error: 验证错误时触发
  • reaction:error: 反应处理错误时触发
  • field:not-found: 尝试访问不存在的字段时触发
  • error: 任何错误发生时都会触发的通用错误事件

ModelOptions

模型配置选项:

  • debounceReactions?: number: 反应触发的防抖时间(毫秒)
  • asyncValidationTimeout?: number: 异步验证的超时时间(毫秒)
  • errorFormatter?: (error: ValidationError) => string: 自定义错误格式化函数

ErrorHandler

错误处理器提供统一的错误管理:

  • onError(type: ErrorType, callback: (error: AppError) => void): void: 订阅特定类型的错误
  • offError(type: ErrorType, callback?: (error: AppError) => void): void: 取消订阅特定类型的错误
  • triggerError(error: AppError): void: 触发错误
  • createValidationError(field: string, message: string): AppError: 创建验证错误
  • createFieldNotFoundError(field: string): AppError: 创建字段不存在错误
  • ... 其他错误创建方法

ErrorType 枚举

  • VALIDATION: 验证错误
  • FIELD_NOT_FOUND: 字段不存在错误
  • REACTION_ERROR: 反应处理错误
  • ASYNC_VALIDATION_TIMEOUT: 异步验证超时错误
  • UNKNOWN: 未知错误

类型定义

详细类型定义请参考 src/types.ts 文件。

高级用法

自定义验证规则和消息

您可以创建自定义验证规则并设置自定义错误消息:

import { createModel, Model, Rule, ErrorHandler } from 'model-reaction';

// 创建错误处理器实例
const errorHandler = new ErrorHandler();

// 创建自定义验证规则
const customRule = new Rule(
  'custom',
  '不符合自定义规则', // 默认错误消息
  (value: any) => {
    // 自定义验证逻辑
    return value === 'custom';
  }
);

// 在模型中使用,并重写错误消息
const model = createModel({
  field: {
    type: 'string',
    validator: [
      customRule.withMessage('字段值必须为"custom"')
    ],
    default: ''
  }
}, {
  errorHandler: errorHandler // 添加errorHandler配置
});

统一错误处理

import { createModel, Model, ValidationRules, ErrorHandler, ErrorType } from 'model-reaction';

// 创建错误处理器
const errorHandler = new ErrorHandler();

// 订阅所有验证错误
errorHandler.onError(ErrorType.VALIDATION, (error) => {
  console.error(`验证错误: ${error.field} - ${error.message}`);
});

// 订阅字段不存在错误
errorHandler.onError(ErrorType.FIELD_NOT_FOUND, (error) => {
  console.error(`字段不存在: ${error.field}`);
});

// 订阅所有错误
errorHandler.onError(ErrorType.UNKNOWN, (error) => {
  console.error(`未知错误: ${error.message}`);
});

// 定义模型架构,传入自定义错误处理器
const model = createModel({
  name: {
    type: 'string',
    validator: [ValidationRules.required.withMessage('姓名不能为空')],
    default: ''
  }
}, {
  errorHandler: errorHandler
});

异步转换和验证

import { createModel, Model, Rule } from 'model-reaction';

const asyncModel = createModel({
  field: {
    type: 'string',
    transform: async (value: string) => {
      // 异步转换值
      return value.toUpperCase();
    },
    validator: [
      new Rule(
        'asyncValidator',
        '异步验证失败',
        async (value: string) => {
          // 异步验证逻辑
          return value.length > 3;
        }
      ).withMessage('字段长度必须大于3个字符')
    ],
    default: ''
  }
});

示例

更多示例请查看 examples/ 目录下的文件。

最佳实践

请参考 BEST_PRACTICES.md 文件中的最佳实践指南。