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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@knotx/data

v0.5.7

Published

Data for Knotx

Readme

@knotx/data

一个基于 RxJS 的响应式数据管理库,提供强大的数据操作和双向关系管理功能。

📦 安装

npm install @knotx/data
yarn add @knotx/data
pnpm add @knotx/data

🔧 基本概述

@knotx/data 是 Knotx 生态系统的核心数据管理包,提供两个主要的数据管理工具:

  • DataManager: 用于管理数据的增删改查操作,支持草稿模式、批量操作、版本控制等高级功能
  • DualRelation: 用于管理父子节点之间的双向关系,支持层级管理、循环引用检测等功能

🚀 快速开始

import { DataManager, DualRelation } from '@knotx/data'

// 创建数据管理器
const dataManager = new DataManager('my-data')

// 创建双向关系管理器
const relation = new DualRelation<string, string>()

📚 API 文档

DataManager

类型定义

interface IData {
  id: string
}

// DataManager 类的类型定义
interface DataManager<TData extends IData = IData, TTag extends string = any> {
  // 数据管理器的方法和属性
}

构造函数

const dataManager = new DataManager<MyData>('my-tag')

参数:

  • tag: 数据管理器的标识符

核心方法

init(initialDataList?: TData[]): void

初始化数据管理器,设置初始数据列表。

interface User {
  id: string
  name: string
  age: number
}

const userManager = new DataManager<User>('users')
userManager.init([
  { id: '1', name: 'Alice', age: 25 },
  { id: '2', name: 'Bob', age: 30 }
])
getDataList$(): Observable<TData[]>

获取数据列表的响应式流。

userManager.getDataList$().subscribe((users) => {
  console.log('用户列表更新:', users)
})
getDataList(): TData[]

获取当前数据列表。

const users = userManager.getDataList()
console.log('当前用户:', users)
getData$(id: string, equal?: (a?: TData, b?: TData) => boolean): Observable<TData | undefined>

获取指定ID数据的响应式流。

userManager.getData$('1').subscribe((user) => {
  console.log('用户1数据:', user)
})
getData(id: string): TData | undefined

获取指定ID的数据。

const user = userManager.getData('1')
console.log('用户1:', user)
dispatch(operation: DataOperation<TData>): void

分发数据操作。

// 添加用户
userManager.dispatch({
  type: 'add',
  data: { id: '3', name: 'Charlie', age: 28 }
})

// 更新用户
userManager.dispatch({
  type: 'update',
  id: '1',
  data: { age: 26 }
})

// 删除用户
userManager.dispatch({
  type: 'remove',
  id: '2'
})

// 批量操作
userManager.dispatch({
  type: 'batch',
  operations: [
    { type: 'add', data: { id: '4', name: 'David', age: 35 } },
    { type: 'update', id: '3', data: { age: 29 } }
  ]
})

草稿模式

草稿模式允许你在不影响主数据的情况下进行数据操作。

dispatch 草稿操作
// 开始草稿
userManager.dispatch({
  type: 'startDraft',
  draftId: 'my-draft'
})

// 在草稿中操作
userManager.dispatch({
  type: 'draftOperation',
  draftId: 'my-draft',
  operation: {
    type: 'add',
    data: { id: '5', name: 'Eve', age: 24 }
  }
})

// 提交草稿
userManager.dispatch({
  type: 'commitDraft',
  draftId: 'my-draft'
})

// 或者丢弃草稿
userManager.dispatch({
  type: 'discardDraft',
  draftId: 'my-draft'
})
getDraftDataList(draftId: string): TData[] | undefined

获取草稿中的数据列表。

const draftUsers = userManager.getDraftDataList('my-draft')
getDraftData(draftId: string, dataId: string): TData | undefined

获取草稿中的特定数据。

const draftUser = userManager.getDraftData('my-draft', '5')
dryRun(operation: DataOperation<TData>): Map<string, TData>

模拟执行操作,返回结果但不实际修改数据。

const result = userManager.dryRun({
  type: 'commitDraft',
  draftId: 'my-draft'
})

版本控制

DataManager 提供版本控制功能,跟踪数据变更。

// 监听版本变更
userManager.patchVersion$.subscribe((version) => {
  console.log('补丁版本:', version)
})

userManager.mapVersion$.subscribe((version) => {
  console.log('映射版本:', version)
})

// 获取当前版本
console.log('当前版本:', userManager.version)

操作管道

操作管道允许你在数据操作的不同阶段插入自定义逻辑。

interface DataOperationPipe<T extends IData = IData> {
  transform?: (operations$: Subject<DataOperation<T>>) => OperatorFunction<DataOperation<T>, DataOperation<T>>
  preOperation?: (operations$: Subject<DataOperation<T>>) => OperatorFunction<DataOperation<T>, DataOperation<T>>
  postOperation?: (operations$: Subject<DataOperation<T>>) => OperatorFunction<
    { dataMap: Map<string, T>, operations: DataOperation<T>[] },
    { dataMap: Map<string, T>, operations: DataOperation<T>[] }
  >
}

// 添加操作管道
const removePipe = userManager.addDataOperationPipe({
  preOperation: () => tap((operation) => {
    console.log('执行操作前:', operation)
  }),
  postOperation: () => tap(({ dataMap, operations }) => {
    console.log('执行操作后:', { dataMap, operations })
  })
})

// 移除管道
removePipe()

DualRelation

类型定义

// DualRelation 类的类型定义
interface DualRelation<P, C> {
  // 双向关系的方法和属性
}

泛型参数:

  • P: 父节点类型
  • C: 子节点类型

构造函数

interface DualRelationOptions {
  allowEmptyParent?: boolean // 是否允许父节点没有子节点
  historyDepth?: number // 历史变更记录的最大数量
}

const relation = new DualRelation<string, string>({
  allowEmptyParent: true,
  historyDepth: 50
})

核心方法

add(parent: P, child: C): void

添加父子关系。

// 创建文件系统关系
const fileSystem = new DualRelation<string, string>()

fileSystem.add('root', 'folder1')
fileSystem.add('root', 'folder2')
fileSystem.add('folder1', 'file1.txt')
fileSystem.add('folder1', 'file2.txt')
fileSystem.add('folder2', 'file3.txt')
removeChild(child: C): boolean

移除子节点及其父关系。

const removed = fileSystem.removeChild('file1.txt')
console.log('是否成功移除:', removed)
removeParent(parent: P): boolean

移除父节点及其所有子关系。

const removed = fileSystem.removeParent('folder1')
console.log('是否成功移除:', removed)
getChildren(parent: P): Set<C>

获取父节点的所有子节点。

const children = fileSystem.getChildren('root')
console.log('root的子节点:', Array.from(children))
getParent(child: C): P | undefined

获取子节点的父节点。

const parent = fileSystem.getParent('file1.txt')
console.log('file1.txt的父节点:', parent)
getRootParent(node: C): P | C | null

获取节点的根父节点。

const rootParent = fileSystem.getRootParent('file1.txt')
console.log('file1.txt的根父节点:', rootParent)
hasRelation(parent: P, child: C): boolean

检查是否存在父子关系。

const exists = fileSystem.hasRelation('folder1', 'file1.txt')
console.log('关系是否存在:', exists)
hasCircularReference(): boolean

检查是否存在循环引用。

const hasCircular = fileSystem.hasCircularReference()
console.log('是否存在循环引用:', hasCircular)
addSafe(parent: P, child: C): boolean

安全地添加关系,会检查循环引用。

const added = fileSystem.addSafe('file1.txt', 'root') // 会失败,因为会产生循环引用
console.log('是否成功添加:', added)

层级管理

getNodeLevel(node: P | C): number

获取节点的层级。

const level = fileSystem.getNodeLevel('file1.txt')
console.log('file1.txt的层级:', level)
getDescendants(parent: P, includeSelf?: boolean): Set<C>

获取父节点的所有后代。

const descendants = fileSystem.getDescendants('root', true)
console.log('root的所有后代:', Array.from(descendants))

批量操作

// 开始批量操作
fileSystem.beginBatch()

// 执行多个操作
fileSystem.add('root', 'folder3')
fileSystem.add('folder3', 'file4.txt')
fileSystem.add('folder3', 'file5.txt')

// 提交批量操作
const hasChanges = fileSystem.commitBatch()
console.log('是否有变更:', hasChanges)

// 或者使用便捷方法
const hasChanges2 = fileSystem.batch(() => {
  fileSystem.add('root', 'folder4')
  fileSystem.add('folder4', 'file6.txt')
})

变更历史

// 监听版本变更
fileSystem.version.subscribe((version) => {
  console.log('版本:', version)
})

// 获取变更历史
const history = fileSystem.changeHistory
console.log('变更历史:', history)

工具方法

// 获取所有父节点
const allParents = fileSystem.getAllParents()

// 获取所有子节点
const allChildren = fileSystem.getAllChildren()

// 获取关系数量
const count = fileSystem.size()

// 清空所有关系
fileSystem.clear()

📁 目录结构

packages/data/
├── src/
│   ├── index.ts              # 主要导出文件
│   ├── data-manager.ts       # DataManager 类和相关接口
│   └── dual-relation.ts      # DualRelation 类和相关接口
├── dist/                     # 编译输出目录
├── package.json             # 包配置文件
├── README.md               # 中文文档
├── README.en.md            # 英文文档
├── CHANGELOG.md            # 变更日志
├── build.config.ts         # 构建配置
├── eslint.config.mjs       # ESLint 配置
└── tsconfig.json           # TypeScript 配置

源代码结构

  • index.ts: 主要的导出文件,导出 DataManager 和 DualRelation
  • data-manager.ts: 包含 DataManager 类的完整实现,提供数据管理功能
  • dual-relation.ts: 包含 DualRelation 类的完整实现,提供双向关系管理功能

🔗 相关链接

📄 许可证

MIT License - 详见 LICENSE 文件。

🤝 贡献

欢迎贡献代码!请查看 CONTRIBUTING.md 了解详细信息。